Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / cppu / source / uno / lbenv.cxx
blobf9d6633b2bede6de6dd634560677a320a7109844
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #endif
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>
40 #include "prim.hxx"
41 #include "loadmodule.hxx"
43 #include <string_view>
44 #include <unordered_map>
45 #include <utility>
46 #include <vector>
47 #include <stdio.h>
50 namespace
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 &&
59 ::rtl_ustr_compare(
60 pTD1->aBase.pTypeName->buffer,
61 pTD2->aBase.pTypeName->buffer ) == 0));
64 struct uno_DefaultEnvironment;
67 struct InterfaceEntry
69 sal_Int32 refCount;
70 void * pInterface;
71 uno_freeProxyFunc fpFreeProxy;
72 typelib_InterfaceTypeDescription * pTypeDescr;
75 struct ObjectEntry
77 OUString oid;
78 std::vector< InterfaceEntry > aInterfaces;
79 sal_Int32 nRef;
80 bool mixedObject;
82 explicit ObjectEntry( OUString aOId_ );
84 void append(
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;
94 struct FctPtrHash
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
114 ::osl::Mutex mutex;
115 OUString2EnvironmentMap aName2EnvMap;
117 EnvironmentsData() : isDisposing(false) {}
118 ~EnvironmentsData();
120 void getEnvironment(
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 );
127 bool isDisposing;
130 EnvironmentsData& theEnvironmentsData()
132 static EnvironmentsData SINGLETON;
133 return SINGLETON;
136 struct uno_DefaultEnvironment : public uno_ExtEnvironment
138 sal_Int32 nRef;
139 sal_Int32 nWeakRef;
141 ::osl::Mutex mutex;
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_ )),
153 nRef( 0 ),
154 mixedObject( false )
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;
166 if (! fpFreeProxy)
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 ) );
176 SAL_WARN_IF(
177 !i.second && (find(pInterface, 0) == -1 || i.first->second != this),
178 "cppu",
179 "map already contains " << i.first->second << " != " << this << " for "
180 << pInterface);
181 aInterfaces.push_back( aNewEntry );
185 InterfaceEntry * ObjectEntry::find(
186 typelib_InterfaceTypeDescription * pTypeDescr_ )
188 OSL_ASSERT( ! aInterfaces.empty() );
189 if (aInterfaces.empty())
190 return nullptr;
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;
205 while (pITD)
207 if (td_equals( pITD, pTypeDescr_ ))
208 return &aInterfaces[ nPos ];
209 pITD = pITD->pBaseTypeDescription;
212 return nullptr;
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)
223 return pos;
225 return -1;
228 extern "C"
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
261 ++pIEntry->refCount;
262 if (pIEntry->pInterface != *ppInterface)
264 void * pInterface = pIEntry->pInterface;
265 (*pEnv->acquireInterface)( pEnv, pInterface );
266 guard.clear();
267 (*pEnv->releaseInterface)( pEnv, *ppInterface );
268 *ppInterface = pInterface;
271 else
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,
284 "### null ptr!" );
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)
317 ++pIEntry->refCount;
319 else
321 void * pInterface = pIEntry->pInterface;
322 (*pEnv->acquireInterface)( pEnv, pInterface );
323 --pOEntry->nRef; // manual revoke of proxy to be freed
324 guard.clear();
325 (*freeProxy)( pEnv, *ppInterface );
326 *ppInterface = pInterface;
329 else
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)
353 // cleanup maps
354 that->aOId2ObjectMap.erase( pOEntry->oid );
355 sal_Int32 nPos;
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!!!
363 guard.clear();
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 );
374 else
376 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
380 delete pOEntry;
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 );
389 if (index > 0)
391 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
392 OSL_ASSERT( entry.pInterface == pInterface );
393 if (entry.fpFreeProxy != nullptr)
395 --entry.refCount;
396 if (entry.refCount == 0)
398 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
399 typelib_TypeDescription * pTypeDescr =
400 reinterpret_cast< typelib_TypeDescription * >(
401 entry.pTypeDescr );
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
409 std::size_t erased =
410 that->aPtr2ObjectMap.erase( pInterface );
411 OSL_ASSERT( erased == 1 );
414 guard.clear();
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!" );
434 if (*ppOId)
436 ::rtl_uString_release( *ppOId );
437 *ppOId = nullptr;
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())
448 guard.clear();
449 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
451 else
453 rtl_uString * hstr = iFind->second->oid.pData;
454 rtl_uString_acquire( hstr );
455 *ppOId = 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!" );
465 if (*ppInterface)
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 );
481 if (pIEntry)
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();
500 sal_Int32 nPos = 0;
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] );
507 nPos++;
510 *pppInterfaces = ppInterfaces;
511 *pnLen = nLen;
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 ))
539 delete that;
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 ))
556 delete that;
561 static void defenv_harden(
562 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
564 if (*ppHardEnv)
566 (*(*ppHardEnv)->release)( *ppHardEnv );
567 *ppHardEnv = nullptr;
570 EnvironmentsData & rData = theEnvironmentsData();
572 if (rData.isDisposing)
573 return;
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
580 that->nRef = 0;
581 return;
584 osl_atomic_increment( &that->nWeakRef );
585 *ppHardEnv = pEnv;
589 static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
595 uno_DefaultEnvironment::uno_DefaultEnvironment(
596 const OUString & rEnvDcp_, void * pContext_ )
597 : nRef( 0 ),
598 nWeakRef( 0 )
600 uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
601 that->pReserved = nullptr;
602 // functions
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;
610 // identifier
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 );
635 void writeLine(
636 void * stream, const char * pLine, const char * pFilter )
638 if (pFilter && *pFilter)
640 // lookup pFilter in pLine
641 while (*pLine)
643 if (*pLine == *pFilter)
645 sal_Int32 nPos = 1;
646 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
648 ++nPos;
650 if (! pFilter[nPos])
652 if (stream)
654 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
656 else
658 SAL_WARN("cppu", pLine );
662 ++pLine;
665 else
667 if (stream)
669 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
671 else
673 fprintf( stderr, "%s\n", pLine );
679 void writeLine(
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 )
691 SAL_THROW_EXTERN_C()
693 OSL_ENSURE( pEnv, "### null ptr!" );
694 OUStringBuffer buf;
696 if (! pEnv->pExtEnv)
698 writeLine( stream, "###################################"
699 "###########################################", pFilter );
700 buf.append( OUString::Concat("environment: ") + OUString::unacquired(&pEnv->pTypeName) );
701 writeLine( stream, buf, pFilter );
702 buf.setLength(0);
703 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
704 return;
707 writeLine( stream, "########################################"
708 "######################################", pFilter );
709 buf.append( OUString::Concat("environment dump: ") + OUString::unacquired(&pEnv->pTypeName) );
710 writeLine( stream, buf, pFilter );
711 buf.setLength(0);
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;
722 buf.append( "+ " );
723 if (pOEntry->mixedObject)
724 buf.append( "mixed " );
725 buf.append( "object entry: nRef="
726 + OUString::number(pOEntry->nRef)
727 + "; oid=\""
728 + pOEntry->oid
729 + "\"" );
730 writeLine( stream, buf, pFilter );
731 buf.setLength(0);
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 ) );
745 else
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 );
755 if (erased != 1)
757 buf.append( " (ptr not found in map!)" );
760 writeLine( stream, buf, pFilter );
761 buf.setLength(0);
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 )
773 SAL_THROW_EXTERN_C()
775 uno_Environment * pEnv = nullptr;
776 uno_getEnvironment( &pEnv, pEnvDcp, nullptr );
777 if (pEnv)
779 ::uno_dumpEnvironment( stream, pEnv, pFilter );
780 (*pEnv->release)( pEnv );
782 else
784 writeLine(
785 stream,
786 Concat2View("environment \"" + OUString::unacquired(&pEnvDcp) + "\" does not exist!"),
787 pFilter );
791 namespace
794 const OUString & unoenv_getStaticOIdPart()
796 static auto const theStaticOIdPart = [] {
797 OUStringBuffer aRet( 64 );
798 aRet.append( "];" );
799 // pid
800 oslProcessInfo info;
801 info.Size = sizeof(oslProcessInfo);
802 if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER, &info ) ==
803 osl_Process_E_None)
805 aRet.append( static_cast<sal_Int64>(info.Ident), 16 );
807 else
809 aRet.append( "unknown process id" );
811 // good guid
812 sal_uInt8 ar[16];
813 ::rtl_getGlobalProcessId( ar );
814 aRet.append( ';' );
815 for (unsigned char i : ar)
816 aRet.append( static_cast<sal_Int32>(i), 16 );
818 return aRet.makeStringAndClear();
819 }();
820 return theStaticOIdPart;
825 extern "C"
829 static void unoenv_computeObjectIdentifier(
830 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
832 assert(pEnv && ppOId && pInterface && "### null ptr!");
833 if (*ppOId)
835 ::rtl_uString_release( *ppOId );
836 *ppOId = nullptr;
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)
844 return;
846 (*pUnoI->release)( pUnoI );
847 OUString aStr(
848 // interface
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 >(
853 reinterpret_cast<
854 uno_Environment * >(pEnv)->pContext ), 16 )
855 // process;good guid
856 + unoenv_getStaticOIdPart() );
857 *ppOId = aStr.pData;
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 );
878 namespace {
880 EnvironmentsData::~EnvironmentsData()
882 ::osl::MutexGuard guard( mutex );
883 isDisposing = true;
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 );
892 if (pHard)
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 )
904 if (*ppEnv)
906 (*(*ppEnv)->release)( *ppEnv );
907 *ppEnv = nullptr;
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;
928 OUString aKey =
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" );
942 else
944 uno_Environment * pHard = nullptr;
945 uno_Environment * pWeak = iFind->second;
946 (*pWeak->harden)( &pHard, pWeak );
947 if (pHard)
949 (*pEnv->release)( pEnv );
950 *ppEnv = pHard;
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!");
968 // max size
969 std::vector<uno_Environment*> aFounds(aName2EnvMap.size());
970 sal_Int32 nSize = 0;
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 );
981 if (aFounds[nSize])
982 ++nSize;
986 *pnLen = nSize;
987 if (nSize)
989 *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
990 sizeof (uno_Environment *) * nSize ));
991 OSL_ASSERT( *pppEnvs );
992 while (nSize--)
994 (*pppEnvs)[nSize] = aFounds[nSize];
997 else
999 *pppEnvs = nullptr;
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;
1014 #endif
1015 else
1017 SAL_INFO("cppu", ": Unhandled env: " << cLibStem);
1018 return false;
1020 #else
1021 // late init with some code from matching uno language binding
1022 // will be unloaded by environment
1023 osl::Module aMod;
1024 try {
1025 bool bMod = cppu::detail::loadModule(aMod, cLibStem);
1026 if (!bMod)
1027 return false;
1029 catch(...) {
1030 // Catch everything and convert to return false
1031 return false;
1035 uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(UNO_INIT_ENVIRONMENT));
1037 if (!fpInit)
1038 return false;
1040 aMod.release();
1041 #endif
1043 (*fpInit)( pEnv ); // init of environment
1044 return true;
1049 extern "C"
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())
1073 OUString libStem(
1074 OUString::Concat(envPurpose.subView(envPurpose.lastIndexOf(':') + 1)) + "_uno_uno");
1075 if(!loadEnv(libStem, pEnv))
1077 pEnv->release(pEnv);
1078 return nullptr;
1082 else
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);
1090 return nullptr;
1094 return 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!");
1103 if (*ppEnv)
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 );
1121 if (! *ppEnv)
1123 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1124 if (*ppEnv)
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()) );
1145 } // extern "C"
1147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */