/************************************************************************* * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_stoc.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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_InterfaceTypeDescription * pTD = 0; const Type & rInvType = ::getCppuType( (const Reference< script::XInvocation > *)0 ); TYPELIB_DANGER_GET( (typelib_TypeDescription **)&pTD, rInvType.getTypeLibType() ); if( ! pTD->aBase.bComplete ) typelib_typedescription_complete( (typelib_TypeDescription **)&pTD ); ::typelib_typedescriptionreference_getDescription( &m_pInvokMethodTD, pTD->ppMembers[ 1 ] ); // invoke() ::typelib_typedescriptionreference_getDescription( &m_pSetValueTD, pTD->ppMembers[ 2 ] ); // setValue() ::typelib_typedescriptionreference_getDescription( &m_pGetValueTD, pTD->ppMembers[ 3 ] ); // getValue() // script.XTypeConverter const Type & rTCType = ::getCppuType( (const Reference< script::XTypeConverter > *)0 ); TYPELIB_DANGER_GET( (typelib_TypeDescription **)&pTD, rTCType.getTypeLibType() ); ::typelib_typedescriptionreference_getDescription( &m_pConvertToTD, pTD->ppMembers[ 0 ] ); // convertTo() TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)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 ); } }