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 { 278 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY ); 279 if (xComp.is()) 280 { 281 xComp->dispose(); 282 } 283 } 284 //-------------------------------------------------------------------------------------------------- 285 static inline void try_dispose( Reference< lang::XComponent > const & xComp ) 286 { 287 if (xComp.is()) 288 { 289 xComp->dispose(); 290 } 291 } 292 293 //================================================================================================== 294 295 class DisposingForwarder 296 : public WeakImplHelper1< lang::XEventListener > 297 { 298 Reference< lang::XComponent > m_xTarget; 299 300 inline DisposingForwarder( Reference< lang::XComponent > const & xTarget ) 301 SAL_THROW( () ) 302 : m_xTarget( xTarget ) 303 { OSL_ASSERT( m_xTarget.is() ); } 304 public: 305 // listens at source for disposing, then disposes target 306 static inline void listen( 307 Reference< lang::XComponent > const & xSource, 308 Reference< lang::XComponent > const & xTarget ); 309 310 virtual void SAL_CALL disposing( lang::EventObject const & rSource ); 311 }; 312 //__________________________________________________________________________________________________ 313 inline void DisposingForwarder::listen( 314 Reference< lang::XComponent > const & xSource, 315 Reference< lang::XComponent > const & xTarget ) 316 { 317 if (xSource.is()) 318 { 319 xSource->addEventListener( new DisposingForwarder( xTarget ) ); 320 } 321 } 322 //__________________________________________________________________________________________________ 323 void DisposingForwarder::disposing( lang::EventObject const & ) 324 { 325 m_xTarget->dispose(); 326 m_xTarget.clear(); 327 } 328 329 //================================================================================================== 330 struct MutexHolder 331 { 332 protected: 333 Mutex m_mutex; 334 }; 335 //================================================================================================== 336 337 class ComponentContext 338 : private MutexHolder 339 , public WeakComponentImplHelper2< XComponentContext, 340 container::XNameContainer > 341 { 342 protected: 343 Reference< XComponentContext > m_xDelegate; 344 345 struct ContextEntry 346 { 347 Any value; 348 bool lateInit; 349 350 inline ContextEntry( Any const & value_, bool lateInit_ ) 351 : value( value_ ) 352 , lateInit( lateInit_ ) 353 {} 354 }; 355 typedef ::std::hash_map< OUString, ContextEntry * , OUStringHash > t_map; 356 t_map m_map; 357 358 Reference< lang::XMultiComponentFactory > m_xSMgr; 359 360 protected: 361 Any lookupMap( OUString const & rName ); 362 363 virtual void SAL_CALL disposing(); 364 public: 365 ComponentContext( 366 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 367 Reference< XComponentContext > const & xDelegate ); 368 virtual ~ComponentContext() 369 SAL_THROW( () ); 370 371 // XComponentContext 372 virtual Any SAL_CALL getValueByName( OUString const & rName ); 373 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager(); 374 375 // XNameContainer 376 virtual void SAL_CALL insertByName( 377 OUString const & name, Any const & element ); 378 virtual void SAL_CALL removeByName( OUString const & name ); 379 // XNameReplace 380 virtual void SAL_CALL replaceByName( 381 OUString const & name, Any const & element ); 382 // XNameAccess 383 virtual Any SAL_CALL getByName( OUString const & name ); 384 virtual Sequence<OUString> SAL_CALL getElementNames(); 385 virtual sal_Bool SAL_CALL hasByName( OUString const & name ); 386 // XElementAccess 387 virtual Type SAL_CALL getElementType(); 388 virtual sal_Bool SAL_CALL hasElements(); 389 }; 390 391 // XNameContainer 392 //______________________________________________________________________________ 393 void ComponentContext::insertByName( 394 OUString const & name, Any const & element ) 395 { 396 t_map::mapped_type entry( 397 new ContextEntry( 398 element, 399 /* lateInit_: */ 400 name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && 401 !element.hasValue() ) ); 402 MutexGuard guard( m_mutex ); 403 ::std::pair<t_map::iterator, bool> insertion( m_map.insert( 404 t_map::value_type( name, entry ) ) ); 405 if (! insertion.second) 406 throw container::ElementExistException( 407 OUSTR("element already exists: ") + name, 408 static_cast<OWeakObject *>(this) ); 409 } 410 411 //______________________________________________________________________________ 412 void ComponentContext::removeByName( OUString const & name ) 413 { 414 MutexGuard guard( m_mutex ); 415 t_map::iterator iFind( m_map.find( name ) ); 416 if (iFind == m_map.end()) 417 throw container::NoSuchElementException( 418 OUSTR("no such element: ") + name, 419 static_cast<OWeakObject *>(this) ); 420 421 delete iFind->second; 422 m_map.erase(iFind); 423 } 424 425 // XNameReplace 426 //______________________________________________________________________________ 427 void ComponentContext::replaceByName( 428 OUString const & name, Any const & element ) 429 { 430 MutexGuard guard( m_mutex ); 431 t_map::const_iterator const iFind( m_map.find( name ) ); 432 if (iFind == m_map.end()) 433 throw container::NoSuchElementException( 434 OUSTR("no such element: ") + name, 435 static_cast<OWeakObject *>(this) ); 436 if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && 437 !element.hasValue()) 438 { 439 iFind->second->value.clear(); 440 iFind->second->lateInit = true; 441 } 442 else 443 { 444 iFind->second->value = element; 445 iFind->second->lateInit = false; 446 } 447 } 448 449 // XNameAccess 450 //______________________________________________________________________________ 451 Any ComponentContext::getByName( OUString const & name ) 452 { 453 return getValueByName( name ); 454 } 455 456 //______________________________________________________________________________ 457 Sequence<OUString> ComponentContext::getElementNames() 458 { 459 MutexGuard guard( m_mutex ); 460 Sequence<OUString> ret( m_map.size() ); 461 OUString * pret = ret.getArray(); 462 sal_Int32 pos = 0; 463 t_map::const_iterator iPos( m_map.begin() ); 464 t_map::const_iterator const iEnd( m_map.end() ); 465 for ( ; iPos != iEnd; ++iPos ) 466 pret[pos++] = iPos->first; 467 return ret; 468 } 469 470 //______________________________________________________________________________ 471 sal_Bool ComponentContext::hasByName( OUString const & name ) 472 { 473 MutexGuard guard( m_mutex ); 474 return m_map.find( name ) != m_map.end(); 475 } 476 477 // XElementAccess 478 //______________________________________________________________________________ 479 Type ComponentContext::getElementType() 480 { 481 return ::getVoidCppuType(); 482 } 483 484 //______________________________________________________________________________ 485 sal_Bool ComponentContext::hasElements() 486 { 487 MutexGuard guard( m_mutex ); 488 return ! m_map.empty(); 489 } 490 491 //__________________________________________________________________________________________________ 492 Any ComponentContext::lookupMap( OUString const & rName ) 493 { 494 #ifdef CONTEXT_DIAG 495 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dump_maps") )) 496 { 497 ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this ); 498 typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map 499 t_sorted sorted; 500 for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos ) 501 { 502 sorted[ iPos->first ] = iPos->second; 503 } 504 { 505 for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos ) 506 { 507 dumpEntry( iPos->first, iPos->second->value ); 508 } 509 } 510 return Any(); 511 } 512 #endif 513 514 ResettableMutexGuard guard( m_mutex ); 515 t_map::const_iterator iFind( m_map.find( rName ) ); 516 if (iFind == m_map.end()) 517 return Any(); 518 519 t_map::mapped_type pEntry = iFind->second; 520 if (! pEntry->lateInit) 521 return pEntry->value; 522 523 // late init singleton entry 524 Reference< XInterface > xInstance; 525 guard.clear(); 526 527 try 528 { 529 Any usesService( getValueByName( rName + OUSTR("/service") ) ); 530 Any args_( getValueByName( rName + OUSTR("/arguments") ) ); 531 Sequence<Any> args; 532 if (args_.hasValue() && !(args_ >>= args)) 533 { 534 args.realloc( 1 ); 535 args[ 0 ] = args_; 536 } 537 538 Reference< lang::XSingleComponentFactory > xFac; 539 if (usesService >>= xFac) // try via factory 540 { 541 xInstance = args.getLength() 542 ? xFac->createInstanceWithArgumentsAndContext( args, this ) 543 : xFac->createInstanceWithContext( this ); 544 } 545 else 546 { 547 Reference< lang::XSingleServiceFactory > xFac2; 548 if (usesService >>= xFac2) 549 { 550 // try via old XSingleServiceFactory 551 #if OSL_DEBUG_LEVEL > 0 552 ::fprintf( 553 stderr, 554 "### omitting context for service instantiation!\n" ); 555 #endif 556 xInstance = args.getLength() 557 ? xFac2->createInstanceWithArguments( args ) 558 : xFac2->createInstance(); 559 } 560 else if (m_xSMgr.is()) // optionally service name 561 { 562 OUString serviceName; 563 if ((usesService >>= serviceName) && 564 serviceName.getLength()) 565 { 566 xInstance = args.getLength() 567 ? m_xSMgr->createInstanceWithArgumentsAndContext( 568 serviceName, args, this ) 569 : m_xSMgr->createInstanceWithContext( 570 serviceName, this ); 571 } 572 } 573 } 574 } 575 catch (RuntimeException &) 576 { 577 throw; 578 } 579 catch (Exception & exc) // rethrow as WrappedTargetRuntimeException 580 { 581 Any caught( getCaughtException() ); 582 OUStringBuffer buf; 583 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 584 "exception occurred raising singleton \"") ); 585 buf.append( rName ); 586 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") ); 587 buf.append( exc.Message ); 588 throw lang::WrappedTargetRuntimeException( 589 buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught ); 590 } 591 592 if (! xInstance.is()) 593 { 594 throw RuntimeException( 595 OUSTR("no service object raising singleton ") + rName, 596 static_cast<OWeakObject *>(this) ); 597 } 598 599 Any ret; 600 guard.reset(); 601 iFind = m_map.find( rName ); 602 if (iFind != m_map.end()) 603 { 604 pEntry = iFind->second; 605 if (pEntry->lateInit) 606 { 607 pEntry->value <<= xInstance; 608 pEntry->lateInit = false; 609 return pEntry->value; 610 } 611 else 612 ret = pEntry->value; 613 } 614 guard.clear(); 615 try_dispose( xInstance ); 616 return ret; 617 } 618 619 //__________________________________________________________________________________________________ 620 Any ComponentContext::getValueByName( OUString const & rName ) 621 { 622 // to determine the root context: 623 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_root") )) 624 { 625 if (m_xDelegate.is()) 626 return m_xDelegate->getValueByName( rName ); 627 else 628 return makeAny( Reference<XComponentContext>(this) ); 629 } 630 631 Any ret( lookupMap( rName ) ); 632 if (!ret.hasValue() && m_xDelegate.is()) 633 { 634 return m_xDelegate->getValueByName( rName ); 635 } 636 return ret; 637 } 638 //__________________________________________________________________________________________________ 639 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager() 640 { 641 return m_xSMgr; 642 } 643 //__________________________________________________________________________________________________ 644 ComponentContext::~ComponentContext() 645 SAL_THROW( () ) 646 { 647 #ifdef CONTEXT_DIAG 648 ::fprintf( stderr, "> destructed context %p\n", this ); 649 #endif 650 t_map::const_iterator iPos( m_map.begin() ); 651 t_map::const_iterator const iEnd( m_map.end() ); 652 for ( ; iPos != iEnd; ++iPos ) 653 delete iPos->second; 654 m_map.clear(); 655 } 656 //__________________________________________________________________________________________________ 657 void ComponentContext::disposing() 658 { 659 #ifdef CONTEXT_DIAG 660 ::fprintf( stderr, "> disposing context %p\n", this ); 661 #endif 662 663 Reference< lang::XComponent > xTDMgr, xAC, xPolicy; // to be disposed separately 664 665 // dispose all context objects 666 t_map::const_iterator iPos( m_map.begin() ); 667 t_map::const_iterator const iEnd( m_map.end() ); 668 for ( ; iPos != iEnd; ++iPos ) 669 { 670 t_map::mapped_type pEntry = iPos->second; 671 672 // service manager disposed separately 673 if (!m_xSMgr.is() || 674 !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) 675 { 676 if (pEntry->lateInit) 677 { 678 // late init 679 MutexGuard guard( m_mutex ); 680 if (pEntry->lateInit) 681 { 682 pEntry->value.clear(); // release factory 683 pEntry->lateInit = false; 684 continue; 685 } 686 } 687 688 Reference< lang::XComponent > xComp; 689 pEntry->value >>= xComp; 690 if (xComp.is()) 691 { 692 if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(TDMGR_SINGLETON) )) 693 { 694 xTDMgr = xComp; 695 } 696 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_SINGLETON) )) 697 { 698 xAC = xComp; 699 } 700 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_POLICY) )) 701 { 702 xPolicy = xComp; 703 } 704 else // dispose immediately 705 { 706 xComp->dispose(); 707 } 708 } 709 } 710 } 711 712 // dispose service manager 713 try_dispose( m_xSMgr ); 714 m_xSMgr.clear(); 715 // dispose ac 716 try_dispose( xAC ); 717 // dispose policy 718 try_dispose( xPolicy ); 719 // dispose tdmgr; revokes callback from cppu runtime 720 try_dispose( xTDMgr ); 721 722 iPos = m_map.begin(); 723 for ( ; iPos != iEnd; ++iPos ) 724 delete iPos->second; 725 m_map.clear(); 726 } 727 //__________________________________________________________________________________________________ 728 ComponentContext::ComponentContext( 729 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 730 Reference< XComponentContext > const & xDelegate ) 731 : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >( 732 m_mutex ), 733 m_xDelegate( xDelegate ) 734 { 735 for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos ) 736 { 737 ContextEntry_Init const & rEntry = pEntries[ nPos ]; 738 739 if (rEntry.name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) 740 { 741 rEntry.value >>= m_xSMgr; 742 } 743 744 if (rEntry.bLateInitService) 745 { 746 // singleton entry 747 m_map[ rEntry.name ] = new ContextEntry( Any(), true ); 748 // /service 749 m_map[ rEntry.name + OUSTR("/service") ] = new ContextEntry( rEntry.value, false ); 750 // /initial-arguments are provided as optional context entry 751 } 752 else 753 { 754 // only value, no late init factory nor string 755 m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false ); 756 } 757 } 758 759 if (!m_xSMgr.is() && m_xDelegate.is()) 760 { 761 // wrap delegate's smgr XPropertySet into new smgr 762 Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() ); 763 if (xMgr.is()) 764 { 765 osl_incrementInterlockedCount( &m_refCount ); 766 try 767 { 768 // create new smgr based on delegate's one 769 m_xSMgr.set( 770 xMgr->createInstanceWithContext( 771 OUSTR("com.sun.star.comp.stoc.OServiceManagerWrapper"), xDelegate ), 772 UNO_QUERY ); 773 // patch DefaultContext property of new one 774 Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY ); 775 OSL_ASSERT( xProps.is() ); 776 if (xProps.is()) 777 { 778 Reference< XComponentContext > xThis( this ); 779 xProps->setPropertyValue( OUSTR("DefaultContext"), makeAny( xThis ) ); 780 } 781 } 782 catch (...) 783 { 784 osl_decrementInterlockedCount( &m_refCount ); 785 throw; 786 } 787 osl_decrementInterlockedCount( &m_refCount ); 788 OSL_ASSERT( m_xSMgr.is() ); 789 } 790 } 791 } 792 793 794 //################################################################################################## 795 extern "C" { static void s_createComponentContext_v(va_list * pParam) 796 { 797 ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *); 798 sal_Int32 nEntries = va_arg(*pParam, sal_Int32); 799 XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *); 800 void ** ppContext = va_arg(*pParam, void **); 801 uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *); 802 803 Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE); 804 Reference<XComponentContext> xContext; 805 806 if (nEntries > 0) 807 { 808 try 809 { 810 ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate ); 811 xContext.set(p); 812 // listen delegate for disposing, to dispose this (wrapping) context first. 813 DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p ); 814 } 815 catch (Exception & exc) 816 { 817 (void) exc; // avoid warning about unused variable 818 OSL_ENSURE( 0, OUStringToOString( 819 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); 820 xContext.clear(); 821 } 822 } 823 else 824 { 825 xContext = xDelegate; 826 } 827 828 delete[] pEntries; 829 830 *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext)); 831 }} 832 833 Reference< XComponentContext > SAL_CALL createComponentContext( 834 ContextEntry_Init const * pEntries, sal_Int32 nEntries, 835 Reference< XComponentContext > const & xDelegate ) 836 SAL_THROW( () ) 837 { 838 uno::Environment curr_env(Environment::getCurrent()); 839 uno::Environment source_env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CPPU_STRINGIFY(CPPU_ENV)))); 840 841 uno::Mapping curr2source(curr_env, source_env); 842 uno::Mapping source2curr(source_env, curr_env); 843 844 ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries]; 845 for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos) 846 { 847 mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService; 848 mapped_entries[nPos].name = pEntries[nPos].name; 849 850 uno_type_any_constructAndConvert(&mapped_entries[nPos].value, 851 const_cast<void *>(pEntries[nPos].value.getValue()), 852 pEntries[nPos].value.getValueTypeRef(), 853 curr2source.get()); 854 } 855 856 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate)); 857 XComponentContext * pXComponentContext = NULL; 858 source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr); 859 860 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE); 861 } 862 863 } 864