LibreOffice Module cppu (master) 1
lbenv.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifdef DISABLE_DYNLOADING
21#include <config_java.h>
22#endif
23
24#include <cppu/EnvDcp.hxx>
25
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"
42
43#include <string_view>
44#include <unordered_map>
45#include <utility>
46#include <vector>
47#include <stdio.h>
48
49
50namespace
51{
52
53
54bool td_equals( typelib_InterfaceTypeDescription const * pTD1,
55 typelib_InterfaceTypeDescription const * pTD2 )
56{
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));
62}
63
64struct uno_DefaultEnvironment;
65
66
67struct InterfaceEntry
68{
69 sal_Int32 refCount;
70 void * pInterface;
71 uno_freeProxyFunc fpFreeProxy;
72 typelib_InterfaceTypeDescription * pTypeDescr;
73};
74
75struct ObjectEntry
76{
77 OUString oid;
78 std::vector< InterfaceEntry > aInterfaces;
79 sal_Int32 nRef;
80 bool mixedObject;
81
82 explicit ObjectEntry( OUString aOId_ );
83
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;
91};
92
93
94struct FctPtrHash
95{
96 std::size_t operator () ( const void * pKey ) const
97 { return reinterpret_cast< std::size_t>( pKey ); }
98};
99
100
101// mapping from environment name to environment
102typedef std::unordered_map<
103 OUString, uno_Environment * > OUString2EnvironmentMap;
104
105// mapping from ptr to object entry
106typedef std::unordered_map<
107 void *, ObjectEntry *, FctPtrHash > Ptr2ObjectMap;
108// mapping from oid to object entry
109typedef std::unordered_map<
110 OUString, ObjectEntry * > OId2ObjectMap;
111
112struct EnvironmentsData
113{
114 ::osl::Mutex mutex;
115 OUString2EnvironmentMap aName2EnvMap;
116
117 EnvironmentsData() : isDisposing(false) {}
118 ~EnvironmentsData();
119
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 );
126
127 bool isDisposing;
128};
129
130EnvironmentsData& theEnvironmentsData()
131{
132 static EnvironmentsData SINGLETON;
133 return SINGLETON;
134}
135
136struct uno_DefaultEnvironment : public uno_ExtEnvironment
137{
138 sal_Int32 nRef;
139 sal_Int32 nWeakRef;
140
141 ::osl::Mutex mutex;
142 Ptr2ObjectMap aPtr2ObjectMap;
143 OId2ObjectMap aOId2ObjectMap;
144
145 uno_DefaultEnvironment(
146 const OUString & rEnvDcp_, void * pContext_ );
147 ~uno_DefaultEnvironment();
148};
149
150
151ObjectEntry::ObjectEntry( OUString aOId_ )
152 : oid(std::move( aOId_ )),
153 nRef( 0 ),
154 mixedObject( false )
155{
156 aInterfaces.reserve( 2 );
157}
158
159
160void ObjectEntry::append(
161 uno_DefaultEnvironment * pEnv,
162 void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
163 uno_freeProxyFunc fpFreeProxy )
164{
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;
173
174 std::pair< Ptr2ObjectMap::iterator, bool > i(
175 pEnv->aPtr2ObjectMap.emplace( pInterface, this ) );
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 );
182}
183
184
185InterfaceEntry * ObjectEntry::find(
186 typelib_InterfaceTypeDescription * pTypeDescr_ )
187{
188 OSL_ASSERT( ! aInterfaces.empty() );
189 if (aInterfaces.empty())
190 return nullptr;
191
192 // shortcut common case:
193 OUString const & type_name =
194 OUString::unacquired( &pTypeDescr_->aBase.pTypeName );
195 if ( type_name == "com.sun.star.uno.XInterface" )
196 {
197 return aInterfaces.data();
198 }
199
200 std::size_t nSize = aInterfaces.size();
201 for ( std::size_t nPos = 0; nPos < nSize; ++nPos )
202 {
203 typelib_InterfaceTypeDescription * pITD =
204 aInterfaces[ nPos ].pTypeDescr;
205 while (pITD)
206 {
207 if (td_equals( pITD, pTypeDescr_ ))
208 return &aInterfaces[ nPos ];
209 pITD = pITD->pBaseTypeDescription;
210 }
211 }
212 return nullptr;
213}
214
215
216sal_Int32 ObjectEntry::find(
217 void const * iface_ptr, std::size_t pos ) const
218{
219 std::size_t size = aInterfaces.size();
220 for ( ; pos < size; ++pos )
221 {
222 if (aInterfaces[ pos ].pInterface == iface_ptr)
223 return pos;
224 }
225 return -1;
226}
227
228extern "C"
229{
230
231
232static void defenv_registerInterface(
233 uno_ExtEnvironment * pEnv, void ** ppInterface,
234 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
235{
236 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
237 OUString const & rOId = OUString::unacquired( &pOId );
238
239 uno_DefaultEnvironment * that =
240 static_cast< uno_DefaultEnvironment * >( pEnv );
241 ::osl::ClearableMutexGuard guard( that->mutex );
242
243 // try to insert dummy 0:
244 std::pair<OId2ObjectMap::iterator, bool> const insertion(
245 that->aOId2ObjectMap.emplace( rOId, nullptr ) );
246 if (insertion.second)
247 {
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 );
252 }
253 else // object entry exists
254 {
255 ObjectEntry * pOEntry = insertion.first->second;
256 ++pOEntry->nRef; // another register call on object
257 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
258
259 if (pIEntry) // type entry exists
260 {
261 ++pIEntry->refCount;
262 if (pIEntry->pInterface != *ppInterface)
263 {
264 void * pInterface = pIEntry->pInterface;
265 (*pEnv->acquireInterface)( pEnv, pInterface );
266 guard.clear();
267 (*pEnv->releaseInterface)( pEnv, *ppInterface );
268 *ppInterface = pInterface;
269 }
270 }
271 else
272 {
273 pOEntry->append( that, *ppInterface, pTypeDescr, nullptr );
274 }
275 }
276}
277
278
279static void defenv_registerProxyInterface(
280 uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
281 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
282{
283 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
284 "### null ptr!" );
285 OUString const & rOId = OUString::unacquired( &pOId );
286
287 uno_DefaultEnvironment * that =
288 static_cast< uno_DefaultEnvironment * >( pEnv );
289 ::osl::ClearableMutexGuard guard( that->mutex );
290
291 // try to insert dummy 0:
292 std::pair<OId2ObjectMap::iterator, bool> const insertion(
293 that->aOId2ObjectMap.emplace( rOId, nullptr ) );
294 if (insertion.second)
295 {
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 );
300 }
301 else // object entry exists
302 {
303 ObjectEntry * pOEntry = insertion.first->second;
304
305 // first registration was an original, then registerProxyInterface():
306 pOEntry->mixedObject |=
307 (!pOEntry->aInterfaces.empty() &&
308 pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr);
309
310 ++pOEntry->nRef; // another register call on object
311 InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
312
313 if (pIEntry) // type entry exists
314 {
315 if (pIEntry->pInterface == *ppInterface)
316 {
317 ++pIEntry->refCount;
318 }
319 else
320 {
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;
327 }
328 }
329 else
330 {
331 pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
332 }
333 }
334}
335
336
337static void s_stub_defenv_revokeInterface(va_list * pParam)
338{
339 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
340 void * pInterface = va_arg(*pParam, void *);
341
342 OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
343 uno_DefaultEnvironment * that =
344 static_cast< uno_DefaultEnvironment * >( pEnv );
345 ::osl::ClearableMutexGuard guard( that->mutex );
346
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)
352 {
353 // cleanup maps
354 that->aOId2ObjectMap.erase( pOEntry->oid );
355 sal_Int32 nPos;
356 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
357 {
358 that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
359 }
360
361 // the last proxy interface of the environment might kill this
362 // environment, because of releasing its language binding!!!
363 guard.clear();
364
365 // release interfaces
366 for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
367 {
368 InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
369 typelib_typedescription_release( &rEntry.pTypeDescr->aBase );
370 if (rEntry.fpFreeProxy) // is proxy or used interface?
371 {
372 (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
373 }
374 else
375 {
376 (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
377 }
378 }
379
380 delete pOEntry;
381 }
382 else if (pOEntry->mixedObject)
383 {
384 OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
385 pOEntry->aInterfaces[ 0 ].fpFreeProxy == nullptr );
386
387 sal_Int32 index = pOEntry->find( pInterface, 1 );
388 OSL_ASSERT( index > 0 );
389 if (index > 0)
390 {
391 InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
392 OSL_ASSERT( entry.pInterface == pInterface );
393 if (entry.fpFreeProxy != nullptr)
394 {
395 --entry.refCount;
396 if (entry.refCount == 0)
397 {
398 uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
399 typelib_TypeDescription * pTypeDescr =
400 reinterpret_cast< typelib_TypeDescription * >(
401 entry.pTypeDescr );
402
403 pOEntry->aInterfaces.erase(
404 pOEntry->aInterfaces.begin() + index );
405 if (pOEntry->find( pInterface, index ) < 0)
406 {
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 );
412 }
413
414 guard.clear();
415
417 (*fpFreeProxy)( pEnv, pInterface );
418 }
419 }
420 }
421 }
422}
423
424static void defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
425{
426 uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
427}
428
429
430static void defenv_getObjectIdentifier(
431 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
432{
433 OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
434 if (*ppOId)
435 {
436 ::rtl_uString_release( *ppOId );
437 *ppOId = nullptr;
438 }
439
440 uno_DefaultEnvironment * that =
441 static_cast< uno_DefaultEnvironment * >( pEnv );
442 ::osl::ClearableMutexGuard guard( that->mutex );
443
444 Ptr2ObjectMap::const_iterator const iFind(
445 that->aPtr2ObjectMap.find( pInterface ) );
446 if (iFind == that->aPtr2ObjectMap.end())
447 {
448 guard.clear();
449 (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
450 }
451 else
452 {
453 rtl_uString * hstr = iFind->second->oid.pData;
454 rtl_uString_acquire( hstr );
455 *ppOId = hstr;
456 }
457}
458
459
460static void defenv_getRegisteredInterface(
461 uno_ExtEnvironment * pEnv, void ** ppInterface,
462 rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
463{
464 OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
465 if (*ppInterface)
466 {
467 (*pEnv->releaseInterface)( pEnv, *ppInterface );
468 *ppInterface = nullptr;
469 }
470
471 OUString const & rOId = OUString::unacquired( &pOId );
472 uno_DefaultEnvironment * that =
473 static_cast< uno_DefaultEnvironment * >( pEnv );
474 ::osl::MutexGuard guard( that->mutex );
475
476 OId2ObjectMap::const_iterator const iFind
477 ( that->aOId2ObjectMap.find( rOId ) );
478 if (iFind != that->aOId2ObjectMap.end())
479 {
480 InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
481 if (pIEntry)
482 {
483 (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
484 *ppInterface = pIEntry->pInterface;
485 }
486 }
487}
488
489
490static void defenv_getRegisteredInterfaces(
491 uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
492 uno_memAlloc memAlloc )
493{
494 assert(pEnv && pppInterfaces && pnLen && memAlloc && "### null ptr!");
495 uno_DefaultEnvironment * that =
496 static_cast< uno_DefaultEnvironment * >( pEnv );
497 ::osl::MutexGuard guard( that->mutex );
498
499 sal_Int32 nLen = that->aPtr2ObjectMap.size();
500 sal_Int32 nPos = 0;
501 void ** ppInterfaces = static_cast<void **>((*memAlloc)( nLen * sizeof (void *) ));
502
503 for (const auto& rEntry : that->aPtr2ObjectMap)
504 {
505 ppInterfaces[nPos] = rEntry.first;
506 (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos] );
507 nPos++;
508 }
509
510 *pppInterfaces = ppInterfaces;
511 *pnLen = nLen;
512}
513
514
515static void defenv_acquire( uno_Environment * pEnv )
516{
517 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
518 osl_atomic_increment( &that->nWeakRef );
519 osl_atomic_increment( &that->nRef );
520}
521
522
523static void defenv_release( uno_Environment * pEnv )
524{
525 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
526 if (! osl_atomic_decrement( &that->nRef ))
527 {
528 // invoke dispose callback
529 if (pEnv->environmentDisposing)
530 {
531 (*pEnv->environmentDisposing)( pEnv );
532 }
533
534 OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
535 }
536 // free memory if no weak refs left
537 if (! osl_atomic_decrement( &that->nWeakRef ))
538 {
539 delete that;
540 }
541}
542
543
544static void defenv_acquireWeak( uno_Environment * pEnv )
545{
546 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
547 osl_atomic_increment( &that->nWeakRef );
548}
549
550
551static void defenv_releaseWeak( uno_Environment * pEnv )
552{
553 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
554 if (! osl_atomic_decrement( &that->nWeakRef ))
555 {
556 delete that;
557 }
558}
559
560
561static void defenv_harden(
562 uno_Environment ** ppHardEnv, uno_Environment * pEnv )
563{
564 if (*ppHardEnv)
565 {
566 (*(*ppHardEnv)->release)( *ppHardEnv );
567 *ppHardEnv = nullptr;
568 }
569
570 EnvironmentsData & rData = theEnvironmentsData();
571
572 if (rData.isDisposing)
573 return;
574
575 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
576 {
577 ::osl::MutexGuard guard( rData.mutex );
578 if (1 == osl_atomic_increment( &that->nRef )) // is dead
579 {
580 that->nRef = 0;
581 return;
582 }
583 }
584 osl_atomic_increment( &that->nWeakRef );
585 *ppHardEnv = pEnv;
586}
587
588
589static void defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
590{
591}
592}
593
594
595uno_DefaultEnvironment::uno_DefaultEnvironment(
596 const OUString & rEnvDcp_, void * pContext_ )
597 : nRef( 0 ),
598 nWeakRef( 0 )
599{
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_;
614
615 // will be late initialized
616 that->environmentDisposing = nullptr;
617
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;
625
626}
627
628
629uno_DefaultEnvironment::~uno_DefaultEnvironment()
630{
631 ::rtl_uString_release( aBase.pTypeName );
632}
633
634
635void writeLine(
636 void * stream, const char * pLine, const char * pFilter )
637{
638 if (pFilter && *pFilter)
639 {
640 // lookup pFilter in pLine
641 while (*pLine)
642 {
643 if (*pLine == *pFilter)
644 {
645 sal_Int32 nPos = 1;
646 while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
647 {
648 ++nPos;
649 }
650 if (! pFilter[nPos])
651 {
652 if (stream)
653 {
654 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
655 }
656 else
657 {
658 SAL_WARN("cppu", pLine );
659 }
660 }
661 }
662 ++pLine;
663 }
664 }
665 else
666 {
667 if (stream)
668 {
669 fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
670 }
671 else
672 {
673 fprintf( stderr, "%s\n", pLine );
674 }
675 }
676}
677
678
679void writeLine(
680 void * stream, std::u16string_view rLine, const char * pFilter )
681{
682 OString aLine( OUStringToOString(
683 rLine, RTL_TEXTENCODING_ASCII_US ) );
684 writeLine( stream, aLine.getStr(), pFilter );
685}
686
687}
688
689extern "C" void SAL_CALL uno_dumpEnvironment(
690 void * stream, uno_Environment * pEnv, const char * pFilter )
692{
693 OSL_ENSURE( pEnv, "### null ptr!" );
694 OUStringBuffer buf;
695
696 if (! pEnv->pExtEnv)
697 {
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;
705 }
706
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);
712
713 uno_DefaultEnvironment * that =
714 reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
715 ::osl::MutexGuard guard( that->mutex );
716
717 Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
718 for (const auto& rEntry : that->aOId2ObjectMap)
719 {
720 ObjectEntry * pOEntry = rEntry.second;
721
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);
732
733 for ( std::size_t nPos = 0;
734 nPos < pOEntry->aInterfaces.size(); ++nPos )
735 {
736 const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
737
738 buf.append( OUString::Concat(" - ")
739 + OUString::unacquired(&rIEntry.pTypeDescr->aBase.pTypeName) );
740 if (rIEntry.fpFreeProxy)
741 {
742 buf.append( "; proxy free=0x"
743 + OUString::number( reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 ) );
744 }
745 else
746 {
747 buf.append( "; original" );
748 }
749 buf.append( "; ptr=0x"
750 + OUString::number(reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 ) );
751
752 if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
753 {
754 std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
755 if (erased != 1)
756 {
757 buf.append( " (ptr not found in map!)" );
758 }
759 }
760 writeLine( stream, buf, pFilter );
761 buf.setLength(0);
762 }
763 }
764 if (! ptr2obj.empty())
765 writeLine( stream, "ptr map inconsistency!!!", pFilter );
766 writeLine( stream, "#####################################"
767 "#########################################", pFilter );
768}
769
770
771extern "C" void SAL_CALL uno_dumpEnvironmentByName(
772 void * stream, rtl_uString * pEnvDcp, const char * pFilter )
774{
775 uno_Environment * pEnv = nullptr;
776 uno_getEnvironment( &pEnv, pEnvDcp, nullptr );
777 if (pEnv)
778 {
779 ::uno_dumpEnvironment( stream, pEnv, pFilter );
780 (*pEnv->release)( pEnv );
781 }
782 else
783 {
784 writeLine(
785 stream,
786 Concat2View("environment \"" + OUString::unacquired(&pEnvDcp) + "\" does not exist!"),
787 pFilter );
788 }
789}
790
791namespace
792{
793
794const OUString & unoenv_getStaticOIdPart()
795{
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)
804 {
805 aRet.append( static_cast<sal_Int64>(info.Ident), 16 );
806 }
807 else
808 {
809 aRet.append( "unknown process id" );
810 }
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 );
817
818 return aRet.makeStringAndClear();
819 }();
820 return theStaticOIdPart;
821}
822
823}
824
825extern "C"
826{
827
828
830 uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
831{
832 assert(pEnv && ppOId && pInterface && "### null ptr!");
833 if (*ppOId)
834 {
835 ::rtl_uString_release( *ppOId );
836 *ppOId = nullptr;
837 }
838
839 uno_Interface * pUnoI = static_cast<uno_Interface *>(
842 typelib_TypeClass_INTERFACE ) ));
843 if (nullptr == pUnoI)
844 return;
845
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 );
859}
860
861
863 SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
864{
865 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
866 (*pUnoI->acquire)( pUnoI );
867}
868
869
871 SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
872{
873 uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
874 (*pUnoI->release)( pUnoI );
875}
876}
877
878namespace {
879
880EnvironmentsData::~EnvironmentsData()
881{
882 ::osl::MutexGuard guard( mutex );
883 isDisposing = true;
884
885 for ( const auto& rEntry : aName2EnvMap )
886 {
887 uno_Environment * pWeak = rEntry.second;
888 uno_Environment * pHard = nullptr;
889 (*pWeak->harden)( &pHard, pWeak );
890 (*pWeak->releaseWeak)( pWeak );
891
892 if (pHard)
893 {
894 (*pHard->dispose)( pHard ); // send explicit dispose
895 (*pHard->release)( pHard );
896 }
897 }
898}
899
900
901void EnvironmentsData::getEnvironment(
902 uno_Environment ** ppEnv, std::u16string_view rEnvDcp, void * pContext )
903{
904 if (*ppEnv)
905 {
906 (*(*ppEnv)->release)( *ppEnv );
907 *ppEnv = nullptr;
908 }
909
910 OUString aKey = OUString::number( reinterpret_cast< sal_IntPtr >(pContext) ) + rEnvDcp;
911
912 // try to find registered mapping
913 OUString2EnvironmentMap::const_iterator const iFind(
914 aName2EnvMap.find( aKey ) );
915 if (iFind != aName2EnvMap.end())
916 {
917 uno_Environment * pWeak = iFind->second;
918 (*pWeak->harden)( ppEnv, pWeak );
919 }
920}
921
922
923void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
924{
925 OSL_ENSURE( ppEnv, "### null ptr!" );
926 uno_Environment * pEnv = *ppEnv;
927
928 OUString aKey =
929 OUString::number( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) +
930 OUString::unacquired(&pEnv->pTypeName);
931
932 // try to find registered environment
933 OUString2EnvironmentMap::const_iterator const iFind(
934 aName2EnvMap.find( aKey ) );
935 if (iFind == aName2EnvMap.end())
936 {
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" );
941 }
942 else
943 {
944 uno_Environment * pHard = nullptr;
945 uno_Environment * pWeak = iFind->second;
946 (*pWeak->harden)( &pHard, pWeak );
947 if (pHard)
948 {
949 (*pEnv->release)( pEnv );
950 *ppEnv = pHard;
951 }
952 else // registered one is dead
953 {
954 (*pWeak->releaseWeak)( pWeak );
955 (*pEnv->acquireWeak)( pEnv );
956 aName2EnvMap[ aKey ] = pEnv;
957 }
958 }
959}
960
961
962void EnvironmentsData::getRegisteredEnvironments(
963 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
964 std::u16string_view rEnvDcp )
965{
966 assert(pppEnvs && pnLen && memAlloc && "### null ptr!");
967
968 // max size
969 std::vector<uno_Environment*> aFounds(aName2EnvMap.size());
970 sal_Int32 nSize = 0;
971
972 // find matching environment
973 for ( const auto& rEntry : aName2EnvMap )
974 {
975 uno_Environment * pWeak = rEntry.second;
976 if (rEnvDcp.empty() ||
977 rEnvDcp == OUString::unacquired(&pWeak->pTypeName) )
978 {
979 aFounds[nSize] = nullptr;
980 (*pWeak->harden)( &aFounds[nSize], pWeak );
981 if (aFounds[nSize])
982 ++nSize;
983 }
984 }
985
986 *pnLen = nSize;
987 if (nSize)
988 {
989 *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
990 sizeof (uno_Environment *) * nSize ));
991 OSL_ASSERT( *pppEnvs );
992 while (nSize--)
993 {
994 (*pppEnvs)[nSize] = aFounds[nSize];
995 }
996 }
997 else
998 {
999 *pppEnvs = nullptr;
1000 }
1001}
1002
1003bool loadEnv(OUString const & cLibStem,
1004 uno_Environment * pEnv)
1005{
1006#ifdef DISABLE_DYNLOADING
1007 uno_initEnvironmentFunc fpInit;
1008
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
1016 {
1017 SAL_INFO("cppu", ": Unhandled env: " << cLibStem);
1018 return false;
1019 }
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;
1028 }
1029 catch(...) {
1030 // Catch everything and convert to return false
1031 return false;
1032 }
1033
1034
1035 uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(UNO_INIT_ENVIRONMENT));
1036
1037 if (!fpInit)
1038 return false;
1039
1040 aMod.release();
1041#endif
1042
1043 (*fpInit)( pEnv ); // init of environment
1044 return true;
1045}
1046
1047}
1048
1049extern "C"
1050{
1051
1052
1054 const OUString & rEnvDcp, void * pContext )
1055{
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 );
1059
1060 OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1061
1062 // create default environment
1063 if ( envTypeName == UNO_LB_UNO )
1064 {
1065 uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
1066 that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1067 that->acquireInterface = unoenv_acquireInterface;
1068 that->releaseInterface = unoenv_releaseInterface;
1069
1070 OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1071 if (!envPurpose.isEmpty())
1072 {
1073 OUString libStem(
1074 OUString::Concat(envPurpose.subView(envPurpose.lastIndexOf(':') + 1)) + "_uno_uno");
1075 if(!loadEnv(libStem, pEnv))
1076 {
1077 pEnv->release(pEnv);
1078 return nullptr;
1079 }
1080 }
1081 }
1082 else
1083 {
1084 // late init with some code from matching uno language binding
1085 OUString aStr( envTypeName + "_uno" );
1086
1087 if (!loadEnv(aStr, pEnv))
1088 {
1089 pEnv->release(pEnv);
1090 return nullptr;
1091 }
1092 }
1093
1094 return pEnv;
1095}
1096
1097
1099 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1101{
1102 assert(ppEnv && "### null ptr!");
1103 if (*ppEnv)
1104 (*(*ppEnv)->release)( *ppEnv );
1105
1106 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1107 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1108}
1109
1111 uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1113{
1114 assert(ppEnv && "### null ptr!");
1115 OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1116
1117 EnvironmentsData & rData = theEnvironmentsData();
1118
1119 ::osl::MutexGuard guard( rData.mutex );
1120 rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1121 if (! *ppEnv)
1122 {
1123 *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1124 if (*ppEnv)
1125 {
1126 // register new environment:
1127 rData.registerEnvironment( ppEnv );
1128 }
1129 }
1130}
1131
1133 uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1134 rtl_uString * pEnvDcp )
1136{
1137 EnvironmentsData & rData = theEnvironmentsData();
1138
1139 ::osl::MutexGuard guard( rData.mutex );
1140 rData.getRegisteredEnvironments(
1141 pppEnvs, pnLen, memAlloc,
1142 (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1143}
1144
1145} // extern "C"
1146
1147/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SAL_CALL uno_Environment_invoke(uno_Environment *pEnv, uno_EnvCallee *pCallee,...) SAL_THROW_EXTERN_C()
Definition: EnvStack.cxx:315
Reference< XOutputStream > stream
struct _uno_Environment uno_Environment
void SAL_CALL uno_getEnvironment(uno_Environment **ppEnv, rtl_uString *pEnvDcp, void *pContext) SAL_THROW_EXTERN_C()
Definition: lbenv.cxx:1110
static void unoenv_releaseInterface(SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void *pUnoI_)
Definition: lbenv.cxx:870
static void unoenv_computeObjectIdentifier(uno_ExtEnvironment *pEnv, rtl_uString **ppOId, void *pInterface)
Definition: lbenv.cxx:829
void SAL_CALL uno_createEnvironment(uno_Environment **ppEnv, rtl_uString *pEnvDcp, void *pContext) SAL_THROW_EXTERN_C()
Definition: lbenv.cxx:1098
static void unoenv_acquireInterface(SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void *pUnoI_)
Definition: lbenv.cxx:862
static uno_Environment * initDefaultEnvironment(const OUString &rEnvDcp, void *pContext)
Definition: lbenv.cxx:1053
void SAL_CALL uno_dumpEnvironmentByName(void *stream, rtl_uString *pEnvDcp, const char *pFilter) SAL_THROW_EXTERN_C()
Definition: lbenv.cxx:771
void SAL_CALL uno_getRegisteredEnvironments(uno_Environment ***pppEnvs, sal_Int32 *pnLen, uno_memAlloc memAlloc, rtl_uString *pEnvDcp) SAL_THROW_EXTERN_C()
Definition: lbenv.cxx:1132
void SAL_CALL uno_dumpEnvironment(void *stream, uno_Environment *pEnv, const char *pFilter) SAL_THROW_EXTERN_C()
Definition: lbenv.cxx:689
sal_Int32 nRef
Definition: lbmap.cxx:122
sal_uInt16 nPos
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
aStr
struct _typelib_TypeDescription typelib_TypeDescription
size
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, std::u16string_view _rVal, const ::comphelper::UStringMixEqual &_rCase)
rtl::OUString getPurpose(rtl::OUString const &rEnvDcp)
Get the purpose part of an environment descriptor.
Definition: EnvDcp.hxx:57
rtl::OUString getTypeName(rtl::OUString const &rEnvDcp)
Get the OBI type part of an environment descriptor.
Definition: EnvDcp.hxx:41
bool loadModule(osl::Module &rModule, OUString const &name)
Load a module.
Definition: loadmodule.cxx:38
void * binuno_queryInterface(void *pUnoI, typelib_TypeDescriptionReference *pDestType)
Definition: data.cxx:40
css::uno::Environment getEnvironment(OUString const &name, std::u16string_view implementation)
int i
index
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
bool td_equals(typelib_TypeDescription *pTD, typelib_TypeDescriptionReference *pType)
typelib_TypeDescriptionReference **SAL_CALL typelib_static_type_getByTypeClass(typelib_TypeClass eTypeClass) SAL_THROW_EXTERN_C()
std::mutex mutex
void SAL_CALL typelib_typedescription_release(typelib_TypeDescription *pTD) SAL_THROW_EXTERN_C()
Definition: typelib.cxx:1325
void SAL_CALL typelib_typedescription_acquire(typelib_TypeDescription *pTypeDescription) SAL_THROW_EXTERN_C()
Definition: typelib.cxx:1197
unsigned char sal_uInt8
#define SAL_THROW_EXTERN_C()
size_t pos