LCOV - code coverage report
Current view: top level - stoc/source/invocation_adapterfactory - iafactory.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 192 320 60.0 %
Date: 2014-11-03 Functions: 20 29 69.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <boost/unordered_map.hpp>
      22             : #include <boost/unordered_set.hpp>
      23             : 
      24             : #include <osl/diagnose.h>
      25             : #include <osl/interlck.h>
      26             : #include <osl/mutex.hxx>
      27             : 
      28             : #include <uno/dispatcher.h>
      29             : #include <uno/data.h>
      30             : #include <uno/any2.h>
      31             : #include <uno/lbnames.h>
      32             : #include <uno/mapping.hxx>
      33             : 
      34             : #include <cppuhelper/factory.hxx>
      35             : #include <cppuhelper/implbase3.hxx>
      36             : #include <cppuhelper/implementationentry.hxx>
      37             : #include <cppuhelper/supportsservice.hxx>
      38             : 
      39             : #include <com/sun/star/uno/XAggregation.hpp>
      40             : #include <com/sun/star/script/XTypeConverter.hpp>
      41             : #include <com/sun/star/script/XInvocationAdapterFactory.hpp>
      42             : #include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
      43             : #include <com/sun/star/script/XInvocation.hpp>
      44             : #include <com/sun/star/lang/XServiceInfo.hpp>
      45             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      46             : #include <com/sun/star/registry/XSimpleRegistry.hpp>
      47             : #include <com/sun/star/registry/XRegistryKey.hpp>
      48             : #include <com/sun/star/reflection/InvocationTargetException.hpp>
      49             : #include <com/sun/star/uno/RuntimeException.hpp>
      50             : 
      51             : #define SERVICENAME "com.sun.star.script.InvocationAdapterFactory"
      52             : #define IMPLNAME    "com.sun.star.comp.stoc.InvocationAdapterFactory"
      53             : 
      54             : 
      55             : using namespace ::std;
      56             : using namespace ::osl;
      57             : using namespace ::com::sun::star;
      58             : using namespace css::uno;
      59             : 
      60             : namespace stoc_invadp
      61             : {
      62             : 
      63          14 : static Sequence< OUString > invadp_getSupportedServiceNames()
      64             : {
      65          14 :     Sequence< OUString > seqNames(1);
      66          28 :     seqNames.getArray()[0] =
      67          14 :         OUString(SERVICENAME);
      68          14 :     return seqNames;
      69             : }
      70             : 
      71          14 : static OUString invadp_getImplementationName()
      72             : {
      73          14 :     return OUString(IMPLNAME);
      74             : }
      75             : 
      76             : struct hash_ptr
      77             : {
      78        1034 :     inline size_t operator() ( void * p ) const
      79        1034 :         { return reinterpret_cast<size_t>(p); }
      80             : };
      81             : typedef boost::unordered_set< void *, hash_ptr, equal_to< void * > > t_ptr_set;
      82             : typedef boost::unordered_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map;
      83             : 
      84             : 
      85             : class FactoryImpl
      86             :     : public ::cppu::WeakImplHelper3< lang::XServiceInfo,
      87             :                                       script::XInvocationAdapterFactory,
      88             :                                       script::XInvocationAdapterFactory2 >
      89             : {
      90             : public:
      91             :     Mapping m_aUno2Cpp;
      92             :     Mapping m_aCpp2Uno;
      93             :     uno_Interface * m_pConverter;
      94             : 
      95             :     typelib_TypeDescription * m_pInvokMethodTD;
      96             :     typelib_TypeDescription * m_pSetValueTD;
      97             :     typelib_TypeDescription * m_pGetValueTD;
      98             :     typelib_TypeDescription * m_pAnySeqTD;
      99             :     typelib_TypeDescription * m_pShortSeqTD;
     100             :     typelib_TypeDescription * m_pConvertToTD;
     101             : 
     102             :     Mutex m_mutex;
     103             :     t_ptr_map m_receiver2adapters;
     104             : 
     105             :     FactoryImpl( Reference< XComponentContext > const & xContext );
     106             :     virtual ~FactoryImpl();
     107             : 
     108             :     // XServiceInfo
     109             :     virtual OUString SAL_CALL getImplementationName()
     110             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     111             :     virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName )
     112             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     113             :     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames()
     114             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     115             : 
     116             :     // XInvocationAdapterFactory
     117             :     virtual Reference< XInterface > SAL_CALL createAdapter(
     118             :         const Reference< script::XInvocation > & xReceiver, const Type & rType )
     119             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     120             :     // XInvocationAdapterFactory2
     121             :     virtual Reference< XInterface > SAL_CALL createAdapter(
     122             :         const Reference< script::XInvocation > & xReceiver,
     123             :         const Sequence< Type > & rTypes )
     124             :         throw (RuntimeException, std::exception) SAL_OVERRIDE;
     125             : };
     126             : struct AdapterImpl;
     127             : 
     128             : struct InterfaceAdapterImpl : public uno_Interface
     129             : {
     130             :     AdapterImpl *                           m_pAdapter;
     131             :     typelib_InterfaceTypeDescription *      m_pTypeDescr;
     132             : };
     133             : 
     134             : struct AdapterImpl
     135             : {
     136             :     oslInterlockedCount         m_nRef;
     137             :     FactoryImpl *               m_pFactory;
     138             :     void *                      m_key; // map key
     139             :     uno_Interface *             m_pReceiver; // XInvocation receiver
     140             : 
     141             :     sal_Int32                   m_nInterfaces;
     142             :     InterfaceAdapterImpl *      m_pInterfaces;
     143             : 
     144             :     // XInvocation calls
     145             :     void getValue(
     146             :         const typelib_TypeDescription * pMemberType,
     147             :         void * pReturn, uno_Any ** ppException );
     148             :     void setValue(
     149             :         const typelib_TypeDescription * pMemberType,
     150             :         void * pArgs[], uno_Any ** ppException );
     151             :     void invoke(
     152             :         const typelib_TypeDescription * pMemberType,
     153             :         void * pReturn, void * pArgs[], uno_Any ** ppException );
     154             : 
     155             :     bool coerce_assign(
     156             :         void * pDest, typelib_TypeDescriptionReference * pType,
     157             :         uno_Any * pSource, uno_Any * pExc );
     158             :     inline bool coerce_construct(
     159             :         void * pDest, typelib_TypeDescriptionReference * pType,
     160             :         uno_Any * pSource, uno_Any * pExc );
     161             : 
     162             :     inline void acquire();
     163             :     inline void release();
     164             :     inline ~AdapterImpl();
     165             :     inline AdapterImpl(
     166             :         void * key, Reference< script::XInvocation > const & xReceiver,
     167             :         const Sequence< Type > & rTypes,
     168             :         FactoryImpl * pFactory );
     169             : };
     170             : 
     171         196 : inline AdapterImpl::~AdapterImpl()
     172             : {
     173         608 :     for ( sal_Int32 nPos = m_nInterfaces; nPos--; )
     174             :     {
     175             :         ::typelib_typedescription_release(
     176         216 :             (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr );
     177             :     }
     178         196 :     delete [] m_pInterfaces;
     179             : 
     180         196 :     (*m_pReceiver->release)( m_pReceiver );
     181         196 :     m_pFactory->release();
     182         196 : }
     183             : 
     184        2130 : inline void AdapterImpl::acquire()
     185             : {
     186        2130 :     osl_atomic_increment( &m_nRef );
     187        2130 : }
     188             : 
     189        2260 : inline void AdapterImpl::release()
     190             : {
     191        2260 :     bool delete_this = false;
     192             :     {
     193        2260 :     MutexGuard guard( m_pFactory->m_mutex );
     194        2260 :     if (! osl_atomic_decrement( &m_nRef ))
     195             :     {
     196             :         t_ptr_map::iterator iFind(
     197         196 :             m_pFactory->m_receiver2adapters.find( m_key ) );
     198             :         OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind );
     199         196 :         t_ptr_set & adapter_set = iFind->second;
     200         196 :         if (adapter_set.erase( this ) != 1) {
     201             :             OSL_ASSERT( false );
     202             :         }
     203         196 :         if (adapter_set.empty())
     204             :         {
     205         196 :             m_pFactory->m_receiver2adapters.erase( iFind );
     206             :         }
     207         196 :         delete_this = true;
     208        2260 :     }
     209             :     }
     210        2260 :     if (delete_this)
     211         196 :         delete this;
     212        2260 : }
     213             : 
     214             : 
     215           0 : static inline void constructRuntimeException(
     216             :     uno_Any * pExc, const OUString & rMsg )
     217             : {
     218           0 :     RuntimeException exc( rMsg );
     219             :     // no conversion needed due to binary compatibility + no convertible type
     220             :     ::uno_type_any_construct(
     221           0 :         pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 );
     222           0 : }
     223             : 
     224             : 
     225        1610 : static inline bool type_equals(
     226             :     typelib_TypeDescriptionReference * pType1,
     227             :     typelib_TypeDescriptionReference * pType2 )
     228             : {
     229        3220 :     return (pType1 == pType2 ||
     230         812 :             (pType1->pTypeName->length == pType2->pTypeName->length &&
     231             :              0 == ::rtl_ustr_compare(
     232        1636 :                  pType1->pTypeName->buffer, pType2->pTypeName->buffer )));
     233             : }
     234             : 
     235             : 
     236           0 : bool AdapterImpl::coerce_assign(
     237             :     void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
     238             :     uno_Any * pOutExc )
     239             : {
     240           0 :     if (typelib_TypeClass_ANY == pType->eTypeClass)
     241             :     {
     242             :         ::uno_type_any_assign(
     243           0 :             (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 );
     244           0 :         return true;
     245             :     }
     246           0 :     if (::uno_type_assignData(
     247           0 :             pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 ))
     248             :     {
     249           0 :         return true;
     250             :     }
     251             :     else // try type converter
     252             :     {
     253             :         uno_Any ret;
     254             :         void * args[ 2 ];
     255           0 :         args[ 0 ] = pSource;
     256           0 :         args[ 1 ] = &pType;
     257             :         uno_Any exc;
     258           0 :         uno_Any * p_exc = &exc;
     259             : 
     260             :         // converTo()
     261             :         (*m_pFactory->m_pConverter->pDispatcher)(
     262             :             m_pFactory->m_pConverter,
     263           0 :             m_pFactory->m_pConvertToTD, &ret, args, &p_exc );
     264             : 
     265           0 :         if (p_exc) // exception occurred
     266             :         {
     267             :             OSL_ASSERT(
     268             :                 p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION );
     269           0 :             if (typelib_typedescriptionreference_isAssignableFrom( cppu::UnoType<RuntimeException>::get().getTypeLibType(),
     270           0 :                     p_exc->pType ))
     271             :             {
     272             :                 // is RuntimeException or derived: rethrow
     273             :                 uno_type_any_construct(
     274           0 :                     pOutExc, p_exc->pData, p_exc->pType, 0 );
     275             :             }
     276             :             else
     277             :             {
     278             :                 // set runtime exception
     279             :                 constructRuntimeException(
     280           0 :                     pOutExc, "type coercion failed: " +
     281             :                     reinterpret_cast< Exception const * >(
     282           0 :                         p_exc->pData )->Message );
     283             :             }
     284           0 :             ::uno_any_destruct( p_exc, 0 );
     285             :             // pOutExc constructed
     286           0 :             return false;
     287             :         }
     288             :         else
     289             :         {
     290             :             bool succ = (sal_False != ::uno_type_assignData(
     291           0 :                              pDest, pType, ret.pData, ret.pType, 0, 0, 0 ));
     292           0 :             ::uno_any_destruct( &ret, 0 );
     293             :             OSL_ENSURE(
     294             :                 succ, "### conversion succeeded, but assignment failed!?" );
     295           0 :             if (! succ)
     296             :             {
     297             :                 // set runtime exception
     298             :                 constructRuntimeException(
     299             :                     pOutExc,
     300             :                     "type coercion failed: "
     301           0 :                     "conversion succeeded, but assignment failed?!" );
     302             :             }
     303           0 :             return succ;
     304             :         }
     305             :     }
     306             : }
     307             : 
     308         198 : inline bool AdapterImpl::coerce_construct(
     309             :     void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource,
     310             :     uno_Any * pExc )
     311             : {
     312         198 :     if (typelib_TypeClass_ANY == pType->eTypeClass)
     313             :     {
     314           0 :         ::uno_type_copyData( pDest, pSource, pType, 0 );
     315           0 :         return true;
     316             :     }
     317         198 :     if (type_equals( pType, pSource->pType))
     318             :     {
     319         198 :         ::uno_type_copyData( pDest, pSource->pData, pType, 0 );
     320         198 :         return true;
     321             :     }
     322           0 :     ::uno_type_constructData( pDest, pType );
     323           0 :     return coerce_assign( pDest, pType, pSource, pExc );
     324             : }
     325             : 
     326             : 
     327           0 : static void handleInvokExc( uno_Any * pDest, uno_Any * pSource )
     328             : {
     329             :     OUString const & name =
     330           0 :         *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName );
     331             : 
     332           0 :     if ( name == "com.sun.star.reflection.InvocationTargetException" )
     333             :     {
     334             :         // unwrap invocation target exception
     335             :         uno_Any * target_exc =
     336             :             &reinterpret_cast< reflection::InvocationTargetException * >(
     337           0 :                 pSource->pData )->TargetException;
     338             :         ::uno_type_any_construct(
     339           0 :             pDest, target_exc->pData, target_exc->pType, 0 );
     340             :     }
     341             :     else // all other exceptions are wrapped to RuntimeException
     342             :     {
     343           0 :         if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass)
     344             :         {
     345             :             constructRuntimeException(
     346           0 :                 pDest, ((Exception const *)pSource->pData)->Message );
     347             :         }
     348             :         else
     349             :         {
     350             :             constructRuntimeException(
     351           0 :                 pDest, "no exception has been thrown via invocation?!" );
     352             :         }
     353             :     }
     354           0 : }
     355             : 
     356           0 : void AdapterImpl::getValue(
     357             :     const typelib_TypeDescription * pMemberType,
     358             :     void * pReturn, uno_Any ** ppException )
     359             : {
     360             :     uno_Any aInvokRet;
     361             :     void * pInvokArgs[1];
     362             :     pInvokArgs[0] =
     363           0 :         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
     364             :     uno_Any aInvokExc;
     365           0 :     uno_Any * pInvokExc = &aInvokExc;
     366             : 
     367             :     // getValue()
     368             :     (*m_pReceiver->pDispatcher)(
     369             :         m_pReceiver, m_pFactory->m_pGetValueTD,
     370           0 :         &aInvokRet, pInvokArgs, &pInvokExc );
     371             : 
     372           0 :     if (pInvokExc) // getValue() call exception
     373             :     {
     374           0 :         handleInvokExc( *ppException, pInvokExc );
     375           0 :         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
     376             :     }
     377             :     else // invocation call succeeded
     378             :     {
     379           0 :         if (coerce_construct(
     380             :                 pReturn,
     381             :                 ((typelib_InterfaceAttributeTypeDescription *)
     382             :                  pMemberType)->pAttributeTypeRef,
     383           0 :                 &aInvokRet, *ppException ))
     384             :         {
     385           0 :             *ppException = 0; // no exceptions be thrown
     386             :         }
     387           0 :         ::uno_any_destruct( &aInvokRet, 0 );
     388             :     }
     389           0 : }
     390             : 
     391           0 : void AdapterImpl::setValue(
     392             :     const typelib_TypeDescription * pMemberType,
     393             :     void * pArgs[], uno_Any ** ppException )
     394             : {
     395             :     uno_Any aInvokVal;
     396             :     ::uno_type_any_construct(
     397             :         &aInvokVal, pArgs[0],
     398             :         ((typelib_InterfaceAttributeTypeDescription *)
     399           0 :          pMemberType)->pAttributeTypeRef, 0 );
     400             : 
     401             :     void * pInvokArgs[2];
     402             :     pInvokArgs[0] =
     403           0 :         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
     404           0 :     pInvokArgs[1] = &aInvokVal;
     405             :     uno_Any aInvokExc;
     406           0 :     uno_Any * pInvokExc = &aInvokExc;
     407             : 
     408             :     // setValue()
     409             :     (*m_pReceiver->pDispatcher)(
     410           0 :         m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc );
     411             : 
     412           0 :     if (pInvokExc) // setValue() call exception
     413             :     {
     414           0 :         handleInvokExc( *ppException, pInvokExc );
     415           0 :         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
     416             :     }
     417             :     else // invocation call succeeded
     418             :     {
     419           0 :         *ppException = 0; // no exceptions be thrown
     420             :     }
     421             : 
     422           0 :     ::uno_any_destruct( &aInvokVal, 0 ); // cleanup
     423           0 : }
     424             : 
     425         198 : void AdapterImpl::invoke(
     426             :     const typelib_TypeDescription * pMemberType,
     427             :     void * pReturn, void * pArgs[], uno_Any ** ppException )
     428             : {
     429             :     sal_Int32 nParams =
     430         198 :         ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams;
     431             :     typelib_MethodParameter * pFormalParams =
     432         198 :         ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams;
     433             : 
     434             :     // in params
     435         198 :     uno_Sequence * pInParamsSeq = 0;
     436             :     ::uno_sequence_construct(
     437         198 :         &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 );
     438         198 :     uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements;
     439         198 :     sal_Int32 nOutParams = 0;
     440             :     sal_Int32 nPos;
     441         614 :     for ( nPos = nParams; nPos--; )
     442             :     {
     443         218 :         typelib_MethodParameter const & rParam = pFormalParams[nPos];
     444         218 :         if (rParam.bIn) // is in/inout param
     445             :         {
     446             :             ::uno_type_any_assign(
     447         218 :                 &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 );
     448             :         }
     449             :         // else: pure out is empty any
     450             : 
     451         218 :         if (rParam.bOut)
     452           0 :             ++nOutParams;
     453             :     }
     454             : 
     455             :     // out params, out indices
     456             :     uno_Sequence * pOutIndices;
     457             :     uno_Sequence * pOutParams;
     458             :     // return value
     459             :     uno_Any aInvokRet;
     460             :     // perform call
     461             :     void * pInvokArgs[4];
     462             :     pInvokArgs[0] =
     463         198 :         &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName;
     464         198 :     pInvokArgs[1] = &pInParamsSeq;
     465         198 :     pInvokArgs[2] = &pOutIndices;
     466         198 :     pInvokArgs[3] = &pOutParams;
     467             :     uno_Any aInvokExc;
     468         198 :     uno_Any * pInvokExc = &aInvokExc;
     469             : 
     470             :     // invoke() call
     471             :     (*m_pReceiver->pDispatcher)(
     472             :         m_pReceiver, m_pFactory->m_pInvokMethodTD,
     473         198 :         &aInvokRet, pInvokArgs, &pInvokExc );
     474             : 
     475         198 :     if (pInvokExc)
     476             :     {
     477           0 :         handleInvokExc( *ppException, pInvokExc );
     478           0 :         ::uno_any_destruct( pInvokExc, 0 ); // cleanup
     479             :     }
     480             :     else // no invocation exception
     481             :     {
     482             :         // write changed out params
     483             :         OSL_ENSURE(
     484             :             pOutParams->nElements == nOutParams &&
     485             :             pOutIndices->nElements == nOutParams,
     486             :             "### out params lens differ!" );
     487         396 :         if (pOutParams->nElements == nOutParams &&
     488         198 :             pOutIndices->nElements == nOutParams)
     489             :         {
     490         198 :             sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements;
     491         198 :             uno_Any * pOut       = (uno_Any *)pOutParams->elements;
     492         198 :             for ( nPos = 0; nPos < nOutParams; ++nPos )
     493             :             {
     494           0 :                 sal_Int32 nIndex = pIndices[nPos];
     495             :                 OSL_ENSURE( nIndex < nParams, "### illegal index!" );
     496           0 :                 typelib_MethodParameter const & rParam = pFormalParams[nIndex];
     497             :                 bool succ;
     498           0 :                 if (rParam.bIn) // is in/inout param
     499             :                 {
     500             :                     succ = coerce_assign(
     501           0 :                         pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
     502           0 :                         *ppException );
     503             :                 }
     504             :                 else // pure out
     505             :                 {
     506             :                     succ = coerce_construct(
     507           0 :                         pArgs[nIndex], rParam.pTypeRef, &pOut[nPos],
     508           0 :                         *ppException );
     509             :                 }
     510           0 :                 if (! succ) // cleanup of out params
     511             :                 {
     512           0 :                     for ( sal_Int32 n = 0; n <= nPos; ++n )
     513             :                     {
     514           0 :                         sal_Int32 nIndex2 = pIndices[n];
     515             :                         OSL_ENSURE( nIndex2 < nParams, "### illegal index!" );
     516             :                         typelib_MethodParameter const & rParam2 =
     517           0 :                             pFormalParams[nIndex2];
     518           0 :                         if (! rParam2.bIn) // is pure out param
     519             :                         {
     520             :                             ::uno_type_destructData(
     521           0 :                                 pArgs[nIndex2], rParam2.pTypeRef, 0 );
     522             :                         }
     523             :                     }
     524             :                 }
     525             :             }
     526         198 :             if (nPos == pOutIndices->nElements)
     527             :             {
     528             :                 // out param copy ok; write return value
     529         198 :                 if (coerce_construct(
     530             :                         pReturn,
     531             :                         ((typelib_InterfaceMethodTypeDescription *)
     532             :                          pMemberType)->pReturnTypeRef,
     533         198 :                         &aInvokRet, *ppException ))
     534             :                 {
     535         198 :                     *ppException = 0; // no exception
     536             :                 }
     537         198 :             }
     538             :         }
     539             :         else
     540             :         {
     541             :             // set runtime exception
     542             :             constructRuntimeException(
     543             :                 *ppException,
     544           0 :                 "out params lengths differ after invocation call!" );
     545             :         }
     546             :         // cleanup invok out params
     547         198 :         ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 );
     548         198 :         ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 );
     549             :         // cleanup invok return value
     550         198 :         ::uno_any_destruct( &aInvokRet, 0 );
     551             :     }
     552             :     // cleanup constructed in params
     553         198 :     ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 );
     554         198 : }
     555             : 
     556             : extern "C"
     557             : {
     558             : 
     559        2130 : static void SAL_CALL adapter_acquire( uno_Interface * pUnoI )
     560             : {
     561        2130 :     static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire();
     562        2130 : }
     563             : 
     564        2046 : static void SAL_CALL adapter_release( uno_Interface * pUnoI )
     565             : {
     566        2046 :     static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release();
     567        2046 : }
     568             : 
     569         874 : static void SAL_CALL adapter_dispatch(
     570             :     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType,
     571             :     void * pReturn, void * pArgs[], uno_Any ** ppException )
     572             : {
     573             :     // query to emulated interface
     574         874 :     switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition)
     575             :     {
     576             :     case 0: // queryInterface()
     577             :     {
     578             :         AdapterImpl * that =
     579         676 :             static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
     580         676 :         *ppException = 0; // no exc
     581             :         typelib_TypeDescriptionReference * pDemanded =
     582         676 :             *(typelib_TypeDescriptionReference **)pArgs[0];
     583             :         // pInterfaces[0] is XInterface
     584         734 :         for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos )
     585             :         {
     586             :             typelib_InterfaceTypeDescription * pTD =
     587         684 :                 that->m_pInterfaces[nPos].m_pTypeDescr;
     588        2154 :             while (pTD)
     589             :             {
     590        1412 :                 if (type_equals(
     591        1412 :                         ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded ))
     592             :                 {
     593         626 :                     uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos];
     594             :                     ::uno_any_construct(
     595             :                         (uno_Any *)pReturn, &pUnoI2,
     596         626 :                         (typelib_TypeDescription *)pTD, 0 );
     597        1500 :                     return;
     598             :                 }
     599         786 :                 pTD = pTD->pBaseTypeDescription;
     600             :             }
     601             :         }
     602          50 :         ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear()
     603          50 :         break;
     604             :     }
     605             :     case 1: // acquire()
     606           0 :         *ppException = 0; // no exc
     607           0 :         adapter_acquire( pUnoI );
     608           0 :         break;
     609             :     case 2: // release()
     610           0 :         *ppException = 0; // no exc
     611           0 :         adapter_release( pUnoI );
     612           0 :         break;
     613             : 
     614             :     default:
     615             :     {
     616             :         AdapterImpl * that =
     617         198 :             static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter;
     618         198 :         if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD)
     619             :         {
     620         198 :             that->invoke( pMemberType, pReturn, pArgs, ppException );
     621             :         }
     622             :         else // attribute
     623             :         {
     624           0 :             if (pReturn)
     625           0 :                 that->getValue( pMemberType, pReturn, ppException );
     626             :             else
     627           0 :                 that->setValue( pMemberType, pArgs, ppException );
     628             :         }
     629             :     }
     630             :     }
     631             : }
     632             : }
     633             : 
     634         214 : AdapterImpl::AdapterImpl(
     635             :     void * key, Reference< script::XInvocation > const & xReceiver,
     636             :     const Sequence< Type > & rTypes,
     637             :     FactoryImpl * pFactory )
     638             :         : m_nRef( 1 ),
     639             :           m_pFactory( pFactory ),
     640         214 :           m_key( key )
     641             : {
     642             :     // init adapters
     643         214 :     m_nInterfaces = rTypes.getLength();
     644         214 :     m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ];
     645         214 :     const Type * pTypes = rTypes.getConstArray();
     646         662 :     for ( sal_Int32 nPos = rTypes.getLength(); nPos--; )
     647             :     {
     648         234 :         InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos];
     649         234 :         pInterface->acquire = adapter_acquire;
     650         234 :         pInterface->release = adapter_release;
     651         234 :         pInterface->pDispatcher = adapter_dispatch;
     652         234 :         pInterface->m_pAdapter = this;
     653         234 :         pInterface->m_pTypeDescr = 0;
     654             :         pTypes[nPos].getDescription(
     655         234 :             (typelib_TypeDescription **)&pInterface->m_pTypeDescr );
     656             :         OSL_ASSERT( pInterface->m_pTypeDescr );
     657         234 :         if (! pInterface->m_pTypeDescr)
     658             :         {
     659           0 :             for ( sal_Int32 n = 0; n < nPos; ++n )
     660             :             {
     661             :                 ::typelib_typedescription_release(
     662             :                     (typelib_TypeDescription *)
     663           0 :                     m_pInterfaces[ n ].m_pTypeDescr );
     664             :             }
     665           0 :             delete [] m_pInterfaces;
     666             :             throw RuntimeException(
     667           0 :                 "cannot retrieve all interface type infos!" );
     668             :         }
     669             :     }
     670             : 
     671             :     // map receiver
     672             :     m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface(
     673         214 :         xReceiver.get(), ::getCppuType( &xReceiver ) );
     674             :     OSL_ASSERT( 0 != m_pReceiver );
     675         214 :     if (! m_pReceiver)
     676             :     {
     677           0 :         throw RuntimeException( "cannot map receiver!" );
     678             :     }
     679             : 
     680         214 :     m_pFactory->acquire();
     681         214 : }
     682             : 
     683             : 
     684          14 : FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext )
     685             :     : m_pInvokMethodTD( 0 ),
     686             :       m_pSetValueTD( 0 ),
     687             :       m_pGetValueTD( 0 ),
     688             :       m_pAnySeqTD( 0 ),
     689             :       m_pShortSeqTD( 0 ),
     690          14 :       m_pConvertToTD( 0 )
     691             : {
     692             :     // C++/UNO bridge
     693          14 :     OUString aCppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
     694          28 :     OUString aUnoEnvTypeName = UNO_LB_UNO;
     695          14 :     m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName );
     696          14 :     m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName );
     697             :     OSL_ENSURE(
     698             :         m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" );
     699             : 
     700             :     // type converter
     701             :     Reference< script::XTypeConverter > xConverter(
     702          28 :         xContext->getServiceManager()->createInstanceWithContext(
     703             :             OUString("com.sun.star.script.Converter"),
     704          14 :             xContext ),
     705          28 :         UNO_QUERY_THROW );
     706             :     m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface(
     707          14 :         xConverter.get(), ::getCppuType( &xConverter ) );
     708             :     OSL_ASSERT( 0 != m_pConverter );
     709             : 
     710             :     // some type info:
     711             :     // sequence< any >
     712          14 :     Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 );
     713          14 :     rAnySeqType.getDescription( &m_pAnySeqTD );
     714             :     // sequence< short >
     715             :     const Type & rShortSeqType =
     716          14 :         ::getCppuType( (const Sequence< sal_Int16 > *)0 );
     717          14 :     rShortSeqType.getDescription( &m_pShortSeqTD );
     718             :     // script.XInvocation
     719          14 :     typelib_TypeDescription * pTD = 0;
     720          14 :     const Type & rInvType = cppu::UnoType<script::XInvocation>::get();
     721          14 :     TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() );
     722             :     typelib_InterfaceTypeDescription * pITD;
     723          14 :     pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
     724          14 :     if( ! pITD->aBase.bComplete )
     725          14 :         typelib_typedescription_complete( &pTD );
     726             :     ::typelib_typedescriptionreference_getDescription(
     727          14 :         &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke()
     728             :     ::typelib_typedescriptionreference_getDescription(
     729          14 :         &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue()
     730             :     ::typelib_typedescriptionreference_getDescription(
     731          14 :         &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue()
     732             :     // script.XTypeConverter
     733             :     const Type & rTCType =
     734          14 :         cppu::UnoType<script::XTypeConverter>::get();
     735          14 :     TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() );
     736          14 :     pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD);
     737             :     ::typelib_typedescriptionreference_getDescription(
     738          14 :         &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo()
     739          14 :     TYPELIB_DANGER_RELEASE( pTD );
     740             : 
     741          28 :     if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD ||
     742          28 :         !m_pConvertToTD ||
     743          28 :         !m_pAnySeqTD || !m_pShortSeqTD)
     744             :     {
     745           0 :         throw RuntimeException( "missing type descriptions!" );
     746          14 :     }
     747          14 : }
     748             : 
     749          12 : FactoryImpl::~FactoryImpl()
     750             : {
     751           4 :     ::typelib_typedescription_release( m_pInvokMethodTD );
     752           4 :     ::typelib_typedescription_release( m_pSetValueTD );
     753           4 :     ::typelib_typedescription_release( m_pGetValueTD );
     754           4 :     ::typelib_typedescription_release( m_pAnySeqTD );
     755           4 :     ::typelib_typedescription_release( m_pShortSeqTD );
     756           4 :     ::typelib_typedescription_release( m_pConvertToTD );
     757             : 
     758           4 :     (*m_pConverter->release)( m_pConverter );
     759             : 
     760             : #if OSL_DEBUG_LEVEL > 1
     761             :     OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" );
     762             : #endif
     763           8 : }
     764             : 
     765             : 
     766         428 : static inline AdapterImpl * lookup_adapter(
     767             :     t_ptr_set ** pp_adapter_set,
     768             :     t_ptr_map & map, void * key, Sequence< Type > const & rTypes )
     769             : {
     770         428 :     t_ptr_set & adapters_set = map[ key ];
     771         428 :     *pp_adapter_set = &adapters_set;
     772         428 :     if (adapters_set.empty())
     773         428 :         return 0; // shortcut
     774             :     // find matching adapter
     775           0 :     Type const * pTypes = rTypes.getConstArray();
     776           0 :     sal_Int32 nTypes = rTypes.getLength();
     777           0 :     t_ptr_set::const_iterator iPos( adapters_set.begin() );
     778           0 :     t_ptr_set::const_iterator const iEnd( adapters_set.end() );
     779           0 :     while (iEnd != iPos)
     780             :     {
     781           0 :         AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos );
     782             :         // iterate thru all types if that is a matching adapter
     783             :         sal_Int32 nPosTypes;
     784           0 :         for ( nPosTypes = nTypes; nPosTypes--; )
     785             :         {
     786           0 :             Type const & rType = pTypes[ nPosTypes ];
     787             :             // find in adapter's type list
     788             :             sal_Int32 nPos;
     789           0 :             for ( nPos = that->m_nInterfaces; nPos--; )
     790             :             {
     791           0 :                 if (::typelib_typedescriptionreference_isAssignableFrom(
     792             :                         rType.getTypeLibType(),
     793             :                         ((typelib_TypeDescription *)that->
     794           0 :                          m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef ))
     795             :                 {
     796             :                     // found
     797           0 :                     break;
     798             :                 }
     799             :             }
     800           0 :             if (nPos < 0) // type not found => next adapter
     801           0 :                 break;
     802             :         }
     803           0 :         if (nPosTypes < 0) // all types found
     804           0 :             return that;
     805           0 :         ++iPos;
     806             :     }
     807           0 :     return 0;
     808             : }
     809             : 
     810             : // XInvocationAdapterFactory2 impl
     811             : 
     812         214 : Reference< XInterface > FactoryImpl::createAdapter(
     813             :     const Reference< script::XInvocation > & xReceiver,
     814             :     const Sequence< Type > & rTypes )
     815             :     throw (RuntimeException, std::exception)
     816             : {
     817         214 :     Reference< XInterface > xRet;
     818         214 :     if (xReceiver.is() && rTypes.getLength())
     819             :     {
     820             :         t_ptr_set * adapter_set;
     821             :         AdapterImpl * that;
     822         214 :         Reference< XInterface > xKey( xReceiver, UNO_QUERY );
     823             :         {
     824         214 :         ClearableMutexGuard guard( m_mutex );
     825             :         that = lookup_adapter(
     826         214 :             &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
     827         214 :         if (0 == that) // no entry
     828             :         {
     829         214 :             guard.clear();
     830             :             // create adapter; already acquired: m_nRef == 1
     831             :             AdapterImpl * pNew =
     832         214 :                 new AdapterImpl( xKey.get(), xReceiver, rTypes, this );
     833             :             // lookup again
     834         214 :             ClearableMutexGuard guard2( m_mutex );
     835             :             that = lookup_adapter(
     836         214 :                 &adapter_set, m_receiver2adapters, xKey.get(), rTypes );
     837         214 :             if (0 == that) // again no entry
     838             :             {
     839         214 :                 pair< t_ptr_set::iterator, bool > i(adapter_set->insert(pNew));
     840             :                 SAL_WARN_IF(
     841             :                     !i.second, "stoc",
     842             :                     "set already contains " << *(i.first) << " != " << pNew);
     843         214 :                 that = pNew;
     844             :             }
     845             :             else
     846             :             {
     847           0 :                 that->acquire();
     848           0 :                 guard2.clear();
     849           0 :                 delete pNew; // has never been inserted
     850         214 :             }
     851             :         }
     852             :         else // found adapter
     853             :         {
     854           0 :             that->acquire();
     855         214 :         }
     856             :         }
     857             :         // map one interface to C++
     858         214 :         uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ];
     859             :         m_aUno2Cpp.mapInterface(
     860         214 :             (void **)&xRet, pUnoI, ::getCppuType( &xRet ) );
     861         214 :         that->release();
     862             :         OSL_ASSERT( xRet.is() );
     863         214 :         if (! xRet.is())
     864             :         {
     865           0 :             throw RuntimeException( "mapping UNO to C++ failed!" );
     866         214 :         }
     867             :     }
     868         214 :     return xRet;
     869             : }
     870             : // XInvocationAdapterFactory impl
     871             : 
     872           0 : Reference< XInterface > FactoryImpl::createAdapter(
     873             :     const Reference< script::XInvocation > & xReceiver, const Type & rType )
     874             :     throw (RuntimeException, std::exception)
     875             : {
     876           0 :     return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) );
     877             : }
     878             : 
     879             : // XServiceInfo
     880             : 
     881           0 : OUString FactoryImpl::getImplementationName()
     882             :     throw (RuntimeException, std::exception)
     883             : {
     884           0 :     return invadp_getImplementationName();
     885             : }
     886             : 
     887           0 : sal_Bool FactoryImpl::supportsService( const OUString & rServiceName )
     888             :     throw (RuntimeException, std::exception)
     889             : {
     890           0 :     return cppu::supportsService(this, rServiceName);
     891             : }
     892             : 
     893           0 : Sequence< OUString > FactoryImpl::getSupportedServiceNames()
     894             :     throw (RuntimeException, std::exception)
     895             : {
     896           0 :     return invadp_getSupportedServiceNames();
     897             : }
     898             : 
     899             : 
     900          14 : static Reference< XInterface > SAL_CALL FactoryImpl_create(
     901             :     const Reference< XComponentContext > & xContext )
     902             :     throw (Exception)
     903             : {
     904          14 :     return (::cppu::OWeakObject *)new FactoryImpl( xContext );
     905             : }
     906             : 
     907             : }
     908             : 
     909             : 
     910             : 
     911             : 
     912             : 
     913             : 
     914             : static const struct ::cppu::ImplementationEntry g_entries[] =
     915             : {
     916             :     {
     917             :         ::stoc_invadp::FactoryImpl_create,
     918             :         ::stoc_invadp::invadp_getImplementationName,
     919             :         ::stoc_invadp::invadp_getSupportedServiceNames,
     920             :         ::cppu::createOneInstanceComponentFactory,
     921             :         0, 0
     922             :     },
     923             :     { 0, 0, 0, 0, 0, 0 }
     924             : };
     925             : 
     926          14 : extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL invocadapt_component_getFactory(
     927             :     const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
     928             : {
     929             :     return ::cppu::component_getFactoryHelper(
     930          14 :         pImplName, pServiceManager, pRegistryKey , g_entries );
     931             : }
     932             : 
     933             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10