1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cppu.hxx" 30 31 #include "cppu/helper/purpenv/Mapping.hxx" 32 33 #include "Proxy.hxx" 34 35 #include "osl/interlck.h" 36 #include "uno/environment.hxx" 37 #include "uno/dispatcher.h" 38 #include "typelib/typedescription.h" 39 40 41 #ifdef debug 42 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping 43 #endif 44 45 #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Mapping 46 # include <iostream> 47 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) x 48 49 #else 50 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) 51 52 #endif 53 54 55 using namespace com::sun::star; 56 57 58 class Mapping : public uno_Mapping 59 { 60 uno::Environment m_from; 61 uno::Environment m_to; 62 63 oslInterlockedCount m_nCount; 64 65 cppu::helper::purpenv::ProbeFun * m_probeFun; 66 void * m_pContext; 67 68 public: 69 explicit Mapping(uno_Environment * pFrom, 70 uno_Environment * pTo, 71 cppu::helper::purpenv::ProbeFun * probeFun, 72 void * pProbeContext); 73 virtual ~Mapping(void); 74 75 void mapInterface( 76 uno_Interface ** ppOut, 77 uno_Interface * pUnoI, 78 typelib_InterfaceTypeDescription * pTypeDescr); 79 80 void acquire(void); 81 void release(void); 82 }; 83 84 static void SAL_CALL s_mapInterface( 85 uno_Mapping * puno_Mapping, 86 uno_Interface ** ppOut, 87 uno_Interface * pUnoI, 88 typelib_InterfaceTypeDescription * pTypeDescr ) 89 SAL_THROW_EXTERN_C() 90 { 91 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 92 pMapping->mapInterface(ppOut, pUnoI, pTypeDescr); 93 } 94 95 extern "C" { 96 static void SAL_CALL s_acquire(uno_Mapping * puno_Mapping) 97 SAL_THROW_EXTERN_C() 98 { 99 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 100 pMapping->acquire(); 101 } 102 103 static void SAL_CALL s_release(uno_Mapping * puno_Mapping) 104 SAL_THROW_EXTERN_C() 105 { 106 Mapping * pMapping = static_cast<Mapping * >(puno_Mapping); 107 pMapping->release(); 108 } 109 110 111 static void s_getIdentifier_v(va_list * pParam) 112 { 113 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 114 rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **); 115 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 116 117 pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI); 118 } 119 120 static void SAL_CALL s_free(uno_Mapping * puno_Mapping) 121 SAL_THROW_EXTERN_C() 122 { 123 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 124 delete pMapping; 125 } 126 } 127 128 Mapping::Mapping(uno_Environment * pFrom, 129 uno_Environment * pTo, 130 cppu::helper::purpenv::ProbeFun * probeFun, 131 void * pProbeContext 132 ) SAL_THROW( () ) 133 : m_from (pFrom), 134 m_to (pTo), 135 m_nCount (1), 136 m_probeFun(probeFun), 137 m_pContext(pProbeContext) 138 { 139 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo) SAL_THROW( () )", this)); 140 141 uno_Mapping::acquire = s_acquire; 142 uno_Mapping::release = s_release; 143 uno_Mapping::mapInterface = (uno_MapInterfaceFunc)s_mapInterface; 144 } 145 146 Mapping::~Mapping(void) 147 { 148 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::~Mapping(void)", this)); 149 } 150 151 152 void Mapping::mapInterface( 153 uno_Interface ** ppOut, 154 uno_Interface * pUnoI, 155 typelib_InterfaceTypeDescription * pTypeDescr) 156 { 157 OSL_ASSERT(ppOut && pTypeDescr); 158 if (*ppOut) 159 { 160 (*ppOut)->release(*ppOut); 161 *ppOut = 0; 162 } 163 164 if (!pUnoI) 165 return; 166 167 // get object id of uno interface to be wrapped 168 // need to enter environment because of potential "queryInterface" call 169 rtl_uString * pOId = 0; 170 uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI); 171 OSL_ASSERT(pOId); 172 173 // try to get any known interface from target environment 174 m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, (void **)ppOut, pOId, pTypeDescr); 175 176 if (!*ppOut) // not yet there, register new proxy interface 177 { 178 // try to publish a new proxy (ref count initially 1) 179 uno_Interface * pProxy = new Proxy(this, 180 m_from.get(), 181 m_to.get(), 182 pUnoI, 183 pTypeDescr, 184 pOId, 185 m_probeFun, 186 m_pContext); 187 188 // proxy may be exchanged during registration 189 m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv, 190 (void **)&pProxy, 191 Proxy_free, 192 pOId, 193 pTypeDescr); 194 195 *ppOut = pProxy; 196 } 197 198 rtl_uString_release(pOId); 199 } 200 201 202 void Mapping::acquire() SAL_THROW(()) 203 { 204 if (osl_incrementInterlockedCount(&m_nCount) == 1) 205 { 206 uno_Mapping * pMapping = this; 207 208 ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), NULL); 209 } 210 } 211 212 void Mapping::release() SAL_THROW(()) 213 { 214 if (osl_decrementInterlockedCount(&m_nCount) == 0) 215 ::uno_revokeMapping(this); 216 } 217 218 219 namespace cppu { namespace helper { namespace purpenv { 220 221 void createMapping(uno_Mapping ** ppMapping, 222 uno_Environment * pFrom, 223 uno_Environment * pTo, 224 ProbeFun * probeFun, 225 void * pContext 226 ) 227 { 228 *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext); 229 230 ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, NULL); 231 } 232 233 }}} 234