Bump version to 5.0-14
[LibreOffice.git] / cppuhelper / source / component_context.cxx
blob7451daf4cf568d9bfa118220e1a9c99d95e5dce6
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 <unordered_map>
30 #ifdef CONTEXT_DIAG
31 #include <map>
32 #endif
34 #include <osl/diagnose.h>
35 #include <osl/mutex.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <sal/log.hxx>
40 #include <uno/lbnames.h>
41 #include <uno/mapping.hxx>
43 #include <cppuhelper/implbase1.hxx>
44 #include <cppuhelper/compbase.hxx>
45 #include <cppuhelper/component_context.hxx>
46 #include <cppuhelper/exc_hlp.hxx>
48 #include <com/sun/star/container/XNameContainer.hpp>
49 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
50 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
51 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
52 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
53 #include <com/sun/star/lang/XComponent.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/uno/DeploymentException.hpp>
56 #include <com/sun/star/uno/RuntimeException.hpp>
58 #include <boost/scoped_array.hpp>
60 #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager"
61 #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager"
62 #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController"
64 using namespace ::osl;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star;
68 using rtl::OUString;
69 using rtl::OUStringBuffer;
70 using rtl::OUStringHash;
72 namespace cppu
75 #ifdef CONTEXT_DIAG
77 static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef )
79 OSL_ASSERT( pVal );
80 if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
81 return "void";
83 OUStringBuffer buf( 64 );
84 buf.append( "(" + pTypeRef->pTypeName + ")" );
86 switch (pTypeRef->eTypeClass)
88 case typelib_TypeClass_INTERFACE:
89 buf.append( "0x" );
90 buf.append( (sal_Int64)*(void **)pVal, 16 );
91 break;
92 case typelib_TypeClass_STRUCT:
93 case typelib_TypeClass_EXCEPTION:
95 buf.append( "{ " );
96 typelib_TypeDescription * pTypeDescr = 0;
97 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
98 OSL_ASSERT( pTypeDescr );
99 if (! pTypeDescr->bComplete)
100 ::typelib_typedescription_complete( &pTypeDescr );
102 typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
103 sal_Int32 nDescr = pCompType->nMembers;
105 if (pCompType->pBaseTypeDescription)
107 buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) );
108 if (nDescr)
109 buf.append( ", " );
112 typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
113 sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
114 rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
116 for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
118 buf.append( ppMemberNames[ nPos ] );
119 buf.append( " = " );
120 typelib_TypeDescription * pMemberType = 0;
121 TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] );
122 buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) );
123 TYPELIB_DANGER_RELEASE( pMemberType );
124 if (nPos < (nDescr -1))
125 buf.append( ", " );
128 ::typelib_typedescription_release( pTypeDescr );
130 buf.append( " }" );
131 break;
133 case typelib_TypeClass_SEQUENCE:
135 typelib_TypeDescription * pTypeDescr = 0;
136 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
138 uno_Sequence * pSequence = *(uno_Sequence **)pVal;
139 typelib_TypeDescription * pElementTypeDescr = 0;
140 TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
142 sal_Int32 nElementSize = pElementTypeDescr->nSize;
143 sal_Int32 nElements = pSequence->nElements;
145 if (nElements)
147 buf.append( "{ " );
148 char * pElements = pSequence->elements;
149 for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
151 buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) );
152 if (nPos < (nElements -1))
153 buf.append( ", " );
155 buf.append( " }" );
157 else
159 buf.append( "{}" );
161 TYPELIB_DANGER_RELEASE( pElementTypeDescr );
162 TYPELIB_DANGER_RELEASE( pTypeDescr );
163 break;
165 case typelib_TypeClass_ANY:
166 buf.append( "{ " );
167 buf.append( val2str( ((uno_Any *)pVal)->pData,
168 ((uno_Any *)pVal)->pType ) );
169 buf.append( " }" );
170 break;
171 case typelib_TypeClass_TYPE:
172 buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
173 break;
174 case typelib_TypeClass_STRING:
175 buf.append( '\"' );
176 buf.append( *(rtl_uString **)pVal );
177 buf.append( '\"' );
178 break;
179 case typelib_TypeClass_ENUM:
181 typelib_TypeDescription * pTypeDescr = 0;
182 ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
183 OSL_ASSERT( pTypeDescr );
184 if (! pTypeDescr->bComplete)
185 ::typelib_typedescription_complete( &pTypeDescr );
187 sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
188 sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
189 while (nPos--)
191 if (pValues[ nPos ] == *(sal_Int32 *)pVal)
192 break;
194 if (nPos >= 0)
195 buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] );
196 else
197 buf.append( '?' );
199 ::typelib_typedescription_release( pTypeDescr );
200 break;
202 case typelib_TypeClass_BOOLEAN:
203 if (*(sal_Bool *)pVal)
204 buf.append( "true" );
205 else
206 buf.append( "false" );
207 break;
208 case typelib_TypeClass_CHAR:
209 buf.append( '\'' );
210 buf.append( *(sal_Unicode *)pVal );
211 buf.append( '\'' );
212 break;
213 case typelib_TypeClass_FLOAT:
214 buf.append( *(float *)pVal );
215 break;
216 case typelib_TypeClass_DOUBLE:
217 buf.append( *(double *)pVal );
218 break;
219 case typelib_TypeClass_BYTE:
220 buf.append( "0x" );
221 buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
222 break;
223 case typelib_TypeClass_SHORT:
224 buf.append( "0x" );
225 buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
226 break;
227 case typelib_TypeClass_UNSIGNED_SHORT:
228 buf.append( "0x" );
229 buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
230 break;
231 case typelib_TypeClass_LONG:
232 buf.append( "0x" );
233 buf.append( *(sal_Int32 *)pVal, 16 );
234 break;
235 case typelib_TypeClass_UNSIGNED_LONG:
236 buf.append( "0x" );
237 buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
238 break;
239 case typelib_TypeClass_HYPER:
240 case typelib_TypeClass_UNSIGNED_HYPER:
241 buf.append( "0x" );
242 #if defined(__GNUC__) && defined(SPARC)
243 // I guess this really should check if there are strict alignment
244 // requirements, not just "GCC on SPARC".
246 sal_Int64 aVal;
247 *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
248 *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
249 buf.append( aVal, 16 );
251 #else
252 buf.append( *(sal_Int64 *)pVal, 16 );
253 #endif
254 break;
255 default:
256 buf.append( '?' );
259 return buf.makeStringAndClear();
262 static void dumpEntry( OUString const & key, Any const & value )
264 OUString val( val2str( value.getValue(), value.getValueTypeRef() ) );
265 OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) );
266 OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) );
267 ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() );
269 #endif
271 static inline void try_dispose( Reference< XInterface > const & xInstance )
273 Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
274 if (xComp.is())
276 xComp->dispose();
280 static inline void try_dispose( Reference< lang::XComponent > const & xComp )
282 if (xComp.is())
284 xComp->dispose();
290 class DisposingForwarder
291 : public WeakImplHelper1< lang::XEventListener >
293 Reference< lang::XComponent > m_xTarget;
295 inline DisposingForwarder( Reference< lang::XComponent > const & xTarget )
296 : m_xTarget( xTarget )
297 { OSL_ASSERT( m_xTarget.is() ); }
298 public:
299 // listens at source for disposing, then disposes target
300 static inline void listen(
301 Reference< lang::XComponent > const & xSource,
302 Reference< lang::XComponent > const & xTarget );
304 virtual void SAL_CALL disposing( lang::EventObject const & rSource )
305 throw (RuntimeException, std::exception) SAL_OVERRIDE;
308 inline void DisposingForwarder::listen(
309 Reference< lang::XComponent > const & xSource,
310 Reference< lang::XComponent > const & xTarget )
312 if (xSource.is())
314 xSource->addEventListener( new DisposingForwarder( xTarget ) );
318 void DisposingForwarder::disposing( lang::EventObject const & )
319 throw (RuntimeException, std::exception)
321 m_xTarget->dispose();
322 m_xTarget.clear();
326 struct MutexHolder
328 protected:
329 Mutex m_mutex;
333 class ComponentContext
334 : private MutexHolder
335 , public WeakComponentImplHelper< XComponentContext,
336 container::XNameContainer >
338 protected:
339 Reference< XComponentContext > m_xDelegate;
341 struct ContextEntry
343 Any value;
344 bool lateInit;
346 inline ContextEntry( Any const & value_, bool lateInit_ )
347 : value( value_ )
348 , lateInit( lateInit_ )
351 typedef std::unordered_map< OUString, ContextEntry * , OUStringHash > t_map;
352 t_map m_map;
354 Reference< lang::XMultiComponentFactory > m_xSMgr;
356 protected:
357 Any lookupMap( OUString const & rName );
359 virtual void SAL_CALL disposing() SAL_OVERRIDE;
360 public:
361 ComponentContext(
362 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
363 Reference< XComponentContext > const & xDelegate );
364 virtual ~ComponentContext();
366 // XComponentContext
367 virtual Any SAL_CALL getValueByName( OUString const & rName )
368 throw (RuntimeException, std::exception) SAL_OVERRIDE;
369 virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
370 throw (RuntimeException, std::exception) SAL_OVERRIDE;
372 // XNameContainer
373 virtual void SAL_CALL insertByName(
374 OUString const & name, Any const & element )
375 throw (lang::IllegalArgumentException, container::ElementExistException,
376 lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
377 virtual void SAL_CALL removeByName( OUString const & name )
378 throw (container::NoSuchElementException,
379 lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
380 // XNameReplace
381 virtual void SAL_CALL replaceByName(
382 OUString const & name, Any const & element )
383 throw (lang::IllegalArgumentException,container::NoSuchElementException,
384 lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
385 // XNameAccess
386 virtual Any SAL_CALL getByName( OUString const & name )
387 throw (container::NoSuchElementException,
388 lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
389 virtual Sequence<OUString> SAL_CALL getElementNames()
390 throw (RuntimeException, std::exception) SAL_OVERRIDE;
391 virtual sal_Bool SAL_CALL hasByName( OUString const & name )
392 throw (RuntimeException, std::exception) SAL_OVERRIDE;
393 // XElementAccess
394 virtual Type SAL_CALL getElementType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
395 virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException, std::exception) SAL_OVERRIDE;
398 // XNameContainer
400 void ComponentContext::insertByName(
401 OUString const & name, Any const & element )
402 throw (lang::IllegalArgumentException, container::ElementExistException,
403 lang::WrappedTargetException, RuntimeException, std::exception)
405 t_map::mapped_type entry(
406 new ContextEntry(
407 element,
408 /* lateInit_: */
409 name.startsWith( "/singletons/" ) &&
410 !element.hasValue() ) );
411 MutexGuard guard( m_mutex );
412 ::std::pair<t_map::iterator, bool> insertion( m_map.insert(
413 t_map::value_type( name, entry ) ) );
414 if (! insertion.second)
415 throw container::ElementExistException(
416 "element already exists: " + name,
417 static_cast<OWeakObject *>(this) );
421 void ComponentContext::removeByName( OUString const & name )
422 throw (container::NoSuchElementException,
423 lang::WrappedTargetException, RuntimeException, std::exception)
425 MutexGuard guard( m_mutex );
426 t_map::iterator iFind( m_map.find( name ) );
427 if (iFind == m_map.end())
428 throw container::NoSuchElementException(
429 "no such element: " + name,
430 static_cast<OWeakObject *>(this) );
432 delete iFind->second;
433 m_map.erase(iFind);
436 // XNameReplace
438 void ComponentContext::replaceByName(
439 OUString const & name, Any const & element )
440 throw (lang::IllegalArgumentException,container::NoSuchElementException,
441 lang::WrappedTargetException, RuntimeException, std::exception)
443 MutexGuard guard( m_mutex );
444 t_map::const_iterator const iFind( m_map.find( name ) );
445 if (iFind == m_map.end())
446 throw container::NoSuchElementException(
447 "no such element: " + name,
448 static_cast<OWeakObject *>(this) );
449 if (name.startsWith( "/singletons/" ) &&
450 !element.hasValue())
452 iFind->second->value.clear();
453 iFind->second->lateInit = true;
455 else
457 iFind->second->value = element;
458 iFind->second->lateInit = false;
462 // XNameAccess
464 Any ComponentContext::getByName( OUString const & name )
465 throw (container::NoSuchElementException,
466 lang::WrappedTargetException, RuntimeException, std::exception)
468 return getValueByName( name );
472 Sequence<OUString> ComponentContext::getElementNames()
473 throw (RuntimeException, std::exception)
475 MutexGuard guard( m_mutex );
476 Sequence<OUString> ret( m_map.size() );
477 OUString * pret = ret.getArray();
478 sal_Int32 pos = 0;
479 t_map::const_iterator iPos( m_map.begin() );
480 t_map::const_iterator const iEnd( m_map.end() );
481 for ( ; iPos != iEnd; ++iPos )
482 pret[pos++] = iPos->first;
483 return ret;
487 sal_Bool ComponentContext::hasByName( OUString const & name )
488 throw (RuntimeException, std::exception)
490 MutexGuard guard( m_mutex );
491 return m_map.find( name ) != m_map.end();
494 // XElementAccess
496 Type ComponentContext::getElementType() throw (RuntimeException, std::exception)
498 return cppu::UnoType<void>::get();
502 sal_Bool ComponentContext::hasElements() throw (RuntimeException, std::exception)
504 MutexGuard guard( m_mutex );
505 return ! m_map.empty();
509 Any ComponentContext::lookupMap( OUString const & rName )
511 #ifdef CONTEXT_DIAG
512 if ( rName == "dump_maps" )
514 ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this );
515 typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map
516 t_sorted sorted;
517 for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
519 sorted[ iPos->first ] = iPos->second;
522 for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos )
524 dumpEntry( iPos->first, iPos->second->value );
527 return Any();
529 #endif
531 ResettableMutexGuard guard( m_mutex );
532 t_map::const_iterator iFind( m_map.find( rName ) );
533 if (iFind == m_map.end())
534 return Any();
536 t_map::mapped_type pEntry = iFind->second;
537 if (! pEntry->lateInit)
538 return pEntry->value;
540 // late init singleton entry
541 Reference< XInterface > xInstance;
542 guard.clear();
546 Any usesService( getValueByName( rName + "/service" ) );
547 Any args_( getValueByName( rName + "/arguments" ) );
548 Sequence<Any> args;
549 if (args_.hasValue() && !(args_ >>= args))
551 args.realloc( 1 );
552 args[ 0 ] = args_;
555 Reference< lang::XSingleComponentFactory > xFac;
556 if (usesService >>= xFac) // try via factory
558 xInstance = args.getLength()
559 ? xFac->createInstanceWithArgumentsAndContext( args, this )
560 : xFac->createInstanceWithContext( this );
562 else
564 Reference< lang::XSingleServiceFactory > xFac2;
565 if (usesService >>= xFac2)
567 // try via old XSingleServiceFactory
568 #if OSL_DEBUG_LEVEL > 0
569 ::fprintf(
570 stderr,
571 "### omitting context for service instantiation!\n" );
572 #endif
573 xInstance = args.getLength()
574 ? xFac2->createInstanceWithArguments( args )
575 : xFac2->createInstance();
577 else if (m_xSMgr.is()) // optionally service name
579 OUString serviceName;
580 if ((usesService >>= serviceName) &&
581 !serviceName.isEmpty())
583 xInstance = args.getLength()
584 ? m_xSMgr->createInstanceWithArgumentsAndContext(
585 serviceName, args, this )
586 : m_xSMgr->createInstanceWithContext(
587 serviceName, this );
592 catch (const RuntimeException &)
594 throw;
596 catch (const Exception & exc)
598 SAL_WARN(
599 "cppuhelper",
600 "exception occurred raising singleton \"" << rName << "\": "
601 << exc.Message);
604 SAL_WARN_IF(!xInstance.is(),
605 "cppuhelper", "no service object raising singleton " << rName);
607 Any ret;
608 guard.reset();
609 iFind = m_map.find( rName );
610 if (iFind != m_map.end())
612 pEntry = iFind->second;
613 if (pEntry->lateInit)
615 pEntry->value <<= xInstance;
616 pEntry->lateInit = false;
617 return pEntry->value;
619 else
620 ret = pEntry->value;
622 guard.clear();
623 try_dispose( xInstance );
624 return ret;
628 Any ComponentContext::getValueByName( OUString const & rName )
629 throw (RuntimeException, std::exception)
631 // to determine the root context:
632 if ( rName == "_root" )
634 if (m_xDelegate.is())
635 return m_xDelegate->getValueByName( rName );
636 else
637 return makeAny( Reference<XComponentContext>(this) );
640 Any ret( lookupMap( rName ) );
641 if (!ret.hasValue() && m_xDelegate.is())
643 return m_xDelegate->getValueByName( rName );
645 return ret;
648 Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
649 throw (RuntimeException, std::exception)
651 if ( !m_xSMgr.is() )
653 throw DeploymentException(
654 "null component context service manager",
655 static_cast<OWeakObject *>(this) );
657 return m_xSMgr;
660 ComponentContext::~ComponentContext()
662 #ifdef CONTEXT_DIAG
663 ::fprintf( stderr, "> destructed context %p\n", this );
664 #endif
665 t_map::const_iterator iPos( m_map.begin() );
666 t_map::const_iterator const iEnd( m_map.end() );
667 for ( ; iPos != iEnd; ++iPos )
668 delete iPos->second;
669 m_map.clear();
672 void ComponentContext::disposing()
674 #ifdef CONTEXT_DIAG
675 ::fprintf( stderr, "> disposing context %p\n", this );
676 #endif
678 Reference< lang::XComponent > xTDMgr, xAC; // to be disposed separately
680 // dispose all context objects
681 t_map::const_iterator iPos( m_map.begin() );
682 t_map::const_iterator const iEnd( m_map.end() );
683 for ( ; iPos != iEnd; ++iPos )
685 t_map::mapped_type pEntry = iPos->second;
687 // service manager disposed separately
688 if (!m_xSMgr.is() ||
689 !iPos->first.startsWith( SMGR_SINGLETON ))
691 if (pEntry->lateInit)
693 // late init
694 MutexGuard guard( m_mutex );
695 if (pEntry->lateInit)
697 pEntry->value.clear(); // release factory
698 pEntry->lateInit = false;
699 continue;
703 Reference< lang::XComponent > xComp;
704 pEntry->value >>= xComp;
705 if (xComp.is())
707 if ( iPos->first == TDMGR_SINGLETON )
709 xTDMgr = xComp;
711 else if ( iPos->first == AC_SINGLETON )
713 xAC = xComp;
715 else // dispose immediately
717 xComp->dispose();
723 // dispose service manager
724 try_dispose( m_xSMgr );
725 m_xSMgr.clear();
726 // dispose ac
727 try_dispose( xAC );
728 // dispose tdmgr; revokes callback from cppu runtime
729 try_dispose( xTDMgr );
731 iPos = m_map.begin();
732 for ( ; iPos != iEnd; ++iPos )
733 delete iPos->second;
734 m_map.clear();
736 // Hack to terminate any JNI bridge's AsynchronousFinalizer thread (as JNI
737 // proxies get finalized with arbitrary delay, so the bridge typically does
738 // not dispose itself early enough before the process exits):
739 uno_Environment ** envs;
740 sal_Int32 envCount;
741 uno_getRegisteredEnvironments(
742 &envs, &envCount, &rtl_allocateMemory, OUString("java").pData);
743 assert(envCount >= 0);
744 assert(envCount == 0 || envs != nullptr);
745 if (envs) {
746 for (sal_Int32 i = 0; i != envCount; ++i) {
747 assert(envs[i] != nullptr);
748 assert(envs[i]->dispose != nullptr);
749 (*envs[i]->dispose)(envs[i]);
751 rtl_freeMemory(envs);
755 ComponentContext::ComponentContext(
756 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
757 Reference< XComponentContext > const & xDelegate )
758 : WeakComponentImplHelper( 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() );
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(), cppu::UnoType<decltype(xContext)>::get());
857 Reference< XComponentContext > SAL_CALL createComponentContext(
858 ContextEntry_Init const * pEntries, sal_Int32 nEntries,
859 Reference< XComponentContext > const & xDelegate )
861 uno::Environment curr_env(Environment::getCurrent());
862 uno::Environment source_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
864 uno::Mapping curr2source(curr_env, source_env);
865 uno::Mapping source2curr(source_env, curr_env);
867 boost::scoped_array<ContextEntry_Init> mapped_entries(new ContextEntry_Init[nEntries]);
868 for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
870 mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
871 mapped_entries[nPos].name = pEntries[nPos].name;
873 uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
874 const_cast<void *>(pEntries[nPos].value.getValue()),
875 pEntries[nPos].value.getValueTypeRef(),
876 curr2source.get());
879 void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), cppu::UnoType<decltype(xDelegate)>::get());
880 XComponentContext * pXComponentContext = NULL;
881 source_env.invoke(s_createComponentContext_v, mapped_entries.get(), nEntries, mapped_delegate, &pXComponentContext, &source2curr);
882 mapped_entries.reset();
884 return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
889 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */