diff options
Diffstat (limited to 'cppu/source/helper')
-rw-r--r-- | cppu/source/helper/purpenv/Proxy.hxx | 79 | ||||
-rw-r--r-- | cppu/source/helper/purpenv/helper_purpenv_Environment.cxx | 522 | ||||
-rw-r--r-- | cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx | 215 | ||||
-rw-r--r-- | cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx | 503 |
4 files changed, 1319 insertions, 0 deletions
diff --git a/cppu/source/helper/purpenv/Proxy.hxx b/cppu/source/helper/purpenv/Proxy.hxx new file mode 100644 index 000000000..6f99ee7d4 --- /dev/null +++ b/cppu/source/helper/purpenv/Proxy.hxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_CPPU_SOURCE_HELPER_PURPENV_PROXY_HXX +#define INCLUDED_CPPU_SOURCE_HELPER_PURPENV_PROXY_HXX + +#include <osl/interlck.h> + +#include <uno/environment.hxx> +#include <uno/mapping.hxx> +#include <uno/dispatcher.h> + +#include <cppu/helper/purpenv/Mapping.hxx> + + +class Proxy : public uno_Interface +{ + oslInterlockedCount m_nRef; + + css::uno::Environment m_from; + css::uno::Environment m_to; + + css::uno::Mapping m_from_to; + css::uno::Mapping m_to_from; + + // mapping information + uno_Interface * m_pUnoI; // wrapped interface + typelib_InterfaceTypeDescription * m_pTypeDescr; + OUString m_aOId; + + cppu::helper::purpenv::ProbeFun * m_probeFun; + void * m_pProbeContext; + +public: + explicit Proxy(css::uno::Mapping const & to_from, + uno_Environment * pTo, + uno_Environment * pFrom, + uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr, + OUString const & rOId, + cppu::helper::purpenv::ProbeFun * probeFun, + void * pProbeContext); + ~Proxy(); + + void acquire(); + void release(); + + void dispatch( + typelib_TypeDescriptionReference * pReturnTypeRef, + typelib_MethodParameter * pParams, + sal_Int32 nParams, + typelib_TypeDescription const * pMemberType, + void * pReturn, + void * pArgs[], + uno_Any ** ppException ); + +}; + +extern "C" void Proxy_free(uno_ExtEnvironment * pEnv, void * pProxy) SAL_THROW_EXTERN_C(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx b/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx new file mode 100644 index 000000000..a0163939f --- /dev/null +++ b/cppu/source/helper/purpenv/helper_purpenv_Environment.cxx @@ -0,0 +1,522 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <cppu/helper/purpenv/Environment.hxx> + +#include <osl/diagnose.h> +#include <sal/log.hxx> +#include <uno/lbnames.h> +#include <cppu/Enterable.hxx> + +#include <typelib/typedescription.h> +#include <osl/interlck.h> +#include <memory> + +extern "C" { +typedef void EnvFun_P (uno_Environment *); +typedef void EnvFun_PP_P(uno_Environment ** ppHardEnv, uno_Environment *); +typedef void ExtEnv_registerProxyInterface (uno_ExtEnvironment *, + void ** ppProxy, + uno_freeProxyFunc freeProxy, + rtl_uString * pOId, + typelib_InterfaceTypeDescription * pTypeDescr); +typedef void ExtEnv_revokeInterface (uno_ExtEnvironment *, + void * pInterface); +typedef void ExtEnv_getObjectIdentifier (uno_ExtEnvironment *, + rtl_uString **, + void *); +typedef void ExtEnv_getRegisteredInterface (uno_ExtEnvironment *, + void **, + rtl_uString *, + typelib_InterfaceTypeDescription *); +typedef void ExtEnv_getRegisteredInterfaces(uno_ExtEnvironment *, + void *** pppInterfaces, + sal_Int32 * pnLen, + uno_memAlloc memAlloc); +typedef void ExtEnv_computeObjectIdentifier(uno_ExtEnvironment *, + rtl_uString ** ppOId, + void * pInterface); +typedef void ExtEnv_acquireInterface (uno_ExtEnvironment *, + void * pInterface); +typedef void ExtEnv_releaseInterface (uno_ExtEnvironment *, + void * pInterface); +} + +namespace { + +class Base : public cppu::Enterable +{ +public: + explicit Base(uno_Environment * pEnv, cppu::Enterable * pEnterable); + + void acquireWeak(); + void releaseWeak(); + void harden (uno_Environment ** ppHardEnv); + void acquire(); + void release(); + + void registerProxyInterface (void ** ppProxy, + uno_freeProxyFunc freeProxy, + OUString const & oid, + typelib_InterfaceTypeDescription * pTypeDescr); + void revokeInterface (void * pInterface); + void getObjectIdentifier (void * pInterface, + OUString * pOid); + void getRegisteredInterface (void **, + OUString const & oid, + typelib_InterfaceTypeDescription *); + void getRegisteredInterfaces(void ***, + sal_Int32 * pnLen, + uno_memAlloc memAlloc); + void computeObjectIdentifier(void * pInterface, + OUString * pOid); + void acquireInterface (void * pInterface); + void releaseInterface (void * pInterface); + + virtual void v_enter() override; + virtual void v_leave() override; + virtual void v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) override; + virtual void v_callOut_v (uno_EnvCallee * pCallee, va_list * pParam) override; + virtual bool v_isValid (OUString * pReason) override; + +protected: + oslInterlockedCount m_nRef; + uno_Environment * m_pEnv; + std::unique_ptr<cppu::Enterable> m_pEnterable; + + EnvFun_P * m_env_acquire; + EnvFun_P * m_env_release; + EnvFun_PP_P * m_env_harden; + EnvFun_P * m_env_acquireWeak; + EnvFun_P * m_env_releaseWeak; + + ExtEnv_registerProxyInterface * m_env_registerProxyInterface; + ExtEnv_revokeInterface * m_env_revokeInterface; + ExtEnv_getObjectIdentifier * m_env_getObjectIdentifier; + ExtEnv_getRegisteredInterface * m_env_getRegisteredInterface; + ExtEnv_getRegisteredInterfaces * m_env_getRegisteredInterfaces; + ExtEnv_computeObjectIdentifier * m_env_computeObjectIdentifier; + ExtEnv_acquireInterface * m_env_acquireInterface; + ExtEnv_releaseInterface * m_env_releaseInterface; + + virtual ~Base() override; +}; + +} + +extern "C" { +static void s_acquire(uno_Environment * pEnv) //SAL_THROW_EXTERN_C() +{ + Base * pBase = static_cast<Base *>(pEnv->pReserved); + pBase->acquire(); +} + +static void s_release(uno_Environment * pEnv) SAL_THROW_EXTERN_C() +{ + Base * pBase = static_cast<Base *>(pEnv->pReserved); + pBase->release(); +} + +static void s_harden(uno_Environment ** ppHardEnv, uno_Environment * pEnv) SAL_THROW_EXTERN_C() +{ + Base * pBase = static_cast<Base *>(pEnv->pReserved); + pBase->harden(ppHardEnv); +} + +static void s_acquireWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C() +{ + Base * pBase = static_cast<Base *>(pEnv->pReserved); + pBase->acquireWeak(); +} + +static void s_releaseWeak(uno_Environment * pEnv) SAL_THROW_EXTERN_C() +{ + Base * pBase = static_cast<Base *>(pEnv->pReserved); + pBase->releaseWeak(); +} + + +static void s_registerProxyInterface(uno_ExtEnvironment * pExtEnv, + void ** ppProxy, + uno_freeProxyFunc freeProxy, + rtl_uString * pOId, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->registerProxyInterface(ppProxy, freeProxy, pOId, pTypeDescr); +} + +static void s_revokeInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->revokeInterface(pInterface); +} + +static void s_getObjectIdentifier(uno_ExtEnvironment * pExtEnv, + rtl_uString ** ppOId, + void * pInterface) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->getObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId)); +} + +static void s_getRegisteredInterface(uno_ExtEnvironment * pExtEnv, + void ** ppInterface, + rtl_uString * pOId, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->getRegisteredInterface(ppInterface, pOId, pTypeDescr); +} + +static void s_getRegisteredInterfaces(uno_ExtEnvironment * pExtEnv, + void *** pppInterface, + sal_Int32 * pnLen, + uno_memAlloc memAlloc) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->getRegisteredInterfaces(pppInterface, pnLen, memAlloc); +} + +static void s_computeObjectIdentifier(uno_ExtEnvironment * pExtEnv, + rtl_uString ** ppOId, + void * pInterface) +{ + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->computeObjectIdentifier(pInterface, reinterpret_cast<OUString *>(ppOId)); +} + +static void s_acquireInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) { + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->acquireInterface(pInterface); +} + +static void s_releaseInterface(uno_ExtEnvironment * pExtEnv, void * pInterface) { + Base * pBase = static_cast<Base *>(pExtEnv->aBase.pReserved); + pBase->releaseInterface(pInterface); +} + +} + +Base::Base(uno_Environment * pEnv, cppu::Enterable * pEnterable) + :m_nRef(1), + m_pEnv(pEnv), + m_pEnterable (pEnterable), + m_env_acquire (pEnv->acquire), + m_env_release (pEnv->release), + m_env_harden (pEnv->harden), + m_env_acquireWeak(pEnv->acquireWeak), + m_env_releaseWeak(pEnv->releaseWeak), + m_env_registerProxyInterface (pEnv->pExtEnv->registerProxyInterface), + m_env_revokeInterface (pEnv->pExtEnv->revokeInterface), + m_env_getObjectIdentifier (pEnv->pExtEnv->getObjectIdentifier), + m_env_getRegisteredInterface (pEnv->pExtEnv->getRegisteredInterface), + m_env_getRegisteredInterfaces(pEnv->pExtEnv->getRegisteredInterfaces), + m_env_computeObjectIdentifier(pEnv->pExtEnv->computeObjectIdentifier), + m_env_acquireInterface (pEnv->pExtEnv->acquireInterface), + m_env_releaseInterface (pEnv->pExtEnv->releaseInterface) +{ + SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::Base(uno_Environment * pEnv) -> " << this); + OSL_ENSURE( + rtl_ustr_ascii_compare_WithLength(pEnv->pTypeName->buffer, rtl_str_getLength(UNO_LB_UNO), UNO_LB_UNO) + == 0, + "### wrong environment type!"); + + pEnv->acquire = s_acquire; + pEnv->release = s_release; + pEnv->harden = s_harden; + pEnv->acquireWeak = s_acquireWeak; + pEnv->releaseWeak = s_releaseWeak; + + pEnv->pExtEnv->registerProxyInterface = s_registerProxyInterface; + pEnv->pExtEnv->revokeInterface = s_revokeInterface; + pEnv->pExtEnv->getObjectIdentifier = s_getObjectIdentifier; + pEnv->pExtEnv->getRegisteredInterface = s_getRegisteredInterface; + pEnv->pExtEnv->getRegisteredInterfaces = s_getRegisteredInterfaces; + pEnv->pExtEnv->computeObjectIdentifier = s_computeObjectIdentifier; + pEnv->pExtEnv->acquireInterface = s_acquireInterface; + pEnv->pExtEnv->releaseInterface = s_releaseInterface; + + pEnv->pReserved = this; +} + +Base::~Base() +{ + SAL_INFO("cppu.purpenv", "LIFE: cppu::helper::purpenv::Base::~Base() -> " << this); + + m_pEnv->acquire = m_env_acquire; + m_pEnv->release = m_env_release; + m_pEnv->harden = m_env_harden; + m_pEnv->acquireWeak = m_env_acquireWeak; + m_pEnv->releaseWeak = m_env_releaseWeak; + + m_pEnv->pReserved = nullptr; + + m_pEnterable.reset(); + m_pEnv->release(m_pEnv); +} + +void Base::acquire() +{ + m_env_acquire(m_pEnv); + + osl_atomic_increment(&m_nRef); +} + +void Base::release() +{ + if (osl_atomic_decrement(&m_nRef) == 0) + delete this; + + else + m_env_release(m_pEnv); +} + +void Base::harden(uno_Environment ** ppHardEnv) +{ + m_env_harden(ppHardEnv, m_pEnv); + osl_atomic_increment(&m_nRef); +} + +void Base::acquireWeak() +{ + m_env_acquireWeak(m_pEnv); +} + +void Base::releaseWeak() +{ + m_env_releaseWeak(m_pEnv); +} + + +extern "C" { static void s_registerProxyInterface_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void ** ppProxy = va_arg(*pParam, void **); + uno_freeProxyFunc freeProxy = va_arg(*pParam, uno_freeProxyFunc); + rtl_uString * pOId = va_arg(*pParam, rtl_uString *); + typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); + ExtEnv_registerProxyInterface * pRegisterProxyInterface + = va_arg(*pParam, ExtEnv_registerProxyInterface *); + + pRegisterProxyInterface(pExtEnv, ppProxy, freeProxy, pOId, pTypeDescr); +}} + +void Base::registerProxyInterface(void ** ppProxy, + uno_freeProxyFunc freeProxy, + OUString const & oid, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + uno_Environment_invoke(m_pEnv, + s_registerProxyInterface_v, + m_pEnv->pExtEnv, + ppProxy, + freeProxy, + oid.pData, + pTypeDescr, + m_env_registerProxyInterface); +} + + +extern "C" { static void s_revokeInterface_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + ExtEnv_revokeInterface * pRevokeInterface = va_arg(*pParam, ExtEnv_revokeInterface *); + + pRevokeInterface(pExtEnv, pInterface); +}} + +void Base::revokeInterface(void * pInterface) +{ + uno_Environment_invoke(m_pEnv, + s_revokeInterface_v, + m_pEnv->pExtEnv, + pInterface, + m_env_revokeInterface); +} + + +extern "C" { static void s_getObjectIdentifier_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + OUString * pOId = va_arg(*pParam, OUString *); + ExtEnv_getObjectIdentifier * pGetObjectIdentifier + = va_arg(*pParam, ExtEnv_getObjectIdentifier *); + + pGetObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface); +}} + +void Base::getObjectIdentifier(void * pInterface, OUString * pOid) +{ + uno_Environment_invoke(m_pEnv, + s_getObjectIdentifier_v, + m_pEnv->pExtEnv, + pInterface, + pOid, + m_env_getObjectIdentifier); +} + + +extern "C" { static void s_getRegisteredInterface_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void ** ppInterface = va_arg(*pParam, void **); + rtl_uString * pOId = va_arg(*pParam, rtl_uString *); + typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); + ExtEnv_getRegisteredInterface * pGetRegisteredInterface + = va_arg(*pParam, ExtEnv_getRegisteredInterface *); + + pGetRegisteredInterface(pExtEnv, ppInterface, pOId, pTypeDescr); +}} + +void Base::getRegisteredInterface(void ** ppInterface, + OUString const & oid, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + uno_Environment_invoke(m_pEnv, + s_getRegisteredInterface_v, + m_pEnv->pExtEnv, + ppInterface, + oid.pData, + pTypeDescr, + m_env_getRegisteredInterface); +} + + +extern "C" { static void s_getRegisteredInterfaces_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void *** pppInterface = va_arg(*pParam, void ***); + sal_Int32 * pnLen = va_arg(*pParam, sal_Int32 *); + uno_memAlloc memAlloc = va_arg(*pParam, uno_memAlloc); + ExtEnv_getRegisteredInterfaces * pGetRegisteredInterfaces + = va_arg(*pParam, ExtEnv_getRegisteredInterfaces *); + + pGetRegisteredInterfaces(pExtEnv, pppInterface, pnLen, memAlloc); +}} + +void Base::getRegisteredInterfaces(void *** pppInterface, + sal_Int32 * pnLen, + uno_memAlloc memAlloc) +{ + uno_Environment_invoke(m_pEnv, + s_getRegisteredInterfaces_v, + m_pEnv->pExtEnv, + pppInterface, + pnLen, + memAlloc, + m_env_getRegisteredInterfaces); +} + + +extern "C" { static void s_computeObjectIdentifier_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + OUString * pOId = va_arg(*pParam, OUString *); + ExtEnv_computeObjectIdentifier * pComputeObjectIdentifier + = va_arg(*pParam, ExtEnv_computeObjectIdentifier *); + + pComputeObjectIdentifier(pExtEnv, reinterpret_cast<rtl_uString **>(pOId), pInterface); +}} + +void Base::computeObjectIdentifier(void * pInterface, OUString * pOid) +{ + uno_Environment_invoke(m_pEnv, + s_computeObjectIdentifier_v, + m_pEnv->pExtEnv, + pInterface, + pOid, + m_env_computeObjectIdentifier); +} + + +extern "C" { static void s_acquireInterface_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + ExtEnv_acquireInterface * pAcquireInterface + = va_arg(*pParam, ExtEnv_acquireInterface *); + + pAcquireInterface(pExtEnv, pInterface); +}} + +void Base::acquireInterface(void * pInterface) +{ + uno_Environment_invoke(m_pEnv, s_acquireInterface_v, m_pEnv->pExtEnv, pInterface, m_env_acquireInterface); +} + + +extern "C" { static void s_releaseInterface_v(va_list * pParam) +{ + uno_ExtEnvironment * pExtEnv = va_arg(*pParam, uno_ExtEnvironment *); + void * pInterface = va_arg(*pParam, void *); + ExtEnv_releaseInterface * pReleaseInterface + = va_arg(*pParam, ExtEnv_releaseInterface *); + + pReleaseInterface(pExtEnv, pInterface); +}} + +void Base::releaseInterface(void * pInterface) +{ + uno_Environment_invoke(m_pEnv, + s_releaseInterface_v, + m_pEnv->pExtEnv, + pInterface, + m_env_releaseInterface); +} + +void Base::v_enter() +{ + m_pEnterable->enter(); +} + +void Base::v_leave() +{ + m_pEnterable->leave(); +} + +void Base::v_callInto_v(uno_EnvCallee * pCallee, va_list * pParam) +{ + m_pEnterable->callInto_v(pCallee, pParam); +} + +void Base::v_callOut_v(uno_EnvCallee * pCallee, va_list * pParam) +{ + m_pEnterable->callOut_v(pCallee, pParam); +} + +bool Base::v_isValid(OUString * pReason) +{ + return m_pEnterable->isValid(pReason); +} + +namespace cppu::helper::purpenv { + +void Environment_initWithEnterable(uno_Environment * pEnvironment, cppu::Enterable * pEnterable) +{ + new Base(pEnvironment, pEnterable); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx b/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx new file mode 100644 index 000000000..f68a47390 --- /dev/null +++ b/cppu/source/helper/purpenv/helper_purpenv_Mapping.cxx @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <cppu/helper/purpenv/Mapping.hxx> + +#include "Proxy.hxx" + +#include <osl/interlck.h> +#include <sal/log.hxx> +#include <uno/environment.hxx> +#include <uno/dispatcher.h> + +using namespace com::sun::star; + +namespace { + +class Mapping : public uno_Mapping +{ + uno::Environment m_from; + uno::Environment m_to; + + oslInterlockedCount m_nCount; + + cppu::helper::purpenv::ProbeFun * m_probeFun; + void * m_pContext; + +public: + explicit Mapping(uno_Environment * pFrom, + uno_Environment * pTo, + cppu::helper::purpenv::ProbeFun * probeFun, + void * pProbeContext); + virtual ~Mapping(); + + void mapInterface( + uno_Interface ** ppOut, + uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr); + + void acquire(); + void release(); +}; + +} + +static void s_mapInterface( + uno_Mapping * puno_Mapping, + void ** ppOut, + void * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr ) + SAL_THROW_EXTERN_C() +{ + Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); + pMapping->mapInterface( + reinterpret_cast<uno_Interface **>(ppOut), + static_cast<uno_Interface *>(pUnoI), pTypeDescr); +} + +extern "C" { +static void s_acquire(uno_Mapping * puno_Mapping) + SAL_THROW_EXTERN_C() +{ + Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); + pMapping->acquire(); +} + +static void s_release(uno_Mapping * puno_Mapping) + SAL_THROW_EXTERN_C() +{ + Mapping * pMapping = static_cast<Mapping * >(puno_Mapping); + pMapping->release(); +} + + +static void s_getIdentifier_v(va_list * pParam) +{ + uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); + rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **); + uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); + + pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI); +} + +static void s_free(uno_Mapping * puno_Mapping) + SAL_THROW_EXTERN_C() +{ + Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); + delete pMapping; +} +} + +Mapping::Mapping(uno_Environment * pFrom, + uno_Environment * pTo, + cppu::helper::purpenv::ProbeFun * probeFun, + void * pProbeContext +) + : m_from (pFrom), + m_to (pTo), + m_nCount (1), + m_probeFun(probeFun), + m_pContext(pProbeContext) +{ + SAL_INFO("cppu.purpenv", "LIFE: Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo -> " << this); + + uno_Mapping::acquire = s_acquire; + uno_Mapping::release = s_release; + uno_Mapping::mapInterface = s_mapInterface; +} + +Mapping::~Mapping() +{ + SAL_INFO("cppu.purpenv", "LIFE: Mapping:~Mapping() -> " << this); +} + + +void Mapping::mapInterface( + uno_Interface ** ppOut, + uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr) +{ + OSL_ASSERT(ppOut && pTypeDescr); + if (*ppOut) + { + (*ppOut)->release(*ppOut); + *ppOut = nullptr; + } + + if (!pUnoI) + return; + + // get object id of uno interface to be wrapped + // need to enter environment because of potential "queryInterface" call + rtl_uString * pOId = nullptr; + uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI); + OSL_ASSERT(pOId); + + // try to get any known interface from target environment + m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, reinterpret_cast<void **>(ppOut), pOId, pTypeDescr); + + if (!*ppOut) // not yet there, register new proxy interface + { + // try to publish a new proxy (ref count initially 1) + uno_Interface * pProxy = new Proxy(this, + m_from.get(), + m_to.get(), + pUnoI, + pTypeDescr, + pOId, + m_probeFun, + m_pContext); + + // proxy may be exchanged during registration + m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv, + reinterpret_cast<void **>(&pProxy), + Proxy_free, + pOId, + pTypeDescr); + + *ppOut = pProxy; + } + + rtl_uString_release(pOId); +} + + +void Mapping::acquire() +{ + if (osl_atomic_increment(&m_nCount) == 1) + { + uno_Mapping * pMapping = this; + + ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), nullptr); + } +} + +void Mapping::release() +{ + if (osl_atomic_decrement(&m_nCount) == 0) + ::uno_revokeMapping(this); +} + + +namespace cppu::helper::purpenv { + +void createMapping(uno_Mapping ** ppMapping, + uno_Environment * pFrom, + uno_Environment * pTo, + ProbeFun * probeFun, + void * pContext + ) +{ + *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext); + + ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, nullptr); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx b/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx new file mode 100644 index 000000000..f62241fe1 --- /dev/null +++ b/cppu/source/helper/purpenv/helper_purpenv_Proxy.cxx @@ -0,0 +1,503 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "Proxy.hxx" + +#include <sal/log.hxx> +#include <uno/dispatcher.h> +#include <typelib/typedescription.hxx> + +using namespace com::sun::star; + +static bool relatesToInterface(typelib_TypeDescription * pTypeDescr) +{ + switch (pTypeDescr->eTypeClass) + { +// case typelib_TypeClass_TYPEDEF: + case typelib_TypeClass_SEQUENCE: + { + switch (reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType->eTypeClass) + { + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_ANY: // might relate to interface + return true; + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = nullptr; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast<typelib_IndirectTypeDescription *>(pTypeDescr)->pType ); + bool bRel = relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + return bRel; + } + default: + ; + } + return false; + } + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + // ...optimized... to avoid getDescription() calls! + typelib_CompoundTypeDescription * pComp = reinterpret_cast<typelib_CompoundTypeDescription *>(pTypeDescr); + typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs; + for ( sal_Int32 nPos = pComp->nMembers; nPos--; ) + { + switch (pTypes[nPos]->eTypeClass) + { + case typelib_TypeClass_INTERFACE: + case typelib_TypeClass_ANY: // might relate to interface + return true; +// case typelib_TypeClass_TYPEDEF: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_EXCEPTION: + { + typelib_TypeDescription * pTD = nullptr; + TYPELIB_DANGER_GET( &pTD, pTypes[nPos] ); + bool bRel = relatesToInterface( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + if (bRel) + return true; + break; + } + default: + break; + } + } + if (pComp->pBaseTypeDescription) + return relatesToInterface( &pComp->pBaseTypeDescription->aBase ); + break; + } + case typelib_TypeClass_ANY: // might relate to interface + case typelib_TypeClass_INTERFACE: + return true; + + default: + ; + } + return false; +} + +extern "C" { static void s_Proxy_dispatch( + uno_Interface * pUnoI, + typelib_TypeDescription const * pMemberType, + void * pReturn, + void * pArgs[], + uno_Any ** ppException) + SAL_THROW_EXTERN_C() +{ + Proxy * pThis = static_cast<Proxy *>(pUnoI); + + typelib_MethodParameter param; + sal_Int32 nParams = 0; + typelib_MethodParameter * pParams = nullptr; + typelib_TypeDescriptionReference * pReturnTypeRef = nullptr; + // sal_Int32 nOutParams = 0; + + switch (pMemberType->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + if (pReturn) + { + pReturnTypeRef = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>( + pMemberType)->pAttributeTypeRef; + nParams = 0; + pParams = nullptr; + } + else + { + param.pTypeRef = reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>( + pMemberType)->pAttributeTypeRef; + param.bIn = true; + param.bOut = false; + nParams = 1; + pParams = ¶m; + } + break; + case typelib_TypeClass_INTERFACE_METHOD: + { + typelib_InterfaceMethodTypeDescription const * method_td = + reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>(pMemberType); + pReturnTypeRef = method_td->pReturnTypeRef; + nParams = method_td->nParams; + pParams = method_td->pParams; + break; + } + default: + OSL_FAIL( "### illegal member typeclass!" ); + abort(); + } + + pThis->dispatch( pReturnTypeRef, + pParams, + nParams, + pMemberType, + pReturn, + pArgs, + ppException ); +}} + +extern "C" void Proxy_free(SAL_UNUSED_PARAMETER uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C() +{ + Proxy * pThis = static_cast<Proxy * >(static_cast<uno_Interface *>(pProxy)); + delete pThis; +} + +extern "C" { +static void s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() +{ + Proxy * pProxy = static_cast<Proxy *>(pUnoI); + pProxy->acquire(); +} + +static void s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() +{ + Proxy * pProxy = static_cast<Proxy *>(pUnoI); + pProxy->release(); +} + +static void s_acquireAndRegister_v(va_list * pParam) +{ + uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); + rtl_uString * pOid = va_arg(*pParam, rtl_uString *); + typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); + uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); + + pUnoI->acquire(pUnoI); + pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr); +} +} + +Proxy::Proxy(uno::Mapping const & to_from, + uno_Environment * pTo, + uno_Environment * pFrom, + uno_Interface * pUnoI, + typelib_InterfaceTypeDescription * pTypeDescr, + OUString const & rOId, + cppu::helper::purpenv::ProbeFun * probeFun, + void * pProbeContext +) + : m_nRef (1), + m_from (pFrom), + m_to (pTo), + m_from_to (pFrom, pTo), + m_to_from (to_from), + m_pUnoI (pUnoI), + m_pTypeDescr (pTypeDescr), + m_aOId (rOId), + m_probeFun (probeFun), + m_pProbeContext(pProbeContext) +{ + SAL_INFO("cppu.purpenv", "LIFE: Proxy::Proxy(<>) -> " << this); + + typelib_typedescription_acquire(&m_pTypeDescr->aBase); + if (!m_pTypeDescr->aBase.bComplete) + typelib_typedescription_complete(reinterpret_cast<typelib_TypeDescription **>(&m_pTypeDescr)); + + OSL_ENSURE(m_pTypeDescr->aBase.bComplete, "### type is incomplete!"); + + uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get()); + + // uno_Interface + uno_Interface::acquire = s_Proxy_acquire; + uno_Interface::release = s_Proxy_release; + uno_Interface::pDispatcher = s_Proxy_dispatch; +} + +extern "C" { static void s_releaseAndRevoke_v(va_list * pParam) +{ + uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); + uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); + + pEnv->revokeInterface(pEnv, pUnoI); + pUnoI->release(pUnoI); +}} + +Proxy::~Proxy() +{ + SAL_INFO("cppu.purpenv", "LIFE: Proxy::~Proxy() -> " << this); + + uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI); + + typelib_typedescription_release(&m_pTypeDescr->aBase); +} + +static uno::TypeDescription getAcquireMethod() +{ + typelib_TypeDescriptionReference * type_XInterface = + * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); + + typelib_TypeDescription * pTXInterfaceDescr = nullptr; + TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); + uno::TypeDescription acquire( + reinterpret_cast< typelib_InterfaceTypeDescription * >( + pTXInterfaceDescr)->ppAllMembers[1]); + TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); + + return acquire; +} + +static uno::TypeDescription getReleaseMethod() +{ + typelib_TypeDescriptionReference * type_XInterface = + * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); + + typelib_TypeDescription * pTXInterfaceDescr = nullptr; + TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); + uno::TypeDescription release( + reinterpret_cast< typelib_InterfaceTypeDescription * >( + pTXInterfaceDescr)->ppAllMembers[2]); + TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); + + return release; +} + +static uno::TypeDescription s_acquireMethod(getAcquireMethod()); +static uno::TypeDescription s_releaseMethod(getReleaseMethod()); + +void Proxy::acquire() +{ + if (m_probeFun) + m_probeFun(true, + this, + m_pProbeContext, + *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), + nullptr, + 0, + s_acquireMethod.get(), + nullptr, + nullptr, + nullptr); + + if (osl_atomic_increment(&m_nRef) == 1) + { + // rebirth of proxy zombie + void * pThis = this; + m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv, + &pThis, + Proxy_free, + m_aOId.pData, + m_pTypeDescr); + OSL_ASSERT(pThis == this); + } + + if (m_probeFun) + m_probeFun(false, + this, + m_pProbeContext, + *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), + nullptr, + 0, + s_acquireMethod.get(), + nullptr, + nullptr, + nullptr); + +} + +void Proxy::release() +{ + cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun; + void * pProbeContext = m_pProbeContext; + + if (m_probeFun) + m_probeFun(true, + this, + m_pProbeContext, + *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), + nullptr, + 0, + s_releaseMethod.get(), + nullptr, + nullptr, + nullptr); + + if (osl_atomic_decrement(&m_nRef) == 0) + m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this); + + if (probeFun) + probeFun(false, + this, + pProbeContext, + *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), + nullptr, + 0, + s_releaseMethod.get(), + nullptr, + nullptr, + nullptr); + +} + + +extern "C" { +static void s_type_destructData_v(va_list * pParam) +{ + void * ret = va_arg(*pParam, void *); + typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *); + + uno_type_destructData(ret, pReturnTypeRef, nullptr); +} + +static void s_dispatcher_v(va_list * pParam) +{ + uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); + typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *); + void * pReturn = va_arg(*pParam, void *); + void ** pArgs = va_arg(*pParam, void **); + uno_Any ** ppException = va_arg(*pParam, uno_Any **); + + pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException); +} +} + +void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef, + typelib_MethodParameter * pParams, + sal_Int32 nParams, + typelib_TypeDescription const * pMemberType, + void * pReturn, + void * pArgs[], + uno_Any ** ppException) +{ + if (m_probeFun) + m_probeFun(true, + this, + m_pProbeContext, + pReturnTypeRef, + pParams, + nParams, + pMemberType, + pReturn, + pArgs, + ppException); + + void ** args = static_cast<void **>(alloca( sizeof (void *) * nParams )); + + typelib_TypeDescription * return_td = nullptr; + void * ret = pReturn; + if (pReturnTypeRef) + { + TYPELIB_DANGER_GET(&return_td, pReturnTypeRef); + + if (relatesToInterface(return_td)) + ret = alloca(return_td->nSize); + + TYPELIB_DANGER_RELEASE(return_td); + } + + for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) + { + typelib_MethodParameter const & param = pParams[nPos]; + typelib_TypeDescription * td = nullptr; + TYPELIB_DANGER_GET( &td, param.pTypeRef ); + if (relatesToInterface(td)) + { + args[nPos] = alloca(td->nSize); + if (param.bIn) + { + uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get()); + } + } + else + { + args[nPos] = pArgs[nPos]; + } + TYPELIB_DANGER_RELEASE( td ); + } + + uno_Any exc_data; + uno_Any * exc = &exc_data; + + // do the UNO call... + uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc); + + if (exc == nullptr) + { + for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) + { + if (args[nPos] != pArgs[nPos]) + { + typelib_MethodParameter const & param = pParams[nPos]; + if (param.bOut) + { + if (param.bIn) // is inout + { + uno_type_destructData(pArgs[nPos], param.pTypeRef, nullptr); + } + uno_type_copyAndConvertData(pArgs[ nPos ], + args[ nPos ], + param.pTypeRef, + m_to_from.get()); + } + uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); + } + } + if (ret != pReturn) + { + uno_type_copyAndConvertData(pReturn, + ret, + pReturnTypeRef, + m_to_from.get()); + + uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0); + } + + *ppException = nullptr; + } + else // exception occurred + { + for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) + { + if (args[nPos] != pArgs[nPos]) + { + typelib_MethodParameter const & param = pParams[nPos]; + if (param.bIn) + { + uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); + } + } + } + + uno_type_any_constructAndConvert(*ppException, + exc->pData, + exc->pType, + m_to_from.get()); + + // FIXME: need to destruct in m_to + uno_any_destruct(exc, nullptr); + } + + if (m_probeFun) + m_probeFun(false, + this, + m_pProbeContext, + pReturnTypeRef, + pParams, + nParams, + pMemberType, + pReturn, + pArgs, + ppException); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |