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

Generated by: LCOV version 1.10