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