LCOV - code coverage report
Current view: top level - cppu/source/helper/purpenv - helper_purpenv_Proxy.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 149 195 76.4 %
Date: 2015-06-13 12:38:46 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      589650 : static bool relatesToInterface(typelib_TypeDescription * pTypeDescr)
      44             : {
      45      589650 :     switch (pTypeDescr->eTypeClass)
      46             :     {
      47             : //      case typelib_TypeClass_TYPEDEF:
      48             :     case typelib_TypeClass_SEQUENCE:
      49             :     {
      50         176 :         switch (reinterpret_cast<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          15 :             typelib_TypeDescription * pTD = 0;
      60          15 :             TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType );
      61          15 :             bool bRel = relatesToInterface( pTD );
      62          15 :             TYPELIB_DANGER_RELEASE( pTD );
      63          15 :             return bRel;
      64             :         }
      65             :         default:
      66             :             ;
      67             :         }
      68         161 :         return false;
      69             :     }
      70             :     case typelib_TypeClass_STRUCT:
      71             :     case typelib_TypeClass_EXCEPTION:
      72             :     {
      73             :         // ...optimized... to avoid getDescription() calls!
      74          60 :         typelib_CompoundTypeDescription * pComp    = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr);
      75          60 :         typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs;
      76         243 :         for ( sal_Int32 nPos = pComp->nMembers; nPos--; )
      77             :         {
      78         147 :             switch (pTypes[nPos]->eTypeClass)
      79             :             {
      80             :             case typelib_TypeClass_INTERFACE:
      81             :             case typelib_TypeClass_ANY: // might relate to interface
      82          24 :                 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          36 :         if (pComp->pBaseTypeDescription)
     100           0 :             return relatesToInterface( &pComp->pBaseTypeDescription->aBase );
     101          36 :         break;
     102             :     }
     103             :     case typelib_TypeClass_ANY: // might relate to interface
     104             :     case typelib_TypeClass_INTERFACE:
     105      126144 :         return true;
     106             : 
     107             :     default:
     108             :         ;
     109             :     }
     110      463306 :     return false;
     111             : }
     112             : 
     113      341489 : 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      341489 :     Proxy * pThis = static_cast<Proxy *>(pUnoI);
     122             : 
     123             :     typelib_MethodParameter            param;
     124      341489 :     sal_Int32                          nParams = 0;
     125      341489 :     typelib_MethodParameter          * pParams = 0;
     126      341489 :     typelib_TypeDescriptionReference * pReturnTypeRef = 0;
     127             :     // sal_Int32                          nOutParams = 0;
     128             : 
     129      341489 :     switch (pMemberType->eTypeClass)
     130             :     {
     131             :     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
     132           0 :         if (pReturn)
     133             :         {
     134             :             pReturnTypeRef =
     135             :                 reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
     136           0 :                  pMemberType)->pAttributeTypeRef;
     137           0 :             nParams = 0;
     138           0 :             pParams = NULL;
     139             :         }
     140             :         else
     141             :         {
     142             :             param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>(
     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 const * method_td =
     153      341489 :             reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType);
     154      341489 :         pReturnTypeRef = method_td->pReturnTypeRef;
     155      341489 :         nParams = method_td->nParams;
     156      341489 :         pParams = method_td->pParams;
     157      341489 :         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      341489 :                      ppException );
     171      341489 : }}
     172             : 
     173       96403 : extern "C" void SAL_CALL Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C()
     174             : {
     175       96403 :     Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy));
     176       96403 :     delete pThis;
     177       96403 : }
     178             : 
     179             : extern "C" {
     180       99025 : static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
     181             : {
     182       99025 :     Proxy * pProxy = static_cast<Proxy *>(pUnoI);
     183       99025 :     pProxy->acquire();
     184       99025 : }
     185             : 
     186      195428 : static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C()
     187             : {
     188      195428 :     Proxy * pProxy = static_cast<Proxy *>(pUnoI);
     189      195428 :     pProxy->release();
     190      195428 : }
     191             : 
     192       96425 : static void s_acquireAndRegister_v(va_list * pParam)
     193             : {
     194       96425 :     uno_Interface                    * pUnoI      = va_arg(*pParam, uno_Interface *);
     195       96425 :     rtl_uString                      * pOid       = va_arg(*pParam, rtl_uString *);
     196       96425 :     typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *);
     197       96425 :     uno_ExtEnvironment               * pEnv       = va_arg(*pParam, uno_ExtEnvironment *);
     198             : 
     199       96425 :     pUnoI->acquire(pUnoI);
     200       96425 :      pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr);
     201       96425 : }
     202             : }
     203             : 
     204       96425 : 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       96425 :           m_pProbeContext(pProbeContext)
     223             : {
     224             :     LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this));
     225             : 
     226       96425 :     typelib_typedescription_acquire(&m_pTypeDescr->aBase);
     227       96425 :     if (!m_pTypeDescr->aBase.bComplete)
     228           0 :         typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr));
     229             : 
     230             :     OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!");
     231             : 
     232       96425 :     uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get());
     233             : 
     234             :     // uno_Interface
     235       96425 :     uno_Interface::acquire     = s_Proxy_acquire;
     236       96425 :     uno_Interface::release     = s_Proxy_release;
     237       96425 :     uno_Interface::pDispatcher = s_Proxy_dispatch;
     238       96425 : }
     239             : 
     240       96403 : extern "C" { static void s_releaseAndRevoke_v(va_list * pParam)
     241             : {
     242       96403 :     uno_ExtEnvironment * pEnv  = va_arg(*pParam, uno_ExtEnvironment *);
     243       96403 :     uno_Interface      * pUnoI = va_arg(*pParam, uno_Interface *);
     244             : 
     245       96403 :     pEnv->revokeInterface(pEnv, pUnoI);
     246       96403 :     pUnoI->release(pUnoI);
     247       96403 : }}
     248             : 
     249      192806 : Proxy::~Proxy()
     250             : {
     251             :     LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this));
     252             : 
     253       96403 :     uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI);
     254             : 
     255       96403 :     typelib_typedescription_release(&m_pTypeDescr->aBase);
     256       96403 : }
     257             : 
     258           5 : static uno::TypeDescription getAcquireMethod()
     259             : {
     260             :     typelib_TypeDescriptionReference * type_XInterface =
     261           5 :         * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
     262             : 
     263           5 :     typelib_TypeDescription * pTXInterfaceDescr = 0;
     264           5 :     TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
     265             :     uno::TypeDescription acquire(
     266             :         reinterpret_cast< typelib_InterfaceTypeDescription * >(
     267           5 :             pTXInterfaceDescr)->ppAllMembers[1]);
     268           5 :     TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
     269             : 
     270           5 :     return acquire;
     271             : }
     272             : 
     273           5 : static uno::TypeDescription getReleaseMethod()
     274             : {
     275             :     typelib_TypeDescriptionReference * type_XInterface =
     276           5 :         * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE);
     277             : 
     278           5 :     typelib_TypeDescription * pTXInterfaceDescr = 0;
     279           5 :     TYPELIB_DANGER_GET    (&pTXInterfaceDescr, type_XInterface);
     280             :     uno::TypeDescription release(
     281             :         reinterpret_cast< typelib_InterfaceTypeDescription * >(
     282           5 :             pTXInterfaceDescr)->ppAllMembers[2]);
     283           5 :     TYPELIB_DANGER_RELEASE(pTXInterfaceDescr);
     284             : 
     285           5 :     return release;
     286             : }
     287             : 
     288           5 : static uno::TypeDescription s_acquireMethod(getAcquireMethod());
     289           5 : static uno::TypeDescription s_releaseMethod(getReleaseMethod());
     290             : 
     291       99025 : void Proxy::acquire()
     292             : {
     293       99025 :     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       99025 :     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       99025 :     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       99025 : }
     330             : 
     331      195428 : void Proxy::release()
     332             : {
     333      195428 :     cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun;
     334      195428 :     void                            * pProbeContext = m_pProbeContext;
     335             : 
     336      195428 :     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      195428 :     if (osl_atomic_decrement(&m_nRef) == 0)
     349       96403 :         m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this);
     350             : 
     351      195428 :     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      195428 : }
     364             : 
     365             : 
     366             : extern "C" {
     367      126168 : static void s_type_destructData_v(va_list * pParam)
     368             : {
     369      126168 :     void * ret = va_arg(*pParam, void *);
     370      126168 :     typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *);
     371             : 
     372      126168 :     uno_type_destructData(ret, pReturnTypeRef, 0);
     373      126168 : }
     374             : 
     375      341489 : static void s_dispatcher_v(va_list * pParam)
     376             : {
     377      341489 :     uno_Interface                 * pUnoI       = va_arg(*pParam, uno_Interface *);
     378      341489 :     typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *);
     379      341489 :     void                          * pReturn     = va_arg(*pParam, void *);
     380      341489 :     void                         ** pArgs       = va_arg(*pParam, void **);
     381      341489 :     uno_Any                      ** ppException = va_arg(*pParam, uno_Any **);
     382             : 
     383      341489 :     pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException);
     384      341489 : }
     385             : }
     386             : 
     387      341489 : 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      341489 :     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      341489 :     void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams ));
     408             : 
     409      341489 :     typelib_TypeDescription * return_td = 0;
     410      341489 :     void * ret = pReturn;
     411      341489 :     if (pReturnTypeRef)
     412             :     {
     413      341489 :         TYPELIB_DANGER_GET(&return_td, pReturnTypeRef);
     414             : 
     415      341489 :         if (relatesToInterface(return_td))
     416      125816 :             ret = alloca(return_td->nSize);
     417             : 
     418      341489 :         TYPELIB_DANGER_RELEASE(return_td);
     419             :     }
     420             : 
     421      589635 :     for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
     422             :     {
     423      248146 :         typelib_MethodParameter const & param = pParams[nPos];
     424      248146 :         typelib_TypeDescription * td = 0;
     425      248146 :         TYPELIB_DANGER_GET( &td, param.pTypeRef );
     426      248146 :         if (relatesToInterface(td))
     427             :         {
     428         352 :             args[nPos] = alloca(td->nSize);
     429         352 :             if (param.bIn)
     430             :             {
     431         352 :                 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get());
     432             :             }
     433             :         }
     434             :         else
     435             :         {
     436      247794 :             args[nPos] = pArgs[nPos];
     437             :         }
     438      248146 :         TYPELIB_DANGER_RELEASE( td );
     439             :     }
     440             : 
     441             :     uno_Any exc_data;
     442      341489 :     uno_Any * exc = &exc_data;
     443             : 
     444             :     // do the UNO call...
     445      341489 :     uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc);
     446             : 
     447      341489 :     if (exc == 0)
     448             :     {
     449      589475 :         for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos)
     450             :         {
     451      248146 :             if (args[nPos] != pArgs[nPos])
     452             :             {
     453         352 :                 typelib_MethodParameter const & param = pParams[nPos];
     454         352 :                 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         352 :                 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0);
     466             :             }
     467             :         }
     468      341329 :         if (ret != pReturn)
     469             :         {
     470             :             uno_type_copyAndConvertData(pReturn,
     471             :                                         ret,
     472             :                                         pReturnTypeRef,
     473      125816 :                                         m_to_from.get());
     474             : 
     475      125816 :             uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0);
     476             :         }
     477             : 
     478      341329 :         *ppException = 0;
     479             :     }
     480             :     else // exception occurred
     481             :     {
     482         160 :         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         160 :                                          m_to_from.get());
     498             : 
     499             :         // FIXME: need to destruct in m_to
     500         160 :         uno_any_destruct(exc, 0);
     501             :     }
     502             : 
     503      341489 :     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      341504 : }
     515             : 
     516             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11