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_cppuhelper.hxx" 30 31 #ifdef DIAG 32 #define CONTEXT_DIAG 33 #endif 34 35 #if OSL_DEBUG_LEVEL > 0 36 #include <stdio.h> 37 #endif 38 39 #include <vector> 40 #include <hash_map> 41 #ifdef CONTEXT_DIAG 42 #include <map> 43 #endif 44 45 #include <osl/diagnose.h> 46 #include <osl/mutex.hxx> 47 48 #include <rtl/ustrbuf.hxx> 49 50 #include <uno/mapping.hxx> 51 52 #include <cppuhelper/implbase1.hxx> 53 #include <cppuhelper/compbase2.hxx> 54 #include <cppuhelper/component_context.hxx> 55 #include <cppuhelper/exc_hlp.hxx> 56 57 #include <com/sun/star/container/XNameContainer.hpp> 58 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 59 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 60 #include <com/sun/star/lang/XSingleComponentFactory.hpp> 61 #include <com/sun/star/lang/XMultiComponentFactory.hpp> 62 #include <com/sun/star/lang/XComponent.hpp> 63 #include <com/sun/star/beans/XPropertySet.hpp> 64 #include "com/sun/star/uno/RuntimeException.hpp" 65 66 #include <hash_map> 67 #include <memory> 68 69 #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager" 70 #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager" 71 #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController" 72 #define AC_POLICY "/singletons/com.sun.star.security.thePolicy" 73 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 74 75 76 using namespace ::osl; 77 using namespace ::rtl; 78 using namespace ::com::sun::star::uno; 79 using namespace ::com::sun::star; 80 81 namespace cppu 82 { 83 84 #ifdef CONTEXT_DIAG 85 //-------------------------------------------------------------------------------------------------- 86 static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef ) 87 { 88 OSL_ASSERT( pVal ); 89 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID) 90 return OUSTR("void"); 91 92 OUStringBuffer buf( 64 ); 93 buf.append( (sal_Unicode)'(' ); 94 buf.append( pTypeRef->pTypeName ); 95 buf.append( (sal_Unicode)')' ); 96 97 switch (pTypeRef->eTypeClass) 98 { 99 case typelib_TypeClass_INTERFACE: 100 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 101 buf.append( (sal_Int64)*(void **)pVal, 16 ); 102 break; 103 case typelib_TypeClass_STRUCT: 104 case typelib_TypeClass_EXCEPTION: 105 { 106 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 107 typelib_TypeDescription * pTypeDescr = 0; 108 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef ); 109 OSL_ASSERT( pTypeDescr ); 110 if (! pTypeDescr->bComplete) 111 ::typelib_typedescription_complete( &pTypeDescr ); 112 113 typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr; 114 sal_Int32 nDescr = pCompType->nMembers; 115 116 if (pCompType->pBaseTypeDescription) 117 { 118 buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) ); 119 if (nDescr) 120 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 121 } 122 123 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs; 124 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets; 125 rtl_uString ** ppMemberNames = pCompType->ppMemberNames; 126 127 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) 128 { 129 buf.append( ppMemberNames[ nPos ] ); 130 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") ); 131 typelib_TypeDescription * pMemberType = 0; 132 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] ); 133 buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) ); 134 TYPELIB_DANGER_RELEASE( pMemberType ); 135 if (nPos < (nDescr -1)) 136 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 137 } 138 139 ::typelib_typedescription_release( pTypeDescr ); 140 141 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 142 break; 143 } 144 case typelib_TypeClass_SEQUENCE: 145 { 146 typelib_TypeDescription * pTypeDescr = 0; 147 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); 148 149 uno_Sequence * pSequence = *(uno_Sequence **)pVal; 150 typelib_TypeDescription * pElementTypeDescr = 0; 151 TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); 152 153 sal_Int32 nElementSize = pElementTypeDescr->nSize; 154 sal_Int32 nElements = pSequence->nElements; 155 156 if (nElements) 157 { 158 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 159 char * pElements = pSequence->elements; 160 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) 161 { 162 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) ); 163 if (nPos < (nElements -1)) 164 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); 165 } 166 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 167 } 168 else 169 { 170 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") ); 171 } 172 TYPELIB_DANGER_RELEASE( pElementTypeDescr ); 173 TYPELIB_DANGER_RELEASE( pTypeDescr ); 174 break; 175 } 176 case typelib_TypeClass_ANY: 177 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); 178 buf.append( val2str( ((uno_Any *)pVal)->pData, 179 ((uno_Any *)pVal)->pType ) ); 180 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); 181 break; 182 case typelib_TypeClass_TYPE: 183 buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName ); 184 break; 185 case typelib_TypeClass_STRING: 186 buf.append( (sal_Unicode)'\"' ); 187 buf.append( *(rtl_uString **)pVal ); 188 buf.append( (sal_Unicode)'\"' ); 189 break; 190 case typelib_TypeClass_ENUM: 191 { 192 typelib_TypeDescription * pTypeDescr = 0; 193 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef ); 194 OSL_ASSERT( pTypeDescr ); 195 if (! pTypeDescr->bComplete) 196 ::typelib_typedescription_complete( &pTypeDescr ); 197 198 sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues; 199 sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues; 200 while (nPos--) 201 { 202 if (pValues[ nPos ] == *(sal_Int32 *)pVal) 203 break; 204 } 205 if (nPos >= 0) 206 buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] ); 207 else 208 buf.append( (sal_Unicode)'?' ); 209 210 ::typelib_typedescription_release( pTypeDescr ); 211 break; 212 } 213 case typelib_TypeClass_BOOLEAN: 214 if (*(sal_Bool *)pVal) 215 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") ); 216 else 217 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") ); 218 break; 219 case typelib_TypeClass_CHAR: 220 buf.append( (sal_Unicode)'\'' ); 221 buf.append( *(sal_Unicode *)pVal ); 222 buf.append( (sal_Unicode)'\'' ); 223 break; 224 case typelib_TypeClass_FLOAT: 225 buf.append( *(float *)pVal ); 226 break; 227 case typelib_TypeClass_DOUBLE: 228 buf.append( *(double *)pVal ); 229 break; 230 case typelib_TypeClass_BYTE: 231 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 232 buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 ); 233 break; 234 case typelib_TypeClass_SHORT: 235 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 236 buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 ); 237 break; 238 case typelib_TypeClass_UNSIGNED_SHORT: 239 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 240 buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 ); 241 break; 242 case typelib_TypeClass_LONG: 243 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 244 buf.append( *(sal_Int32 *)pVal, 16 ); 245 break; 246 case typelib_TypeClass_UNSIGNED_LONG: 247 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 248 buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 ); 249 break; 250 case typelib_TypeClass_HYPER: 251 case typelib_TypeClass_UNSIGNED_HYPER: 252 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); 253 #if defined(GCC) && defined(SPARC) 254 { 255 sal_Int64 aVal; 256 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal; 257 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1); 258 buf.append( aVal, 16 ); 259 } 260 #else 261 buf.append( *(sal_Int64 *)pVal, 16 ); 262 #endif 263 break; 264 default: 265 buf.append( (sal_Unicode)'?' ); 266 } 267 268 return buf.makeStringAndClear(); 269 } 270 //-------------------------------------------------------------------------------------------------- 271 static void dumpEntry( OUString const & key, Any const & value ) 272 { 273 OUString val( val2str( value.getValue(), value.getValueTypeRef() ) ); 274 OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) ); 275 OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) ); 276 ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() ); 277 } 278 #endif 279 //-------------------------------------------------------------------------------------------------- 280 static inline void try_dispose( Reference< XInterface > const & xInstance ) 281 SAL_THROW( (RuntimeException) ) 282 { 283 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY ); 284 if (xComp.is()) 285 { 286 xComp->dispose(); 287 } 288 } 289 //-------------------------------------------------------------------------------------------------- 290 static inline void try_dispose( Reference< lang::XComponent > const & xComp ) 291 SAL_THROW( (RuntimeException) ) 292 { 293 if (xComp.is()) 294 { 295 xComp->dispose(); 296 } 297 } 298 299 //================================================================================================== 300 301 class DisposingForwarder 302 : public WeakImplHelper1< lang::XEventListener > 303 { 304 Reference< lang::XComponent > m_xTarget; 305 306 inline DisposingForwarder( Reference< lang::XComponent > const & xTarget ) 307 SAL_THROW( () ) 308 : m_xTarget( xTarget ) 309 { OSL_ASSERT( m_xTarget.is() ); } 310 public: 311 // listens at source for disposing, then disposes target 312 static inline void listen( 313 Reference< lang::XComponent > const & xSource, 314 Reference< lang::XComponent > const & xTarget ) 315 SAL_THROW( (RuntimeException) ); 316 317 virtual void SAL_CALL disposing( lang::EventObject const & rSource ) 318 throw (RuntimeException); 319 }; 320 //__________________________________________________________________________________________________ 321 inline void DisposingForwarder::listen( 322 Reference< lang::XComponent > const & xSource, 323 Reference< lang::XComponent > const & xTarget ) 324 SAL_THROW( (RuntimeException) ) 325 { 326 if (xSource.is()) 327 { 328 xSource->addEventListener( new DisposingForwarder( xTarget ) ); 329 } 330 } 331 //__________________________________________________________________________________________________ 332 void DisposingForwarder::disposing( lang::EventObject const & ) 333 throw (RuntimeException) 334 { 335 m_xTarget->dispose(); 336 m_xTarget.clear(); 337 } 338 339 //================================================================================================== 340 struct MutexHolder 341 { 342 protected: 343 Mutex m_mutex; 344 }; 345 //================================================================================================== 346 347 class ComponentContext 348 : private MutexHolder 349 , public WeakComponentImplHelper2< XComponentContext, 350 container::XNameContainer > 351 { 352 protected: 353 Reference< XComponentContext > m_xDelegate; 354 355 struct ContextEntry 356 { 357 Any value; 358 bool lateInit; 359 360 inline ContextEntry( Any const & value_, bool lateInit_ ) 361 : value( value_ ) 362 , lateInit( lateInit_ ) 363 {} 364 }; 365 typedef ::std::hash_map< OUString, ContextEntry * , OUStringHash > t_map; 366 t_map m_map; 367 368 Reference< lang::XMultiComponentFactory > m_xSMgr; 369 370 protected: 371 Any lookupMap( OUString const & rName ) 372 SAL_THROW( (RuntimeException) ); 373 374 virtual void SAL_CALL disposing(); 375 public: 376 ComponentContext( 377 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 378 Reference< XComponentContext > const & xDelegate ); 379 virtual ~ComponentContext() 380 SAL_THROW( () ); 381 382 // XComponentContext 383 virtual Any SAL_CALL getValueByName( OUString const & rName ) 384 throw (RuntimeException); 385 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager() 386 throw (RuntimeException); 387 388 // XNameContainer 389 virtual void SAL_CALL insertByName( 390 OUString const & name, Any const & element ) 391 throw (lang::IllegalArgumentException, container::ElementExistException, 392 lang::WrappedTargetException, RuntimeException); 393 virtual void SAL_CALL removeByName( OUString const & name ) 394 throw (container::NoSuchElementException, 395 lang::WrappedTargetException, RuntimeException); 396 // XNameReplace 397 virtual void SAL_CALL replaceByName( 398 OUString const & name, Any const & element ) 399 throw (lang::IllegalArgumentException,container::NoSuchElementException, 400 lang::WrappedTargetException, RuntimeException); 401 // XNameAccess 402 virtual Any SAL_CALL getByName( OUString const & name ) 403 throw (container::NoSuchElementException, 404 lang::WrappedTargetException, RuntimeException); 405 virtual Sequence<OUString> SAL_CALL getElementNames() 406 throw (RuntimeException); 407 virtual sal_Bool SAL_CALL hasByName( OUString const & name ) 408 throw (RuntimeException); 409 // XElementAccess 410 virtual Type SAL_CALL getElementType() throw (RuntimeException); 411 virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException); 412 }; 413 414 // XNameContainer 415 //______________________________________________________________________________ 416 void ComponentContext::insertByName( 417 OUString const & name, Any const & element ) 418 throw (lang::IllegalArgumentException, container::ElementExistException, 419 lang::WrappedTargetException, RuntimeException) 420 { 421 t_map::mapped_type entry( 422 new ContextEntry( 423 element, 424 /* lateInit_: */ 425 name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && 426 !element.hasValue() ) ); 427 MutexGuard guard( m_mutex ); 428 ::std::pair<t_map::iterator, bool> insertion( m_map.insert( 429 t_map::value_type( name, entry ) ) ); 430 if (! insertion.second) 431 throw container::ElementExistException( 432 OUSTR("element already exists: ") + name, 433 static_cast<OWeakObject *>(this) ); 434 } 435 436 //______________________________________________________________________________ 437 void ComponentContext::removeByName( OUString const & name ) 438 throw (container::NoSuchElementException, 439 lang::WrappedTargetException, RuntimeException) 440 { 441 MutexGuard guard( m_mutex ); 442 t_map::iterator iFind( m_map.find( name ) ); 443 if (iFind == m_map.end()) 444 throw container::NoSuchElementException( 445 OUSTR("no such element: ") + name, 446 static_cast<OWeakObject *>(this) ); 447 448 delete iFind->second; 449 m_map.erase(iFind); 450 } 451 452 // XNameReplace 453 //______________________________________________________________________________ 454 void ComponentContext::replaceByName( 455 OUString const & name, Any const & element ) 456 throw (lang::IllegalArgumentException,container::NoSuchElementException, 457 lang::WrappedTargetException, RuntimeException) 458 { 459 MutexGuard guard( m_mutex ); 460 t_map::const_iterator const iFind( m_map.find( name ) ); 461 if (iFind == m_map.end()) 462 throw container::NoSuchElementException( 463 OUSTR("no such element: ") + name, 464 static_cast<OWeakObject *>(this) ); 465 if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && 466 !element.hasValue()) 467 { 468 iFind->second->value.clear(); 469 iFind->second->lateInit = true; 470 } 471 else 472 { 473 iFind->second->value = element; 474 iFind->second->lateInit = false; 475 } 476 } 477 478 // XNameAccess 479 //______________________________________________________________________________ 480 Any ComponentContext::getByName( OUString const & name ) 481 throw (container::NoSuchElementException, 482 lang::WrappedTargetException, RuntimeException) 483 { 484 return getValueByName( name ); 485 } 486 487 //______________________________________________________________________________ 488 Sequence<OUString> ComponentContext::getElementNames() 489 throw (RuntimeException) 490 { 491 MutexGuard guard( m_mutex ); 492 Sequence<OUString> ret( m_map.size() ); 493 OUString * pret = ret.getArray(); 494 sal_Int32 pos = 0; 495 t_map::const_iterator iPos( m_map.begin() ); 496 t_map::const_iterator const iEnd( m_map.end() ); 497 for ( ; iPos != iEnd; ++iPos ) 498 pret[pos++] = iPos->first; 499 return ret; 500 } 501 502 //______________________________________________________________________________ 503 sal_Bool ComponentContext::hasByName( OUString const & name ) 504 throw (RuntimeException) 505 { 506 MutexGuard guard( m_mutex ); 507 return m_map.find( name ) != m_map.end(); 508 } 509 510 // XElementAccess 511 //______________________________________________________________________________ 512 Type ComponentContext::getElementType() throw (RuntimeException) 513 { 514 return ::getVoidCppuType(); 515 } 516 517 //______________________________________________________________________________ 518 sal_Bool ComponentContext::hasElements() throw (RuntimeException) 519 { 520 MutexGuard guard( m_mutex ); 521 return ! m_map.empty(); 522 } 523 524 //__________________________________________________________________________________________________ 525 Any ComponentContext::lookupMap( OUString const & rName ) 526 SAL_THROW( (RuntimeException) ) 527 { 528 #ifdef CONTEXT_DIAG 529 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dump_maps") )) 530 { 531 ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this ); 532 typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map 533 t_sorted sorted; 534 for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos ) 535 { 536 sorted[ iPos->first ] = iPos->second; 537 } 538 { 539 for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos ) 540 { 541 dumpEntry( iPos->first, iPos->second->value ); 542 } 543 } 544 return Any(); 545 } 546 #endif 547 548 ResettableMutexGuard guard( m_mutex ); 549 t_map::const_iterator iFind( m_map.find( rName ) ); 550 if (iFind == m_map.end()) 551 return Any(); 552 553 t_map::mapped_type pEntry = iFind->second; 554 if (! pEntry->lateInit) 555 return pEntry->value; 556 557 // late init singleton entry 558 Reference< XInterface > xInstance; 559 guard.clear(); 560 561 try 562 { 563 Any usesService( getValueByName( rName + OUSTR("/service") ) ); 564 Any args_( getValueByName( rName + OUSTR("/arguments") ) ); 565 Sequence<Any> args; 566 if (args_.hasValue() && !(args_ >>= args)) 567 { 568 args.realloc( 1 ); 569 args[ 0 ] = args_; 570 } 571 572 Reference< lang::XSingleComponentFactory > xFac; 573 if (usesService >>= xFac) // try via factory 574 { 575 xInstance = args.getLength() 576 ? xFac->createInstanceWithArgumentsAndContext( args, this ) 577 : xFac->createInstanceWithContext( this ); 578 } 579 else 580 { 581 Reference< lang::XSingleServiceFactory > xFac2; 582 if (usesService >>= xFac2) 583 { 584 // try via old XSingleServiceFactory 585 #if OSL_DEBUG_LEVEL > 0 586 ::fprintf( 587 stderr, 588 "### omitting context for service instanciation!\n" ); 589 #endif 590 xInstance = args.getLength() 591 ? xFac2->createInstanceWithArguments( args ) 592 : xFac2->createInstance(); 593 } 594 else if (m_xSMgr.is()) // optionally service name 595 { 596 OUString serviceName; 597 if ((usesService >>= serviceName) && 598 serviceName.getLength()) 599 { 600 xInstance = args.getLength() 601 ? m_xSMgr->createInstanceWithArgumentsAndContext( 602 serviceName, args, this ) 603 : m_xSMgr->createInstanceWithContext( 604 serviceName, this ); 605 } 606 } 607 } 608 } 609 catch (RuntimeException &) 610 { 611 throw; 612 } 613 catch (Exception & exc) // rethrow as WrappedTargetRuntimeException 614 { 615 Any caught( getCaughtException() ); 616 OUStringBuffer buf; 617 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 618 "exception occured raising singleton \"") ); 619 buf.append( rName ); 620 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") ); 621 buf.append( exc.Message ); 622 throw lang::WrappedTargetRuntimeException( 623 buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught ); 624 } 625 626 if (! xInstance.is()) 627 { 628 throw RuntimeException( 629 OUSTR("no service object raising singleton ") + rName, 630 static_cast<OWeakObject *>(this) ); 631 } 632 633 Any ret; 634 guard.reset(); 635 iFind = m_map.find( rName ); 636 if (iFind != m_map.end()) 637 { 638 pEntry = iFind->second; 639 if (pEntry->lateInit) 640 { 641 pEntry->value <<= xInstance; 642 pEntry->lateInit = false; 643 return pEntry->value; 644 } 645 else 646 ret = pEntry->value; 647 } 648 guard.clear(); 649 try_dispose( xInstance ); 650 return ret; 651 } 652 653 //__________________________________________________________________________________________________ 654 Any ComponentContext::getValueByName( OUString const & rName ) 655 throw (RuntimeException) 656 { 657 // to determine the root context: 658 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_root") )) 659 { 660 if (m_xDelegate.is()) 661 return m_xDelegate->getValueByName( rName ); 662 else 663 return makeAny( Reference<XComponentContext>(this) ); 664 } 665 666 Any ret( lookupMap( rName ) ); 667 if (!ret.hasValue() && m_xDelegate.is()) 668 { 669 return m_xDelegate->getValueByName( rName ); 670 } 671 return ret; 672 } 673 //__________________________________________________________________________________________________ 674 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager() 675 throw (RuntimeException) 676 { 677 return m_xSMgr; 678 } 679 //__________________________________________________________________________________________________ 680 ComponentContext::~ComponentContext() 681 SAL_THROW( () ) 682 { 683 #ifdef CONTEXT_DIAG 684 ::fprintf( stderr, "> destructed context %p\n", this ); 685 #endif 686 t_map::const_iterator iPos( m_map.begin() ); 687 t_map::const_iterator const iEnd( m_map.end() ); 688 for ( ; iPos != iEnd; ++iPos ) 689 delete iPos->second; 690 m_map.clear(); 691 } 692 //__________________________________________________________________________________________________ 693 void ComponentContext::disposing() 694 { 695 #ifdef CONTEXT_DIAG 696 ::fprintf( stderr, "> disposing context %p\n", this ); 697 #endif 698 699 Reference< lang::XComponent > xTDMgr, xAC, xPolicy; // to be disposed separately 700 701 // dispose all context objects 702 t_map::const_iterator iPos( m_map.begin() ); 703 t_map::const_iterator const iEnd( m_map.end() ); 704 for ( ; iPos != iEnd; ++iPos ) 705 { 706 t_map::mapped_type pEntry = iPos->second; 707 708 // service manager disposed separately 709 if (!m_xSMgr.is() || 710 !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) 711 { 712 if (pEntry->lateInit) 713 { 714 // late init 715 MutexGuard guard( m_mutex ); 716 if (pEntry->lateInit) 717 { 718 pEntry->value.clear(); // release factory 719 pEntry->lateInit = false; 720 continue; 721 } 722 } 723 724 Reference< lang::XComponent > xComp; 725 pEntry->value >>= xComp; 726 if (xComp.is()) 727 { 728 if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(TDMGR_SINGLETON) )) 729 { 730 xTDMgr = xComp; 731 } 732 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_SINGLETON) )) 733 { 734 xAC = xComp; 735 } 736 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_POLICY) )) 737 { 738 xPolicy = xComp; 739 } 740 else // dispose immediately 741 { 742 xComp->dispose(); 743 } 744 } 745 } 746 } 747 748 // dispose service manager 749 try_dispose( m_xSMgr ); 750 m_xSMgr.clear(); 751 // dispose ac 752 try_dispose( xAC ); 753 // dispose policy 754 try_dispose( xPolicy ); 755 // dispose tdmgr; revokes callback from cppu runtime 756 try_dispose( xTDMgr ); 757 758 iPos = m_map.begin(); 759 for ( ; iPos != iEnd; ++iPos ) 760 delete iPos->second; 761 m_map.clear(); 762 } 763 //__________________________________________________________________________________________________ 764 ComponentContext::ComponentContext( 765 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 766 Reference< XComponentContext > const & xDelegate ) 767 : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >( 768 m_mutex ), 769 m_xDelegate( xDelegate ) 770 { 771 for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos ) 772 { 773 ContextEntry_Init const & rEntry = pEntries[ nPos ]; 774 775 if (rEntry.name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) 776 { 777 rEntry.value >>= m_xSMgr; 778 } 779 780 if (rEntry.bLateInitService) 781 { 782 // singleton entry 783 m_map[ rEntry.name ] = new ContextEntry( Any(), true ); 784 // /service 785 m_map[ rEntry.name + OUSTR("/service") ] = new ContextEntry( rEntry.value, false ); 786 // /initial-arguments are provided as optional context entry 787 } 788 else 789 { 790 // only value, no late init factory nor string 791 m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false ); 792 } 793 } 794 795 if (!m_xSMgr.is() && m_xDelegate.is()) 796 { 797 // wrap delegate's smgr XPropertySet into new smgr 798 Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() ); 799 if (xMgr.is()) 800 { 801 osl_incrementInterlockedCount( &m_refCount ); 802 try 803 { 804 // create new smgr based on delegate's one 805 m_xSMgr.set( 806 xMgr->createInstanceWithContext( 807 OUSTR("com.sun.star.comp.stoc.OServiceManagerWrapper"), xDelegate ), 808 UNO_QUERY ); 809 // patch DefaultContext property of new one 810 Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY ); 811 OSL_ASSERT( xProps.is() ); 812 if (xProps.is()) 813 { 814 Reference< XComponentContext > xThis( this ); 815 xProps->setPropertyValue( OUSTR("DefaultContext"), makeAny( xThis ) ); 816 } 817 } 818 catch (...) 819 { 820 osl_decrementInterlockedCount( &m_refCount ); 821 throw; 822 } 823 osl_decrementInterlockedCount( &m_refCount ); 824 OSL_ASSERT( m_xSMgr.is() ); 825 } 826 } 827 } 828 829 830 //################################################################################################## 831 extern "C" { static void s_createComponentContext_v(va_list * pParam) 832 { 833 ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *); 834 sal_Int32 nEntries = va_arg(*pParam, sal_Int32); 835 XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *); 836 void ** ppContext = va_arg(*pParam, void **); 837 uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *); 838 839 Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE); 840 Reference<XComponentContext> xContext; 841 842 if (nEntries > 0) 843 { 844 try 845 { 846 ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate ); 847 xContext.set(p); 848 // listen delegate for disposing, to dispose this (wrapping) context first. 849 DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p ); 850 } 851 catch (Exception & exc) 852 { 853 (void) exc; // avoid warning about unused variable 854 OSL_ENSURE( 0, OUStringToOString( 855 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); 856 xContext.clear(); 857 } 858 } 859 else 860 { 861 xContext = xDelegate; 862 } 863 864 delete[] pEntries; 865 866 *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext)); 867 }} 868 869 Reference< XComponentContext > SAL_CALL createComponentContext( 870 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 871 Reference< XComponentContext > const & xDelegate ) 872 SAL_THROW( () ) 873 { 874 uno::Environment curr_env(Environment::getCurrent()); 875 uno::Environment source_env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CPPU_STRINGIFY(CPPU_ENV)))); 876 877 uno::Mapping curr2source(curr_env, source_env); 878 uno::Mapping source2curr(source_env, curr_env); 879 880 ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries]; 881 for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos) 882 { 883 mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService; 884 mapped_entries[nPos].name = pEntries[nPos].name; 885 886 uno_type_any_constructAndConvert(&mapped_entries[nPos].value, 887 const_cast<void *>(pEntries[nPos].value.getValue()), 888 pEntries[nPos].value.getValueTypeRef(), 889 curr2source.get()); 890 } 891 892 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate)); 893 XComponentContext * pXComponentContext = NULL; 894 source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr); 895 896 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE); 897 } 898 899 } 900