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_testtools.hxx" 30 #include <osl/diagnose.h> 31 #include <osl/interlck.h> 32 #include <rtl/ustring.hxx> 33 #include <typelib/typedescription.h> 34 #include <uno/dispatcher.h> 35 #include <uno/environment.h> 36 #include <uno/mapping.h> 37 #include <uno/lbnames.h> 38 39 using namespace rtl; 40 41 42 namespace pseudo_uno 43 { 44 45 //================================================================================================== 46 struct pseudo_Mapping : public uno_Mapping 47 { 48 oslInterlockedCount nRef; 49 50 uno_ExtEnvironment * pFrom; 51 uno_ExtEnvironment * pTo; 52 53 pseudo_Mapping( uno_ExtEnvironment * pFrom_, uno_ExtEnvironment * pTo_ ); 54 ~pseudo_Mapping(); 55 }; 56 57 //==== a uno pseudo proxy ============================================================================= 58 struct pseudo_unoInterfaceProxy : public uno_Interface 59 { 60 oslInterlockedCount nRef; 61 pseudo_Mapping * pPseudoMapping; 62 63 // mapping information 64 uno_Interface * pUnoI; // wrapped interface 65 typelib_InterfaceTypeDescription * pTypeDescr; 66 OUString oid; 67 68 // ctor 69 inline pseudo_unoInterfaceProxy( pseudo_Mapping * pPseudoMapping_, 70 uno_Interface * pUnoI_, 71 typelib_InterfaceTypeDescription * pTypeDescr_, 72 const OUString & rOId_ ); 73 }; 74 //-------------------------------------------------------------------------------------------------- 75 static void SAL_CALL pseudo_unoInterfaceProxy_dispatch( 76 uno_Interface * pUnoI, 77 const typelib_TypeDescription * pMemberType, 78 void * pReturn, 79 void * pArgs[], 80 uno_Any ** ppException ) 81 { 82 pseudo_unoInterfaceProxy * pThis = static_cast< pseudo_unoInterfaceProxy * >( pUnoI ); 83 (*pThis->pUnoI->pDispatcher)( pThis->pUnoI, pMemberType, pReturn, pArgs, ppException ); 84 } 85 86 //-------------------------------------------------------------------------------------------------- 87 static void SAL_CALL pseudo_unoInterfaceProxy_free( uno_ExtEnvironment * pEnv, void * pProxy ) 88 { 89 pseudo_unoInterfaceProxy * pThis = 90 static_cast< pseudo_unoInterfaceProxy * >( 91 reinterpret_cast< uno_Interface * >( pProxy ) ); 92 OSL_ASSERT( pEnv == pThis->pPseudoMapping->pTo ); 93 94 (*pThis->pPseudoMapping->pFrom->revokeInterface)( pThis->pPseudoMapping->pFrom, pThis->pUnoI ); 95 (*pThis->pUnoI->release)( pThis->pUnoI ); 96 typelib_typedescription_release( (typelib_TypeDescription *)pThis->pTypeDescr ); 97 (*pThis->pPseudoMapping->release)( pThis->pPseudoMapping ); 98 99 #if OSL_DEBUG_LEVEL > 1 100 *(int *)pProxy = 0xdeadbabe; 101 #endif 102 delete pThis; 103 } 104 //-------------------------------------------------------------------------------------------------- 105 static void SAL_CALL pseudo_unoInterfaceProxy_acquire( uno_Interface * pUnoI ) 106 { 107 if (1 == osl_incrementInterlockedCount( &static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->nRef )) 108 { 109 // rebirth of proxy zombie 110 // register at uno env 111 void * pThis = static_cast< uno_Interface * >( pUnoI ); 112 (*static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo->registerProxyInterface)( 113 static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo, 114 &pThis, pseudo_unoInterfaceProxy_free, 115 static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->oid.pData, 116 static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pTypeDescr ); 117 OSL_ASSERT( pThis == static_cast< uno_Interface * >( pUnoI ) ); 118 } 119 } 120 //-------------------------------------------------------------------------------------------------- 121 static void SAL_CALL pseudo_unoInterfaceProxy_release( uno_Interface * pUnoI ) 122 { 123 if (! osl_decrementInterlockedCount( & static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->nRef )) 124 { 125 // revoke from uno env on last release 126 (*static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo->revokeInterface)( 127 static_cast< pseudo_unoInterfaceProxy * >( pUnoI )->pPseudoMapping->pTo, pUnoI ); 128 } 129 } 130 //__________________________________________________________________________________________________ 131 inline pseudo_unoInterfaceProxy::pseudo_unoInterfaceProxy( 132 pseudo_Mapping * pPseudoMapping_, uno_Interface * pUnoI_, 133 typelib_InterfaceTypeDescription * pTypeDescr_, const OUString & rOId_ ) 134 : nRef( 1 ) 135 , pPseudoMapping( pPseudoMapping_ ) 136 , pUnoI( pUnoI_ ) 137 , pTypeDescr( pTypeDescr_ ) 138 , oid( rOId_ ) 139 { 140 (*pPseudoMapping->acquire)( pPseudoMapping ); 141 typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr ); 142 (*pPseudoMapping->pFrom->registerInterface)( 143 pPseudoMapping->pFrom, reinterpret_cast< void ** >( &pUnoI ), oid.pData, pTypeDescr ); 144 (*pUnoI->acquire)( pUnoI ); 145 146 // uno_Interface 147 uno_Interface::acquire = pseudo_unoInterfaceProxy_acquire; 148 uno_Interface::release = pseudo_unoInterfaceProxy_release; 149 uno_Interface::pDispatcher = pseudo_unoInterfaceProxy_dispatch; 150 } 151 152 //-------------------------------------------------------------------------------------------------- 153 static void SAL_CALL pseudo_Mapping_mapInterface( 154 uno_Mapping * pMapping, void ** ppOut, 155 void * pUnoI, typelib_InterfaceTypeDescription * pTypeDescr ) 156 { 157 OSL_ASSERT( ppOut && pTypeDescr ); 158 if (*ppOut) 159 { 160 (*reinterpret_cast< uno_Interface * >( *ppOut )->release)( 161 reinterpret_cast< uno_Interface * >( *ppOut ) ); 162 *ppOut = 0; 163 } 164 if (pUnoI && pTypeDescr) 165 { 166 // get object id of uno interface to be wrapped 167 rtl_uString * pOId = 0; 168 (*static_cast< pseudo_Mapping * >( pMapping )->pFrom->getObjectIdentifier)( 169 static_cast< pseudo_Mapping * >( pMapping )->pFrom, &pOId, pUnoI ); 170 OSL_ASSERT( pOId ); 171 172 if (pOId) 173 { 174 // try to get any known interface from target environment 175 (*static_cast< pseudo_Mapping * >( pMapping )->pTo->getRegisteredInterface)( 176 static_cast< pseudo_Mapping * >( pMapping )->pTo, ppOut, pOId, pTypeDescr ); 177 if (! *ppOut) // no existing interface, register new proxy interface 178 { 179 // try to publish a new proxy (ref count initially 1) 180 void * pProxy = new pseudo_unoInterfaceProxy( 181 static_cast< pseudo_Mapping * >( pMapping ), 182 reinterpret_cast< uno_Interface * >( pUnoI ), pTypeDescr, pOId ); 183 184 // proxy may be exchanged during registration 185 (*static_cast< pseudo_Mapping * >( pMapping )->pTo->registerProxyInterface)( 186 static_cast< pseudo_Mapping * >( pMapping )->pTo, 187 &pProxy, pseudo_unoInterfaceProxy_free, pOId, pTypeDescr ); 188 189 *ppOut = pProxy; 190 } 191 rtl_uString_release( pOId ); 192 } 193 } 194 } 195 //-------------------------------------------------------------------------------------------------- 196 static void SAL_CALL pseudo_Mapping_free( uno_Mapping * pMapping ) 197 { 198 delete static_cast< pseudo_Mapping * >( pMapping ); 199 } 200 //-------------------------------------------------------------------------------------------------- 201 static void SAL_CALL pseudo_Mapping_acquire( uno_Mapping * pMapping ) 202 { 203 if (1 == osl_incrementInterlockedCount( & static_cast< pseudo_Mapping * >( pMapping )->nRef )) 204 { 205 OUString aMappingPurpose( RTL_CONSTASCII_USTRINGPARAM("pseudo") ); 206 uno_registerMapping( &pMapping, 207 pseudo_Mapping_free, 208 (uno_Environment *)((pseudo_Mapping *)pMapping)->pFrom, 209 (uno_Environment *)((pseudo_Mapping *)pMapping)->pTo, 210 aMappingPurpose.pData ); 211 } 212 } 213 //-------------------------------------------------------------------------------------------------- 214 static void SAL_CALL pseudo_Mapping_release( uno_Mapping * pMapping ) 215 { 216 if (! osl_decrementInterlockedCount( & static_cast< pseudo_Mapping * >( pMapping )->nRef )) 217 { 218 uno_revokeMapping( pMapping ); 219 } 220 } 221 222 //__________________________________________________________________________________________________ 223 pseudo_Mapping::pseudo_Mapping( uno_ExtEnvironment * pFrom_, uno_ExtEnvironment * pTo_ ) 224 : nRef( 1 ) 225 , pFrom( pFrom_ ) 226 , pTo( pTo_ ) 227 { 228 (*((uno_Environment *)pFrom)->acquire)( (uno_Environment *)pFrom ); 229 (*((uno_Environment *)pTo)->acquire)( (uno_Environment *)pTo ); 230 // 231 uno_Mapping::acquire = pseudo_Mapping_acquire; 232 uno_Mapping::release = pseudo_Mapping_release; 233 uno_Mapping::mapInterface = pseudo_Mapping_mapInterface; 234 } 235 //__________________________________________________________________________________________________ 236 pseudo_Mapping::~pseudo_Mapping() 237 { 238 (*((uno_Environment *)pTo)->release)( (uno_Environment *)pTo ); 239 (*((uno_Environment *)pFrom)->release)( (uno_Environment *)pFrom ); 240 } 241 242 } 243 244 //################################################################################################## 245 extern "C" void SAL_CALL uno_initEnvironment( uno_Environment * pUnoEnv ) 246 { 247 OSL_ENSURE( sal_False, "### no impl: unexpected call!" ); 248 } 249 //################################################################################################## 250 extern "C" void SAL_CALL uno_ext_getMapping( 251 uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) 252 { 253 OSL_ASSERT( ppMapping && pFrom && pTo ); 254 if (ppMapping && pFrom && pTo && pFrom->pExtEnv && pTo->pExtEnv) 255 { 256 uno_Mapping * pMapping = 0; 257 258 if (0 == rtl_ustr_ascii_compare( pFrom->pTypeName->buffer, UNO_LB_UNO ) && 259 0 == rtl_ustr_ascii_compare( pTo->pTypeName->buffer, UNO_LB_UNO )) 260 { 261 OUString aMappingPurpose( RTL_CONSTASCII_USTRINGPARAM("pseudo") ); 262 // ref count is initially 1 263 pMapping = new pseudo_uno::pseudo_Mapping( pFrom->pExtEnv, pTo->pExtEnv ); 264 uno_registerMapping( &pMapping, pseudo_uno::pseudo_Mapping_free, 265 (uno_Environment *)pFrom->pExtEnv, 266 (uno_Environment *)pTo->pExtEnv, 267 aMappingPurpose.pData ); 268 } 269 270 if (*ppMapping) 271 (*(*ppMapping)->release)( *ppMapping ); 272 *ppMapping = pMapping; 273 } 274 } 275