1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
42 #include "loadmodule.hxx"
44 #include <unordered_map>
49 using ::rtl::OUString
;
50 using ::rtl::OUStringHash
;
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
&&
62 pTD1
->aBase
.pTypeName
->buffer
,
63 pTD2
->aBase
.pTypeName
->buffer
) == 0));
67 struct uno_DefaultEnvironment
;
74 uno_freeProxyFunc fpFreeProxy
;
75 typelib_InterfaceTypeDescription
* pTypeDescr
;
82 ::std::vector
< InterfaceEntry
> aInterfaces
;
85 inline ObjectEntry( const OUString
& rOId_
);
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
);
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
120 OUString2EnvironmentMap aName2EnvMap
;
122 EnvironmentsData() : isDisposing(false) {}
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
);
135 struct theEnvironmentsData
: public rtl::Static
< EnvironmentsData
, theEnvironmentsData
> {};
137 struct uno_DefaultEnvironment
: public uno_ExtEnvironment
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_
)
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
;
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 ) ) );
179 !i
.second
&& (find(pInterface
, 0) == -1 || i
.first
->second
!= this),
181 "map already contains " << i
.first
->second
<< " != " << this << " for "
183 aInterfaces
.push_back( aNewEntry
);
187 inline InterfaceEntry
* ObjectEntry::find(
188 typelib_InterfaceTypeDescription
* pTypeDescr_
)
190 OSL_ASSERT( ! aInterfaces
.empty() );
191 if (aInterfaces
.empty())
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
;
209 if (td_equals( pITD
, pTypeDescr_
))
210 return &aInterfaces
[ nPos
];
211 pITD
= pITD
->pBaseTypeDescription
;
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
)
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
264 if (pIEntry
->pInterface
!= *ppInterface
)
266 void * pInterface
= pIEntry
->pInterface
;
267 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
269 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
270 *ppInterface
= pInterface
;
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
,
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
)
323 void * pInterface
= pIEntry
->pInterface
;
324 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
325 --pOEntry
->nRef
; // manual revoke of proxy to be freed
327 (*freeProxy
)( pEnv
, *ppInterface
);
328 *ppInterface
= pInterface
;
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
)
356 that
->aOId2ObjectMap
.erase( pOEntry
->oid
);
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!!!
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
);
378 (*pEnv
->releaseInterface
)( pEnv
, rEntry
.pInterface
);
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 );
393 InterfaceEntry
& entry
= pOEntry
->aInterfaces
[ index
];
394 OSL_ASSERT( entry
.pInterface
== pInterface
);
395 if (entry
.fpFreeProxy
!= 0)
398 if (entry
.refCount
== 0)
400 uno_freeProxyFunc fpFreeProxy
= entry
.fpFreeProxy
;
401 typelib_TypeDescription
* pTypeDescr
=
402 reinterpret_cast< typelib_TypeDescription
* >(
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
=
414 that
->aPtr2ObjectMap
.erase( pInterface
);
415 OSL_ASSERT( erased
== 1 );
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!" );
440 ::rtl_uString_release( *ppOId
);
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())
453 (*pEnv
->computeObjectIdentifier
)( pEnv
, ppOId
, pInterface
);
457 rtl_uString
* hstr
= iFind
->second
->oid
.pData
;
458 rtl_uString_acquire( 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!" );
471 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
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
);
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();
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() );
511 (*pEnv
->acquireInterface
)( pEnv
, ppInterfaces
[nPos
++] = (*iPos
).first
);
515 *pppInterfaces
= ppInterfaces
;
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
))
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
))
566 static void SAL_CALL
defenv_harden(
567 uno_Environment
** ppHardEnv
, uno_Environment
* pEnv
)
571 (*(*ppHardEnv
)->release
)( *ppHardEnv
);
575 EnvironmentsData
& rData
= theEnvironmentsData::get();
577 if (rData
.isDisposing
)
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
589 osl_atomic_increment( &that
->nWeakRef
);
594 static void SAL_CALL
defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment
* )
600 uno_DefaultEnvironment::uno_DefaultEnvironment(
601 const OUString
& rEnvDcp_
, void * pContext_
)
605 uno_Environment
* that
= reinterpret_cast< uno_Environment
* >(this);
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;
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
648 if (*pLine
== *pFilter
)
651 while (pLine
[nPos
] && pFilter
[nPos
] == pLine
[nPos
])
659 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
663 OSL_TRACE( "%s", pLine
);
674 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
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
)
698 OSL_ENSURE( pEnv
, "### null ptr!" );
699 ::rtl::OUStringBuffer buf
;
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
);
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
;
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
);
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
];
744 buf
.append( rIEntry
.pTypeDescr
->aBase
.pTypeName
);
745 if (rIEntry
.fpFreeProxy
)
747 buf
.append( "; proxy free=0x" );
749 reinterpret_cast< sal_IntPtr
>(rIEntry
.fpFreeProxy
), 16 );
753 buf
.append( "; original" );
755 buf
.append( "; ptr=0x" );
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
);
764 buf
.append( " (ptr not found in map!)" );
767 writeLine( stream
, buf
.makeStringAndClear(), pFilter
);
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
)
782 uno_Environment
* pEnv
= 0;
783 uno_getEnvironment( &pEnv
, pEnvDcp
, 0 );
786 ::uno_dumpEnvironment( stream
, pEnv
, pFilter
);
787 (*pEnv
->release
)( pEnv
);
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
);
808 ::rtl::OUStringBuffer
aRet( 64 );
812 info
.Size
= sizeof(oslProcessInfo
);
813 if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER
, &info
) ==
816 aRet
.append( (sal_Int64
)info
.Ident
, 16 );
820 aRet
.append( "unknown process id" );
824 ::rtl_getGlobalProcessId( ar
);
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();
847 static void SAL_CALL
unoenv_computeObjectIdentifier(
848 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
850 assert(pEnv
&& ppOId
&& pInterface
&& "### null ptr!");
853 ::rtl_uString_release( *ppOId
);
857 uno_Interface
* pUnoI
= static_cast<uno_Interface
*>(
858 ::cppu::binuno_queryInterface(
859 pInterface
, *typelib_static_type_getByTypeClass(
860 typelib_TypeClass_INTERFACE
) ));
863 (*pUnoI
->release
)( pUnoI
);
865 ::rtl::OUStringBuffer
oid( 64 );
866 oid
.append( reinterpret_cast< sal_Int64
>(pUnoI
), 16 );
868 // environment[context]
869 oid
.append( pEnv
->aBase
.pTypeName
);
871 oid
.append( reinterpret_cast< sal_Int64
>(
873 uno_Environment
* >(pEnv
)->pContext
), 16 );
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
);
900 EnvironmentsData::~EnvironmentsData()
902 ::osl::MutexGuard
guard( mutex
);
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
);
915 #if OSL_DEBUG_LEVEL > 1
916 ::uno_dumpEnvironment( 0, pHard
, 0 );
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
)
930 (*(*ppEnv
)->release
)( *ppEnv
);
935 OUString::number( reinterpret_cast< sal_IntPtr
>(pContext
) ) );
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
;
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 (
966 OUString2EnvironmentMap::value_type( aKey
, pEnv
) ) );
967 SAL_WARN_IF( !insertion
.second
, "cppu", "key " << aKey
<< " already in env map" );
971 uno_Environment
* pHard
= 0;
972 uno_Environment
* pWeak
= iFind
->second
;
973 (*pWeak
->harden
)( &pHard
, pWeak
);
976 (*pEnv
->release
)( pEnv
);
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!");
996 uno_Environment
** ppFound
= static_cast<uno_Environment
**>(alloca(
997 sizeof(uno_Environment
*) * aName2EnvMap
.size() ));
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
))
1009 (*pWeak
->harden
)( &ppFound
[nSize
], pWeak
);
1018 *pppEnvs
= static_cast<uno_Environment
**>((*memAlloc
)(
1019 sizeof (uno_Environment
*) * nSize
));
1020 OSL_ASSERT( *pppEnvs
);
1023 (*pppEnvs
)[nSize
] = ppFound
[nSize
];
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
;
1046 #if OSL_DEBUG_LEVEL > 1
1047 OSL_TRACE( "%s: Unhandled env: %s", __PRETTY_FUNCTION__
, OUStringToOString( cLibStem
, RTL_TEXTENCODING_ASCII_US
).getStr() );
1052 // late init with some code from matching uno language binding
1053 // will be unloaded by environment
1055 bool bMod
= cppu::detail::loadModule(aMod
, cLibStem
);
1060 OUString
aSymbolName(UNO_INIT_ENVIRONMENT
);
1061 uno_initEnvironmentFunc fpInit
= reinterpret_cast<uno_initEnvironmentFunc
>(aMod
.getSymbol(aSymbolName
));
1069 (*fpInit
)( pEnv
); // init of environment
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
);
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
);
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!");
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
);
1152 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
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()) );
1176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */