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 OSL_ENSURE( 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 );
279 static void defenv_registerProxyInterface(
280 uno_ExtEnvironment
* pEnv
, void ** ppInterface
, uno_freeProxyFunc freeProxy
,
281 rtl_uString
* pOId
, typelib_InterfaceTypeDescription
* pTypeDescr
)
283 OSL_ENSURE( pEnv
&& ppInterface
&& pOId
&& pTypeDescr
&& freeProxy
,
285 OUString
const & rOId
= OUString::unacquired( &pOId
);
287 uno_DefaultEnvironment
* that
=
288 static_cast< uno_DefaultEnvironment
* >( pEnv
);
289 ::osl::ClearableMutexGuard
guard( that
->mutex
);
291 // try to insert dummy 0:
292 std::pair
<OId2ObjectMap::iterator
, bool> const insertion(
293 that
->aOId2ObjectMap
.emplace( rOId
, nullptr ) );
294 if (insertion
.second
)
296 ObjectEntry
* pOEntry
= new ObjectEntry( rOId
);
297 insertion
.first
->second
= pOEntry
;
298 ++pOEntry
->nRef
; // another register call on object
299 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, freeProxy
);
301 else // object entry exists
303 ObjectEntry
* pOEntry
= insertion
.first
->second
;
305 // first registration was an original, then registerProxyInterface():
306 pOEntry
->mixedObject
|=
307 (!pOEntry
->aInterfaces
.empty() &&
308 pOEntry
->aInterfaces
[ 0 ].fpFreeProxy
== nullptr);
310 ++pOEntry
->nRef
; // another register call on object
311 InterfaceEntry
* pIEntry
= pOEntry
->find( pTypeDescr
);
313 if (pIEntry
) // type entry exists
315 if (pIEntry
->pInterface
== *ppInterface
)
321 void * pInterface
= pIEntry
->pInterface
;
322 (*pEnv
->acquireInterface
)( pEnv
, pInterface
);
323 --pOEntry
->nRef
; // manual revoke of proxy to be freed
325 (*freeProxy
)( pEnv
, *ppInterface
);
326 *ppInterface
= pInterface
;
331 pOEntry
->append( that
, *ppInterface
, pTypeDescr
, freeProxy
);
337 static void s_stub_defenv_revokeInterface(va_list * pParam
)
339 uno_ExtEnvironment
* pEnv
= va_arg(*pParam
, uno_ExtEnvironment
*);
340 void * pInterface
= va_arg(*pParam
, void *);
342 OSL_ENSURE( pEnv
&& pInterface
, "### null ptr!" );
343 uno_DefaultEnvironment
* that
=
344 static_cast< uno_DefaultEnvironment
* >( pEnv
);
345 ::osl::ClearableMutexGuard
guard( that
->mutex
);
347 Ptr2ObjectMap::const_iterator
const iFind(
348 that
->aPtr2ObjectMap
.find( pInterface
) );
349 OSL_ASSERT( iFind
!= that
->aPtr2ObjectMap
.end() );
350 ObjectEntry
* pOEntry
= iFind
->second
;
351 if (! --pOEntry
->nRef
)
354 that
->aOId2ObjectMap
.erase( pOEntry
->oid
);
356 for ( nPos
= pOEntry
->aInterfaces
.size(); nPos
--; )
358 that
->aPtr2ObjectMap
.erase( pOEntry
->aInterfaces
[nPos
].pInterface
);
361 // the last proxy interface of the environment might kill this
362 // environment, because of releasing its language binding!!!
365 // release interfaces
366 for ( nPos
= pOEntry
->aInterfaces
.size(); nPos
--; )
368 InterfaceEntry
const & rEntry
= pOEntry
->aInterfaces
[nPos
];
369 typelib_typedescription_release( &rEntry
.pTypeDescr
->aBase
);
370 if (rEntry
.fpFreeProxy
) // is proxy or used interface?
372 (*rEntry
.fpFreeProxy
)( pEnv
, rEntry
.pInterface
);
376 (*pEnv
->releaseInterface
)( pEnv
, rEntry
.pInterface
);
382 else if (pOEntry
->mixedObject
)
384 OSL_ASSERT( !pOEntry
->aInterfaces
.empty() &&
385 pOEntry
->aInterfaces
[ 0 ].fpFreeProxy
== nullptr );
387 sal_Int32 index
= pOEntry
->find( pInterface
, 1 );
388 OSL_ASSERT( index
> 0 );
391 InterfaceEntry
& entry
= pOEntry
->aInterfaces
[ index
];
392 OSL_ASSERT( entry
.pInterface
== pInterface
);
393 if (entry
.fpFreeProxy
!= nullptr)
396 if (entry
.refCount
== 0)
398 uno_freeProxyFunc fpFreeProxy
= entry
.fpFreeProxy
;
399 typelib_TypeDescription
* pTypeDescr
=
400 reinterpret_cast< typelib_TypeDescription
* >(
403 pOEntry
->aInterfaces
.erase(
404 pOEntry
->aInterfaces
.begin() + index
);
405 if (pOEntry
->find( pInterface
, index
) < 0)
407 // proxy ptr not registered for another interface:
408 // remove from ptr map
410 that
->aPtr2ObjectMap
.erase( pInterface
);
411 OSL_ASSERT( erased
== 1 );
416 typelib_typedescription_release( pTypeDescr
);
417 (*fpFreeProxy
)( pEnv
, pInterface
);
424 static void defenv_revokeInterface(uno_ExtEnvironment
* pEnv
, void * pInterface
)
426 uno_Environment_invoke(&pEnv
->aBase
, s_stub_defenv_revokeInterface
, pEnv
, pInterface
);
430 static void defenv_getObjectIdentifier(
431 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
433 OSL_ENSURE( pEnv
&& ppOId
&& pInterface
, "### null ptr!" );
436 ::rtl_uString_release( *ppOId
);
440 uno_DefaultEnvironment
* that
=
441 static_cast< uno_DefaultEnvironment
* >( pEnv
);
442 ::osl::ClearableMutexGuard
guard( that
->mutex
);
444 Ptr2ObjectMap::const_iterator
const iFind(
445 that
->aPtr2ObjectMap
.find( pInterface
) );
446 if (iFind
== that
->aPtr2ObjectMap
.end())
449 (*pEnv
->computeObjectIdentifier
)( pEnv
, ppOId
, pInterface
);
453 rtl_uString
* hstr
= iFind
->second
->oid
.pData
;
454 rtl_uString_acquire( hstr
);
460 static void defenv_getRegisteredInterface(
461 uno_ExtEnvironment
* pEnv
, void ** ppInterface
,
462 rtl_uString
* pOId
, typelib_InterfaceTypeDescription
* pTypeDescr
)
464 OSL_ENSURE( pEnv
&& ppInterface
&& pOId
&& pTypeDescr
, "### null ptr!" );
467 (*pEnv
->releaseInterface
)( pEnv
, *ppInterface
);
468 *ppInterface
= nullptr;
471 OUString
const & rOId
= OUString::unacquired( &pOId
);
472 uno_DefaultEnvironment
* that
=
473 static_cast< uno_DefaultEnvironment
* >( pEnv
);
474 ::osl::MutexGuard
guard( that
->mutex
);
476 OId2ObjectMap::const_iterator
const iFind
477 ( that
->aOId2ObjectMap
.find( rOId
) );
478 if (iFind
!= that
->aOId2ObjectMap
.end())
480 InterfaceEntry
const * pIEntry
= iFind
->second
->find( pTypeDescr
);
483 (*pEnv
->acquireInterface
)( pEnv
, pIEntry
->pInterface
);
484 *ppInterface
= pIEntry
->pInterface
;
490 static void defenv_getRegisteredInterfaces(
491 uno_ExtEnvironment
* pEnv
, void *** pppInterfaces
, sal_Int32
* pnLen
,
492 uno_memAlloc memAlloc
)
494 assert(pEnv
&& pppInterfaces
&& pnLen
&& memAlloc
&& "### null ptr!");
495 uno_DefaultEnvironment
* that
=
496 static_cast< uno_DefaultEnvironment
* >( pEnv
);
497 ::osl::MutexGuard
guard( that
->mutex
);
499 sal_Int32 nLen
= that
->aPtr2ObjectMap
.size();
501 void ** ppInterfaces
= static_cast<void **>((*memAlloc
)( nLen
* sizeof (void *) ));
503 for (const auto& rEntry
: that
->aPtr2ObjectMap
)
505 ppInterfaces
[nPos
] = rEntry
.first
;
506 (*pEnv
->acquireInterface
)( pEnv
, ppInterfaces
[nPos
] );
510 *pppInterfaces
= ppInterfaces
;
515 static void defenv_acquire( uno_Environment
* pEnv
)
517 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
518 osl_atomic_increment( &that
->nWeakRef
);
519 osl_atomic_increment( &that
->nRef
);
523 static void defenv_release( uno_Environment
* pEnv
)
525 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
526 if (! osl_atomic_decrement( &that
->nRef
))
528 // invoke dispose callback
529 if (pEnv
->environmentDisposing
)
531 (*pEnv
->environmentDisposing
)( pEnv
);
534 OSL_ENSURE( that
->aOId2ObjectMap
.empty(), "### object entries left!" );
536 // free memory if no weak refs left
537 if (! osl_atomic_decrement( &that
->nWeakRef
))
544 static void defenv_acquireWeak( uno_Environment
* pEnv
)
546 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
547 osl_atomic_increment( &that
->nWeakRef
);
551 static void defenv_releaseWeak( uno_Environment
* pEnv
)
553 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
554 if (! osl_atomic_decrement( &that
->nWeakRef
))
561 static void defenv_harden(
562 uno_Environment
** ppHardEnv
, uno_Environment
* pEnv
)
566 (*(*ppHardEnv
)->release
)( *ppHardEnv
);
567 *ppHardEnv
= nullptr;
570 EnvironmentsData
& rData
= theEnvironmentsData();
572 if (rData
.isDisposing
)
575 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
577 ::osl::MutexGuard
guard( rData
.mutex
);
578 if (1 == osl_atomic_increment( &that
->nRef
)) // is dead
584 osl_atomic_increment( &that
->nWeakRef
);
589 static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment
* )
595 uno_DefaultEnvironment::uno_DefaultEnvironment(
596 const OUString
& rEnvDcp_
, void * pContext_
)
600 uno_Environment
* that
= reinterpret_cast< uno_Environment
* >(this);
601 that
->pReserved
= nullptr;
603 that
->acquire
= defenv_acquire
;
604 that
->release
= defenv_release
;
605 that
->acquireWeak
= defenv_acquireWeak
;
606 that
->releaseWeak
= defenv_releaseWeak
;
607 that
->harden
= defenv_harden
;
608 that
->dispose
= defenv_dispose
;
609 that
->pExtEnv
= this;
611 ::rtl_uString_acquire( rEnvDcp_
.pData
);
612 that
->pTypeName
= rEnvDcp_
.pData
;
613 that
->pContext
= pContext_
;
615 // will be late initialized
616 that
->environmentDisposing
= nullptr;
618 uno_ExtEnvironment::registerInterface
= defenv_registerInterface
;
619 uno_ExtEnvironment::registerProxyInterface
= defenv_registerProxyInterface
;
620 uno_ExtEnvironment::revokeInterface
= defenv_revokeInterface
;
621 uno_ExtEnvironment::getObjectIdentifier
= defenv_getObjectIdentifier
;
622 uno_ExtEnvironment::getRegisteredInterface
= defenv_getRegisteredInterface
;
623 uno_ExtEnvironment::getRegisteredInterfaces
=
624 defenv_getRegisteredInterfaces
;
629 uno_DefaultEnvironment::~uno_DefaultEnvironment()
631 ::rtl_uString_release( aBase
.pTypeName
);
636 void * stream
, const char * pLine
, const char * pFilter
)
638 if (pFilter
&& *pFilter
)
640 // lookup pFilter in pLine
643 if (*pLine
== *pFilter
)
646 while (pLine
[nPos
] && pFilter
[nPos
] == pLine
[nPos
])
654 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
658 SAL_WARN("cppu", pLine
);
669 fprintf( static_cast<FILE *>(stream
), "%s\n", pLine
);
673 fprintf( stderr
, "%s\n", pLine
);
680 void * stream
, std::u16string_view rLine
, const char * pFilter
)
682 OString
aLine( OUStringToOString(
683 rLine
, RTL_TEXTENCODING_ASCII_US
) );
684 writeLine( stream
, aLine
.getStr(), pFilter
);
689 extern "C" void SAL_CALL
uno_dumpEnvironment(
690 void * stream
, uno_Environment
* pEnv
, const char * pFilter
)
693 OSL_ENSURE( pEnv
, "### null ptr!" );
698 writeLine( stream
, "###################################"
699 "###########################################", pFilter
);
700 buf
.append( OUString::Concat("environment: ") + OUString::unacquired(&pEnv
->pTypeName
) );
701 writeLine( stream
, buf
, pFilter
);
703 writeLine( stream
, "NO INTERFACE INFORMATION AVAILABLE!", pFilter
);
707 writeLine( stream
, "########################################"
708 "######################################", pFilter
);
709 buf
.append( OUString::Concat("environment dump: ") + OUString::unacquired(&pEnv
->pTypeName
) );
710 writeLine( stream
, buf
, pFilter
);
713 uno_DefaultEnvironment
* that
=
714 reinterpret_cast< uno_DefaultEnvironment
* >(pEnv
);
715 ::osl::MutexGuard
guard( that
->mutex
);
717 Ptr2ObjectMap
ptr2obj( that
->aPtr2ObjectMap
);
718 for (const auto& rEntry
: that
->aOId2ObjectMap
)
720 ObjectEntry
* pOEntry
= rEntry
.second
;
723 if (pOEntry
->mixedObject
)
724 buf
.append( "mixed " );
725 buf
.append( "object entry: nRef="
726 + OUString::number(pOEntry
->nRef
)
730 writeLine( stream
, buf
, pFilter
);
733 for ( std::size_t nPos
= 0;
734 nPos
< pOEntry
->aInterfaces
.size(); ++nPos
)
736 const InterfaceEntry
& rIEntry
= pOEntry
->aInterfaces
[nPos
];
738 buf
.append( OUString::Concat(" - ")
739 + OUString::unacquired(&rIEntry
.pTypeDescr
->aBase
.pTypeName
) );
740 if (rIEntry
.fpFreeProxy
)
742 buf
.append( "; proxy free=0x"
743 + OUString::number( reinterpret_cast< sal_IntPtr
>(rIEntry
.fpFreeProxy
), 16 ) );
747 buf
.append( "; original" );
749 buf
.append( "; ptr=0x"
750 + OUString::number(reinterpret_cast< sal_IntPtr
>(rIEntry
.pInterface
), 16 ) );
752 if (pOEntry
->find( rIEntry
.pInterface
, nPos
+ 1 ) < 0)
754 std::size_t erased
= ptr2obj
.erase( rIEntry
.pInterface
);
757 buf
.append( " (ptr not found in map!)" );
760 writeLine( stream
, buf
, pFilter
);
764 if (! ptr2obj
.empty())
765 writeLine( stream
, "ptr map inconsistency!!!", pFilter
);
766 writeLine( stream
, "#####################################"
767 "#########################################", pFilter
);
771 extern "C" void SAL_CALL
uno_dumpEnvironmentByName(
772 void * stream
, rtl_uString
* pEnvDcp
, const char * pFilter
)
775 uno_Environment
* pEnv
= nullptr;
776 uno_getEnvironment( &pEnv
, pEnvDcp
, nullptr );
779 ::uno_dumpEnvironment( stream
, pEnv
, pFilter
);
780 (*pEnv
->release
)( pEnv
);
786 Concat2View("environment \"" + OUString::unacquired(&pEnvDcp
) + "\" does not exist!"),
794 const OUString
& unoenv_getStaticOIdPart()
796 static auto const theStaticOIdPart
= [] {
797 OUStringBuffer
aRet( 64 );
801 info
.Size
= sizeof(oslProcessInfo
);
802 if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER
, &info
) ==
805 aRet
.append( static_cast<sal_Int64
>(info
.Ident
), 16 );
809 aRet
.append( "unknown process id" );
813 ::rtl_getGlobalProcessId( ar
);
815 for (unsigned char i
: ar
)
816 aRet
.append( static_cast<sal_Int32
>(i
), 16 );
818 return aRet
.makeStringAndClear();
820 return theStaticOIdPart
;
829 static void unoenv_computeObjectIdentifier(
830 uno_ExtEnvironment
* pEnv
, rtl_uString
** ppOId
, void * pInterface
)
832 assert(pEnv
&& ppOId
&& pInterface
&& "### null ptr!");
835 ::rtl_uString_release( *ppOId
);
839 uno_Interface
* pUnoI
= static_cast<uno_Interface
*>(
840 ::cppu::binuno_queryInterface(
841 pInterface
, *typelib_static_type_getByTypeClass(
842 typelib_TypeClass_INTERFACE
) ));
843 if (nullptr == pUnoI
)
846 (*pUnoI
->release
)( pUnoI
);
849 OUString::number( reinterpret_cast< sal_IntPtr
>(pUnoI
), 16 ) + ";"
850 // environment[context]
851 + OUString::unacquired(&pEnv
->aBase
.pTypeName
) + "["
852 + OUString::number( reinterpret_cast< sal_IntPtr
>(
854 uno_Environment
* >(pEnv
)->pContext
), 16 )
856 + unoenv_getStaticOIdPart() );
858 ::rtl_uString_acquire( *ppOId
);
862 static void unoenv_acquireInterface(
863 SAL_UNUSED_PARAMETER uno_ExtEnvironment
*, void * pUnoI_
)
865 uno_Interface
* pUnoI
= static_cast< uno_Interface
* >(pUnoI_
);
866 (*pUnoI
->acquire
)( pUnoI
);
870 static void unoenv_releaseInterface(
871 SAL_UNUSED_PARAMETER uno_ExtEnvironment
*, void * pUnoI_
)
873 uno_Interface
* pUnoI
= static_cast< uno_Interface
* >(pUnoI_
);
874 (*pUnoI
->release
)( pUnoI
);
880 EnvironmentsData::~EnvironmentsData()
882 ::osl::MutexGuard
guard( mutex
);
885 for ( const auto& rEntry
: aName2EnvMap
)
887 uno_Environment
* pWeak
= rEntry
.second
;
888 uno_Environment
* pHard
= nullptr;
889 (*pWeak
->harden
)( &pHard
, pWeak
);
890 (*pWeak
->releaseWeak
)( pWeak
);
894 (*pHard
->dispose
)( pHard
); // send explicit dispose
895 (*pHard
->release
)( pHard
);
901 void EnvironmentsData::getEnvironment(
902 uno_Environment
** ppEnv
, std::u16string_view rEnvDcp
, void * pContext
)
906 (*(*ppEnv
)->release
)( *ppEnv
);
910 OUString aKey
= OUString::number( reinterpret_cast< sal_IntPtr
>(pContext
) ) + rEnvDcp
;
912 // try to find registered mapping
913 OUString2EnvironmentMap::const_iterator
const iFind(
914 aName2EnvMap
.find( aKey
) );
915 if (iFind
!= aName2EnvMap
.end())
917 uno_Environment
* pWeak
= iFind
->second
;
918 (*pWeak
->harden
)( ppEnv
, pWeak
);
923 void EnvironmentsData::registerEnvironment( uno_Environment
** ppEnv
)
925 OSL_ENSURE( ppEnv
, "### null ptr!" );
926 uno_Environment
* pEnv
= *ppEnv
;
929 OUString::number( reinterpret_cast< sal_IntPtr
>(pEnv
->pContext
) ) +
930 OUString::unacquired(&pEnv
->pTypeName
);
932 // try to find registered environment
933 OUString2EnvironmentMap::const_iterator
const iFind(
934 aName2EnvMap
.find( aKey
) );
935 if (iFind
== aName2EnvMap
.end())
937 (*pEnv
->acquireWeak
)( pEnv
);
938 std::pair
< OUString2EnvironmentMap::iterator
, bool > insertion (
939 aName2EnvMap
.emplace( aKey
, pEnv
) );
940 SAL_WARN_IF( !insertion
.second
, "cppu", "key " << aKey
<< " already in env map" );
944 uno_Environment
* pHard
= nullptr;
945 uno_Environment
* pWeak
= iFind
->second
;
946 (*pWeak
->harden
)( &pHard
, pWeak
);
949 (*pEnv
->release
)( pEnv
);
952 else // registered one is dead
954 (*pWeak
->releaseWeak
)( pWeak
);
955 (*pEnv
->acquireWeak
)( pEnv
);
956 aName2EnvMap
[ aKey
] = pEnv
;
962 void EnvironmentsData::getRegisteredEnvironments(
963 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
, uno_memAlloc memAlloc
,
964 std::u16string_view rEnvDcp
)
966 assert(pppEnvs
&& pnLen
&& memAlloc
&& "### null ptr!");
969 std::vector
<uno_Environment
*> aFounds(aName2EnvMap
.size());
972 // find matching environment
973 for ( const auto& rEntry
: aName2EnvMap
)
975 uno_Environment
* pWeak
= rEntry
.second
;
976 if (rEnvDcp
.empty() ||
977 rEnvDcp
== OUString::unacquired(&pWeak
->pTypeName
) )
979 aFounds
[nSize
] = nullptr;
980 (*pWeak
->harden
)( &aFounds
[nSize
], pWeak
);
989 *pppEnvs
= static_cast<uno_Environment
**>((*memAlloc
)(
990 sizeof (uno_Environment
*) * nSize
));
991 OSL_ASSERT( *pppEnvs
);
994 (*pppEnvs
)[nSize
] = aFounds
[nSize
];
1003 bool loadEnv(OUString
const & cLibStem
,
1004 uno_Environment
* pEnv
)
1006 #ifdef DISABLE_DYNLOADING
1007 uno_initEnvironmentFunc fpInit
;
1009 if ( cLibStem
== CPPU_CURRENT_LANGUAGE_BINDING_NAME
"_uno" )
1010 fpInit
= CPPU_ENV_uno_initEnvironment
;
1011 #if HAVE_FEATURE_JAVA
1012 else if ( cLibStem
== "java_uno" )
1013 fpInit
= java_uno_initEnvironment
;
1017 SAL_INFO("cppu", ": Unhandled env: " << cLibStem
);
1021 // late init with some code from matching uno language binding
1022 // will be unloaded by environment
1025 bool bMod
= cppu::detail::loadModule(aMod
, cLibStem
);
1030 // Catch everything and convert to return false
1035 uno_initEnvironmentFunc fpInit
= reinterpret_cast<uno_initEnvironmentFunc
>(aMod
.getSymbol(UNO_INIT_ENVIRONMENT
));
1043 (*fpInit
)( pEnv
); // init of environment
1053 static uno_Environment
* initDefaultEnvironment(
1054 const OUString
& rEnvDcp
, void * pContext
)
1056 // coverity[leaked_storage : FALSE] - lifetime is controlled by acquire()/release() calls
1057 uno_Environment
* pEnv
= &(new uno_DefaultEnvironment( rEnvDcp
, pContext
))->aBase
;
1058 (*pEnv
->acquire
)( pEnv
);
1060 OUString envTypeName
= cppu::EnvDcp::getTypeName(rEnvDcp
);
1062 // create default environment
1063 if ( envTypeName
== UNO_LB_UNO
)
1065 uno_DefaultEnvironment
* that
= reinterpret_cast<uno_DefaultEnvironment
*>(pEnv
);
1066 that
->computeObjectIdentifier
= unoenv_computeObjectIdentifier
;
1067 that
->acquireInterface
= unoenv_acquireInterface
;
1068 that
->releaseInterface
= unoenv_releaseInterface
;
1070 OUString envPurpose
= cppu::EnvDcp::getPurpose(rEnvDcp
);
1071 if (!envPurpose
.isEmpty())
1074 OUString::Concat(envPurpose
.subView(envPurpose
.lastIndexOf(':') + 1)) + "_uno_uno");
1075 if(!loadEnv(libStem
, pEnv
))
1077 pEnv
->release(pEnv
);
1084 // late init with some code from matching uno language binding
1085 OUString
aStr( envTypeName
+ "_uno" );
1087 if (!loadEnv(aStr
, pEnv
))
1089 pEnv
->release(pEnv
);
1098 void SAL_CALL
uno_createEnvironment(
1099 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
)
1100 SAL_THROW_EXTERN_C()
1102 assert(ppEnv
&& "### null ptr!");
1104 (*(*ppEnv
)->release
)( *ppEnv
);
1106 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1107 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1110 void SAL_CALL
uno_getEnvironment(
1111 uno_Environment
** ppEnv
, rtl_uString
* pEnvDcp
, void * pContext
)
1112 SAL_THROW_EXTERN_C()
1114 assert(ppEnv
&& "### null ptr!");
1115 OUString
const & rEnvDcp
= OUString::unacquired( &pEnvDcp
);
1117 EnvironmentsData
& rData
= theEnvironmentsData();
1119 ::osl::MutexGuard
guard( rData
.mutex
);
1120 rData
.getEnvironment( ppEnv
, rEnvDcp
, pContext
);
1123 *ppEnv
= initDefaultEnvironment( rEnvDcp
, pContext
);
1126 // register new environment:
1127 rData
.registerEnvironment( ppEnv
);
1132 void SAL_CALL
uno_getRegisteredEnvironments(
1133 uno_Environment
*** pppEnvs
, sal_Int32
* pnLen
, uno_memAlloc memAlloc
,
1134 rtl_uString
* pEnvDcp
)
1135 SAL_THROW_EXTERN_C()
1137 EnvironmentsData
& rData
= theEnvironmentsData();
1139 ::osl::MutexGuard
guard( rData
.mutex
);
1140 rData
.getRegisteredEnvironments(
1141 pppEnvs
, pnLen
, memAlloc
,
1142 (pEnvDcp
? OUString(pEnvDcp
) : OUString()) );
1147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */