LCOV - code coverage report
Current view: top level - cppu/source/helper/purpenv - helper_purpenv_Proxy.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 195 0.0 %
Date: 2014-04-14 Functions: 0 18 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 "Proxy.hxx"
      22             : 
      23             : #include "sal/alloca.h"
      24             : #include "uno/dispatcher.h"
      25             : #include "typelib/typedescription.hxx"
      26             : #include "cppu/EnvDcp.hxx"
      27             : 
      28             : 
      29             : //#define LOG_LIFECYCLE_Proxy
      30             : #ifdef LOG_LIFECYCLE_Proxy
      31             : #  include <iostream>
      32             : #  define LOG_LIFECYCLE_Proxy_emit(x) x
      33             : 
      34             : #else
      35             : #  define LOG_LIFECYCLE_Proxy_emit(x)
      36             : 
      37             : #endif
      38             : 
      39             : 
      40             : using namespace com::sun::star;
      41             : 
      42             : 
      43           0 : static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
      44             :     SAL_THROW(())
      45             : {
      46           0 :     switch (pTypeDescr->eTypeClass)
      47             :     {
      48             : //      case typelib_TypeClass_TYPEDEF:
      49             :     case typelib_TypeClass_SEQUENCE:
      50             :     {
      51           0 :         switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass)
      52             :         {
      53             :         case typelib_TypeClass_INTERFACE:
      54             :         case typelib_TypeClass_ANY: // might relate to interface
      55           0 :             return true;
      56             :         case typelib_TypeClass_SEQUENCE:
      57             :         case typelib_TypeClass_STRUCT:
      58             :         case typelib_TypeClass_EXCEPTION:
      59             :         {
      60           0 :             typelib_TypeDescription * pTD = 0;
      61           0 :             TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
      62           0 :             bool bRel = relatesToInterface( pTD );
      63           0 :             TYPELIB_DANGER_RELEASE( pTD );
      64           0 :             return bRel;
      65             :         }
      66             :         default:
      67             :             ;
      68             :         }
      69           0 :         return false;
      70             :     }
      71             :     case typelib_TypeClass_STRUCT:
      72             :     case typelib_TypeClass_EXCEPTION:
      73             :     {
      74             :         // ...optimized... to avoid getDescription() calls!
      75           0 :         typelib_CompoundTypeDescription * pComp    = (typelib_CompoundTypeDescription *)pTypeDescr;
      76           0 :         typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
      77           0 :         for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
      78             :         {
      79           0 :             switch (pTypes[nPos]->eTypeClass)
      80             :             {
      81             :             case typelib_TypeClass_INTERFACE:
      82             :             case typelib_TypeClass_ANY: // might relate to interface
      83           0 :                 return true;
      84             : //              case typelib_TypeClass_TYPEDEF:
      85             :             case typelib_TypeClass_SEQUENCE:
      86             :             case typelib_TypeClass_STRUCT:
      87             :             case typelib_TypeClass_EXCEPTION:
      88             :             {
      89           0 :                 typelib_TypeDescription * pTD = 0;
      90           0 :                 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] );
      91           0 :                 bool bRel = relatesToInterface( pTD );
      92           0 :                 TYPELIB_DANGER_RELEASE( pTD );
      93           0 :                 if (bRel)
      94           0 :                     return true;
      95             :             }
      96             :             default:
      97             :                 ;
      98             :             }
      99             :         }
     100           0 :         if (pComp->pBaseTypeDescription)
     101           0 :             return relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription );
     102           0 :         break;
     103             :     }
     104             :     case typelib_TypeClass_ANY: // might relate to interface
     105             :     case typelib_TypeClass_INTERFACE:
     106           0 :         return true;
     107             : 
     108             :     default:
     109             :         ;
     110             :     }
     111           0 :     return false;
     112             : }
     113             : 
     114           0 : extern "C" { static void SAL_CALL s_Proxy_dispatch(
     115             :     uno_Interface                 * pUnoI,
     116             :     typelib_TypeDescription const * pMemberType,
     117             :     void                          * pReturn,
     118             :     void                          * pArgs[],
     119             :     uno_Any                      ** ppException)
     120             :     SAL_THROW_EXTERN_C()
     121             : {
     122           0 :     Proxy * pThis = static_cast<Proxy *>(pUnoI);
     123             : 
     124             :     typelib_MethodParameter            param;
     125           0 :     sal_Int32                          nParams = 0;
     126           0 :     typelib_MethodParameter          * pParams = 0;
     127           0 :     typelib_TypeDescriptionReference * pReturnTypeRef = 0;
     128             :     // sal_Int32                          nOutParams = 0;
     129             : 
     130           0 :     switch (pMemberType->eTypeClass)
     131             :     {
     132             :     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
     133           0 :         if (pReturn)
     134             :         {
     135             :             pReturnTypeRef =
     136             :                 ((typelib_InterfaceAttributeTypeDescription *)
     137           0 :                  pMemberType)->pAttributeTypeRef;
     138           0 :             nParams = 0;
     139           0 :             pParams = NULL;
     140             :         }
     141             :         else
     142             :         {
     143             :             param.pTypeRef = ((typelib_InterfaceAttributeTypeDescription *)
     144           0 :                               pMemberType)->pAttributeTypeRef;
     145           0 :             param.bIn = sal_True;
     146           0 :             param.bOut = sal_False;
     147           0 :             nParams = 1;
     148           0 :             pParams = &param;
     149             :         }
     150           0 :         break;
     151             :     case typelib_TypeClass_INTERFACE_METHOD:
     152             :     {
     153             :         typelib_InterfaceMethodTypeDescription * method_td =
     154           0 :             (typelib_InterfaceMethodTypeDescription *) pMemberType;
     155           0 :         pReturnTypeRef = method_td->pReturnTypeRef;
     156           0 :         nParams = method_td->nParams;
     157           0 :         pParams = method_td->pParams;
     158           0 :         break;
     159             :     }
     160             :     default:
     161             :         OSL_FAIL( "### illegal member typeclass!" );
     162           0 :         abort();
     163             :     }
     164             : 
     165             :     pThis->dispatch( pReturnTypeRef,
     166             :                      pParams,
     167             :                      nParams,
     168             :                      pMemberType,
     169             :                      pReturn,
     170             :                      pArgs,
     171           0 :                      ppException );
     172           0 : }}
     173             : 
     174           0 : extern "C" void SAL_CALL Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
     175             : {
     176           0 :     Proxy * pThis = static_cast<Proxy * >(reinterpret_cast<uno_Interface *>(pProxy));
     177           0 :     delete pThis;
     178           0 : }
     179             : 
     180             : extern "C" {
     181           0 : static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
     182             : {
     183           0 :     Proxy * pProxy = static_cast<Proxy *>(pUnoI);
     184           0 :     pProxy->acquire();
     185           0 : }
     186             : 
     187           0 : static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
     188             : {
     189           0 :     Proxy * pProxy = static_cast<Proxy *>(pUnoI);
     190           0 :     pProxy->release();
     191           0 : }
     192             : 
     193           0 : static void s_acquireAndRegister_v(va_list * pParam)
     194             : {
     195           0 :     uno_Interface                    * pUnoI      = va_arg(*pParam, uno_Interface *);
     196           0 :     rtl_uString                      * pOid       = va_arg(*pParam, rtl_uString *);
     197           0 :     typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
     198           0 :     uno_ExtEnvironment               * pEnv       = va_arg(*pParam, uno_ExtEnvironment *);
     199             : 
     200           0 :     pUnoI->acquire(pUnoI);
     201           0 :      pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
     202           0 : }
     203             : }
     204             : 
     205           0 : Proxy::Proxy(uno::Mapping                  const & to_from,
     206             :              uno_Environment                     * pTo,
     207             :              uno_Environment                     * pFrom,
     208             :              uno_Interface                       * pUnoI,
     209             :              typelib_InterfaceTypeDescription    * pTypeDescr,
     210             :              rtl::OUString                 const & rOId,
     211             :              cppu::helper::purpenv::ProbeFun     * probeFun,
     212             :              void                                * pProbeContext
     213             : )
     214             :     SAL_THROW(())
     215             :         : m_nRef         (1),
     216             :           m_from         (pFrom),
     217             :           m_to           (pTo),
     218             :           m_from_to      (pFrom, pTo),
     219             :           m_to_from      (to_from),
     220             :           m_pUnoI        (pUnoI),
     221             :           m_pTypeDescr   (pTypeDescr),
     222             :           m_aOId         (rOId),
     223             :           m_probeFun     (probeFun),
     224           0 :           m_pProbeContext(pProbeContext)
     225             : {
     226             :     LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
     227             : 
     228           0 :     typelib_typedescription_acquire((typelib_TypeDescription *)m_pTypeDescr);
     229           0 :     if (!((typelib_TypeDescription *)m_pTypeDescr)->bComplete)
     230           0 :         typelib_typedescription_complete((typelib_TypeDescription **)&m_pTypeDescr);
     231             : 
     232             :     OSL_ENSURE(((typelib_TypeDescription *)m_pTypeDescr)->bComplete, "### type is incomplete!");
     233             : 
     234           0 :     uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
     235             : 
     236             :     // uno_Interface
     237           0 :     uno_Interface::acquire     = s_Proxy_acquire;
     238           0 :     uno_Interface::release     = s_Proxy_release;
     239           0 :     uno_Interface::pDispatcher = s_Proxy_dispatch;
     240           0 : }
     241             : 
     242           0 : extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
     243             : {
     244           0 :     uno_ExtEnvironment * pEnv  = va_arg(*pParam, uno_ExtEnvironment *);
     245           0 :     uno_Interface      * pUnoI = va_arg(*pParam, uno_Interface *);
     246             : 
     247           0 :     pEnv->revokeInterface(pEnv, reinterpret_cast<void *>(pUnoI));
     248           0 :     pUnoI->release(pUnoI);
     249           0 : }}
     250             : 
     251           0 : Proxy::~Proxy()
     252             : {
     253             :     LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
     254             : 
     255           0 :     uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
     256             : 
     257           0 :     typelib_typedescription_release((typelib_TypeDescription *)m_pTypeDescr);
     258           0 : }
     259             : 
     260           0 : static uno::TypeDescription getAcquireMethod(void)
     261             : {
     262             :     typelib_TypeDescriptionReference * type_XInterface =
     263           0 :         * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
     264             : 
     265           0 :     typelib_TypeDescription * pTXInterfaceDescr = 0;
     266           0 :     TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
     267             :     uno::TypeDescription acquire(
     268             :         reinterpret_cast< typelib_InterfaceTypeDescription * >(
     269           0 :             pTXInterfaceDescr)->ppAllMembers[1]);
     270           0 :     TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
     271             : 
     272           0 :     return acquire;
     273             : }
     274             : 
     275           0 : static uno::TypeDescription getReleaseMethod(void)
     276             : {
     277             :     typelib_TypeDescriptionReference * type_XInterface =
     278           0 :         * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
     279             : 
     280           0 :     typelib_TypeDescription * pTXInterfaceDescr = 0;
     281           0 :     TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
     282             :     uno::TypeDescription release(
     283             :         reinterpret_cast< typelib_InterfaceTypeDescription * >(
     284           0 :             pTXInterfaceDescr)->ppAllMembers[2]);
     285           0 :     TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
     286             : 
     287           0 :     return release;
     288             : }
     289             : 
     290           0 : static uno::TypeDescription s_acquireMethod(getAcquireMethod());
     291           0 : static uno::TypeDescription s_releaseMethod(getReleaseMethod());
     292             : 
     293           0 : void Proxy::acquire(void)
     294             : {
     295           0 :     if (m_probeFun)
     296             :         m_probeFun(true,
     297             :                    this,
     298             :                    m_pProbeContext,
     299           0 :                    *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
     300             :                    NULL,
     301             :                    0,
     302           0 :                    s_acquireMethod.get(),
     303             :                    NULL,
     304             :                    NULL,
     305           0 :                    NULL);
     306             : 
     307           0 :     if (osl_atomic_increment(&m_nRef) == 1)
     308             :     {
     309             :         // rebirth of proxy zombie
     310           0 :         void * pThis = this;
     311           0 :         m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv,
     312             :                                                       &pThis,
     313             :                                                       Proxy_free,
     314             :                                                       m_aOId.pData,
     315           0 :                                                       m_pTypeDescr);
     316             :         OSL_ASSERT(pThis == this);
     317             :     }
     318             : 
     319           0 :     if (m_probeFun)
     320             :         m_probeFun(false,
     321             :                    this,
     322             :                    m_pProbeContext,
     323           0 :                    *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
     324             :                    NULL,
     325             :                    0,
     326           0 :                    s_acquireMethod.get(),
     327             :                    NULL,
     328             :                    NULL,
     329           0 :                    NULL);
     330             : 
     331           0 : }
     332             : 
     333           0 : void Proxy::release(void)
     334             : {
     335           0 :     cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
     336           0 :     void                            * pProbeContext = m_pProbeContext;
     337             : 
     338           0 :     if (m_probeFun)
     339             :         m_probeFun(true,
     340             :                    this,
     341             :                    m_pProbeContext,
     342           0 :                    *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
     343             :                    NULL,
     344             :                    0,
     345           0 :                    s_releaseMethod.get(),
     346             :                    NULL,
     347             :                    NULL,
     348           0 :                    NULL);
     349             : 
     350           0 :     if (osl_atomic_decrement(&m_nRef) == 0)
     351           0 :         m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
     352             : 
     353           0 :     if (probeFun)
     354             :         probeFun(false,
     355             :                  this,
     356             :                  pProbeContext,
     357           0 :                  *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID),
     358             :                  NULL,
     359             :                  0,
     360           0 :                  s_releaseMethod.get(),
     361             :                  NULL,
     362             :                  NULL,
     363           0 :                  NULL);
     364             : 
     365           0 : }
     366             : 
     367             : 
     368             : extern "C" {
     369           0 : static void s_type_destructData_v(va_list * pParam)
     370             : {
     371           0 :     void * ret = va_arg(*pParam, void *);
     372           0 :     typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
     373             : 
     374           0 :     uno_type_destructData(ret, pReturnTypeRef, 0);
     375           0 : }
     376             : 
     377           0 : static void s_dispatcher_v(va_list * pParam)
     378             : {
     379           0 :     uno_Interface                 * pUnoI       = va_arg(*pParam, uno_Interface *);
     380           0 :     typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
     381           0 :     void                          * pReturn     = va_arg(*pParam, void *);
     382           0 :     void                         ** pArgs       = va_arg(*pParam, void **);
     383           0 :     uno_Any                      ** ppException = va_arg(*pParam, uno_Any **);
     384             : 
     385           0 :     pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
     386           0 : }
     387             : }
     388             : 
     389           0 : void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,
     390             :                      typelib_MethodParameter          * pParams,
     391             :                      sal_Int32                          nParams,
     392             :                      typelib_TypeDescription    const * pMemberType,
     393             :                      void                             * pReturn,
     394             :                      void                             * pArgs[],
     395             :                      uno_Any                         ** ppException)
     396             : {
     397           0 :     if (m_probeFun)
     398             :         m_probeFun(true,
     399             :                    this,
     400             :                    m_pProbeContext,
     401             :                    pReturnTypeRef,
     402             :                    pParams,
     403             :                    nParams,
     404             :                    pMemberType,
     405             :                    pReturn,
     406             :                    pArgs,
     407           0 :                    ppException);
     408             : 
     409           0 :     void ** args = (void **) alloca( sizeof (void *) * nParams );
     410             : 
     411           0 :     typelib_TypeDescription * return_td = 0;
     412           0 :     void * ret = pReturn;
     413           0 :     if (pReturnTypeRef)
     414             :     {
     415           0 :         TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
     416             : 
     417           0 :         if (relatesToInterface(return_td))
     418           0 :             ret = alloca(return_td->nSize);
     419             : 
     420           0 :         TYPELIB_DANGER_RELEASE(return_td);
     421             :     }
     422             : 
     423           0 :     for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
     424             :     {
     425           0 :         typelib_MethodParameter const & param = pParams[nPos];
     426           0 :         typelib_TypeDescription * td = 0;
     427           0 :         TYPELIB_DANGER_GET( &td, param.pTypeRef );
     428           0 :         if (relatesToInterface(td))
     429             :         {
     430           0 :             args[nPos] = alloca(td->nSize);
     431           0 :             if (param.bIn)
     432             :             {
     433           0 :                 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
     434             :             }
     435             :         }
     436             :         else
     437             :         {
     438           0 :             args[nPos] = pArgs[nPos];
     439             :         }
     440           0 :         TYPELIB_DANGER_RELEASE( td );
     441             :     }
     442             : 
     443             :     uno_Any exc_data;
     444           0 :     uno_Any * exc = &exc_data;
     445             : 
     446             :     // do the UNO call...
     447           0 :     uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
     448             : 
     449           0 :     if (exc == 0)
     450             :     {
     451           0 :         for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
     452             :         {
     453           0 :             if (args[nPos] != pArgs[nPos])
     454             :             {
     455           0 :                 typelib_MethodParameter const & param = pParams[nPos];
     456           0 :                 if (param.bOut)
     457             :                 {
     458           0 :                     if (param.bIn) // is inout
     459             :                     {
     460           0 :                         uno_type_destructData(pArgs[nPos], param.pTypeRef, 0);
     461             :                     }
     462           0 :                     uno_type_copyAndConvertData(pArgs[ nPos ],
     463           0 :                                                 args[ nPos ],
     464             :                                                 param.pTypeRef,
     465           0 :                                                 m_to_from.get());
     466             :                 }
     467           0 :                 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
     468             :             }
     469             :         }
     470           0 :         if (ret != pReturn)
     471             :         {
     472             :             uno_type_copyAndConvertData(pReturn,
     473             :                                         ret,
     474             :                                         pReturnTypeRef,
     475           0 :                                         m_to_from.get());
     476             : 
     477           0 :             uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
     478             :         }
     479             : 
     480           0 :         *ppException = 0;
     481             :     }
     482             :     else // exception occurred
     483             :     {
     484           0 :         for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
     485             :         {
     486           0 :             if (args[nPos] != pArgs[nPos])
     487             :             {
     488           0 :                 typelib_MethodParameter const & param = pParams[nPos];
     489           0 :                 if (param.bIn)
     490             :                 {
     491           0 :                     uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
     492             :                 }
     493             :             }
     494             :         }
     495             : 
     496             :         uno_type_any_constructAndConvert(*ppException,
     497             :                                          exc->pData,
     498             :                                          exc->pType,
     499           0 :                                          m_to_from.get());
     500             : 
     501             :         // FIXME: need to destruct in m_to
     502           0 :         uno_any_destruct(exc, 0);
     503             :     }
     504             : 
     505           0 :     if (m_probeFun)
     506             :         m_probeFun(false,
     507             :                    this,
     508             :                    m_pProbeContext,
     509             :                    pReturnTypeRef,
     510             :                    pParams,
     511             :                    nParams,
     512             :                    pMemberType,
     513             :                    pReturn,
     514             :                    pArgs,
     515           0 :                    ppException);
     516           0 : }
     517             : 
     518             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10