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 SAL_THROW( (RuntimeException) )
278 {
279 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
280 if (xComp.is())
281 {
282 xComp->dispose();
283 }
284 }
285 //--------------------------------------------------------------------------------------------------
try_dispose(Reference<lang::XComponent> const & xComp)286 static inline void try_dispose( Reference< lang::XComponent > const & xComp )
287 SAL_THROW( (RuntimeException) )
288 {
289 if (xComp.is())
290 {
291 xComp->dispose();
292 }
293 }
294
295 //==================================================================================================
296
297 class DisposingForwarder
298 : public WeakImplHelper1< lang::XEventListener >
299 {
300 Reference< lang::XComponent > m_xTarget;
301
302 inline DisposingForwarder( Reference< lang::XComponent > const & xTarget )
303 SAL_THROW( () )
304 : m_xTarget( xTarget )
305 { OSL_ASSERT( m_xTarget.is() ); }
306 public:
307 // listens at source for disposing, then disposes target
308 static inline void listen(
309 Reference< lang::XComponent > const & xSource,
310 Reference< lang::XComponent > const & xTarget )
311 SAL_THROW( (RuntimeException) );
312
313 virtual void SAL_CALL disposing( lang::EventObject const & rSource )
314 throw (RuntimeException);
315 };
316 //__________________________________________________________________________________________________
listen(Reference<lang::XComponent> const & xSource,Reference<lang::XComponent> const & xTarget)317 inline void DisposingForwarder::listen(
318 Reference< lang::XComponent > const & xSource,
319 Reference< lang::XComponent > const & xTarget )
320 SAL_THROW( (RuntimeException) )
321 {
322 if (xSource.is())
323 {
324 xSource->addEventListener( new DisposingForwarder( xTarget ) );
325 }
326 }
327 //__________________________________________________________________________________________________
disposing(lang::EventObject const &)328 void DisposingForwarder::disposing( lang::EventObject const & )
329 throw (RuntimeException)
330 {
331 m_xTarget->dispose();
332 m_xTarget.clear();
333 }
334
335 //==================================================================================================
336 struct MutexHolder
337 {
338 protected:
339 Mutex m_mutex;
340 };
341 //==================================================================================================
342
343 class ComponentContext
344 : private MutexHolder
345 , public WeakComponentImplHelper2< XComponentContext,
346 container::XNameContainer >
347 {
348 protected:
349 Reference< XComponentContext > m_xDelegate;
350
351 struct ContextEntry
352 {
353 Any value;
354 bool lateInit;
355
ContextEntrycppu::ComponentContext::ContextEntry356 inline ContextEntry( Any const & value_, bool lateInit_ )
357 : value( value_ )
358 , lateInit( lateInit_ )
359 {}
360 };
361 typedef ::std::hash_map< OUString, ContextEntry * , OUStringHash > t_map;
362 t_map m_map;
363
364 Reference< lang::XMultiComponentFactory > m_xSMgr;
365
366 protected:
367 Any lookupMap( OUString const & rName )
368 SAL_THROW( (RuntimeException) );
369
370 virtual void SAL_CALL disposing();
371 public:
372 ComponentContext(
373 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
374 Reference< XComponentContext > const & xDelegate );
375 virtual ~ComponentContext()
376 SAL_THROW( () );
377
378 // XComponentContext
379 virtual Any SAL_CALL getValueByName( OUString const & rName )
380 throw (RuntimeException);
381 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
382 throw (RuntimeException);
383
384 // XNameContainer
385 virtual void SAL_CALL insertByName(
386 OUString const & name, Any const & element )
387 throw (lang::IllegalArgumentException, container::ElementExistException,
388 lang::WrappedTargetException, RuntimeException);
389 virtual void SAL_CALL removeByName( OUString const & name )
390 throw (container::NoSuchElementException,
391 lang::WrappedTargetException, RuntimeException);
392 // XNameReplace
393 virtual void SAL_CALL replaceByName(
394 OUString const & name, Any const & element )
395 throw (lang::IllegalArgumentException,container::NoSuchElementException,
396 lang::WrappedTargetException, RuntimeException);
397 // XNameAccess
398 virtual Any SAL_CALL getByName( OUString const & name )
399 throw (container::NoSuchElementException,
400 lang::WrappedTargetException, RuntimeException);
401 virtual Sequence<OUString> SAL_CALL getElementNames()
402 throw (RuntimeException);
403 virtual sal_Bool SAL_CALL hasByName( OUString const & name )
404 throw (RuntimeException);
405 // XElementAccess
406 virtual Type SAL_CALL getElementType() throw (RuntimeException);
407 virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException);
408 };
409
410 // XNameContainer
411 //______________________________________________________________________________
insertByName(OUString const & name,Any const & element)412 void ComponentContext::insertByName(
413 OUString const & name, Any const & element )
414 throw (lang::IllegalArgumentException, container::ElementExistException,
415 lang::WrappedTargetException, RuntimeException)
416 {
417 t_map::mapped_type entry(
418 new ContextEntry(
419 element,
420 /* lateInit_: */
421 name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
422 !element.hasValue() ) );
423 MutexGuard guard( m_mutex );
424 ::std::pair<t_map::iterator, bool> insertion( m_map.insert(
425 t_map::value_type( name, entry ) ) );
426 if (! insertion.second)
427 throw container::ElementExistException(
428 OUSTR("element already exists: ") + name,
429 static_cast<OWeakObject *>(this) );
430 }
431
432 //______________________________________________________________________________
removeByName(OUString const & name)433 void ComponentContext::removeByName( OUString const & name )
434 throw (container::NoSuchElementException,
435 lang::WrappedTargetException, RuntimeException)
436 {
437 MutexGuard guard( m_mutex );
438 t_map::iterator iFind( m_map.find( name ) );
439 if (iFind == m_map.end())
440 throw container::NoSuchElementException(
441 OUSTR("no such element: ") + name,
442 static_cast<OWeakObject *>(this) );
443
444 delete iFind->second;
445 m_map.erase(iFind);
446 }
447
448 // XNameReplace
449 //______________________________________________________________________________
replaceByName(OUString const & name,Any const & element)450 void ComponentContext::replaceByName(
451 OUString const & name, Any const & element )
452 throw (lang::IllegalArgumentException,container::NoSuchElementException,
453 lang::WrappedTargetException, RuntimeException)
454 {
455 MutexGuard guard( m_mutex );
456 t_map::const_iterator const iFind( m_map.find( name ) );
457 if (iFind == m_map.end())
458 throw container::NoSuchElementException(
459 OUSTR("no such element: ") + name,
460 static_cast<OWeakObject *>(this) );
461 if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
462 !element.hasValue())
463 {
464 iFind->second->value.clear();
465 iFind->second->lateInit = true;
466 }
467 else
468 {
469 iFind->second->value = element;
470 iFind->second->lateInit = false;
471 }
472 }
473
474 // XNameAccess
475 //______________________________________________________________________________
getByName(OUString const & name)476 Any ComponentContext::getByName( OUString const & name )
477 throw (container::NoSuchElementException,
478 lang::WrappedTargetException, RuntimeException)
479 {
480 return getValueByName( name );
481 }
482
483 //______________________________________________________________________________
getElementNames()484 Sequence<OUString> ComponentContext::getElementNames()
485 throw (RuntimeException)
486 {
487 MutexGuard guard( m_mutex );
488 Sequence<OUString> ret( m_map.size() );
489 OUString * pret = ret.getArray();
490 sal_Int32 pos = 0;
491 t_map::const_iterator iPos( m_map.begin() );
492 t_map::const_iterator const iEnd( m_map.end() );
493 for ( ; iPos != iEnd; ++iPos )
494 pret[pos++] = iPos->first;
495 return ret;
496 }
497
498 //______________________________________________________________________________
hasByName(OUString const & name)499 sal_Bool ComponentContext::hasByName( OUString const & name )
500 throw (RuntimeException)
501 {
502 MutexGuard guard( m_mutex );
503 return m_map.find( name ) != m_map.end();
504 }
505
506 // XElementAccess
507 //______________________________________________________________________________
getElementType()508 Type ComponentContext::getElementType() throw (RuntimeException)
509 {
510 return ::getVoidCppuType();
511 }
512
513 //______________________________________________________________________________
hasElements()514 sal_Bool ComponentContext::hasElements() throw (RuntimeException)
515 {
516 MutexGuard guard( m_mutex );
517 return ! m_map.empty();
518 }
519
520 //__________________________________________________________________________________________________
lookupMap(OUString const & rName)521 Any ComponentContext::lookupMap( OUString const & rName )
522 SAL_THROW( (RuntimeException) )
523 {
524 #ifdef CONTEXT_DIAG
525 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dump_maps") ))
526 {
527 ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this );
528 typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map
529 t_sorted sorted;
530 for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
531 {
532 sorted[ iPos->first ] = iPos->second;
533 }
534 {
535 for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos )
536 {
537 dumpEntry( iPos->first, iPos->second->value );
538 }
539 }
540 return Any();
541 }
542 #endif
543
544 ResettableMutexGuard guard( m_mutex );
545 t_map::const_iterator iFind( m_map.find( rName ) );
546 if (iFind == m_map.end())
547 return Any();
548
549 t_map::mapped_type pEntry = iFind->second;
550 if (! pEntry->lateInit)
551 return pEntry->value;
552
553 // late init singleton entry
554 Reference< XInterface > xInstance;
555 guard.clear();
556
557 try
558 {
559 Any usesService( getValueByName( rName + OUSTR("/service") ) );
560 Any args_( getValueByName( rName + OUSTR("/arguments") ) );
561 Sequence<Any> args;
562 if (args_.hasValue() && !(args_ >>= args))
563 {
564 args.realloc( 1 );
565 args[ 0 ] = args_;
566 }
567
568 Reference< lang::XSingleComponentFactory > xFac;
569 if (usesService >>= xFac) // try via factory
570 {
571 xInstance = args.getLength()
572 ? xFac->createInstanceWithArgumentsAndContext( args, this )
573 : xFac->createInstanceWithContext( this );
574 }
575 else
576 {
577 Reference< lang::XSingleServiceFactory > xFac2;
578 if (usesService >>= xFac2)
579 {
580 // try via old XSingleServiceFactory
581 #if OSL_DEBUG_LEVEL > 0
582 ::fprintf(
583 stderr,
584 "### omitting context for service instantiation!\n" );
585 #endif
586 xInstance = args.getLength()
587 ? xFac2->createInstanceWithArguments( args )
588 : xFac2->createInstance();
589 }
590 else if (m_xSMgr.is()) // optionally service name
591 {
592 OUString serviceName;
593 if ((usesService >>= serviceName) &&
594 serviceName.getLength())
595 {
596 xInstance = args.getLength()
597 ? m_xSMgr->createInstanceWithArgumentsAndContext(
598 serviceName, args, this )
599 : m_xSMgr->createInstanceWithContext(
600 serviceName, this );
601 }
602 }
603 }
604 }
605 catch (RuntimeException &)
606 {
607 throw;
608 }
609 catch (Exception & exc) // rethrow as WrappedTargetRuntimeException
610 {
611 Any caught( getCaughtException() );
612 OUStringBuffer buf;
613 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
614 "exception occurred raising singleton \"") );
615 buf.append( rName );
616 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") );
617 buf.append( exc.Message );
618 throw lang::WrappedTargetRuntimeException(
619 buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught );
620 }
621
622 if (! xInstance.is())
623 {
624 throw RuntimeException(
625 OUSTR("no service object raising singleton ") + rName,
626 static_cast<OWeakObject *>(this) );
627 }
628
629 Any ret;
630 guard.reset();
631 iFind = m_map.find( rName );
632 if (iFind != m_map.end())
633 {
634 pEntry = iFind->second;
635 if (pEntry->lateInit)
636 {
637 pEntry->value <<= xInstance;
638 pEntry->lateInit = false;
639 return pEntry->value;
640 }
641 else
642 ret = pEntry->value;
643 }
644 guard.clear();
645 try_dispose( xInstance );
646 return ret;
647 }
648
649 //__________________________________________________________________________________________________
getValueByName(OUString const & rName)650 Any ComponentContext::getValueByName( OUString const & rName )
651 throw (RuntimeException)
652 {
653 // to determine the root context:
654 if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_root") ))
655 {
656 if (m_xDelegate.is())
657 return m_xDelegate->getValueByName( rName );
658 else
659 return makeAny( Reference<XComponentContext>(this) );
660 }
661
662 Any ret( lookupMap( rName ) );
663 if (!ret.hasValue() && m_xDelegate.is())
664 {
665 return m_xDelegate->getValueByName( rName );
666 }
667 return ret;
668 }
669 //__________________________________________________________________________________________________
getServiceManager()670 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
671 throw (RuntimeException)
672 {
673 return m_xSMgr;
674 }
675 //__________________________________________________________________________________________________
~ComponentContext()676 ComponentContext::~ComponentContext()
677 SAL_THROW( () )
678 {
679 #ifdef CONTEXT_DIAG
680 ::fprintf( stderr, "> destructed context %p\n", this );
681 #endif
682 t_map::const_iterator iPos( m_map.begin() );
683 t_map::const_iterator const iEnd( m_map.end() );
684 for ( ; iPos != iEnd; ++iPos )
685 delete iPos->second;
686 m_map.clear();
687 }
688 //__________________________________________________________________________________________________
disposing()689 void ComponentContext::disposing()
690 {
691 #ifdef CONTEXT_DIAG
692 ::fprintf( stderr, "> disposing context %p\n", this );
693 #endif
694
695 Reference< lang::XComponent > xTDMgr, xAC, xPolicy; // to be disposed separately
696
697 // dispose all context objects
698 t_map::const_iterator iPos( m_map.begin() );
699 t_map::const_iterator const iEnd( m_map.end() );
700 for ( ; iPos != iEnd; ++iPos )
701 {
702 t_map::mapped_type pEntry = iPos->second;
703
704 // service manager disposed separately
705 if (!m_xSMgr.is() ||
706 !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) ))
707 {
708 if (pEntry->lateInit)
709 {
710 // late init
711 MutexGuard guard( m_mutex );
712 if (pEntry->lateInit)
713 {
714 pEntry->value.clear(); // release factory
715 pEntry->lateInit = false;
716 continue;
717 }
718 }
719
720 Reference< lang::XComponent > xComp;
721 pEntry->value >>= xComp;
722 if (xComp.is())
723 {
724 if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(TDMGR_SINGLETON) ))
725 {
726 xTDMgr = xComp;
727 }
728 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_SINGLETON) ))
729 {
730 xAC = xComp;
731 }
732 else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_POLICY) ))
733 {
734 xPolicy = xComp;
735 }
736 else // dispose immediately
737 {
738 xComp->dispose();
739 }
740 }
741 }
742 }
743
744 // dispose service manager
745 try_dispose( m_xSMgr );
746 m_xSMgr.clear();
747 // dispose ac
748 try_dispose( xAC );
749 // dispose policy
750 try_dispose( xPolicy );
751 // dispose tdmgr; revokes callback from cppu runtime
752 try_dispose( xTDMgr );
753
754 iPos = m_map.begin();
755 for ( ; iPos != iEnd; ++iPos )
756 delete iPos->second;
757 m_map.clear();
758 }
759 //__________________________________________________________________________________________________
ComponentContext(ContextEntry_Init const * pEntries,sal_Int32 nEntries,Reference<XComponentContext> const & xDelegate)760 ComponentContext::ComponentContext(
761 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
762 Reference< XComponentContext > const & xDelegate )
763 : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >(
764 m_mutex ),
765 m_xDelegate( xDelegate )
766 {
767 for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
768 {
769 ContextEntry_Init const & rEntry = pEntries[ nPos ];
770
771 if (rEntry.name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) ))
772 {
773 rEntry.value >>= m_xSMgr;
774 }
775
776 if (rEntry.bLateInitService)
777 {
778 // singleton entry
779 m_map[ rEntry.name ] = new ContextEntry( Any(), true );
780 // /service
781 m_map[ rEntry.name + OUSTR("/service") ] = new ContextEntry( rEntry.value, false );
782 // /initial-arguments are provided as optional context entry
783 }
784 else
785 {
786 // only value, no late init factory nor string
787 m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false );
788 }
789 }
790
791 if (!m_xSMgr.is() && m_xDelegate.is())
792 {
793 // wrap delegate's smgr XPropertySet into new smgr
794 Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() );
795 if (xMgr.is())
796 {
797 osl_incrementInterlockedCount( &m_refCount );
798 try
799 {
800 // create new smgr based on delegate's one
801 m_xSMgr.set(
802 xMgr->createInstanceWithContext(
803 OUSTR("com.sun.star.comp.stoc.OServiceManagerWrapper"), xDelegate ),
804 UNO_QUERY );
805 // patch DefaultContext property of new one
806 Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY );
807 OSL_ASSERT( xProps.is() );
808 if (xProps.is())
809 {
810 Reference< XComponentContext > xThis( this );
811 xProps->setPropertyValue( OUSTR("DefaultContext"), makeAny( xThis ) );
812 }
813 }
814 catch (...)
815 {
816 osl_decrementInterlockedCount( &m_refCount );
817 throw;
818 }
819 osl_decrementInterlockedCount( &m_refCount );
820 OSL_ASSERT( m_xSMgr.is() );
821 }
822 }
823 }
824
825
826 //##################################################################################################
s_createComponentContext_v(va_list * pParam)827 extern "C" { static void s_createComponentContext_v(va_list * pParam)
828 {
829 ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *);
830 sal_Int32 nEntries = va_arg(*pParam, sal_Int32);
831 XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *);
832 void ** ppContext = va_arg(*pParam, void **);
833 uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *);
834
835 Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
836 Reference<XComponentContext> xContext;
837
838 if (nEntries > 0)
839 {
840 try
841 {
842 ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate );
843 xContext.set(p);
844 // listen delegate for disposing, to dispose this (wrapping) context first.
845 DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p );
846 }
847 catch (Exception & exc)
848 {
849 (void) exc; // avoid warning about unused variable
850 OSL_ENSURE( 0, OUStringToOString(
851 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
852 xContext.clear();
853 }
854 }
855 else
856 {
857 xContext = xDelegate;
858 }
859
860 delete[] pEntries;
861
862 *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext));
863 }}
864
createComponentContext(ContextEntry_Init const * pEntries,sal_Int32 nEntries,Reference<XComponentContext> const & xDelegate)865 Reference< XComponentContext > SAL_CALL createComponentContext(
866 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
867 Reference< XComponentContext > const & xDelegate )
868 SAL_THROW( () )
869 {
870 uno::Environment curr_env(Environment::getCurrent());
871 uno::Environment source_env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CPPU_STRINGIFY(CPPU_ENV))));
872
873 uno::Mapping curr2source(curr_env, source_env);
874 uno::Mapping source2curr(source_env, curr_env);
875
876 ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries];
877 for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
878 {
879 mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
880 mapped_entries[nPos].name = pEntries[nPos].name;
881
882 uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
883 const_cast<void *>(pEntries[nPos].value.getValue()),
884 pEntries[nPos].value.getValueTypeRef(),
885 curr2source.get());
886 }
887
888 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate));
889 XComponentContext * pXComponentContext = NULL;
890 source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr);
891
892 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
893 }
894
895 }
896