merge the formfield patch from ooo-build
[ooovba.git] / cppu / source / uno / lbenv.cxx
blob6eef3551a97a201a70f0a471f84261c88910df86
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: lbenv.cxx,v $
10 * $Revision: 1.39 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppu.hxx"
34 #include "cppu/EnvDcp.hxx"
36 #include "sal/alloca.h"
37 #include "osl/diagnose.h"
38 #include "osl/interlck.h"
39 #include "osl/mutex.hxx"
40 #include "osl/module.h"
41 #include "osl/process.h"
42 #include "rtl/process.h"
43 #include "rtl/unload.h"
44 #include "rtl/string.hxx"
45 #include "rtl/ustring.hxx"
46 #include "rtl/ustrbuf.hxx"
47 #include "rtl/instance.hxx"
48 #include "typelib/typedescription.h"
49 #include "uno/dispatcher.h"
50 #include "uno/environment.h"
51 #include "uno/lbnames.h"
52 #include "prim.hxx"
53 #include "destr.hxx"
54 #include "loadmodule.hxx"
56 #include <hash_map>
57 #include <vector>
58 #include <stdio.h>
61 using ::rtl::OUString;
63 namespace
66 //------------------------------------------------------------------------------
67 inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
68 typelib_InterfaceTypeDescription * pTD2 )
70 return (pTD1 == pTD2 ||
71 (((typelib_TypeDescription *)pTD1)->pTypeName->length ==
72 ((typelib_TypeDescription *)pTD2)->pTypeName->length &&
73 ::rtl_ustr_compare(
74 ((typelib_TypeDescription *) pTD1)->pTypeName->buffer,
75 ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0));
78 struct ObjectEntry;
79 struct uno_DefaultEnvironment;
81 //------------------------------------------------------------------------------
82 struct InterfaceEntry
84 sal_Int32 refCount;
85 void * pInterface;
86 uno_freeProxyFunc fpFreeProxy;
87 typelib_InterfaceTypeDescription * pTypeDescr;
90 struct ObjectEntry
92 OUString oid;
93 sal_Int32 nRef;
94 ::std::vector< InterfaceEntry > aInterfaces;
95 bool mixedObject;
97 inline ObjectEntry( const OUString & rOId_ );
99 inline void append(
100 uno_DefaultEnvironment * pEnv,
101 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
102 uno_freeProxyFunc fpFreeProxy );
103 inline InterfaceEntry * find(
104 typelib_InterfaceTypeDescription * pTypeDescr );
105 inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
108 //------------------------------------------------------------------------------
109 struct FctPtrHash :
110 public ::std::unary_function< const void *, ::std::size_t >
112 ::std::size_t operator () ( const void * pKey ) const
113 { return (::std::size_t) pKey; }
116 //------------------------------------------------------------------------------
117 struct FctOUStringHash :
118 public ::std::unary_function< const OUString &, ::std::size_t >
120 ::std::size_t operator () ( const OUString & rKey ) const
121 { return rKey.hashCode(); }
124 // mapping from environment name to environment
125 typedef ::std::hash_map<
126 OUString, uno_Environment *, FctOUStringHash,
127 ::std::equal_to< OUString > > OUString2EnvironmentMap;
129 // mapping from ptr to object entry
130 typedef ::std::hash_map<
131 void *, ObjectEntry *, FctPtrHash,
132 ::std::equal_to< void * > > Ptr2ObjectMap;
133 // mapping from oid to object entry
134 typedef ::std::hash_map<
135 OUString, ObjectEntry *, FctOUStringHash,
136 ::std::equal_to< OUString > > OId2ObjectMap;
139 //==============================================================================
140 struct EnvironmentsData
142 ::osl::Mutex mutex;
143 OUString2EnvironmentMap aName2EnvMap;
145 ~EnvironmentsData();
147 inline void getEnvironment(
148 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
149 inline void registerEnvironment( uno_Environment ** ppEnv );
150 inline void getRegisteredEnvironments(
151 uno_Environment *** pppEnvs, sal_Int32 * pnLen,
152 uno_memAlloc memAlloc, const OUString & rEnvDcp );
155 namespace
157 struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
160 //==============================================================================
161 struct uno_DefaultEnvironment : public uno_ExtEnvironment
163 sal_Int32 nRef;
164 sal_Int32 nWeakRef;
166 ::osl::Mutex mutex;
167 Ptr2ObjectMap aPtr2ObjectMap;
168 OId2ObjectMap aOId2ObjectMap;
170 uno_DefaultEnvironment(
171 const OUString & rEnvDcp_, void * pContext_ );
172 ~uno_DefaultEnvironment();
175 //______________________________________________________________________________
176 inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
177 : oid( rOId_ ),
178 nRef( 0 ),
179 mixedObject( false )
181 aInterfaces.reserve( 2 );
184 //______________________________________________________________________________
185 inline void ObjectEntry::append(
186 uno_DefaultEnvironment * pEnv,
187 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
188 uno_freeProxyFunc fpFreeProxy )
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;
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 );
209 //______________________________________________________________________________
210 inline InterfaceEntry * ObjectEntry::find(
211 typelib_InterfaceTypeDescription * pTypeDescr_ )
213 OSL_ASSERT( ! aInterfaces.empty() );
214 if (aInterfaces.empty())
215 return 0;
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") ))
224 return &aInterfaces[ 0 ];
227 ::std::size_t nSize = aInterfaces.size();
228 for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
230 typelib_InterfaceTypeDescription * pITD =
231 aInterfaces[ nPos ].pTypeDescr;
232 while (pITD)
234 if (td_equals( pITD, pTypeDescr_ ))
235 return &aInterfaces[ nPos ];
236 pITD = pITD->pBaseTypeDescription;
239 return 0;
242 //______________________________________________________________________________
243 inline sal_Int32 ObjectEntry::find(
244 void * iface_ptr, ::std::size_t pos )
246 ::std::size_t size = aInterfaces.size();
247 for ( ; pos < size; ++pos )
249 if (aInterfaces[ pos ].pInterface == iface_ptr)
250 return pos;
252 return -1;
255 extern "C"
258 //------------------------------------------------------------------------------
259 static void SAL_CALL defenv_registerInterface(
260 uno_ExtEnvironment * pEnv, void ** ppInterface,
261 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
263 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
264 OUString const & rOId = OUString::unacquired( &pOId );
266 uno_DefaultEnvironment * that =
267 static_cast< uno_DefaultEnvironment * >( pEnv );
268 ::osl::ClearableMutexGuard guard( that->mutex );
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)
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 );
280 else // object entry exists
282 ObjectEntry * pOEntry = insertion.first->second;
283 ++pOEntry->nRef; // another register call on object
284 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
286 if (pIEntry) // type entry exists
288 ++pIEntry->refCount;
289 if (pIEntry->pInterface != *ppInterface)
291 void * pInterface = pIEntry->pInterface;
292 (*pEnv->acquireInterface)( pEnv, pInterface );
293 guard.clear();
294 (*pEnv->releaseInterface)( pEnv, *ppInterface );
295 *ppInterface = pInterface;
298 else
300 pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
305 //------------------------------------------------------------------------------
306 static void SAL_CALL defenv_registerProxyInterface(
307 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
308 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
310 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
311 "### null ptr!" );
312 OUString const & rOId = OUString::unacquired( &pOId );
314 uno_DefaultEnvironment * that =
315 static_cast< uno_DefaultEnvironment * >( pEnv );
316 ::osl::ClearableMutexGuard guard( that->mutex );
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)
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 );
328 else // object entry exists
330 ObjectEntry * pOEntry = insertion.first->second;
332 // first registration was an original, then registerProxyInterface():
333 pOEntry->mixedObject |=
334 (!pOEntry->aInterfaces.empty() &&
335 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
337 ++pOEntry->nRef; // another register call on object
338 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
340 if (pIEntry) // type entry exists
342 if (pIEntry->pInterface == *ppInterface)
344 ++pIEntry->refCount;
346 else
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;
356 else
358 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
363 //------------------------------------------------------------------------------
364 static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
366 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
367 void * pInterface = va_arg(*pParam, void *);
369 OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
370 uno_DefaultEnvironment * that =
371 static_cast< uno_DefaultEnvironment * >( pEnv );
372 ::osl::ClearableMutexGuard guard( that->mutex );
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)
380 // cleanup maps
381 that->aOId2ObjectMap.erase( pOEntry->oid );
382 sal_Int32 nPos;
383 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
385 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
388 // the last proxy interface of the environment might kill this
389 // environment, because of releasing its language binding!!!
390 guard.clear();
392 // release interfaces
393 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
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?
400 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
402 else
404 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
408 delete pOEntry;
410 else if (pOEntry->mixedObject)
412 OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
413 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
415 sal_Int32 index = pOEntry->find( pInterface, 1 );
416 OSL_ASSERT( index > 0 );
417 if (index > 0)
419 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
420 OSL_ASSERT( entry.pInterface == pInterface );
421 if (entry.fpFreeProxy != 0)
423 --entry.refCount;
424 if (entry.refCount == 0)
426 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
427 typelib_TypeDescription * pTypeDescr =
428 reinterpret_cast< typelib_TypeDescription * >(
429 entry.pTypeDescr );
431 pOEntry->aInterfaces.erase(
432 pOEntry->aInterfaces.begin() + index );
433 if (pOEntry->find( pInterface, index ) < 0)
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 );
444 guard.clear();
446 typelib_typedescription_release( pTypeDescr );
447 (*fpFreeProxy)( pEnv, pInterface );
454 static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
456 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
459 //------------------------------------------------------------------------------
460 static void SAL_CALL defenv_getObjectIdentifier(
461 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
463 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
464 if (*ppOId)
466 ::rtl_uString_release( *ppOId );
467 *ppOId = 0;
470 uno_DefaultEnvironment * that =
471 static_cast< uno_DefaultEnvironment * >( pEnv );
472 ::osl::ClearableMutexGuard guard( that->mutex );
474 Ptr2ObjectMap::const_iterator const iFind(
475 that->aPtr2ObjectMap.find( pInterface ) );
476 if (iFind == that->aPtr2ObjectMap.end())
478 guard.clear();
479 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
481 else
483 rtl_uString * hstr = iFind->second->oid.pData;
484 rtl_uString_acquire( hstr );
485 *ppOId = hstr;
489 //------------------------------------------------------------------------------
490 static void SAL_CALL defenv_getRegisteredInterface(
491 uno_ExtEnvironment * pEnv, void ** ppInterface,
492 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
494 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
495 if (*ppInterface)
497 (*pEnv->releaseInterface)( pEnv, *ppInterface );
498 *ppInterface = 0;
501 OUString const & rOId = OUString::unacquired( &pOId );
502 uno_DefaultEnvironment * that =
503 static_cast< uno_DefaultEnvironment * >( pEnv );
504 ::osl::MutexGuard guard( that->mutex );
506 OId2ObjectMap::const_iterator const iFind
507 ( that->aOId2ObjectMap.find( rOId ) );
508 if (iFind != that->aOId2ObjectMap.end())
510 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
511 if (pIEntry)
513 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
514 *ppInterface = pIEntry->pInterface;
519 //------------------------------------------------------------------------------
520 static void SAL_CALL defenv_getRegisteredInterfaces(
521 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
522 uno_memAlloc memAlloc )
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 );
529 sal_Int32 nLen = that->aPtr2ObjectMap.size();
530 sal_Int32 nPos = 0;
531 void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) );
533 Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
534 Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
535 while (iPos != iEnd)
537 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
538 ++iPos;
541 *pppInterfaces = ppInterfaces;
542 *pnLen = nLen;
545 //------------------------------------------------------------------------------
546 static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
548 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
549 ::osl_incrementInterlockedCount( &that->nWeakRef );
550 ::osl_incrementInterlockedCount( &that->nRef );
553 //------------------------------------------------------------------------------
554 static void SAL_CALL defenv_release( uno_Environment * pEnv )
556 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
557 if (! ::osl_decrementInterlockedCount( &that->nRef ))
559 // invoke dispose callback
560 if (pEnv->environmentDisposing)
562 (*pEnv->environmentDisposing)( pEnv );
565 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
567 // free memory if no weak refs left
568 if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
570 delete that;
574 //------------------------------------------------------------------------------
575 static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
577 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
578 ::osl_incrementInterlockedCount( &that->nWeakRef );
581 //------------------------------------------------------------------------------
582 static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
584 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
585 if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
587 delete that;
591 //------------------------------------------------------------------------------
592 static void SAL_CALL defenv_harden(
593 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
595 if (*ppHardEnv)
597 (*(*ppHardEnv)->release)( *ppHardEnv );
598 *ppHardEnv = 0;
601 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
603 ::osl::MutexGuard guard( theEnvironmentsData::get().mutex );
604 if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead
606 that->nRef = 0;
607 return;
610 ::osl_incrementInterlockedCount( &that->nWeakRef );
611 *ppHardEnv = pEnv;
614 //------------------------------------------------------------------------------
615 static void SAL_CALL defenv_dispose( uno_Environment * )
620 //______________________________________________________________________________
621 uno_DefaultEnvironment::uno_DefaultEnvironment(
622 const OUString & rEnvDcp_, void * pContext_ )
623 : nRef( 0 ),
624 nWeakRef( 0 )
626 uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
627 that->pReserved = 0;
628 // functions
629 that->acquire = defenv_acquire;
630 that->release = defenv_release;
631 that->acquireWeak = defenv_acquireWeak;
632 that->releaseWeak = defenv_releaseWeak;
633 that->harden = defenv_harden;
634 that->dispose = defenv_dispose;
635 that->pExtEnv = this;
636 // identifier
637 ::rtl_uString_acquire( rEnvDcp_.pData );
638 that->pTypeName = rEnvDcp_.pData;
639 that->pContext = pContext_;
641 // will be late initialized
642 that->environmentDisposing = 0;
644 uno_ExtEnvironment::registerInterface = defenv_registerInterface;
645 uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
646 uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
647 uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
648 uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
649 uno_ExtEnvironment::getRegisteredInterfaces =
650 defenv_getRegisteredInterfaces;
654 //______________________________________________________________________________
655 uno_DefaultEnvironment::~uno_DefaultEnvironment()
657 ::rtl_uString_release( ((uno_Environment *) this)->pTypeName );
660 //==============================================================================
661 static void writeLine(
662 void * stream, const sal_Char * pLine, const sal_Char * pFilter )
664 if (pFilter && *pFilter)
666 // lookup pFilter in pLine
667 while (*pLine)
669 if (*pLine == *pFilter)
671 sal_Int32 nPos = 1;
672 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
674 ++nPos;
676 if (! pFilter[nPos])
678 if (stream)
680 fprintf( (FILE *) stream, "%s\n", pLine );
682 else
684 OSL_TRACE( pLine );
685 OSL_TRACE( "\n" );
689 ++pLine;
692 else
694 if (stream)
696 fprintf( (FILE *) stream, "%s\n", pLine );
698 else
700 fprintf( stderr, "%s\n", pLine );
705 //==============================================================================
706 static void writeLine(
707 void * stream, const OUString & rLine, const sal_Char * pFilter )
709 ::rtl::OString aLine( ::rtl::OUStringToOString(
710 rLine, RTL_TEXTENCODING_ASCII_US ) );
711 writeLine( stream, aLine.getStr(), pFilter );
714 //##############################################################################
715 extern "C" void SAL_CALL uno_dumpEnvironment(
716 void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
717 SAL_THROW_EXTERN_C()
719 OSL_ENSURE( pEnv, "### null ptr!" );
720 ::rtl::OUStringBuffer buf;
722 if (! pEnv->pExtEnv)
724 writeLine( stream, "###################################"
725 "###########################################", pFilter );
726 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") );
727 buf.append( pEnv->pTypeName );
728 writeLine( stream, buf.makeStringAndClear(), pFilter );
729 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
730 return;
733 writeLine( stream, "########################################"
734 "######################################", pFilter );
735 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") );
736 buf.append( pEnv->pTypeName );
737 writeLine( stream, buf.makeStringAndClear(), pFilter );
739 uno_DefaultEnvironment * that =
740 reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
741 ::osl::MutexGuard guard( that->mutex );
743 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
744 OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
745 while (iPos != that->aOId2ObjectMap.end())
747 ObjectEntry * pOEntry = iPos->second;
749 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") );
750 if (pOEntry->mixedObject)
751 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") );
752 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") );
753 buf.append( pOEntry->nRef, 10 );
754 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") );
755 buf.append( pOEntry->oid );
756 buf.append( (sal_Unicode) '\"' );
757 writeLine( stream, buf.makeStringAndClear(), pFilter );
759 for ( ::std::size_t nPos = 0;
760 nPos < pOEntry->aInterfaces.size(); ++nPos )
762 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
764 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") );
765 buf.append(
766 ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName );
767 if (rIEntry.fpFreeProxy)
769 buf.appendAscii(
770 RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
771 buf.append(
772 reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
774 else
776 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
778 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
779 buf.append(
780 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
782 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
784 ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
785 if (erased != 1)
787 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
788 " (ptr not found in map!)") );
791 writeLine( stream, buf.makeStringAndClear(), pFilter );
793 ++iPos;
795 if (! ptr2obj.empty())
796 writeLine( stream, "ptr map inconsistency!!!", pFilter );
797 writeLine( stream, "#####################################"
798 "#########################################", pFilter );
801 //##############################################################################
802 extern "C" void SAL_CALL uno_dumpEnvironmentByName(
803 void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
804 SAL_THROW_EXTERN_C()
806 uno_Environment * pEnv = 0;
807 uno_getEnvironment( &pEnv, pEnvDcp, 0 );
808 if (pEnv)
810 ::uno_dumpEnvironment( stream, pEnv, pFilter );
811 (*pEnv->release)( pEnv );
813 else
815 ::rtl::OUStringBuffer buf( 32 );
816 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") );
817 buf.append( pEnvDcp );
818 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") );
819 writeLine( stream, buf.makeStringAndClear(), pFilter );
823 //------------------------------------------------------------------------------
824 inline static const OUString & unoenv_getStaticOIdPart()
826 static OUString * s_pStaticOidPart = 0;
827 if (! s_pStaticOidPart)
829 ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
830 if (! s_pStaticOidPart)
832 ::rtl::OUStringBuffer aRet( 64 );
833 aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
834 // pid
835 oslProcessInfo info;
836 info.Size = sizeof(oslProcessInfo);
837 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
838 osl_Process_E_None)
840 aRet.append( (sal_Int64)info.Ident, 16 );
842 else
844 aRet.appendAscii(
845 RTL_CONSTASCII_STRINGPARAM("unknown process id") );
847 // good guid
848 sal_uInt8 ar[16];
849 ::rtl_getGlobalProcessId( ar );
850 aRet.append( (sal_Unicode)';' );
851 for ( sal_Int32 i = 0; i < 16; ++i )
852 aRet.append( (sal_Int32)ar[i], 16 );
854 static OUString s_aStaticOidPart( aRet.makeStringAndClear() );
855 s_pStaticOidPart = &s_aStaticOidPart;
858 return *s_pStaticOidPart;
861 extern "C"
864 //------------------------------------------------------------------------------
865 static void SAL_CALL unoenv_computeObjectIdentifier(
866 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
868 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
869 if (*ppOId)
871 ::rtl_uString_release( *ppOId );
872 *ppOId = 0;
875 uno_Interface * pUnoI = (uno_Interface *)
876 ::cppu::binuno_queryInterface(
877 pInterface, *typelib_static_type_getByTypeClass(
878 typelib_TypeClass_INTERFACE ) );
879 if (0 != pUnoI)
881 (*pUnoI->release)( pUnoI );
882 // interface
883 ::rtl::OUStringBuffer oid( 64 );
884 oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
885 oid.append( static_cast< sal_Unicode >(';') );
886 // environment[context]
887 oid.append( ((uno_Environment *) pEnv)->pTypeName );
888 oid.append( static_cast< sal_Unicode >('[') );
889 oid.append( reinterpret_cast< sal_Int64 >(
890 reinterpret_cast<
891 uno_Environment * >(pEnv)->pContext ), 16 );
892 // process;good guid
893 oid.append( unoenv_getStaticOIdPart() );
894 OUString aStr( oid.makeStringAndClear() );
895 ::rtl_uString_acquire( *ppOId = aStr.pData );
899 //==============================================================================
900 static void SAL_CALL unoenv_acquireInterface(
901 uno_ExtEnvironment *, void * pUnoI_ )
903 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
904 (*pUnoI->acquire)( pUnoI );
907 //==============================================================================
908 static void SAL_CALL unoenv_releaseInterface(
909 uno_ExtEnvironment *, void * pUnoI_ )
911 uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
912 (*pUnoI->release)( pUnoI );
916 //______________________________________________________________________________
917 EnvironmentsData::~EnvironmentsData()
919 ::osl::MutexGuard guard( mutex );
921 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
922 iPos != aName2EnvMap.end(); ++iPos )
924 uno_Environment * pWeak = iPos->second;
925 uno_Environment * pHard = 0;
926 (*pWeak->harden)( &pHard, pWeak );
927 (*pWeak->releaseWeak)( pWeak );
929 if (pHard)
931 #if OSL_DEBUG_LEVEL > 1
932 ::uno_dumpEnvironment( 0, pHard, 0 );
933 #endif
934 #if defined CPPU_LEAK_STATIC_DATA
935 pHard->environmentDisposing = 0; // set to null => wont be called
936 #else
937 (*pHard->dispose)( pHard ); // send explicit dispose
938 #endif
939 (*pHard->release)( pHard );
944 //______________________________________________________________________________
945 inline void EnvironmentsData::getEnvironment(
946 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
948 if (*ppEnv)
950 (*(*ppEnv)->release)( *ppEnv );
951 *ppEnv = 0;
954 OUString aKey(
955 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) );
956 aKey += rEnvDcp;
958 // try to find registered mapping
959 OUString2EnvironmentMap::const_iterator const iFind(
960 aName2EnvMap.find( aKey ) );
961 if (iFind != aName2EnvMap.end())
963 uno_Environment * pWeak = iFind->second;
964 (*pWeak->harden)( ppEnv, pWeak );
968 //______________________________________________________________________________
969 inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
971 OSL_ENSURE( ppEnv, "### null ptr!" );
972 uno_Environment * pEnv = *ppEnv;
974 OUString aKey(
975 OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
976 aKey += pEnv->pTypeName;
978 // try to find registered environment
979 OUString2EnvironmentMap::const_iterator const iFind(
980 aName2EnvMap.find( aKey ) );
981 if (iFind == aName2EnvMap.end())
983 (*pEnv->acquireWeak)( pEnv );
984 ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion(
985 aName2EnvMap.insert(
986 OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
987 OSL_ENSURE(
988 insertion.second, "### insertion of env into map failed?!" );
990 else
992 uno_Environment * pHard = 0;
993 uno_Environment * pWeak = iFind->second;
994 (*pWeak->harden)( &pHard, pWeak );
995 if (pHard)
997 if (pEnv)
998 (*pEnv->release)( pEnv );
999 *ppEnv = pHard;
1001 else // registered one is dead
1003 (*pWeak->releaseWeak)( pWeak );
1004 (*pEnv->acquireWeak)( pEnv );
1005 aName2EnvMap[ aKey ] = pEnv;
1010 //______________________________________________________________________________
1011 inline void EnvironmentsData::getRegisteredEnvironments(
1012 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1013 const OUString & rEnvDcp )
1015 OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" );
1017 // max size
1018 uno_Environment ** ppFound = (uno_Environment **)alloca(
1019 sizeof(uno_Environment *) * aName2EnvMap.size() );
1020 sal_Int32 nSize = 0;
1022 // find matching environment
1023 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
1024 iPos != aName2EnvMap.end(); ++iPos )
1026 uno_Environment * pWeak = iPos->second;
1027 if (!rEnvDcp.getLength() ||
1028 rEnvDcp.equals( pWeak->pTypeName ))
1030 ppFound[nSize] = 0;
1031 (*pWeak->harden)( &ppFound[nSize], pWeak );
1032 if (ppFound[nSize])
1033 ++nSize;
1037 *pnLen = nSize;
1038 if (nSize)
1040 *pppEnvs = (uno_Environment **) (*memAlloc)(
1041 sizeof (uno_Environment *) * nSize );
1042 OSL_ASSERT( *pppEnvs );
1043 while (nSize--)
1045 (*pppEnvs)[nSize] = ppFound[nSize];
1048 else
1050 *pppEnvs = 0;
1054 static bool loadEnv(OUString const & cLibStem,
1055 uno_Environment * pEnv,
1056 void * /*pContext*/)
1058 // late init with some code from matching uno language binding
1059 // will be unloaded by environment
1060 oslModule hMod = cppu::detail::loadModule( cLibStem );
1062 if (!hMod)
1063 return false;
1065 OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT));
1066 uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc)
1067 ::osl_getFunctionSymbol( hMod, aSymbolName.pData );
1068 if (!fpInit)
1070 ::osl_unloadModule( hMod );
1071 return false;
1074 (*fpInit)( pEnv ); // init of environment
1075 ::rtl_registerModuleForUnloading( hMod );
1077 return true;
1081 extern "C"
1084 //------------------------------------------------------------------------------
1085 static uno_Environment * initDefaultEnvironment(
1086 const OUString & rEnvDcp, void * pContext )
1088 uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
1089 (*pEnv->acquire)( pEnv );
1091 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1093 // create default environment
1094 if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
1096 uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
1097 that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1098 that->acquireInterface = unoenv_acquireInterface;
1099 that->releaseInterface = unoenv_releaseInterface;
1101 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1102 if (envPurpose.getLength())
1104 rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
1105 libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") );
1107 if(!loadEnv(libStem, pEnv, pContext))
1109 pEnv->release(pEnv);
1110 return NULL;
1114 else
1116 // late init with some code from matching uno language binding
1117 ::rtl::OUStringBuffer aLibName( 16 );
1118 aLibName.append( envTypeName );
1119 aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) );
1120 OUString aStr( aLibName.makeStringAndClear() );
1122 if (!loadEnv(aStr, pEnv, pContext))
1124 pEnv->release(pEnv);
1125 return NULL;
1129 return pEnv;
1132 //##############################################################################
1133 void SAL_CALL uno_createEnvironment(
1134 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1135 SAL_THROW_EXTERN_C()
1137 OSL_ENSURE( ppEnv, "### null ptr!" );
1138 if (*ppEnv)
1139 (*(*ppEnv)->release)( *ppEnv );
1141 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1142 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1145 //##############################################################################
1146 void SAL_CALL uno_direct_getEnvironment(
1147 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1148 SAL_THROW_EXTERN_C()
1150 OSL_ENSURE( ppEnv, "### null ptr!" );
1151 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1153 EnvironmentsData & rData = theEnvironmentsData::get();
1155 ::osl::MutexGuard guard( rData.mutex );
1156 rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1157 if (! *ppEnv)
1159 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1160 if (*ppEnv)
1162 // register new environment:
1163 rData.registerEnvironment( ppEnv );
1168 //##############################################################################
1169 void SAL_CALL uno_getRegisteredEnvironments(
1170 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1171 rtl_uString * pEnvDcp )
1172 SAL_THROW_EXTERN_C()
1174 EnvironmentsData & rData = theEnvironmentsData::get();
1176 ::osl::MutexGuard guard( rData.mutex );
1177 rData.getRegisteredEnvironments(
1178 pppEnvs, pnLen, memAlloc,
1179 (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1182 } // extern "C"