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_cppu.hxx" 30 31 #include "cppu/EnvDcp.hxx" 32 33 #include "sal/alloca.h" 34 #include "osl/diagnose.h" 35 #include "osl/interlck.h" 36 #include "osl/mutex.hxx" 37 #include "osl/module.h" 38 #include "osl/process.h" 39 #include "rtl/process.h" 40 #include "rtl/unload.h" 41 #include "rtl/string.hxx" 42 #include "rtl/ustring.hxx" 43 #include "rtl/ustrbuf.hxx" 44 #include "rtl/instance.hxx" 45 #include "typelib/typedescription.h" 46 #include "uno/dispatcher.h" 47 #include "uno/environment.h" 48 #include "uno/lbnames.h" 49 #include "prim.hxx" 50 #include "destr.hxx" 51 #include "loadmodule.hxx" 52 53 #include <hash_map> 54 #include <vector> 55 #include <stdio.h> 56 57 58 using ::rtl::OUString; 59 60 namespace 61 { 62 63 //------------------------------------------------------------------------------ 64 inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1, 65 typelib_InterfaceTypeDescription * pTD2 ) 66 { 67 return (pTD1 == pTD2 || 68 (((typelib_TypeDescription *)pTD1)->pTypeName->length == 69 ((typelib_TypeDescription *)pTD2)->pTypeName->length && 70 ::rtl_ustr_compare( 71 ((typelib_TypeDescription *) pTD1)->pTypeName->buffer, 72 ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0)); 73 } 74 75 struct ObjectEntry; 76 struct uno_DefaultEnvironment; 77 78 //------------------------------------------------------------------------------ 79 struct InterfaceEntry 80 { 81 sal_Int32 refCount; 82 void * pInterface; 83 uno_freeProxyFunc fpFreeProxy; 84 typelib_InterfaceTypeDescription * pTypeDescr; 85 }; 86 87 struct ObjectEntry 88 { 89 OUString oid; 90 sal_Int32 nRef; 91 ::std::vector< InterfaceEntry > aInterfaces; 92 bool mixedObject; 93 94 inline ObjectEntry( const OUString & rOId_ ); 95 96 inline void append( 97 uno_DefaultEnvironment * pEnv, 98 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, 99 uno_freeProxyFunc fpFreeProxy ); 100 inline InterfaceEntry * find( 101 typelib_InterfaceTypeDescription * pTypeDescr ); 102 inline sal_Int32 find( void * iface_ptr, ::std::size_t pos ); 103 }; 104 105 //------------------------------------------------------------------------------ 106 struct FctPtrHash : 107 public ::std::unary_function< const void *, ::std::size_t > 108 { 109 ::std::size_t operator () ( const void * pKey ) const 110 { return (::std::size_t) pKey; } 111 }; 112 113 //------------------------------------------------------------------------------ 114 struct FctOUStringHash : 115 public ::std::unary_function< const OUString &, ::std::size_t > 116 { 117 ::std::size_t operator () ( const OUString & rKey ) const 118 { return rKey.hashCode(); } 119 }; 120 121 // mapping from environment name to environment 122 typedef ::std::hash_map< 123 OUString, uno_Environment *, FctOUStringHash, 124 ::std::equal_to< OUString > > OUString2EnvironmentMap; 125 126 // mapping from ptr to object entry 127 typedef ::std::hash_map< 128 void *, ObjectEntry *, FctPtrHash, 129 ::std::equal_to< void * > > Ptr2ObjectMap; 130 // mapping from oid to object entry 131 typedef ::std::hash_map< 132 OUString, ObjectEntry *, FctOUStringHash, 133 ::std::equal_to< OUString > > OId2ObjectMap; 134 135 136 //============================================================================== 137 struct EnvironmentsData 138 { 139 ::osl::Mutex mutex; 140 OUString2EnvironmentMap aName2EnvMap; 141 142 EnvironmentsData() : isDisposing(false) {} 143 ~EnvironmentsData(); 144 145 inline void getEnvironment( 146 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ); 147 inline void registerEnvironment( uno_Environment ** ppEnv ); 148 inline void getRegisteredEnvironments( 149 uno_Environment *** pppEnvs, sal_Int32 * pnLen, 150 uno_memAlloc memAlloc, const OUString & rEnvDcp ); 151 152 bool isDisposing; 153 }; 154 155 namespace 156 { 157 struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {}; 158 } 159 160 //============================================================================== 161 struct uno_DefaultEnvironment : public uno_ExtEnvironment 162 { 163 sal_Int32 nRef; 164 sal_Int32 nWeakRef; 165 166 ::osl::Mutex mutex; 167 Ptr2ObjectMap aPtr2ObjectMap; 168 OId2ObjectMap aOId2ObjectMap; 169 170 uno_DefaultEnvironment( 171 const OUString & rEnvDcp_, void * pContext_ ); 172 ~uno_DefaultEnvironment(); 173 }; 174 175 //______________________________________________________________________________ 176 inline ObjectEntry::ObjectEntry( OUString const & rOId_ ) 177 : oid( rOId_ ), 178 nRef( 0 ), 179 mixedObject( false ) 180 { 181 aInterfaces.reserve( 2 ); 182 } 183 184 //______________________________________________________________________________ 185 inline void ObjectEntry::append( 186 uno_DefaultEnvironment * pEnv, 187 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr, 188 uno_freeProxyFunc fpFreeProxy ) 189 { 190 InterfaceEntry aNewEntry; 191 if (! fpFreeProxy) 192 (*pEnv->acquireInterface)( pEnv, pInterface ); 193 aNewEntry.refCount = 1; 194 aNewEntry.pInterface = pInterface; 195 aNewEntry.fpFreeProxy = fpFreeProxy; 196 typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr ); 197 aNewEntry.pTypeDescr = pTypeDescr; 198 199 ::std::pair< Ptr2ObjectMap::iterator, bool > insertion( 200 pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type( 201 pInterface, this ) ) ); 202 OSL_ASSERT( insertion.second || 203 (find( pInterface, 0 ) >= 0 && 204 // points to the same object entry: 205 insertion.first->second == this) ); 206 aInterfaces.push_back( aNewEntry ); 207 } 208 209 //______________________________________________________________________________ 210 inline InterfaceEntry * ObjectEntry::find( 211 typelib_InterfaceTypeDescription * pTypeDescr_ ) 212 { 213 OSL_ASSERT( ! aInterfaces.empty() ); 214 if (aInterfaces.empty()) 215 return 0; 216 217 // shortcut common case: 218 OUString const & type_name = 219 OUString::unacquired( 220 &((typelib_TypeDescription *) pTypeDescr_)->pTypeName ); 221 if (type_name.equalsAsciiL( 222 RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) 223 { 224 return &aInterfaces[ 0 ]; 225 } 226 227 ::std::size_t nSize = aInterfaces.size(); 228 for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos ) 229 { 230 typelib_InterfaceTypeDescription * pITD = 231 aInterfaces[ nPos ].pTypeDescr; 232 while (pITD) 233 { 234 if (td_equals( pITD, pTypeDescr_ )) 235 return &aInterfaces[ nPos ]; 236 pITD = pITD->pBaseTypeDescription; 237 } 238 } 239 return 0; 240 } 241 242 //______________________________________________________________________________ 243 inline sal_Int32 ObjectEntry::find( 244 void * iface_ptr, ::std::size_t pos ) 245 { 246 ::std::size_t size = aInterfaces.size(); 247 for ( ; pos < size; ++pos ) 248 { 249 if (aInterfaces[ pos ].pInterface == iface_ptr) 250 return pos; 251 } 252 return -1; 253 } 254 255 extern "C" 256 { 257 258 //------------------------------------------------------------------------------ 259 static void SAL_CALL defenv_registerInterface( 260 uno_ExtEnvironment * pEnv, void ** ppInterface, 261 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 262 { 263 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); 264 OUString const & rOId = OUString::unacquired( &pOId ); 265 266 uno_DefaultEnvironment * that = 267 static_cast< uno_DefaultEnvironment * >( pEnv ); 268 ::osl::ClearableMutexGuard guard( that->mutex ); 269 270 // try to insert dummy 0: 271 std::pair<OId2ObjectMap::iterator, bool> const insertion( 272 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); 273 if (insertion.second) 274 { 275 ObjectEntry * pOEntry = new ObjectEntry( rOId ); 276 insertion.first->second = pOEntry; 277 ++pOEntry->nRef; // another register call on object 278 pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); 279 } 280 else // object entry exists 281 { 282 ObjectEntry * pOEntry = insertion.first->second; 283 ++pOEntry->nRef; // another register call on object 284 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); 285 286 if (pIEntry) // type entry exists 287 { 288 ++pIEntry->refCount; 289 if (pIEntry->pInterface != *ppInterface) 290 { 291 void * pInterface = pIEntry->pInterface; 292 (*pEnv->acquireInterface)( pEnv, pInterface ); 293 guard.clear(); 294 (*pEnv->releaseInterface)( pEnv, *ppInterface ); 295 *ppInterface = pInterface; 296 } 297 } 298 else 299 { 300 pOEntry->append( that, *ppInterface, pTypeDescr, 0 ); 301 } 302 } 303 } 304 305 //------------------------------------------------------------------------------ 306 static void SAL_CALL defenv_registerProxyInterface( 307 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy, 308 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 309 { 310 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy, 311 "### null ptr!" ); 312 OUString const & rOId = OUString::unacquired( &pOId ); 313 314 uno_DefaultEnvironment * that = 315 static_cast< uno_DefaultEnvironment * >( pEnv ); 316 ::osl::ClearableMutexGuard guard( that->mutex ); 317 318 // try to insert dummy 0: 319 std::pair<OId2ObjectMap::iterator, bool> const insertion( 320 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) ); 321 if (insertion.second) 322 { 323 ObjectEntry * pOEntry = new ObjectEntry( rOId ); 324 insertion.first->second = pOEntry; 325 ++pOEntry->nRef; // another register call on object 326 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); 327 } 328 else // object entry exists 329 { 330 ObjectEntry * pOEntry = insertion.first->second; 331 332 // first registration was an original, then registerProxyInterface(): 333 pOEntry->mixedObject |= 334 (!pOEntry->aInterfaces.empty() && 335 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0); 336 337 ++pOEntry->nRef; // another register call on object 338 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr ); 339 340 if (pIEntry) // type entry exists 341 { 342 if (pIEntry->pInterface == *ppInterface) 343 { 344 ++pIEntry->refCount; 345 } 346 else 347 { 348 void * pInterface = pIEntry->pInterface; 349 (*pEnv->acquireInterface)( pEnv, pInterface ); 350 --pOEntry->nRef; // manual revoke of proxy to be freed 351 guard.clear(); 352 (*freeProxy)( pEnv, *ppInterface ); 353 *ppInterface = pInterface; 354 } 355 } 356 else 357 { 358 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy ); 359 } 360 } 361 } 362 363 //------------------------------------------------------------------------------ 364 static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam) 365 { 366 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 367 void * pInterface = va_arg(*pParam, void *); 368 369 OSL_ENSURE( pEnv && pInterface, "### null ptr!" ); 370 uno_DefaultEnvironment * that = 371 static_cast< uno_DefaultEnvironment * >( pEnv ); 372 ::osl::ClearableMutexGuard guard( that->mutex ); 373 374 Ptr2ObjectMap::const_iterator const iFind( 375 that->aPtr2ObjectMap.find( pInterface ) ); 376 OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() ); 377 ObjectEntry * pOEntry = iFind->second; 378 if (! --pOEntry->nRef) 379 { 380 // cleanup maps 381 that->aOId2ObjectMap.erase( pOEntry->oid ); 382 sal_Int32 nPos; 383 for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) 384 { 385 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface ); 386 } 387 388 // the last proxy interface of the environment might kill this 389 // environment, because of releasing its language binding!!! 390 guard.clear(); 391 392 // release interfaces 393 for ( nPos = pOEntry->aInterfaces.size(); nPos--; ) 394 { 395 InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos]; 396 typelib_typedescription_release( 397 (typelib_TypeDescription *) rEntry.pTypeDescr ); 398 if (rEntry.fpFreeProxy) // is proxy or used interface? 399 { 400 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface ); 401 } 402 else 403 { 404 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface ); 405 } 406 } 407 408 delete pOEntry; 409 } 410 else if (pOEntry->mixedObject) 411 { 412 OSL_ASSERT( !pOEntry->aInterfaces.empty() && 413 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 ); 414 415 sal_Int32 index = pOEntry->find( pInterface, 1 ); 416 OSL_ASSERT( index > 0 ); 417 if (index > 0) 418 { 419 InterfaceEntry & entry = pOEntry->aInterfaces[ index ]; 420 OSL_ASSERT( entry.pInterface == pInterface ); 421 if (entry.fpFreeProxy != 0) 422 { 423 --entry.refCount; 424 if (entry.refCount == 0) 425 { 426 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy; 427 typelib_TypeDescription * pTypeDescr = 428 reinterpret_cast< typelib_TypeDescription * >( 429 entry.pTypeDescr ); 430 431 pOEntry->aInterfaces.erase( 432 pOEntry->aInterfaces.begin() + index ); 433 if (pOEntry->find( pInterface, index ) < 0) 434 { 435 // proxy ptr not registered for another interface: 436 // remove from ptr map 437 #if OSL_DEBUG_LEVEL > 0 438 ::std::size_t erased = 439 #endif 440 that->aPtr2ObjectMap.erase( pInterface ); 441 OSL_ASSERT( erased == 1 ); 442 } 443 444 guard.clear(); 445 446 typelib_typedescription_release( pTypeDescr ); 447 (*fpFreeProxy)( pEnv, pInterface ); 448 } 449 } 450 } 451 } 452 } 453 454 static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface) 455 { 456 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface); 457 } 458 459 //------------------------------------------------------------------------------ 460 static void SAL_CALL defenv_getObjectIdentifier( 461 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) 462 { 463 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); 464 if (*ppOId) 465 { 466 ::rtl_uString_release( *ppOId ); 467 *ppOId = 0; 468 } 469 470 uno_DefaultEnvironment * that = 471 static_cast< uno_DefaultEnvironment * >( pEnv ); 472 ::osl::ClearableMutexGuard guard( that->mutex ); 473 474 Ptr2ObjectMap::const_iterator const iFind( 475 that->aPtr2ObjectMap.find( pInterface ) ); 476 if (iFind == that->aPtr2ObjectMap.end()) 477 { 478 guard.clear(); 479 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface ); 480 } 481 else 482 { 483 rtl_uString * hstr = iFind->second->oid.pData; 484 rtl_uString_acquire( hstr ); 485 *ppOId = hstr; 486 } 487 } 488 489 //------------------------------------------------------------------------------ 490 static void SAL_CALL defenv_getRegisteredInterface( 491 uno_ExtEnvironment * pEnv, void ** ppInterface, 492 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr ) 493 { 494 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" ); 495 if (*ppInterface) 496 { 497 (*pEnv->releaseInterface)( pEnv, *ppInterface ); 498 *ppInterface = 0; 499 } 500 501 OUString const & rOId = OUString::unacquired( &pOId ); 502 uno_DefaultEnvironment * that = 503 static_cast< uno_DefaultEnvironment * >( pEnv ); 504 ::osl::MutexGuard guard( that->mutex ); 505 506 OId2ObjectMap::const_iterator const iFind 507 ( that->aOId2ObjectMap.find( rOId ) ); 508 if (iFind != that->aOId2ObjectMap.end()) 509 { 510 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr ); 511 if (pIEntry) 512 { 513 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface ); 514 *ppInterface = pIEntry->pInterface; 515 } 516 } 517 } 518 519 //------------------------------------------------------------------------------ 520 static void SAL_CALL defenv_getRegisteredInterfaces( 521 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen, 522 uno_memAlloc memAlloc ) 523 { 524 OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" ); 525 uno_DefaultEnvironment * that = 526 static_cast< uno_DefaultEnvironment * >( pEnv ); 527 ::osl::MutexGuard guard( that->mutex ); 528 529 sal_Int32 nLen = that->aPtr2ObjectMap.size(); 530 sal_Int32 nPos = 0; 531 void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) ); 532 533 Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() ); 534 Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() ); 535 while (iPos != iEnd) 536 { 537 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first ); 538 ++iPos; 539 } 540 541 *pppInterfaces = ppInterfaces; 542 *pnLen = nLen; 543 } 544 545 //------------------------------------------------------------------------------ 546 static void SAL_CALL defenv_acquire( uno_Environment * pEnv ) 547 { 548 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 549 ::osl_incrementInterlockedCount( &that->nWeakRef ); 550 ::osl_incrementInterlockedCount( &that->nRef ); 551 } 552 553 //------------------------------------------------------------------------------ 554 static void SAL_CALL defenv_release( uno_Environment * pEnv ) 555 { 556 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 557 if (! ::osl_decrementInterlockedCount( &that->nRef )) 558 { 559 // invoke dispose callback 560 if (pEnv->environmentDisposing) 561 { 562 (*pEnv->environmentDisposing)( pEnv ); 563 } 564 565 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" ); 566 } 567 // free memory if no weak refs left 568 if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) 569 { 570 delete that; 571 } 572 } 573 574 //------------------------------------------------------------------------------ 575 static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv ) 576 { 577 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 578 ::osl_incrementInterlockedCount( &that->nWeakRef ); 579 } 580 581 //------------------------------------------------------------------------------ 582 static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv ) 583 { 584 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 585 if (! ::osl_decrementInterlockedCount( &that->nWeakRef )) 586 { 587 delete that; 588 } 589 } 590 591 //------------------------------------------------------------------------------ 592 static void SAL_CALL defenv_harden( 593 uno_Environment ** ppHardEnv, uno_Environment * pEnv ) 594 { 595 if (*ppHardEnv) 596 { 597 (*(*ppHardEnv)->release)( *ppHardEnv ); 598 *ppHardEnv = 0; 599 } 600 601 EnvironmentsData & rData = theEnvironmentsData::get(); 602 603 if (rData.isDisposing) 604 return; 605 606 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 607 { 608 ::osl::MutexGuard guard( rData.mutex ); 609 if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead 610 { 611 that->nRef = 0; 612 return; 613 } 614 } 615 ::osl_incrementInterlockedCount( &that->nWeakRef ); 616 *ppHardEnv = pEnv; 617 } 618 619 //------------------------------------------------------------------------------ 620 static void SAL_CALL defenv_dispose( uno_Environment * ) 621 { 622 } 623 } 624 625 //______________________________________________________________________________ 626 uno_DefaultEnvironment::uno_DefaultEnvironment( 627 const OUString & rEnvDcp_, void * pContext_ ) 628 : nRef( 0 ), 629 nWeakRef( 0 ) 630 { 631 uno_Environment * that = reinterpret_cast< uno_Environment * >(this); 632 that->pReserved = 0; 633 // functions 634 that->acquire = defenv_acquire; 635 that->release = defenv_release; 636 that->acquireWeak = defenv_acquireWeak; 637 that->releaseWeak = defenv_releaseWeak; 638 that->harden = defenv_harden; 639 that->dispose = defenv_dispose; 640 that->pExtEnv = this; 641 // identifier 642 ::rtl_uString_acquire( rEnvDcp_.pData ); 643 that->pTypeName = rEnvDcp_.pData; 644 that->pContext = pContext_; 645 646 // will be late initialized 647 that->environmentDisposing = 0; 648 649 uno_ExtEnvironment::registerInterface = defenv_registerInterface; 650 uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface; 651 uno_ExtEnvironment::revokeInterface = defenv_revokeInterface; 652 uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier; 653 uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface; 654 uno_ExtEnvironment::getRegisteredInterfaces = 655 defenv_getRegisteredInterfaces; 656 657 } 658 659 //______________________________________________________________________________ 660 uno_DefaultEnvironment::~uno_DefaultEnvironment() 661 { 662 ::rtl_uString_release( ((uno_Environment *) this)->pTypeName ); 663 } 664 665 //============================================================================== 666 static void writeLine( 667 void * stream, const sal_Char * pLine, const sal_Char * pFilter ) 668 { 669 if (pFilter && *pFilter) 670 { 671 // lookup pFilter in pLine 672 while (*pLine) 673 { 674 if (*pLine == *pFilter) 675 { 676 sal_Int32 nPos = 1; 677 while (pLine[nPos] && pFilter[nPos] == pLine[nPos]) 678 { 679 ++nPos; 680 } 681 if (! pFilter[nPos]) 682 { 683 if (stream) 684 { 685 fprintf( (FILE *) stream, "%s\n", pLine ); 686 } 687 else 688 { 689 OSL_TRACE( pLine ); 690 OSL_TRACE( "\n" ); 691 } 692 } 693 } 694 ++pLine; 695 } 696 } 697 else 698 { 699 if (stream) 700 { 701 fprintf( (FILE *) stream, "%s\n", pLine ); 702 } 703 else 704 { 705 fprintf( stderr, "%s\n", pLine ); 706 } 707 } 708 } 709 710 //============================================================================== 711 static void writeLine( 712 void * stream, const OUString & rLine, const sal_Char * pFilter ) 713 { 714 ::rtl::OString aLine( ::rtl::OUStringToOString( 715 rLine, RTL_TEXTENCODING_ASCII_US ) ); 716 writeLine( stream, aLine.getStr(), pFilter ); 717 } 718 719 //############################################################################## 720 extern "C" void SAL_CALL uno_dumpEnvironment( 721 void * stream, uno_Environment * pEnv, const sal_Char * pFilter ) 722 SAL_THROW_EXTERN_C() 723 { 724 OSL_ENSURE( pEnv, "### null ptr!" ); 725 ::rtl::OUStringBuffer buf; 726 727 if (! pEnv->pExtEnv) 728 { 729 writeLine( stream, "###################################" 730 "###########################################", pFilter ); 731 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") ); 732 buf.append( pEnv->pTypeName ); 733 writeLine( stream, buf.makeStringAndClear(), pFilter ); 734 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter ); 735 return; 736 } 737 738 writeLine( stream, "########################################" 739 "######################################", pFilter ); 740 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") ); 741 buf.append( pEnv->pTypeName ); 742 writeLine( stream, buf.makeStringAndClear(), pFilter ); 743 744 uno_DefaultEnvironment * that = 745 reinterpret_cast< uno_DefaultEnvironment * >(pEnv); 746 ::osl::MutexGuard guard( that->mutex ); 747 748 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap ); 749 OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() ); 750 while (iPos != that->aOId2ObjectMap.end()) 751 { 752 ObjectEntry * pOEntry = iPos->second; 753 754 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") ); 755 if (pOEntry->mixedObject) 756 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") ); 757 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") ); 758 buf.append( pOEntry->nRef, 10 ); 759 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") ); 760 buf.append( pOEntry->oid ); 761 buf.append( (sal_Unicode) '\"' ); 762 writeLine( stream, buf.makeStringAndClear(), pFilter ); 763 764 for ( ::std::size_t nPos = 0; 765 nPos < pOEntry->aInterfaces.size(); ++nPos ) 766 { 767 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos]; 768 769 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") ); 770 buf.append( 771 ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName ); 772 if (rIEntry.fpFreeProxy) 773 { 774 buf.appendAscii( 775 RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") ); 776 buf.append( 777 reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 ); 778 } 779 else 780 { 781 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") ); 782 } 783 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") ); 784 buf.append( 785 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 ); 786 787 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0) 788 { 789 ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface ); 790 if (erased != 1) 791 { 792 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 793 " (ptr not found in map!)") ); 794 } 795 } 796 writeLine( stream, buf.makeStringAndClear(), pFilter ); 797 } 798 ++iPos; 799 } 800 if (! ptr2obj.empty()) 801 writeLine( stream, "ptr map inconsistency!!!", pFilter ); 802 writeLine( stream, "#####################################" 803 "#########################################", pFilter ); 804 } 805 806 //############################################################################## 807 extern "C" void SAL_CALL uno_dumpEnvironmentByName( 808 void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter ) 809 SAL_THROW_EXTERN_C() 810 { 811 uno_Environment * pEnv = 0; 812 uno_getEnvironment( &pEnv, pEnvDcp, 0 ); 813 if (pEnv) 814 { 815 ::uno_dumpEnvironment( stream, pEnv, pFilter ); 816 (*pEnv->release)( pEnv ); 817 } 818 else 819 { 820 ::rtl::OUStringBuffer buf( 32 ); 821 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") ); 822 buf.append( pEnvDcp ); 823 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") ); 824 writeLine( stream, buf.makeStringAndClear(), pFilter ); 825 } 826 } 827 828 //------------------------------------------------------------------------------ 829 inline static const OUString & unoenv_getStaticOIdPart() 830 { 831 static OUString * s_pStaticOidPart = 0; 832 if (! s_pStaticOidPart) 833 { 834 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); 835 if (! s_pStaticOidPart) 836 { 837 ::rtl::OUStringBuffer aRet( 64 ); 838 aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); 839 // pid 840 oslProcessInfo info; 841 info.Size = sizeof(oslProcessInfo); 842 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) == 843 osl_Process_E_None) 844 { 845 aRet.append( (sal_Int64)info.Ident, 16 ); 846 } 847 else 848 { 849 aRet.appendAscii( 850 RTL_CONSTASCII_STRINGPARAM("unknown process id") ); 851 } 852 // good guid 853 sal_uInt8 ar[16]; 854 ::rtl_getGlobalProcessId( ar ); 855 aRet.append( (sal_Unicode)';' ); 856 for ( sal_Int32 i = 0; i < 16; ++i ) 857 aRet.append( (sal_Int32)ar[i], 16 ); 858 859 static OUString s_aStaticOidPart( aRet.makeStringAndClear() ); 860 s_pStaticOidPart = &s_aStaticOidPart; 861 } 862 } 863 return *s_pStaticOidPart; 864 } 865 866 extern "C" 867 { 868 869 //------------------------------------------------------------------------------ 870 static void SAL_CALL unoenv_computeObjectIdentifier( 871 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface ) 872 { 873 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" ); 874 if (*ppOId) 875 { 876 ::rtl_uString_release( *ppOId ); 877 *ppOId = 0; 878 } 879 880 uno_Interface * pUnoI = (uno_Interface *) 881 ::cppu::binuno_queryInterface( 882 pInterface, *typelib_static_type_getByTypeClass( 883 typelib_TypeClass_INTERFACE ) ); 884 if (0 != pUnoI) 885 { 886 (*pUnoI->release)( pUnoI ); 887 // interface 888 ::rtl::OUStringBuffer oid( 64 ); 889 oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 ); 890 oid.append( static_cast< sal_Unicode >(';') ); 891 // environment[context] 892 oid.append( ((uno_Environment *) pEnv)->pTypeName ); 893 oid.append( static_cast< sal_Unicode >('[') ); 894 oid.append( reinterpret_cast< sal_Int64 >( 895 reinterpret_cast< 896 uno_Environment * >(pEnv)->pContext ), 16 ); 897 // process;good guid 898 oid.append( unoenv_getStaticOIdPart() ); 899 OUString aStr( oid.makeStringAndClear() ); 900 ::rtl_uString_acquire( *ppOId = aStr.pData ); 901 } 902 } 903 904 //============================================================================== 905 static void SAL_CALL unoenv_acquireInterface( 906 uno_ExtEnvironment *, void * pUnoI_ ) 907 { 908 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); 909 (*pUnoI->acquire)( pUnoI ); 910 } 911 912 //============================================================================== 913 static void SAL_CALL unoenv_releaseInterface( 914 uno_ExtEnvironment *, void * pUnoI_ ) 915 { 916 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_); 917 (*pUnoI->release)( pUnoI ); 918 } 919 } 920 921 //______________________________________________________________________________ 922 EnvironmentsData::~EnvironmentsData() 923 { 924 ::osl::MutexGuard guard( mutex ); 925 isDisposing = true; 926 927 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); 928 iPos != aName2EnvMap.end(); ++iPos ) 929 { 930 uno_Environment * pWeak = iPos->second; 931 uno_Environment * pHard = 0; 932 (*pWeak->harden)( &pHard, pWeak ); 933 (*pWeak->releaseWeak)( pWeak ); 934 935 if (pHard) 936 { 937 #if OSL_DEBUG_LEVEL > 1 938 ::uno_dumpEnvironment( 0, pHard, 0 ); 939 #endif 940 (*pHard->dispose)( pHard ); // send explicit dispose 941 (*pHard->release)( pHard ); 942 } 943 } 944 } 945 946 //______________________________________________________________________________ 947 inline void EnvironmentsData::getEnvironment( 948 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext ) 949 { 950 if (*ppEnv) 951 { 952 (*(*ppEnv)->release)( *ppEnv ); 953 *ppEnv = 0; 954 } 955 956 OUString aKey( 957 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) ); 958 aKey += rEnvDcp; 959 960 // try to find registered mapping 961 OUString2EnvironmentMap::const_iterator const iFind( 962 aName2EnvMap.find( aKey ) ); 963 if (iFind != aName2EnvMap.end()) 964 { 965 uno_Environment * pWeak = iFind->second; 966 (*pWeak->harden)( ppEnv, pWeak ); 967 } 968 } 969 970 //______________________________________________________________________________ 971 inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv ) 972 { 973 OSL_ENSURE( ppEnv, "### null ptr!" ); 974 uno_Environment * pEnv = *ppEnv; 975 976 OUString aKey( 977 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) ); 978 aKey += pEnv->pTypeName; 979 980 // try to find registered environment 981 OUString2EnvironmentMap::const_iterator const iFind( 982 aName2EnvMap.find( aKey ) ); 983 if (iFind == aName2EnvMap.end()) 984 { 985 (*pEnv->acquireWeak)( pEnv ); 986 ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion( 987 aName2EnvMap.insert( 988 OUString2EnvironmentMap::value_type( aKey, pEnv ) ) ); 989 OSL_ENSURE( 990 insertion.second, "### insertion of env into map failed?!" ); 991 } 992 else 993 { 994 uno_Environment * pHard = 0; 995 uno_Environment * pWeak = iFind->second; 996 (*pWeak->harden)( &pHard, pWeak ); 997 if (pHard) 998 { 999 if (pEnv) 1000 (*pEnv->release)( pEnv ); 1001 *ppEnv = pHard; 1002 } 1003 else // registered one is dead 1004 { 1005 (*pWeak->releaseWeak)( pWeak ); 1006 (*pEnv->acquireWeak)( pEnv ); 1007 aName2EnvMap[ aKey ] = pEnv; 1008 } 1009 } 1010 } 1011 1012 //______________________________________________________________________________ 1013 inline void EnvironmentsData::getRegisteredEnvironments( 1014 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, 1015 const OUString & rEnvDcp ) 1016 { 1017 OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" ); 1018 1019 // max size 1020 uno_Environment ** ppFound = (uno_Environment **)alloca( 1021 sizeof(uno_Environment *) * aName2EnvMap.size() ); 1022 sal_Int32 nSize = 0; 1023 1024 // find matching environment 1025 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() ); 1026 iPos != aName2EnvMap.end(); ++iPos ) 1027 { 1028 uno_Environment * pWeak = iPos->second; 1029 if (!rEnvDcp.getLength() || 1030 rEnvDcp.equals( pWeak->pTypeName )) 1031 { 1032 ppFound[nSize] = 0; 1033 (*pWeak->harden)( &ppFound[nSize], pWeak ); 1034 if (ppFound[nSize]) 1035 ++nSize; 1036 } 1037 } 1038 1039 *pnLen = nSize; 1040 if (nSize) 1041 { 1042 *pppEnvs = (uno_Environment **) (*memAlloc)( 1043 sizeof (uno_Environment *) * nSize ); 1044 OSL_ASSERT( *pppEnvs ); 1045 while (nSize--) 1046 { 1047 (*pppEnvs)[nSize] = ppFound[nSize]; 1048 } 1049 } 1050 else 1051 { 1052 *pppEnvs = 0; 1053 } 1054 } 1055 1056 static bool loadEnv(OUString const & cLibStem, 1057 uno_Environment * pEnv, 1058 void * /*pContext*/) 1059 { 1060 // late init with some code from matching uno language binding 1061 // will be unloaded by environment 1062 oslModule hMod = cppu::detail::loadModule( cLibStem ); 1063 1064 if (!hMod) 1065 return false; 1066 1067 OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT)); 1068 uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc) 1069 ::osl_getFunctionSymbol( hMod, aSymbolName.pData ); 1070 if (!fpInit) 1071 { 1072 ::osl_unloadModule( hMod ); 1073 return false; 1074 } 1075 1076 (*fpInit)( pEnv ); // init of environment 1077 ::rtl_registerModuleForUnloading( hMod ); 1078 1079 return true; 1080 } 1081 1082 1083 extern "C" 1084 { 1085 1086 //------------------------------------------------------------------------------ 1087 static uno_Environment * initDefaultEnvironment( 1088 const OUString & rEnvDcp, void * pContext ) 1089 { 1090 uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase; 1091 (*pEnv->acquire)( pEnv ); 1092 1093 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp); 1094 1095 // create default environment 1096 if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) 1097 { 1098 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv; 1099 that->computeObjectIdentifier = unoenv_computeObjectIdentifier; 1100 that->acquireInterface = unoenv_acquireInterface; 1101 that->releaseInterface = unoenv_releaseInterface; 1102 1103 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp); 1104 if (envPurpose.getLength()) 1105 { 1106 rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1); 1107 libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") ); 1108 1109 if(!loadEnv(libStem, pEnv, pContext)) 1110 { 1111 pEnv->release(pEnv); 1112 return NULL; 1113 } 1114 } 1115 } 1116 else 1117 { 1118 // late init with some code from matching uno language binding 1119 ::rtl::OUStringBuffer aLibName( 16 ); 1120 aLibName.append( envTypeName ); 1121 aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) ); 1122 OUString aStr( aLibName.makeStringAndClear() ); 1123 1124 if (!loadEnv(aStr, pEnv, pContext)) 1125 { 1126 pEnv->release(pEnv); 1127 return NULL; 1128 } 1129 } 1130 1131 return pEnv; 1132 } 1133 1134 //############################################################################## 1135 void SAL_CALL uno_createEnvironment( 1136 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) 1137 SAL_THROW_EXTERN_C() 1138 { 1139 OSL_ENSURE( ppEnv, "### null ptr!" ); 1140 if (*ppEnv) 1141 (*(*ppEnv)->release)( *ppEnv ); 1142 1143 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); 1144 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); 1145 } 1146 1147 //############################################################################## 1148 void SAL_CALL uno_direct_getEnvironment( 1149 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) 1150 SAL_THROW_EXTERN_C() 1151 { 1152 OSL_ENSURE( ppEnv, "### null ptr!" ); 1153 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp ); 1154 1155 EnvironmentsData & rData = theEnvironmentsData::get(); 1156 1157 ::osl::MutexGuard guard( rData.mutex ); 1158 rData.getEnvironment( ppEnv, rEnvDcp, pContext ); 1159 if (! *ppEnv) 1160 { 1161 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext ); 1162 if (*ppEnv) 1163 { 1164 // register new environment: 1165 rData.registerEnvironment( ppEnv ); 1166 } 1167 } 1168 } 1169 1170 //############################################################################## 1171 void SAL_CALL uno_getRegisteredEnvironments( 1172 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc, 1173 rtl_uString * pEnvDcp ) 1174 SAL_THROW_EXTERN_C() 1175 { 1176 EnvironmentsData & rData = theEnvironmentsData::get(); 1177 1178 ::osl::MutexGuard guard( rData.mutex ); 1179 rData.getRegisteredEnvironments( 1180 pppEnvs, pnLen, memAlloc, 1181 (pEnvDcp ? OUString(pEnvDcp) : OUString()) ); 1182 } 1183 1184 } // extern "C" 1185 1186 } 1187 1188