fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / cppu / source / uno / lbenv.cxx
blobcc7a02e3364aebf06d209e26ac695cbfb76b3b4a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include "cppu/EnvDcp.hxx"
24 #include "sal/alloca.h"
25 #include "sal/log.hxx"
26 #include "osl/diagnose.h"
27 #include "osl/interlck.h"
28 #include "osl/mutex.hxx"
29 #include "osl/module.h"
30 #include "osl/process.h"
31 #include "rtl/process.h"
32 #include "rtl/string.hxx"
33 #include "rtl/ustring.hxx"
34 #include "rtl/ustrbuf.hxx"
35 #include "rtl/instance.hxx"
36 #include "typelib/typedescription.h"
37 #include "uno/dispatcher.h"
38 #include "uno/environment.h"
39 #include "uno/lbnames.h"
40 #include "prim.hxx"
41 #include "destr.hxx"
42 #include "loadmodule.hxx"
44 #include <unordered_map>
45 #include <vector>
46 #include <stdio.h>
49 using ::rtl::OUString;
50 using ::rtl::OUStringHash;
52 namespace
56 inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
57 typelib_InterfaceTypeDescription * pTD2 )
59 return (pTD1 == pTD2 ||
60 (pTD1->aBase.pTypeName->length == pTD2->aBase.pTypeName->length &&
61 ::rtl_ustr_compare(
62 pTD1->aBase.pTypeName->buffer,
63 pTD2->aBase.pTypeName->buffer ) == 0));
66 struct ObjectEntry;
67 struct uno_DefaultEnvironment;
70 struct InterfaceEntry
72 sal_Int32 refCount;
73 void * pInterface;
74 uno_freeProxyFunc fpFreeProxy;
75 typelib_InterfaceTypeDescription * pTypeDescr;
78 struct ObjectEntry
80 OUString oid;
81 sal_Int32 nRef;
82 ::std::vector< InterfaceEntry > aInterfaces;
83 bool mixedObject;
85 inline ObjectEntry( const OUString & rOId_ );
87 inline void append(
88 uno_DefaultEnvironment * pEnv,
89 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
90 uno_freeProxyFunc fpFreeProxy );
91 inline InterfaceEntry * find(
92 typelib_InterfaceTypeDescription * pTypeDescr );
93 inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
97 struct FctPtrHash :
98 public ::std::unary_function< const void *, ::std::size_t >
100 ::std::size_t operator () ( const void * pKey ) const
101 { return reinterpret_cast< ::std::size_t>( pKey ); }
105 // mapping from environment name to environment
106 typedef std::unordered_map<
107 OUString, uno_Environment *, OUStringHash > OUString2EnvironmentMap;
109 // mapping from ptr to object entry
110 typedef std::unordered_map<
111 void *, ObjectEntry *, FctPtrHash,
112 ::std::equal_to< void * > > Ptr2ObjectMap;
113 // mapping from oid to object entry
114 typedef std::unordered_map<
115 OUString, ObjectEntry *, OUStringHash > OId2ObjectMap;
117 struct EnvironmentsData
119 ::osl::Mutex mutex;
120 OUString2EnvironmentMap aName2EnvMap;
122 EnvironmentsData() : isDisposing(false) {}
123 ~EnvironmentsData();
125 inline void getEnvironment(
126 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
127 inline void registerEnvironment( uno_Environment ** ppEnv );
128 inline void getRegisteredEnvironments(
129 uno_Environment *** pppEnvs, sal_Int32 * pnLen,
130 uno_memAlloc memAlloc, const OUString & rEnvDcp );
132 bool isDisposing;
135 struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
137 struct uno_DefaultEnvironment : public uno_ExtEnvironment
139 sal_Int32 nRef;
140 sal_Int32 nWeakRef;
142 ::osl::Mutex mutex;
143 Ptr2ObjectMap aPtr2ObjectMap;
144 OId2ObjectMap aOId2ObjectMap;
146 uno_DefaultEnvironment(
147 const OUString & rEnvDcp_, void * pContext_ );
148 ~uno_DefaultEnvironment();
152 inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
153 : oid( rOId_ ),
154 nRef( 0 ),
155 mixedObject( false )
157 aInterfaces.reserve( 2 );
161 inline void ObjectEntry::append(
162 uno_DefaultEnvironment * pEnv,
163 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
164 uno_freeProxyFunc fpFreeProxy )
166 InterfaceEntry aNewEntry;
167 if (! fpFreeProxy)
168 (*pEnv->acquireInterface)( pEnv, pInterface );
169 aNewEntry.refCount = 1;
170 aNewEntry.pInterface = pInterface;
171 aNewEntry.fpFreeProxy = fpFreeProxy;
172 typelib_typedescription_acquire( &pTypeDescr->aBase );
173 aNewEntry.pTypeDescr = pTypeDescr;
175 ::std::pair< Ptr2ObjectMap::iterator, bool > i(
176 pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type(
177 pInterface, this ) ) );
178 SAL_WARN_IF(
179 !i.second && (find(pInterface, 0) == -1 || i.first->second != this),
180 "cppu",
181 "map already contains " << i.first->second << " != " << this << " for "
182 << pInterface);
183 aInterfaces.push_back( aNewEntry );
187 inline InterfaceEntry * ObjectEntry::find(
188 typelib_InterfaceTypeDescription * pTypeDescr_ )
190 OSL_ASSERT( ! aInterfaces.empty() );
191 if (aInterfaces.empty())
192 return 0;
194 // shortcut common case:
195 OUString const & type_name =
196 OUString::unacquired( &pTypeDescr_->aBase.pTypeName );
197 if ( type_name == "com.sun.star.uno.XInterface" )
199 return &aInterfaces[ 0 ];
202 ::std::size_t nSize = aInterfaces.size();
203 for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
205 typelib_InterfaceTypeDescription * pITD =
206 aInterfaces[ nPos ].pTypeDescr;
207 while (pITD)
209 if (td_equals( pITD, pTypeDescr_ ))
210 return &aInterfaces[ nPos ];
211 pITD = pITD->pBaseTypeDescription;
214 return 0;
218 inline sal_Int32 ObjectEntry::find(
219 void * iface_ptr, ::std::size_t pos )
221 ::std::size_t size = aInterfaces.size();
222 for ( ; pos < size; ++pos )
224 if (aInterfaces[ pos ].pInterface == iface_ptr)
225 return pos;
227 return -1;
230 extern "C"
234 static void SAL_CALL defenv_registerInterface(
235 uno_ExtEnvironment * pEnv, void ** ppInterface,
236 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
238 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
239 OUString const & rOId = OUString::unacquired( &pOId );
241 uno_DefaultEnvironment * that =
242 static_cast< uno_DefaultEnvironment * >( pEnv );
243 ::osl::ClearableMutexGuard guard( that->mutex );
245 // try to insert dummy 0:
246 std::pair<OId2ObjectMap::iterator, bool> const insertion(
247 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, (ObjectEntry*)0 ) ) );
248 if (insertion.second)
250 ObjectEntry * pOEntry = new ObjectEntry( rOId );
251 insertion.first->second = pOEntry;
252 ++pOEntry->nRef; // another register call on object
253 pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
255 else // object entry exists
257 ObjectEntry * pOEntry = insertion.first->second;
258 ++pOEntry->nRef; // another register call on object
259 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
261 if (pIEntry) // type entry exists
263 ++pIEntry->refCount;
264 if (pIEntry->pInterface != *ppInterface)
266 void * pInterface = pIEntry->pInterface;
267 (*pEnv->acquireInterface)( pEnv, pInterface );
268 guard.clear();
269 (*pEnv->releaseInterface)( pEnv, *ppInterface );
270 *ppInterface = pInterface;
273 else
275 pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
281 static void SAL_CALL defenv_registerProxyInterface(
282 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
283 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
285 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
286 "### null ptr!" );
287 OUString const & rOId = OUString::unacquired( &pOId );
289 uno_DefaultEnvironment * that =
290 static_cast< uno_DefaultEnvironment * >( pEnv );
291 ::osl::ClearableMutexGuard guard( that->mutex );
293 // try to insert dummy 0:
294 std::pair<OId2ObjectMap::iterator, bool> const insertion(
295 that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, (ObjectEntry*)0 ) ) );
296 if (insertion.second)
298 ObjectEntry * pOEntry = new ObjectEntry( rOId );
299 insertion.first->second = pOEntry;
300 ++pOEntry->nRef; // another register call on object
301 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
303 else // object entry exists
305 ObjectEntry * pOEntry = insertion.first->second;
307 // first registration was an original, then registerProxyInterface():
308 pOEntry->mixedObject |=
309 (!pOEntry->aInterfaces.empty() &&
310 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
312 ++pOEntry->nRef; // another register call on object
313 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
315 if (pIEntry) // type entry exists
317 if (pIEntry->pInterface == *ppInterface)
319 ++pIEntry->refCount;
321 else
323 void * pInterface = pIEntry->pInterface;
324 (*pEnv->acquireInterface)( pEnv, pInterface );
325 --pOEntry->nRef; // manual revoke of proxy to be freed
326 guard.clear();
327 (*freeProxy)( pEnv, *ppInterface );
328 *ppInterface = pInterface;
331 else
333 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
339 static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
341 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
342 void * pInterface = va_arg(*pParam, void *);
344 OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
345 uno_DefaultEnvironment * that =
346 static_cast< uno_DefaultEnvironment * >( pEnv );
347 ::osl::ClearableMutexGuard guard( that->mutex );
349 Ptr2ObjectMap::const_iterator const iFind(
350 that->aPtr2ObjectMap.find( pInterface ) );
351 OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
352 ObjectEntry * pOEntry = iFind->second;
353 if (! --pOEntry->nRef)
355 // cleanup maps
356 that->aOId2ObjectMap.erase( pOEntry->oid );
357 sal_Int32 nPos;
358 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
360 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
363 // the last proxy interface of the environment might kill this
364 // environment, because of releasing its language binding!!!
365 guard.clear();
367 // release interfaces
368 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
370 InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
371 typelib_typedescription_release( &rEntry.pTypeDescr->aBase );
372 if (rEntry.fpFreeProxy) // is proxy or used interface?
374 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
376 else
378 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
382 delete pOEntry;
384 else if (pOEntry->mixedObject)
386 OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
387 pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
389 sal_Int32 index = pOEntry->find( pInterface, 1 );
390 OSL_ASSERT( index > 0 );
391 if (index > 0)
393 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
394 OSL_ASSERT( entry.pInterface == pInterface );
395 if (entry.fpFreeProxy != 0)
397 --entry.refCount;
398 if (entry.refCount == 0)
400 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
401 typelib_TypeDescription * pTypeDescr =
402 reinterpret_cast< typelib_TypeDescription * >(
403 entry.pTypeDescr );
405 pOEntry->aInterfaces.erase(
406 pOEntry->aInterfaces.begin() + index );
407 if (pOEntry->find( pInterface, index ) < 0)
409 // proxy ptr not registered for another interface:
410 // remove from ptr map
411 #if OSL_DEBUG_LEVEL > 0
412 ::std::size_t erased =
413 #endif
414 that->aPtr2ObjectMap.erase( pInterface );
415 OSL_ASSERT( erased == 1 );
418 guard.clear();
420 typelib_typedescription_release( pTypeDescr );
421 (*fpFreeProxy)( pEnv, pInterface );
428 static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
430 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
434 static void SAL_CALL defenv_getObjectIdentifier(
435 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
437 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
438 if (*ppOId)
440 ::rtl_uString_release( *ppOId );
441 *ppOId = 0;
444 uno_DefaultEnvironment * that =
445 static_cast< uno_DefaultEnvironment * >( pEnv );
446 ::osl::ClearableMutexGuard guard( that->mutex );
448 Ptr2ObjectMap::const_iterator const iFind(
449 that->aPtr2ObjectMap.find( pInterface ) );
450 if (iFind == that->aPtr2ObjectMap.end())
452 guard.clear();
453 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
455 else
457 rtl_uString * hstr = iFind->second->oid.pData;
458 rtl_uString_acquire( hstr );
459 *ppOId = hstr;
464 static void SAL_CALL defenv_getRegisteredInterface(
465 uno_ExtEnvironment * pEnv, void ** ppInterface,
466 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
468 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
469 if (*ppInterface)
471 (*pEnv->releaseInterface)( pEnv, *ppInterface );
472 *ppInterface = 0;
475 OUString const & rOId = OUString::unacquired( &pOId );
476 uno_DefaultEnvironment * that =
477 static_cast< uno_DefaultEnvironment * >( pEnv );
478 ::osl::MutexGuard guard( that->mutex );
480 OId2ObjectMap::const_iterator const iFind
481 ( that->aOId2ObjectMap.find( rOId ) );
482 if (iFind != that->aOId2ObjectMap.end())
484 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
485 if (pIEntry)
487 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
488 *ppInterface = pIEntry->pInterface;
494 static void SAL_CALL defenv_getRegisteredInterfaces(
495 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
496 uno_memAlloc memAlloc )
498 assert(pEnv && pppInterfaces && pnLen && memAlloc && "### null ptr!");
499 uno_DefaultEnvironment * that =
500 static_cast< uno_DefaultEnvironment * >( pEnv );
501 ::osl::MutexGuard guard( that->mutex );
503 sal_Int32 nLen = that->aPtr2ObjectMap.size();
504 sal_Int32 nPos = 0;
505 void ** ppInterfaces = static_cast<void **>((*memAlloc)( nLen * sizeof (void *) ));
507 Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
508 Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
509 while (iPos != iEnd)
511 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
512 ++iPos;
515 *pppInterfaces = ppInterfaces;
516 *pnLen = nLen;
520 static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
522 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
523 osl_atomic_increment( &that->nWeakRef );
524 osl_atomic_increment( &that->nRef );
528 static void SAL_CALL defenv_release( uno_Environment * pEnv )
530 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
531 if (! osl_atomic_decrement( &that->nRef ))
533 // invoke dispose callback
534 if (pEnv->environmentDisposing)
536 (*pEnv->environmentDisposing)( pEnv );
539 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
541 // free memory if no weak refs left
542 if (! osl_atomic_decrement( &that->nWeakRef ))
544 delete that;
549 static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
551 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
552 osl_atomic_increment( &that->nWeakRef );
556 static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
558 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
559 if (! osl_atomic_decrement( &that->nWeakRef ))
561 delete that;
566 static void SAL_CALL defenv_harden(
567 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
569 if (*ppHardEnv)
571 (*(*ppHardEnv)->release)( *ppHardEnv );
572 *ppHardEnv = 0;
575 EnvironmentsData & rData = theEnvironmentsData::get();
577 if (rData.isDisposing)
578 return;
580 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
582 ::osl::MutexGuard guard( rData.mutex );
583 if (1 == osl_atomic_increment( &that->nRef )) // is dead
585 that->nRef = 0;
586 return;
589 osl_atomic_increment( &that->nWeakRef );
590 *ppHardEnv = pEnv;
594 static void SAL_CALL defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
600 uno_DefaultEnvironment::uno_DefaultEnvironment(
601 const OUString & rEnvDcp_, void * pContext_ )
602 : nRef( 0 ),
603 nWeakRef( 0 )
605 uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
606 that->pReserved = 0;
607 // functions
608 that->acquire = defenv_acquire;
609 that->release = defenv_release;
610 that->acquireWeak = defenv_acquireWeak;
611 that->releaseWeak = defenv_releaseWeak;
612 that->harden = defenv_harden;
613 that->dispose = defenv_dispose;
614 that->pExtEnv = this;
615 // identifier
616 ::rtl_uString_acquire( rEnvDcp_.pData );
617 that->pTypeName = rEnvDcp_.pData;
618 that->pContext = pContext_;
620 // will be late initialized
621 that->environmentDisposing = 0;
623 uno_ExtEnvironment::registerInterface = defenv_registerInterface;
624 uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
625 uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
626 uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
627 uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
628 uno_ExtEnvironment::getRegisteredInterfaces =
629 defenv_getRegisteredInterfaces;
634 uno_DefaultEnvironment::~uno_DefaultEnvironment()
636 ::rtl_uString_release( aBase.pTypeName );
640 static void writeLine(
641 void * stream, const sal_Char * pLine, const sal_Char * pFilter )
643 if (pFilter && *pFilter)
645 // lookup pFilter in pLine
646 while (*pLine)
648 if (*pLine == *pFilter)
650 sal_Int32 nPos = 1;
651 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
653 ++nPos;
655 if (! pFilter[nPos])
657 if (stream)
659 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
661 else
663 OSL_TRACE( "%s", pLine );
667 ++pLine;
670 else
672 if (stream)
674 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
676 else
678 fprintf( stderr, "%s\n", pLine );
684 static void writeLine(
685 void * stream, const OUString & rLine, const sal_Char * pFilter )
687 ::rtl::OString aLine( ::rtl::OUStringToOString(
688 rLine, RTL_TEXTENCODING_ASCII_US ) );
689 writeLine( stream, aLine.getStr(), pFilter );
694 extern "C" void SAL_CALL uno_dumpEnvironment(
695 void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
696 SAL_THROW_EXTERN_C()
698 OSL_ENSURE( pEnv, "### null ptr!" );
699 ::rtl::OUStringBuffer buf;
701 if (! pEnv->pExtEnv)
703 writeLine( stream, "###################################"
704 "###########################################", pFilter );
705 buf.append( "environment: " );
706 buf.append( pEnv->pTypeName );
707 writeLine( stream, buf.makeStringAndClear(), pFilter );
708 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
709 return;
712 writeLine( stream, "########################################"
713 "######################################", pFilter );
714 buf.append( "environment dump: " );
715 buf.append( pEnv->pTypeName );
716 writeLine( stream, buf.makeStringAndClear(), pFilter );
718 uno_DefaultEnvironment * that =
719 reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
720 ::osl::MutexGuard guard( that->mutex );
722 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
723 OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
724 while (iPos != that->aOId2ObjectMap.end())
726 ObjectEntry * pOEntry = iPos->second;
728 buf.append( "+ " );
729 if (pOEntry->mixedObject)
730 buf.append( "mixed " );
731 buf.append( "object entry: nRef=" );
732 buf.append( pOEntry->nRef, 10 );
733 buf.append( "; oid=\"" );
734 buf.append( pOEntry->oid );
735 buf.append( '\"' );
736 writeLine( stream, buf.makeStringAndClear(), pFilter );
738 for ( ::std::size_t nPos = 0;
739 nPos < pOEntry->aInterfaces.size(); ++nPos )
741 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
743 buf.append( " - " );
744 buf.append( rIEntry.pTypeDescr->aBase.pTypeName );
745 if (rIEntry.fpFreeProxy)
747 buf.append( "; proxy free=0x" );
748 buf.append(
749 reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
751 else
753 buf.append( "; original" );
755 buf.append( "; ptr=0x" );
756 buf.append(
757 reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
759 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
761 ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
762 if (erased != 1)
764 buf.append( " (ptr not found in map!)" );
767 writeLine( stream, buf.makeStringAndClear(), pFilter );
769 ++iPos;
771 if (! ptr2obj.empty())
772 writeLine( stream, "ptr map inconsistency!!!", pFilter );
773 writeLine( stream, "#####################################"
774 "#########################################", pFilter );
778 extern "C" void SAL_CALL uno_dumpEnvironmentByName(
779 void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
780 SAL_THROW_EXTERN_C()
782 uno_Environment * pEnv = 0;
783 uno_getEnvironment( &pEnv, pEnvDcp, 0 );
784 if (pEnv)
786 ::uno_dumpEnvironment( stream, pEnv, pFilter );
787 (*pEnv->release)( pEnv );
789 else
791 ::rtl::OUStringBuffer buf( 32 );
792 buf.append( "environment \"" );
793 buf.append( pEnvDcp );
794 buf.append( "\" does not exist!" );
795 writeLine( stream, buf.makeStringAndClear(), pFilter );
799 namespace
801 class makeOIdPart
803 private:
804 OUString m_sOidPart;
805 public:
806 makeOIdPart()
808 ::rtl::OUStringBuffer aRet( 64 );
809 aRet.append( "];" );
810 // pid
811 oslProcessInfo info;
812 info.Size = sizeof(oslProcessInfo);
813 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
814 osl_Process_E_None)
816 aRet.append( (sal_Int64)info.Ident, 16 );
818 else
820 aRet.append( "unknown process id" );
822 // good guid
823 sal_uInt8 ar[16];
824 ::rtl_getGlobalProcessId( ar );
825 aRet.append( ';' );
826 for ( sal_Int32 i = 0; i < 16; ++i )
827 aRet.append( (sal_Int32)ar[i], 16 );
829 m_sOidPart = aRet.makeStringAndClear();
831 const OUString& getOIdPart() const { return m_sOidPart; }
834 class theStaticOIdPart : public rtl::Static<makeOIdPart, theStaticOIdPart> {};
836 inline static const OUString & unoenv_getStaticOIdPart()
838 return theStaticOIdPart::get().getOIdPart();
843 extern "C"
847 static void SAL_CALL unoenv_computeObjectIdentifier(
848 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
850 assert(pEnv && ppOId && pInterface && "### null ptr!");
851 if (*ppOId)
853 ::rtl_uString_release( *ppOId );
854 *ppOId = 0;
857 uno_Interface * pUnoI = static_cast<uno_Interface *>(
858 ::cppu::binuno_queryInterface(
859 pInterface, *typelib_static_type_getByTypeClass(
860 typelib_TypeClass_INTERFACE ) ));
861 if (0 != pUnoI)
863 (*pUnoI->release)( pUnoI );
864 // interface
865 ::rtl::OUStringBuffer oid( 64 );
866 oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
867 oid.append( ';' );
868 // environment[context]
869 oid.append( pEnv->aBase.pTypeName );
870 oid.append( '[' );
871 oid.append( reinterpret_cast< sal_Int64 >(
872 reinterpret_cast<
873 uno_Environment * >(pEnv)->pContext ), 16 );
874 // process;good guid
875 oid.append( unoenv_getStaticOIdPart() );
876 OUString aStr( oid.makeStringAndClear() );
877 ::rtl_uString_acquire( *ppOId = aStr.pData );
882 static void SAL_CALL unoenv_acquireInterface(
883 SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
885 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
886 (*pUnoI->acquire)( pUnoI );
890 static void SAL_CALL unoenv_releaseInterface(
891 SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
893 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
894 (*pUnoI->release)( pUnoI );
898 namespace {
900 EnvironmentsData::~EnvironmentsData()
902 ::osl::MutexGuard guard( mutex );
903 isDisposing = true;
905 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
906 iPos != aName2EnvMap.end(); ++iPos )
908 uno_Environment * pWeak = iPos->second;
909 uno_Environment * pHard = 0;
910 (*pWeak->harden)( &pHard, pWeak );
911 (*pWeak->releaseWeak)( pWeak );
913 if (pHard)
915 #if OSL_DEBUG_LEVEL > 1
916 ::uno_dumpEnvironment( 0, pHard, 0 );
917 #endif
918 (*pHard->dispose)( pHard ); // send explicit dispose
919 (*pHard->release)( pHard );
925 inline void EnvironmentsData::getEnvironment(
926 uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
928 if (*ppEnv)
930 (*(*ppEnv)->release)( *ppEnv );
931 *ppEnv = 0;
934 OUString aKey(
935 OUString::number( reinterpret_cast< sal_IntPtr >(pContext) ) );
936 aKey += rEnvDcp;
938 // try to find registered mapping
939 OUString2EnvironmentMap::const_iterator const iFind(
940 aName2EnvMap.find( aKey ) );
941 if (iFind != aName2EnvMap.end())
943 uno_Environment * pWeak = iFind->second;
944 (*pWeak->harden)( ppEnv, pWeak );
949 inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
951 OSL_ENSURE( ppEnv, "### null ptr!" );
952 uno_Environment * pEnv = *ppEnv;
954 OUString aKey(
955 OUString::number( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
956 aKey += pEnv->pTypeName;
958 // try to find registered environment
959 OUString2EnvironmentMap::const_iterator const iFind(
960 aName2EnvMap.find( aKey ) );
961 if (iFind == aName2EnvMap.end())
963 (*pEnv->acquireWeak)( pEnv );
964 ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion (
965 aName2EnvMap.insert(
966 OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
967 SAL_WARN_IF( !insertion.second, "cppu", "key " << aKey << " already in env map" );
969 else
971 uno_Environment * pHard = 0;
972 uno_Environment * pWeak = iFind->second;
973 (*pWeak->harden)( &pHard, pWeak );
974 if (pHard)
976 (*pEnv->release)( pEnv );
977 *ppEnv = pHard;
979 else // registered one is dead
981 (*pWeak->releaseWeak)( pWeak );
982 (*pEnv->acquireWeak)( pEnv );
983 aName2EnvMap[ aKey ] = pEnv;
989 inline void EnvironmentsData::getRegisteredEnvironments(
990 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
991 const OUString & rEnvDcp )
993 assert(pppEnvs && pnLen && memAlloc && "### null ptr!");
995 // max size
996 uno_Environment ** ppFound = static_cast<uno_Environment **>(alloca(
997 sizeof(uno_Environment *) * aName2EnvMap.size() ));
998 sal_Int32 nSize = 0;
1000 // find matching environment
1001 for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
1002 iPos != aName2EnvMap.end(); ++iPos )
1004 uno_Environment * pWeak = iPos->second;
1005 if (rEnvDcp.isEmpty() ||
1006 rEnvDcp.equals( pWeak->pTypeName ))
1008 ppFound[nSize] = 0;
1009 (*pWeak->harden)( &ppFound[nSize], pWeak );
1010 if (ppFound[nSize])
1011 ++nSize;
1015 *pnLen = nSize;
1016 if (nSize)
1018 *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
1019 sizeof (uno_Environment *) * nSize ));
1020 OSL_ASSERT( *pppEnvs );
1021 while (nSize--)
1023 (*pppEnvs)[nSize] = ppFound[nSize];
1026 else
1028 *pppEnvs = 0;
1032 static bool loadEnv(OUString const & cLibStem,
1033 uno_Environment * pEnv)
1035 #ifdef DISABLE_DYNLOADING
1036 uno_initEnvironmentFunc fpInit;
1038 if ( cLibStem == CPPU_CURRENT_LANGUAGE_BINDING_NAME "_uno" )
1039 fpInit = CPPU_ENV_uno_initEnvironment;
1040 #if HAVE_FEATURE_JAVA
1041 else if ( cLibStem == "java_uno" )
1042 fpInit = java_uno_initEnvironment;
1043 #endif
1044 else
1046 #if OSL_DEBUG_LEVEL > 1
1047 OSL_TRACE( "%s: Unhandled env: %s", __PRETTY_FUNCTION__, OUStringToOString( cLibStem, RTL_TEXTENCODING_ASCII_US).getStr() );
1048 #endif
1049 return false;
1051 #else
1052 // late init with some code from matching uno language binding
1053 // will be unloaded by environment
1054 osl::Module aMod;
1055 bool bMod = cppu::detail::loadModule(aMod, cLibStem);
1057 if (!bMod)
1058 return false;
1060 OUString aSymbolName(UNO_INIT_ENVIRONMENT);
1061 uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(aSymbolName));
1063 if (!fpInit)
1064 return false;
1066 aMod.release();
1067 #endif
1069 (*fpInit)( pEnv ); // init of environment
1070 return true;
1075 extern "C"
1079 static uno_Environment * initDefaultEnvironment(
1080 const OUString & rEnvDcp, void * pContext )
1082 uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
1083 (*pEnv->acquire)( pEnv );
1085 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1087 // create default environment
1088 if ( envTypeName == UNO_LB_UNO )
1090 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
1091 that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1092 that->acquireInterface = unoenv_acquireInterface;
1093 that->releaseInterface = unoenv_releaseInterface;
1095 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1096 if (!envPurpose.isEmpty())
1098 rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
1099 libStem += rtl::OUString("_uno_uno");
1101 if(!loadEnv(libStem, pEnv))
1103 pEnv->release(pEnv);
1104 return NULL;
1108 else
1110 // late init with some code from matching uno language binding
1111 ::rtl::OUStringBuffer aLibName( 16 );
1112 aLibName.append( envTypeName );
1113 aLibName.append( "_uno" );
1114 OUString aStr( aLibName.makeStringAndClear() );
1116 if (!loadEnv(aStr, pEnv))
1118 pEnv->release(pEnv);
1119 return NULL;
1123 return pEnv;
1127 void SAL_CALL uno_createEnvironment(
1128 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1129 SAL_THROW_EXTERN_C()
1131 assert(ppEnv && "### null ptr!");
1132 if (*ppEnv)
1133 (*(*ppEnv)->release)( *ppEnv );
1135 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1136 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1139 void SAL_CALL uno_getEnvironment(
1140 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1141 SAL_THROW_EXTERN_C()
1143 assert(ppEnv && "### null ptr!");
1144 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1146 EnvironmentsData & rData = theEnvironmentsData::get();
1148 ::osl::MutexGuard guard( rData.mutex );
1149 rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1150 if (! *ppEnv)
1152 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1153 if (*ppEnv)
1155 // register new environment:
1156 rData.registerEnvironment( ppEnv );
1161 void SAL_CALL uno_getRegisteredEnvironments(
1162 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1163 rtl_uString * pEnvDcp )
1164 SAL_THROW_EXTERN_C()
1166 EnvironmentsData & rData = theEnvironmentsData::get();
1168 ::osl::MutexGuard guard( rData.mutex );
1169 rData.getRegisteredEnvironments(
1170 pppEnvs, pnLen, memAlloc,
1171 (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1174 } // extern "C"
1176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */