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

Generated by: LCOV version 1.10