summaryrefslogtreecommitdiff
path: root/cppuhelper/source/component_context.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cppuhelper/source/component_context.cxx')
-rw-r--r--cppuhelper/source/component_context.cxx902
1 files changed, 902 insertions, 0 deletions
diff --git a/cppuhelper/source/component_context.cxx b/cppuhelper/source/component_context.cxx
new file mode 100644
index 000000000000..306490aa1616
--- /dev/null
+++ b/cppuhelper/source/component_context.cxx
@@ -0,0 +1,902 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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 instanciation!\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 occured 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);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */