xref: /trunk/main/cppuhelper/source/component_context.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppuhelper.hxx"
26 
27 #ifdef DIAG
28 #define CONTEXT_DIAG
29 #endif
30 
31 #if OSL_DEBUG_LEVEL > 0
32 #include <stdio.h>
33 #endif
34 
35 #include <vector>
36 #include <hash_map>
37 #ifdef CONTEXT_DIAG
38 #include <map>
39 #endif
40 
41 #include <osl/diagnose.h>
42 #include <osl/mutex.hxx>
43 
44 #include <rtl/ustrbuf.hxx>
45 
46 #include <uno/mapping.hxx>
47 
48 #include <cppuhelper/implbase1.hxx>
49 #include <cppuhelper/compbase2.hxx>
50 #include <cppuhelper/component_context.hxx>
51 #include <cppuhelper/exc_hlp.hxx>
52 
53 #include <com/sun/star/container/XNameContainer.hpp>
54 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
55 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
56 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
57 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
58 #include <com/sun/star/lang/XComponent.hpp>
59 #include <com/sun/star/beans/XPropertySet.hpp>
60 #include "com/sun/star/uno/RuntimeException.hpp"
61 
62 #include <hash_map>
63 #include <memory>
64 
65 #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager"
66 #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager"
67 #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController"
68 #define AC_POLICY "/singletons/com.sun.star.security.thePolicy"
69 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
70 
71 
72 using namespace ::osl;
73 using namespace ::rtl;
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star;
76 
77 namespace cppu
78 {
79 
80 #ifdef CONTEXT_DIAG
81 //--------------------------------------------------------------------------------------------------
val2str(void const * pVal,typelib_TypeDescriptionReference * pTypeRef)82 static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef )
83 {
84     OSL_ASSERT( pVal );
85     if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
86         return OUSTR("void");
87 
88     OUStringBuffer buf( 64 );
89     buf.append( (sal_Unicode)'(' );
90     buf.append( pTypeRef->pTypeName );
91     buf.append( (sal_Unicode)')' );
92 
93     switch (pTypeRef->eTypeClass)
94     {
95     case typelib_TypeClass_INTERFACE:
96         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
97         buf.append( (sal_Int64)*(void **)pVal, 16 );
98         break;
99     case typelib_TypeClass_STRUCT:
100     case typelib_TypeClass_EXCEPTION:
101     {
102         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
103         typelib_TypeDescription * pTypeDescr = 0;
104         ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
105         OSL_ASSERT( pTypeDescr );
106         if (! pTypeDescr->bComplete)
107             ::typelib_typedescription_complete( &pTypeDescr );
108 
109         typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
110         sal_Int32 nDescr = pCompType->nMembers;
111 
112         if (pCompType->pBaseTypeDescription)
113         {
114             buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) );
115             if (nDescr)
116                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
117         }
118 
119         typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
120         sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
121         rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
122 
123         for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
124         {
125             buf.append( ppMemberNames[ nPos ] );
126             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") );
127             typelib_TypeDescription * pMemberType = 0;
128             TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] );
129             buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) );
130             TYPELIB_DANGER_RELEASE( pMemberType );
131             if (nPos < (nDescr -1))
132                 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
133         }
134 
135         ::typelib_typedescription_release( pTypeDescr );
136 
137         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
138         break;
139     }
140     case typelib_TypeClass_SEQUENCE:
141     {
142         typelib_TypeDescription * pTypeDescr = 0;
143         TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
144 
145         uno_Sequence * pSequence = *(uno_Sequence **)pVal;
146         typelib_TypeDescription * pElementTypeDescr = 0;
147         TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
148 
149         sal_Int32 nElementSize = pElementTypeDescr->nSize;
150         sal_Int32 nElements    = pSequence->nElements;
151 
152         if (nElements)
153         {
154             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
155             char * pElements = pSequence->elements;
156             for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
157             {
158                 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) );
159                 if (nPos < (nElements -1))
160                     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
161             }
162             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
163         }
164         else
165         {
166             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") );
167         }
168         TYPELIB_DANGER_RELEASE( pElementTypeDescr );
169         TYPELIB_DANGER_RELEASE( pTypeDescr );
170         break;
171     }
172     case typelib_TypeClass_ANY:
173         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
174         buf.append( val2str( ((uno_Any *)pVal)->pData,
175                              ((uno_Any *)pVal)->pType ) );
176         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
177         break;
178     case typelib_TypeClass_TYPE:
179         buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
180         break;
181     case typelib_TypeClass_STRING:
182         buf.append( (sal_Unicode)'\"' );
183         buf.append( *(rtl_uString **)pVal );
184         buf.append( (sal_Unicode)'\"' );
185         break;
186     case typelib_TypeClass_ENUM:
187     {
188         typelib_TypeDescription * pTypeDescr = 0;
189         ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
190         OSL_ASSERT( pTypeDescr );
191         if (! pTypeDescr->bComplete)
192             ::typelib_typedescription_complete( &pTypeDescr );
193 
194         sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
195         sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
196         while (nPos--)
197         {
198             if (pValues[ nPos ] == *(sal_Int32 *)pVal)
199                 break;
200         }
201         if (nPos >= 0)
202             buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] );
203         else
204             buf.append( (sal_Unicode)'?' );
205 
206         ::typelib_typedescription_release( pTypeDescr );
207         break;
208     }
209     case typelib_TypeClass_BOOLEAN:
210         if (*(sal_Bool *)pVal)
211             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") );
212         else
213             buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") );
214         break;
215     case typelib_TypeClass_CHAR:
216         buf.append( (sal_Unicode)'\'' );
217         buf.append( *(sal_Unicode *)pVal );
218         buf.append( (sal_Unicode)'\'' );
219         break;
220     case typelib_TypeClass_FLOAT:
221         buf.append( *(float *)pVal );
222         break;
223     case typelib_TypeClass_DOUBLE:
224         buf.append( *(double *)pVal );
225         break;
226     case typelib_TypeClass_BYTE:
227         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
228         buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
229         break;
230     case typelib_TypeClass_SHORT:
231         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
232         buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
233         break;
234     case typelib_TypeClass_UNSIGNED_SHORT:
235         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
236         buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
237         break;
238     case typelib_TypeClass_LONG:
239         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
240         buf.append( *(sal_Int32 *)pVal, 16 );
241         break;
242     case typelib_TypeClass_UNSIGNED_LONG:
243         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
244         buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
245         break;
246     case typelib_TypeClass_HYPER:
247     case typelib_TypeClass_UNSIGNED_HYPER:
248         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
249 #if defined(GCC) && defined(SPARC)
250         {
251             sal_Int64 aVal;
252             *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
253             *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
254             buf.append( aVal, 16 );
255         }
256 #else
257         buf.append( *(sal_Int64 *)pVal, 16 );
258 #endif
259         break;
260     default:
261         buf.append( (sal_Unicode)'?' );
262     }
263 
264     return buf.makeStringAndClear();
265 }
266 //--------------------------------------------------------------------------------------------------
dumpEntry(OUString const & key,Any const & value)267 static void dumpEntry( OUString const & key, Any const & value )
268 {
269     OUString val( val2str( value.getValue(), value.getValueTypeRef() ) );
270     OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) );
271     OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) );
272     ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() );
273 }
274 #endif
275 //--------------------------------------------------------------------------------------------------
try_dispose(Reference<XInterface> const & xInstance)276 static inline void try_dispose( Reference< XInterface > const & xInstance )
277 {
278     Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
279     if (xComp.is())
280     {
281         xComp->dispose();
282     }
283 }
284 //--------------------------------------------------------------------------------------------------
try_dispose(Reference<lang::XComponent> const & xComp)285 static inline void try_dispose( Reference< lang::XComponent > const & xComp )
286 {
287     if (xComp.is())
288     {
289         xComp->dispose();
290     }
291 }
292 
293 //==================================================================================================
294 
295 class DisposingForwarder
296     : public WeakImplHelper1< lang::XEventListener >
297 {
298     Reference< lang::XComponent > m_xTarget;
299 
300     inline DisposingForwarder( Reference< lang::XComponent > const & xTarget )
301         SAL_THROW( () )
302         : m_xTarget( xTarget )
303         { OSL_ASSERT( m_xTarget.is() ); }
304 public:
305     // listens at source for disposing, then disposes target
306     static inline void listen(
307         Reference< lang::XComponent > const & xSource,
308         Reference< lang::XComponent > const & xTarget );
309 
310     virtual void SAL_CALL disposing( lang::EventObject const & rSource );
311 };
312 //__________________________________________________________________________________________________
listen(Reference<lang::XComponent> const & xSource,Reference<lang::XComponent> const & xTarget)313 inline void DisposingForwarder::listen(
314     Reference< lang::XComponent > const & xSource,
315     Reference< lang::XComponent > const & xTarget )
316 {
317     if (xSource.is())
318     {
319         xSource->addEventListener( new DisposingForwarder( xTarget ) );
320     }
321 }
322 //__________________________________________________________________________________________________
disposing(lang::EventObject const &)323 void DisposingForwarder::disposing( lang::EventObject const & )
324 {
325     m_xTarget->dispose();
326     m_xTarget.clear();
327 }
328 
329 //==================================================================================================
330 struct MutexHolder
331 {
332 protected:
333     Mutex m_mutex;
334 };
335 //==================================================================================================
336 
337 class ComponentContext
338     : private MutexHolder
339     , public WeakComponentImplHelper2< XComponentContext,
340                                        container::XNameContainer >
341 {
342 protected:
343     Reference< XComponentContext > m_xDelegate;
344 
345     struct ContextEntry
346     {
347         Any value;
348         bool lateInit;
349 
ContextEntrycppu::ComponentContext::ContextEntry350         inline ContextEntry( Any const & value_, bool lateInit_ )
351             : value( value_ )
352             , lateInit( lateInit_ )
353             {}
354     };
355     typedef ::std::hash_map< OUString, ContextEntry * , OUStringHash > t_map;
356     t_map m_map;
357 
358     Reference< lang::XMultiComponentFactory > m_xSMgr;
359 
360 protected:
361     Any lookupMap( OUString const & rName );
362 
363     virtual void SAL_CALL disposing();
364 public:
365     ComponentContext(
366         ContextEntry_Init const * pEntries, sal_Int32 nEntries,
367         Reference< XComponentContext > const & xDelegate );
368     virtual ~ComponentContext()
369         SAL_THROW( () );
370 
371     // XComponentContext
372     virtual Any SAL_CALL getValueByName( OUString const & rName );
373     virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager();
374 
375     // XNameContainer
376     virtual void SAL_CALL insertByName(
377         OUString const & name, Any const & element );
378     virtual void SAL_CALL removeByName( OUString const & name );
379     // XNameReplace
380     virtual void SAL_CALL replaceByName(
381         OUString const & name, Any const & element );
382     // XNameAccess
383     virtual Any SAL_CALL getByName( OUString const & name );
384     virtual Sequence<OUString> SAL_CALL getElementNames();
385     virtual sal_Bool SAL_CALL hasByName( OUString const & name );
386     // XElementAccess
387     virtual Type SAL_CALL getElementType();
388     virtual sal_Bool SAL_CALL hasElements();
389 };
390 
391 // XNameContainer
392 //______________________________________________________________________________
insertByName(OUString const & name,Any const & element)393 void ComponentContext::insertByName(
394     OUString const & name, Any const & element )
395 {
396     t_map::mapped_type entry(
397         new ContextEntry(
398             element,
399             /* lateInit_: */
400             name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
401             !element.hasValue() ) );
402     MutexGuard guard( m_mutex );
403     ::std::pair<t_map::iterator, bool> insertion( m_map.insert(
404         t_map::value_type( name, entry ) ) );
405     if (! insertion.second)
406         throw container::ElementExistException(
407             OUSTR("element already exists: ") + name,
408             static_cast<OWeakObject *>(this) );
409 }
410 
411 //______________________________________________________________________________
removeByName(OUString const & name)412 void ComponentContext::removeByName( OUString const & name )
413 {
414     MutexGuard guard( m_mutex );
415     t_map::iterator iFind( m_map.find( name ) );
416     if (iFind == m_map.end())
417         throw container::NoSuchElementException(
418             OUSTR("no such element: ") + name,
419             static_cast<OWeakObject *>(this) );
420 
421     delete iFind->second;
422     m_map.erase(iFind);
423 }
424 
425 // XNameReplace
426 //______________________________________________________________________________
replaceByName(OUString const & name,Any const & element)427 void ComponentContext::replaceByName(
428     OUString const & name, Any const & element )
429 {
430     MutexGuard guard( m_mutex );
431     t_map::const_iterator const iFind( m_map.find( name ) );
432     if (iFind == m_map.end())
433         throw container::NoSuchElementException(
434             OUSTR("no such element: ") + name,
435             static_cast<OWeakObject *>(this) );
436     if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
437         !element.hasValue())
438     {
439         iFind->second->value.clear();
440         iFind->second->lateInit = true;
441     }
442     else
443     {
444         iFind->second->value = element;
445         iFind->second->lateInit = false;
446     }
447 }
448 
449 // XNameAccess
450 //______________________________________________________________________________
getByName(OUString const & name)451 Any ComponentContext::getByName( OUString const & name )
452 {
453     return getValueByName( name );
454 }
455 
456 //______________________________________________________________________________
getElementNames()457 Sequence<OUString> ComponentContext::getElementNames()
458 {
459     MutexGuard guard( m_mutex );
460     Sequence<OUString> ret( m_map.size() );
461     OUString * pret = ret.getArray();
462     sal_Int32 pos = 0;
463     t_map::const_iterator iPos( m_map.begin() );
464     t_map::const_iterator const iEnd( m_map.end() );
465     for ( ; iPos != iEnd; ++iPos )
466         pret[pos++] = iPos->first;
467     return ret;
468 }
469 
470 //______________________________________________________________________________
hasByName(OUString const & name)471 sal_Bool ComponentContext::hasByName( OUString const & name )
472 {
473     MutexGuard guard( m_mutex );
474     return m_map.find( name ) != m_map.end();
475 }
476 
477 // XElementAccess
478 //______________________________________________________________________________
getElementType()479 Type ComponentContext::getElementType()
480 {
481     return ::getVoidCppuType();
482 }
483 
484 //______________________________________________________________________________
hasElements()485 sal_Bool ComponentContext::hasElements()
486 {
487     MutexGuard guard( m_mutex );
488     return ! m_map.empty();
489 }
490 
491 //__________________________________________________________________________________________________
lookupMap(OUString const & rName)492 Any ComponentContext::lookupMap( OUString const & rName )
493 {
494 #ifdef CONTEXT_DIAG
495     if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dump_maps") ))
496     {
497         ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this );
498         typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map
499         t_sorted sorted;
500         for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
501         {
502             sorted[ iPos->first ] = iPos->second;
503         }
504         {
505         for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos )
506         {
507             dumpEntry( iPos->first, iPos->second->value );
508         }
509         }
510         return Any();
511     }
512 #endif
513 
514     ResettableMutexGuard guard( m_mutex );
515     t_map::const_iterator iFind( m_map.find( rName ) );
516     if (iFind == m_map.end())
517         return Any();
518 
519     t_map::mapped_type pEntry = iFind->second;
520     if (! pEntry->lateInit)
521         return pEntry->value;
522 
523     // late init singleton entry
524     Reference< XInterface > xInstance;
525     guard.clear();
526 
527     try
528     {
529         Any usesService( getValueByName( rName + OUSTR("/service") ) );
530         Any args_( getValueByName( rName + OUSTR("/arguments") ) );
531         Sequence<Any> args;
532         if (args_.hasValue() && !(args_ >>= args))
533         {
534             args.realloc( 1 );
535             args[ 0 ] = args_;
536         }
537 
538         Reference< lang::XSingleComponentFactory > xFac;
539         if (usesService >>= xFac) // try via factory
540         {
541             xInstance = args.getLength()
542                 ? xFac->createInstanceWithArgumentsAndContext( args, this )
543                 : xFac->createInstanceWithContext( this );
544         }
545         else
546         {
547             Reference< lang::XSingleServiceFactory > xFac2;
548             if (usesService >>= xFac2)
549             {
550                 // try via old XSingleServiceFactory
551 #if OSL_DEBUG_LEVEL > 0
552                 ::fprintf(
553                     stderr,
554                     "### omitting context for service instantiation!\n" );
555 #endif
556                 xInstance = args.getLength()
557                     ? xFac2->createInstanceWithArguments( args )
558                     : xFac2->createInstance();
559             }
560             else if (m_xSMgr.is()) // optionally service name
561             {
562                 OUString serviceName;
563                 if ((usesService >>= serviceName) &&
564                     serviceName.getLength())
565                 {
566                     xInstance = args.getLength()
567                         ? m_xSMgr->createInstanceWithArgumentsAndContext(
568                             serviceName, args, this )
569                         : m_xSMgr->createInstanceWithContext(
570                             serviceName, this );
571                 }
572             }
573         }
574     }
575     catch (RuntimeException &)
576     {
577         throw;
578     }
579     catch (Exception & exc) // rethrow as WrappedTargetRuntimeException
580     {
581         Any caught( getCaughtException() );
582         OUStringBuffer buf;
583         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
584                              "exception occurred raising singleton \"") );
585         buf.append( rName );
586         buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") );
587         buf.append( exc.Message );
588         throw lang::WrappedTargetRuntimeException(
589             buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught );
590     }
591 
592     if (! xInstance.is())
593     {
594         throw RuntimeException(
595             OUSTR("no service object raising singleton ") + rName,
596             static_cast<OWeakObject *>(this) );
597     }
598 
599     Any ret;
600     guard.reset();
601     iFind = m_map.find( rName );
602     if (iFind != m_map.end())
603     {
604         pEntry = iFind->second;
605         if (pEntry->lateInit)
606         {
607             pEntry->value <<= xInstance;
608             pEntry->lateInit = false;
609             return pEntry->value;
610         }
611         else
612             ret = pEntry->value;
613     }
614     guard.clear();
615     try_dispose( xInstance );
616     return ret;
617 }
618 
619 //__________________________________________________________________________________________________
getValueByName(OUString const & rName)620 Any ComponentContext::getValueByName( OUString const & rName )
621 {
622     // to determine the root context:
623     if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_root") ))
624     {
625         if (m_xDelegate.is())
626             return m_xDelegate->getValueByName( rName );
627         else
628             return makeAny( Reference<XComponentContext>(this) );
629     }
630 
631     Any ret( lookupMap( rName ) );
632     if (!ret.hasValue() && m_xDelegate.is())
633     {
634         return m_xDelegate->getValueByName( rName );
635     }
636     return ret;
637 }
638 //__________________________________________________________________________________________________
getServiceManager()639 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
640 {
641     return m_xSMgr;
642 }
643 //__________________________________________________________________________________________________
~ComponentContext()644 ComponentContext::~ComponentContext()
645     SAL_THROW( () )
646 {
647 #ifdef CONTEXT_DIAG
648     ::fprintf( stderr, "> destructed context %p\n", this );
649 #endif
650     t_map::const_iterator iPos( m_map.begin() );
651     t_map::const_iterator const iEnd( m_map.end() );
652     for ( ; iPos != iEnd; ++iPos )
653         delete iPos->second;
654     m_map.clear();
655 }
656 //__________________________________________________________________________________________________
disposing()657 void ComponentContext::disposing()
658 {
659 #ifdef CONTEXT_DIAG
660     ::fprintf( stderr, "> disposing context %p\n", this );
661 #endif
662 
663     Reference< lang::XComponent > xTDMgr, xAC, xPolicy; // to be disposed separately
664 
665     // dispose all context objects
666     t_map::const_iterator iPos( m_map.begin() );
667     t_map::const_iterator const iEnd( m_map.end() );
668     for ( ; iPos != iEnd; ++iPos )
669     {
670         t_map::mapped_type pEntry = iPos->second;
671 
672         // service manager disposed separately
673         if (!m_xSMgr.is() ||
674             !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) ))
675         {
676             if (pEntry->lateInit)
677             {
678                 // late init
679                 MutexGuard guard( m_mutex );
680                 if (pEntry->lateInit)
681                 {
682                     pEntry->value.clear(); // release factory
683                     pEntry->lateInit = false;
684                     continue;
685                 }
686             }
687 
688             Reference< lang::XComponent > xComp;
689             pEntry->value >>= xComp;
690             if (xComp.is())
691             {
692                 if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(TDMGR_SINGLETON) ))
693                 {
694                     xTDMgr = xComp;
695                 }
696                 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_SINGLETON) ))
697                 {
698                     xAC = xComp;
699                 }
700                 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_POLICY) ))
701                 {
702                     xPolicy = xComp;
703                 }
704                 else // dispose immediately
705                 {
706                     xComp->dispose();
707                 }
708             }
709         }
710     }
711 
712     // dispose service manager
713     try_dispose( m_xSMgr );
714     m_xSMgr.clear();
715     // dispose ac
716     try_dispose( xAC );
717     // dispose policy
718     try_dispose( xPolicy );
719     // dispose tdmgr; revokes callback from cppu runtime
720     try_dispose( xTDMgr );
721 
722     iPos = m_map.begin();
723     for ( ; iPos != iEnd; ++iPos )
724         delete iPos->second;
725     m_map.clear();
726 }
727 //__________________________________________________________________________________________________
ComponentContext(ContextEntry_Init const * pEntries,sal_Int32 nEntries,Reference<XComponentContext> const & xDelegate)728 ComponentContext::ComponentContext(
729     ContextEntry_Init const * pEntries, sal_Int32 nEntries,
730     Reference< XComponentContext > const & xDelegate )
731     : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >(
732         m_mutex ),
733       m_xDelegate( xDelegate )
734 {
735     for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
736     {
737         ContextEntry_Init const & rEntry = pEntries[ nPos ];
738 
739         if (rEntry.name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) ))
740         {
741             rEntry.value >>= m_xSMgr;
742         }
743 
744         if (rEntry.bLateInitService)
745         {
746             // singleton entry
747             m_map[ rEntry.name ] = new ContextEntry( Any(), true );
748             // /service
749             m_map[ rEntry.name + OUSTR("/service") ] = new ContextEntry( rEntry.value, false );
750             // /initial-arguments are provided as optional context entry
751         }
752         else
753         {
754             // only value, no late init factory nor string
755             m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false );
756         }
757     }
758 
759     if (!m_xSMgr.is() && m_xDelegate.is())
760     {
761         // wrap delegate's smgr XPropertySet into new smgr
762         Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() );
763         if (xMgr.is())
764         {
765             osl_incrementInterlockedCount( &m_refCount );
766             try
767             {
768                 // create new smgr based on delegate's one
769                 m_xSMgr.set(
770                     xMgr->createInstanceWithContext(
771                         OUSTR("com.sun.star.comp.stoc.OServiceManagerWrapper"), xDelegate ),
772                     UNO_QUERY );
773                 // patch DefaultContext property of new one
774                 Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY );
775                 OSL_ASSERT( xProps.is() );
776                 if (xProps.is())
777                 {
778                     Reference< XComponentContext > xThis( this );
779                     xProps->setPropertyValue( OUSTR("DefaultContext"), makeAny( xThis ) );
780                 }
781             }
782             catch (...)
783             {
784                 osl_decrementInterlockedCount( &m_refCount );
785                 throw;
786             }
787             osl_decrementInterlockedCount( &m_refCount );
788             OSL_ASSERT( m_xSMgr.is() );
789         }
790     }
791 }
792 
793 
794 //##################################################################################################
s_createComponentContext_v(va_list * pParam)795 extern "C" { static void s_createComponentContext_v(va_list * pParam)
796 {
797     ContextEntry_Init const  * pEntries     = va_arg(*pParam, ContextEntry_Init const *);
798     sal_Int32                  nEntries     = va_arg(*pParam, sal_Int32);
799     XComponentContext        * pDelegatee   = va_arg(*pParam, XComponentContext *);
800     void                    ** ppContext    = va_arg(*pParam, void **);
801     uno::Mapping             * pTarget2curr = va_arg(*pParam, uno::Mapping *);
802 
803     Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
804     Reference<XComponentContext> xContext;
805 
806     if (nEntries > 0)
807     {
808         try
809         {
810             ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate );
811             xContext.set(p);
812             // listen delegate for disposing, to dispose this (wrapping) context first.
813             DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p );
814         }
815         catch (Exception & exc)
816         {
817             (void) exc; // avoid warning about unused variable
818             OSL_ENSURE( 0, OUStringToOString(
819                             exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
820             xContext.clear();
821         }
822     }
823     else
824     {
825         xContext = xDelegate;
826     }
827 
828     delete[] pEntries;
829 
830     *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext));
831 }}
832 
createComponentContext(ContextEntry_Init const * pEntries,sal_Int32 nEntries,Reference<XComponentContext> const & xDelegate)833 Reference< XComponentContext > SAL_CALL createComponentContext(
834     ContextEntry_Init const * pEntries, sal_Int32 nEntries,
835     Reference< XComponentContext > const & xDelegate )
836     SAL_THROW( () )
837 {
838     uno::Environment curr_env(Environment::getCurrent());
839     uno::Environment source_env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CPPU_STRINGIFY(CPPU_ENV))));
840 
841     uno::Mapping curr2source(curr_env, source_env);
842     uno::Mapping source2curr(source_env, curr_env);
843 
844     ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries];
845     for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
846     {
847         mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
848         mapped_entries[nPos].name             = pEntries[nPos].name;
849 
850         uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
851                                          const_cast<void *>(pEntries[nPos].value.getValue()),
852                                          pEntries[nPos].value.getValueTypeRef(),
853                                          curr2source.get());
854     }
855 
856     void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate));
857     XComponentContext * pXComponentContext = NULL;
858     source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr);
859 
860     return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
861 }
862 
863 }
864