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