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

Generated by: LCOV version 1.11