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_stoc.hxx" 30 31 #include "osl/diagnose.h" 32 #include "osl/interlck.h" 33 #include "osl/doublecheckedlocking.h" 34 #include "osl/mutex.hxx" 35 #include "rtl/ref.hxx" 36 #include "uno/dispatcher.hxx" 37 #include "uno/data.h" 38 #include "uno/mapping.hxx" 39 #include "uno/environment.hxx" 40 #include "typelib/typedescription.hxx" 41 #include "cppuhelper/exc_hlp.hxx" 42 #include "cppuhelper/implbase2.hxx" 43 #include "cppuhelper/implementationentry.hxx" 44 #include "cppuhelper/factory.hxx" 45 #include "com/sun/star/lang/XServiceInfo.hpp" 46 #include "com/sun/star/registry/XRegistryKey.hpp" 47 #include "com/sun/star/reflection/XProxyFactory.hpp" 48 #include "com/sun/star/uno/RuntimeException.hpp" 49 50 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 51 #define SERVICE_NAME "com.sun.star.reflection.ProxyFactory" 52 #define IMPL_NAME "com.sun.star.comp.reflection.ProxyFactory" 53 54 55 using namespace ::com::sun::star; 56 using namespace ::com::sun::star::uno; 57 using ::rtl::OUString; 58 59 60 namespace 61 { 62 63 static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; 64 65 static OUString proxyfac_getImplementationName() 66 { 67 return OUSTR(IMPL_NAME); 68 } 69 70 static Sequence< OUString > proxyfac_getSupportedServiceNames() 71 { 72 OUString str_name = OUSTR(SERVICE_NAME); 73 return Sequence< OUString >( &str_name, 1 ); 74 } 75 76 //============================================================================== 77 struct FactoryImpl : public ::cppu::WeakImplHelper2< lang::XServiceInfo, 78 reflection::XProxyFactory > 79 { 80 Environment m_uno_env; 81 Environment m_cpp_env; 82 Mapping m_uno2cpp; 83 Mapping m_cpp2uno; 84 85 UnoInterfaceReference binuno_queryInterface( 86 UnoInterfaceReference const & unoI, 87 typelib_InterfaceTypeDescription * pTypeDescr ); 88 89 FactoryImpl(); 90 virtual ~FactoryImpl(); 91 92 // XServiceInfo 93 virtual OUString SAL_CALL getImplementationName() 94 throw (RuntimeException); 95 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) 96 throw (RuntimeException); 97 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() 98 throw (RuntimeException); 99 100 // XProxyFactory 101 virtual Reference< XAggregation > SAL_CALL createProxy( 102 Reference< XInterface > const & xTarget ) 103 throw (RuntimeException); 104 }; 105 106 //______________________________________________________________________________ 107 UnoInterfaceReference FactoryImpl::binuno_queryInterface( 108 UnoInterfaceReference const & unoI, 109 typelib_InterfaceTypeDescription * pTypeDescr ) 110 { 111 // init queryInterface() td 112 static typelib_TypeDescription * s_pQITD = 0; 113 if (s_pQITD == 0) 114 { 115 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 116 if (s_pQITD == 0) 117 { 118 typelib_TypeDescription * pTXInterfaceDescr = 0; 119 TYPELIB_DANGER_GET( 120 &pTXInterfaceDescr, 121 ::getCppuType( reinterpret_cast< Reference< XInterface > 122 const * >(0) ).getTypeLibType() ); 123 typelib_TypeDescription * pQITD = 0; 124 typelib_typedescriptionreference_getDescription( 125 &pQITD, reinterpret_cast< typelib_InterfaceTypeDescription * >( 126 pTXInterfaceDescr )->ppAllMembers[ 0 ] ); 127 TYPELIB_DANGER_RELEASE( pTXInterfaceDescr ); 128 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 129 s_pQITD = pQITD; 130 } 131 } 132 else 133 { 134 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 135 } 136 137 void * args[ 1 ]; 138 args[ 0 ] = &reinterpret_cast< typelib_TypeDescription * >( 139 pTypeDescr )->pWeakRef; 140 uno_Any ret_val, exc_space; 141 uno_Any * exc = &exc_space; 142 143 unoI.dispatch( s_pQITD, &ret_val, args, &exc ); 144 145 if (exc == 0) 146 { 147 UnoInterfaceReference ret; 148 if (ret_val.pType->eTypeClass == typelib_TypeClass_INTERFACE) 149 { 150 ret.set( *reinterpret_cast< uno_Interface ** >(ret_val.pData), 151 SAL_NO_ACQUIRE ); 152 typelib_typedescriptionreference_release( ret_val.pType ); 153 } 154 else 155 { 156 uno_any_destruct( &ret_val, 0 ); 157 } 158 return ret; 159 } 160 else 161 { 162 // exception occured: 163 OSL_ENSURE( 164 typelib_typedescriptionreference_isAssignableFrom( 165 ::getCppuType( reinterpret_cast< 166 RuntimeException const * >(0) ).getTypeLibType(), 167 exc->pType ), 168 "### RuntimeException expected!" ); 169 Any cpp_exc; 170 uno_type_copyAndConvertData( 171 &cpp_exc, exc, ::getCppuType( &cpp_exc ).getTypeLibType(), 172 m_uno2cpp.get() ); 173 uno_any_destruct( exc, 0 ); 174 ::cppu::throwException( cpp_exc ); 175 OSL_ASSERT( 0 ); // way of no return 176 return UnoInterfaceReference(); // for dummy 177 } 178 } 179 180 //============================================================================== 181 struct ProxyRoot : public ::cppu::OWeakAggObject 182 { 183 // XAggregation 184 virtual Any SAL_CALL queryAggregation( Type const & rType ) 185 throw (RuntimeException); 186 187 virtual ~ProxyRoot(); 188 inline ProxyRoot( ::rtl::Reference< FactoryImpl > const & factory, 189 Reference< XInterface > const & xTarget ); 190 191 ::rtl::Reference< FactoryImpl > m_factory; 192 193 private: 194 UnoInterfaceReference m_target; 195 }; 196 197 //============================================================================== 198 struct binuno_Proxy : public uno_Interface 199 { 200 oslInterlockedCount m_nRefCount; 201 ::rtl::Reference< ProxyRoot > m_root; 202 UnoInterfaceReference m_target; 203 OUString m_oid; 204 TypeDescription m_typeDescr; 205 206 inline binuno_Proxy( 207 ::rtl::Reference< ProxyRoot > const & root, 208 UnoInterfaceReference const & target, 209 OUString const & oid, TypeDescription const & typeDescr ); 210 }; 211 212 extern "C" 213 { 214 215 //------------------------------------------------------------------------------ 216 static void SAL_CALL binuno_proxy_free( 217 uno_ExtEnvironment * pEnv, void * pProxy ) 218 { 219 (void) pEnv; // avoid warning about unused parameter 220 binuno_Proxy * proxy = static_cast< binuno_Proxy * >( 221 reinterpret_cast< uno_Interface * >( pProxy ) ); 222 OSL_ASSERT( proxy->m_root->m_factory->m_uno_env.get()->pExtEnv == pEnv ); 223 delete proxy; 224 } 225 226 //------------------------------------------------------------------------------ 227 static void SAL_CALL binuno_proxy_acquire( uno_Interface * pUnoI ) 228 { 229 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); 230 if (osl_incrementInterlockedCount( &that->m_nRefCount ) == 1) 231 { 232 // rebirth of zombie 233 uno_ExtEnvironment * uno_env = 234 that->m_root->m_factory->m_uno_env.get()->pExtEnv; 235 OSL_ASSERT( uno_env != 0 ); 236 (*uno_env->registerProxyInterface)( 237 uno_env, reinterpret_cast< void ** >( &pUnoI ), binuno_proxy_free, 238 that->m_oid.pData, 239 reinterpret_cast< typelib_InterfaceTypeDescription * >( 240 that->m_typeDescr.get() ) ); 241 OSL_ASSERT( that == static_cast< binuno_Proxy * >( pUnoI ) ); 242 } 243 } 244 245 //------------------------------------------------------------------------------ 246 static void SAL_CALL binuno_proxy_release( uno_Interface * pUnoI ) 247 { 248 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); 249 if (osl_decrementInterlockedCount( &that->m_nRefCount ) == 0) 250 { 251 uno_ExtEnvironment * uno_env = 252 that->m_root->m_factory->m_uno_env.get()->pExtEnv; 253 OSL_ASSERT( uno_env != 0 ); 254 (*uno_env->revokeInterface)( uno_env, pUnoI ); 255 } 256 } 257 258 //------------------------------------------------------------------------------ 259 static void SAL_CALL binuno_proxy_dispatch( 260 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType, 261 void * pReturn, void * pArgs [], uno_Any ** ppException ) 262 { 263 binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); 264 switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription const * >( 265 pMemberType )->nPosition) 266 { 267 case 0: // queryInterface() 268 { 269 try 270 { 271 Type const & rType = 272 *reinterpret_cast< Type const * >( pArgs[ 0 ] ); 273 Any ret( that->m_root->queryInterface( rType ) ); 274 uno_type_copyAndConvertData( 275 pReturn, &ret, ::getCppuType( &ret ).getTypeLibType(), 276 that->m_root->m_factory->m_cpp2uno.get() ); 277 *ppException = 0; // no exc 278 } 279 catch (RuntimeException &) 280 { 281 Any exc( ::cppu::getCaughtException() ); 282 uno_type_any_constructAndConvert( 283 *ppException, const_cast< void * >(exc.getValue()), 284 exc.getValueTypeRef(), 285 that->m_root->m_factory->m_cpp2uno.get() ); 286 } 287 break; 288 } 289 case 1: // acquire() 290 binuno_proxy_acquire( pUnoI ); 291 *ppException = 0; // no exc 292 break; 293 case 2: // release() 294 binuno_proxy_release( pUnoI ); 295 *ppException = 0; // no exc 296 break; 297 default: 298 that->m_target.dispatch( pMemberType, pReturn, pArgs, ppException ); 299 break; 300 } 301 } 302 303 } 304 305 //______________________________________________________________________________ 306 inline binuno_Proxy::binuno_Proxy( 307 ::rtl::Reference< ProxyRoot > const & root, 308 UnoInterfaceReference const & target, 309 OUString const & oid, TypeDescription const & typeDescr ) 310 : m_nRefCount( 1 ), 311 m_root( root ), 312 m_target( target ), 313 m_oid( oid ), 314 m_typeDescr( typeDescr ) 315 { 316 uno_Interface::acquire = binuno_proxy_acquire; 317 uno_Interface::release = binuno_proxy_release; 318 uno_Interface::pDispatcher = binuno_proxy_dispatch; 319 } 320 321 //______________________________________________________________________________ 322 ProxyRoot::~ProxyRoot() 323 { 324 } 325 326 //______________________________________________________________________________ 327 inline ProxyRoot::ProxyRoot( 328 ::rtl::Reference< FactoryImpl > const & factory, 329 Reference< XInterface > const & xTarget ) 330 : m_factory( factory ) 331 { 332 m_factory->m_cpp2uno.mapInterface( 333 reinterpret_cast< void ** >( &m_target.m_pUnoI ), xTarget.get(), 334 ::getCppuType( &xTarget ) ); 335 OSL_ENSURE( m_target.is(), "### mapping interface failed!" ); 336 } 337 338 //______________________________________________________________________________ 339 Any ProxyRoot::queryAggregation( Type const & rType ) 340 throw (RuntimeException) 341 { 342 Any ret( OWeakAggObject::queryAggregation( rType ) ); 343 if (! ret.hasValue()) 344 { 345 typelib_TypeDescription * pTypeDescr = 0; 346 TYPELIB_DANGER_GET( &pTypeDescr, rType.getTypeLibType() ); 347 try 348 { 349 Reference< XInterface > xProxy; 350 uno_ExtEnvironment * cpp_env = m_factory->m_cpp_env.get()->pExtEnv; 351 OSL_ASSERT( cpp_env != 0 ); 352 353 // mind a new delegator, calculate current root: 354 Reference< XInterface > xRoot( 355 static_cast< OWeakObject * >(this), UNO_QUERY_THROW ); 356 OUString oid; 357 (*cpp_env->getObjectIdentifier)( cpp_env, &oid.pData, xRoot.get() ); 358 OSL_ASSERT( oid.getLength() > 0 ); 359 360 (*cpp_env->getRegisteredInterface)( 361 cpp_env, reinterpret_cast< void ** >( &xProxy ), 362 oid.pData, reinterpret_cast< 363 typelib_InterfaceTypeDescription * >(pTypeDescr) ); 364 if (! xProxy.is()) 365 { 366 // perform query on target: 367 UnoInterfaceReference proxy_target( 368 m_factory->binuno_queryInterface( 369 m_target, reinterpret_cast< 370 typelib_InterfaceTypeDescription * >(pTypeDescr) ) ); 371 if (proxy_target.is()) 372 { 373 // ensure root's object entries: 374 UnoInterfaceReference root; 375 m_factory->m_cpp2uno.mapInterface( 376 reinterpret_cast< void ** >( &root.m_pUnoI ), 377 xRoot.get(), ::getCppuType( &xRoot ) ); 378 379 UnoInterfaceReference proxy( 380 // ref count initially 1: 381 new binuno_Proxy( this, proxy_target, oid, pTypeDescr ), 382 SAL_NO_ACQUIRE ); 383 uno_ExtEnvironment * uno_env = 384 m_factory->m_uno_env.get()->pExtEnv; 385 OSL_ASSERT( uno_env != 0 ); 386 (*uno_env->registerProxyInterface)( 387 uno_env, reinterpret_cast< void ** >( &proxy.m_pUnoI ), 388 binuno_proxy_free, oid.pData, 389 reinterpret_cast< typelib_InterfaceTypeDescription * >( 390 pTypeDescr ) ); 391 392 m_factory->m_uno2cpp.mapInterface( 393 reinterpret_cast< void ** >( &xProxy ), 394 proxy.get(), pTypeDescr ); 395 } 396 } 397 if (xProxy.is()) 398 ret.setValue( &xProxy, pTypeDescr ); 399 } 400 catch (...) // finally 401 { 402 TYPELIB_DANGER_RELEASE( pTypeDescr ); 403 throw; 404 } 405 TYPELIB_DANGER_RELEASE( pTypeDescr ); 406 } 407 return ret; 408 } 409 410 //############################################################################## 411 412 //______________________________________________________________________________ 413 FactoryImpl::FactoryImpl() 414 { 415 OUString uno = OUSTR(UNO_LB_UNO); 416 OUString cpp = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); 417 418 uno_getEnvironment( 419 reinterpret_cast< uno_Environment ** >( &m_uno_env ), uno.pData, 0 ); 420 OSL_ENSURE( m_uno_env.is(), "### cannot get binary uno env!" ); 421 422 uno_getEnvironment( 423 reinterpret_cast< uno_Environment ** >( &m_cpp_env ), cpp.pData, 0 ); 424 OSL_ENSURE( m_cpp_env.is(), "### cannot get C++ uno env!" ); 425 426 uno_getMapping( 427 reinterpret_cast< uno_Mapping ** >( &m_uno2cpp ), 428 m_uno_env.get(), m_cpp_env.get(), 0 ); 429 OSL_ENSURE( m_uno2cpp.is(), "### cannot get bridge uno <-> C++!" ); 430 431 uno_getMapping( 432 reinterpret_cast< uno_Mapping ** >( &m_cpp2uno ), 433 m_cpp_env.get(), m_uno_env.get(), 0 ); 434 OSL_ENSURE( m_cpp2uno.is(), "### cannot get bridge C++ <-> uno!" ); 435 436 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 437 } 438 439 //______________________________________________________________________________ 440 FactoryImpl::~FactoryImpl() 441 { 442 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 443 } 444 445 // XProxyFactory 446 //______________________________________________________________________________ 447 Reference< XAggregation > FactoryImpl::createProxy( 448 Reference< XInterface > const & xTarget ) 449 throw (RuntimeException) 450 { 451 return new ProxyRoot( this, xTarget ); 452 } 453 454 // XServiceInfo 455 //______________________________________________________________________________ 456 OUString FactoryImpl::getImplementationName() 457 throw (RuntimeException) 458 { 459 return proxyfac_getImplementationName();; 460 } 461 462 //______________________________________________________________________________ 463 sal_Bool FactoryImpl::supportsService( const OUString & rServiceName ) 464 throw (RuntimeException) 465 { 466 Sequence< OUString > const & rSNL = getSupportedServiceNames(); 467 OUString const * pArray = rSNL.getConstArray(); 468 for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) 469 { 470 if (rServiceName.equals( pArray[ nPos ] )) 471 return true; 472 } 473 return false; 474 } 475 476 //______________________________________________________________________________ 477 Sequence< OUString > FactoryImpl::getSupportedServiceNames() 478 throw(::com::sun::star::uno::RuntimeException) 479 { 480 return proxyfac_getSupportedServiceNames(); 481 } 482 483 //============================================================================== 484 static Reference< XInterface > SAL_CALL proxyfac_create( 485 Reference< XComponentContext > const & ) 486 throw (Exception) 487 { 488 Reference< XInterface > xRet; 489 { 490 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); 491 static WeakReference < XInterface > rwInstance; 492 xRet = rwInstance; 493 494 if (! xRet.is()) 495 { 496 xRet = static_cast< ::cppu::OWeakObject * >(new FactoryImpl); 497 rwInstance = xRet; 498 } 499 } 500 return xRet; 501 } 502 503 static ::cppu::ImplementationEntry g_entries [] = 504 { 505 { 506 proxyfac_create, proxyfac_getImplementationName, 507 proxyfac_getSupportedServiceNames, ::cppu::createSingleComponentFactory, 508 &g_moduleCount.modCnt, 0 509 }, 510 { 0, 0, 0, 0, 0, 0 } 511 }; 512 513 } 514 515 extern "C" 516 { 517 518 sal_Bool SAL_CALL component_canUnload( TimeValue * pTime ) 519 { 520 return g_moduleCount.canUnload( &g_moduleCount, pTime ); 521 } 522 523 void SAL_CALL component_getImplementationEnvironment( 524 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 525 { 526 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 527 } 528 529 void * SAL_CALL component_getFactory( 530 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 531 { 532 return ::cppu::component_getFactoryHelper( 533 pImplName, pServiceManager, pRegistryKey, g_entries ); 534 } 535 536 } 537 538