tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / cppu / source / uno / lbenv.cxx
blob32a145e3de355a18713f09b9e17988b55714d00a
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 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
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 );
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)
315 ++pIEntry->refCount;
317 else
319 void * pInterface = pIEntry->pInterface;
320 (*pEnv->acquireInterface)( pEnv, pInterface );
321 --pOEntry->nRef; // manual revoke of proxy to be freed
322 guard.clear();
323 (*freeProxy)( pEnv, *ppInterface );
324 *ppInterface = pInterface;
327 else
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)
350 // cleanup maps
351 that->aOId2ObjectMap.erase( pOEntry->oid );
352 sal_Int32 nPos;
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!!!
360 guard.clear();
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 );
371 else
373 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
377 delete pOEntry;
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 );
386 if (index > 0)
388 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
389 OSL_ASSERT( entry.pInterface == pInterface );
390 if (entry.fpFreeProxy != nullptr)
392 --entry.refCount;
393 if (entry.refCount == 0)
395 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
396 typelib_TypeDescription * pTypeDescr =
397 reinterpret_cast< typelib_TypeDescription * >(
398 entry.pTypeDescr );
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
406 std::size_t erased =
407 that->aPtr2ObjectMap.erase( pInterface );
408 OSL_ASSERT( erased == 1 );
411 guard.clear();
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!");
431 if (*ppOId)
433 ::rtl_uString_release( *ppOId );
434 *ppOId = nullptr;
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())
445 guard.clear();
446 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
448 else
450 rtl_uString * hstr = iFind->second->oid.pData;
451 rtl_uString_acquire( hstr );
452 *ppOId = 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!");
461 if (*ppInterface)
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 );
477 if (pIEntry)
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();
495 sal_Int32 nPos = 0;
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] );
502 nPos++;
505 *pppInterfaces = ppInterfaces;
506 *pnLen = nLen;
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 ))
534 delete that;
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 ))
551 delete that;
556 static void defenv_harden(
557 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
559 if (*ppHardEnv)
561 (*(*ppHardEnv)->release)( *ppHardEnv );
562 *ppHardEnv = nullptr;
565 EnvironmentsData & rData = theEnvironmentsData();
567 if (rData.isDisposing)
568 return;
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
575 that->nRef = 0;
576 return;
579 osl_atomic_increment( &that->nWeakRef );
580 *ppHardEnv = pEnv;
584 static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
590 uno_DefaultEnvironment::uno_DefaultEnvironment(
591 const OUString & rEnvDcp_, void * pContext_ )
592 : nRef( 0 ),
593 nWeakRef( 0 )
595 uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
596 that->pReserved = nullptr;
597 // functions
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;
605 // identifier
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 );
630 void writeLine(
631 void * stream, const char * pLine, const char * pFilter )
633 if (pFilter && *pFilter)
635 // lookup pFilter in pLine
636 while (*pLine)
638 if (*pLine == *pFilter)
640 sal_Int32 nPos = 1;
641 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
643 ++nPos;
645 if (! pFilter[nPos])
647 if (stream)
649 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
651 else
653 SAL_WARN("cppu", pLine );
657 ++pLine;
660 else
662 if (stream)
664 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
666 else
668 fprintf( stderr, "%s\n", pLine );
674 void writeLine(
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!");
688 OUStringBuffer buf;
690 if (! pEnv->pExtEnv)
692 writeLine( stream, "###################################"
693 "###########################################", pFilter );
694 buf.append( OUString::Concat("environment: ") + OUString::unacquired(&pEnv->pTypeName) );
695 writeLine( stream, buf, pFilter );
696 buf.setLength(0);
697 writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
698 return;
701 writeLine( stream, "########################################"
702 "######################################", pFilter );
703 buf.append( OUString::Concat("environment dump: ") + OUString::unacquired(&pEnv->pTypeName) );
704 writeLine( stream, buf, pFilter );
705 buf.setLength(0);
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;
716 buf.append( "+ " );
717 if (pOEntry->mixedObject)
718 buf.append( "mixed " );
719 buf.append( "object entry: nRef="
720 + OUString::number(pOEntry->nRef)
721 + "; oid=\""
722 + pOEntry->oid
723 + "\"" );
724 writeLine( stream, buf, pFilter );
725 buf.setLength(0);
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 ) );
739 else
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 );
749 if (erased != 1)
751 buf.append( " (ptr not found in map!)" );
754 writeLine( stream, buf, pFilter );
755 buf.setLength(0);
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 );
770 if (pEnv)
772 ::uno_dumpEnvironment( stream, pEnv, pFilter );
773 (*pEnv->release)( pEnv );
775 else
777 writeLine(
778 stream,
779 Concat2View("environment \"" + OUString::unacquired(&pEnvDcp) + "\" does not exist!"),
780 pFilter );
784 namespace
787 const OUString & unoenv_getStaticOIdPart()
789 static auto const theStaticOIdPart = [] {
790 OUStringBuffer aRet( 64 );
791 aRet.append( "];" );
792 // pid
793 oslProcessInfo info;
794 info.Size = sizeof(oslProcessInfo);
795 if (::osl_getProcessInfo( nullptr, osl_Process_IDENTIFIER, &info ) ==
796 osl_Process_E_None)
798 aRet.append( static_cast<sal_Int64>(info.Ident), 16 );
800 else
802 aRet.append( "unknown process id" );
804 // good guid
805 sal_uInt8 ar[16];
806 ::rtl_getGlobalProcessId( ar );
807 aRet.append( ';' );
808 for (unsigned char i : ar)
809 aRet.append( static_cast<sal_Int32>(i), 16 );
811 return aRet.makeStringAndClear();
812 }();
813 return theStaticOIdPart;
818 extern "C"
822 static void unoenv_computeObjectIdentifier(
823 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
825 assert(pEnv && ppOId && pInterface && "### null ptr!");
826 if (*ppOId)
828 ::rtl_uString_release( *ppOId );
829 *ppOId = nullptr;
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)
837 return;
839 (*pUnoI->release)( pUnoI );
840 OUString aStr(
841 // interface
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 >(
846 reinterpret_cast<
847 uno_Environment * >(pEnv)->pContext ), 16 )
848 // process;good guid
849 + unoenv_getStaticOIdPart() );
850 *ppOId = aStr.pData;
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 );
871 namespace {
873 EnvironmentsData::~EnvironmentsData()
875 ::osl::MutexGuard guard( mutex );
876 isDisposing = true;
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 );
885 if (pHard)
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 )
897 if (*ppEnv)
899 (*(*ppEnv)->release)( *ppEnv );
900 *ppEnv = nullptr;
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;
920 OUString aKey =
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" );
934 else
936 uno_Environment * pHard = nullptr;
937 uno_Environment * pWeak = iFind->second;
938 (*pWeak->harden)( &pHard, pWeak );
939 if (pHard)
941 (*pEnv->release)( pEnv );
942 *ppEnv = pHard;
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!");
959 // max size
960 std::vector<uno_Environment*> aFounds(aName2EnvMap.size());
961 sal_Int32 nSize = 0;
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 );
972 if (aFounds[nSize])
973 ++nSize;
977 *pnLen = nSize;
978 if (nSize)
980 *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
981 sizeof (uno_Environment *) * nSize ));
982 OSL_ASSERT( *pppEnvs );
983 while (nSize--)
985 (*pppEnvs)[nSize] = aFounds[nSize];
988 else
990 *pppEnvs = nullptr;
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;
1005 #endif
1006 else
1008 SAL_INFO("cppu", ": Unhandled env: " << cLibStem);
1009 return false;
1011 #else
1012 // late init with some code from matching uno language binding
1013 // will be unloaded by environment
1014 osl::Module aMod;
1015 try {
1016 bool bMod = cppu::detail::loadModule(aMod, cLibStem);
1017 if (!bMod)
1018 return false;
1020 catch(...) {
1021 // Catch everything and convert to return false
1022 return false;
1026 uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(u"" UNO_INIT_ENVIRONMENT ""_ustr));
1028 if (!fpInit)
1029 return false;
1031 aMod.release();
1032 #endif
1034 (*fpInit)( pEnv ); // init of environment
1035 return true;
1040 extern "C"
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())
1064 OUString libStem(
1065 OUString::Concat(envPurpose.subView(envPurpose.lastIndexOf(':') + 1)) + "_uno_uno");
1066 if(!loadEnv(libStem, pEnv))
1068 pEnv->release(pEnv);
1069 return nullptr;
1073 else
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);
1081 return nullptr;
1085 return pEnv;
1089 void SAL_CALL uno_createEnvironment(
1090 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext ) noexcept
1092 assert(ppEnv && "### null ptr!");
1093 if (*ppEnv)
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 );
1110 if (! *ppEnv)
1112 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1113 if (*ppEnv)
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()) );
1133 } // extern "C"
1135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */