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

Generated by: LCOV version 1.10