1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cppu.hxx" 26 27 #include "cppu/helper/purpenv/Mapping.hxx" 28 29 #include "Proxy.hxx" 30 31 #include "osl/interlck.h" 32 #include "uno/environment.hxx" 33 #include "uno/dispatcher.h" 34 #include "typelib/typedescription.h" 35 36 37 #ifdef debug 38 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping 39 #endif 40 41 #ifdef LOG_LIFECYCLE_cppu_helper_purpenv_Mapping 42 # include <iostream> 43 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) x 44 45 #else 46 # define LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(x) 47 48 #endif 49 50 51 using namespace com::sun::star; 52 53 54 class Mapping : public uno_Mapping 55 { 56 uno::Environment m_from; 57 uno::Environment m_to; 58 59 oslInterlockedCount m_nCount; 60 61 cppu::helper::purpenv::ProbeFun * m_probeFun; 62 void * m_pContext; 63 64 public: 65 explicit Mapping(uno_Environment * pFrom, 66 uno_Environment * pTo, 67 cppu::helper::purpenv::ProbeFun * probeFun, 68 void * pProbeContext); 69 virtual ~Mapping(void); 70 71 void mapInterface( 72 uno_Interface ** ppOut, 73 uno_Interface * pUnoI, 74 typelib_InterfaceTypeDescription * pTypeDescr); 75 76 void acquire(void); 77 void release(void); 78 }; 79 80 static void SAL_CALL s_mapInterface( 81 uno_Mapping * puno_Mapping, 82 uno_Interface ** ppOut, 83 uno_Interface * pUnoI, 84 typelib_InterfaceTypeDescription * pTypeDescr ) 85 SAL_THROW_EXTERN_C() 86 { 87 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 88 pMapping->mapInterface(ppOut, pUnoI, pTypeDescr); 89 } 90 91 extern "C" { 92 static void SAL_CALL s_acquire(uno_Mapping * puno_Mapping) 93 SAL_THROW_EXTERN_C() 94 { 95 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 96 pMapping->acquire(); 97 } 98 99 static void SAL_CALL s_release(uno_Mapping * puno_Mapping) 100 SAL_THROW_EXTERN_C() 101 { 102 Mapping * pMapping = static_cast<Mapping * >(puno_Mapping); 103 pMapping->release(); 104 } 105 106 107 static void s_getIdentifier_v(va_list * pParam) 108 { 109 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 110 rtl_uString ** ppOid = va_arg(*pParam, rtl_uString **); 111 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 112 113 pEnv->getObjectIdentifier(pEnv, ppOid, pUnoI); 114 } 115 116 static void SAL_CALL s_free(uno_Mapping * puno_Mapping) 117 SAL_THROW_EXTERN_C() 118 { 119 Mapping * pMapping = static_cast<Mapping *>(puno_Mapping); 120 delete pMapping; 121 } 122 } 123 124 Mapping::Mapping(uno_Environment * pFrom, 125 uno_Environment * pTo, 126 cppu::helper::purpenv::ProbeFun * probeFun, 127 void * pProbeContext 128 ) SAL_THROW( () ) 129 : m_from (pFrom), 130 m_to (pTo), 131 m_nCount (1), 132 m_probeFun(probeFun), 133 m_pContext(pProbeContext) 134 { 135 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::Mapping(uno_Environment * pFrom, uno_Environment * pTo) SAL_THROW( () )", this)); 136 137 uno_Mapping::acquire = s_acquire; 138 uno_Mapping::release = s_release; 139 uno_Mapping::mapInterface = (uno_MapInterfaceFunc)s_mapInterface; 140 } 141 142 Mapping::~Mapping(void) 143 { 144 LOG_LIFECYCLE_cppu_helper_purpenv_Mapping_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Mapping::~Mapping(void)", this)); 145 } 146 147 148 void Mapping::mapInterface( 149 uno_Interface ** ppOut, 150 uno_Interface * pUnoI, 151 typelib_InterfaceTypeDescription * pTypeDescr) 152 { 153 OSL_ASSERT(ppOut && pTypeDescr); 154 if (*ppOut) 155 { 156 (*ppOut)->release(*ppOut); 157 *ppOut = 0; 158 } 159 160 if (!pUnoI) 161 return; 162 163 // get object id of uno interface to be wrapped 164 // need to enter environment because of potential "queryInterface" call 165 rtl_uString * pOId = 0; 166 uno_Environment_invoke(m_from.get(), s_getIdentifier_v, m_from.get(), &pOId, pUnoI); 167 OSL_ASSERT(pOId); 168 169 // try to get any known interface from target environment 170 m_to.get()->pExtEnv->getRegisteredInterface(m_to.get()->pExtEnv, (void **)ppOut, pOId, pTypeDescr); 171 172 if (!*ppOut) // not yet there, register new proxy interface 173 { 174 // try to publish a new proxy (ref count initially 1) 175 uno_Interface * pProxy = new Proxy(this, 176 m_from.get(), 177 m_to.get(), 178 pUnoI, 179 pTypeDescr, 180 pOId, 181 m_probeFun, 182 m_pContext); 183 184 // proxy may be exchanged during registration 185 m_to.get()->pExtEnv->registerProxyInterface(m_to.get()->pExtEnv, 186 (void **)&pProxy, 187 Proxy_free, 188 pOId, 189 pTypeDescr); 190 191 *ppOut = pProxy; 192 } 193 194 rtl_uString_release(pOId); 195 } 196 197 198 void Mapping::acquire() SAL_THROW(()) 199 { 200 if (osl_incrementInterlockedCount(&m_nCount) == 1) 201 { 202 uno_Mapping * pMapping = this; 203 204 ::uno_registerMapping(&pMapping, s_free, m_from.get(), m_to.get(), NULL); 205 } 206 } 207 208 void Mapping::release() SAL_THROW(()) 209 { 210 if (osl_decrementInterlockedCount(&m_nCount) == 0) 211 ::uno_revokeMapping(this); 212 } 213 214 215 namespace cppu { namespace helper { namespace purpenv { 216 217 void createMapping(uno_Mapping ** ppMapping, 218 uno_Environment * pFrom, 219 uno_Environment * pTo, 220 ProbeFun * probeFun, 221 void * pContext 222 ) 223 { 224 *ppMapping = new Mapping(pFrom, pTo, probeFun, pContext); 225 226 ::uno_registerMapping(ppMapping, s_free, pFrom, pTo, NULL); 227 } 228 229 }}} 230