update credits
[LibreOffice.git] / cppuhelper / source / component_context.cxx
blob7d417788238f5aa3d4a61287762c76f4bd371076
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #ifdef DIAG
22 #define CONTEXT_DIAG
23 #endif
25 #if OSL_DEBUG_LEVEL > 0
26 #include <stdio.h>
27 #endif
29 #include <vector>
30 #include <boost/unordered_map.hpp>
31 #ifdef CONTEXT_DIAG
32 #include <map>
33 #endif
35 #include <osl/diagnose.h>
36 #include <osl/mutex.hxx>
38 #include <rtl/ustrbuf.hxx>
40 #include <uno/mapping.hxx>
42 #include <cppuhelper/implbase1.hxx>
43 #include <cppuhelper/compbase2.hxx>
44 #include <cppuhelper/component_context.hxx>
45 #include <cppuhelper/exc_hlp.hxx>
47 #include <com/sun/star/container/XNameContainer.hpp>
48 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
49 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
50 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
51 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
52 #include <com/sun/star/lang/XComponent.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include "com/sun/star/uno/DeploymentException.hpp"
55 #include "com/sun/star/uno/RuntimeException.hpp"
57 #include <memory>
59 #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager"
60 #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager"
61 #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController"
64 using namespace ::osl;
65 using namespace ::rtl;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star;
69 namespace cppu
72 #ifdef CONTEXT_DIAG
73 //--------------------------------------------------------------------------------------------------
74 static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef )
76 OSL_ASSERT( pVal );
77 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
78 return "void";
80 OUStringBuffer buf( 64 );
81 buf.append( (sal_Unicode)'(' );
82 buf.append( pTypeRef->pTypeName );
83 buf.append( (sal_Unicode)')' );
85 switch (pTypeRef->eTypeClass)
87 case typelib_TypeClass_INTERFACE:
88 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
89 buf.append( (sal_Int64)*(void **)pVal, 16 );
90 break;
91 case typelib_TypeClass_STRUCT:
92 case typelib_TypeClass_EXCEPTION:
94 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
95 typelib_TypeDescription * pTypeDescr = 0;
96 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
97 OSL_ASSERT( pTypeDescr );
98 if (! pTypeDescr->bComplete)
99 ::typelib_typedescription_complete( &pTypeDescr );
101 typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
102 sal_Int32 nDescr = pCompType->nMembers;
104 if (pCompType->pBaseTypeDescription)
106 buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) );
107 if (nDescr)
108 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
111 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
112 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
113 rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
115 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
117 buf.append( ppMemberNames[ nPos ] );
118 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") );
119 typelib_TypeDescription * pMemberType = 0;
120 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] );
121 buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) );
122 TYPELIB_DANGER_RELEASE( pMemberType );
123 if (nPos < (nDescr -1))
124 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
127 ::typelib_typedescription_release( pTypeDescr );
129 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
130 break;
132 case typelib_TypeClass_SEQUENCE:
134 typelib_TypeDescription * pTypeDescr = 0;
135 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
137 uno_Sequence * pSequence = *(uno_Sequence **)pVal;
138 typelib_TypeDescription * pElementTypeDescr = 0;
139 TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
141 sal_Int32 nElementSize = pElementTypeDescr->nSize;
142 sal_Int32 nElements = pSequence->nElements;
144 if (nElements)
146 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
147 char * pElements = pSequence->elements;
148 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
150 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) );
151 if (nPos < (nElements -1))
152 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
154 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
156 else
158 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") );
160 TYPELIB_DANGER_RELEASE( pElementTypeDescr );
161 TYPELIB_DANGER_RELEASE( pTypeDescr );
162 break;
164 case typelib_TypeClass_ANY:
165 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
166 buf.append( val2str( ((uno_Any *)pVal)->pData,
167 ((uno_Any *)pVal)->pType ) );
168 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
169 break;
170 case typelib_TypeClass_TYPE:
171 buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
172 break;
173 case typelib_TypeClass_STRING:
174 buf.append( (sal_Unicode)'\"' );
175 buf.append( *(rtl_uString **)pVal );
176 buf.append( (sal_Unicode)'\"' );
177 break;
178 case typelib_TypeClass_ENUM:
180 typelib_TypeDescription * pTypeDescr = 0;
181 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
182 OSL_ASSERT( pTypeDescr );
183 if (! pTypeDescr->bComplete)
184 ::typelib_typedescription_complete( &pTypeDescr );
186 sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
187 sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
188 while (nPos--)
190 if (pValues[ nPos ] == *(sal_Int32 *)pVal)
191 break;
193 if (nPos >= 0)
194 buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] );
195 else
196 buf.append( (sal_Unicode)'?' );
198 ::typelib_typedescription_release( pTypeDescr );
199 break;
201 case typelib_TypeClass_BOOLEAN:
202 if (*(sal_Bool *)pVal)
203 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") );
204 else
205 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") );
206 break;
207 case typelib_TypeClass_CHAR:
208 buf.append( (sal_Unicode)'\'' );
209 buf.append( *(sal_Unicode *)pVal );
210 buf.append( (sal_Unicode)'\'' );
211 break;
212 case typelib_TypeClass_FLOAT:
213 buf.append( *(float *)pVal );
214 break;
215 case typelib_TypeClass_DOUBLE:
216 buf.append( *(double *)pVal );
217 break;
218 case typelib_TypeClass_BYTE:
219 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
220 buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
221 break;
222 case typelib_TypeClass_SHORT:
223 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
224 buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
225 break;
226 case typelib_TypeClass_UNSIGNED_SHORT:
227 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
228 buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
229 break;
230 case typelib_TypeClass_LONG:
231 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
232 buf.append( *(sal_Int32 *)pVal, 16 );
233 break;
234 case typelib_TypeClass_UNSIGNED_LONG:
235 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
236 buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
237 break;
238 case typelib_TypeClass_HYPER:
239 case typelib_TypeClass_UNSIGNED_HYPER:
240 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
241 #if defined(__GNUC__) && defined(SPARC)
242 // I guess this really should check if there are strict alignment
243 // requirements, not just "GCC on SPARC".
245 sal_Int64 aVal;
246 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
247 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
248 buf.append( aVal, 16 );
250 #else
251 buf.append( *(sal_Int64 *)pVal, 16 );
252 #endif
253 break;
254 default:
255 buf.append( (sal_Unicode)'?' );
258 return buf.makeStringAndClear();
260 //--------------------------------------------------------------------------------------------------
261 static void dumpEntry( OUString const & key, Any const & value )
263 OUString val( val2str( value.getValue(), value.getValueTypeRef() ) );
264 OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) );
265 OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) );
266 ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() );
268 #endif
269 //--------------------------------------------------------------------------------------------------
270 static inline void try_dispose( Reference< XInterface > const & xInstance )
271 SAL_THROW( (RuntimeException) )
273 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
274 if (xComp.is())
276 xComp->dispose();
279 //--------------------------------------------------------------------------------------------------
280 static inline void try_dispose( Reference< lang::XComponent > const & xComp )
281 SAL_THROW( (RuntimeException) )
283 if (xComp.is())
285 xComp->dispose();
289 //==================================================================================================
291 class DisposingForwarder
292 : public WeakImplHelper1< lang::XEventListener >
294 Reference< lang::XComponent > m_xTarget;
296 inline DisposingForwarder( Reference< lang::XComponent > const & xTarget )
297 SAL_THROW(())
298 : m_xTarget( xTarget )
299 { OSL_ASSERT( m_xTarget.is() ); }
300 public:
301 // listens at source for disposing, then disposes target
302 static inline void listen(
303 Reference< lang::XComponent > const & xSource,
304 Reference< lang::XComponent > const & xTarget )
305 SAL_THROW( (RuntimeException) );
307 virtual void SAL_CALL disposing( lang::EventObject const & rSource )
308 throw (RuntimeException);
310 //__________________________________________________________________________________________________
311 inline void DisposingForwarder::listen(
312 Reference< lang::XComponent > const & xSource,
313 Reference< lang::XComponent > const & xTarget )
314 SAL_THROW( (RuntimeException) )
316 if (xSource.is())
318 xSource->addEventListener( new DisposingForwarder( xTarget ) );
321 //__________________________________________________________________________________________________
322 void DisposingForwarder::disposing( lang::EventObject const & )
323 throw (RuntimeException)
325 m_xTarget->dispose();
326 m_xTarget.clear();
329 //==================================================================================================
330 struct MutexHolder
332 protected:
333 Mutex m_mutex;
335 //==================================================================================================
337 class ComponentContext
338 : private MutexHolder
339 , public WeakComponentImplHelper2< XComponentContext,
340 container::XNameContainer >
342 protected:
343 Reference< XComponentContext > m_xDelegate;
345 struct ContextEntry
347 Any value;
348 bool lateInit;
350 inline ContextEntry( Any const & value_, bool lateInit_ )
351 : value( value_ )
352 , lateInit( lateInit_ )
355 typedef ::boost::unordered_map< OUString, ContextEntry * , OUStringHash > t_map;
356 t_map m_map;
358 Reference< lang::XMultiComponentFactory > m_xSMgr;
360 protected:
361 Any lookupMap( OUString const & rName )
362 SAL_THROW( (RuntimeException) );
364 virtual void SAL_CALL disposing();
365 public:
366 ComponentContext(
367 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
368 Reference< XComponentContext > const & xDelegate );
369 virtual ~ComponentContext()
370 SAL_THROW(());
372 // XComponentContext
373 virtual Any SAL_CALL getValueByName( OUString const & rName )
374 throw (RuntimeException);
375 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
376 throw (RuntimeException);
378 // XNameContainer
379 virtual void SAL_CALL insertByName(
380 OUString const & name, Any const & element )
381 throw (lang::IllegalArgumentException, container::ElementExistException,
382 lang::WrappedTargetException, RuntimeException);
383 virtual void SAL_CALL removeByName( OUString const & name )
384 throw (container::NoSuchElementException,
385 lang::WrappedTargetException, RuntimeException);
386 // XNameReplace
387 virtual void SAL_CALL replaceByName(
388 OUString const & name, Any const & element )
389 throw (lang::IllegalArgumentException,container::NoSuchElementException,
390 lang::WrappedTargetException, RuntimeException);
391 // XNameAccess
392 virtual Any SAL_CALL getByName( OUString const & name )
393 throw (container::NoSuchElementException,
394 lang::WrappedTargetException, RuntimeException);
395 virtual Sequence<OUString> SAL_CALL getElementNames()
396 throw (RuntimeException);
397 virtual sal_Bool SAL_CALL hasByName( OUString const & name )
398 throw (RuntimeException);
399 // XElementAccess
400 virtual Type SAL_CALL getElementType() throw (RuntimeException);
401 virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException);
404 // XNameContainer
405 //______________________________________________________________________________
406 void ComponentContext::insertByName(
407 OUString const & name, Any const & element )
408 throw (lang::IllegalArgumentException, container::ElementExistException,
409 lang::WrappedTargetException, RuntimeException)
411 t_map::mapped_type entry(
412 new ContextEntry(
413 element,
414 /* lateInit_: */
415 name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
416 !element.hasValue() ) );
417 MutexGuard guard( m_mutex );
418 ::std::pair<t_map::iterator, bool> insertion( m_map.insert(
419 t_map::value_type( name, entry ) ) );
420 if (! insertion.second)
421 throw container::ElementExistException(
422 "element already exists: " + name,
423 static_cast<OWeakObject *>(this) );
426 //______________________________________________________________________________
427 void ComponentContext::removeByName( OUString const & name )
428 throw (container::NoSuchElementException,
429 lang::WrappedTargetException, RuntimeException)
431 MutexGuard guard( m_mutex );
432 t_map::iterator iFind( m_map.find( name ) );
433 if (iFind == m_map.end())
434 throw container::NoSuchElementException(
435 "no such element: " + name,
436 static_cast<OWeakObject *>(this) );
438 delete iFind->second;
439 m_map.erase(iFind);
442 // XNameReplace
443 //______________________________________________________________________________
444 void ComponentContext::replaceByName(
445 OUString const & name, Any const & element )
446 throw (lang::IllegalArgumentException,container::NoSuchElementException,
447 lang::WrappedTargetException, RuntimeException)
449 MutexGuard guard( m_mutex );
450 t_map::const_iterator const iFind( m_map.find( name ) );
451 if (iFind == m_map.end())
452 throw container::NoSuchElementException(
453 "no such element: " + name,
454 static_cast<OWeakObject *>(this) );
455 if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) &&
456 !element.hasValue())
458 iFind->second->value.clear();
459 iFind->second->lateInit = true;
461 else
463 iFind->second->value = element;
464 iFind->second->lateInit = false;
468 // XNameAccess
469 //______________________________________________________________________________
470 Any ComponentContext::getByName( OUString const & name )
471 throw (container::NoSuchElementException,
472 lang::WrappedTargetException, RuntimeException)
474 return getValueByName( name );
477 //______________________________________________________________________________
478 Sequence<OUString> ComponentContext::getElementNames()
479 throw (RuntimeException)
481 MutexGuard guard( m_mutex );
482 Sequence<OUString> ret( m_map.size() );
483 OUString * pret = ret.getArray();
484 sal_Int32 pos = 0;
485 t_map::const_iterator iPos( m_map.begin() );
486 t_map::const_iterator const iEnd( m_map.end() );
487 for ( ; iPos != iEnd; ++iPos )
488 pret[pos++] = iPos->first;
489 return ret;
492 //______________________________________________________________________________
493 sal_Bool ComponentContext::hasByName( OUString const & name )
494 throw (RuntimeException)
496 MutexGuard guard( m_mutex );
497 return m_map.find( name ) != m_map.end();
500 // XElementAccess
501 //______________________________________________________________________________
502 Type ComponentContext::getElementType() throw (RuntimeException)
504 return ::getVoidCppuType();
507 //______________________________________________________________________________
508 sal_Bool ComponentContext::hasElements() throw (RuntimeException)
510 MutexGuard guard( m_mutex );
511 return ! m_map.empty();
514 //__________________________________________________________________________________________________
515 Any ComponentContext::lookupMap( OUString const & rName )
516 SAL_THROW( (RuntimeException) )
518 #ifdef CONTEXT_DIAG
519 if ( rName == "dump_maps" )
521 ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this );
522 typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map
523 t_sorted sorted;
524 for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
526 sorted[ iPos->first ] = iPos->second;
529 for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos )
531 dumpEntry( iPos->first, iPos->second->value );
534 return Any();
536 #endif
538 ResettableMutexGuard guard( m_mutex );
539 t_map::const_iterator iFind( m_map.find( rName ) );
540 if (iFind == m_map.end())
541 return Any();
543 t_map::mapped_type pEntry = iFind->second;
544 if (! pEntry->lateInit)
545 return pEntry->value;
547 // late init singleton entry
548 Reference< XInterface > xInstance;
549 guard.clear();
553 Any usesService( getValueByName( rName + "/service" ) );
554 Any args_( getValueByName( rName + "/arguments" ) );
555 Sequence<Any> args;
556 if (args_.hasValue() && !(args_ >>= args))
558 args.realloc( 1 );
559 args[ 0 ] = args_;
562 Reference< lang::XSingleComponentFactory > xFac;
563 if (usesService >>= xFac) // try via factory
565 xInstance = args.getLength()
566 ? xFac->createInstanceWithArgumentsAndContext( args, this )
567 : xFac->createInstanceWithContext( this );
569 else
571 Reference< lang::XSingleServiceFactory > xFac2;
572 if (usesService >>= xFac2)
574 // try via old XSingleServiceFactory
575 #if OSL_DEBUG_LEVEL > 0
576 ::fprintf(
577 stderr,
578 "### omitting context for service instanciation!\n" );
579 #endif
580 xInstance = args.getLength()
581 ? xFac2->createInstanceWithArguments( args )
582 : xFac2->createInstance();
584 else if (m_xSMgr.is()) // optionally service name
586 OUString serviceName;
587 if ((usesService >>= serviceName) &&
588 !serviceName.isEmpty())
590 xInstance = args.getLength()
591 ? m_xSMgr->createInstanceWithArgumentsAndContext(
592 serviceName, args, this )
593 : m_xSMgr->createInstanceWithContext(
594 serviceName, this );
599 catch (RuntimeException &)
601 throw;
603 catch (Exception & exc) // rethrow as WrappedTargetRuntimeException
605 Any caught( getCaughtException() );
606 OUStringBuffer buf;
607 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
608 "exception occurred raising singleton \"") );
609 buf.append( rName );
610 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") );
611 buf.append( exc.Message );
612 throw lang::WrappedTargetRuntimeException(
613 buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught );
616 if (! xInstance.is())
618 throw RuntimeException(
619 "no service object raising singleton " + rName,
620 static_cast<OWeakObject *>(this) );
623 Any ret;
624 guard.reset();
625 iFind = m_map.find( rName );
626 if (iFind != m_map.end())
628 pEntry = iFind->second;
629 if (pEntry->lateInit)
631 pEntry->value <<= xInstance;
632 pEntry->lateInit = false;
633 return pEntry->value;
635 else
636 ret = pEntry->value;
638 guard.clear();
639 try_dispose( xInstance );
640 return ret;
643 //__________________________________________________________________________________________________
644 Any ComponentContext::getValueByName( OUString const & rName )
645 throw (RuntimeException)
647 // to determine the root context:
648 if ( rName == "_root" )
650 if (m_xDelegate.is())
651 return m_xDelegate->getValueByName( rName );
652 else
653 return makeAny( Reference<XComponentContext>(this) );
656 Any ret( lookupMap( rName ) );
657 if (!ret.hasValue() && m_xDelegate.is())
659 return m_xDelegate->getValueByName( rName );
661 return ret;
663 //__________________________________________________________________________________________________
664 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
665 throw (RuntimeException)
667 if ( !m_xSMgr.is() )
669 throw DeploymentException(
670 "null component context service manager",
671 static_cast<OWeakObject *>(this) );
673 return m_xSMgr;
675 //__________________________________________________________________________________________________
676 ComponentContext::~ComponentContext()
677 SAL_THROW(())
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();
688 //__________________________________________________________________________________________________
689 void ComponentContext::disposing()
691 #ifdef CONTEXT_DIAG
692 ::fprintf( stderr, "> disposing context %p\n", this );
693 #endif
695 Reference< lang::XComponent > xTDMgr, xAC; // to be disposed separately
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 )
702 t_map::mapped_type pEntry = iPos->second;
704 // service manager disposed separately
705 if (!m_xSMgr.is() ||
706 !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) ))
708 if (pEntry->lateInit)
710 // late init
711 MutexGuard guard( m_mutex );
712 if (pEntry->lateInit)
714 pEntry->value.clear(); // release factory
715 pEntry->lateInit = false;
716 continue;
720 Reference< lang::XComponent > xComp;
721 pEntry->value >>= xComp;
722 if (xComp.is())
724 if ( iPos->first == TDMGR_SINGLETON )
726 xTDMgr = xComp;
728 else if ( iPos->first == AC_SINGLETON )
730 xAC = xComp;
732 else // dispose immediately
734 xComp->dispose();
740 // dispose service manager
741 try_dispose( m_xSMgr );
742 m_xSMgr.clear();
743 // dispose ac
744 try_dispose( xAC );
745 // dispose tdmgr; revokes callback from cppu runtime
746 try_dispose( xTDMgr );
748 iPos = m_map.begin();
749 for ( ; iPos != iEnd; ++iPos )
750 delete iPos->second;
751 m_map.clear();
753 //__________________________________________________________________________________________________
754 ComponentContext::ComponentContext(
755 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
756 Reference< XComponentContext > const & xDelegate )
757 : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >(
758 m_mutex ),
759 m_xDelegate( xDelegate )
761 for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
763 ContextEntry_Init const & rEntry = pEntries[ nPos ];
765 if ( rEntry.name == SMGR_SINGLETON )
767 rEntry.value >>= m_xSMgr;
770 if (rEntry.bLateInitService)
772 // singleton entry
773 m_map[ rEntry.name ] = new ContextEntry( Any(), true );
774 // /service
775 m_map[ rEntry.name + "/service" ] = new ContextEntry( rEntry.value, false );
776 // /initial-arguments are provided as optional context entry
778 else
780 // only value, no late init factory nor string
781 m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false );
785 if (!m_xSMgr.is() && m_xDelegate.is())
787 // wrap delegate's smgr XPropertySet into new smgr
788 Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() );
789 if (xMgr.is())
791 osl_atomic_increment( &m_refCount );
794 // create new smgr based on delegate's one
795 m_xSMgr.set(
796 xMgr->createInstanceWithContext(
797 "com.sun.star.comp.stoc.OServiceManagerWrapper", xDelegate ),
798 UNO_QUERY );
799 // patch DefaultContext property of new one
800 Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY );
801 OSL_ASSERT( xProps.is() );
802 if (xProps.is())
804 Reference< XComponentContext > xThis( this );
805 xProps->setPropertyValue( "DefaultContext", makeAny( xThis ) );
808 catch (...)
810 osl_atomic_decrement( &m_refCount );
811 throw;
813 osl_atomic_decrement( &m_refCount );
814 OSL_ASSERT( m_xSMgr.is() );
820 //##################################################################################################
821 extern "C" { static void s_createComponentContext_v(va_list * pParam)
823 ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *);
824 sal_Int32 nEntries = va_arg(*pParam, sal_Int32);
825 XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *);
826 void ** ppContext = va_arg(*pParam, void **);
827 uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *);
829 Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
830 Reference<XComponentContext> xContext;
832 if (nEntries > 0)
836 ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate );
837 xContext.set(p);
838 // listen delegate for disposing, to dispose this (wrapping) context first.
839 DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p );
841 catch (Exception & exc)
843 (void) exc; // avoid warning about unused variable
844 OSL_FAIL( OUStringToOString(
845 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
846 xContext.clear();
849 else
851 xContext = xDelegate;
854 *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext));
857 Reference< XComponentContext > SAL_CALL createComponentContext(
858 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
859 Reference< XComponentContext > const & xDelegate )
860 SAL_THROW(())
862 uno::Environment curr_env(Environment::getCurrent());
863 uno::Environment source_env(rtl::OUString(CPPU_STRINGIFY(CPPU_ENV)));
865 uno::Mapping curr2source(curr_env, source_env);
866 uno::Mapping source2curr(source_env, curr_env);
868 ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries];
869 for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
871 mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
872 mapped_entries[nPos].name = pEntries[nPos].name;
874 uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
875 const_cast<void *>(pEntries[nPos].value.getValue()),
876 pEntries[nPos].value.getValueTypeRef(),
877 curr2source.get());
880 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate));
881 XComponentContext * pXComponentContext = NULL;
882 source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr);
883 delete[] mapped_entries;
885 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
890 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */