| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_cppuhelper.hxx" |
| |
| #ifdef DIAG |
| #define CONTEXT_DIAG |
| #endif |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| #include <stdio.h> |
| #endif |
| |
| #include <vector> |
| #include <hash_map> |
| #ifdef CONTEXT_DIAG |
| #include <map> |
| #endif |
| |
| #include <osl/diagnose.h> |
| #include <osl/mutex.hxx> |
| |
| #include <rtl/ustrbuf.hxx> |
| |
| #include <uno/mapping.hxx> |
| |
| #include <cppuhelper/implbase1.hxx> |
| #include <cppuhelper/compbase2.hxx> |
| #include <cppuhelper/component_context.hxx> |
| #include <cppuhelper/exc_hlp.hxx> |
| |
| #include <com/sun/star/container/XNameContainer.hpp> |
| #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> |
| #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
| #include <com/sun/star/lang/XSingleComponentFactory.hpp> |
| #include <com/sun/star/lang/XMultiComponentFactory.hpp> |
| #include <com/sun/star/lang/XComponent.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include "com/sun/star/uno/RuntimeException.hpp" |
| |
| #include <hash_map> |
| #include <memory> |
| |
| #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager" |
| #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager" |
| #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController" |
| #define AC_POLICY "/singletons/com.sun.star.security.thePolicy" |
| #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) |
| |
| |
| using namespace ::osl; |
| using namespace ::rtl; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star; |
| |
| namespace cppu |
| { |
| |
| #ifdef CONTEXT_DIAG |
| //-------------------------------------------------------------------------------------------------- |
| static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef ) |
| { |
| OSL_ASSERT( pVal ); |
| if (pTypeRef->eTypeClass == typelib_TypeClass_VOID) |
| return OUSTR("void"); |
| |
| OUStringBuffer buf( 64 ); |
| buf.append( (sal_Unicode)'(' ); |
| buf.append( pTypeRef->pTypeName ); |
| buf.append( (sal_Unicode)')' ); |
| |
| switch (pTypeRef->eTypeClass) |
| { |
| case typelib_TypeClass_INTERFACE: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( (sal_Int64)*(void **)pVal, 16 ); |
| break; |
| case typelib_TypeClass_STRUCT: |
| case typelib_TypeClass_EXCEPTION: |
| { |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); |
| typelib_TypeDescription * pTypeDescr = 0; |
| ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef ); |
| OSL_ASSERT( pTypeDescr ); |
| if (! pTypeDescr->bComplete) |
| ::typelib_typedescription_complete( &pTypeDescr ); |
| |
| typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr; |
| sal_Int32 nDescr = pCompType->nMembers; |
| |
| if (pCompType->pBaseTypeDescription) |
| { |
| buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) ); |
| if (nDescr) |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); |
| } |
| |
| typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs; |
| sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets; |
| rtl_uString ** ppMemberNames = pCompType->ppMemberNames; |
| |
| for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos ) |
| { |
| buf.append( ppMemberNames[ nPos ] ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") ); |
| typelib_TypeDescription * pMemberType = 0; |
| TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] ); |
| buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) ); |
| TYPELIB_DANGER_RELEASE( pMemberType ); |
| if (nPos < (nDescr -1)) |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); |
| } |
| |
| ::typelib_typedescription_release( pTypeDescr ); |
| |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); |
| break; |
| } |
| case typelib_TypeClass_SEQUENCE: |
| { |
| typelib_TypeDescription * pTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef ); |
| |
| uno_Sequence * pSequence = *(uno_Sequence **)pVal; |
| typelib_TypeDescription * pElementTypeDescr = 0; |
| TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); |
| |
| sal_Int32 nElementSize = pElementTypeDescr->nSize; |
| sal_Int32 nElements = pSequence->nElements; |
| |
| if (nElements) |
| { |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); |
| char * pElements = pSequence->elements; |
| for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos ) |
| { |
| buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) ); |
| if (nPos < (nElements -1)) |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); |
| } |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); |
| } |
| else |
| { |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") ); |
| } |
| TYPELIB_DANGER_RELEASE( pElementTypeDescr ); |
| TYPELIB_DANGER_RELEASE( pTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_ANY: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") ); |
| buf.append( val2str( ((uno_Any *)pVal)->pData, |
| ((uno_Any *)pVal)->pType ) ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") ); |
| break; |
| case typelib_TypeClass_TYPE: |
| buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName ); |
| break; |
| case typelib_TypeClass_STRING: |
| buf.append( (sal_Unicode)'\"' ); |
| buf.append( *(rtl_uString **)pVal ); |
| buf.append( (sal_Unicode)'\"' ); |
| break; |
| case typelib_TypeClass_ENUM: |
| { |
| typelib_TypeDescription * pTypeDescr = 0; |
| ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef ); |
| OSL_ASSERT( pTypeDescr ); |
| if (! pTypeDescr->bComplete) |
| ::typelib_typedescription_complete( &pTypeDescr ); |
| |
| sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues; |
| sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues; |
| while (nPos--) |
| { |
| if (pValues[ nPos ] == *(sal_Int32 *)pVal) |
| break; |
| } |
| if (nPos >= 0) |
| buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] ); |
| else |
| buf.append( (sal_Unicode)'?' ); |
| |
| ::typelib_typedescription_release( pTypeDescr ); |
| break; |
| } |
| case typelib_TypeClass_BOOLEAN: |
| if (*(sal_Bool *)pVal) |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") ); |
| else |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") ); |
| break; |
| case typelib_TypeClass_CHAR: |
| buf.append( (sal_Unicode)'\'' ); |
| buf.append( *(sal_Unicode *)pVal ); |
| buf.append( (sal_Unicode)'\'' ); |
| break; |
| case typelib_TypeClass_FLOAT: |
| buf.append( *(float *)pVal ); |
| break; |
| case typelib_TypeClass_DOUBLE: |
| buf.append( *(double *)pVal ); |
| break; |
| case typelib_TypeClass_BYTE: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 ); |
| break; |
| case typelib_TypeClass_SHORT: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 ); |
| break; |
| case typelib_TypeClass_UNSIGNED_SHORT: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 ); |
| break; |
| case typelib_TypeClass_LONG: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( *(sal_Int32 *)pVal, 16 ); |
| break; |
| case typelib_TypeClass_UNSIGNED_LONG: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 ); |
| break; |
| case typelib_TypeClass_HYPER: |
| case typelib_TypeClass_UNSIGNED_HYPER: |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") ); |
| #if defined(GCC) && defined(SPARC) |
| { |
| sal_Int64 aVal; |
| *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal; |
| *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1); |
| buf.append( aVal, 16 ); |
| } |
| #else |
| buf.append( *(sal_Int64 *)pVal, 16 ); |
| #endif |
| break; |
| default: |
| buf.append( (sal_Unicode)'?' ); |
| } |
| |
| return buf.makeStringAndClear(); |
| } |
| //-------------------------------------------------------------------------------------------------- |
| static void dumpEntry( OUString const & key, Any const & value ) |
| { |
| OUString val( val2str( value.getValue(), value.getValueTypeRef() ) ); |
| OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) ); |
| OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) ); |
| ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() ); |
| } |
| #endif |
| //-------------------------------------------------------------------------------------------------- |
| static inline void try_dispose( Reference< XInterface > const & xInstance ) |
| SAL_THROW( (RuntimeException) ) |
| { |
| Reference< lang::XComponent > xComp( xInstance, UNO_QUERY ); |
| if (xComp.is()) |
| { |
| xComp->dispose(); |
| } |
| } |
| //-------------------------------------------------------------------------------------------------- |
| static inline void try_dispose( Reference< lang::XComponent > const & xComp ) |
| SAL_THROW( (RuntimeException) ) |
| { |
| if (xComp.is()) |
| { |
| xComp->dispose(); |
| } |
| } |
| |
| //================================================================================================== |
| |
| class DisposingForwarder |
| : public WeakImplHelper1< lang::XEventListener > |
| { |
| Reference< lang::XComponent > m_xTarget; |
| |
| inline DisposingForwarder( Reference< lang::XComponent > const & xTarget ) |
| SAL_THROW( () ) |
| : m_xTarget( xTarget ) |
| { OSL_ASSERT( m_xTarget.is() ); } |
| public: |
| // listens at source for disposing, then disposes target |
| static inline void listen( |
| Reference< lang::XComponent > const & xSource, |
| Reference< lang::XComponent > const & xTarget ) |
| SAL_THROW( (RuntimeException) ); |
| |
| virtual void SAL_CALL disposing( lang::EventObject const & rSource ) |
| throw (RuntimeException); |
| }; |
| //__________________________________________________________________________________________________ |
| inline void DisposingForwarder::listen( |
| Reference< lang::XComponent > const & xSource, |
| Reference< lang::XComponent > const & xTarget ) |
| SAL_THROW( (RuntimeException) ) |
| { |
| if (xSource.is()) |
| { |
| xSource->addEventListener( new DisposingForwarder( xTarget ) ); |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void DisposingForwarder::disposing( lang::EventObject const & ) |
| throw (RuntimeException) |
| { |
| m_xTarget->dispose(); |
| m_xTarget.clear(); |
| } |
| |
| //================================================================================================== |
| struct MutexHolder |
| { |
| protected: |
| Mutex m_mutex; |
| }; |
| //================================================================================================== |
| |
| class ComponentContext |
| : private MutexHolder |
| , public WeakComponentImplHelper2< XComponentContext, |
| container::XNameContainer > |
| { |
| protected: |
| Reference< XComponentContext > m_xDelegate; |
| |
| struct ContextEntry |
| { |
| Any value; |
| bool lateInit; |
| |
| inline ContextEntry( Any const & value_, bool lateInit_ ) |
| : value( value_ ) |
| , lateInit( lateInit_ ) |
| {} |
| }; |
| typedef ::std::hash_map< OUString, ContextEntry * , OUStringHash > t_map; |
| t_map m_map; |
| |
| Reference< lang::XMultiComponentFactory > m_xSMgr; |
| |
| protected: |
| Any lookupMap( OUString const & rName ) |
| SAL_THROW( (RuntimeException) ); |
| |
| virtual void SAL_CALL disposing(); |
| public: |
| ComponentContext( |
| ContextEntry_Init const * pEntries, sal_Int32 nEntries, |
| Reference< XComponentContext > const & xDelegate ); |
| virtual ~ComponentContext() |
| SAL_THROW( () ); |
| |
| // XComponentContext |
| virtual Any SAL_CALL getValueByName( OUString const & rName ) |
| throw (RuntimeException); |
| virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager() |
| throw (RuntimeException); |
| |
| // XNameContainer |
| virtual void SAL_CALL insertByName( |
| OUString const & name, Any const & element ) |
| throw (lang::IllegalArgumentException, container::ElementExistException, |
| lang::WrappedTargetException, RuntimeException); |
| virtual void SAL_CALL removeByName( OUString const & name ) |
| throw (container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException); |
| // XNameReplace |
| virtual void SAL_CALL replaceByName( |
| OUString const & name, Any const & element ) |
| throw (lang::IllegalArgumentException,container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException); |
| // XNameAccess |
| virtual Any SAL_CALL getByName( OUString const & name ) |
| throw (container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException); |
| virtual Sequence<OUString> SAL_CALL getElementNames() |
| throw (RuntimeException); |
| virtual sal_Bool SAL_CALL hasByName( OUString const & name ) |
| throw (RuntimeException); |
| // XElementAccess |
| virtual Type SAL_CALL getElementType() throw (RuntimeException); |
| virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException); |
| }; |
| |
| // XNameContainer |
| //______________________________________________________________________________ |
| void ComponentContext::insertByName( |
| OUString const & name, Any const & element ) |
| throw (lang::IllegalArgumentException, container::ElementExistException, |
| lang::WrappedTargetException, RuntimeException) |
| { |
| t_map::mapped_type entry( |
| new ContextEntry( |
| element, |
| /* lateInit_: */ |
| name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && |
| !element.hasValue() ) ); |
| MutexGuard guard( m_mutex ); |
| ::std::pair<t_map::iterator, bool> insertion( m_map.insert( |
| t_map::value_type( name, entry ) ) ); |
| if (! insertion.second) |
| throw container::ElementExistException( |
| OUSTR("element already exists: ") + name, |
| static_cast<OWeakObject *>(this) ); |
| } |
| |
| //______________________________________________________________________________ |
| void ComponentContext::removeByName( OUString const & name ) |
| throw (container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException) |
| { |
| MutexGuard guard( m_mutex ); |
| t_map::iterator iFind( m_map.find( name ) ); |
| if (iFind == m_map.end()) |
| throw container::NoSuchElementException( |
| OUSTR("no such element: ") + name, |
| static_cast<OWeakObject *>(this) ); |
| |
| delete iFind->second; |
| m_map.erase(iFind); |
| } |
| |
| // XNameReplace |
| //______________________________________________________________________________ |
| void ComponentContext::replaceByName( |
| OUString const & name, Any const & element ) |
| throw (lang::IllegalArgumentException,container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException) |
| { |
| MutexGuard guard( m_mutex ); |
| t_map::const_iterator const iFind( m_map.find( name ) ); |
| if (iFind == m_map.end()) |
| throw container::NoSuchElementException( |
| OUSTR("no such element: ") + name, |
| static_cast<OWeakObject *>(this) ); |
| if (name.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("/singletons/") ) && |
| !element.hasValue()) |
| { |
| iFind->second->value.clear(); |
| iFind->second->lateInit = true; |
| } |
| else |
| { |
| iFind->second->value = element; |
| iFind->second->lateInit = false; |
| } |
| } |
| |
| // XNameAccess |
| //______________________________________________________________________________ |
| Any ComponentContext::getByName( OUString const & name ) |
| throw (container::NoSuchElementException, |
| lang::WrappedTargetException, RuntimeException) |
| { |
| return getValueByName( name ); |
| } |
| |
| //______________________________________________________________________________ |
| Sequence<OUString> ComponentContext::getElementNames() |
| throw (RuntimeException) |
| { |
| MutexGuard guard( m_mutex ); |
| Sequence<OUString> ret( m_map.size() ); |
| OUString * pret = ret.getArray(); |
| sal_Int32 pos = 0; |
| t_map::const_iterator iPos( m_map.begin() ); |
| t_map::const_iterator const iEnd( m_map.end() ); |
| for ( ; iPos != iEnd; ++iPos ) |
| pret[pos++] = iPos->first; |
| return ret; |
| } |
| |
| //______________________________________________________________________________ |
| sal_Bool ComponentContext::hasByName( OUString const & name ) |
| throw (RuntimeException) |
| { |
| MutexGuard guard( m_mutex ); |
| return m_map.find( name ) != m_map.end(); |
| } |
| |
| // XElementAccess |
| //______________________________________________________________________________ |
| Type ComponentContext::getElementType() throw (RuntimeException) |
| { |
| return ::getVoidCppuType(); |
| } |
| |
| //______________________________________________________________________________ |
| sal_Bool ComponentContext::hasElements() throw (RuntimeException) |
| { |
| MutexGuard guard( m_mutex ); |
| return ! m_map.empty(); |
| } |
| |
| //__________________________________________________________________________________________________ |
| Any ComponentContext::lookupMap( OUString const & rName ) |
| SAL_THROW( (RuntimeException) ) |
| { |
| #ifdef CONTEXT_DIAG |
| if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dump_maps") )) |
| { |
| ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this ); |
| typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map |
| t_sorted sorted; |
| for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos ) |
| { |
| sorted[ iPos->first ] = iPos->second; |
| } |
| { |
| for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos ) |
| { |
| dumpEntry( iPos->first, iPos->second->value ); |
| } |
| } |
| return Any(); |
| } |
| #endif |
| |
| ResettableMutexGuard guard( m_mutex ); |
| t_map::const_iterator iFind( m_map.find( rName ) ); |
| if (iFind == m_map.end()) |
| return Any(); |
| |
| t_map::mapped_type pEntry = iFind->second; |
| if (! pEntry->lateInit) |
| return pEntry->value; |
| |
| // late init singleton entry |
| Reference< XInterface > xInstance; |
| guard.clear(); |
| |
| try |
| { |
| Any usesService( getValueByName( rName + OUSTR("/service") ) ); |
| Any args_( getValueByName( rName + OUSTR("/arguments") ) ); |
| Sequence<Any> args; |
| if (args_.hasValue() && !(args_ >>= args)) |
| { |
| args.realloc( 1 ); |
| args[ 0 ] = args_; |
| } |
| |
| Reference< lang::XSingleComponentFactory > xFac; |
| if (usesService >>= xFac) // try via factory |
| { |
| xInstance = args.getLength() |
| ? xFac->createInstanceWithArgumentsAndContext( args, this ) |
| : xFac->createInstanceWithContext( this ); |
| } |
| else |
| { |
| Reference< lang::XSingleServiceFactory > xFac2; |
| if (usesService >>= xFac2) |
| { |
| // try via old XSingleServiceFactory |
| #if OSL_DEBUG_LEVEL > 0 |
| ::fprintf( |
| stderr, |
| "### omitting context for service instantiation!\n" ); |
| #endif |
| xInstance = args.getLength() |
| ? xFac2->createInstanceWithArguments( args ) |
| : xFac2->createInstance(); |
| } |
| else if (m_xSMgr.is()) // optionally service name |
| { |
| OUString serviceName; |
| if ((usesService >>= serviceName) && |
| serviceName.getLength()) |
| { |
| xInstance = args.getLength() |
| ? m_xSMgr->createInstanceWithArgumentsAndContext( |
| serviceName, args, this ) |
| : m_xSMgr->createInstanceWithContext( |
| serviceName, this ); |
| } |
| } |
| } |
| } |
| catch (RuntimeException &) |
| { |
| throw; |
| } |
| catch (Exception & exc) // rethrow as WrappedTargetRuntimeException |
| { |
| Any caught( getCaughtException() ); |
| OUStringBuffer buf; |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( |
| "exception occurred raising singleton \"") ); |
| buf.append( rName ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\": ") ); |
| buf.append( exc.Message ); |
| throw lang::WrappedTargetRuntimeException( |
| buf.makeStringAndClear(), static_cast<OWeakObject *>(this),caught ); |
| } |
| |
| if (! xInstance.is()) |
| { |
| throw RuntimeException( |
| OUSTR("no service object raising singleton ") + rName, |
| static_cast<OWeakObject *>(this) ); |
| } |
| |
| Any ret; |
| guard.reset(); |
| iFind = m_map.find( rName ); |
| if (iFind != m_map.end()) |
| { |
| pEntry = iFind->second; |
| if (pEntry->lateInit) |
| { |
| pEntry->value <<= xInstance; |
| pEntry->lateInit = false; |
| return pEntry->value; |
| } |
| else |
| ret = pEntry->value; |
| } |
| guard.clear(); |
| try_dispose( xInstance ); |
| return ret; |
| } |
| |
| //__________________________________________________________________________________________________ |
| Any ComponentContext::getValueByName( OUString const & rName ) |
| throw (RuntimeException) |
| { |
| // to determine the root context: |
| if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_root") )) |
| { |
| if (m_xDelegate.is()) |
| return m_xDelegate->getValueByName( rName ); |
| else |
| return makeAny( Reference<XComponentContext>(this) ); |
| } |
| |
| Any ret( lookupMap( rName ) ); |
| if (!ret.hasValue() && m_xDelegate.is()) |
| { |
| return m_xDelegate->getValueByName( rName ); |
| } |
| return ret; |
| } |
| //__________________________________________________________________________________________________ |
| Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager() |
| throw (RuntimeException) |
| { |
| return m_xSMgr; |
| } |
| //__________________________________________________________________________________________________ |
| ComponentContext::~ComponentContext() |
| SAL_THROW( () ) |
| { |
| #ifdef CONTEXT_DIAG |
| ::fprintf( stderr, "> destructed context %p\n", this ); |
| #endif |
| t_map::const_iterator iPos( m_map.begin() ); |
| t_map::const_iterator const iEnd( m_map.end() ); |
| for ( ; iPos != iEnd; ++iPos ) |
| delete iPos->second; |
| m_map.clear(); |
| } |
| //__________________________________________________________________________________________________ |
| void ComponentContext::disposing() |
| { |
| #ifdef CONTEXT_DIAG |
| ::fprintf( stderr, "> disposing context %p\n", this ); |
| #endif |
| |
| Reference< lang::XComponent > xTDMgr, xAC, xPolicy; // to be disposed separately |
| |
| // dispose all context objects |
| t_map::const_iterator iPos( m_map.begin() ); |
| t_map::const_iterator const iEnd( m_map.end() ); |
| for ( ; iPos != iEnd; ++iPos ) |
| { |
| t_map::mapped_type pEntry = iPos->second; |
| |
| // service manager disposed separately |
| if (!m_xSMgr.is() || |
| !iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) |
| { |
| if (pEntry->lateInit) |
| { |
| // late init |
| MutexGuard guard( m_mutex ); |
| if (pEntry->lateInit) |
| { |
| pEntry->value.clear(); // release factory |
| pEntry->lateInit = false; |
| continue; |
| } |
| } |
| |
| Reference< lang::XComponent > xComp; |
| pEntry->value >>= xComp; |
| if (xComp.is()) |
| { |
| if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(TDMGR_SINGLETON) )) |
| { |
| xTDMgr = xComp; |
| } |
| else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_SINGLETON) )) |
| { |
| xAC = xComp; |
| } |
| else if (iPos->first.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(AC_POLICY) )) |
| { |
| xPolicy = xComp; |
| } |
| else // dispose immediately |
| { |
| xComp->dispose(); |
| } |
| } |
| } |
| } |
| |
| // dispose service manager |
| try_dispose( m_xSMgr ); |
| m_xSMgr.clear(); |
| // dispose ac |
| try_dispose( xAC ); |
| // dispose policy |
| try_dispose( xPolicy ); |
| // dispose tdmgr; revokes callback from cppu runtime |
| try_dispose( xTDMgr ); |
| |
| iPos = m_map.begin(); |
| for ( ; iPos != iEnd; ++iPos ) |
| delete iPos->second; |
| m_map.clear(); |
| } |
| //__________________________________________________________________________________________________ |
| ComponentContext::ComponentContext( |
| ContextEntry_Init const * pEntries, sal_Int32 nEntries, |
| Reference< XComponentContext > const & xDelegate ) |
| : WeakComponentImplHelper2< XComponentContext, container::XNameContainer >( |
| m_mutex ), |
| m_xDelegate( xDelegate ) |
| { |
| for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos ) |
| { |
| ContextEntry_Init const & rEntry = pEntries[ nPos ]; |
| |
| if (rEntry.name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SMGR_SINGLETON) )) |
| { |
| rEntry.value >>= m_xSMgr; |
| } |
| |
| if (rEntry.bLateInitService) |
| { |
| // singleton entry |
| m_map[ rEntry.name ] = new ContextEntry( Any(), true ); |
| // /service |
| m_map[ rEntry.name + OUSTR("/service") ] = new ContextEntry( rEntry.value, false ); |
| // /initial-arguments are provided as optional context entry |
| } |
| else |
| { |
| // only value, no late init factory nor string |
| m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false ); |
| } |
| } |
| |
| if (!m_xSMgr.is() && m_xDelegate.is()) |
| { |
| // wrap delegate's smgr XPropertySet into new smgr |
| Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() ); |
| if (xMgr.is()) |
| { |
| osl_incrementInterlockedCount( &m_refCount ); |
| try |
| { |
| // create new smgr based on delegate's one |
| m_xSMgr.set( |
| xMgr->createInstanceWithContext( |
| OUSTR("com.sun.star.comp.stoc.OServiceManagerWrapper"), xDelegate ), |
| UNO_QUERY ); |
| // patch DefaultContext property of new one |
| Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY ); |
| OSL_ASSERT( xProps.is() ); |
| if (xProps.is()) |
| { |
| Reference< XComponentContext > xThis( this ); |
| xProps->setPropertyValue( OUSTR("DefaultContext"), makeAny( xThis ) ); |
| } |
| } |
| catch (...) |
| { |
| osl_decrementInterlockedCount( &m_refCount ); |
| throw; |
| } |
| osl_decrementInterlockedCount( &m_refCount ); |
| OSL_ASSERT( m_xSMgr.is() ); |
| } |
| } |
| } |
| |
| |
| //################################################################################################## |
| extern "C" { static void s_createComponentContext_v(va_list * pParam) |
| { |
| ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *); |
| sal_Int32 nEntries = va_arg(*pParam, sal_Int32); |
| XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *); |
| void ** ppContext = va_arg(*pParam, void **); |
| uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *); |
| |
| Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE); |
| Reference<XComponentContext> xContext; |
| |
| if (nEntries > 0) |
| { |
| try |
| { |
| ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate ); |
| xContext.set(p); |
| // listen delegate for disposing, to dispose this (wrapping) context first. |
| DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p ); |
| } |
| catch (Exception & exc) |
| { |
| (void) exc; // avoid warning about unused variable |
| OSL_ENSURE( 0, OUStringToOString( |
| exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| xContext.clear(); |
| } |
| } |
| else |
| { |
| xContext = xDelegate; |
| } |
| |
| delete[] pEntries; |
| |
| *ppContext = pTarget2curr->mapInterface(xContext.get(), ::getCppuType(&xContext)); |
| }} |
| |
| Reference< XComponentContext > SAL_CALL createComponentContext( |
| ContextEntry_Init const * pEntries, sal_Int32 nEntries, |
| Reference< XComponentContext > const & xDelegate ) |
| SAL_THROW( () ) |
| { |
| uno::Environment curr_env(Environment::getCurrent()); |
| uno::Environment source_env(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CPPU_STRINGIFY(CPPU_ENV)))); |
| |
| uno::Mapping curr2source(curr_env, source_env); |
| uno::Mapping source2curr(source_env, curr_env); |
| |
| ContextEntry_Init * mapped_entries = new ContextEntry_Init[nEntries]; |
| for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos) |
| { |
| mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService; |
| mapped_entries[nPos].name = pEntries[nPos].name; |
| |
| uno_type_any_constructAndConvert(&mapped_entries[nPos].value, |
| const_cast<void *>(pEntries[nPos].value.getValue()), |
| pEntries[nPos].value.getValueTypeRef(), |
| curr2source.get()); |
| } |
| |
| void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), ::getCppuType(&xDelegate)); |
| XComponentContext * pXComponentContext = NULL; |
| source_env.invoke(s_createComponentContext_v, mapped_entries, nEntries, mapped_delegate, &pXComponentContext, &source2curr); |
| |
| return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE); |
| } |
| |
| } |