Line data Source code
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 : #include <config_features.h>
21 :
22 : #include "cppu/EnvDcp.hxx"
23 :
24 : #include "sal/alloca.h"
25 : #include "sal/log.hxx"
26 : #include "osl/diagnose.h"
27 : #include "osl/interlck.h"
28 : #include "osl/mutex.hxx"
29 : #include "osl/module.h"
30 : #include "osl/process.h"
31 : #include "rtl/process.h"
32 : #include "rtl/string.hxx"
33 : #include "rtl/ustring.hxx"
34 : #include "rtl/ustrbuf.hxx"
35 : #include "rtl/instance.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 "destr.hxx"
42 : #include "loadmodule.hxx"
43 :
44 : #include <unordered_map>
45 : #include <vector>
46 : #include <stdio.h>
47 :
48 :
49 : using ::rtl::OUString;
50 : using ::rtl::OUStringHash;
51 :
52 : namespace
53 : {
54 :
55 :
56 7897404 : inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
57 : typelib_InterfaceTypeDescription * pTD2 )
58 : {
59 15794808 : return (pTD1 == pTD2 ||
60 7983354 : (pTD1->aBase.pTypeName->length == pTD2->aBase.pTypeName->length &&
61 : ::rtl_ustr_compare(
62 : pTD1->aBase.pTypeName->buffer,
63 8388258 : pTD2->aBase.pTypeName->buffer ) == 0));
64 : }
65 :
66 : struct ObjectEntry;
67 : struct uno_DefaultEnvironment;
68 :
69 :
70 : struct InterfaceEntry
71 : {
72 : sal_Int32 refCount;
73 : void * pInterface;
74 : uno_freeProxyFunc fpFreeProxy;
75 : typelib_InterfaceTypeDescription * pTypeDescr;
76 : };
77 :
78 260167 : struct ObjectEntry
79 : {
80 : OUString oid;
81 : sal_Int32 nRef;
82 : ::std::vector< InterfaceEntry > aInterfaces;
83 : bool mixedObject;
84 :
85 : explicit inline ObjectEntry( const OUString & rOId_ );
86 :
87 : inline void append(
88 : uno_DefaultEnvironment * pEnv,
89 : void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
90 : uno_freeProxyFunc fpFreeProxy );
91 : inline InterfaceEntry * find(
92 : typelib_InterfaceTypeDescription * pTypeDescr );
93 : inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
94 : };
95 :
96 :
97 : struct FctPtrHash :
98 : public ::std::unary_function< const void *, ::std::size_t >
99 : {
100 2800974 : ::std::size_t operator () ( const void * pKey ) const
101 2800974 : { return reinterpret_cast< ::std::size_t>( pKey ); }
102 : };
103 :
104 :
105 : // mapping from environment name to environment
106 : typedef std::unordered_map<
107 : OUString, uno_Environment *, OUStringHash > OUString2EnvironmentMap;
108 :
109 : // mapping from ptr to object entry
110 : typedef std::unordered_map<
111 : void *, ObjectEntry *, FctPtrHash,
112 : ::std::equal_to< void * > > Ptr2ObjectMap;
113 : // mapping from oid to object entry
114 : typedef std::unordered_map<
115 : OUString, ObjectEntry *, OUStringHash > OId2ObjectMap;
116 :
117 : struct EnvironmentsData
118 : {
119 : ::osl::Mutex mutex;
120 : OUString2EnvironmentMap aName2EnvMap;
121 :
122 506 : EnvironmentsData() : isDisposing(false) {}
123 : ~EnvironmentsData();
124 :
125 : inline void getEnvironment(
126 : uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
127 : inline void registerEnvironment( uno_Environment ** ppEnv );
128 : inline void getRegisteredEnvironments(
129 : uno_Environment *** pppEnvs, sal_Int32 * pnLen,
130 : uno_memAlloc memAlloc, const OUString & rEnvDcp );
131 :
132 : bool isDisposing;
133 : };
134 :
135 : struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
136 :
137 : struct uno_DefaultEnvironment : public uno_ExtEnvironment
138 : {
139 : sal_Int32 nRef;
140 : sal_Int32 nWeakRef;
141 :
142 : ::osl::Mutex mutex;
143 : Ptr2ObjectMap aPtr2ObjectMap;
144 : OId2ObjectMap aOId2ObjectMap;
145 :
146 : uno_DefaultEnvironment(
147 : const OUString & rEnvDcp_, void * pContext_ );
148 : ~uno_DefaultEnvironment();
149 : };
150 :
151 :
152 261181 : inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
153 : : oid( rOId_ ),
154 : nRef( 0 ),
155 261181 : mixedObject( false )
156 : {
157 261181 : aInterfaces.reserve( 2 );
158 261181 : }
159 :
160 :
161 638841 : inline void ObjectEntry::append(
162 : uno_DefaultEnvironment * pEnv,
163 : void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
164 : uno_freeProxyFunc fpFreeProxy )
165 : {
166 : InterfaceEntry aNewEntry;
167 638841 : if (! fpFreeProxy)
168 215621 : (*pEnv->acquireInterface)( pEnv, pInterface );
169 638841 : aNewEntry.refCount = 1;
170 638841 : aNewEntry.pInterface = pInterface;
171 638841 : aNewEntry.fpFreeProxy = fpFreeProxy;
172 638841 : typelib_typedescription_acquire( &pTypeDescr->aBase );
173 638841 : aNewEntry.pTypeDescr = pTypeDescr;
174 :
175 : ::std::pair< Ptr2ObjectMap::iterator, bool > i(
176 : pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type(
177 638841 : pInterface, this ) ) );
178 : SAL_WARN_IF(
179 : !i.second && (find(pInterface, 0) == -1 || i.first->second != this),
180 : "cppu",
181 : "map already contains " << i.first->second << " != " << this << " for "
182 : << pInterface);
183 638841 : aInterfaces.push_back( aNewEntry );
184 638841 : }
185 :
186 :
187 1294245 : inline InterfaceEntry * ObjectEntry::find(
188 : typelib_InterfaceTypeDescription * pTypeDescr_ )
189 : {
190 : OSL_ASSERT( ! aInterfaces.empty() );
191 1294245 : if (aInterfaces.empty())
192 0 : return 0;
193 :
194 : // shortcut common case:
195 : OUString const & type_name =
196 1294245 : OUString::unacquired( &pTypeDescr_->aBase.pTypeName );
197 1294245 : if ( type_name == "com.sun.star.uno.XInterface" )
198 : {
199 45007 : return &aInterfaces[ 0 ];
200 : }
201 :
202 1249238 : ::std::size_t nSize = aInterfaces.size();
203 4990735 : for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
204 : {
205 : typelib_InterfaceTypeDescription * pITD =
206 4146401 : aInterfaces[ nPos ].pTypeDescr;
207 15785302 : while (pITD)
208 : {
209 7897404 : if (td_equals( pITD, pTypeDescr_ ))
210 404904 : return &aInterfaces[ nPos ];
211 7492500 : pITD = pITD->pBaseTypeDescription;
212 : }
213 : }
214 844334 : return 0;
215 : }
216 :
217 :
218 13921 : inline sal_Int32 ObjectEntry::find(
219 : void * iface_ptr, ::std::size_t pos )
220 : {
221 13921 : ::std::size_t size = aInterfaces.size();
222 23496 : for ( ; pos < size; ++pos )
223 : {
224 17009 : if (aInterfaces[ pos ].pInterface == iface_ptr)
225 7434 : return pos;
226 : }
227 6487 : return -1;
228 : }
229 :
230 : extern "C"
231 : {
232 :
233 :
234 469264 : static void SAL_CALL defenv_registerInterface(
235 : uno_ExtEnvironment * pEnv, void ** ppInterface,
236 : rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
237 : {
238 : OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
239 469264 : OUString const & rOId = OUString::unacquired( &pOId );
240 :
241 : uno_DefaultEnvironment * that =
242 469264 : static_cast< uno_DefaultEnvironment * >( pEnv );
243 469264 : ::osl::ClearableMutexGuard guard( that->mutex );
244 :
245 : // try to insert dummy 0:
246 : std::pair<OId2ObjectMap::iterator, bool> const insertion(
247 469264 : that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, nullptr ) ) );
248 469264 : if (insertion.second)
249 : {
250 114628 : ObjectEntry * pOEntry = new ObjectEntry( rOId );
251 114628 : insertion.first->second = pOEntry;
252 114628 : ++pOEntry->nRef; // another register call on object
253 114628 : pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
254 : }
255 : else // object entry exists
256 : {
257 354636 : ObjectEntry * pOEntry = insertion.first->second;
258 354636 : ++pOEntry->nRef; // another register call on object
259 354636 : InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
260 :
261 354636 : if (pIEntry) // type entry exists
262 : {
263 253643 : ++pIEntry->refCount;
264 253643 : if (pIEntry->pInterface != *ppInterface)
265 : {
266 0 : void * pInterface = pIEntry->pInterface;
267 0 : (*pEnv->acquireInterface)( pEnv, pInterface );
268 0 : guard.clear();
269 0 : (*pEnv->releaseInterface)( pEnv, *ppInterface );
270 0 : *ppInterface = pInterface;
271 : }
272 : }
273 : else
274 : {
275 100993 : pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
276 : }
277 469264 : }
278 469264 : }
279 :
280 :
281 470867 : static void SAL_CALL defenv_registerProxyInterface(
282 : uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
283 : rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
284 : {
285 : OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
286 : "### null ptr!" );
287 470867 : OUString const & rOId = OUString::unacquired( &pOId );
288 :
289 : uno_DefaultEnvironment * that =
290 470867 : static_cast< uno_DefaultEnvironment * >( pEnv );
291 470867 : ::osl::ClearableMutexGuard guard( that->mutex );
292 :
293 : // try to insert dummy 0:
294 : std::pair<OId2ObjectMap::iterator, bool> const insertion(
295 470867 : that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, nullptr ) ) );
296 470867 : if (insertion.second)
297 : {
298 146553 : ObjectEntry * pOEntry = new ObjectEntry( rOId );
299 146553 : insertion.first->second = pOEntry;
300 146553 : ++pOEntry->nRef; // another register call on object
301 146553 : pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
302 : }
303 : else // object entry exists
304 : {
305 324314 : ObjectEntry * pOEntry = insertion.first->second;
306 :
307 : // first registration was an original, then registerProxyInterface():
308 : pOEntry->mixedObject |=
309 648628 : (!pOEntry->aInterfaces.empty() &&
310 648628 : pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
311 :
312 324314 : ++pOEntry->nRef; // another register call on object
313 324314 : InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
314 :
315 324314 : if (pIEntry) // type entry exists
316 : {
317 47647 : if (pIEntry->pInterface == *ppInterface)
318 : {
319 47100 : ++pIEntry->refCount;
320 : }
321 : else
322 : {
323 547 : void * pInterface = pIEntry->pInterface;
324 547 : (*pEnv->acquireInterface)( pEnv, pInterface );
325 547 : --pOEntry->nRef; // manual revoke of proxy to be freed
326 547 : guard.clear();
327 547 : (*freeProxy)( pEnv, *ppInterface );
328 547 : *ppInterface = pInterface;
329 : }
330 : }
331 : else
332 : {
333 276667 : pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
334 : }
335 470867 : }
336 470867 : }
337 :
338 :
339 937518 : static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
340 : {
341 937518 : uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
342 937518 : void * pInterface = va_arg(*pParam, void *);
343 :
344 : OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
345 : uno_DefaultEnvironment * that =
346 937518 : static_cast< uno_DefaultEnvironment * >( pEnv );
347 937518 : ::osl::ClearableMutexGuard guard( that->mutex );
348 :
349 : Ptr2ObjectMap::const_iterator const iFind(
350 937518 : that->aPtr2ObjectMap.find( pInterface ) );
351 : OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
352 937518 : ObjectEntry * pOEntry = iFind->second;
353 937518 : if (! --pOEntry->nRef)
354 : {
355 : // cleanup maps
356 260167 : that->aOId2ObjectMap.erase( pOEntry->oid );
357 : sal_Int32 nPos;
358 1150682 : for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
359 : {
360 630348 : that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
361 : }
362 :
363 : // the last proxy interface of the environment might kill this
364 : // environment, because of releasing its language binding!!!
365 260167 : guard.clear();
366 :
367 : // release interfaces
368 1150682 : for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
369 : {
370 630348 : InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
371 630347 : typelib_typedescription_release( &rEntry.pTypeDescr->aBase );
372 630348 : if (rEntry.fpFreeProxy) // is proxy or used interface?
373 : {
374 415404 : (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
375 : }
376 : else
377 : {
378 214944 : (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
379 : }
380 : }
381 :
382 260167 : delete pOEntry;
383 : }
384 677351 : else if (pOEntry->mixedObject)
385 : {
386 : OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
387 : pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
388 :
389 7434 : sal_Int32 index = pOEntry->find( pInterface, 1 );
390 : OSL_ASSERT( index > 0 );
391 7434 : if (index > 0)
392 : {
393 7434 : InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
394 : OSL_ASSERT( entry.pInterface == pInterface );
395 7434 : if (entry.fpFreeProxy != 0)
396 : {
397 6487 : --entry.refCount;
398 6487 : if (entry.refCount == 0)
399 : {
400 6487 : uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
401 : typelib_TypeDescription * pTypeDescr =
402 : reinterpret_cast< typelib_TypeDescription * >(
403 6487 : entry.pTypeDescr );
404 :
405 : pOEntry->aInterfaces.erase(
406 6487 : pOEntry->aInterfaces.begin() + index );
407 6487 : if (pOEntry->find( pInterface, index ) < 0)
408 : {
409 : // proxy ptr not registered for another interface:
410 : // remove from ptr map
411 : #if OSL_DEBUG_LEVEL > 0
412 : ::std::size_t erased =
413 : #endif
414 6487 : that->aPtr2ObjectMap.erase( pInterface );
415 : OSL_ASSERT( erased == 1 );
416 : }
417 :
418 6487 : guard.clear();
419 :
420 6487 : typelib_typedescription_release( pTypeDescr );
421 6487 : (*fpFreeProxy)( pEnv, pInterface );
422 : }
423 : }
424 : }
425 937518 : }
426 937518 : }
427 :
428 937518 : static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
429 : {
430 937518 : uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
431 937518 : }
432 :
433 :
434 587789 : static void SAL_CALL defenv_getObjectIdentifier(
435 : uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
436 : {
437 : OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
438 587789 : if (*ppOId)
439 : {
440 94394 : ::rtl_uString_release( *ppOId );
441 94394 : *ppOId = 0;
442 : }
443 :
444 : uno_DefaultEnvironment * that =
445 587789 : static_cast< uno_DefaultEnvironment * >( pEnv );
446 587789 : ::osl::ClearableMutexGuard guard( that->mutex );
447 :
448 : Ptr2ObjectMap::const_iterator const iFind(
449 587789 : that->aPtr2ObjectMap.find( pInterface ) );
450 587789 : if (iFind == that->aPtr2ObjectMap.end())
451 : {
452 216790 : guard.clear();
453 216790 : (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
454 : }
455 : else
456 : {
457 370999 : rtl_uString * hstr = iFind->second->oid.pData;
458 370999 : rtl_uString_acquire( hstr );
459 370999 : *ppOId = hstr;
460 587789 : }
461 587789 : }
462 :
463 :
464 764594 : static void SAL_CALL defenv_getRegisteredInterface(
465 : uno_ExtEnvironment * pEnv, void ** ppInterface,
466 : rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
467 : {
468 : OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
469 764594 : if (*ppInterface)
470 : {
471 0 : (*pEnv->releaseInterface)( pEnv, *ppInterface );
472 0 : *ppInterface = 0;
473 : }
474 :
475 764594 : OUString const & rOId = OUString::unacquired( &pOId );
476 : uno_DefaultEnvironment * that =
477 764594 : static_cast< uno_DefaultEnvironment * >( pEnv );
478 764594 : ::osl::MutexGuard guard( that->mutex );
479 :
480 : OId2ObjectMap::const_iterator const iFind
481 764594 : ( that->aOId2ObjectMap.find( rOId ) );
482 764594 : if (iFind != that->aOId2ObjectMap.end())
483 : {
484 615295 : InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
485 615295 : if (pIEntry)
486 : {
487 148621 : (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
488 148621 : *ppInterface = pIEntry->pInterface;
489 : }
490 764594 : }
491 764594 : }
492 :
493 :
494 0 : static void SAL_CALL defenv_getRegisteredInterfaces(
495 : uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
496 : uno_memAlloc memAlloc )
497 : {
498 : assert(pEnv && pppInterfaces && pnLen && memAlloc && "### null ptr!");
499 : uno_DefaultEnvironment * that =
500 0 : static_cast< uno_DefaultEnvironment * >( pEnv );
501 0 : ::osl::MutexGuard guard( that->mutex );
502 :
503 0 : sal_Int32 nLen = that->aPtr2ObjectMap.size();
504 0 : sal_Int32 nPos = 0;
505 0 : void ** ppInterfaces = static_cast<void **>((*memAlloc)( nLen * sizeof (void *) ));
506 :
507 0 : Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
508 0 : Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
509 0 : while (iPos != iEnd)
510 : {
511 0 : (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
512 0 : ++iPos;
513 : }
514 :
515 0 : *pppInterfaces = ppInterfaces;
516 0 : *pnLen = nLen;
517 0 : }
518 :
519 :
520 573910 : static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
521 : {
522 573910 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
523 573910 : osl_atomic_increment( &that->nWeakRef );
524 573910 : osl_atomic_increment( &that->nRef );
525 573910 : }
526 :
527 :
528 1374943 : static void SAL_CALL defenv_release( uno_Environment * pEnv )
529 : {
530 1374943 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
531 1374943 : if (! osl_atomic_decrement( &that->nRef ))
532 : {
533 : // invoke dispose callback
534 12765 : if (pEnv->environmentDisposing)
535 : {
536 2043 : (*pEnv->environmentDisposing)( pEnv );
537 : }
538 :
539 : OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
540 : }
541 : // free memory if no weak refs left
542 1374943 : if (! osl_atomic_decrement( &that->nWeakRef ))
543 : {
544 2 : delete that;
545 : }
546 1374943 : }
547 :
548 :
549 13061 : static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
550 : {
551 13061 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
552 13061 : osl_atomic_increment( &that->nWeakRef );
553 13061 : }
554 :
555 :
556 13061 : static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
557 : {
558 13061 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
559 13061 : if (! osl_atomic_decrement( &that->nWeakRef ))
560 : {
561 12763 : delete that;
562 : }
563 13061 : }
564 :
565 :
566 826956 : static void SAL_CALL defenv_harden(
567 : uno_Environment ** ppHardEnv, uno_Environment * pEnv )
568 : {
569 826956 : if (*ppHardEnv)
570 : {
571 0 : (*(*ppHardEnv)->release)( *ppHardEnv );
572 0 : *ppHardEnv = 0;
573 : }
574 :
575 826956 : EnvironmentsData & rData = theEnvironmentsData::get();
576 :
577 826956 : if (rData.isDisposing)
578 729 : return;
579 :
580 826227 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
581 : {
582 826227 : ::osl::MutexGuard guard( rData.mutex );
583 826227 : if (1 == osl_atomic_increment( &that->nRef )) // is dead
584 : {
585 24664 : that->nRef = 0;
586 24664 : return;
587 801563 : }
588 : }
589 801563 : osl_atomic_increment( &that->nWeakRef );
590 801563 : *ppHardEnv = pEnv;
591 : }
592 :
593 :
594 0 : static void SAL_CALL defenv_dispose( SAL_UNUSED_PARAMETER uno_Environment * )
595 : {
596 0 : }
597 : }
598 :
599 :
600 13063 : uno_DefaultEnvironment::uno_DefaultEnvironment(
601 : const OUString & rEnvDcp_, void * pContext_ )
602 : : nRef( 0 ),
603 13063 : nWeakRef( 0 )
604 : {
605 13063 : uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
606 13063 : that->pReserved = 0;
607 : // functions
608 13063 : that->acquire = defenv_acquire;
609 13063 : that->release = defenv_release;
610 13063 : that->acquireWeak = defenv_acquireWeak;
611 13063 : that->releaseWeak = defenv_releaseWeak;
612 13063 : that->harden = defenv_harden;
613 13063 : that->dispose = defenv_dispose;
614 13063 : that->pExtEnv = this;
615 : // identifier
616 13063 : ::rtl_uString_acquire( rEnvDcp_.pData );
617 13063 : that->pTypeName = rEnvDcp_.pData;
618 13063 : that->pContext = pContext_;
619 :
620 : // will be late initialized
621 13063 : that->environmentDisposing = 0;
622 :
623 13063 : uno_ExtEnvironment::registerInterface = defenv_registerInterface;
624 13063 : uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
625 13063 : uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
626 13063 : uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
627 13063 : uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
628 : uno_ExtEnvironment::getRegisteredInterfaces =
629 13063 : defenv_getRegisteredInterfaces;
630 :
631 13063 : }
632 :
633 :
634 25530 : uno_DefaultEnvironment::~uno_DefaultEnvironment()
635 : {
636 12765 : ::rtl_uString_release( aBase.pTypeName );
637 12765 : }
638 :
639 :
640 0 : static void writeLine(
641 : void * stream, const sal_Char * pLine, const sal_Char * pFilter )
642 : {
643 0 : if (pFilter && *pFilter)
644 : {
645 : // lookup pFilter in pLine
646 0 : while (*pLine)
647 : {
648 0 : if (*pLine == *pFilter)
649 : {
650 0 : sal_Int32 nPos = 1;
651 0 : while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
652 : {
653 0 : ++nPos;
654 : }
655 0 : if (! pFilter[nPos])
656 : {
657 0 : if (stream)
658 : {
659 0 : fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
660 : }
661 : else
662 : {
663 : OSL_TRACE( "%s", pLine );
664 : }
665 : }
666 : }
667 0 : ++pLine;
668 0 : }
669 : }
670 : else
671 : {
672 0 : if (stream)
673 : {
674 0 : fprintf( static_cast<FILE *>(stream), "%s\n", pLine );
675 : }
676 : else
677 : {
678 0 : fprintf( stderr, "%s\n", pLine );
679 : }
680 : }
681 0 : }
682 :
683 :
684 0 : static void writeLine(
685 : void * stream, const OUString & rLine, const sal_Char * pFilter )
686 : {
687 : ::rtl::OString aLine( ::rtl::OUStringToOString(
688 0 : rLine, RTL_TEXTENCODING_ASCII_US ) );
689 0 : writeLine( stream, aLine.getStr(), pFilter );
690 0 : }
691 :
692 : }
693 :
694 0 : extern "C" void SAL_CALL uno_dumpEnvironment(
695 : void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
696 : SAL_THROW_EXTERN_C()
697 : {
698 : OSL_ENSURE( pEnv, "### null ptr!" );
699 0 : ::rtl::OUStringBuffer buf;
700 :
701 0 : if (! pEnv->pExtEnv)
702 : {
703 : writeLine( stream, "###################################"
704 0 : "###########################################", pFilter );
705 0 : buf.append( "environment: " );
706 0 : buf.append( pEnv->pTypeName );
707 0 : writeLine( stream, buf.makeStringAndClear(), pFilter );
708 0 : writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
709 0 : return;
710 : }
711 :
712 : writeLine( stream, "########################################"
713 0 : "######################################", pFilter );
714 0 : buf.append( "environment dump: " );
715 0 : buf.append( pEnv->pTypeName );
716 0 : writeLine( stream, buf.makeStringAndClear(), pFilter );
717 :
718 : uno_DefaultEnvironment * that =
719 0 : reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
720 0 : ::osl::MutexGuard guard( that->mutex );
721 :
722 0 : Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
723 0 : OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
724 0 : while (iPos != that->aOId2ObjectMap.end())
725 : {
726 0 : ObjectEntry * pOEntry = iPos->second;
727 :
728 0 : buf.append( "+ " );
729 0 : if (pOEntry->mixedObject)
730 0 : buf.append( "mixed " );
731 0 : buf.append( "object entry: nRef=" );
732 0 : buf.append( pOEntry->nRef, 10 );
733 0 : buf.append( "; oid=\"" );
734 0 : buf.append( pOEntry->oid );
735 0 : buf.append( '\"' );
736 0 : writeLine( stream, buf.makeStringAndClear(), pFilter );
737 :
738 0 : for ( ::std::size_t nPos = 0;
739 0 : nPos < pOEntry->aInterfaces.size(); ++nPos )
740 : {
741 0 : const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
742 :
743 0 : buf.append( " - " );
744 0 : buf.append( rIEntry.pTypeDescr->aBase.pTypeName );
745 0 : if (rIEntry.fpFreeProxy)
746 : {
747 0 : buf.append( "; proxy free=0x" );
748 : buf.append(
749 0 : reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
750 : }
751 : else
752 : {
753 0 : buf.append( "; original" );
754 : }
755 0 : buf.append( "; ptr=0x" );
756 : buf.append(
757 0 : reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
758 :
759 0 : if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
760 : {
761 0 : ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
762 0 : if (erased != 1)
763 : {
764 0 : buf.append( " (ptr not found in map!)" );
765 : }
766 : }
767 0 : writeLine( stream, buf.makeStringAndClear(), pFilter );
768 : }
769 0 : ++iPos;
770 : }
771 0 : if (! ptr2obj.empty())
772 0 : writeLine( stream, "ptr map inconsistency!!!", pFilter );
773 : writeLine( stream, "#####################################"
774 0 : "#########################################", pFilter );
775 : }
776 :
777 :
778 0 : extern "C" void SAL_CALL uno_dumpEnvironmentByName(
779 : void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
780 : SAL_THROW_EXTERN_C()
781 : {
782 0 : uno_Environment * pEnv = 0;
783 0 : uno_getEnvironment( &pEnv, pEnvDcp, 0 );
784 0 : if (pEnv)
785 : {
786 0 : ::uno_dumpEnvironment( stream, pEnv, pFilter );
787 0 : (*pEnv->release)( pEnv );
788 : }
789 : else
790 : {
791 0 : ::rtl::OUStringBuffer buf( 32 );
792 0 : buf.append( "environment \"" );
793 0 : buf.append( pEnvDcp );
794 0 : buf.append( "\" does not exist!" );
795 0 : writeLine( stream, buf.makeStringAndClear(), pFilter );
796 : }
797 0 : }
798 :
799 : namespace
800 : {
801 195 : class makeOIdPart
802 : {
803 : private:
804 : OUString m_sOidPart;
805 : public:
806 195 : makeOIdPart()
807 195 : {
808 195 : ::rtl::OUStringBuffer aRet( 64 );
809 195 : aRet.append( "];" );
810 : // pid
811 : oslProcessInfo info;
812 195 : info.Size = sizeof(oslProcessInfo);
813 195 : if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
814 : osl_Process_E_None)
815 : {
816 195 : aRet.append( (sal_Int64)info.Ident, 16 );
817 : }
818 : else
819 : {
820 0 : aRet.append( "unknown process id" );
821 : }
822 : // good guid
823 : sal_uInt8 ar[16];
824 195 : ::rtl_getGlobalProcessId( ar );
825 195 : aRet.append( ';' );
826 3315 : for ( sal_Int32 i = 0; i < 16; ++i )
827 3120 : aRet.append( (sal_Int32)ar[i], 16 );
828 :
829 195 : m_sOidPart = aRet.makeStringAndClear();
830 195 : }
831 22923 : const OUString& getOIdPart() const { return m_sOidPart; }
832 : };
833 :
834 : class theStaticOIdPart : public rtl::Static<makeOIdPart, theStaticOIdPart> {};
835 :
836 22923 : inline static const OUString & unoenv_getStaticOIdPart()
837 : {
838 22923 : return theStaticOIdPart::get().getOIdPart();
839 : }
840 :
841 : }
842 :
843 : extern "C"
844 : {
845 :
846 :
847 22923 : static void SAL_CALL unoenv_computeObjectIdentifier(
848 : uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
849 : {
850 : assert(pEnv && ppOId && pInterface && "### null ptr!");
851 22923 : if (*ppOId)
852 : {
853 0 : ::rtl_uString_release( *ppOId );
854 0 : *ppOId = 0;
855 : }
856 :
857 : uno_Interface * pUnoI = static_cast<uno_Interface *>(
858 : ::cppu::binuno_queryInterface(
859 : pInterface, *typelib_static_type_getByTypeClass(
860 22923 : typelib_TypeClass_INTERFACE ) ));
861 22923 : if (0 != pUnoI)
862 : {
863 22923 : (*pUnoI->release)( pUnoI );
864 : // interface
865 22923 : ::rtl::OUStringBuffer oid( 64 );
866 22923 : oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
867 22923 : oid.append( ';' );
868 : // environment[context]
869 22923 : oid.append( pEnv->aBase.pTypeName );
870 22923 : oid.append( '[' );
871 : oid.append( reinterpret_cast< sal_Int64 >(
872 : reinterpret_cast<
873 22923 : uno_Environment * >(pEnv)->pContext ), 16 );
874 : // process;good guid
875 22923 : oid.append( unoenv_getStaticOIdPart() );
876 45846 : OUString aStr( oid.makeStringAndClear() );
877 45846 : ::rtl_uString_acquire( *ppOId = aStr.pData );
878 : }
879 22923 : }
880 :
881 :
882 69542 : static void SAL_CALL unoenv_acquireInterface(
883 : SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
884 : {
885 69542 : uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
886 69542 : (*pUnoI->acquire)( pUnoI );
887 69542 : }
888 :
889 :
890 23329 : static void SAL_CALL unoenv_releaseInterface(
891 : SAL_UNUSED_PARAMETER uno_ExtEnvironment *, void * pUnoI_ )
892 : {
893 23329 : uno_Interface * pUnoI = static_cast< uno_Interface * >(pUnoI_);
894 23329 : (*pUnoI->release)( pUnoI );
895 23329 : }
896 : }
897 :
898 : namespace {
899 :
900 1012 : EnvironmentsData::~EnvironmentsData()
901 : {
902 506 : ::osl::MutexGuard guard( mutex );
903 506 : isDisposing = true;
904 :
905 3705 : for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
906 2470 : iPos != aName2EnvMap.end(); ++iPos )
907 : {
908 729 : uno_Environment * pWeak = iPos->second;
909 729 : uno_Environment * pHard = 0;
910 729 : (*pWeak->harden)( &pHard, pWeak );
911 729 : (*pWeak->releaseWeak)( pWeak );
912 :
913 729 : if (pHard)
914 : {
915 : #if OSL_DEBUG_LEVEL > 1
916 : ::uno_dumpEnvironment( 0, pHard, 0 );
917 : #endif
918 0 : (*pHard->dispose)( pHard ); // send explicit dispose
919 0 : (*pHard->release)( pHard );
920 : }
921 506 : }
922 506 : }
923 :
924 :
925 814621 : inline void EnvironmentsData::getEnvironment(
926 : uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
927 : {
928 814621 : if (*ppEnv)
929 : {
930 0 : (*(*ppEnv)->release)( *ppEnv );
931 0 : *ppEnv = 0;
932 : }
933 :
934 : OUString aKey(
935 814621 : OUString::number( reinterpret_cast< sal_IntPtr >(pContext) ) );
936 814621 : aKey += rEnvDcp;
937 :
938 : // try to find registered mapping
939 : OUString2EnvironmentMap::const_iterator const iFind(
940 814621 : aName2EnvMap.find( aKey ) );
941 814621 : if (iFind != aName2EnvMap.end())
942 : {
943 813892 : uno_Environment * pWeak = iFind->second;
944 813892 : (*pWeak->harden)( ppEnv, pWeak );
945 814621 : }
946 814621 : }
947 :
948 :
949 13061 : inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
950 : {
951 : OSL_ENSURE( ppEnv, "### null ptr!" );
952 13061 : uno_Environment * pEnv = *ppEnv;
953 :
954 : OUString aKey(
955 13061 : OUString::number( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
956 13061 : aKey += pEnv->pTypeName;
957 :
958 : // try to find registered environment
959 : OUString2EnvironmentMap::const_iterator const iFind(
960 13061 : aName2EnvMap.find( aKey ) );
961 13061 : if (iFind == aName2EnvMap.end())
962 : {
963 729 : (*pEnv->acquireWeak)( pEnv );
964 : ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion (
965 : aName2EnvMap.insert(
966 729 : OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
967 : SAL_WARN_IF( !insertion.second, "cppu", "key " << aKey << " already in env map" );
968 : }
969 : else
970 : {
971 12332 : uno_Environment * pHard = 0;
972 12332 : uno_Environment * pWeak = iFind->second;
973 12332 : (*pWeak->harden)( &pHard, pWeak );
974 12332 : if (pHard)
975 : {
976 0 : (*pEnv->release)( pEnv );
977 0 : *ppEnv = pHard;
978 : }
979 : else // registered one is dead
980 : {
981 12332 : (*pWeak->releaseWeak)( pWeak );
982 12332 : (*pEnv->acquireWeak)( pEnv );
983 12332 : aName2EnvMap[ aKey ] = pEnv;
984 : }
985 13061 : }
986 13061 : }
987 :
988 :
989 521 : inline void EnvironmentsData::getRegisteredEnvironments(
990 : uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
991 : const OUString & rEnvDcp )
992 : {
993 : assert(pppEnvs && pnLen && memAlloc && "### null ptr!");
994 :
995 : // max size
996 521 : uno_Environment ** ppFound = static_cast<uno_Environment **>(alloca(
997 521 : sizeof(uno_Environment *) * aName2EnvMap.size() ));
998 521 : sal_Int32 nSize = 0;
999 :
1000 : // find matching environment
1001 3801 : for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
1002 2534 : iPos != aName2EnvMap.end(); ++iPos )
1003 : {
1004 746 : uno_Environment * pWeak = iPos->second;
1005 2984 : if (rEnvDcp.isEmpty() ||
1006 2984 : rEnvDcp.equals( pWeak->pTypeName ))
1007 : {
1008 3 : ppFound[nSize] = 0;
1009 3 : (*pWeak->harden)( &ppFound[nSize], pWeak );
1010 3 : if (ppFound[nSize])
1011 3 : ++nSize;
1012 : }
1013 : }
1014 :
1015 521 : *pnLen = nSize;
1016 521 : if (nSize)
1017 : {
1018 : *pppEnvs = static_cast<uno_Environment **>((*memAlloc)(
1019 3 : sizeof (uno_Environment *) * nSize ));
1020 : OSL_ASSERT( *pppEnvs );
1021 9 : while (nSize--)
1022 : {
1023 3 : (*pppEnvs)[nSize] = ppFound[nSize];
1024 : }
1025 : }
1026 : else
1027 : {
1028 518 : *pppEnvs = 0;
1029 : }
1030 521 : }
1031 :
1032 2300 : static bool loadEnv(OUString const & cLibStem,
1033 : uno_Environment * pEnv)
1034 : {
1035 : #ifdef DISABLE_DYNLOADING
1036 : uno_initEnvironmentFunc fpInit;
1037 :
1038 : if ( cLibStem == CPPU_CURRENT_LANGUAGE_BINDING_NAME "_uno" )
1039 : fpInit = CPPU_ENV_uno_initEnvironment;
1040 : #if HAVE_FEATURE_JAVA
1041 : else if ( cLibStem == "java_uno" )
1042 : fpInit = java_uno_initEnvironment;
1043 : #endif
1044 : else
1045 : {
1046 : #if OSL_DEBUG_LEVEL > 1
1047 : OSL_TRACE( "%s: Unhandled env: %s", __PRETTY_FUNCTION__, OUStringToOString( cLibStem, RTL_TEXTENCODING_ASCII_US).getStr() );
1048 : #endif
1049 : return false;
1050 : }
1051 : #else
1052 : // late init with some code from matching uno language binding
1053 : // will be unloaded by environment
1054 2300 : osl::Module aMod;
1055 2300 : bool bMod = cppu::detail::loadModule(aMod, cLibStem);
1056 :
1057 2300 : if (!bMod)
1058 0 : return false;
1059 :
1060 4600 : OUString aSymbolName(UNO_INIT_ENVIRONMENT);
1061 2300 : uno_initEnvironmentFunc fpInit = reinterpret_cast<uno_initEnvironmentFunc>(aMod.getSymbol(aSymbolName));
1062 :
1063 2300 : if (!fpInit)
1064 0 : return false;
1065 :
1066 2300 : aMod.release();
1067 : #endif
1068 :
1069 2300 : (*fpInit)( pEnv ); // init of environment
1070 4600 : return true;
1071 : }
1072 :
1073 : }
1074 :
1075 : extern "C"
1076 : {
1077 :
1078 :
1079 13063 : static uno_Environment * initDefaultEnvironment(
1080 : const OUString & rEnvDcp, void * pContext )
1081 : {
1082 13063 : uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
1083 13063 : (*pEnv->acquire)( pEnv );
1084 :
1085 13063 : OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
1086 :
1087 : // create default environment
1088 13063 : if ( envTypeName == UNO_LB_UNO )
1089 : {
1090 10768 : uno_DefaultEnvironment * that = reinterpret_cast<uno_DefaultEnvironment *>(pEnv);
1091 10768 : that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
1092 10768 : that->acquireInterface = unoenv_acquireInterface;
1093 10768 : that->releaseInterface = unoenv_releaseInterface;
1094 :
1095 10768 : OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
1096 10768 : if (!envPurpose.isEmpty())
1097 : {
1098 5 : rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
1099 5 : libStem += rtl::OUString("_uno_uno");
1100 :
1101 5 : if(!loadEnv(libStem, pEnv))
1102 : {
1103 0 : pEnv->release(pEnv);
1104 0 : return NULL;
1105 5 : }
1106 10768 : }
1107 : }
1108 : else
1109 : {
1110 : // late init with some code from matching uno language binding
1111 2295 : ::rtl::OUStringBuffer aLibName( 16 );
1112 2295 : aLibName.append( envTypeName );
1113 2295 : aLibName.append( "_uno" );
1114 4590 : OUString aStr( aLibName.makeStringAndClear() );
1115 :
1116 2295 : if (!loadEnv(aStr, pEnv))
1117 : {
1118 0 : pEnv->release(pEnv);
1119 0 : return NULL;
1120 2295 : }
1121 : }
1122 :
1123 13063 : return pEnv;
1124 : }
1125 :
1126 :
1127 2 : void SAL_CALL uno_createEnvironment(
1128 : uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1129 : SAL_THROW_EXTERN_C()
1130 : {
1131 : assert(ppEnv && "### null ptr!");
1132 2 : if (*ppEnv)
1133 0 : (*(*ppEnv)->release)( *ppEnv );
1134 :
1135 2 : OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1136 2 : *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1137 2 : }
1138 :
1139 814621 : void SAL_CALL uno_getEnvironment(
1140 : uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
1141 : SAL_THROW_EXTERN_C()
1142 : {
1143 : assert(ppEnv && "### null ptr!");
1144 814621 : OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
1145 :
1146 814621 : EnvironmentsData & rData = theEnvironmentsData::get();
1147 :
1148 814621 : ::osl::MutexGuard guard( rData.mutex );
1149 814621 : rData.getEnvironment( ppEnv, rEnvDcp, pContext );
1150 814621 : if (! *ppEnv)
1151 : {
1152 13061 : *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
1153 13061 : if (*ppEnv)
1154 : {
1155 : // register new environment:
1156 13061 : rData.registerEnvironment( ppEnv );
1157 : }
1158 814621 : }
1159 814621 : }
1160 :
1161 521 : void SAL_CALL uno_getRegisteredEnvironments(
1162 : uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
1163 : rtl_uString * pEnvDcp )
1164 : SAL_THROW_EXTERN_C()
1165 : {
1166 521 : EnvironmentsData & rData = theEnvironmentsData::get();
1167 :
1168 521 : ::osl::MutexGuard guard( rData.mutex );
1169 : rData.getRegisteredEnvironments(
1170 : pppEnvs, pnLen, memAlloc,
1171 521 : (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
1172 521 : }
1173 :
1174 : } // extern "C"
1175 :
1176 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|