/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_cppu.hxx" #include "cppu/helper/purpenv/Mapping.hxx" #include "Proxy.hxx" #include "osl/interlck.h" #include "uno/environment.hxx" #include "uno/dispatcher.h" #include "typelib/typedescription.h" #ifdef debug # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping #endif #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Mapping # include # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) x #else # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) #endif using namespace com::sun::star; 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); void mapInterface( uno_Interface ** ppOut, uno_Interface * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr); void acquire(void); void release(void); }; static void SAL_CALL s_mapInterface( uno_Mapping * puno_Mapping, uno_Interface ** ppOut, uno_Interface * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr ) SAL_THROW_EXTERN_C() { Mapping * pMapping = static_cast(puno_Mapping); pMapping->mapInterface(ppOut, pUnoI, pTypeDescr); } extern "C" { static void SAL_CALL s_acquire(uno_Mapping * puno_Mapping) SAL_THROW_EXTERN_C() { Mapping * pMapping = static_cast(puno_Mapping); pMapping->acquire(); } static void SAL_CALL s_release(uno_Mapping * puno_Mapping) SAL_THROW_EXTERN_C() { Mapping * pMapping = static_cast(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 SAL_CALL s_free(uno_Mapping * puno_Mapping) SAL_THROW_EXTERN_C() { Mapping * pMapping = static_cast(puno_Mapping); delete pMapping; } } Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo, cppu::helper::purpenv::ProbeFun * probeFun, void * pProbeContext ) SAL_THROW( () ) : m_from (pFrom), m_to (pTo), m_nCount (1), m_probeFun(probeFun), m_pContext(pProbeContext) { LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo) SAL_THROW( () )", this)); uno_Mapping::acquire = s_acquire; uno_Mapping::release = s_release; uno_Mapping::mapInterface = (uno_MapInterfaceFunc)s_mapInterface; } Mapping::~Mapping(void) { LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::~Mapping(void)", this)); } void Mapping::mapInterface( uno_Interface ** ppOut, uno_Interface * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr) { OSL_ASSERT(ppOut && pTypeDescr); if (*ppOut) { (*ppOut)->release(*ppOut); *ppOut = 0; } if (!pUnoI) return; // get object id of uno interface to be wrapped // need to enter environment because of potential "queryInterface" call rtl_uString * pOId = 0; 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, (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, (void **)&pProxy, Proxy_free, pOId, pTypeDescr); *ppOut = pProxy; } rtl_uString_release(pOId); } void Mapping::acquire() SAL_THROW(()) { if (osl_incrementInterlockedCount(&m_nCount) == 1) { uno_Mapping * pMapping = this; ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), NULL); } } void Mapping::release() SAL_THROW(()) { if (osl_decrementInterlockedCount(&m_nCount) == 0) ::uno_revokeMapping(this); } namespace cppu { namespace helper { namespace 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, NULL); } }}}