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

Generated by: LCOV version 1.10