1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppu.hxx"
31 #include "cppu/EnvDcp.hxx"
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"
51 #include "loadmodule.hxx"
58 using ::rtl::OUString
;
63 //------------------------------------------------------------------------------
64 inline static bool td_equals( typelib_InterfaceTypeDescription
* pTD1
,
65 typelib_InterfaceTypeDescription
* pTD2
)
67 return (pTD1
== pTD2
||
68 (((typelib_TypeDescription
*)pTD1
)->pTypeName
->length
==
69 ((typelib_TypeDescription
*)pTD2
)->pTypeName
->length
&&
71 ((typelib_TypeDescription
*) pTD1
)->pTypeName
->buffer
,
72 ((typelib_TypeDescription
*) pTD2
)->pTypeName
->buffer
) == 0));
76 struct uno_DefaultEnvironment
;
78 //------------------------------------------------------------------------------
83 uno_freeProxyFunc fpFreeProxy
;
84 typelib_InterfaceTypeDescription
* pTypeDescr
;
91 ::std::vector
< InterfaceEntry
> aInterfaces
;
94 inline ObjectEntry( const OUString
& rOId_
);
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
);
105 //------------------------------------------------------------------------------
107 public ::std::unary_function
< const void *, ::std::size_t >
109 ::std::size_t operator () ( const void * pKey
) const
110 { return (::std::size_t) pKey
; }
113 //------------------------------------------------------------------------------
114 struct FctOUStringHash
:
115 public ::std::unary_function
< const OUString
&, ::std::size_t >
117 ::std::size_t operator () ( const OUString
& rKey
) const
118 { return rKey
.hashCode(); }
121 // mapping from environment name to environment
122 typedef ::std::hash_map
<
123 OUString
, uno_Environment
*, FctOUStringHash
,
124 ::std::equal_to
< OUString
> > OUString2EnvironmentMap
;
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
;
136 //==============================================================================
137 struct EnvironmentsData
140 OUString2EnvironmentMap aName2EnvMap
;
142 EnvironmentsData() : isDisposing(false) {}
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
);
157 struct theEnvironmentsData
: public rtl::Static
< EnvironmentsData
, theEnvironmentsData
> {};
160 //==============================================================================
161 struct uno_DefaultEnvironment
: public uno_ExtEnvironment
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_
)
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
;
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())
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
;
234 if (td_equals( pITD
, pTypeDescr_
))
235 return &aInterfaces
[ nPos
];
236 pITD
= pITD
->pBaseTypeDescription
;
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
)
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
289 if (pIEntry
->pInterface
!= *ppInterface
)
291 void * pInterface
= pIEntry
->pInterface
;
292 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
294 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
295 *ppInterface
= pInterface
;
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
,
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
)
348 void * pInterface
= pIEntry
->pInterface
;
349 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
350 --pOEntry
->nRef
; // manual revoke of proxy to be freed
352 (*freeProxy
)( pEnv
, *ppInterface
);
353 *ppInterface
= pInterface
;
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
)
381 that
->aOId2ObjectMap
.erase( pOEntry
->oid
);
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!!!
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
);
404 (*pEnv
->releaseInterface
)( pEnv
, rEntry
.pInterface
);
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 );
419 InterfaceEntry
& entry
= pOEntry
->aInterfaces
[ index
];
420 OSL_ASSERT( entry
.pInterface
== pInterface
);
421 if (entry
.fpFreeProxy
!= 0)
424 if (entry
.refCount
== 0)
426 uno_freeProxyFunc fpFreeProxy
= entry
.fpFreeProxy
;
427 typelib_TypeDescription
* pTypeDescr
=
428 reinterpret_cast< typelib_TypeDescription
* >(
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
=
440 that
->aPtr2ObjectMap
.erase( pInterface
);
441 OSL_ASSERT( erased
== 1 );
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!" );
466 ::rtl_uString_release( *ppOId
);
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())
479 (*pEnv
->computeObjectIdentifier
)( pEnv
, ppOId
, pInterface
);
483 rtl_uString
* hstr
= iFind
->second
->oid
.pData
;
484 rtl_uString_acquire( 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!" );
497 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
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
);
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();
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() );
537 (*pEnv
->acquireInterface
)( pEnv
, ppInterfaces
[nPos
++] = (*iPos
).first
);
541 *pppInterfaces
= ppInterfaces
;
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
))
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
))
591 //------------------------------------------------------------------------------
592 static void SAL_CALL
defenv_harden(
593 uno_Environment
** ppHardEnv
, uno_Environment
* pEnv
)
597 (*(*ppHardEnv
)->release
)( *ppHardEnv
);
601 EnvironmentsData
& rData
= theEnvironmentsData::get();
603 if (rData
.isDisposing
)
606 uno_DefaultEnvironment
* that
= (uno_DefaultEnvironment
*)pEnv
;
608 ::osl::MutexGuard
guard( rData
.mutex
);
609 if (1 == ::osl_incrementInterlockedCount( &that
->nRef
)) // is dead
615 ::osl_incrementInterlockedCount( &that
->nWeakRef
);
619 //------------------------------------------------------------------------------
620 static void SAL_CALL
defenv_dispose( uno_Environment
* )
625 //______________________________________________________________________________
626 uno_DefaultEnvironment::uno_DefaultEnvironment(
627 const OUString
& rEnvDcp_
, void * pContext_
)
631 uno_Environment
* that
= reinterpret_cast< uno_Environment
* >(this);
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;
642 ::rtl_uString_acquire( rEnvDcp_
.pData
);
643 that
->pTypeName
= rEnvDcp_
.pData
;
644 that
->pContext
= pContext_
;
646 // will be late initialized
647 that
->environmentDisposing
= 0;
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
;
659 //______________________________________________________________________________
660 uno_DefaultEnvironment::~uno_DefaultEnvironment()
662 ::rtl_uString_release( ((uno_Environment
*) this)->pTypeName
);
665 //==============================================================================
666 static void writeLine(
667 void * stream
, const sal_Char
* pLine
, const sal_Char
* pFilter
)
669 if (pFilter
&& *pFilter
)
671 // lookup pFilter in pLine
674 if (*pLine
== *pFilter
)
677 while (pLine
[nPos
] && pFilter
[nPos
] == pLine
[nPos
])
685 fprintf( (FILE *) stream
, "%s\n", pLine
);
701 fprintf( (FILE *) stream
, "%s\n", pLine
);
705 fprintf( stderr
, "%s\n", pLine
);
710 //==============================================================================
711 static void writeLine(
712 void * stream
, const OUString
& rLine
, const sal_Char
* pFilter
)
714 ::rtl::OString
aLine( ::rtl::OUStringToOString(
715 rLine
, RTL_TEXTENCODING_ASCII_US
) );
716 writeLine( stream
, aLine
.getStr(), pFilter
);
719 //##############################################################################
720 extern "C" void SAL_CALL
uno_dumpEnvironment(
721 void * stream
, uno_Environment
* pEnv
, const sal_Char
* pFilter
)
724 OSL_ENSURE( pEnv
, "### null ptr!" );
725 ::rtl::OUStringBuffer buf
;
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
);
738 writeLine( stream
, "########################################"
739 "######################################", pFilter
);
740 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") );
741 buf
.append( pEnv
->pTypeName
);
742 writeLine( stream
, buf
.makeStringAndClear(), pFilter
);
744 uno_DefaultEnvironment
* that
=
745 reinterpret_cast< uno_DefaultEnvironment
* >(pEnv
);
746 ::osl::MutexGuard
guard( that
->mutex
);
748 Ptr2ObjectMap
ptr2obj( that
->aPtr2ObjectMap
);
749 OId2ObjectMap::const_iterator
iPos( that
->aOId2ObjectMap
.begin() );
750 while (iPos
!= that
->aOId2ObjectMap
.end())
752 ObjectEntry
* pOEntry
= iPos
->second
;
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
);
764 for ( ::std::size_t nPos
= 0;
765 nPos
< pOEntry
->aInterfaces
.size(); ++nPos
)
767 const InterfaceEntry
& rIEntry
= pOEntry
->aInterfaces
[nPos
];
769 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") );
771 ((typelib_TypeDescription
*) rIEntry
.pTypeDescr
)->pTypeName
);
772 if (rIEntry
.fpFreeProxy
)
775 RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
777 reinterpret_cast< sal_IntPtr
>(rIEntry
.fpFreeProxy
), 16 );
781 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
783 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
785 reinterpret_cast< sal_IntPtr
>(rIEntry
.pInterface
), 16 );
787 if (pOEntry
->find( rIEntry
.pInterface
, nPos
+ 1 ) < 0)
789 ::std::size_t erased
= ptr2obj
.erase( rIEntry
.pInterface
);
792 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
793 " (ptr not found in map!)") );
796 writeLine( stream
, buf
.makeStringAndClear(), pFilter
);
800 if (! ptr2obj
.empty())
801 writeLine( stream
, "ptr map inconsistency!!!", pFilter
);
802 writeLine( stream
, "#####################################"
803 "#########################################", pFilter
);
806 //##############################################################################
807 extern "C" void SAL_CALL
uno_dumpEnvironmentByName(
808 void * stream
, rtl_uString
* pEnvDcp
, const sal_Char
* pFilter
)
811 uno_Environment
* pEnv
= 0;
812 uno_getEnvironment( &pEnv
, pEnvDcp
, 0 );
815 ::uno_dumpEnvironment( stream
, pEnv
, pFilter
);
816 (*pEnv
->release
)( pEnv
);
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
);
828 //------------------------------------------------------------------------------
829 inline static const OUString
& unoenv_getStaticOIdPart()
831 static OUString
* s_pStaticOidPart
= 0;
832 if (! s_pStaticOidPart
)
834 ::osl::MutexGuard
guard( ::osl::Mutex::getGlobalMutex() );
835 if (! s_pStaticOidPart
)
837 ::rtl::OUStringBuffer
aRet( 64 );
838 aRet
.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
841 info
.Size
= sizeof(oslProcessInfo
);
842 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER
, &info
) ==
845 aRet
.append( (sal_Int64
)info
.Ident
, 16 );
850 RTL_CONSTASCII_STRINGPARAM("unknown process id") );
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 );
859 static OUString
s_aStaticOidPart( aRet
.makeStringAndClear() );
860 s_pStaticOidPart
= &s_aStaticOidPart
;
863 return *s_pStaticOidPart
;
869 //------------------------------------------------------------------------------
870 static void SAL_CALL
unoenv_computeObjectIdentifier(
871 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
873 OSL_ENSURE( pEnv
&& ppOId
&& pInterface
, "### null ptr!" );
876 ::rtl_uString_release( *ppOId
);
880 uno_Interface
* pUnoI
= (uno_Interface
*)
881 ::cppu::binuno_queryInterface(
882 pInterface
, *typelib_static_type_getByTypeClass(
883 typelib_TypeClass_INTERFACE
) );
886 (*pUnoI
->release
)( pUnoI
);
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
>(
896 uno_Environment
* >(pEnv
)->pContext
), 16 );
898 oid
.append( unoenv_getStaticOIdPart() );
899 OUString
aStr( oid
.makeStringAndClear() );
900 ::rtl_uString_acquire( *ppOId
= aStr
.pData
);
904 //==============================================================================
905 static void SAL_CALL
unoenv_acquireInterface(
906 uno_ExtEnvironment
*, void * pUnoI_
)
908 uno_Interface
* pUnoI
= reinterpret_cast< uno_Interface
* >(pUnoI_
);
909 (*pUnoI
->acquire
)( pUnoI
);
912 //==============================================================================
913 static void SAL_CALL
unoenv_releaseInterface(
914 uno_ExtEnvironment
*, void * pUnoI_
)
916 uno_Interface
* pUnoI
= reinterpret_cast< uno_Interface
* >(pUnoI_
);
917 (*pUnoI
->release
)( pUnoI
);
921 //______________________________________________________________________________
922 EnvironmentsData::~EnvironmentsData()
924 ::osl::MutexGuard
guard( mutex
);
927 for ( OUString2EnvironmentMap::const_iterator
iPos( aName2EnvMap
.begin() );
928 iPos
!= aName2EnvMap
.end(); ++iPos
)
930 uno_Environment
* pWeak
= iPos
->second
;
931 uno_Environment
* pHard
= 0;
932 (*pWeak
->harden
)( &pHard
, pWeak
);
933 (*pWeak
->releaseWeak
)( pWeak
);
937 #if OSL_DEBUG_LEVEL > 1
938 ::uno_dumpEnvironment( 0, pHard
, 0 );
940 (*pHard
->dispose
)( pHard
); // send explicit dispose
941 (*pHard
->release
)( pHard
);
946 //______________________________________________________________________________
947 inline void EnvironmentsData::getEnvironment(
948 uno_Environment
** ppEnv
, const OUString
& rEnvDcp
, void * pContext
)
952 (*(*ppEnv
)->release
)( *ppEnv
);
957 OUString::valueOf( reinterpret_cast< sal_IntPtr
>(pContext
) ) );
960 // try to find registered mapping
961 OUString2EnvironmentMap::const_iterator
const iFind(
962 aName2EnvMap
.find( aKey
) );
963 if (iFind
!= aName2EnvMap
.end())
965 uno_Environment
* pWeak
= iFind
->second
;
966 (*pWeak
->harden
)( ppEnv
, pWeak
);
970 //______________________________________________________________________________
971 inline void EnvironmentsData::registerEnvironment( uno_Environment
** ppEnv
)
973 OSL_ENSURE( ppEnv
, "### null ptr!" );
974 uno_Environment
* pEnv
= *ppEnv
;
977 OUString::valueOf( reinterpret_cast< sal_IntPtr
>(pEnv
->pContext
) ) );
978 aKey
+= pEnv
->pTypeName
;
980 // try to find registered environment
981 OUString2EnvironmentMap::const_iterator
const iFind(
982 aName2EnvMap
.find( aKey
) );
983 if (iFind
== aName2EnvMap
.end())
985 (*pEnv
->acquireWeak
)( pEnv
);
986 ::std::pair
< OUString2EnvironmentMap::iterator
, bool > insertion(
988 OUString2EnvironmentMap::value_type( aKey
, pEnv
) ) );
990 insertion
.second
, "### insertion of env into map failed?!" );
994 uno_Environment
* pHard
= 0;
995 uno_Environment
* pWeak
= iFind
->second
;
996 (*pWeak
->harden
)( &pHard
, pWeak
);
1000 (*pEnv
->release
)( pEnv
);
1003 else // registered one is dead
1005 (*pWeak
->releaseWeak
)( pWeak
);
1006 (*pEnv
->acquireWeak
)( pEnv
);
1007 aName2EnvMap
[ aKey
] = pEnv
;
1012 //______________________________________________________________________________
1013 inline void EnvironmentsData::getRegisteredEnvironments(
1014 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
, uno_memAlloc memAlloc
,
1015 const OUString
& rEnvDcp
)
1017 OSL_ENSURE( pppEnvs
&& pnLen
&& memAlloc
, "### null ptr!" );
1020 uno_Environment
** ppFound
= (uno_Environment
**)alloca(
1021 sizeof(uno_Environment
*) * aName2EnvMap
.size() );
1022 sal_Int32 nSize
= 0;
1024 // find matching environment
1025 for ( OUString2EnvironmentMap::const_iterator
iPos( aName2EnvMap
.begin() );
1026 iPos
!= aName2EnvMap
.end(); ++iPos
)
1028 uno_Environment
* pWeak
= iPos
->second
;
1029 if (!rEnvDcp
.getLength() ||
1030 rEnvDcp
.equals( pWeak
->pTypeName
))
1033 (*pWeak
->harden
)( &ppFound
[nSize
], pWeak
);
1042 *pppEnvs
= (uno_Environment
**) (*memAlloc
)(
1043 sizeof (uno_Environment
*) * nSize
);
1044 OSL_ASSERT( *pppEnvs
);
1047 (*pppEnvs
)[nSize
] = ppFound
[nSize
];
1056 static bool loadEnv(OUString
const & cLibStem
,
1057 uno_Environment
* pEnv
,
1058 void * /*pContext*/)
1060 // late init with some code from matching uno language binding
1061 // will be unloaded by environment
1062 oslModule hMod
= cppu::detail::loadModule( cLibStem
);
1067 OUString
aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT
));
1068 uno_initEnvironmentFunc fpInit
= (uno_initEnvironmentFunc
)
1069 ::osl_getFunctionSymbol( hMod
, aSymbolName
.pData
);
1072 ::osl_unloadModule( hMod
);
1076 (*fpInit
)( pEnv
); // init of environment
1077 ::rtl_registerModuleForUnloading( hMod
);
1086 //------------------------------------------------------------------------------
1087 static uno_Environment
* initDefaultEnvironment(
1088 const OUString
& rEnvDcp
, void * pContext
)
1090 uno_Environment
* pEnv
= &(new uno_DefaultEnvironment( rEnvDcp
, pContext
))->aBase
;
1091 (*pEnv
->acquire
)( pEnv
);
1093 OUString envTypeName
= cppu::EnvDcp::getTypeName(rEnvDcp
);
1095 // create default environment
1096 if (envTypeName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO
) ))
1098 uno_DefaultEnvironment
* that
= (uno_DefaultEnvironment
*)pEnv
;
1099 that
->computeObjectIdentifier
= unoenv_computeObjectIdentifier
;
1100 that
->acquireInterface
= unoenv_acquireInterface
;
1101 that
->releaseInterface
= unoenv_releaseInterface
;
1103 OUString envPurpose
= cppu::EnvDcp::getPurpose(rEnvDcp
);
1104 if (envPurpose
.getLength())
1106 rtl::OUString libStem
= envPurpose
.copy(envPurpose
.lastIndexOf(':') + 1);
1107 libStem
+= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") );
1109 if(!loadEnv(libStem
, pEnv
, pContext
))
1111 pEnv
->release(pEnv
);
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() );
1124 if (!loadEnv(aStr
, pEnv
, pContext
))
1126 pEnv
->release(pEnv
);
1134 //##############################################################################
1135 void SAL_CALL
uno_createEnvironment(
1136 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
)
1137 SAL_THROW_EXTERN_C()
1139 OSL_ENSURE( ppEnv
, "### null ptr!" );
1141 (*(*ppEnv
)->release
)( *ppEnv
);
1143 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1144 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1147 //##############################################################################
1148 void SAL_CALL
uno_direct_getEnvironment(
1149 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
)
1150 SAL_THROW_EXTERN_C()
1152 OSL_ENSURE( ppEnv
, "### null ptr!" );
1153 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1155 EnvironmentsData
& rData
= theEnvironmentsData::get();
1157 ::osl::MutexGuard
guard( rData
.mutex
);
1158 rData
.getEnvironment( ppEnv
, rEnvDcp
, pContext
);
1161 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1164 // register new environment:
1165 rData
.registerEnvironment( ppEnv
);
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()
1176 EnvironmentsData
& rData
= theEnvironmentsData::get();
1178 ::osl::MutexGuard
guard( rData
.mutex
);
1179 rData
.getRegisteredEnvironments(
1180 pppEnvs
, pnLen
, memAlloc
,
1181 (pEnvDcp
? OUString(pEnvDcp
) : OUString()) );