summaryrefslogtreecommitdiff
path: root/extensions/source/ole/unoconversionutilities.hxx
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2004-03-17 12:08:56 +0000
committerOliver Bolte <obo@openoffice.org>2004-03-17 12:08:56 +0000
commit9dda09623d3f0e5ccc9fe8835c8a1365bcb5a51d (patch)
tree5d6ca04aef703188cc7823a07b5726efd79152b4 /extensions/source/ole/unoconversionutilities.hxx
parent4686b3b969cd379d9f1aea48e8ea401e18afe423 (diff)
INTEGRATION: CWS jl5vba (1.14.150); FILE MERGED
2004/01/19 11:17:08 jl 1.14.150.1: #112890# #112889# #112893# #112560# #112509# #112053# #112366# #111023# #111748# #i15215# #109950# join cws ab02vba
Diffstat (limited to 'extensions/source/ole/unoconversionutilities.hxx')
-rw-r--r--extensions/source/ole/unoconversionutilities.hxx2316
1 files changed, 1345 insertions, 971 deletions
diff --git a/extensions/source/ole/unoconversionutilities.hxx b/extensions/source/ole/unoconversionutilities.hxx
index cf355a0ab657..bdecc14ff302 100644
--- a/extensions/source/ole/unoconversionutilities.hxx
+++ b/extensions/source/ole/unoconversionutilities.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: unoconversionutilities.hxx,v $
*
- * $Revision: 1.14 $
+ * $Revision: 1.15 $
*
- * last change: $Author: hr $ $Date: 2003-04-04 19:16:55 $
+ * last change: $Author: obo $ $Date: 2004-03-17 13:08:56 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -61,15 +61,20 @@
#ifndef _UNO_CONVERSION_UTILITIES
#define _UNO_CONVERSION_UTILITIES
-#include <com/sun/star/script/XInvocationAdapterFactory.hpp>
-#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
-
-#include <typelib/typedescription.hxx>
+#include "external/boost/scoped_array.hpp"
+#include "com/sun/star/script/XInvocationAdapterFactory.hpp"
+#include "com/sun/star/script/XInvocationAdapterFactory2.hpp"
+#include "com/sun/star/script/XTypeConverter.hpp"
+#include "com/sun/star/script/FailReason.hpp"
+#include "com/sun/star/bridge/oleautomation/Date.hpp"
+#include "com/sun/star/bridge/oleautomation/Currency.hpp"
+#include "com/sun/star/bridge/oleautomation/SCode.hpp"
+#include "com/sun/star/bridge/oleautomation/Decimal.hpp"
+#include "typelib/typedescription.hxx"
#include "ole2uno.hxx"
-// Test -------------------
-#include <com/sun/star/lang/XEventListener.hpp>
-// ------------------------
+// for some reason DECIMAL_NEG (wtypes.h) which contains BYTE is not resolved.
+typedef unsigned char BYTE;
// classes for wrapping uno objects
#define INTERFACE_OLE_WRAPPER_IMPL 1
#define UNO_OBJECT_WRAPPER_REMOTE_OPT 2
@@ -89,7 +94,8 @@
using namespace com::sun::star::script;
using namespace com::sun::star::beans;
using namespace com::sun::star::uno;
-
+using namespace com::sun::star::bridge::oleautomation;
+using namespace boost;
namespace ole_adapter
{
extern hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
@@ -121,6 +127,8 @@ typedef hash_map<sal_uInt32, WeakReference<XInterface> >::const_iterator CIT_Uno
// and initializes it via XInitialization. The wrapper object is required to implement
// XBridgeSupplier so that it can convert itself to IDispatch.
// class T: Deriving class ( must implement XInterface )
+/** All methods are allowed to throw at least a BridgeRuntimeError.
+ */
template< class >
class UnoConversionUtilities
{
@@ -134,22 +142,60 @@ public:
UnoConversionUtilities( const Reference<XMultiServiceFactory> & xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass )
: m_smgr( xFactory), m_nComWrapperClass( comWrapperClass), m_nUnoWrapperClass( unoWrapperClass)
{}
- // converts only into oleautomation types, that is there is no VT_I1, VT_UI2, VT_UI4
- // a sal_Unicode character is converted into a BSTR
- sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny);
- sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type);
-
+ /** converts only into oleautomation types, that is there is no VT_I1, VT_UI2, VT_UI4
+ a sal_Unicode character is converted into a BSTR.
+ @exception com.sun.star.lang.IllegalArgumentException
+ If the any was inappropriate for conversion.
+ @exception com.sun.star.script.CannotConvertException
+ The any contains a type class for which no conversion is provided.
+ */
+ void anyToVariant(VARIANT* pVariant, const Any& rAny);
+ void anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type);
+
+ /** @exception com.sun.star.lang.IllegalArgumentException
+ If rSeq does not contain a sequence then the exception is thrown.
+ */
SAFEARRAY* createUnoSequenceWrapper(const Any& rSeq);
+ /** @exception com.sun.star.lang.IllegalArgumentException
+ If rSeq does not contain a sequence or elemtype has no proper value
+ then the exception is thrown.
+ */
SAFEARRAY* createUnoSequenceWrapper(const Any& rSeq, VARTYPE elemtype);
- IDispatch* createUnoObjectWrapper(const Any& rObj);
-
- sal_Bool variantToAny(const VARIANT* pVariant, Any& rAny, sal_Bool bReduceValueRange = sal_True);
- sal_Bool variantToAny2( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange = sal_True);
-
- Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType= Type());
-
- sal_Bool convertValueObject( const VARIANTARG *var, Any& any, sal_Bool& bHandled);
- sal_Bool dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type);
+ /**
+ @exception com.sun.star.lang.IllegalArgumentException
+ If rObj does not contain a struct or interface
+ */
+ void createUnoObjectWrapper(const Any & rObj, VARIANT * pVar);
+ /** @exception CannotConvertException
+ Thrown if the VARIANT contains a type that cannot be coerced in the expected Any.
+ ArgumentIndex is 0.
+ @IllegalArgumentException
+ Thrown if the VARIANT is inappropriate for conversion. ArgumentPosition is -1,
+ */
+ void variantToAny(const VARIANT* pVariant, Any& rAny, sal_Bool bReduceValueRange = sal_True);
+ /** This method converts variants arguments in calls from COM -> UNO. Only then
+ the expected UNO type is known.
+ @exception CannotConvertException
+ Thrown if the VARIANT contains a type that cannot be coerced in the expected Any.
+ ArgumentIndex is 0.
+ @IllegalArgumentException
+ Thrown if the VARIANT is inappropriate for conversion. ArgumentPosition is -1,
+ */
+ void variantToAny( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange = sal_True);
+
+ /**
+ @exception IllegalArgumentException
+ -if pVar does not contain VT_UNKNOWN or VT_DISPATCH or
+ pVar is used for a particular UNO type which is not supported by pVar
+ */
+ Any createOleObjectWrapper(VARIANT* pVar, const Type& aType= Type());
+
+ /*
+ Return true means var contained a ValueObject, and it was successfully converted.
+ The result is in any. It an error occurred a BridgeRuntimeError will be thrown.
+ */
+ bool convertValueObject( const VARIANTARG *var, Any& any);
+ void dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type);
Sequence<Any> createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index,
VARTYPE type, const Type& unotype);
@@ -168,6 +214,8 @@ public:
Sequence<Type> getImplementedInterfaces(IUnknown* pUnk);
protected:
+ Reference<XInterface> createAdapter(const Sequence<Type>& types, const Reference<XInterface>& receiver);
+
// helper function for Sequence conversion
void getElementCountAndTypeOfSequence( const Any& rSeq, sal_Int32 dim, Sequence< sal_Int32 >& seqElementCounts, TypeDescription& typeDesc);
// helper function for Sequence conversion
@@ -178,6 +226,8 @@ protected:
Type getElementTypeOfSequence( const Type& seqType);
+ //Provides a typeconverter
+ Reference<XTypeConverter> getTypeConverter();
// This member determines what class is used to convert a UNO object
// or struct to a COM object. It is passed along to the o2u_anyToVariant
@@ -199,9 +249,52 @@ protected:
Reference<XSingleServiceFactory> m_xInvocationFactoryLocal;
Reference<XSingleServiceFactory> m_xInvocationFactoryRemote;
+private:
+ // Holds the type converter which is used for sequence conversion etc.
+ // Use the getTypeConverter function to obtain the interface.
+ Reference<XTypeConverter> m_typeConverter;
+
};
+// ask the object for XBridgeSupplier2 and on success bridges
+// the uno object to IUnknown or IDispatch.
+// return true the UNO object supports
+template < class T >
+bool convertSelfToCom( T& unoInterface, VARIANT * pVar)
+{
+ bool ret = false;
+ Reference< XInterface > xInt( unoInterface, UNO_QUERY);
+ if( xInt.is())
+ {
+ Reference< XBridgeSupplier2 > xSupplier( xInt, UNO_QUERY);
+ if( xSupplier.is())
+ {
+ sal_Int8 arId[16];
+ rtl_getGlobalProcessId( (sal_uInt8*)arId);
+ Sequence<sal_Int8> seqId( arId, 16);
+ Any anySource;
+ anySource <<= xInt;
+ Any anyDisp= xSupplier->createBridge( anySource, seqId, UNO, OLE);
+ if( anyDisp.getValueTypeClass() == TypeClass_UNSIGNED_LONG)
+ {
+ VARIANT* pvariant= *(VARIANT**)anyDisp.getValue();
+ HRESULT hr;
+ if (FAILED(hr = VariantCopy(pVar, pvariant)))
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] convertSelfToCom\n"
+ "VariantCopy failed! Error: ") +
+ OUString::valueOf(hr));
+ VariantClear( pvariant);
+ CoTaskMemFree( pvariant);
+ ret = true;
+ }
+ }
+ }
+ return ret;
+}
+
+
// Gets the invocation factory depending on the Type in the Any.
// The factory can be created by a local or remote multi service factory.
@@ -234,326 +327,477 @@ Reference< XSingleServiceFactory > UnoConversionUtilities<T>::getInvocationFacto
}
template<class T>
-sal_Bool UnoConversionUtilities<T>::variantToAny2( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange /* = sal_True */)
+void UnoConversionUtilities<T>::variantToAny( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange /* = sal_True */)
{
- HRESULT hr;
- sal_Bool retVal= sal_True;
-
- CComVariant var;
- VariantInit( &var);
- // There is no need to support indirect values, since they're not supported by UNO
- if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pArg)))) // remove VT_BYREF
- return sal_False;
-
- sal_Bool bHandled= sal_False;
+ try
+ {
+ HRESULT hr;
+ bool bFail = false;
+ bool bCannotConvert = false;
+ CComVariant var;
- if( !convertValueObject( &var, rAny, bHandled))
- return sal_False;
- if( bHandled)
- OSL_ENSURE( rAny.getValueType() == ptype, "type in Value Object must match the type parameter");
+ // There is no need to support indirect values, since they're not supported by UNO
+ if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pArg)))) // remove VT_BYREF
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n"
+ "VariantCopyInd failed for reason : ") + OUString::valueOf(hr));
+ bool bHandled = convertValueObject( & var, rAny);
+ if( bHandled)
+ OSL_ENSURE( rAny.getValueType() == ptype, "type in Value Object must match the type parameter");
- if( ! bHandled)
- {
- // convert into a variant type that is the equivalent to the type
- // the sequence expects. Thus variantToAny produces the correct type
- // E.g. An Array object contains VT_I4 and the sequence expects shorts
- // than the vartype must be changed. The reason is, you can't specify the
- // type in JavaScript and the script engine determines the type beeing used.
- switch( ptype.getTypeClass())
+ if( ! bHandled)
{
- case TypeClass_CHAR: // could be: new Array( 12, 'w', "w")
- if( pArg->vt == VT_BSTR)
- {
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
- rAny.setValue( (void*)V_BSTR( &var), ptype);
- else
- retVal= sal_False;
- }
- else if( pArg->vt == VT_I4 ||
- pArg->vt == VT_UI4 ||
- pArg->vt == VT_I2 ||
- pArg->vt == VT_UI2 ||
- pArg->vt == VT_I1 ||
- pArg->vt == VT_UI1)
+ // convert into a variant type that is the equivalent to the type
+ // the sequence expects. Thus variantToAny produces the correct type
+ // E.g. An Array object contains VT_I4 and the sequence expects shorts
+ // than the vartype must be changed. The reason is, you can't specify the
+ // type in JavaScript and the script engine determines the type beeing used.
+ switch( ptype.getTypeClass())
{
- if( SUCCEEDED( hr= VariantChangeType( &var, & var, 0, VT_UI2)))
- rAny.setValue(& V_UI2( &var), ptype);
+ case TypeClass_CHAR: // could be: new Array( 12, 'w', "w")
+ if( var.vt == VT_BSTR)
+ {
+ if(SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
+ rAny.setValue( (void*)V_BSTR( &var), ptype);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ }
else
- retVal= sal_False;
- }
- break;
- case TypeClass_INTERFACE: // could also be an IUnknown
- {
- CComVariant varUnk;
- if( SUCCEEDED( hr= VariantChangeType( &varUnk, &var, 0, VT_UNKNOWN)))
- {
- rAny = createOleObjectWrapper( varUnk.punkVal, ptype);
- retVal = sal_True;
- }
- else
- retVal= sal_False;
- break;
- }
- case TypeClass_SERVICE: break; // meta construct
- case TypeClass_STRUCT:
- {// dispatch
- CComVariant varUnk;
- if( SUCCEEDED( hr= VariantChangeType( &varUnk, &var, 0, VT_UNKNOWN)))
- {
- rAny= createOleObjectWrapper( varUnk.punkVal, ptype);
- retVal= sal_True;
- }
- else
- retVal= sal_False;
- break;
- }
- case TypeClass_TYPEDEF: break;
- case TypeClass_UNION: break;
- case TypeClass_ENUM:
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I4)))
+ {
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
+ rAny.setValue((void*) & var.iVal, ptype);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ }
+ break;
+ case TypeClass_INTERFACE: // could also be an IUnknown
+ case TypeClass_STRUCT:
{
- rAny.setValue( (void*)&var.lVal, ptype);
- retVal= sal_True;
+ rAny = createOleObjectWrapper( & var, ptype);
+ break;
}
+ case TypeClass_ENUM:
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I4)))
+ rAny.setValue((void*) & var.lVal, ptype);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_SEQUENCE:
+ // There are different ways of receiving a sequence:
+ // 1: JScript, VARTYPE: VT_DISPATCH
+ // 2. VBScript simple arraysVT_VARIANT|VT_BYREF the referenced VARIANT contains
+ // a VT_ARRAY| <type>
+ // 3. VBSrcript multi dimensional arrays: VT_ARRAY|VT_BYREF
+ if( pArg->vt == VT_DISPATCH)
+ {
+ dispatchExObject2Sequence( pArg, rAny, ptype);
+ }
+ else
+ {
+ if ((var.vt & VT_ARRAY) != 0)
+ {
+ VARTYPE oleType = var.vt ^ VT_ARRAY;
+ Sequence<Any> unoSeq = createOleArrayWrapper( var.parray, oleType, ptype);
+ Reference<XTypeConverter> conv = getTypeConverter();
+ if (conv.is())
+ {
+ try
+ {
+ Any anySeq = makeAny(unoSeq);
+ Any convAny = conv->convertTo(anySeq, ptype);
+ rAny = convAny;
+ }
+ catch (IllegalArgumentException& e)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]com.sun.star.lang.IllegalArgumentException "
+ "in UnoConversionUtilities<T>::variantToAny! Message: ") +
+ e.Message);
+ }
+ catch (CannotConvertException& e)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]com.sun.star.script.CannotConvertException "
+ "in UnoConversionUtilities<T>::variantToAny! Message: ") +
+ e.Message);
+ }
+ }
+ }
+ }
+ break;
+ case TypeClass_VOID:
+ rAny.setValue(NULL,Type());
+ break;
+ case TypeClass_ANY: // Any
+ // There could be a JScript Array that needs special handling
+ // If an Any is expected and this Any must contain a Sequence
+ // then we cannot figure out what element type is required.
+ // Therefore we convert to Sequence< Any >
+ if( pArg->vt == VT_DISPATCH && isJScriptArray( pArg))
+ {
+ dispatchExObject2Sequence( pArg, rAny,
+ getCppuType((Sequence<Any>*) 0));
+ }
+ else if (pArg->vt == VT_DECIMAL)
+ {
+ //Decimal maps to hyper in calls from COM -> UNO
+ // It does not matter if we create a sal_uInt64 or sal_Int64,
+ // because the UNO object is called through invocation which
+ //will do a type conversion if necessary
+ if (var.decVal.sign == 0)
+ {
+ // positive value
+ variantToAny( & var, rAny, getCppuType( (sal_uInt64*) 0),
+ bReduceValueRange);
+ }
+ else
+ {
+ //negative value
+ variantToAny( & var, rAny, getCppuType( (sal_Int64*) 0),
+ bReduceValueRange);
+ }
+ }
+ else
+ {
+ variantToAny( & var, rAny);
+ }
+ break;
+ case TypeClass_BOOLEAN: // VARIANT could be VARIANT_BOOL or other
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BOOL)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_STRING: // UString
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BSTR)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_FLOAT: // float
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R4)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_DOUBLE: // double
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R8)))
+ variantToAny(& var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
else
- retVal= sal_False;
+ bFail = true;
break;
- case TypeClass_EXCEPTION: break;
- case TypeClass_ARRAY: break; // there's no Array at the moment
- case TypeClass_SEQUENCE:
- // There are different ways of receiving a sequence:
- // 1: JScript, VARTYPE: VT_DISPATCH
- // 2. VBScript simple arraysVT_VARIANT|VT_BYREF the referenced VARIANT contains
- // a VT_ARRAY| <type>
- // 3. VBSrcript multi dimensional arrays: VT_ARRAY|VT_BYREF
- if( pArg->vt == VT_DISPATCH)
- {
- retVal= dispatchExObject2Sequence( pArg, rAny, ptype);
- }
- else
- {
- if ((var.vt & VT_ARRAY) != 0)
+ case TypeClass_BYTE: // BYTE
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I1)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_SHORT: // INT16
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_LONG:
+ if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_I4)))
+ variantToAny( & var, rAny, bReduceValueRange);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_HYPER:
+ if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
{
- VARTYPE oleType = var.vt ^ VT_ARRAY;
- Sequence<Any> unoSeq = createOleArrayWrapper( var.parray, oleType, ptype);
- rAny.setValue( &unoSeq, getCppuType( &unoSeq));
- retVal = sal_True;
+ if (var.decVal.Lo64 > 0x8000000000000000
+ || var.decVal.Hi32 > 0
+ || var.decVal.scale > 0)
+ {
+ bFail = true;
+ break;
+ }
+ sal_Int64 value = var.decVal.Lo64;
+ if (var.decVal.sign == DECIMAL_NEG)
+ value |= 0x8000000000000000;
+ rAny <<= value;
}
- }
- break;
- case TypeClass_VOID:
- rAny.setValue(NULL,Type());
- break;
-
- case TypeClass_ANY: // Any
- // There could be a JScript Array that needs special handling
- // If an Any is expected and this Any must contain a Sequence
- // then we cannot figure out what element type is required.
- // Therefore we convert to Sequence< Any >
- if( pArg->vt == VT_DISPATCH && isJScriptArray( pArg))
- {
- Sequence<Any> s;
- retVal= dispatchExObject2Sequence( pArg, rAny, getCppuType(&s));
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_UNSIGNED_SHORT: // UINT16
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI2)))
+ variantToAny( & var, rAny);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_UNSIGNED_LONG:
+ if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI4)))
+ variantToAny( & var, rAny, bReduceValueRange);
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ case TypeClass_UNSIGNED_HYPER:
+ if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
+ {
+ if (var.decVal.Hi32 > 0 || var.decVal.scale > 0)
+ {
+ bFail = true;
+ break;
+ }
+ rAny <<= var.decVal.Lo64;
+ }
+ else if (hr == DISP_E_TYPEMISMATCH)
+ bCannotConvert = true;
+ else
+ bFail = true;
+ break;
+ default:
+// case TypeClass_SERVICE: break; // meta construct
+// case TypeClass_TYPEDEF: break;
+// case TypeClass_UNION: break;
+// case TypeClass_MODULE: break; // module
+// case TypeClass_EXCEPTION: break;
+// case TypeClass_ARRAY: break; // there's no Array at the moment
+// case TypeClass_UNKNOWN: break;
+ bCannotConvert = true;
+ break;
}
- else
- retVal= variantToAny( &var, rAny);
- break;
- case TypeClass_UNKNOWN: break;
- case TypeClass_BOOLEAN: // VARIANT could be VARIANT_BOOL or other
- if(SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BOOL)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_STRING: // UString
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_FLOAT: // float
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_R4)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_DOUBLE: // double
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_R8)))
- retVal= variantToAny(&var, rAny );
- else
- retVal= sal_False;
- break;
- case TypeClass_BYTE: // BYTE
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I1)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_SHORT: // INT16
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I2)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_LONG: // INT32
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I4)))
- retVal= variantToAny(&var, rAny, bReduceValueRange);
- else
- retVal= sal_False;
- break;
- case TypeClass_HYPER: break; // INT64
- case TypeClass_UNSIGNED_SHORT: // UINT16
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_UI2)))
- retVal= variantToAny(&var, rAny);
- else
- retVal= sal_False;
- break;
- case TypeClass_UNSIGNED_LONG: // UINT32
- if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_UI4)))
- retVal= variantToAny(&var, rAny, bReduceValueRange);
- else
- retVal= sal_False;
- break;
- case TypeClass_UNSIGNED_HYPER: break;// UINT64
- case TypeClass_MODULE: break; // module
-
- default:
- retVal= variantToAny(pArg, rAny); // hopfully delegating ;-)
- break;
-
}
+ if (bCannotConvert)
+ throw CannotConvertException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n"
+ "Cannot convert the value of vartype :\"") +
+ OUString::valueOf((sal_Int32) var.vt) +
+ OUSTR("\" to the expected UNO type of type class: ") +
+ OUString::valueOf((sal_Int32) ptype.getTypeClass()),
+ 0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
+
+ if (bFail)
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>:variantToAny\n"
+ "The provided VARIANT of type\" ") + OUString::valueOf((sal_Int32) var.vt) +
+ OUSTR("\" is unappropriate for conversion!"), Reference<XInterface>(), -1);
+ }
+ catch (CannotConvertException &)
+ {
+ throw;
+ }
+ catch (IllegalArgumentException &)
+ {
+ throw;
+ }
+ catch (BridgeRuntimeError &)
+ {
+ throw;
+ }
+ catch (Exception & e)
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::variantToAny ! Message : \n") +
+ e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::variantToAny !"));
}
- return retVal;
}
// The function only converts Sequences to SAFEARRAYS with elements of the type
// specified by the parameter type. Everything else is forwarded to
// anyToVariant(VARIANT* pVariant, const Any& rAny)
+// Param type must not be VT_BYREF
template<class T>
-sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type)
+void UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type)
{
- HRESULT hr= S_OK;
- sal_Bool ret= sal_False;
- type &= 0xffff ^ VT_BYREF; // remove VT_BYREF if set
- if( type & VT_ARRAY)
+ try
{
- type ^= VT_ARRAY;
- SAFEARRAY* ar= createUnoSequenceWrapper( rAny, type);
- if( ar)
+ HRESULT hr= S_OK;
+
+ OSL_ASSERT( (type & VT_BYREF) == 0);
+ if (type & VT_ARRAY)
+ {
+ type ^= VT_ARRAY;
+ SAFEARRAY* ar= createUnoSequenceWrapper( rAny, type);
+ if( ar)
+ {
+ VariantClear( pVariant);
+ pVariant->vt= VT_ARRAY | type;
+ pVariant->byref= ar;
+ }
+ }
+ else if(type == VT_VARIANT)
{
- VariantClear( pVariant);
- pVariant->vt= VT_ARRAY | type;
- pVariant->byref= ar;
- ret= sal_True;
+ anyToVariant(pVariant, rAny);
}
+ else
+ {
+ CComVariant var;
+ anyToVariant( &var, rAny);
+ if(FAILED(hr = VariantChangeType(&var, &var, 0, type)))
+ {
+ if (hr == DISP_E_TYPEMISMATCH)
+ throw CannotConvertException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Cannot convert the value of type :\"") +
+ rAny.getValueTypeName() +
+ OUSTR("\" to the expected Automation type of VARTYPE: ") +
+ OUString::valueOf((sal_Int32)type),
+ 0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
+
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Conversion of any with ") +
+ rAny.getValueType().getTypeName() +
+ OUSTR(" to VARIANT with type: ") + OUString::valueOf((sal_Int32) type) +
+ OUSTR(" failed! Error code: ") + OUString::valueOf(hr));
+ }
+ if(FAILED(hr = VariantCopy(pVariant, &var)))
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "VariantCopy failed for reason: ") + OUString::valueOf(hr));
+ }
+ }
}
- else if(type == VT_VARIANT)
+ catch (IllegalArgumentException &)
{
- ret= anyToVariant(pVariant, rAny);
+ throw;
}
- else
+ catch (CannotConvertException & )
{
- CComVariant var;
- if(anyToVariant( &var, rAny))
- {
- if(SUCCEEDED(hr= VariantChangeType(&var, &var, 0, type)))
- {
- if( SUCCEEDED(VariantCopy(pVariant, &var)))
- ret= sal_True;
- }
- }
+ throw;
+ }
+ catch (BridgeRuntimeError&)
+ {
+ throw;
+ }
+ catch(Exception & e)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Unexpected exception occurred. Message: ") + e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Unexpected exception occurred."));
}
-
- return ret;
}
template<class T>
-sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny)
+void UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny)
{
- sal_Bool ret = sal_False;
-
- switch (rAny.getValueTypeClass())
+ bool bCannotConvert = false;
+ bool bIllegal = false;
+ try
{
- case TypeClass_INTERFACE: // XInterfaceRef
+ switch (rAny.getValueTypeClass())
{
- Reference<XInterface> xInt( *(XInterface**)rAny.getValue());
-
- V_VT(pVariant) = VT_DISPATCH;
- V_DISPATCH(pVariant) = NULL;
-
- if (xInt.is())
+ case TypeClass_INTERFACE:
+ {
+ Reference<XInterface> xInt;
+ if (rAny >>= xInt)
+ {
+ createUnoObjectWrapper(rAny, pVariant);
+ }
+ else
+ {
+ bIllegal = true;
+ }
+ break;
+ }
+ case TypeClass_STRUCT:
+ {
+ if (rAny.getValueType() == getCppuType((Date*)0))
{
- // check, wether the object provides OLE bridging or not
- Reference<XBridgeSupplier2> XBridgeSup(xInt, UNO_QUERY);
- sal_Bool bOwnService= sal_False;
- if (XBridgeSup.is())
+ Date d;
+ if (rAny >>= d)
{
- // check if we try to convert our own OleConverter2 service
- // If so we would run into a recursion!!!
- T* pT= static_cast< T* >( this);
-
- Any anyXInt= pT->queryInterface( getCppuType( static_cast<Reference<XInterface>* >( 0) ));
- Reference< XInterface > xIntThis;
-
- if( (anyXInt >>= xIntThis) && xInt != xIntThis)
- { // not our own OleConverter_Impl2
- sal_uInt8 arId[16];
- rtl_getGlobalProcessId( arId);
- Any oleAny = XBridgeSup->createBridge(
- rAny,
- Sequence<sal_Int8>( (sal_Int8*)arId, 16),
- UNO,
- OLE);
-
- if( oleAny.getValueType() == getCppuType( (sal_uInt32*)0))
- {
- VARIANT* pTmpVariant = *(VARIANT**)oleAny.getValue();
-
- VariantCopy(pVariant, pTmpVariant);
- VariantClear(pTmpVariant);
- CoTaskMemFree(pTmpVariant);
- }
- else
- {
- XBridgeSup = Reference<XBridgeSupplier2>();
- }
- }
- else
- {// The object is our OleConverter_Impl2 !!
- bOwnService= sal_True;
- }
+ pVariant->vt = VT_DATE;
+ pVariant->date = d.Value;
}
-
- if (!XBridgeSup.is() || bOwnService )
+ else
{
- V_DISPATCH(pVariant)= createUnoObjectWrapper( rAny);
+ bIllegal = true;
}
}
- ret = sal_True;
-
+ else if(rAny.getValueType() == getCppuType((Decimal*)0))
+ {
+ Decimal d;
+ if (rAny >>= d)
+ {
+ pVariant->vt = VT_DECIMAL;
+ pVariant->decVal.scale = d.Scale;
+ pVariant->decVal.sign = d.Sign;
+ pVariant->decVal.Lo32 = d.LowValue;
+ pVariant->decVal.Mid32 = d.MiddleValue;
+ pVariant->decVal.Hi32 = d.HighValue;
+ }
+ else
+ {
+ bIllegal = true;
+ }
+ }
+ else if (rAny.getValueType() == getCppuType((Currency*)0))
+ {
+ Currency c;
+ if (rAny >>= c)
+ {
+ pVariant->vt = VT_CY;
+ pVariant->cyVal.int64 = c.Value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
+ }
+ else if(rAny.getValueType() == getCppuType((SCode*)0))
+ {
+ SCode s;
+ if (rAny >>= s)
+ {
+ pVariant->vt = VT_ERROR;
+ pVariant->scode = s.Value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
+ }
+ else
+ {
+ createUnoObjectWrapper(rAny, pVariant);
+ }
break;
}
- case TypeClass_SERVICE: // meta construct
- break;
- case TypeClass_STRUCT: // struct
- V_VT(pVariant) = VT_DISPATCH;
- V_DISPATCH(pVariant) = createUnoObjectWrapper(rAny);
- ret = sal_True;
- break;
- case TypeClass_TYPEDEF: // typedef compiler construct ???
- break;
- case TypeClass_UNION: // union
- break;
- case TypeClass_ENUM: // enumeration
- V_VT(pVariant) = VT_I4;
- V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
- ret = sal_True;
- break;
- case TypeClass_EXCEPTION: // exception
- break;
- case TypeClass_ARRAY: // array not implemented
- break;
case TypeClass_SEQUENCE: // sequence ??? SafeArray descriptor
{
SAFEARRAY* pArray = createUnoSequenceWrapper(rAny);
@@ -561,98 +805,227 @@ sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& r
{
V_VT(pVariant) = VT_ARRAY | VT_VARIANT;
V_ARRAY(pVariant) = pArray;
- ret = sal_True;
+ }
+ else
+ {
+ bIllegal = true;
}
break;
}
- case TypeClass_VOID: // void
- VariantClear(pVariant);
- ret = sal_True;
- break;
- case TypeClass_ANY: // Any
+ case TypeClass_VOID:
+ {
+ HRESULT hr = S_OK;
+ if (FAILED(hr = VariantClear(pVariant)))
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
+ "VariantClear failed with error:") + OUString::valueOf(hr));
+ }
break;
- case TypeClass_UNKNOWN: // unknown type
+ }
+ case TypeClass_BOOLEAN:
+ {
+ sal_Bool value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_BOOL;
+ pVariant->boolVal = value == sal_True? VARIANT_TRUE: VARIANT_FALSE;
+ }
+ else
+ {
+ bIllegal = true;
+ }
break;
- case TypeClass_BOOLEAN: // BOOL
+ }
+ case TypeClass_CHAR:
{
- V_VT(pVariant) = VT_BOOL;
- V_BOOL( pVariant)= *(sal_Bool*) rAny.getValue() == sal_True? VARIANT_TRUE: VARIANT_FALSE;
- ret = sal_True;
+ // Because VT_UI2 does not conform to oleautomation we convert into VT_I2 instead
+ sal_uInt16 value = *(sal_Unicode*) rAny.getValue();
+ pVariant->vt = VT_I2;
+ pVariant->iVal = value;
break;
}
- case TypeClass_CHAR:// char
+ case TypeClass_STRING:
+ {
+ OUString value;
+ if (rAny >>= value)
{
- // Because VT_UI2 does not conform to oleautomation we convert into VT_I2 instead
- V_VT(pVariant) = VT_I2;
- V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
- ret = sal_True;
- break;
+ pVariant->vt = VT_BSTR;
+ pVariant->bstrVal = SysAllocString(value);
+ }
+ else
+ {
+ bIllegal = true;
}
- case TypeClass_STRING: // UString
- V_VT(pVariant) = VT_BSTR;
- V_BSTR(pVariant) = SysAllocString( OUString(*(rtl_uString**)rAny.getValue()));
- ret = sal_True;
break;
- case TypeClass_FLOAT: // float
- V_VT(pVariant) = VT_R4;
- V_R4(pVariant) = *(float*)rAny.getValue();
- ret = sal_True;
+ }
+ case TypeClass_FLOAT:
+ {
+ float value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_R4;
+ pVariant->fltVal = value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
break;
- case TypeClass_DOUBLE: // double
- V_VT(pVariant) = VT_R8;
- V_R8(pVariant) = *(double*)rAny.getValue();
- ret = sal_True;
+ }
+ case TypeClass_DOUBLE:
+ {
+ double value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_R8;
+ pVariant->dblVal = value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
break;
- case TypeClass_BYTE: // BYTE
+ }
+ case TypeClass_BYTE:
+ {
// ole automation does not know a signed char but only unsigned char
- V_VT(pVariant) = VT_UI1;
- V_UI1(pVariant) = *(sal_uInt8*)rAny.getValue();
- ret= sal_True;
+ sal_Int8 value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_UI1;
+ pVariant->bVal = value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
break;
+ }
case TypeClass_SHORT: // INT16
- V_VT(pVariant) = VT_I2;
- V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
- ret = sal_True;
- break;
- case TypeClass_LONG: // INT32
- V_VT(pVariant) = VT_I4;
- V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
- ret = sal_True;
- break;
- case TypeClass_HYPER: // INT64
-
- break;
- //case TypeClass_UNSIGNED_OCTET: // ??? not implemented
- // V_VT(pVariant) = VT_UI1;
- // V_UI1(pVariant) = rAny.getBYTE();
- // ret = sal_True;
- // break;
case TypeClass_UNSIGNED_SHORT: // UINT16
- V_VT(pVariant) = VT_I2;
- V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
- ret = sal_True;
+ {
+ sal_Int16 value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_I2;
+ pVariant->iVal = value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
+ break;
+ }
+ case TypeClass_ENUM:
+ {
+ sal_Int32 value = *(sal_Int32*) rAny.getValue();
+ pVariant->vt = VT_I4;
+ pVariant->lVal= value;
break;
- case TypeClass_UNSIGNED_LONG: // UINT32
- V_VT(pVariant) = VT_I4;
- V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
- ret = sal_True;
+ }
+ case TypeClass_LONG:
+ case TypeClass_UNSIGNED_LONG:
+ {
+ sal_Int32 value;
+ if (rAny >>= value)
+ {
+ pVariant->vt = VT_I4;
+ pVariant->lVal= value;
+ }
+ else
+ {
+ bIllegal = true;
+ }
break;
- case TypeClass_UNSIGNED_HYPER: // UINT64
+ }
+ case TypeClass_HYPER:
+ {
+
+ pVariant->vt = VT_DECIMAL;
+ pVariant->decVal.scale = 0;
+ pVariant->decVal.sign = 0;
+ pVariant->decVal.Hi32 = 0;
+
+ sal_Int64 value;
+ rAny >>= value;
+
+ if (value & 0x8000000000000000)
+ pVariant->decVal.sign = DECIMAL_NEG;
+
+ pVariant->decVal.Lo64 = value;
break;
- // case TypeClass_UNSIGNED_INT: // int not implemented
- // break;
- //case TypeClass_UNSIGNED_BYTE:
- // V_VT(pVariant) = VT_UI1;
- // V_UI1(pVariant) = rAny.getBYTE();
- // ret = sal_True;
- // break;
- case TypeClass_MODULE: // module
+ }
+ case TypeClass_UNSIGNED_HYPER:
+ {
+ pVariant->vt = VT_DECIMAL;
+ pVariant->decVal.scale = 0;
+ pVariant->decVal.sign = 0;
+ pVariant->decVal.Hi32 = 0;
+
+ sal_uInt64 value;
+ rAny >>= value;
+ pVariant->decVal.Lo64 = value;
break;
+ }
default:
+ //TypeClass_SERVICE:
+ //TypeClass_EXCEPTION:
+ //When a InvocationTargetException is thrown when calling XInvocation::invoke
+ //on a UNO object, then the target exception is directly used to create a
+ //EXEPINFO structure
+ //TypeClass_TYPEDEF
+ //TypeClass_ANY:
+ //TypeClass_UNKNOWN:
+ //TypeClass_UNSIGNED_OCTET:
+ // TypeClass_UNION:
+ // TypeClass_ARRAY:
+ // TypeClass_UNSIGNED_INT:
+ // TypeClass_UNSIGNED_BYTE:
+ // TypeClass_MODULE:
+ throw CannotConvertException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
+ "There is no conversion for this UNO type to a Automation type."
+ "The destination type class is the type class of the UNO "
+ "argument which was to be converted."),
+ Reference<XInterface>(), rAny.getValueTypeClass(),
+ FailReason::TYPE_NOT_SUPPORTED, 0);
+
break;
- }
+ }
+ if (bIllegal)
+ {
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
+ "The provided any of type\" ") + rAny.getValueType().getTypeName() +
+ OUSTR("\" is unappropriate for conversion!"), Reference<XInterface>(), -1);
- return ret;
+ }
+ }
+ catch (CannotConvertException & )
+ {
+ throw;
+ }
+ catch (IllegalArgumentException & )
+ {
+ throw;
+ }
+ catch(BridgeRuntimeError&)
+ {
+ throw;
+ }
+ catch(Exception & e)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Unexpected exception occurred. Message: ") + e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
+ "Unexpected exception occurred. ") );
+ }
}
// Creates an SAFEARRAY of the specified element and if necessary
@@ -661,10 +1034,14 @@ sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& r
template<class T>
SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq, VARTYPE elemtype)
{
- if( ! (rSeq.getValueTypeClass() == TypeClass_SEQUENCE) |
- ( elemtype == VT_NULL) | ( elemtype == VT_EMPTY) )
- return NULL;
-
+ if (rSeq.getValueTypeClass() != TypeClass_SEQUENCE)
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper \n"
+ "The any does not contain a sequence!"), 0, 0);
+ if (elemtype == VT_NULL || elemtype == VT_EMPTY)
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper \n"
+ "No element type supplied!"),0, -1);
SAFEARRAY* pArray= NULL;
// Get the dimensions. This is done by examining the type name string
// The count of brackets determines the dimensions.
@@ -680,7 +1057,8 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq,
if( elementTypeDesc.is() )
{
// set up the SAFEARRAY
- SAFEARRAYBOUND* prgsabound= new SAFEARRAYBOUND[dims];
+ scoped_array<SAFEARRAYBOUND> sarSafeArrayBound(new SAFEARRAYBOUND[dims]);
+ SAFEARRAYBOUND* prgsabound= sarSafeArrayBound.get();
sal_Int32 elementCount=0; //the number of all elements in the SAFEARRAY
for( sal_Int32 i=0; i < dims; i++)
{
@@ -711,10 +1089,12 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq,
// In this case arDimSeqIndices would have the size 1. That is the elements are not counted
// but the Sequences that contain those elements.
// The indices ar 0 based
+ scoped_array<sal_Int32> sarDimsSeqIndices;
sal_Int32* arDimsSeqIndices= NULL;
if( dimsSeq > 0)
{
- arDimsSeqIndices= new sal_Int32[dimsSeq];
+ sarDimsSeqIndices.reset(new sal_Int32[dimsSeq]);
+ arDimsSeqIndices = sarDimsSeqIndices.get();
memset( arDimsSeqIndices, 0, sizeof( sal_Int32 ) * dimsSeq);
}
@@ -773,29 +1153,23 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq,
VARIANT var;
VariantInit( &var);
- if( anyToVariant( &var, unoElement))
+ anyToVariant( &var, unoElement);
+ if( elemtype == VT_VARIANT )
{
- if( elemtype == VT_VARIANT )
- {
- VariantCopy( ( VARIANT*)psaCurrentData, &var);
- VariantClear( &var);
- }
- else
- memcpy( psaCurrentData, &var.byref, oleElementSize);
+ VariantCopy( ( VARIANT*)psaCurrentData, &var);
+ VariantClear( &var);
}
+ else
+ memcpy( psaCurrentData, &var.byref, oleElementSize);
+
psaCurrentData+= oleElementSize;
}
}
while( incrementMultidimensionalIndex( dimsSeq, parElementCount, arDimsSeqIndices));
- if( arDimsSeqIndices)
- delete [] arDimsSeqIndices;
-
SafeArrayUnaccessData( pArray);
}
}
- if( prgsabound)
- delete [] prgsabound;
}
return pArray;
}
@@ -932,53 +1306,52 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq)
SAFEARRAY* pArray = NULL;
sal_uInt32 n = 0;
- if( rSeq.getValueTypeClass() == TypeClass_SEQUENCE )
- {
- uno_Sequence * punoSeq= *(uno_Sequence**) rSeq.getValue();
+ if( rSeq.getValueTypeClass() != TypeClass_SEQUENCE )
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper\n"
+ "The UNO argument is not a sequence"), 0, -1);
- typelib_TypeDescriptionReference* pSeqTypeRef= rSeq.getValueTypeRef();
- typelib_TypeDescription* pSeqType= NULL;
- TYPELIB_DANGER_GET( &pSeqType, pSeqTypeRef)
- typelib_IndirectTypeDescription * pSeqIndDec= (typelib_IndirectTypeDescription*) pSeqType;
-// typelib_IndirectTypeDescription * pSeqDec= (typelib_IndirectTypeDescription*)rSeq.getValueTypeDescriptionRef();
+ uno_Sequence * punoSeq= *(uno_Sequence**) rSeq.getValue();
- typelib_TypeDescriptionReference * pSeqElementTypeRef= pSeqIndDec->pType;
- TYPELIB_DANGER_RELEASE( pSeqType)
+ typelib_TypeDescriptionReference* pSeqTypeRef= rSeq.getValueTypeRef();
+ typelib_TypeDescription* pSeqType= NULL;
+ TYPELIB_DANGER_GET( &pSeqType, pSeqTypeRef);
+ typelib_IndirectTypeDescription * pSeqIndDec= (typelib_IndirectTypeDescription*) pSeqType;
+ typelib_TypeDescriptionReference * pSeqElementTypeRef= pSeqIndDec->pType;
+ TYPELIB_DANGER_RELEASE( pSeqType);
- typelib_TypeDescription* pSeqElementDesc= NULL;
- TYPELIB_DANGER_GET( &pSeqElementDesc, pSeqElementTypeRef)
- sal_Int32 nElementSize= pSeqElementDesc->nSize;
- n= punoSeq->nElements;
+ typelib_TypeDescription* pSeqElementDesc= NULL;
+ TYPELIB_DANGER_GET( &pSeqElementDesc, pSeqElementTypeRef);
+ sal_Int32 nElementSize= pSeqElementDesc->nSize;
+ n= punoSeq->nElements;
- SAFEARRAYBOUND rgsabound[1];
- rgsabound[0].lLbound = 0;
- rgsabound[0].cElements = n;
- VARIANT oleElement;
- long safeI[1];
+ SAFEARRAYBOUND rgsabound[1];
+ rgsabound[0].lLbound = 0;
+ rgsabound[0].cElements = n;
+ VARIANT oleElement;
+ long safeI[1];
- pArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
+ pArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
- Any unoElement;
+ Any unoElement;
// sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->pElements;
- sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->elements;
+ sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->elements;
- for (sal_uInt32 i = 0; i < n; i++)
- {
- unoElement.setValue( pSeqData + i * nElementSize, pSeqElementDesc);
- VariantInit(&oleElement);
+ for (sal_uInt32 i = 0; i < n; i++)
+ {
+ unoElement.setValue( pSeqData + i * nElementSize, pSeqElementDesc);
+ VariantInit(&oleElement);
- if (anyToVariant(&oleElement, unoElement))
- {
- safeI[0] = i;
- SafeArrayPutElement(pArray, safeI, &oleElement);
- }
+ anyToVariant(&oleElement, unoElement);
- VariantClear(&oleElement);
- }
- TYPELIB_DANGER_RELEASE( pSeqElementDesc)
+ safeI[0] = i;
+ SafeArrayPutElement(pArray, safeI, &oleElement);
+
+ VariantClear(&oleElement);
}
+ TYPELIB_DANGER_RELEASE( pSeqElementDesc);
return pArray;
}
@@ -988,374 +1361,268 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq)
- UNO interface
- UNO interface created by this bridge (adapter factory)
- UNO interface created by this bridge ( COM Wrapper)
+
+pVar must be initialized.
*/
template<class T>
-IDispatch* UnoConversionUtilities<T>::createUnoObjectWrapper(const Any& rObj)
+void UnoConversionUtilities<T>::createUnoObjectWrapper(const Any & rObj, VARIANT * pVar)
{
MutexGuard guard(getBridgeMutex());
- IDispatch* pDispatch = NULL;
- Reference<XInvocation> xInv;
Reference<XInterface> xInt;
- rObj >>= xInt;
- //make sure we have the main XInterface which is used with a map
- xInt=Reference<XInterface>(xInt, UNO_QUERY);
- //If there is already a wrapper for the UNO object then use it
- Reference<XInterface> xIntWrapper;
- // Does a UNO wrapper exist already ?
- if(xInt.is())
+ TypeClass tc = rObj.getValueTypeClass();
+ if (tc != TypeClass_INTERFACE && tc != TypeClass_STRUCT)
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoObjectWrapper \n"
+ "Cannot create an Automation interface for a UNO type which is not "
+ "a struct or interface!"), 0, -1);
+
+ if (rObj.getValueTypeClass() == TypeClass_INTERFACE)
{
- IT_Uno it_uno= UnoObjToWrapperMap.find( (sal_uInt32) xInt.get());
+ if (! (rObj >>= xInt))
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge] UnoConversionUtilities<T>::createUnoObjectWrapper\n "
+ "Could not create wrapper object for UNO object!"), 0, -1);
+ //If XInterface is NULL, which is a valid value, then simply return NULL.
+ if ( ! xInt.is())
+ {
+ pVar->vt = VT_UNKNOWN;
+ pVar->punkVal = NULL;
+ return;
+ }
+ //make sure we have the main XInterface which is used with a map
+ xInt = Reference<XInterface>(xInt, UNO_QUERY);
+ //If there is already a wrapper for the UNO object then use it
+
+ Reference<XInterface> xIntWrapper;
+ // Does a UNO wrapper exist already ?
+ IT_Uno it_uno = UnoObjToWrapperMap.find( (sal_uInt32) xInt.get());
if(it_uno != UnoObjToWrapperMap.end())
{
- xIntWrapper= it_uno->second;
- OSL_ENSURE( xIntWrapper.is(),"Automation bridge: Mapping failure");
+ xIntWrapper = it_uno->second;
+ if (xIntWrapper.is())
+ {
+ convertSelfToCom(xIntWrapper, pVar);
+ return;
+ }
+ }
+ // Is the object a COM wrapper ( either XInvocation, or Adapter object)
+ // or does it suppy an IDispatch by its own ?
+ else
+ {
+ Reference<XInterface> xIntComWrapper = xInt;
+ typedef hash_map<sal_uInt32,sal_uInt32>::iterator _IT;
+ // Adapter? then get the COM wrapper to which the adapter delegates its calls
+ _IT it= AdapterToWrapperMap.find( (sal_uInt32) xInt.get());
+ if( it != AdapterToWrapperMap.end() )
+ xIntComWrapper= reinterpret_cast<XInterface*>(it->second);
+
+ if (convertSelfToCom(xIntComWrapper, pVar))
+ return;
}
}
-
- // Is the object a COM wrapper ( either XInvocation, or Adapter object)
- // or does it suppy an IDispatch by its own ?
- if(xInt.is() && ! xIntWrapper.is())
- {
- Reference<XInterface> xIntComWrapper= xInt;
- typedef hash_map<sal_uInt32,sal_uInt32>::iterator _IT;
- // Adapter? then get the COM wrapper to which the adapter delegates its calls
- _IT it= AdapterToWrapperMap.find( (sal_uInt32) xInt.get());
- if( it != AdapterToWrapperMap.end() )
- xIntComWrapper= reinterpret_cast<XInterface*>(it->second);
-
- // the object can be a COM wrapper, or any other UNO object that supports
- // a bridge (XBridgeSupplier) and provide an IDispatch on its own.
- convertSelfToIDispatch(xIntComWrapper, &pDispatch);
- }
// If we have no UNO wrapper nor the IDispatch yet then we have to create
// a wrapper. For that we need an XInvocation from the UNO object.
- if( !xIntWrapper.is() && ! pDispatch)
+
+ // get an XInvocation or create one using the invocation service
+ Reference<XInvocation> xInv(xInt, UNO_QUERY);
+ if ( ! xInv.is())
{
- // get an XInvocation or create one using the invocation service
- Reference<XInvocation> xInv(xInt, UNO_QUERY);
- if( ! xInv.is())
+ Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj);
+ if (xInvFactory.is())
{
- Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj);
- if( xInvFactory.is())
- {
- Sequence<Any> params(1);
- params.getArray()[0] = rObj;
- Reference<XInterface> xInt = xInvFactory->createInstanceWithArguments(params);
- xInv= Reference<XInvocation>(xInt, UNO_QUERY);
- }
+ Sequence<Any> params(1);
+ params.getArray()[0] = rObj;
+ Reference<XInterface> xInt = xInvFactory->createInstanceWithArguments(params);
+ xInv= Reference<XInvocation>(xInt, UNO_QUERY);
}
+ }
- if( xInv.is())
+ if (xInv.is())
+ {
+ Reference<XInterface> xNewWrapper = createUnoWrapperInstance();
+ Reference<XInitialization> xInitWrapper(xNewWrapper, UNO_QUERY);
+ if (xInitWrapper.is())
{
- Reference< XInterface > xNewWrapper= createUnoWrapperInstance();
- Reference< XInitialization > xInitWrapper( xNewWrapper, UNO_QUERY);
- if( xInitWrapper.is() )
- {
- VARTYPE vartype= getVarType( rObj);
-
- if( xInt.is())
- {
- Any params[3];
- params[0] <<= xInv;
- params[1] <<= xInt;
- params[2] <<= vartype;
- xInitWrapper->initialize( Sequence<Any>(params, 3));
- }
- else
- {
- Any params[2];
- params[0] <<= xInv;
- params[1] <<= vartype;
- xInitWrapper->initialize( Sequence<Any>(params, 2));
- }
+ VARTYPE vartype= getVarType( rObj);
- xIntWrapper= xNewWrapper;
- // put the newly created object into a map. If the same object will
- // be mapped again and there is already a wrapper then the old wrapper
- // will be used.
- if(xInt.is()) // only interfaces
- UnoObjToWrapperMap[(sal_uInt32) xInt.get()]= xIntWrapper;
+ if (xInt.is())
+ {
+ Any params[3];
+ params[0] <<= xInv;
+ params[1] <<= xInt;
+ params[2] <<= vartype;
+ xInitWrapper->initialize( Sequence<Any>(params, 3));
}
+ else
+ {
+ Any params[2];
+ params[0] <<= xInv;
+ params[1] <<= vartype;
+ xInitWrapper->initialize( Sequence<Any>(params, 2));
+ }
+
+ // put the newly created object into a map. If the same object will
+ // be mapped again and there is already a wrapper then the old wrapper
+ // will be used.
+ if(xInt.is()) // only interfaces
+ UnoObjToWrapperMap[(sal_uInt32) xInt.get()]= xNewWrapper;
+ convertSelfToCom(xNewWrapper, pVar);
+ return;
}
}
-
- // get IDispatch from the UNO wrapper
- if( !pDispatch)
- convertSelfToIDispatch(xIntWrapper, &pDispatch);
-
- return pDispatch;
}
template<class T>
-sal_Bool UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& rAny,
+void UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& rAny,
sal_Bool bReduceValueRange /* = sal_True */)
{
- sal_Bool ret = sal_False;
- VARTYPE oleTypeFlags = V_VT(pVariant);
-
- if ((oleTypeFlags & VT_BYREF) != 0)
+ HRESULT hr = S_OK;
+ try
{
- oleTypeFlags ^= VT_BYREF;
-
- if ((oleTypeFlags & VT_ARRAY) != 0)
- {
- oleTypeFlags ^= VT_ARRAY;
+ CComVariant var;
- Sequence<Any> unoSeq = createOleArrayWrapper(*V_ARRAYREF(pVariant), oleTypeFlags);
- rAny.setValue( &unoSeq, getCppuType( &unoSeq));
+ // There is no need to support indirect values, since they're not supported by UNO
+ if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pVariant)))) // remove VT_BYREF
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n"
+ "VariantCopyInd failed for reason : ") + OUString::valueOf(hr));
- ret = sal_True;
- }
- else
+ if ( ! convertValueObject( & var, rAny))
{
- switch (oleTypeFlags) // conversion by reference
- {
- case VT_EMPTY: // jo
- rAny.setValue(NULL, Type());
- ret= sal_True;
- break;
- case VT_NULL:
- rAny.setValue(NULL, Type());
- ret = sal_True;
- break;
- case VT_I2:
- rAny.setValue(V_I2REF(pVariant), getCppuType((sal_Int16*)0));
- ret = sal_True;
- break;
- case VT_I4:
- rAny.setValue(V_I4REF(pVariant), getCppuType((sal_Int32*)0));
- ret = sal_True;
- break;
- case VT_R4:
- rAny.setValue(V_R4REF(pVariant), getCppuType( (float*)0));
- ret = sal_True;
- break;
- case VT_R8:
- rAny.setValue(V_R8REF(pVariant), getCppuType( (double*)0));
- ret = sal_True;
- break;
- case VT_CY:
- // rAny.setHyper(*V_CYREF(pVariant));
- // ret = sal_True;
- break;
- case VT_DATE:
- break;
- case VT_BSTR:
- {
- OUString s(*V_BSTRREF(pVariant));
- rAny.setValue( &s, getCppuType( &s));
- ret = sal_True;
- break;
- }
- case VT_DISPATCH:
- {
- IUnknown* pUnknown = NULL;
-
- if ((*V_DISPATCHREF(pVariant)) != NULL)
- {
- (*V_DISPATCHREF(pVariant))->QueryInterface(IID_IUnknown, (void**)&pUnknown);
- }
-
- rAny = createOleObjectWrapper(pUnknown);
-
- if (pUnknown != NULL)
- {
- pUnknown->Release();
- }
+ if ((var.vt & VT_ARRAY) > 0)
+ {
+ VARTYPE oleTypeFlags = var.vt ^ VT_ARRAY;
- ret = sal_True;
- break;
- }
- case VT_ERROR:
- rAny.setValue(V_ERRORREF(pVariant), getCppuType( (sal_uInt32*)0));
- ret = sal_True;
- break;
- case VT_BOOL:
- {
- sal_Bool b= (*V_BOOLREF(pVariant)) == VARIANT_TRUE;
- rAny.setValue( &b, getCppuType( &b));
- ret = sal_True;
- break;
- }
- case VT_VARIANT:
- {
- if (V_VT(V_VARIANTREF(pVariant)) == VT_EMPTY)
- {
- rAny.setValue(NULL, Type());
- ret = sal_True;
- }
- else
- {
- ret = variantToAny(V_VARIANTREF(pVariant), rAny);
- }
- }
- break;
- case VT_UNKNOWN:
- rAny = createOleObjectWrapper(*V_UNKNOWNREF(pVariant));
- ret = sal_True;
- break;
- case VT_I1:
- rAny.setValue(V_I1REF(pVariant), getCppuType( (sal_Int8*)0));
- ret = sal_True;
- break;
- case VT_UI1:
- // convert to sal_Int8 because there is no Type for sal_uInt8
- rAny.setValue(V_UI1REF(pVariant), getCppuType( (sal_Int8*)0));
- ret = sal_True;
- break;
- case VT_UI2:
- rAny.setValue(V_UI2REF(pVariant), getCppuType( (sal_uInt16*)0));
- ret = sal_True;
- break;
- case VT_UI4:
- rAny.setValue(V_UI4REF(pVariant), getCppuType( (sal_uInt32*)0));
- ret = sal_True;
- break;
- case VT_INT:
- rAny.setValue(V_INTREF(pVariant), getCppuType( (sal_Int32*)0));
- ret = sal_True;
- break;
- case VT_UINT:
- rAny.setValue(V_UINTREF(pVariant), getCppuType((sal_uInt32*)0));
- ret = sal_True;
- break;
- case VT_VOID:
- rAny.setValue( NULL, Type());
- ret = sal_True;
- break;
- default:
- break;
+ Sequence<Any> unoSeq = createOleArrayWrapper(var.parray, oleTypeFlags);
+ rAny.setValue( &unoSeq, getCppuType( &unoSeq));
}
- }
- }
- else
- {
- if ((oleTypeFlags & VT_ARRAY) > 0)
- {
- oleTypeFlags ^= VT_ARRAY;
-
- Sequence<Any> unoSeq = createOleArrayWrapper(V_ARRAY(pVariant), oleTypeFlags);
- rAny.setValue( &unoSeq, getCppuType( &unoSeq));
-
- ret = sal_True;
- }
- else
- {
- switch (oleTypeFlags) // conversion by value
+ else
{
- case VT_EMPTY: // jo
+ switch (var.vt)
+ {
+ case VT_EMPTY:
rAny.setValue(NULL, Type());
- ret= sal_True;
break;
-
case VT_NULL:
rAny.setValue(NULL, Type());
- ret = sal_True;
break;
case VT_I2:
- rAny.setValue(&V_I2(pVariant), getCppuType( (sal_Int16*)0));
- ret = sal_True;
+ rAny.setValue( & var.iVal, getCppuType( (sal_Int16*)0));
break;
case VT_I4:
- rAny.setValue(&V_I4(pVariant), getCppuType( (sal_Int32*)0));
+ rAny.setValue( & var.lVal, getCppuType( (sal_Int32*)0));
// necessary for use in JavaScript ( see "reduceRange")
if( bReduceValueRange)
- reduceRange( rAny);
- ret = sal_True;
+ reduceRange(rAny);
break;
case VT_R4:
- rAny.setValue(&V_R4(pVariant), getCppuType( (float*)0));
- ret = sal_True;
+ rAny.setValue( & var.fltVal, getCppuType( (float*)0));
break;
case VT_R8:
- rAny.setValue(&V_R8(pVariant), getCppuType( (double*)0));
- ret = sal_True;
+ rAny.setValue(& var.dblVal, getCppuType( (double*)0));
break;
case VT_CY:
- // rAny.setHyper(V_CY(pVariant));
- // ret = sal_True;
+ {
+ Currency cy(var.cyVal.int64);
+ rAny <<= cy;
break;
+ }
case VT_DATE:
+ {
+ Date d(var.date);
+ rAny <<= d;
break;
+ }
case VT_BSTR:
{
- OUString b( V_BSTR(pVariant));
+ OUString b(var.bstrVal);
rAny.setValue( &b, getCppuType( &b));
- ret = sal_True;
break;
}
+ case VT_UNKNOWN:
case VT_DISPATCH:
{
- IUnknown* pUnknown = NULL;
-
- if (V_DISPATCH(pVariant) != NULL)
- {
- V_DISPATCH(pVariant)->QueryInterface(IID_IUnknown, (void**)&pUnknown);
- }
-
- rAny = createOleObjectWrapper(pUnknown);
-
- if (pUnknown != NULL)
- {
- pUnknown->Release();
- }
-
- ret = sal_True;
-
+ rAny = createOleObjectWrapper( & var);
break;
}
case VT_ERROR:
- rAny.setValue(&V_ERROR(pVariant), getCppuType( (sal_uInt32*)0));
- ret = sal_True;
+ {
+ SCode scode(var.scode);
+ rAny <<= scode;
break;
+ }
case VT_BOOL:
{
- sal_Bool b= V_BOOL(pVariant) == VARIANT_TRUE;
+ sal_Bool b= var.boolVal == VARIANT_TRUE;
rAny.setValue( &b, getCppuType( &b));
- ret = sal_True;
break;
}
- case VT_UNKNOWN:
- rAny = createOleObjectWrapper(V_UNKNOWN(pVariant));
- ret = sal_True;
- break;
case VT_I1:
- rAny.setValue(&V_I1(pVariant), getCppuType((sal_Int8*)0));
- ret = sal_True;
+ rAny.setValue( & var.cVal, getCppuType((sal_Int8*)0));
break;
case VT_UI1: // there is no unsigned char in UNO
- rAny.setValue((char*)&V_UI1(pVariant), getCppuType( (sal_Int8*)0));
- ret = sal_True;
+ rAny.setValue( & var.bVal, getCppuType( (sal_Int8*)0));
break;
case VT_UI2:
- rAny.setValue(&V_UI2(pVariant), getCppuType( (sal_uInt16*)0));
- ret = sal_True;
+ rAny.setValue( & var.uiVal, getCppuType( (sal_uInt16*)0));
break;
case VT_UI4:
- rAny.setValue(&V_UI4(pVariant), getCppuType( (sal_uInt32*)0));
- ret = sal_True;
+ rAny.setValue( & var.ulVal, getCppuType( (sal_uInt32*)0));
break;
case VT_INT:
- rAny.setValue(&V_INT(pVariant), getCppuType( (sal_Int32*)0));
- ret = sal_True;
+ rAny.setValue( & var.intVal, getCppuType( (sal_Int32*)0));
break;
case VT_UINT:
- rAny.setValue(&V_UINT(pVariant), getCppuType( (sal_uInt32*)0));
- ret = sal_True;
+ rAny.setValue( & var.uintVal, getCppuType( (sal_uInt32*)0));
break;
case VT_VOID:
rAny.setValue( NULL, Type());
- ret = sal_True;
break;
+ case VT_DECIMAL:
+ {
+ Decimal dec;
+ dec.Scale = var.decVal.scale;
+ dec.Sign = var.decVal.sign;
+ dec.LowValue = var.decVal.Lo32;
+ dec.MiddleValue = var.decVal.Mid32;
+ dec.HighValue = var.decVal.Hi32;
+ rAny <<= dec;
+ break;
+ }
+
default:
break;
+ }
}
}
}
+ catch (IllegalArgumentException & )
+ {
+ throw;
+ }
+ catch (CannotConvertException &)
+ {
+ throw;
+ }
+ catch (BridgeRuntimeError & )
+ {
+ throw;
+ }
+ catch (Exception & e)
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::variantToAny ! Message : \n") +
+ e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::variantToAny !"));
+ }
- return ret;
}
// The function converts an IUnknown* into an UNO interface or struct. The
// IUnknown pointer can constitute different kind of objects:
@@ -1381,321 +1648,426 @@ sal_Bool UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any&
// UNO wrapper than the original UNO object is being extracted, queried for "aType" (if
// it is no struct) and returned.
template<class T>
-Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const Type& aType= Type())
+Any UnoConversionUtilities<T>::createOleObjectWrapper(VARIANT* pVar, const Type& aType= Type())
{
+ if (pVar->vt != VT_UNKNOWN && pVar->vt != VT_DISPATCH)
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
+ "The VARIANT does not contain an object type! "), 0, -1);
+
MutexGuard guard( getBridgeMutex());
+
+ CComPtr<IUnknown> spUnknown;
+ CComPtr<IDispatch> spDispatch;
+
+ if (pVar->vt == VT_UNKNOWN)
+ {
+ spUnknown = pVar->punkVal;
+ if (spUnknown)
+ spUnknown.QueryInterface( & spDispatch.p);
+ }
+ else if (pVar->vt == VT_DISPATCH && pVar->pdispVal != NULL)
+ {
+ CComPtr<IDispatch> spDispatch(pVar->pdispVal);
+ if (spDispatch)
+ spDispatch.QueryInterface( & spUnknown.p);
+ }
+
static Type VOID_TYPE= Type();
Any ret;
+ //If no Type is provided and pVar contains IUnknown then we return a XInterface.
+ //If pVar contains an IDispatch then we return a XInvocation.
+ Type desiredType;
+ if (aType == VOID_TYPE && pVar->vt == VT_UNKNOWN)
+ desiredType = getCppuType((Reference<XInterface>*) 0);
+ else if (aType == VOID_TYPE && pVar->vt == VT_DISPATCH)
+ desiredType = getCppuType((Reference<XInvocation>*) 0);
+ else
+ desiredType = aType;
- Type desiredType= aType == VOID_TYPE ? getCppuType((Reference<XInvocation>*) 0) : aType;
-
- if (pUnknown == NULL)
+ // COM pointer are NULL, no wrapper required
+ if (spUnknown == NULL)
{
Reference<XInterface> xInt;
if( aType.getTypeClass() == TypeClass_INTERFACE)
ret.setValue( &xInt, aType);
else if( aType.getTypeClass() == TypeClass_STRUCT)
ret.setValue( NULL, aType);
+ else
+ ret <<= xInt;
+ return ret;
}
- else
+
+
+ // Check if "spUnknown" is a UNO wrapper, that is an UNO object that has been
+ // passed to COM. Then it supports IUnoObjectWrapper
+ // and we extract the original UNO object.
+ CComQIPtr<IUnoObjectWrapper> spUno( spUnknown);
+ if( spUno)
+ { // it is a wrapper
+ Reference<XInterface> xInt;
+ if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt)))
+ {
+ ret <<= xInt;
+ }
+ else
+ {
+ Any any;
+ if( SUCCEEDED( spUno->getOriginalUnoStruct(&any)))
+ ret= any;
+ }
+ return ret;
+ }
+
+ // "spUnknown" is a real COM object.
+ // Before we create a new wrapper object we check if there is an existing wrapper
+ // There can be two kinds of wrappers, those who wrap dispatch - UNO objects, and those who
+ // wrap ordinary dispatch objects. The dispatch-UNO objects usually are adapted to represent
+ // particular UNO interfaces.
+ Reference<XInterface> xIntWrapper;
+ CIT_Com cit_currWrapper= ComPtrToWrapperMap.find( reinterpret_cast<sal_uInt32>(spUnknown.p));
+ if(cit_currWrapper != ComPtrToWrapperMap.end())
+ xIntWrapper = cit_currWrapper->second;
+ if (xIntWrapper.is())
{
- // Check if "pUnknown" is a UNO wrapper. Then it supports IUnoObjectWrapper
- // and we extract the original UNO object.
- CComQIPtr<IUnoObjectWrapper> spUno( pUnknown);
- if( spUno)
- { // it is a wrapper
- Reference<XInterface> xInt;
- if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt)))
+ //Try to find an adapter for the wrapper
+ //find the proper Adapter. The pointer in the WrapperToAdapterMap are valid as long as
+ //we get a pointer to the wrapper from ComPtrToWrapperMap, because the Adapter hold references
+ //to the wrapper.
+ CIT_Wrap it = WrapperToAdapterMap.find((sal_uInt32) xIntWrapper.get());
+ if (it == WrapperToAdapterMap.end())
+ {
+ // No adapter available.
+ //The COM component could be a UNO object. Then we need to provide
+ // a proxy that implements all interfaces
+ Sequence<Type> seqTypes= getImplementedInterfaces(spUnknown);
+ Reference<XInterface> xIntAdapter;
+ if (seqTypes.getLength() > 0)
{
- ret <<= xInt;
+ //It is a COM UNO object
+ xIntAdapter = createAdapter(seqTypes, xIntWrapper);
}
else
{
- Any any;
- if( SUCCEEDED( spUno->getOriginalUnoStruct(&any)))
- ret= any;
+ // Some ordinary COM object
+ xIntAdapter = xIntWrapper;
}
+ // return the wrapper directly, return XInterface or XInvocation
+ ret = xIntWrapper->queryInterface(desiredType);
+ if ( ! ret.hasValue())
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
+ "The COM object is not suitable for the UNO type: ") +
+ desiredType.getTypeName(), 0, -1);
}
else
{
- // "pUnknown" is a real COM object.
- // If the object implements UNO interfaces then get the types.
- Sequence<Type> seqTypes= getImplementedInterfaces(pUnknown);
- // Before we create a new wrapper object we check if there is an existing wrapper
- Reference<XInterface> xIntWrapper;
- CIT_Com cit_currWrapper= ComPtrToWrapperMap.find( reinterpret_cast<sal_uInt32>(pUnknown));
- if(cit_currWrapper != ComPtrToWrapperMap.end())
- {
- WeakReference<XInterface> xweak= cit_currWrapper->second;
- xIntWrapper= xweak;
- //When the wrapper is destructed it must remove the entry in the map
- //therefore we must always get a hard reference
- OSL_ENSURE(xIntWrapper.is(),"OLE Automation bridge");
- }
- else
- {
- //There is no existing wrapper, therefore we create one for the real COM object
- Reference<XInterface> xInt= createComWrapperInstance();
- if( xInt.is())
- {
- // initialize the COM wrapper ( IUnknown + Type s)
- Reference<XInitialization> xInit( xInt, UNO_QUERY);
- if( xInit.is())
- {
- Any params[2];
- params[0] <<= (sal_uInt32) pUnknown;
- if( ! seqTypes.getLength() )
- {
- params[1] <<= Sequence<Type>( &aType, 1);
- }
- else
- {
- params[1] <<= seqTypes;
- }
-
- xInit->initialize( Sequence<Any>( params, 2));
- xIntWrapper= xInt;
- }
- }
- }
+ //There is an adapter available
+ Reference<XInterface> xIntAdapter((XInterface*) it->second);
+ ret = xIntAdapter->queryInterface( desiredType);
+ if ( ! ret.hasValue())
+ throw IllegalArgumentException(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
+ "The COM object is not suitable for the UNO type: ") +
+ desiredType.getTypeName(), 0, -1);
+ }
- if( xIntWrapper.is())
- {
- // we have a wrapper object
- //The wrapper implements already XInvocation and XInterface. Therefore if the
- //param aType is one of those we can use the wrapper object directly otherwise
- //we have to create an Adapter interface.
- //If aType is void then we assume the type to be XInterface
- if( desiredType == getCppuType((Reference<XInvocation>*) 0))
- {
- ret <<= xIntWrapper;
- // remember the wrapper object
- ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(pUnknown)]= xIntWrapper;
- }
- else
- {
- Reference< XInterface> xIntAdapterFac;
- xIntAdapterFac= m_smgr->createInstance( INTERFACE_ADAPTER_FACTORY);
- // We create an adapter object that does not only implement the required type but also
- // all types that the COM object pretends to implement. An COM object must therefore
- // support the property "_implementedInterfaces".
- Reference<XInterface> xIntAdapted;
- sal_Int32 seqTypesLen = seqTypes.getLength();
- Reference<XInvocation> xInv( xIntWrapper, UNO_QUERY);
- if( seqTypesLen > 0)
- {
- Reference< XInvocationAdapterFactory2> xAdapterFac( xIntAdapterFac, UNO_QUERY);
- if( xAdapterFac.is())
- xIntAdapted= xAdapterFac->createAdapter( xInv, seqTypes);
- }
- else
- {
- Reference<XInvocationAdapterFactory> xAdapterFac( xIntAdapterFac, UNO_QUERY);
- if( xAdapterFac.is())
- xIntAdapted= xAdapterFac->createAdapter( xInv, desiredType);
- }
- if( xIntAdapted.is())
- {
- ret= xIntAdapted->queryInterface( desiredType);
- // Put the pointer to the wrapper object and the interface pointer of the adapted interface
- // in a global map. Thus we can determine in a call to createUnoObjectWrapper whether the UNO
- // object is a wrapped COM object. In that case we extract the original COM object rather than
- // creating a wrapper around the UNO object.
- typedef hash_map<sal_uInt32,sal_uInt32>::value_type VALUE;
- AdapterToWrapperMap.insert( VALUE( (sal_uInt32) xIntAdapted.get(), (sal_uInt32) xIntWrapper.get()));
- WrapperToAdapterMap.insert( VALUE( (sal_uInt32) xIntWrapper.get(), (sal_uInt32) xIntAdapted.get()));
- ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(pUnknown)]= xIntWrapper;
- }
- }
+ return ret;
+ }
+ // No existing wrapper. Therefore create a new proxy.
+ // If the object implements UNO interfaces then get the types.
+ Sequence<Type> seqTypes = getImplementedInterfaces(spUnknown);
+ if (seqTypes.getLength() == 0 &&
+ aType != VOID_TYPE && aType != getCppuType((Reference<XInvocation>*)0))
+ {
+ seqTypes = Sequence<Type>( & aType, 1);
+ }
- }
- }
+ //There is no existing wrapper, therefore we create one for the real COM object
+ Reference<XInterface> xIntNewProxy= createComWrapperInstance();
+ if ( ! xIntNewProxy.is())
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
+ "Could not create proxy object for COM object!"));
+
+ // initialize the COM wrapper
+ Reference<XInitialization> xInit( xIntNewProxy, UNO_QUERY);
+ OSL_ASSERT( xInit.is());
+
+ Any params[3];
+ params[0] <<= (sal_uInt32) spUnknown.p;
+ sal_Bool bDisp = pVar->vt == VT_DISPATCH ? sal_True : sal_False;
+ params[1].setValue( & bDisp, getBooleanCppuType());
+ params[2] <<= seqTypes;
+
+ xInit->initialize( Sequence<Any>( params, 3));
+ ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(spUnknown.p)]= xIntNewProxy;
+
+ // we have a wrapper object
+ //The wrapper implements already XInvocation and XInterface. If
+ //param aType is void then the object is supposed to have XInvocation.
+ if (aType == getCppuType((Reference<XInvocation>*)0) ||
+ (aType == VOID_TYPE && seqTypes.getLength() == 0 ))
+ {
+ ret = xIntNewProxy->queryInterface(desiredType);
+ }
+ else
+ {
+ Reference<XInterface> xIntAdapter =
+ createAdapter(seqTypes, xIntNewProxy);
+ ret = xIntAdapter->queryInterface(desiredType);
}
-
return ret;
}
+template<class T>
+Reference<XInterface> UnoConversionUtilities<T>::createAdapter(const Sequence<Type>& seqTypes,
+ const Reference<XInterface>& receiver)
+{
+ Reference< XInterface> xIntAdapterFac;
+ xIntAdapterFac= m_smgr->createInstance(INTERFACE_ADAPTER_FACTORY);
+ // We create an adapter object that does not only implement the required type but also
+ // all types that the COM object pretends to implement. An COM object must therefore
+ // support the property "_implementedInterfaces".
+ Reference<XInterface> xIntAdapted;
+ Reference<XInvocation> xInv(receiver, UNO_QUERY);
+ Reference<XInvocationAdapterFactory2> xAdapterFac( xIntAdapterFac, UNO_QUERY);
+ if( xAdapterFac.is())
+ xIntAdapted= xAdapterFac->createAdapter( xInv, seqTypes);
+
+ if( xIntAdapted.is())
+ {
+ // Put the pointer to the wrapper object and the interface pointer of the adapted interface
+ // in a global map. Thus we can determine in a call to createUnoObjectWrapper whether the UNO
+ // object is a wrapped COM object. In that case we extract the original COM object rather than
+ // creating a wrapper around the UNO object.
+ typedef hash_map<sal_uInt32,sal_uInt32>::value_type VALUE;
+ AdapterToWrapperMap.insert( VALUE( (sal_uInt32) xIntAdapted.get(), (sal_uInt32) receiver.get()));
+ WrapperToAdapterMap.insert( VALUE( (sal_uInt32) receiver.get(), (sal_uInt32) xIntAdapted.get()));
+ }
+ else
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
+ "Could not create a proxy for COM object! Creation of adapter failed."));
+ }
+ return xIntAdapted;
+}
// "convertValueObject" converts a JScriptValue object contained in "var" into
// an any. The type contained in the any is stipulated by a "type value" thas
// was set within the JScript script on the value object ( see JScriptValue).
-// return bHandled = true - it was a ValueObject
-// return true - no errors, false - errors
template<class T>
-sal_Bool UnoConversionUtilities<T>::convertValueObject( const VARIANTARG *var, Any& any, sal_Bool& bHandled)
+bool UnoConversionUtilities<T>::convertValueObject( const VARIANTARG *var, Any& any)
{
- sal_Bool retVal= sal_True;
- bHandled= sal_False;
- HRESULT hr= S_OK;
- CComVariant varDisp;
-
- if( SUCCEEDED( varDisp.ChangeType( VT_DISPATCH, var)))
+ bool ret = false;
+ try
{
- CComPtr <IJScriptValueObject> spValue;
- VARIANT_BOOL varBool;
- CComBSTR bstrType;
- CComVariant varValue;
- CComPtr<IDispatch> spDisp( varDisp.pdispVal);
- if( spDisp)
+ bool bFail = false;
+ HRESULT hr= S_OK;
+ CComVariant varDisp;
+
+ if(SUCCEEDED(hr = varDisp.ChangeType( VT_DISPATCH, var)))
{
- if( SUCCEEDED( spDisp->QueryInterface( __uuidof( IJScriptValueObject),
- reinterpret_cast<void**> (&spValue))))
+ CComPtr <IJScriptValueObject> spValue;
+ VARIANT_BOOL varBool;
+ CComBSTR bstrType;
+ CComVariant varValue;
+ CComPtr<IDispatch> spDisp( varDisp.pdispVal);
+ if(spDisp)
{
- bHandled= sal_True; // is is a ValueObject
- //If it is an out - param then it does not need to be converted. In/out and
- // in params does so.
- if ( SUCCEEDED ( hr= spValue->IsOutParam( &varBool)))
+ if(SUCCEEDED( spDisp->QueryInterface( __uuidof( IJScriptValueObject),
+ reinterpret_cast<void**> (&spValue))))
{
- // if varBool == true then no conversion needed because out param
- if( varBool == VARIANT_FALSE)
+ ret = true; // is is a ValueObject
+ //If it is an out - param then it does not need to be converted. In/out and
+ // in params does so.
+ if (SUCCEEDED(hr= spValue->IsOutParam( &varBool)))
{
- if( SUCCEEDED( hr= spValue->GetValue( &bstrType, &varValue)))
+ // if varBool == true then no conversion needed because out param
+ if (varBool == VARIANT_FALSE)
{
- if( ! variantToAny2( &varValue, any, getType( bstrType)))
- retVal= sal_False;
+ if(SUCCEEDED(hr = spValue->GetValue( & bstrType, & varValue)))
+ variantToAny( & varValue, any, getType(bstrType));
+ else
+ bFail = true;
}
- else
- retVal= sal_False;
}
+ else
+ bFail = true;;
}
- else
- retVal= sal_False;
}
}
+ else if( hr != DISP_E_TYPEMISMATCH && hr != E_NOINTERFACE)
+ bFail = true;
+
+ if (bFail)
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] Conversion of ValueObject failed "));
}
- return retVal;
+ catch (BridgeRuntimeError &)
+ {
+ throw;
+ }
+ catch (Exception & e)
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::convertValueObject ! Message : \n") +
+ e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::convertValueObject !"));
+ }
+ return ret;
}
+
template<class T>
-sal_Bool UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type)
+void UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type)
{
- sal_Bool retVal= TRUE;
-
- if( pvar->vt != VT_DISPATCH) return FALSE;
- IDispatchEx* pdispEx;
- HRESULT hr;
- if( FAILED( hr= pvar->pdispVal->QueryInterface( IID_IDispatchEx,
- reinterpret_cast<void**>( &pdispEx)))) return FALSE;
-
- DISPID dispid;
- OUString sindex;
- DISPPARAMS param= {0,0,0,0};
- VARIANT result;
- VariantInit( & result);
- OLECHAR* sLength= L"length";
-
- // Get the length of the array. Can also be obtained throu GetNextDispID. The
- // method only returns DISPIDs of the array data. Their names are like "0", "1" etc.
- if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sLength , 1, LOCALE_USER_DEFAULT, &dispid)))
- return FALSE;
- if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
- &param, &result, NULL, NULL)))
- return FALSE;
- if( FAILED( VariantChangeType( &result, &result, 0, VT_I4)))
- return FALSE;
- long length= result.lVal;
- VariantClear( &result);
-
- // get a few basic facts about the sequence, and reallocate:
- // create the Sequences
- // get the size of the elements
- typelib_TypeDescription *pDesc= NULL;
- type.getDescription( &pDesc);
-
- typelib_IndirectTypeDescription *pSeqDesc= reinterpret_cast<typelib_IndirectTypeDescription*>(pDesc);
- typelib_TypeDescriptionReference *pSeqElemDescRef= pSeqDesc->pType; // type of the Sequence' elements
- Type elemType( pSeqElemDescRef);
- _typelib_TypeDescription* pSeqElemDesc=NULL;
- TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef)
- sal_uInt32 nelementSize= pSeqElemDesc->nSize;
- TYPELIB_DANGER_RELEASE( pSeqElemDesc)
-
- uno_Sequence *p_uno_Seq;
- uno_sequence_construct( &p_uno_Seq, pDesc, NULL, length, cpp_acquire);
-
- typelib_TypeClass typeElement= pSeqDesc->pType->eTypeClass;
- char *pArray= p_uno_Seq->elements;
-
- // Get All properties in the object, convert their values to the expected type and
- // put them into the passed in sequence
- for( sal_Int32 i= 0; i< length; i++)
+ try
{
- OUString ousIndex=OUString::valueOf( i);
- OLECHAR* sindex = (OLECHAR*)ousIndex.getStr();
-
- if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sindex , 1, LOCALE_USER_DEFAULT, &dispid)))
- {
- retVal= FALSE;
- break;
- }
+ bool bFail = false;
+ if( pvar->vt != VT_DISPATCH)
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+ IDispatchEx* pdispEx;
+ HRESULT hr;
+ if( FAILED( hr= pvar->pdispVal->QueryInterface( IID_IDispatchEx,
+ reinterpret_cast<void**>( &pdispEx))))
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+
+ DISPID dispid;
+ OUString sindex;
+ DISPPARAMS param= {0,0,0,0};
+ CComVariant result;
+
+ OLECHAR* sLength= L"length";
+
+ // Get the length of the array. Can also be obtained throu GetNextDispID. The
+ // method only returns DISPIDs of the array data. Their names are like "0", "1" etc.
+ if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sLength , 1, LOCALE_USER_DEFAULT, &dispid)))
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
- &param, &result, NULL, NULL)))
+ &param, &result, NULL, NULL)))
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+ if( FAILED( VariantChangeType( &result, &result, 0, VT_I4)))
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+ long length= result.lVal;
+
+ result.Clear();
+
+ // get a few basic facts about the sequence, and reallocate:
+ // create the Sequences
+ // get the size of the elements
+ typelib_TypeDescription *pDesc= NULL;
+ type.getDescription( &pDesc);
+
+ typelib_IndirectTypeDescription *pSeqDesc= reinterpret_cast<typelib_IndirectTypeDescription*>(pDesc);
+ typelib_TypeDescriptionReference *pSeqElemDescRef= pSeqDesc->pType; // type of the Sequence' elements
+ Type elemType( pSeqElemDescRef);
+ _typelib_TypeDescription* pSeqElemDesc=NULL;
+ TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef)
+ sal_uInt32 nelementSize= pSeqElemDesc->nSize;
+ TYPELIB_DANGER_RELEASE( pSeqElemDesc)
+
+ uno_Sequence *p_uno_Seq;
+ uno_sequence_construct( &p_uno_Seq, pDesc, NULL, length, cpp_acquire);
+
+ typelib_TypeClass typeElement= pSeqDesc->pType->eTypeClass;
+ char *pArray= p_uno_Seq->elements;
+
+ // Get All properties in the object, convert their values to the expected type and
+ // put them into the passed in sequence
+ for( sal_Int32 i= 0; i< length; i++)
{
- retVal= FALSE;
- break;
- }
+ OUString ousIndex=OUString::valueOf( i);
+ OLECHAR* sindex = (OLECHAR*)ousIndex.getStr();
- // If the result is VT_DISPATCH than the Sequence's element type could be Sequence
- // Look that up in the CoreReflection to make clear.
- // That requires a recursiv conversion
- Any any;
- // Destination address within the out-Sequence "anySeq" where to copy the next converted element
- void* pDest= (void*)(pArray + (i * nelementSize));
+ if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sindex , 1, LOCALE_USER_DEFAULT, &dispid)))
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+ }
+ if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
+ &param, &result, NULL, NULL)))
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
+ "Conversion of dispatch object to Sequence failed!"));
+ }
- if( result.vt & VT_DISPATCH && typeElement == typelib_TypeClass_SEQUENCE)
- {
- if( variantToAny2( &result, any, elemType, sal_False) )
+ // If the result is VT_DISPATCH than the Sequence's element type could be Sequence
+ // Look that up in the CoreReflection to make clear.
+ // That requires a recursiv conversion
+ Any any;
+ // Destination address within the out-Sequence "anySeq" where to copy the next converted element
+ void* pDest= (void*)(pArray + (i * nelementSize));
+
+ if( result.vt & VT_DISPATCH && typeElement == typelib_TypeClass_SEQUENCE)
{
- // copy the converted VARIANT, that is a Sequence to the Sequence
+ variantToAny( &result, any, elemType, sal_False);
+ // copy the converted VARIANT, that is a Sequence to the Sequence
uno_Sequence * p_unoSeq= *(uno_Sequence**)any.getValue();
// just copy the pointer of the uno_Sequence
// nelementSize should be 4 !!!!
memcpy( pDest, &p_unoSeq, nelementSize);
osl_incrementInterlockedCount( &p_unoSeq->nRefCount);
}
- else
- {
- retVal= FALSE;
- break;
- }
- }
- else // Element type is no Sequence -> do one conversion
- {
- if( variantToAny2( &result, any, elemType, sal_False) )
+ else // Element type is no Sequence -> do one conversion
{
-
+ variantToAny( &result, any, elemType, sal_False);
if( typeElement == typelib_TypeClass_ANY)
{
// copy the converted VARIANT to the Sequence
uno_type_assignData( pDest, pSeqElemDescRef , &any, pSeqElemDescRef,cpp_queryInterface,
- cpp_acquire, cpp_release);
+ cpp_acquire, cpp_release);
}
else
{
// type after conversion must be the element type of the sequence
OSL_ENSURE( (any.getValueTypeClass() == typeElement), "wrong conversion");
uno_type_assignData( pDest, pSeqElemDescRef,const_cast<void*>( any.getValue()), any.getValueTypeRef(),
- cpp_queryInterface, cpp_acquire, cpp_release);
+ cpp_queryInterface, cpp_acquire, cpp_release);
}
- } // if
- else
- {
- retVal= FALSE;
- break;
}
} // else
- VariantClear(&result);
- if( retVal == FALSE)
- break;
- } // for
- VariantClear(&result);
- uno_Sequence **pps= &p_uno_Seq;
- anySeq.setValue( &p_uno_Seq, pDesc);
- uno_destructData( &p_uno_Seq, pDesc, cpp_release);
- typelib_typedescription_release( pDesc);
- return retVal;
+ result.Clear();
+ uno_Sequence **pps= &p_uno_Seq;
+ anySeq.setValue( &p_uno_Seq, pDesc);
+ uno_destructData( &p_uno_Seq, pDesc, cpp_release);
+ typelib_typedescription_release( pDesc);
+
+ if (bFail)
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] Conversion of ValueObject failed "));
+ }
+ catch (BridgeRuntimeError & )
+ {
+ throw;
+ }
+ catch (Exception & e)
+ {
+ throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::convertValueObject ! Message : \n") +
+ e.Message);
+ }
+ catch(...)
+ {
+ throw BridgeRuntimeError(
+ OUSTR("[automation bridge] unexpected exception in "
+ "UnoConversionUtilities<T>::convertValueObject !"));
+ }
}
/* The argument unotype is the type that is expected by the currently called UNO function.
- For example: []long, [][]long. If the function calls itself recursively then unotype is
- just passed on. It is only used to determine the element type (e.g. long here).
+ For example: []long, [][]long. If the function calls itself recursively then the element type
+ is passed on. For example a two dimensional SAFEARRAY of type VT_I4 is to be converted. Then
+ unotype has to be either void or [][]long. When the function calls itself recursivly then
+ it passes the element type which is []long.
*/
template<class T>
Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray,
@@ -1710,16 +2082,15 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* p
SafeArrayGetUBound(pArray, actDim, &uBound);
nCountElements= uBound - lBound +1;
- Type elementType;
-
Sequence<Any> anySeq(nCountElements);
Any* pUnoArray = anySeq.getArray();
- for (index[actDim - 1] = lBound; index[actDim - 1] < nCountElements; index[actDim - 1]++)
+ for (index[actDim - 1] = lBound; index[actDim - 1] <= uBound; index[actDim - 1]++)
{
if (actDim > 1 )
{
- Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount, actDim - 1, index, type, unotype);
+ Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount,
+ actDim - 1, index, type, getElementTypeOfSequence(unotype));
pUnoArray[index[actDim - 1] - lBound].setValue(&element, getCppuType(&element));
}
@@ -1785,19 +2156,12 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* p
break;
}
- // obtain the element type of the sequence. In case the sequence contains a sequence, then
- // get the element type of that sequence and so on. For example, element type of
- // Sequence<Sequence<long> > is long
- if( elementType.getTypeClass() == TypeClass_VOID)
- elementType= getElementTypeOfSequence( unotype);
-
if( unotype.getTypeClass() == TypeClass_VOID)
// the function was called without specifying the destination type
variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], sal_False);
- else if( variant.vt & VT_ARRAY)
- variantToAny2(&variant, pUnoArray[index[actDim - 1] - lBound], unotype, sal_False);
else
- variantToAny2(&variant, pUnoArray[index[actDim - 1] - lBound], elementType, sal_False);
+ variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound],
+ getElementTypeOfSequence(unotype), sal_False);
VariantClear(&variant);
}
@@ -1812,14 +2176,9 @@ Type UnoConversionUtilities<T>::getElementTypeOfSequence( const Type& seqType)
if( seqType.getTypeClass() != TypeClass_VOID)
{
OSL_ASSERT( seqType.getTypeClass() == TypeClass_SEQUENCE);
-
typelib_IndirectTypeDescription* pDescSeq= NULL;
- seqType.getDescription( (typelib_TypeDescription** ) & pDescSeq);
- if( pDescSeq->pType->eTypeClass == TypeClass_SEQUENCE)
- retValue= getElementTypeOfSequence( Type( pDescSeq->pType));
- else
- retValue= Type( pDescSeq->pType);
-
+ seqType.getDescription((typelib_TypeDescription** ) & pDescSeq);
+ retValue = Type(pDescSeq->pType);
typelib_typedescription_release( (typelib_TypeDescription*) pDescSeq);
}
return retValue;
@@ -1833,7 +2192,8 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray
if (dim > 0)
{
- long * index = new long[dim];
+ scoped_array<long> sarIndex(new long[dim]);
+ long * index = sarIndex.get();
for (unsigned int i = 0; i < dim; i++)
{
@@ -1841,8 +2201,6 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray
}
ret = createOleArrayWrapperOfDim(pArray, dim, dim, index, type, unoType);
-
- delete[] index;
}
return ret;
@@ -1933,25 +2291,38 @@ Sequence<Type> UnoConversionUtilities<T>::getImplementedInterfaces(IUnknown* pUn
{
// we exspect an array( SafeArray or IDispatch) of Strings.
Any anyNames;
- if( variantToAny2( &var, anyNames, getCppuType( (Sequence<Any>*) 0)))
+ variantToAny( &var, anyNames, getCppuType( (Sequence<Any>*) 0));
+ Sequence<Any> seqAny;
+ if( anyNames >>= seqAny)
{
- Sequence<Any> seqAny;
- if( anyNames >>= seqAny)
+ seqTypes.realloc( seqAny.getLength());
+ for( sal_Int32 i=0; i < seqAny.getLength(); i++)
{
- seqTypes.realloc( seqAny.getLength());
- for( sal_Int32 i=0; i < seqAny.getLength(); i++)
- {
- OUString typeName;
- seqAny[i] >>= typeName;
- seqTypes[i]= Type( TypeClass_INTERFACE, typeName);
- }
+ OUString typeName;
+ seqAny[i] >>= typeName;
+ seqTypes[i]= Type( TypeClass_INTERFACE, typeName);
}
}
}
}
return seqTypes;
}
-
+template<class T>
+Reference<XTypeConverter> UnoConversionUtilities<T>::getTypeConverter()
+{
+ if ( ! m_typeConverter.is())
+ {
+ MutexGuard guard(getBridgeMutex());
+ if ( ! m_typeConverter.is())
+ {
+ Reference<XInterface> xIntConverter =
+ m_smgr->createInstance(OUSTR("com.sun.star.script.Converter"));
+ if (xIntConverter.is())
+ m_typeConverter = Reference<XTypeConverter>(xIntConverter, UNO_QUERY);
+ }
+ }
+ return m_typeConverter;
+}
// This function tries to the change the type of a value (contained in the Any)
// to the smallest possible that can hold the value. This is actually done only
@@ -1990,6 +2361,9 @@ inline void reduceRange( Any& any)
}
}
#endif
+
+
+
} // end namespace
#endif