1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: lbenv.cxx,v $
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"
54 #include "loadmodule.hxx"
61 using ::rtl::OUString
;
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
&&
74 ((typelib_TypeDescription
*) pTD1
)->pTypeName
->buffer
,
75 ((typelib_TypeDescription
*) pTD2
)->pTypeName
->buffer
) == 0));
79 struct uno_DefaultEnvironment
;
81 //------------------------------------------------------------------------------
86 uno_freeProxyFunc fpFreeProxy
;
87 typelib_InterfaceTypeDescription
* pTypeDescr
;
94 ::std::vector
< InterfaceEntry
> aInterfaces
;
97 inline ObjectEntry( const OUString
& rOId_
);
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 //------------------------------------------------------------------------------
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
143 OUString2EnvironmentMap aName2EnvMap
;
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
);
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 uno_DefaultEnvironment
* that
= (uno_DefaultEnvironment
*)pEnv
;
603 ::osl::MutexGuard
guard( theEnvironmentsData::get().mutex
);
604 if (1 == ::osl_incrementInterlockedCount( &that
->nRef
)) // is dead
610 ::osl_incrementInterlockedCount( &that
->nWeakRef
);
614 //------------------------------------------------------------------------------
615 static void SAL_CALL
defenv_dispose( uno_Environment
* )
620 //______________________________________________________________________________
621 uno_DefaultEnvironment::uno_DefaultEnvironment(
622 const OUString
& rEnvDcp_
, void * pContext_
)
626 uno_Environment
* that
= reinterpret_cast< uno_Environment
* >(this);
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;
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
669 if (*pLine
== *pFilter
)
672 while (pLine
[nPos
] && pFilter
[nPos
] == pLine
[nPos
])
680 fprintf( (FILE *) stream
, "%s\n", pLine
);
696 fprintf( (FILE *) stream
, "%s\n", pLine
);
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
)
719 OSL_ENSURE( pEnv
, "### null ptr!" );
720 ::rtl::OUStringBuffer buf
;
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
);
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(" - ") );
766 ((typelib_TypeDescription
*) rIEntry
.pTypeDescr
)->pTypeName
);
767 if (rIEntry
.fpFreeProxy
)
770 RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
772 reinterpret_cast< sal_IntPtr
>(rIEntry
.fpFreeProxy
), 16 );
776 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
778 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
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
);
787 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
788 " (ptr not found in map!)") );
791 writeLine( stream
, buf
.makeStringAndClear(), pFilter
);
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
)
806 uno_Environment
* pEnv
= 0;
807 uno_getEnvironment( &pEnv
, pEnvDcp
, 0 );
810 ::uno_dumpEnvironment( stream
, pEnv
, pFilter
);
811 (*pEnv
->release
)( pEnv
);
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("];") );
836 info
.Size
= sizeof(oslProcessInfo
);
837 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER
, &info
) ==
840 aRet
.append( (sal_Int64
)info
.Ident
, 16 );
845 RTL_CONSTASCII_STRINGPARAM("unknown process id") );
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
;
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!" );
871 ::rtl_uString_release( *ppOId
);
875 uno_Interface
* pUnoI
= (uno_Interface
*)
876 ::cppu::binuno_queryInterface(
877 pInterface
, *typelib_static_type_getByTypeClass(
878 typelib_TypeClass_INTERFACE
) );
881 (*pUnoI
->release
)( pUnoI
);
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
>(
891 uno_Environment
* >(pEnv
)->pContext
), 16 );
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
);
931 #if OSL_DEBUG_LEVEL > 1
932 ::uno_dumpEnvironment( 0, pHard
, 0 );
934 #if defined CPPU_LEAK_STATIC_DATA
935 pHard
->environmentDisposing
= 0; // set to null => wont be called
937 (*pHard
->dispose
)( pHard
); // send explicit dispose
939 (*pHard
->release
)( pHard
);
944 //______________________________________________________________________________
945 inline void EnvironmentsData::getEnvironment(
946 uno_Environment
** ppEnv
, const OUString
& rEnvDcp
, void * pContext
)
950 (*(*ppEnv
)->release
)( *ppEnv
);
955 OUString::valueOf( reinterpret_cast< sal_IntPtr
>(pContext
) ) );
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
;
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(
986 OUString2EnvironmentMap::value_type( aKey
, pEnv
) ) );
988 insertion
.second
, "### insertion of env into map failed?!" );
992 uno_Environment
* pHard
= 0;
993 uno_Environment
* pWeak
= iFind
->second
;
994 (*pWeak
->harden
)( &pHard
, pWeak
);
998 (*pEnv
->release
)( pEnv
);
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!" );
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
))
1031 (*pWeak
->harden
)( &ppFound
[nSize
], pWeak
);
1040 *pppEnvs
= (uno_Environment
**) (*memAlloc
)(
1041 sizeof (uno_Environment
*) * nSize
);
1042 OSL_ASSERT( *pppEnvs
);
1045 (*pppEnvs
)[nSize
] = ppFound
[nSize
];
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
);
1065 OUString
aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT
));
1066 uno_initEnvironmentFunc fpInit
= (uno_initEnvironmentFunc
)
1067 ::osl_getFunctionSymbol( hMod
, aSymbolName
.pData
);
1070 ::osl_unloadModule( hMod
);
1074 (*fpInit
)( pEnv
); // init of environment
1075 ::rtl_registerModuleForUnloading( hMod
);
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
);
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
);
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!" );
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
);
1159 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
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()) );