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