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 #ifdef DISABLE_DYNLOADING
21 #include <config_java.h>
24 #include <cppu/EnvDcp.hxx>
26 #include <sal/log.hxx>
27 #include <osl/diagnose.h>
28 #include <osl/interlck.h>
29 #include <osl/mutex.hxx>
30 #include <osl/module.hxx>
31 #include <osl/process.h>
32 #include <rtl/process.h>
33 #include <rtl/string.hxx>
34 #include <rtl/ustring.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <typelib/typedescription.h>
37 #include <uno/dispatcher.h>
38 #include <uno/environment.h>
39 #include <uno/lbnames.h>
41 #include "loadmodule.hxx"
43 #include <string_view>
44 #include <unordered_map>
54 bool td_equals( typelib_InterfaceTypeDescription
const * pTD1
,
55 typelib_InterfaceTypeDescription
const * pTD2
)
57 return (pTD1
== pTD2
||
58 (pTD1
->aBase
.pTypeName
->length
== pTD2
->aBase
.pTypeName
->length
&&
60 pTD1
->aBase
.pTypeName
->buffer
,
61 pTD2
->aBase
.pTypeName
->buffer
) == 0));
64 struct uno_DefaultEnvironment
;
71 uno_freeProxyFunc fpFreeProxy
;
72 typelib_InterfaceTypeDescription
* pTypeDescr
;
78 std::vector
< InterfaceEntry
> aInterfaces
;
82 explicit ObjectEntry( OUString aOId_
);
85 uno_DefaultEnvironment
* pEnv
,
86 void * pInterface
, typelib_InterfaceTypeDescription
* pTypeDescr
,
87 uno_freeProxyFunc fpFreeProxy
);
88 InterfaceEntry
* find(
89 typelib_InterfaceTypeDescription
* pTypeDescr
);
90 sal_Int32
find( void const * iface_ptr
, std::size_t pos
) const;
96 std::size_t operator () ( const void * pKey
) const
97 { return reinterpret_cast< std::size_t>( pKey
); }
101 // mapping from environment name to environment
102 typedef std::unordered_map
<
103 OUString
, uno_Environment
* > OUString2EnvironmentMap
;
105 // mapping from ptr to object entry
106 typedef std::unordered_map
<
107 void *, ObjectEntry
*, FctPtrHash
> Ptr2ObjectMap
;
108 // mapping from oid to object entry
109 typedef std::unordered_map
<
110 OUString
, ObjectEntry
* > OId2ObjectMap
;
112 struct EnvironmentsData
115 OUString2EnvironmentMap aName2EnvMap
;
117 EnvironmentsData() : isDisposing(false) {}
121 uno_Environment
** ppEnv
, std::u16string_view rEnvDcp
, void * pContext
);
122 void registerEnvironment( uno_Environment
** ppEnv
);
123 void getRegisteredEnvironments(
124 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
,
125 uno_memAlloc memAlloc
, std::u16string_view rEnvDcp
);
130 EnvironmentsData
& theEnvironmentsData()
132 static EnvironmentsData SINGLETON
;
136 struct uno_DefaultEnvironment
: public uno_ExtEnvironment
142 Ptr2ObjectMap aPtr2ObjectMap
;
143 OId2ObjectMap aOId2ObjectMap
;
145 uno_DefaultEnvironment(
146 const OUString
& rEnvDcp_
, void * pContext_
);
147 ~uno_DefaultEnvironment();
151 ObjectEntry::ObjectEntry( OUString aOId_
)
152 : oid(std::move( aOId_
)),
156 aInterfaces
.reserve( 2 );
160 void ObjectEntry::append(
161 uno_DefaultEnvironment
* pEnv
,
162 void * pInterface
, typelib_InterfaceTypeDescription
* pTypeDescr
,
163 uno_freeProxyFunc fpFreeProxy
)
165 InterfaceEntry aNewEntry
;
167 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
168 aNewEntry
.refCount
= 1;
169 aNewEntry
.pInterface
= pInterface
;
170 aNewEntry
.fpFreeProxy
= fpFreeProxy
;
171 typelib_typedescription_acquire( &pTypeDescr
->aBase
);
172 aNewEntry
.pTypeDescr
= pTypeDescr
;
174 std::pair
< Ptr2ObjectMap::iterator
, bool > i(
175 pEnv
->aPtr2ObjectMap
.emplace( pInterface
, this ) );
177 !i
.second
&& (find(pInterface
, 0) == -1 || i
.first
->second
!= this),
179 "map already contains " << i
.first
->second
<< " != " << this << " for "
181 aInterfaces
.push_back( aNewEntry
);
185 InterfaceEntry
* ObjectEntry::find(
186 typelib_InterfaceTypeDescription
* pTypeDescr_
)
188 OSL_ASSERT( ! aInterfaces
.empty() );
189 if (aInterfaces
.empty())
192 // shortcut common case:
193 OUString
const & type_name
=
194 OUString::unacquired( &pTypeDescr_
->aBase
.pTypeName
);
195 if ( type_name
== "com.sun.star.uno.XInterface" )
197 return aInterfaces
.data();
200 std::size_t nSize
= aInterfaces
.size();
201 for ( std::size_t nPos
= 0; nPos
< nSize
; ++nPos
)
203 typelib_InterfaceTypeDescription
* pITD
=
204 aInterfaces
[ nPos
].pTypeDescr
;
207 if (td_equals( pITD
, pTypeDescr_
))
208 return &aInterfaces
[ nPos
];
209 pITD
= pITD
->pBaseTypeDescription
;
216 sal_Int32
ObjectEntry::find(
217 void const * iface_ptr
, std::size_t pos
) const
219 std::size_t size
= aInterfaces
.size();
220 for ( ; pos
< size
; ++pos
)
222 if (aInterfaces
[ pos
].pInterface
== iface_ptr
)
232 static void defenv_registerInterface(
233 uno_ExtEnvironment
* pEnv
, void ** ppInterface
,
234 rtl_uString
* pOId
, typelib_InterfaceTypeDescription
* pTypeDescr
)
236 assert(pEnv
&& ppInterface
&& pOId
&& pTypeDescr
&& "### null ptr!");
237 OUString
const & rOId
= OUString::unacquired( &pOId
);
239 uno_DefaultEnvironment
* that
=
240 static_cast< uno_DefaultEnvironment
* >( pEnv
);
241 ::osl::ClearableMutexGuard
guard( that
->mutex
);
243 // try to insert dummy 0:
244 std::pair
<OId2ObjectMap::iterator
, bool> const insertion(
245 that
->aOId2ObjectMap
.emplace( rOId
, nullptr ) );
246 if (insertion
.second
)
248 ObjectEntry
* pOEntry
= new ObjectEntry( rOId
);
249 insertion
.first
->second
= pOEntry
;
250 ++pOEntry
->nRef
; // another register call on object
251 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, nullptr );
253 else // object entry exists
255 ObjectEntry
* pOEntry
= insertion
.first
->second
;
256 ++pOEntry
->nRef
; // another register call on object
257 InterfaceEntry
* pIEntry
= pOEntry
->find( pTypeDescr
);
259 if (pIEntry
) // type entry exists
262 if (pIEntry
->pInterface
!= *ppInterface
)
264 void * pInterface
= pIEntry
->pInterface
;
265 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
267 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
268 *ppInterface
= pInterface
;
273 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, nullptr );
278 static void defenv_registerProxyInterface(
279 uno_ExtEnvironment
* pEnv
, void ** ppInterface
, uno_freeProxyFunc freeProxy
,
280 rtl_uString
* pOId
, typelib_InterfaceTypeDescription
* pTypeDescr
)
282 assert(pEnv
&& ppInterface
&& pOId
&& pTypeDescr
&& freeProxy
&& "### null ptr!");
283 OUString
const & rOId
= OUString::unacquired( &pOId
);
285 uno_DefaultEnvironment
* that
=
286 static_cast< uno_DefaultEnvironment
* >( pEnv
);
287 ::osl::ClearableMutexGuard
guard( that
->mutex
);
289 // try to insert dummy 0:
290 std::pair
<OId2ObjectMap::iterator
, bool> const insertion(
291 that
->aOId2ObjectMap
.emplace( rOId
, nullptr ) );
292 if (insertion
.second
)
294 ObjectEntry
* pOEntry
= new ObjectEntry( rOId
);
295 insertion
.first
->second
= pOEntry
;
296 ++pOEntry
->nRef
; // another register call on object
297 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, freeProxy
);
299 else // object entry exists
301 ObjectEntry
* pOEntry
= insertion
.first
->second
;
303 // first registration was an original, then registerProxyInterface():
304 pOEntry
->mixedObject
|=
305 (!pOEntry
->aInterfaces
.empty() &&
306 pOEntry
->aInterfaces
[ 0 ].fpFreeProxy
== nullptr);
308 ++pOEntry
->nRef
; // another register call on object
309 InterfaceEntry
* pIEntry
= pOEntry
->find( pTypeDescr
);
311 if (pIEntry
) // type entry exists
313 if (pIEntry
->pInterface
== *ppInterface
)
319 void * pInterface
= pIEntry
->pInterface
;
320 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
321 --pOEntry
->nRef
; // manual revoke of proxy to be freed
323 (*freeProxy
)( pEnv
, *ppInterface
);
324 *ppInterface
= pInterface
;
329 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, freeProxy
);
334 static void s_stub_defenv_revokeInterface(va_list * pParam
)
336 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
337 void * pInterface
= va_arg(*pParam
, void *);
339 assert(pEnv
&& pInterface
&& "### null ptr!");
340 uno_DefaultEnvironment
* that
=
341 static_cast< uno_DefaultEnvironment
* >( pEnv
);
342 ::osl::ClearableMutexGuard
guard( that
->mutex
);
344 Ptr2ObjectMap::const_iterator
const iFind(
345 that
->aPtr2ObjectMap
.find( pInterface
) );
346 assert(iFind
!= that
->aPtr2ObjectMap
.end());
347 ObjectEntry
* pOEntry
= iFind
->second
;
348 if (! --pOEntry
->nRef
)
351 that
->aOId2ObjectMap
.erase( pOEntry
->oid
);
353 for ( nPos
= pOEntry
->aInterfaces
.size(); nPos
--; )
355 that
->aPtr2ObjectMap
.erase( pOEntry
->aInterfaces
[nPos
].pInterface
);
358 // the last proxy interface of the environment might kill this
359 // environment, because of releasing its language binding!!!
362 // release interfaces
363 for ( nPos
= pOEntry
->aInterfaces
.size(); nPos
--; )
365 InterfaceEntry
const & rEntry
= pOEntry
->aInterfaces
[nPos
];
366 typelib_typedescription_release( &rEntry
.pTypeDescr
->aBase
);
367 if (rEntry
.fpFreeProxy
) // is proxy or used interface?
369 (*rEntry
.fpFreeProxy
)( pEnv
, rEntry
.pInterface
);
373 (*pEnv
->releaseInterface
)( pEnv
, rEntry
.pInterface
);
379 else if (pOEntry
->mixedObject
)
381 OSL_ASSERT( !pOEntry
->aInterfaces
.empty() &&
382 pOEntry
->aInterfaces
[ 0 ].fpFreeProxy
== nullptr );
384 sal_Int32 index
= pOEntry
->find( pInterface
, 1 );
385 OSL_ASSERT( index
> 0 );
388 InterfaceEntry
& entry
= pOEntry
->aInterfaces
[ index
];
389 OSL_ASSERT( entry
.pInterface
== pInterface
);
390 if (entry
.fpFreeProxy
!= nullptr)
393 if (entry
.refCount
== 0)
395 uno_freeProxyFunc fpFreeProxy
= entry
.fpFreeProxy
;
396 typelib_TypeDescription
* pTypeDescr
=
397 reinterpret_cast< typelib_TypeDescription
* >(
400 pOEntry
->aInterfaces
.erase(
401 pOEntry
->aInterfaces
.begin() + index
);
402 if (pOEntry
->find( pInterface
, index
) < 0)
404 // proxy ptr not registered for another interface:
405 // remove from ptr map
407 that
->aPtr2ObjectMap
.erase( pInterface
);
408 OSL_ASSERT( erased
== 1 );
413 typelib_typedescription_release( pTypeDescr
);
414 (*fpFreeProxy
)( pEnv
, pInterface
);
421 static void defenv_revokeInterface(uno_ExtEnvironment
* pEnv
, void * pInterface
)
423 uno_Environment_invoke(&pEnv
->aBase
, s_stub_defenv_revokeInterface
, pEnv
, pInterface
);
427 static void defenv_getObjectIdentifier(
428 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
430 assert(pEnv
&& ppOId
&& pInterface
&& "### null ptr!");
433 ::rtl_uString_release( *ppOId
);
437 uno_DefaultEnvironment
* that
=
438 static_cast< uno_DefaultEnvironment
* >( pEnv
);
439 ::osl::ClearableMutexGuard
guard( that
->mutex
);
441 Ptr2ObjectMap::const_iterator
const iFind(
442 that
->aPtr2ObjectMap
.find( pInterface
) );
443 if (iFind
== that
->aPtr2ObjectMap
.end())
446 (*pEnv
->computeObjectIdentifier
)( pEnv
, ppOId
, pInterface
);
450 rtl_uString
* hstr
= iFind
->second
->oid
.pData
;
451 rtl_uString_acquire( hstr
);
456 static void defenv_getRegisteredInterface(
457 uno_ExtEnvironment
* pEnv
, void ** ppInterface
,
458 rtl_uString
* pOId
, typelib_InterfaceTypeDescription
* pTypeDescr
)
460 assert(pEnv
&& ppInterface
&& pOId
&& pTypeDescr
&& "### null ptr!");
463 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
464 *ppInterface
= nullptr;
467 OUString
const & rOId
= OUString::unacquired( &pOId
);
468 uno_DefaultEnvironment
* that
=
469 static_cast< uno_DefaultEnvironment
* >( pEnv
);
470 ::osl::MutexGuard
guard( that
->mutex
);
472 OId2ObjectMap::const_iterator
const iFind
473 ( that
->aOId2ObjectMap
.find( rOId
) );
474 if (iFind
!= that
->aOId2ObjectMap
.end())
476 InterfaceEntry
const * pIEntry
= iFind
->second
->find( pTypeDescr
);
479 (*pEnv
->acquireInterface
)( pEnv
, pIEntry
->pInterface
);
480 *ppInterface
= pIEntry
->pInterface
;
485 static void defenv_getRegisteredInterfaces(
486 uno_ExtEnvironment
* pEnv
, void *** pppInterfaces
, sal_Int32
* pnLen
,
487 uno_memAlloc memAlloc
)
489 assert(pEnv
&& pppInterfaces
&& pnLen
&& memAlloc
&& "### null ptr!");
490 uno_DefaultEnvironment
* that
=
491 static_cast< uno_DefaultEnvironment
* >( pEnv
);
492 ::osl::MutexGuard
guard( that
->mutex
);
494 sal_Int32 nLen
= that
->aPtr2ObjectMap
.size();
496 void ** ppInterfaces
= static_cast<void **>((*memAlloc
)( nLen
* sizeof (void *) ));
498 for (const auto& rEntry
: that
->aPtr2ObjectMap
)
500 ppInterfaces
[nPos
] = rEntry
.first
;
501 (*pEnv
->acquireInterface
)( pEnv
, ppInterfaces
[nPos
] );
505 *pppInterfaces
= ppInterfaces
;
510 static void defenv_acquire( uno_Environment
* pEnv
)
512 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
513 osl_atomic_increment( &that
->nWeakRef
);
514 osl_atomic_increment( &that
->nRef
);
518 static void defenv_release( uno_Environment
* pEnv
)
520 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
521 if (! osl_atomic_decrement( &that
->nRef
))
523 // invoke dispose callback
524 if (pEnv
->environmentDisposing
)
526 (*pEnv
->environmentDisposing
)( pEnv
);
529 OSL_ENSURE( that
->aOId2ObjectMap
.empty(), "### object entries left!" );
531 // free memory if no weak refs left
532 if (! osl_atomic_decrement( &that
->nWeakRef
))
539 static void defenv_acquireWeak( uno_Environment
* pEnv
)
541 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
542 osl_atomic_increment( &that
->nWeakRef
);
546 static void defenv_releaseWeak( uno_Environment
* pEnv
)
548 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
549 if (! osl_atomic_decrement( &that
->nWeakRef
))
556 static void defenv_harden(
557 uno_Environment
** ppHardEnv
, uno_Environment
* pEnv
)
561 (*(*ppHardEnv
)->release
)( *ppHardEnv
);
562 *ppHardEnv
= nullptr;
565 EnvironmentsData
& rData
= theEnvironmentsData();
567 if (rData
.isDisposing
)
570 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
572 ::osl::MutexGuard
guard( rData
.mutex
);
573 if (1 == osl_atomic_increment( &that
->nRef
)) // is dead
579 osl_atomic_increment( &that
->nWeakRef
);
584 static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment
* )
590 uno_DefaultEnvironment::uno_DefaultEnvironment(
591 const OUString
& rEnvDcp_
, void * pContext_
)
595 uno_Environment
* that
= reinterpret_cast< uno_Environment
* >(this);
596 that
->pReserved
= nullptr;
598 that
->acquire
= defenv_acquire
;
599 that
->release
= defenv_release
;
600 that
->acquireWeak
= defenv_acquireWeak
;
601 that
->releaseWeak
= defenv_releaseWeak
;
602 that
->harden
= defenv_harden
;
603 that
->dispose
= defenv_dispose
;
604 that
->pExtEnv
= this;
606 ::rtl_uString_acquire( rEnvDcp_
.pData
);
607 that
->pTypeName
= rEnvDcp_
.pData
;
608 that
->pContext
= pContext_
;
610 // will be late initialized
611 that
->environmentDisposing
= nullptr;
613 uno_ExtEnvironment::registerInterface
= defenv_registerInterface
;
614 uno_ExtEnvironment::registerProxyInterface
= defenv_registerProxyInterface
;
615 uno_ExtEnvironment::revokeInterface
= defenv_revokeInterface
;
616 uno_ExtEnvironment::getObjectIdentifier
= defenv_getObjectIdentifier
;
617 uno_ExtEnvironment::getRegisteredInterface
= defenv_getRegisteredInterface
;
618 uno_ExtEnvironment::getRegisteredInterfaces
=
619 defenv_getRegisteredInterfaces
;
624 uno_DefaultEnvironment::~uno_DefaultEnvironment()
626 ::rtl_uString_release( aBase
.pTypeName
);
631 void * stream
, const char * pLine
, const char * pFilter
)
633 if (pFilter
&& *pFilter
)
635 // lookup pFilter in pLine
638 if (*pLine
== *pFilter
)
641 while (pLine
[nPos
] && pFilter
[nPos
] == pLine
[nPos
])
649 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
653 SAL_WARN("cppu", pLine
);
664 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
668 fprintf( stderr
, "%s\n", pLine
);
675 void * stream
, std::u16string_view rLine
, const char * pFilter
)
677 OString
aLine( OUStringToOString(
678 rLine
, RTL_TEXTENCODING_ASCII_US
) );
679 writeLine( stream
, aLine
.getStr(), pFilter
);
684 extern "C" void SAL_CALL
uno_dumpEnvironment(
685 void * stream
, uno_Environment
* pEnv
, const char * pFilter
) noexcept
687 assert(pEnv
&& "### null ptr!");
692 writeLine( stream
, "###################################"
693 "###########################################", pFilter
);
694 buf
.append( OUString::Concat("environment: ") + OUString::unacquired(&pEnv
->pTypeName
) );
695 writeLine( stream
, buf
, pFilter
);
697 writeLine( stream
, "NO INTERFACE INFORMATION AVAILABLE!", pFilter
);
701 writeLine( stream
, "########################################"
702 "######################################", pFilter
);
703 buf
.append( OUString::Concat("environment dump: ") + OUString::unacquired(&pEnv
->pTypeName
) );
704 writeLine( stream
, buf
, pFilter
);
707 uno_DefaultEnvironment
* that
=
708 reinterpret_cast< uno_DefaultEnvironment
* >(pEnv
);
709 ::osl::MutexGuard
guard( that
->mutex
);
711 Ptr2ObjectMap
ptr2obj( that
->aPtr2ObjectMap
);
712 for (const auto& rEntry
: that
->aOId2ObjectMap
)
714 ObjectEntry
* pOEntry
= rEntry
.second
;
717 if (pOEntry
->mixedObject
)
718 buf
.append( "mixed " );
719 buf
.append( "object entry: nRef="
720 + OUString::number(pOEntry
->nRef
)
724 writeLine( stream
, buf
, pFilter
);
727 for ( std::size_t nPos
= 0;
728 nPos
< pOEntry
->aInterfaces
.size(); ++nPos
)
730 const InterfaceEntry
& rIEntry
= pOEntry
->aInterfaces
[nPos
];
732 buf
.append( OUString::Concat(" - ")
733 + OUString::unacquired(&rIEntry
.pTypeDescr
->aBase
.pTypeName
) );
734 if (rIEntry
.fpFreeProxy
)
736 buf
.append( "; proxy free=0x"
737 + OUString::number( reinterpret_cast< sal_IntPtr
>(rIEntry
.fpFreeProxy
), 16 ) );
741 buf
.append( "; original" );
743 buf
.append( "; ptr=0x"
744 + OUString::number(reinterpret_cast< sal_IntPtr
>(rIEntry
.pInterface
), 16 ) );
746 if (pOEntry
->find( rIEntry
.pInterface
, nPos
+ 1 ) < 0)
748 std::size_t erased
= ptr2obj
.erase( rIEntry
.pInterface
);
751 buf
.append( " (ptr not found in map!)" );
754 writeLine( stream
, buf
, pFilter
);
758 if (! ptr2obj
.empty())
759 writeLine( stream
, "ptr map inconsistency!!!", pFilter
);
760 writeLine( stream
, "#####################################"
761 "#########################################", pFilter
);
765 extern "C" void SAL_CALL
uno_dumpEnvironmentByName(
766 void * stream
, rtl_uString
* pEnvDcp
, const char * pFilter
) noexcept
768 uno_Environment
* pEnv
= nullptr;
769 uno_getEnvironment( &pEnv
, pEnvDcp
, nullptr );
772 ::uno_dumpEnvironment( stream
, pEnv
, pFilter
);
773 (*pEnv
->release
)( pEnv
);
779 Concat2View("environment \"" + OUString::unacquired(&pEnvDcp
) + "\" does not exist!"),
787 const OUString
& unoenv_getStaticOIdPart()
789 static auto const theStaticOIdPart
= [] {
790 OUStringBuffer
aRet( 64 );
794 info
.Size
= sizeof(oslProcessInfo
);
795 if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER
, &info
) ==
798 aRet
.append( static_cast<sal_Int64
>(info
.Ident
), 16 );
802 aRet
.append( "unknown process id" );
806 ::rtl_getGlobalProcessId( ar
);
808 for (unsigned char i
: ar
)
809 aRet
.append( static_cast<sal_Int32
>(i
), 16 );
811 return aRet
.makeStringAndClear();
813 return theStaticOIdPart
;
822 static void unoenv_computeObjectIdentifier(
823 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
825 assert(pEnv
&& ppOId
&& pInterface
&& "### null ptr!");
828 ::rtl_uString_release( *ppOId
);
832 uno_Interface
* pUnoI
= static_cast<uno_Interface
*>(
833 ::cppu::binuno_queryInterface(
834 pInterface
, *typelib_static_type_getByTypeClass(
835 typelib_TypeClass_INTERFACE
) ));
836 if (nullptr == pUnoI
)
839 (*pUnoI
->release
)( pUnoI
);
842 OUString::number( reinterpret_cast< sal_IntPtr
>(pUnoI
), 16 ) + ";"
843 // environment[context]
844 + OUString::unacquired(&pEnv
->aBase
.pTypeName
) + "["
845 + OUString::number( reinterpret_cast< sal_IntPtr
>(
847 uno_Environment
* >(pEnv
)->pContext
), 16 )
849 + unoenv_getStaticOIdPart() );
851 ::rtl_uString_acquire( *ppOId
);
855 static void unoenv_acquireInterface(
856 SAL_UNUSED_PARAMETER uno_ExtEnvironment
*, void * pUnoI_
)
858 uno_Interface
* pUnoI
= static_cast< uno_Interface
* >(pUnoI_
);
859 (*pUnoI
->acquire
)( pUnoI
);
863 static void unoenv_releaseInterface(
864 SAL_UNUSED_PARAMETER uno_ExtEnvironment
*, void * pUnoI_
)
866 uno_Interface
* pUnoI
= static_cast< uno_Interface
* >(pUnoI_
);
867 (*pUnoI
->release
)( pUnoI
);
873 EnvironmentsData::~EnvironmentsData()
875 ::osl::MutexGuard
guard( mutex
);
878 for ( const auto& rEntry
: aName2EnvMap
)
880 uno_Environment
* pWeak
= rEntry
.second
;
881 uno_Environment
* pHard
= nullptr;
882 (*pWeak
->harden
)( &pHard
, pWeak
);
883 (*pWeak
->releaseWeak
)( pWeak
);
887 (*pHard
->dispose
)( pHard
); // send explicit dispose
888 (*pHard
->release
)( pHard
);
894 void EnvironmentsData::getEnvironment(
895 uno_Environment
** ppEnv
, std::u16string_view rEnvDcp
, void * pContext
)
899 (*(*ppEnv
)->release
)( *ppEnv
);
903 OUString aKey
= OUString::number( reinterpret_cast< sal_IntPtr
>(pContext
) ) + rEnvDcp
;
905 // try to find registered mapping
906 OUString2EnvironmentMap::const_iterator
const iFind(
907 aName2EnvMap
.find( aKey
) );
908 if (iFind
!= aName2EnvMap
.end())
910 uno_Environment
* pWeak
= iFind
->second
;
911 (*pWeak
->harden
)( ppEnv
, pWeak
);
915 void EnvironmentsData::registerEnvironment( uno_Environment
** ppEnv
)
917 assert(ppEnv
&& "### null ptr!");
918 uno_Environment
* pEnv
= *ppEnv
;
921 OUString::number( reinterpret_cast< sal_IntPtr
>(pEnv
->pContext
) ) +
922 OUString::unacquired(&pEnv
->pTypeName
);
924 // try to find registered environment
925 OUString2EnvironmentMap::const_iterator
const iFind(
926 aName2EnvMap
.find( aKey
) );
927 if (iFind
== aName2EnvMap
.end())
929 (*pEnv
->acquireWeak
)( pEnv
);
930 std::pair
< OUString2EnvironmentMap::iterator
, bool > insertion (
931 aName2EnvMap
.emplace( aKey
, pEnv
) );
932 SAL_WARN_IF( !insertion
.second
, "cppu", "key " << aKey
<< " already in env map" );
936 uno_Environment
* pHard
= nullptr;
937 uno_Environment
* pWeak
= iFind
->second
;
938 (*pWeak
->harden
)( &pHard
, pWeak
);
941 (*pEnv
->release
)( pEnv
);
944 else // registered one is dead
946 (*pWeak
->releaseWeak
)( pWeak
);
947 (*pEnv
->acquireWeak
)( pEnv
);
948 aName2EnvMap
[ aKey
] = pEnv
;
953 void EnvironmentsData::getRegisteredEnvironments(
954 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
, uno_memAlloc memAlloc
,
955 std::u16string_view rEnvDcp
)
957 assert(pppEnvs
&& pnLen
&& memAlloc
&& "### null ptr!");
960 std::vector
<uno_Environment
*> aFounds(aName2EnvMap
.size());
963 // find matching environment
964 for ( const auto& rEntry
: aName2EnvMap
)
966 uno_Environment
* pWeak
= rEntry
.second
;
967 if (rEnvDcp
.empty() ||
968 rEnvDcp
== OUString::unacquired(&pWeak
->pTypeName
) )
970 aFounds
[nSize
] = nullptr;
971 (*pWeak
->harden
)( &aFounds
[nSize
], pWeak
);
980 *pppEnvs
= static_cast<uno_Environment
**>((*memAlloc
)(
981 sizeof (uno_Environment
*) * nSize
));
982 OSL_ASSERT( *pppEnvs
);
985 (*pppEnvs
)[nSize
] = aFounds
[nSize
];
994 bool loadEnv(OUString
const & cLibStem
,
995 uno_Environment
* pEnv
)
997 #ifdef DISABLE_DYNLOADING
998 uno_initEnvironmentFunc fpInit
;
1000 if ( cLibStem
== CPPU_CURRENT_LANGUAGE_BINDING_NAME
"_uno" )
1001 fpInit
= CPPU_ENV_uno_initEnvironment
;
1002 #if HAVE_FEATURE_JAVA
1003 else if ( cLibStem
== "java_uno" )
1004 fpInit
= java_uno_initEnvironment
;
1008 SAL_INFO("cppu", ": Unhandled env: " << cLibStem
);
1012 // late init with some code from matching uno language binding
1013 // will be unloaded by environment
1016 bool bMod
= cppu::detail::loadModule(aMod
, cLibStem
);
1021 // Catch everything and convert to return false
1026 uno_initEnvironmentFunc fpInit
= reinterpret_cast<uno_initEnvironmentFunc
>(aMod
.getSymbol(u
"" UNO_INIT_ENVIRONMENT
""_ustr
));
1034 (*fpInit
)( pEnv
); // init of environment
1044 static uno_Environment
* initDefaultEnvironment(
1045 const OUString
& rEnvDcp
, void * pContext
)
1047 // coverity[leaked_storage : FALSE] - lifetime is controlled by acquire()/release() calls
1048 uno_Environment
* pEnv
= &(new uno_DefaultEnvironment( rEnvDcp
, pContext
))->aBase
;
1049 (*pEnv
->acquire
)( pEnv
);
1051 OUString envTypeName
= cppu::EnvDcp::getTypeName(rEnvDcp
);
1053 // create default environment
1054 if ( envTypeName
== UNO_LB_UNO
)
1056 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
1057 that
->computeObjectIdentifier
= unoenv_computeObjectIdentifier
;
1058 that
->acquireInterface
= unoenv_acquireInterface
;
1059 that
->releaseInterface
= unoenv_releaseInterface
;
1061 OUString envPurpose
= cppu::EnvDcp::getPurpose(rEnvDcp
);
1062 if (!envPurpose
.isEmpty())
1065 OUString::Concat(envPurpose
.subView(envPurpose
.lastIndexOf(':') + 1)) + "_uno_uno");
1066 if(!loadEnv(libStem
, pEnv
))
1068 pEnv
->release(pEnv
);
1075 // late init with some code from matching uno language binding
1076 OUString
aStr( envTypeName
+ "_uno" );
1078 if (!loadEnv(aStr
, pEnv
))
1080 pEnv
->release(pEnv
);
1089 void SAL_CALL
uno_createEnvironment(
1090 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
) noexcept
1092 assert(ppEnv
&& "### null ptr!");
1094 (*(*ppEnv
)->release
)( *ppEnv
);
1096 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1097 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1100 void SAL_CALL
uno_getEnvironment(
1101 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
) noexcept
1103 assert(ppEnv
&& "### null ptr!");
1104 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1106 EnvironmentsData
& rData
= theEnvironmentsData();
1108 ::osl::MutexGuard
guard( rData
.mutex
);
1109 rData
.getEnvironment( ppEnv
, rEnvDcp
, pContext
);
1112 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1115 // register new environment:
1116 rData
.registerEnvironment( ppEnv
);
1121 void SAL_CALL
uno_getRegisteredEnvironments(
1122 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
, uno_memAlloc memAlloc
,
1123 rtl_uString
* pEnvDcp
) noexcept
1125 EnvironmentsData
& rData
= theEnvironmentsData();
1127 ::osl::MutexGuard
guard( rData
.mutex
);
1128 rData
.getRegisteredEnvironments(
1129 pppEnvs
, pnLen
, memAlloc
,
1130 (pEnvDcp
? OUString(pEnvDcp
) : OUString()) );
1135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */