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