summaryrefslogtreecommitdiff
path: root/cppu/source/uno/lbenv.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cppu/source/uno/lbenv.cxx')
-rw-r--r--cppu/source/uno/lbenv.cxx1182
1 files changed, 1182 insertions, 0 deletions
diff --git a/cppu/source/uno/lbenv.cxx b/cppu/source/uno/lbenv.cxx
new file mode 100644
index 000000000000..21d16c5b9148
--- /dev/null
+++ b/cppu/source/uno/lbenv.cxx
@@ -0,0 +1,1182 @@
+/*************************************************************************
+ *
+ * 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_cppu.hxx"
+
+#include "cppu/EnvDcp.hxx"
+
+#include "sal/alloca.h"
+#include "osl/diagnose.h"
+#include "osl/interlck.h"
+#include "osl/mutex.hxx"
+#include "osl/module.h"
+#include "osl/process.h"
+#include "rtl/process.h"
+#include "rtl/unload.h"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "rtl/ustrbuf.hxx"
+#include "rtl/instance.hxx"
+#include "typelib/typedescription.h"
+#include "uno/dispatcher.h"
+#include "uno/environment.h"
+#include "uno/lbnames.h"
+#include "prim.hxx"
+#include "destr.hxx"
+#include "loadmodule.hxx"
+
+#include <hash_map>
+#include <vector>
+#include <stdio.h>
+
+
+using ::rtl::OUString;
+
+namespace
+{
+
+//------------------------------------------------------------------------------
+inline static bool td_equals( typelib_InterfaceTypeDescription * pTD1,
+ typelib_InterfaceTypeDescription * pTD2 )
+{
+ return (pTD1 == pTD2 ||
+ (((typelib_TypeDescription *)pTD1)->pTypeName->length ==
+ ((typelib_TypeDescription *)pTD2)->pTypeName->length &&
+ ::rtl_ustr_compare(
+ ((typelib_TypeDescription *) pTD1)->pTypeName->buffer,
+ ((typelib_TypeDescription *) pTD2)->pTypeName->buffer ) == 0));
+}
+
+struct ObjectEntry;
+struct uno_DefaultEnvironment;
+
+//------------------------------------------------------------------------------
+struct InterfaceEntry
+{
+ sal_Int32 refCount;
+ void * pInterface;
+ uno_freeProxyFunc fpFreeProxy;
+ typelib_InterfaceTypeDescription * pTypeDescr;
+};
+
+struct ObjectEntry
+{
+ OUString oid;
+ sal_Int32 nRef;
+ ::std::vector< InterfaceEntry > aInterfaces;
+ bool mixedObject;
+
+ inline ObjectEntry( const OUString & rOId_ );
+
+ inline void append(
+ uno_DefaultEnvironment * pEnv,
+ void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
+ uno_freeProxyFunc fpFreeProxy );
+ inline InterfaceEntry * find(
+ typelib_InterfaceTypeDescription * pTypeDescr );
+ inline sal_Int32 find( void * iface_ptr, ::std::size_t pos );
+};
+
+//------------------------------------------------------------------------------
+struct FctPtrHash :
+ public ::std::unary_function< const void *, ::std::size_t >
+{
+ ::std::size_t operator () ( const void * pKey ) const
+ { return (::std::size_t) pKey; }
+};
+
+//------------------------------------------------------------------------------
+struct FctOUStringHash :
+ public ::std::unary_function< const OUString &, ::std::size_t >
+{
+ ::std::size_t operator () ( const OUString & rKey ) const
+ { return rKey.hashCode(); }
+};
+
+// mapping from environment name to environment
+typedef ::std::hash_map<
+ OUString, uno_Environment *, FctOUStringHash,
+ ::std::equal_to< OUString > > OUString2EnvironmentMap;
+
+// mapping from ptr to object entry
+typedef ::std::hash_map<
+ void *, ObjectEntry *, FctPtrHash,
+ ::std::equal_to< void * > > Ptr2ObjectMap;
+// mapping from oid to object entry
+typedef ::std::hash_map<
+ OUString, ObjectEntry *, FctOUStringHash,
+ ::std::equal_to< OUString > > OId2ObjectMap;
+
+
+//==============================================================================
+struct EnvironmentsData
+{
+ ::osl::Mutex mutex;
+ OUString2EnvironmentMap aName2EnvMap;
+
+ ~EnvironmentsData();
+
+ inline void getEnvironment(
+ uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext );
+ inline void registerEnvironment( uno_Environment ** ppEnv );
+ inline void getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen,
+ uno_memAlloc memAlloc, const OUString & rEnvDcp );
+};
+
+namespace
+{
+ struct theEnvironmentsData : public rtl::Static< EnvironmentsData, theEnvironmentsData > {};
+}
+
+//==============================================================================
+struct uno_DefaultEnvironment : public uno_ExtEnvironment
+{
+ sal_Int32 nRef;
+ sal_Int32 nWeakRef;
+
+ ::osl::Mutex mutex;
+ Ptr2ObjectMap aPtr2ObjectMap;
+ OId2ObjectMap aOId2ObjectMap;
+
+ uno_DefaultEnvironment(
+ const OUString & rEnvDcp_, void * pContext_ );
+ ~uno_DefaultEnvironment();
+};
+
+//______________________________________________________________________________
+inline ObjectEntry::ObjectEntry( OUString const & rOId_ )
+ : oid( rOId_ ),
+ nRef( 0 ),
+ mixedObject( false )
+{
+ aInterfaces.reserve( 2 );
+}
+
+//______________________________________________________________________________
+inline void ObjectEntry::append(
+ uno_DefaultEnvironment * pEnv,
+ void * pInterface, typelib_InterfaceTypeDescription * pTypeDescr,
+ uno_freeProxyFunc fpFreeProxy )
+{
+ InterfaceEntry aNewEntry;
+ if (! fpFreeProxy)
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ aNewEntry.refCount = 1;
+ aNewEntry.pInterface = pInterface;
+ aNewEntry.fpFreeProxy = fpFreeProxy;
+ typelib_typedescription_acquire( (typelib_TypeDescription *) pTypeDescr );
+ aNewEntry.pTypeDescr = pTypeDescr;
+
+ ::std::pair< Ptr2ObjectMap::iterator, bool > insertion(
+ pEnv->aPtr2ObjectMap.insert( Ptr2ObjectMap::value_type(
+ pInterface, this ) ) );
+ OSL_ASSERT( insertion.second ||
+ (find( pInterface, 0 ) >= 0 &&
+ // points to the same object entry:
+ insertion.first->second == this) );
+ aInterfaces.push_back( aNewEntry );
+}
+
+//______________________________________________________________________________
+inline InterfaceEntry * ObjectEntry::find(
+ typelib_InterfaceTypeDescription * pTypeDescr_ )
+{
+ OSL_ASSERT( ! aInterfaces.empty() );
+ if (aInterfaces.empty())
+ return 0;
+
+ // shortcut common case:
+ OUString const & type_name =
+ OUString::unacquired(
+ &((typelib_TypeDescription *) pTypeDescr_)->pTypeName );
+ if (type_name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ))
+ {
+ return &aInterfaces[ 0 ];
+ }
+
+ ::std::size_t nSize = aInterfaces.size();
+ for ( ::std::size_t nPos = 0; nPos < nSize; ++nPos )
+ {
+ typelib_InterfaceTypeDescription * pITD =
+ aInterfaces[ nPos ].pTypeDescr;
+ while (pITD)
+ {
+ if (td_equals( pITD, pTypeDescr_ ))
+ return &aInterfaces[ nPos ];
+ pITD = pITD->pBaseTypeDescription;
+ }
+ }
+ return 0;
+}
+
+//______________________________________________________________________________
+inline sal_Int32 ObjectEntry::find(
+ void * iface_ptr, ::std::size_t pos )
+{
+ ::std::size_t size = aInterfaces.size();
+ for ( ; pos < size; ++pos )
+ {
+ if (aInterfaces[ pos ].pInterface == iface_ptr)
+ return pos;
+ }
+ return -1;
+}
+
+extern "C"
+{
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_registerInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
+ OUString const & rOId = OUString::unacquired( &pOId );
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ // try to insert dummy 0:
+ std::pair<OId2ObjectMap::iterator, bool> const insertion(
+ that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) );
+ if (insertion.second)
+ {
+ ObjectEntry * pOEntry = new ObjectEntry( rOId );
+ insertion.first->second = pOEntry;
+ ++pOEntry->nRef; // another register call on object
+ pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
+ }
+ else // object entry exists
+ {
+ ObjectEntry * pOEntry = insertion.first->second;
+ ++pOEntry->nRef; // another register call on object
+ InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
+
+ if (pIEntry) // type entry exists
+ {
+ ++pIEntry->refCount;
+ if (pIEntry->pInterface != *ppInterface)
+ {
+ void * pInterface = pIEntry->pInterface;
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ guard.clear();
+ (*pEnv->releaseInterface)( pEnv, *ppInterface );
+ *ppInterface = pInterface;
+ }
+ }
+ else
+ {
+ pOEntry->append( that, *ppInterface, pTypeDescr, 0 );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_registerProxyInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface, uno_freeProxyFunc freeProxy,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr && freeProxy,
+ "### null ptr!" );
+ OUString const & rOId = OUString::unacquired( &pOId );
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ // try to insert dummy 0:
+ std::pair<OId2ObjectMap::iterator, bool> const insertion(
+ that->aOId2ObjectMap.insert( OId2ObjectMap::value_type( rOId, 0 ) ) );
+ if (insertion.second)
+ {
+ ObjectEntry * pOEntry = new ObjectEntry( rOId );
+ insertion.first->second = pOEntry;
+ ++pOEntry->nRef; // another register call on object
+ pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
+ }
+ else // object entry exists
+ {
+ ObjectEntry * pOEntry = insertion.first->second;
+
+ // first registration was an original, then registerProxyInterface():
+ pOEntry->mixedObject |=
+ (!pOEntry->aInterfaces.empty() &&
+ pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0);
+
+ ++pOEntry->nRef; // another register call on object
+ InterfaceEntry * pIEntry = pOEntry->find( pTypeDescr );
+
+ if (pIEntry) // type entry exists
+ {
+ if (pIEntry->pInterface == *ppInterface)
+ {
+ ++pIEntry->refCount;
+ }
+ else
+ {
+ void * pInterface = pIEntry->pInterface;
+ (*pEnv->acquireInterface)( pEnv, pInterface );
+ --pOEntry->nRef; // manual revoke of proxy to be freed
+ guard.clear();
+ (*freeProxy)( pEnv, *ppInterface );
+ *ppInterface = pInterface;
+ }
+ }
+ else
+ {
+ pOEntry->append( that, *ppInterface, pTypeDescr, freeProxy );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL s_stub_defenv_revokeInterface(va_list * pParam)
+{
+ uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *);
+ void * pInterface = va_arg(*pParam, void *);
+
+ OSL_ENSURE( pEnv && pInterface, "### null ptr!" );
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap::const_iterator const iFind(
+ that->aPtr2ObjectMap.find( pInterface ) );
+ OSL_ASSERT( iFind != that->aPtr2ObjectMap.end() );
+ ObjectEntry * pOEntry = iFind->second;
+ if (! --pOEntry->nRef)
+ {
+ // cleanup maps
+ that->aOId2ObjectMap.erase( pOEntry->oid );
+ sal_Int32 nPos;
+ for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
+ {
+ that->aPtr2ObjectMap.erase( pOEntry->aInterfaces[nPos].pInterface );
+ }
+
+ // the last proxy interface of the environment might kill this
+ // environment, because of releasing its language binding!!!
+ guard.clear();
+
+ // release interfaces
+ for ( nPos = pOEntry->aInterfaces.size(); nPos--; )
+ {
+ InterfaceEntry const & rEntry = pOEntry->aInterfaces[nPos];
+ typelib_typedescription_release(
+ (typelib_TypeDescription *) rEntry.pTypeDescr );
+ if (rEntry.fpFreeProxy) // is proxy or used interface?
+ {
+ (*rEntry.fpFreeProxy)( pEnv, rEntry.pInterface );
+ }
+ else
+ {
+ (*pEnv->releaseInterface)( pEnv, rEntry.pInterface );
+ }
+ }
+
+ delete pOEntry;
+ }
+ else if (pOEntry->mixedObject)
+ {
+ OSL_ASSERT( !pOEntry->aInterfaces.empty() &&
+ pOEntry->aInterfaces[ 0 ].fpFreeProxy == 0 );
+
+ sal_Int32 index = pOEntry->find( pInterface, 1 );
+ OSL_ASSERT( index > 0 );
+ if (index > 0)
+ {
+ InterfaceEntry & entry = pOEntry->aInterfaces[ index ];
+ OSL_ASSERT( entry.pInterface == pInterface );
+ if (entry.fpFreeProxy != 0)
+ {
+ --entry.refCount;
+ if (entry.refCount == 0)
+ {
+ uno_freeProxyFunc fpFreeProxy = entry.fpFreeProxy;
+ typelib_TypeDescription * pTypeDescr =
+ reinterpret_cast< typelib_TypeDescription * >(
+ entry.pTypeDescr );
+
+ pOEntry->aInterfaces.erase(
+ pOEntry->aInterfaces.begin() + index );
+ if (pOEntry->find( pInterface, index ) < 0)
+ {
+ // proxy ptr not registered for another interface:
+ // remove from ptr map
+#if OSL_DEBUG_LEVEL > 0
+ ::std::size_t erased =
+#endif
+ that->aPtr2ObjectMap.erase( pInterface );
+ OSL_ASSERT( erased == 1 );
+ }
+
+ guard.clear();
+
+ typelib_typedescription_release( pTypeDescr );
+ (*fpFreeProxy)( pEnv, pInterface );
+ }
+ }
+ }
+ }
+}
+
+static void SAL_CALL defenv_revokeInterface(uno_ExtEnvironment * pEnv, void * pInterface)
+{
+ uno_Environment_invoke(&pEnv->aBase, s_stub_defenv_revokeInterface, pEnv, pInterface);
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_getObjectIdentifier(
+ uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
+{
+ OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
+ if (*ppOId)
+ {
+ ::rtl_uString_release( *ppOId );
+ *ppOId = 0;
+ }
+
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::ClearableMutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap::const_iterator const iFind(
+ that->aPtr2ObjectMap.find( pInterface ) );
+ if (iFind == that->aPtr2ObjectMap.end())
+ {
+ guard.clear();
+ (*pEnv->computeObjectIdentifier)( pEnv, ppOId, pInterface );
+ }
+ else
+ {
+ rtl_uString * hstr = iFind->second->oid.pData;
+ rtl_uString_acquire( hstr );
+ *ppOId = hstr;
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_getRegisteredInterface(
+ uno_ExtEnvironment * pEnv, void ** ppInterface,
+ rtl_uString * pOId, typelib_InterfaceTypeDescription * pTypeDescr )
+{
+ OSL_ENSURE( pEnv && ppInterface && pOId && pTypeDescr, "### null ptr!" );
+ if (*ppInterface)
+ {
+ (*pEnv->releaseInterface)( pEnv, *ppInterface );
+ *ppInterface = 0;
+ }
+
+ OUString const & rOId = OUString::unacquired( &pOId );
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::MutexGuard guard( that->mutex );
+
+ OId2ObjectMap::const_iterator const iFind
+ ( that->aOId2ObjectMap.find( rOId ) );
+ if (iFind != that->aOId2ObjectMap.end())
+ {
+ InterfaceEntry const * pIEntry = iFind->second->find( pTypeDescr );
+ if (pIEntry)
+ {
+ (*pEnv->acquireInterface)( pEnv, pIEntry->pInterface );
+ *ppInterface = pIEntry->pInterface;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_getRegisteredInterfaces(
+ uno_ExtEnvironment * pEnv, void *** pppInterfaces, sal_Int32 * pnLen,
+ uno_memAlloc memAlloc )
+{
+ OSL_ENSURE( pEnv && pppInterfaces && pnLen && memAlloc, "### null ptr!" );
+ uno_DefaultEnvironment * that =
+ static_cast< uno_DefaultEnvironment * >( pEnv );
+ ::osl::MutexGuard guard( that->mutex );
+
+ sal_Int32 nLen = that->aPtr2ObjectMap.size();
+ sal_Int32 nPos = 0;
+ void ** ppInterfaces = (void **) (*memAlloc)( nLen * sizeof (void *) );
+
+ Ptr2ObjectMap::const_iterator iPos( that->aPtr2ObjectMap.begin() );
+ Ptr2ObjectMap::const_iterator const iEnd( that->aPtr2ObjectMap.end() );
+ while (iPos != iEnd)
+ {
+ (*pEnv->acquireInterface)( pEnv, ppInterfaces[nPos++] = (*iPos).first );
+ ++iPos;
+ }
+
+ *pppInterfaces = ppInterfaces;
+ *pnLen = nLen;
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_acquire( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ ::osl_incrementInterlockedCount( &that->nWeakRef );
+ ::osl_incrementInterlockedCount( &that->nRef );
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_release( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ if (! ::osl_decrementInterlockedCount( &that->nRef ))
+ {
+ // invoke dispose callback
+ if (pEnv->environmentDisposing)
+ {
+ (*pEnv->environmentDisposing)( pEnv );
+ }
+
+ OSL_ENSURE( that->aOId2ObjectMap.empty(), "### object entries left!" );
+ }
+ // free memory if no weak refs left
+ if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
+ {
+ delete that;
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_acquireWeak( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ ::osl_incrementInterlockedCount( &that->nWeakRef );
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_releaseWeak( uno_Environment * pEnv )
+{
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ if (! ::osl_decrementInterlockedCount( &that->nWeakRef ))
+ {
+ delete that;
+ }
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_harden(
+ uno_Environment ** ppHardEnv, uno_Environment * pEnv )
+{
+ if (*ppHardEnv)
+ {
+ (*(*ppHardEnv)->release)( *ppHardEnv );
+ *ppHardEnv = 0;
+ }
+
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ {
+ ::osl::MutexGuard guard( theEnvironmentsData::get().mutex );
+ if (1 == ::osl_incrementInterlockedCount( &that->nRef )) // is dead
+ {
+ that->nRef = 0;
+ return;
+ }
+ }
+ ::osl_incrementInterlockedCount( &that->nWeakRef );
+ *ppHardEnv = pEnv;
+}
+
+//------------------------------------------------------------------------------
+static void SAL_CALL defenv_dispose( uno_Environment * )
+{
+}
+}
+
+//______________________________________________________________________________
+uno_DefaultEnvironment::uno_DefaultEnvironment(
+ const OUString & rEnvDcp_, void * pContext_ )
+ : nRef( 0 ),
+ nWeakRef( 0 )
+{
+ uno_Environment * that = reinterpret_cast< uno_Environment * >(this);
+ that->pReserved = 0;
+ // functions
+ that->acquire = defenv_acquire;
+ that->release = defenv_release;
+ that->acquireWeak = defenv_acquireWeak;
+ that->releaseWeak = defenv_releaseWeak;
+ that->harden = defenv_harden;
+ that->dispose = defenv_dispose;
+ that->pExtEnv = this;
+ // identifier
+ ::rtl_uString_acquire( rEnvDcp_.pData );
+ that->pTypeName = rEnvDcp_.pData;
+ that->pContext = pContext_;
+
+ // will be late initialized
+ that->environmentDisposing = 0;
+
+ uno_ExtEnvironment::registerInterface = defenv_registerInterface;
+ uno_ExtEnvironment::registerProxyInterface = defenv_registerProxyInterface;
+ uno_ExtEnvironment::revokeInterface = defenv_revokeInterface;
+ uno_ExtEnvironment::getObjectIdentifier = defenv_getObjectIdentifier;
+ uno_ExtEnvironment::getRegisteredInterface = defenv_getRegisteredInterface;
+ uno_ExtEnvironment::getRegisteredInterfaces =
+ defenv_getRegisteredInterfaces;
+
+}
+
+//______________________________________________________________________________
+uno_DefaultEnvironment::~uno_DefaultEnvironment()
+{
+ ::rtl_uString_release( ((uno_Environment *) this)->pTypeName );
+}
+
+//==============================================================================
+static void writeLine(
+ void * stream, const sal_Char * pLine, const sal_Char * pFilter )
+{
+ if (pFilter && *pFilter)
+ {
+ // lookup pFilter in pLine
+ while (*pLine)
+ {
+ if (*pLine == *pFilter)
+ {
+ sal_Int32 nPos = 1;
+ while (pLine[nPos] && pFilter[nPos] == pLine[nPos])
+ {
+ ++nPos;
+ }
+ if (! pFilter[nPos])
+ {
+ if (stream)
+ {
+ fprintf( (FILE *) stream, "%s\n", pLine );
+ }
+ else
+ {
+ OSL_TRACE( pLine );
+ OSL_TRACE( "\n" );
+ }
+ }
+ }
+ ++pLine;
+ }
+ }
+ else
+ {
+ if (stream)
+ {
+ fprintf( (FILE *) stream, "%s\n", pLine );
+ }
+ else
+ {
+ fprintf( stderr, "%s\n", pLine );
+ }
+ }
+}
+
+//==============================================================================
+static void writeLine(
+ void * stream, const OUString & rLine, const sal_Char * pFilter )
+{
+ ::rtl::OString aLine( ::rtl::OUStringToOString(
+ rLine, RTL_TEXTENCODING_ASCII_US ) );
+ writeLine( stream, aLine.getStr(), pFilter );
+}
+
+//##############################################################################
+extern "C" void SAL_CALL uno_dumpEnvironment(
+ void * stream, uno_Environment * pEnv, const sal_Char * pFilter )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( pEnv, "### null ptr!" );
+ ::rtl::OUStringBuffer buf;
+
+ if (! pEnv->pExtEnv)
+ {
+ writeLine( stream, "###################################"
+ "###########################################", pFilter );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment: ") );
+ buf.append( pEnv->pTypeName );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+ writeLine( stream, "NO INTERFACE INFORMATION AVAILABLE!", pFilter );
+ return;
+ }
+
+ writeLine( stream, "########################################"
+ "######################################", pFilter );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment dump: ") );
+ buf.append( pEnv->pTypeName );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+
+ uno_DefaultEnvironment * that =
+ reinterpret_cast< uno_DefaultEnvironment * >(pEnv);
+ ::osl::MutexGuard guard( that->mutex );
+
+ Ptr2ObjectMap ptr2obj( that->aPtr2ObjectMap );
+ OId2ObjectMap::const_iterator iPos( that->aOId2ObjectMap.begin() );
+ while (iPos != that->aOId2ObjectMap.end())
+ {
+ ObjectEntry * pOEntry = iPos->second;
+
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("+ ") );
+ if (pOEntry->mixedObject)
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("mixed ") );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("object entry: nRef=") );
+ buf.append( pOEntry->nRef, 10 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; oid=\"") );
+ buf.append( pOEntry->oid );
+ buf.append( (sal_Unicode) '\"' );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+
+ for ( ::std::size_t nPos = 0;
+ nPos < pOEntry->aInterfaces.size(); ++nPos )
+ {
+ const InterfaceEntry & rIEntry = pOEntry->aInterfaces[nPos];
+
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" - ") );
+ buf.append(
+ ((typelib_TypeDescription *) rIEntry.pTypeDescr)->pTypeName );
+ if (rIEntry.fpFreeProxy)
+ {
+ buf.appendAscii(
+ RTL_CONSTASCII_STRINGPARAM("; proxy free=0x") );
+ buf.append(
+ reinterpret_cast< sal_IntPtr >(rIEntry.fpFreeProxy), 16 );
+ }
+ else
+ {
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; original") );
+ }
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("; ptr=0x") );
+ buf.append(
+ reinterpret_cast< sal_IntPtr >(rIEntry.pInterface), 16 );
+
+ if (pOEntry->find( rIEntry.pInterface, nPos + 1 ) < 0)
+ {
+ ::std::size_t erased = ptr2obj.erase( rIEntry.pInterface );
+ if (erased != 1)
+ {
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(
+ " (ptr not found in map!)") );
+ }
+ }
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+ }
+ ++iPos;
+ }
+ if (! ptr2obj.empty())
+ writeLine( stream, "ptr map inconsistency!!!", pFilter );
+ writeLine( stream, "#####################################"
+ "#########################################", pFilter );
+}
+
+//##############################################################################
+extern "C" void SAL_CALL uno_dumpEnvironmentByName(
+ void * stream, rtl_uString * pEnvDcp, const sal_Char * pFilter )
+ SAL_THROW_EXTERN_C()
+{
+ uno_Environment * pEnv = 0;
+ uno_getEnvironment( &pEnv, pEnvDcp, 0 );
+ if (pEnv)
+ {
+ ::uno_dumpEnvironment( stream, pEnv, pFilter );
+ (*pEnv->release)( pEnv );
+ }
+ else
+ {
+ ::rtl::OUStringBuffer buf( 32 );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("environment \"") );
+ buf.append( pEnvDcp );
+ buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not exist!") );
+ writeLine( stream, buf.makeStringAndClear(), pFilter );
+ }
+}
+
+//------------------------------------------------------------------------------
+inline static const OUString & unoenv_getStaticOIdPart()
+{
+ static OUString * s_pStaticOidPart = 0;
+ if (! s_pStaticOidPart)
+ {
+ ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() );
+ if (! s_pStaticOidPart)
+ {
+ ::rtl::OUStringBuffer aRet( 64 );
+ aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
+ // pid
+ oslProcessInfo info;
+ info.Size = sizeof(oslProcessInfo);
+ if (::osl_getProcessInfo( 0, osl_Process_IDENTIFIER, &info ) ==
+ osl_Process_E_None)
+ {
+ aRet.append( (sal_Int64)info.Ident, 16 );
+ }
+ else
+ {
+ aRet.appendAscii(
+ RTL_CONSTASCII_STRINGPARAM("unknown process id") );
+ }
+ // good guid
+ sal_uInt8 ar[16];
+ ::rtl_getGlobalProcessId( ar );
+ aRet.append( (sal_Unicode)';' );
+ for ( sal_Int32 i = 0; i < 16; ++i )
+ aRet.append( (sal_Int32)ar[i], 16 );
+
+ static OUString s_aStaticOidPart( aRet.makeStringAndClear() );
+ s_pStaticOidPart = &s_aStaticOidPart;
+ }
+ }
+ return *s_pStaticOidPart;
+}
+
+extern "C"
+{
+
+//------------------------------------------------------------------------------
+static void SAL_CALL unoenv_computeObjectIdentifier(
+ uno_ExtEnvironment * pEnv, rtl_uString ** ppOId, void * pInterface )
+{
+ OSL_ENSURE( pEnv && ppOId && pInterface, "### null ptr!" );
+ if (*ppOId)
+ {
+ ::rtl_uString_release( *ppOId );
+ *ppOId = 0;
+ }
+
+ uno_Interface * pUnoI = (uno_Interface *)
+ ::cppu::binuno_queryInterface(
+ pInterface, *typelib_static_type_getByTypeClass(
+ typelib_TypeClass_INTERFACE ) );
+ if (0 != pUnoI)
+ {
+ (*pUnoI->release)( pUnoI );
+ // interface
+ ::rtl::OUStringBuffer oid( 64 );
+ oid.append( reinterpret_cast< sal_Int64 >(pUnoI), 16 );
+ oid.append( static_cast< sal_Unicode >(';') );
+ // environment[context]
+ oid.append( ((uno_Environment *) pEnv)->pTypeName );
+ oid.append( static_cast< sal_Unicode >('[') );
+ oid.append( reinterpret_cast< sal_Int64 >(
+ reinterpret_cast<
+ uno_Environment * >(pEnv)->pContext ), 16 );
+ // process;good guid
+ oid.append( unoenv_getStaticOIdPart() );
+ OUString aStr( oid.makeStringAndClear() );
+ ::rtl_uString_acquire( *ppOId = aStr.pData );
+ }
+}
+
+//==============================================================================
+static void SAL_CALL unoenv_acquireInterface(
+ uno_ExtEnvironment *, void * pUnoI_ )
+{
+ uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
+ (*pUnoI->acquire)( pUnoI );
+}
+
+//==============================================================================
+static void SAL_CALL unoenv_releaseInterface(
+ uno_ExtEnvironment *, void * pUnoI_ )
+{
+ uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >(pUnoI_);
+ (*pUnoI->release)( pUnoI );
+}
+}
+
+//______________________________________________________________________________
+EnvironmentsData::~EnvironmentsData()
+{
+ ::osl::MutexGuard guard( mutex );
+
+ for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
+ iPos != aName2EnvMap.end(); ++iPos )
+ {
+ uno_Environment * pWeak = iPos->second;
+ uno_Environment * pHard = 0;
+ (*pWeak->harden)( &pHard, pWeak );
+ (*pWeak->releaseWeak)( pWeak );
+
+ if (pHard)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ ::uno_dumpEnvironment( 0, pHard, 0 );
+#endif
+#if defined CPPU_LEAK_STATIC_DATA
+ pHard->environmentDisposing = 0; // set to null => wont be called
+#else
+ (*pHard->dispose)( pHard ); // send explicit dispose
+#endif
+ (*pHard->release)( pHard );
+ }
+ }
+}
+
+//______________________________________________________________________________
+inline void EnvironmentsData::getEnvironment(
+ uno_Environment ** ppEnv, const OUString & rEnvDcp, void * pContext )
+{
+ if (*ppEnv)
+ {
+ (*(*ppEnv)->release)( *ppEnv );
+ *ppEnv = 0;
+ }
+
+ OUString aKey(
+ OUString::valueOf( reinterpret_cast< sal_IntPtr >(pContext) ) );
+ aKey += rEnvDcp;
+
+ // try to find registered mapping
+ OUString2EnvironmentMap::const_iterator const iFind(
+ aName2EnvMap.find( aKey ) );
+ if (iFind != aName2EnvMap.end())
+ {
+ uno_Environment * pWeak = iFind->second;
+ (*pWeak->harden)( ppEnv, pWeak );
+ }
+}
+
+//______________________________________________________________________________
+inline void EnvironmentsData::registerEnvironment( uno_Environment ** ppEnv )
+{
+ OSL_ENSURE( ppEnv, "### null ptr!" );
+ uno_Environment * pEnv = *ppEnv;
+
+ OUString aKey(
+ OUString::valueOf( reinterpret_cast< sal_IntPtr >(pEnv->pContext) ) );
+ aKey += pEnv->pTypeName;
+
+ // try to find registered environment
+ OUString2EnvironmentMap::const_iterator const iFind(
+ aName2EnvMap.find( aKey ) );
+ if (iFind == aName2EnvMap.end())
+ {
+ (*pEnv->acquireWeak)( pEnv );
+ ::std::pair< OUString2EnvironmentMap::iterator, bool > insertion(
+ aName2EnvMap.insert(
+ OUString2EnvironmentMap::value_type( aKey, pEnv ) ) );
+ OSL_ENSURE(
+ insertion.second, "### insertion of env into map failed?!" );
+ }
+ else
+ {
+ uno_Environment * pHard = 0;
+ uno_Environment * pWeak = iFind->second;
+ (*pWeak->harden)( &pHard, pWeak );
+ if (pHard)
+ {
+ if (pEnv)
+ (*pEnv->release)( pEnv );
+ *ppEnv = pHard;
+ }
+ else // registered one is dead
+ {
+ (*pWeak->releaseWeak)( pWeak );
+ (*pEnv->acquireWeak)( pEnv );
+ aName2EnvMap[ aKey ] = pEnv;
+ }
+ }
+}
+
+//______________________________________________________________________________
+inline void EnvironmentsData::getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
+ const OUString & rEnvDcp )
+{
+ OSL_ENSURE( pppEnvs && pnLen && memAlloc, "### null ptr!" );
+
+ // max size
+ uno_Environment ** ppFound = (uno_Environment **)alloca(
+ sizeof(uno_Environment *) * aName2EnvMap.size() );
+ sal_Int32 nSize = 0;
+
+ // find matching environment
+ for ( OUString2EnvironmentMap::const_iterator iPos( aName2EnvMap.begin() );
+ iPos != aName2EnvMap.end(); ++iPos )
+ {
+ uno_Environment * pWeak = iPos->second;
+ if (!rEnvDcp.getLength() ||
+ rEnvDcp.equals( pWeak->pTypeName ))
+ {
+ ppFound[nSize] = 0;
+ (*pWeak->harden)( &ppFound[nSize], pWeak );
+ if (ppFound[nSize])
+ ++nSize;
+ }
+ }
+
+ *pnLen = nSize;
+ if (nSize)
+ {
+ *pppEnvs = (uno_Environment **) (*memAlloc)(
+ sizeof (uno_Environment *) * nSize );
+ OSL_ASSERT( *pppEnvs );
+ while (nSize--)
+ {
+ (*pppEnvs)[nSize] = ppFound[nSize];
+ }
+ }
+ else
+ {
+ *pppEnvs = 0;
+ }
+}
+
+static bool loadEnv(OUString const & cLibStem,
+ uno_Environment * pEnv,
+ void * /*pContext*/)
+{
+ // late init with some code from matching uno language binding
+ // will be unloaded by environment
+ oslModule hMod = cppu::detail::loadModule( cLibStem );
+
+ if (!hMod)
+ return false;
+
+ OUString aSymbolName(RTL_CONSTASCII_USTRINGPARAM(UNO_INIT_ENVIRONMENT));
+ uno_initEnvironmentFunc fpInit = (uno_initEnvironmentFunc)
+ ::osl_getFunctionSymbol( hMod, aSymbolName.pData );
+ if (!fpInit)
+ {
+ ::osl_unloadModule( hMod );
+ return false;
+ }
+
+ (*fpInit)( pEnv ); // init of environment
+ ::rtl_registerModuleForUnloading( hMod );
+
+ return true;
+}
+
+
+extern "C"
+{
+
+//------------------------------------------------------------------------------
+static uno_Environment * initDefaultEnvironment(
+ const OUString & rEnvDcp, void * pContext )
+{
+ uno_Environment * pEnv = &(new uno_DefaultEnvironment( rEnvDcp, pContext ))->aBase;
+ (*pEnv->acquire)( pEnv );
+
+ OUString envTypeName = cppu::EnvDcp::getTypeName(rEnvDcp);
+
+ // create default environment
+ if (envTypeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
+ {
+ uno_DefaultEnvironment * that = (uno_DefaultEnvironment *)pEnv;
+ that->computeObjectIdentifier = unoenv_computeObjectIdentifier;
+ that->acquireInterface = unoenv_acquireInterface;
+ that->releaseInterface = unoenv_releaseInterface;
+
+ OUString envPurpose = cppu::EnvDcp::getPurpose(rEnvDcp);
+ if (envPurpose.getLength())
+ {
+ rtl::OUString libStem = envPurpose.copy(envPurpose.lastIndexOf(':') + 1);
+ libStem += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_uno_uno") );
+
+ if(!loadEnv(libStem, pEnv, pContext))
+ {
+ pEnv->release(pEnv);
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ // late init with some code from matching uno language binding
+ ::rtl::OUStringBuffer aLibName( 16 );
+ aLibName.append( envTypeName );
+ aLibName.appendAscii( RTL_CONSTASCII_STRINGPARAM("_uno" ) );
+ OUString aStr( aLibName.makeStringAndClear() );
+
+ if (!loadEnv(aStr, pEnv, pContext))
+ {
+ pEnv->release(pEnv);
+ return NULL;
+ }
+ }
+
+ return pEnv;
+}
+
+//##############################################################################
+void SAL_CALL uno_createEnvironment(
+ uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( ppEnv, "### null ptr!" );
+ if (*ppEnv)
+ (*(*ppEnv)->release)( *ppEnv );
+
+ OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
+ *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
+}
+
+//##############################################################################
+void SAL_CALL uno_direct_getEnvironment(
+ uno_Environment ** ppEnv, rtl_uString * pEnvDcp, void * pContext )
+ SAL_THROW_EXTERN_C()
+{
+ OSL_ENSURE( ppEnv, "### null ptr!" );
+ OUString const & rEnvDcp = OUString::unacquired( &pEnvDcp );
+
+ EnvironmentsData & rData = theEnvironmentsData::get();
+
+ ::osl::MutexGuard guard( rData.mutex );
+ rData.getEnvironment( ppEnv, rEnvDcp, pContext );
+ if (! *ppEnv)
+ {
+ *ppEnv = initDefaultEnvironment( rEnvDcp, pContext );
+ if (*ppEnv)
+ {
+ // register new environment:
+ rData.registerEnvironment( ppEnv );
+ }
+ }
+}
+
+//##############################################################################
+void SAL_CALL uno_getRegisteredEnvironments(
+ uno_Environment *** pppEnvs, sal_Int32 * pnLen, uno_memAlloc memAlloc,
+ rtl_uString * pEnvDcp )
+ SAL_THROW_EXTERN_C()
+{
+ EnvironmentsData & rData = theEnvironmentsData::get();
+
+ ::osl::MutexGuard guard( rData.mutex );
+ rData.getRegisteredEnvironments(
+ pppEnvs, pnLen, memAlloc,
+ (pEnvDcp ? OUString(pEnvDcp) : OUString()) );
+}
+
+} // extern "C"
+
+}
+