summaryrefslogtreecommitdiff
path: root/stoc/source/invocation_adapterfactory/iafactory.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'stoc/source/invocation_adapterfactory/iafactory.cxx')
-rw-r--r--stoc/source/invocation_adapterfactory/iafactory.cxx1033
1 files changed, 1033 insertions, 0 deletions
diff --git a/stoc/source/invocation_adapterfactory/iafactory.cxx b/stoc/source/invocation_adapterfactory/iafactory.cxx
new file mode 100644
index 000000000000..2fda1819f891
--- /dev/null
+++ b/stoc/source/invocation_adapterfactory/iafactory.cxx
@@ -0,0 +1,1033 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_stoc.hxx"
+
+#include <hash_map>
+#include <hash_set>
+
+#include <osl/diagnose.h>
+#include <osl/interlck.h>
+#include <osl/mutex.hxx>
+
+#include <uno/dispatcher.h>
+#include <uno/data.h>
+#include <uno/any2.h>
+#include <uno/mapping.hxx>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/implementationentry.hxx>
+
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/script/XTypeConverter.hpp>
+#include <com/sun/star/script/XInvocationAdapterFactory.hpp>
+#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include <com/sun/star/reflection/InvocationTargetException.hpp>
+#include "com/sun/star/uno/RuntimeException.hpp"
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+
+#define SERVICENAME "com.sun.star.script.InvocationAdapterFactory"
+#define IMPLNAME "com.sun.star.comp.stoc.InvocationAdapterFactory"
+
+
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+namespace stoc_invadp
+{
+
+static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
+
+static Sequence< OUString > invadp_getSupportedServiceNames()
+{
+ static Sequence < OUString > *pNames = 0;
+ if( ! pNames )
+ {
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ if( !pNames )
+ {
+ static Sequence< OUString > seqNames(1);
+ seqNames.getArray()[0] =
+ OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME));
+ pNames = &seqNames;
+ }
+ }
+ return *pNames;
+}
+
+static OUString invadp_getImplementationName()
+{
+ static OUString *pImplName = 0;
+ if( ! pImplName )
+ {
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ if( ! pImplName )
+ {
+ static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) );
+ pImplName = &implName;
+ }
+ }
+ return *pImplName;
+}
+
+struct hash_ptr
+{
+ inline size_t operator() ( void * p ) const
+ { return (size_t)p; }
+};
+typedef hash_set< void *, hash_ptr, equal_to< void * > > t_ptr_set;
+typedef hash_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map;
+
+//==============================================================================
+class FactoryImpl
+ : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
+ script::XInvocationAdapterFactory,
+ script::XInvocationAdapterFactory2 >
+{
+public:
+ Mapping m_aUno2Cpp;
+ Mapping m_aCpp2Uno;
+ uno_Interface * m_pConverter;
+
+ typelib_TypeDescription * m_pInvokMethodTD;
+ typelib_TypeDescription * m_pSetValueTD;
+ typelib_TypeDescription * m_pGetValueTD;
+ typelib_TypeDescription * m_pAnySeqTD;
+ typelib_TypeDescription * m_pShortSeqTD;
+ typelib_TypeDescription * m_pConvertToTD;
+
+ Mutex m_mutex;
+ t_ptr_map m_receiver2adapters;
+
+ FactoryImpl( Reference< XComponentContext > const & xContext )
+ SAL_THROW( (RuntimeException) );
+ virtual ~FactoryImpl() SAL_THROW( () );
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName()
+ throw (RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName )
+ throw (RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
+ throw (RuntimeException);
+
+ // XInvocationAdapterFactory
+ virtual Reference< XInterface > SAL_CALL createAdapter(
+ const Reference< script::XInvocation > & xReceiver, const Type & rType )
+ throw (RuntimeException);
+ // XInvocationAdapterFactory2
+ virtual Reference< XInterface > SAL_CALL createAdapter(
+ const Reference< script::XInvocation > & xReceiver,
+ const Sequence< Type > & rTypes )
+ throw (RuntimeException);
+};
+struct AdapterImpl;
+//==============================================================================
+struct InterfaceAdapterImpl : public uno_Interface
+{
+ AdapterImpl * m_pAdapter;
+ typelib_InterfaceTypeDescription * m_pTypeDescr;
+};
+//==============================================================================
+struct AdapterImpl
+{
+ oslInterlockedCount m_nRef;
+ FactoryImpl * m_pFactory;
+ void * m_key; // map key
+ uno_Interface * m_pReceiver; // XInvocation receiver
+
+ sal_Int32 m_nInterfaces;
+ InterfaceAdapterImpl * m_pInterfaces;
+
+ // XInvocation calls
+ void getValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException );
+ void setValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException );
+ void invoke(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException );
+
+ bool coerce_assign(
+ void * pDest, typelib_TypeDescriptionReference * pType,
+ uno_Any * pSource, uno_Any * pExc );
+ inline bool coerce_construct(
+ void * pDest, typelib_TypeDescriptionReference * pType,
+ uno_Any * pSource, uno_Any * pExc );
+
+ inline void acquire()
+ SAL_THROW( () );
+ inline void release()
+ SAL_THROW( () );
+ inline ~AdapterImpl()
+ SAL_THROW( () );
+ inline AdapterImpl(
+ void * key, Reference< script::XInvocation > const & xReceiver,
+ const Sequence< Type > & rTypes,
+ FactoryImpl * pFactory )
+ SAL_THROW( (RuntimeException) );
+};
+//______________________________________________________________________________
+inline AdapterImpl::~AdapterImpl()
+ SAL_THROW( () )
+{
+ for ( sal_Int32 nPos = m_nInterfaces; nPos--; )
+ {
+ ::typelib_typedescription_release(
+ (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr );
+ }
+ delete [] m_pInterfaces;
+ //
+ (*m_pReceiver->release)( m_pReceiver );
+ m_pFactory->release();
+}
+//______________________________________________________________________________
+inline void AdapterImpl::acquire()
+ SAL_THROW( () )
+{
+ ::osl_incrementInterlockedCount( &m_nRef );
+}
+//______________________________________________________________________________
+inline void AdapterImpl::release()
+ SAL_THROW( () )
+{
+ bool delete_this = false;
+ {
+ MutexGuard guard( m_pFactory->m_mutex );
+ if (! ::osl_decrementInterlockedCount( &m_nRef ))
+ {
+ t_ptr_map::iterator iFind(
+ m_pFactory->m_receiver2adapters.find( m_key ) );
+ OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
+ t_ptr_set & adapter_set = iFind->second;
+ if (adapter_set.erase( this ) != 1) {
+ OSL_ASSERT( false );
+ }
+ if (adapter_set.empty())
+ {
+ m_pFactory->m_receiver2adapters.erase( iFind );
+ }
+ delete_this = true;
+ }
+ }
+ if (delete_this)
+ delete this;
+}
+
+//------------------------------------------------------------------------------
+static inline void constructRuntimeException(
+ uno_Any * pExc, const OUString & rMsg )
+{
+ RuntimeException exc( rMsg, Reference< XInterface >() );
+ // no conversion neeeded due to binary compatibility + no convertable type
+ ::uno_type_any_construct(
+ pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 );
+}
+
+//------------------------------------------------------------------------------
+static inline sal_Bool type_equals(
+ typelib_TypeDescriptionReference * pType1,
+ typelib_TypeDescriptionReference * pType2 )
+ SAL_THROW( () )
+{
+ return (pType1 == pType2 ||
+ (pType1->pTypeName->length == pType2->pTypeName->length &&
+ 0 == ::rtl_ustr_compare(
+ pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
+}
+
+//______________________________________________________________________________
+bool AdapterImpl::coerce_assign(
+ void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
+ uno_Any * pOutExc )
+{
+ if (typelib_TypeClass_ANY == pType->eTypeClass)
+ {
+ ::uno_type_any_assign(
+ (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 );
+ return true;
+ }
+ if (::uno_type_assignData(
+ pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 ))
+ {
+ return true;
+ }
+ else // try type converter
+ {
+ uno_Any ret;
+ void * args[ 2 ];
+ args[ 0 ] = pSource;
+ args[ 1 ] = &pType;
+ uno_Any exc;
+ uno_Any * p_exc = &exc;
+
+ // converTo()
+ (*m_pFactory->m_pConverter->pDispatcher)(
+ m_pFactory->m_pConverter,
+ m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
+
+ if (p_exc) // exception occured
+ {
+ OSL_ASSERT(
+ p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
+ if (typelib_typedescriptionreference_isAssignableFrom(
+ ::getCppuType(
+ (RuntimeException const *) 0 ).getTypeLibType(),
+ p_exc->pType ))
+ {
+ // is RuntimeException or derived: rethrow
+ uno_type_any_construct(
+ pOutExc, p_exc->pData, p_exc->pType, 0 );
+ }
+ else
+ {
+ // set runtime exception
+ constructRuntimeException(
+ pOutExc, OUSTR("type coercion failed: ") +
+ reinterpret_cast< Exception const * >(
+ p_exc->pData )->Message );
+ }
+ ::uno_any_destruct( p_exc, 0 );
+ // pOutExc constructed
+ return false;
+ }
+ else
+ {
+ bool succ = (sal_False != ::uno_type_assignData(
+ pDest, pType, ret.pData, ret.pType, 0, 0, 0 ));
+ ::uno_any_destruct( &ret, 0 );
+ OSL_ENSURE(
+ succ, "### conversion succeeded, but assignment failed!?" );
+ if (! succ)
+ {
+ // set runtime exception
+ constructRuntimeException(
+ pOutExc,
+ OUSTR("type coercion failed: "
+ "conversion succeeded, but assignment failed?!") );
+ }
+ return succ;
+ }
+ }
+}
+//______________________________________________________________________________
+inline bool AdapterImpl::coerce_construct(
+ void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
+ uno_Any * pExc )
+{
+ if (typelib_TypeClass_ANY == pType->eTypeClass)
+ {
+ ::uno_type_copyData( pDest, pSource, pType, 0 );
+ return true;
+ }
+ if (type_equals( pType, pSource->pType))
+ {
+ ::uno_type_copyData( pDest, pSource->pData, pType, 0 );
+ return true;
+ }
+ ::uno_type_constructData( pDest, pType );
+ return coerce_assign( pDest, pType, pSource, pExc );
+}
+
+//------------------------------------------------------------------------------
+static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
+{
+ OUString const & name =
+ *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName );
+
+ if (name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.reflection.InvocationTargetException") ))
+ {
+ // unwrap invocation target exception
+ uno_Any * target_exc =
+ &reinterpret_cast< reflection::InvocationTargetException * >(
+ pSource->pData )->TargetException;
+ ::uno_type_any_construct(
+ pDest, target_exc->pData, target_exc->pType, 0 );
+ }
+ else // all other exceptions are wrapped to RuntimeException
+ {
+ if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
+ {
+ constructRuntimeException(
+ pDest, ((Exception const *)pSource->pData)->Message );
+ }
+ else
+ {
+ constructRuntimeException(
+ pDest, OUSTR("no exception has been thrown via invocation?!") );
+ }
+ }
+}
+//______________________________________________________________________________
+void AdapterImpl::getValue(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * [], uno_Any ** ppException )
+{
+ uno_Any aInvokRet;
+ void * pInvokArgs[1];
+ pInvokArgs[0] =
+ &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // getValue()
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pGetValueTD,
+ &aInvokRet, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc) // getValue() call exception
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, 0 ); // cleanup
+ }
+ else // invocation call succeeded
+ {
+ if (coerce_construct(
+ pReturn,
+ ((typelib_InterfaceAttributeTypeDescription *)
+ pMemberType)->pAttributeTypeRef,
+ &aInvokRet, *ppException ))
+ {
+ *ppException = 0; // no exceptions be thrown
+ }
+ ::uno_any_destruct( &aInvokRet, 0 );
+ }
+}
+//______________________________________________________________________________
+void AdapterImpl::setValue(
+ const typelib_TypeDescription * pMemberType,
+ void *, void * pArgs[], uno_Any ** ppException )
+{
+ uno_Any aInvokVal;
+ ::uno_type_any_construct(
+ &aInvokVal, pArgs[0],
+ ((typelib_InterfaceAttributeTypeDescription *)
+ pMemberType)->pAttributeTypeRef, 0 );
+
+ void * pInvokArgs[2];
+ pInvokArgs[0] =
+ &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
+ pInvokArgs[1] = &aInvokVal;
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // setValue()
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc) // setValue() call exception
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, 0 ); // cleanup
+ }
+ else // invocation call succeeded
+ {
+ *ppException = 0; // no exceptions be thrown
+ }
+
+ ::uno_any_destruct( &aInvokVal, 0 ); // cleanup
+}
+//______________________________________________________________________________
+void AdapterImpl::invoke(
+ const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+ sal_Int32 nParams =
+ ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams;
+ typelib_MethodParameter * pFormalParams =
+ ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams;
+
+ // in params
+ uno_Sequence * pInParamsSeq = 0;
+ ::uno_sequence_construct(
+ &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 );
+ uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements;
+ sal_Int32 nOutParams = 0;
+ sal_Int32 nPos;
+ for ( nPos = nParams; nPos--; )
+ {
+ typelib_MethodParameter const & rParam = pFormalParams[nPos];
+ if (rParam.bIn) // is in/inout param
+ {
+ ::uno_type_any_assign(
+ &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 );
+ }
+ // else: pure out is empty any
+
+ if (rParam.bOut)
+ ++nOutParams;
+ }
+
+ // out params, out indices
+ uno_Sequence * pOutIndices;
+ uno_Sequence * pOutParams;
+ // return value
+ uno_Any aInvokRet;
+ // perform call
+ void * pInvokArgs[4];
+ pInvokArgs[0] =
+ &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
+ pInvokArgs[1] = &pInParamsSeq;
+ pInvokArgs[2] = &pOutIndices;
+ pInvokArgs[3] = &pOutParams;
+ uno_Any aInvokExc;
+ uno_Any * pInvokExc = &aInvokExc;
+
+ // invoke() call
+ (*m_pReceiver->pDispatcher)(
+ m_pReceiver, m_pFactory->m_pInvokMethodTD,
+ &aInvokRet, pInvokArgs, &pInvokExc );
+
+ if (pInvokExc)
+ {
+ handleInvokExc( *ppException, pInvokExc );
+ ::uno_any_destruct( pInvokExc, 0 ); // cleanup
+ }
+ else // no invocation exception
+ {
+ // write changed out params
+ OSL_ENSURE(
+ pOutParams->nElements == nOutParams &&
+ pOutIndices->nElements == nOutParams,
+ "### out params lens differ!" );
+ if (pOutParams->nElements == nOutParams &&
+ pOutIndices->nElements == nOutParams)
+ {
+ sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements;
+ uno_Any * pOut = (uno_Any *)pOutParams->elements;
+ for ( nPos = 0; nPos < nOutParams; ++nPos )
+ {
+ sal_Int32 nIndex = pIndices[nPos];
+ OSL_ENSURE( nIndex < nParams, "### illegal index!" );
+ typelib_MethodParameter const & rParam = pFormalParams[nIndex];
+ bool succ;
+ if (rParam.bIn) // is in/inout param
+ {
+ succ = coerce_assign(
+ pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
+ *ppException );
+ }
+ else // pure out
+ {
+ succ = coerce_construct(
+ pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
+ *ppException );
+ }
+ if (! succ) // cleanup of out params
+ {
+ for ( sal_Int32 n = 0; n <= nPos; ++n )
+ {
+ sal_Int32 nIndex2 = pIndices[n];
+ OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
+ typelib_MethodParameter const & rParam2 =
+ pFormalParams[nIndex2];
+ if (! rParam2.bIn) // is pure out param
+ {
+ ::uno_type_destructData(
+ pArgs[nIndex2], rParam2.pTypeRef, 0 );
+ }
+ }
+ }
+ }
+ if (nPos == pOutIndices->nElements)
+ {
+ // out param copy ok; write return value
+ if (coerce_construct(
+ pReturn,
+ ((typelib_InterfaceMethodTypeDescription *)
+ pMemberType)->pReturnTypeRef,
+ &aInvokRet, *ppException ))
+ {
+ *ppException = 0; // no exception
+ }
+ }
+ }
+ else
+ {
+ // set runtime exception
+ constructRuntimeException(
+ *ppException,
+ OUSTR("out params lengths differ after invocation call!") );
+ }
+ // cleanup invok out params
+ ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 );
+ ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 );
+ // cleanup invok return value
+ ::uno_any_destruct( &aInvokRet, 0 );
+ }
+ // cleanup constructed in params
+ ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 );
+}
+
+extern "C"
+{
+//______________________________________________________________________________
+static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
+{
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
+}
+//______________________________________________________________________________
+static void SAL_CALL adapter_release( uno_Interface * pUnoI )
+{
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
+}
+//______________________________________________________________________________
+static void SAL_CALL adapter_dispatch(
+ uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
+ void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+ // query to emulated interface
+ switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition)
+ {
+ case 0: // queryInterface()
+ {
+ AdapterImpl * that =
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
+ *ppException = 0; // no exc
+ typelib_TypeDescriptionReference * pDemanded =
+ *(typelib_TypeDescriptionReference **)pArgs[0];
+ // pInterfaces[0] is XInterface
+ for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos )
+ {
+ typelib_InterfaceTypeDescription * pTD =
+ that->m_pInterfaces[nPos].m_pTypeDescr;
+ while (pTD)
+ {
+ if (type_equals(
+ ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded ))
+ {
+ uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
+ ::uno_any_construct(
+ (uno_Any *)pReturn, &pUnoI2,
+ (typelib_TypeDescription *)pTD, 0 );
+ return;
+ }
+ pTD = pTD->pBaseTypeDescription;
+ }
+ }
+ ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear()
+ break;
+ }
+ case 1: // acquire()
+ *ppException = 0; // no exc
+ adapter_acquire( pUnoI );
+ break;
+ case 2: // release()
+ *ppException = 0; // no exc
+ adapter_release( pUnoI );
+ break;
+
+ default:
+ {
+ AdapterImpl * that =
+ static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
+ if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
+ {
+ that->invoke( pMemberType, pReturn, pArgs, ppException );
+ }
+ else // attribute
+ {
+ if (pReturn)
+ that->getValue( pMemberType, pReturn, pArgs, ppException );
+ else
+ that->setValue( pMemberType, pReturn, pArgs, ppException );
+ }
+ }
+ }
+}
+}
+//______________________________________________________________________________
+AdapterImpl::AdapterImpl(
+ void * key, Reference< script::XInvocation > const & xReceiver,
+ const Sequence< Type > & rTypes,
+ FactoryImpl * pFactory )
+ SAL_THROW( (RuntimeException) )
+ : m_nRef( 1 ),
+ m_pFactory( pFactory ),
+ m_key( key )
+{
+ // init adapters
+ m_nInterfaces = rTypes.getLength();
+ m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ];
+ const Type * pTypes = rTypes.getConstArray();
+ for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
+ {
+ InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos];
+ pInterface->acquire = adapter_acquire;
+ pInterface->release = adapter_release;
+ pInterface->pDispatcher = adapter_dispatch;
+ pInterface->m_pAdapter = this;
+ pInterface->m_pTypeDescr = 0;
+ pTypes[nPos].getDescription(
+ (typelib_TypeDescription **)&pInterface->m_pTypeDescr );
+ OSL_ASSERT( pInterface->m_pTypeDescr );
+ if (! pInterface->m_pTypeDescr)
+ {
+ for ( sal_Int32 n = 0; n < nPos; ++n )
+ {
+ ::typelib_typedescription_release(
+ (typelib_TypeDescription *)
+ m_pInterfaces[ n ].m_pTypeDescr );
+ }
+ delete [] m_pInterfaces;
+ throw RuntimeException(
+ OUSTR("cannot retrieve all interface type infos!"),
+ Reference< XInterface >() );
+ }
+ }
+
+ // map receiver
+ m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface(
+ xReceiver.get(), ::getCppuType( &xReceiver ) );
+ OSL_ASSERT( 0 != m_pReceiver );
+ if (! m_pReceiver)
+ {
+ throw RuntimeException(
+ OUSTR("cannot map receiver!"), Reference< XInterface >() );
+ }
+
+ m_pFactory->acquire();
+}
+
+//______________________________________________________________________________
+FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
+ SAL_THROW( (RuntimeException) )
+ : m_pInvokMethodTD( 0 ),
+ m_pSetValueTD( 0 ),
+ m_pGetValueTD( 0 ),
+ m_pAnySeqTD( 0 ),
+ m_pShortSeqTD( 0 ),
+ m_pConvertToTD( 0 )
+{
+ // C++/UNO bridge
+ OUString aCppEnvTypeName = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
+ OUString aUnoEnvTypeName = OUSTR(UNO_LB_UNO);
+ m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName );
+ m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName );
+ OSL_ENSURE(
+ m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
+
+ // type converter
+ Reference< script::XTypeConverter > xConverter(
+ xContext->getServiceManager()->createInstanceWithContext(
+ OUString(
+ RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter") ),
+ xContext ),
+ UNO_QUERY_THROW );
+ m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface(
+ xConverter.get(), ::getCppuType( &xConverter ) );
+ OSL_ASSERT( 0 != m_pConverter );
+
+ // some type info:
+ // sequence< any >
+ Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 );
+ rAnySeqType.getDescription( &m_pAnySeqTD );
+ // sequence< short >
+ const Type & rShortSeqType =
+ ::getCppuType( (const Sequence< sal_Int16 > *)0 );
+ rShortSeqType.getDescription( &m_pShortSeqTD );
+ // script.XInvocation
+ typelib_TypeDescription * pTD = 0;
+ const Type & rInvType = ::getCppuType(
+ (const Reference< script::XInvocation > *)0 );
+ TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
+ typelib_InterfaceTypeDescription * pITD;
+ pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
+ if( ! pITD->aBase.bComplete )
+ typelib_typedescription_complete( &pTD );
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
+ // script.XTypeConverter
+ const Type & rTCType =
+ ::getCppuType( (const Reference< script::XTypeConverter > *)0 );
+ TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
+ pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
+ ::typelib_typedescriptionreference_getDescription(
+ &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
+ !m_pConvertToTD ||
+ !m_pAnySeqTD || !m_pShortSeqTD)
+ {
+ throw RuntimeException(
+ OUSTR("missing type descriptions!"), Reference< XInterface >() );
+ }
+
+ g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
+}
+//______________________________________________________________________________
+FactoryImpl::~FactoryImpl() SAL_THROW( () )
+{
+ ::typelib_typedescription_release( m_pInvokMethodTD );
+ ::typelib_typedescription_release( m_pSetValueTD );
+ ::typelib_typedescription_release( m_pGetValueTD );
+ ::typelib_typedescription_release( m_pAnySeqTD );
+ ::typelib_typedescription_release( m_pShortSeqTD );
+ ::typelib_typedescription_release( m_pConvertToTD );
+
+ (*m_pConverter->release)( m_pConverter );
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" );
+#endif
+ g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
+}
+
+//------------------------------------------------------------------------------
+static inline AdapterImpl * lookup_adapter(
+ t_ptr_set ** pp_adapter_set,
+ t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
+ SAL_THROW( () )
+{
+ t_ptr_set & adapters_set = map[ key ];
+ *pp_adapter_set = &adapters_set;
+ if (adapters_set.empty())
+ return 0; // shortcut
+ // find matching adapter
+ Type const * pTypes = rTypes.getConstArray();
+ sal_Int32 nTypes = rTypes.getLength();
+ t_ptr_set::const_iterator iPos( adapters_set.begin() );
+ t_ptr_set::const_iterator const iEnd( adapters_set.end() );
+ while (iEnd != iPos)
+ {
+ AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos );
+ // iterate thru all types if that is a matching adapter
+ sal_Int32 nPosTypes;
+ for ( nPosTypes = nTypes; nPosTypes--; )
+ {
+ Type const & rType = pTypes[ nPosTypes ];
+ // find in adapter's type list
+ sal_Int32 nPos;
+ for ( nPos = that->m_nInterfaces; nPos--; )
+ {
+ if (::typelib_typedescriptionreference_isAssignableFrom(
+ rType.getTypeLibType(),
+ ((typelib_TypeDescription *)that->
+ m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef ))
+ {
+ // found
+ break;
+ }
+ }
+ if (nPos < 0) // type not found => next adapter
+ break;
+ }
+ if (nPosTypes < 0) // all types found
+ return that;
+ ++iPos;
+ }
+ return 0;
+}
+
+// XInvocationAdapterFactory2 impl
+//______________________________________________________________________________
+Reference< XInterface > FactoryImpl::createAdapter(
+ const Reference< script::XInvocation > & xReceiver,
+ const Sequence< Type > & rTypes )
+ throw (RuntimeException)
+{
+ Reference< XInterface > xRet;
+ if (xReceiver.is() && rTypes.getLength())
+ {
+ t_ptr_set * adapter_set;
+ AdapterImpl * that;
+ Reference< XInterface > xKey( xReceiver, UNO_QUERY );
+ {
+ ClearableMutexGuard guard( m_mutex );
+ that = lookup_adapter(
+ &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
+ if (0 == that) // no entry
+ {
+ guard.clear();
+ // create adapter; already acquired: m_nRef == 1
+ AdapterImpl * pNew =
+ new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
+ // lookup again
+ ClearableMutexGuard guard2( m_mutex );
+ that = lookup_adapter(
+ &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
+ if (0 == that) // again no entry
+ {
+ pair< t_ptr_set::iterator, bool > insertion(
+ adapter_set->insert( pNew ) );
+ OSL_ASSERT( insertion.second );
+ that = pNew;
+ }
+ else
+ {
+ that->acquire();
+ guard2.clear();
+ delete pNew; // has never been inserted
+ }
+ }
+ else // found adapter
+ {
+ that->acquire();
+ }
+ }
+ // map one interface to C++
+ uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ];
+ m_aUno2Cpp.mapInterface(
+ (void **)&xRet, pUnoI, ::getCppuType( &xRet ) );
+ that->release();
+ OSL_ASSERT( xRet.is() );
+ if (! xRet.is())
+ {
+ throw RuntimeException(
+ OUSTR("mapping UNO to C++ failed!"),
+ Reference< XInterface >() );
+ }
+ }
+ return xRet;
+}
+// XInvocationAdapterFactory impl
+//______________________________________________________________________________
+Reference< XInterface > FactoryImpl::createAdapter(
+ const Reference< script::XInvocation > & xReceiver, const Type & rType )
+ throw (RuntimeException)
+{
+ return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
+}
+
+// XServiceInfo
+//______________________________________________________________________________
+OUString FactoryImpl::getImplementationName()
+ throw (RuntimeException)
+{
+ return invadp_getImplementationName();
+}
+//______________________________________________________________________________
+sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
+ throw (RuntimeException)
+{
+ const Sequence< OUString > & rSNL = getSupportedServiceNames();
+ const OUString * pArray = rSNL.getConstArray();
+ for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
+ {
+ if (pArray[nPos].equals( rServiceName ))
+ return sal_True;
+ }
+ return sal_False;
+}
+//______________________________________________________________________________
+Sequence< OUString > FactoryImpl::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return invadp_getSupportedServiceNames();
+}
+
+//==============================================================================
+static Reference< XInterface > SAL_CALL FactoryImpl_create(
+ const Reference< XComponentContext > & xContext )
+ throw (Exception)
+{
+ Reference< XInterface > rRet;
+ {
+ MutexGuard guard( Mutex::getGlobalMutex() );
+ static WeakReference < XInterface > rwInstance;
+ rRet = rwInstance;
+
+ if( ! rRet.is() )
+ {
+ rRet = (::cppu::OWeakObject *)new FactoryImpl( xContext );
+ rwInstance = rRet;
+ }
+ }
+ return rRet;
+}
+
+}
+
+
+//##############################################################################
+//##############################################################################
+//##############################################################################
+
+static struct ::cppu::ImplementationEntry g_entries[] =
+{
+ {
+ ::stoc_invadp::FactoryImpl_create,
+ ::stoc_invadp::invadp_getImplementationName,
+ ::stoc_invadp::invadp_getSupportedServiceNames,
+ ::cppu::createSingleComponentFactory,
+ &::stoc_invadp::g_moduleCount.modCnt , 0
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+extern "C"
+{
+sal_Bool SAL_CALL component_canUnload(
+ TimeValue *pTime )
+{
+ return ::stoc_invadp::g_moduleCount.canUnload(
+ &::stoc_invadp::g_moduleCount, pTime );
+}
+
+//==============================================================================
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+//==============================================================================
+sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ return ::cppu::component_writeInfoHelper(
+ pServiceManager, pRegistryKey, g_entries );
+}
+
+//==============================================================================
+void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ return ::cppu::component_getFactoryHelper(
+ pImplName, pServiceManager, pRegistryKey , g_entries );
+}
+}