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_bridges.hxx" 30 31 #include "bridges/cpp_uno/shared/bridge.hxx" 32 33 #include "component.hxx" 34 35 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" 36 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 37 38 #include "com/sun/star/uno/XInterface.hpp" 39 #include "osl/diagnose.h" 40 #include "osl/interlck.h" 41 #include "rtl/ustring.h" 42 #include "sal/types.h" 43 #include "typelib/typedescription.h" 44 #include "uno/dispatcher.h" 45 #include "uno/environment.h" 46 #include "uno/mapping.h" 47 48 namespace bridges { namespace cpp_uno { namespace shared { 49 50 void freeMapping(uno_Mapping * pMapping) 51 { 52 delete static_cast< Bridge::Mapping * >( pMapping )->pBridge; 53 } 54 55 void acquireMapping(uno_Mapping * pMapping) 56 { 57 static_cast< Bridge::Mapping * >( pMapping )->pBridge->acquire(); 58 } 59 60 void releaseMapping(uno_Mapping * pMapping) 61 { 62 static_cast< Bridge::Mapping * >( pMapping )->pBridge->release(); 63 } 64 65 void cpp2unoMapping( 66 uno_Mapping * pMapping, void ** ppUnoI, void * pCppI, 67 typelib_InterfaceTypeDescription * pTypeDescr) 68 { 69 OSL_ENSURE( ppUnoI && pTypeDescr, "### null ptr!" ); 70 if (*ppUnoI) 71 { 72 (*reinterpret_cast< uno_Interface * >( *ppUnoI )->release)( 73 reinterpret_cast< uno_Interface * >( *ppUnoI ) ); 74 *ppUnoI = 0; 75 } 76 if (pCppI) 77 { 78 Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; 79 80 // get object id of interface to be wrapped 81 rtl_uString * pOId = 0; 82 (*pBridge->pCppEnv->getObjectIdentifier)( 83 pBridge->pCppEnv, &pOId, pCppI ); 84 OSL_ASSERT( pOId ); 85 86 // try to get any known interface from target environment 87 (*pBridge->pUnoEnv->getRegisteredInterface)( 88 pBridge->pUnoEnv, ppUnoI, pOId, pTypeDescr ); 89 90 if (! *ppUnoI) // no existing interface, register new proxy interface 91 { 92 // try to publish a new proxy (refcount initially 1) 93 uno_Interface * pSurrogate 94 = bridges::cpp_uno::shared::UnoInterfaceProxy::create( 95 pBridge, 96 static_cast< ::com::sun::star::uno::XInterface * >( pCppI ), 97 pTypeDescr, pOId ); 98 99 // proxy may be exchanged during registration 100 (*pBridge->pUnoEnv->registerProxyInterface)( 101 pBridge->pUnoEnv, reinterpret_cast< void ** >( &pSurrogate ), 102 freeUnoInterfaceProxy, pOId, 103 pTypeDescr ); 104 105 *ppUnoI = pSurrogate; 106 } 107 ::rtl_uString_release( pOId ); 108 } 109 } 110 111 void uno2cppMapping( 112 uno_Mapping * pMapping, void ** ppCppI, void * pUnoI, 113 typelib_InterfaceTypeDescription * pTypeDescr) 114 { 115 OSL_ASSERT( ppCppI && pTypeDescr ); 116 if (*ppCppI) 117 { 118 static_cast< ::com::sun::star::uno::XInterface * >( *ppCppI )-> 119 release(); 120 *ppCppI = 0; 121 } 122 if (pUnoI) 123 { 124 Bridge * pBridge = static_cast< Bridge::Mapping * >( pMapping )->pBridge; 125 126 // get object id of uno interface to be wrapped 127 rtl_uString * pOId = 0; 128 (*pBridge->pUnoEnv->getObjectIdentifier)( 129 pBridge->pUnoEnv, &pOId, pUnoI ); 130 OSL_ASSERT( pOId ); 131 132 // try to get any known interface from target environment 133 (*pBridge->pCppEnv->getRegisteredInterface)( 134 pBridge->pCppEnv, ppCppI, pOId, pTypeDescr ); 135 136 if (! *ppCppI) // no existing interface, register new proxy interface 137 { 138 // try to publish a new proxy (ref count initially 1) 139 com::sun::star::uno::XInterface * pProxy 140 = bridges::cpp_uno::shared::CppInterfaceProxy::create( 141 pBridge, static_cast< uno_Interface * >( pUnoI ), 142 pTypeDescr, pOId ); 143 144 // proxy may be exchanged during registration 145 (*pBridge->pCppEnv->registerProxyInterface)( 146 pBridge->pCppEnv, reinterpret_cast< void ** >( &pProxy ), 147 freeCppInterfaceProxy, pOId, 148 pTypeDescr ); 149 150 *ppCppI = pProxy; 151 } 152 ::rtl_uString_release( pOId ); 153 } 154 } 155 156 uno_Mapping * Bridge::createMapping( 157 uno_ExtEnvironment * pCppEnv, uno_ExtEnvironment * pUnoEnv, 158 bool bExportCpp2Uno) SAL_THROW(()) 159 { 160 Bridge * bridge = new Bridge(pCppEnv, pUnoEnv, bExportCpp2Uno); 161 return bExportCpp2Uno ? &bridge->aCpp2Uno : &bridge->aUno2Cpp; 162 } 163 164 void Bridge::acquire() SAL_THROW(()) 165 { 166 if (1 == osl_incrementInterlockedCount( &nRef )) 167 { 168 if (bExportCpp2Uno) 169 { 170 uno_Mapping * pMapping = &aCpp2Uno; 171 ::uno_registerMapping( 172 &pMapping, freeMapping, (uno_Environment *)pCppEnv, 173 (uno_Environment *)pUnoEnv, 0 ); 174 } 175 else 176 { 177 uno_Mapping * pMapping = &aUno2Cpp; 178 ::uno_registerMapping( 179 &pMapping, freeMapping, (uno_Environment *)pUnoEnv, 180 (uno_Environment *)pCppEnv, 0 ); 181 } 182 } 183 } 184 185 void Bridge::release() SAL_THROW(()) 186 { 187 if (! osl_decrementInterlockedCount( &nRef )) 188 { 189 ::uno_revokeMapping( bExportCpp2Uno ? &aCpp2Uno : &aUno2Cpp ); 190 } 191 } 192 193 Bridge::Bridge( 194 uno_ExtEnvironment * pCppEnv_, uno_ExtEnvironment * pUnoEnv_, 195 bool bExportCpp2Uno_) SAL_THROW(()) 196 : nRef( 1 ) 197 , pCppEnv( pCppEnv_ ) 198 , pUnoEnv( pUnoEnv_ ) 199 , bExportCpp2Uno( bExportCpp2Uno_ ) 200 { 201 bridges::cpp_uno::shared::g_moduleCount.modCnt.acquire( 202 &bridges::cpp_uno::shared::g_moduleCount.modCnt ); 203 204 aCpp2Uno.pBridge = this; 205 aCpp2Uno.acquire = acquireMapping; 206 aCpp2Uno.release = releaseMapping; 207 aCpp2Uno.mapInterface = cpp2unoMapping; 208 209 aUno2Cpp.pBridge = this; 210 aUno2Cpp.acquire = acquireMapping; 211 aUno2Cpp.release = releaseMapping; 212 aUno2Cpp.mapInterface = uno2cppMapping; 213 214 (*((uno_Environment *)pCppEnv)->acquire)( (uno_Environment *)pCppEnv ); 215 (*((uno_Environment *)pUnoEnv)->acquire)( (uno_Environment *)pUnoEnv ); 216 } 217 218 Bridge::~Bridge() SAL_THROW(()) 219 { 220 (*((uno_Environment *)pUnoEnv)->release)( (uno_Environment *)pUnoEnv ); 221 (*((uno_Environment *)pCppEnv)->release)( (uno_Environment *)pCppEnv ); 222 bridges::cpp_uno::shared::g_moduleCount.modCnt.release( 223 &bridges::cpp_uno::shared::g_moduleCount.modCnt ); 224 } 225 226 } } } 227