| /************************************************************** |
| * |
| * 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_cppu.hxx" |
| |
| #include "IdentityMapping.hxx" |
| |
| #include <hash_map> |
| #include <set> |
| #include <algorithm> |
| |
| #include "rtl/unload.h" |
| #include "rtl/ustring.hxx" |
| #include "rtl/ustrbuf.hxx" |
| #include "osl/module.h" |
| #include "osl/diagnose.h" |
| #include "osl/mutex.hxx" |
| #include "osl/interlck.h" |
| |
| #include "uno/dispatcher.h" |
| #include "uno/mapping.h" |
| #include "uno/lbnames.h" |
| #include "uno/environment.hxx" |
| |
| #include "typelib/typedescription.h" |
| |
| #include "cppu/EnvDcp.hxx" |
| #include "cascade_mapping.hxx" |
| #include "IdentityMapping.hxx" |
| #include "loadmodule.hxx" |
| |
| using namespace std; |
| using namespace osl; |
| using namespace rtl; |
| using namespace com::sun::star::uno; |
| |
| |
| namespace cppu |
| { |
| |
| class Mapping |
| { |
| uno_Mapping * _pMapping; |
| |
| public: |
| inline Mapping( uno_Mapping * pMapping = 0 ) SAL_THROW( () ); |
| inline Mapping( const Mapping & rMapping ) SAL_THROW( () ); |
| inline ~Mapping() SAL_THROW( () ); |
| inline Mapping & SAL_CALL operator = ( uno_Mapping * pMapping ) SAL_THROW( () ); |
| inline Mapping & SAL_CALL operator = ( const Mapping & rMapping ) SAL_THROW( () ) |
| { return operator = ( rMapping._pMapping ); } |
| inline uno_Mapping * SAL_CALL get() const SAL_THROW( () ) |
| { return _pMapping; } |
| inline sal_Bool SAL_CALL is() const SAL_THROW( () ) |
| { return (_pMapping != 0); } |
| }; |
| //__________________________________________________________________________________________________ |
| inline Mapping::Mapping( uno_Mapping * pMapping ) SAL_THROW( () ) |
| : _pMapping( pMapping ) |
| { |
| if (_pMapping) |
| (*_pMapping->acquire)( _pMapping ); |
| } |
| //__________________________________________________________________________________________________ |
| inline Mapping::Mapping( const Mapping & rMapping ) SAL_THROW( () ) |
| : _pMapping( rMapping._pMapping ) |
| { |
| if (_pMapping) |
| (*_pMapping->acquire)( _pMapping ); |
| } |
| //__________________________________________________________________________________________________ |
| inline Mapping::~Mapping() SAL_THROW( () ) |
| { |
| if (_pMapping) |
| (*_pMapping->release)( _pMapping ); |
| } |
| //__________________________________________________________________________________________________ |
| inline Mapping & Mapping::operator = ( uno_Mapping * pMapping ) SAL_THROW( () ) |
| { |
| if (pMapping) |
| (*pMapping->acquire)( pMapping ); |
| if (_pMapping) |
| (*_pMapping->release)( _pMapping ); |
| _pMapping = pMapping; |
| return *this; |
| } |
| |
| //================================================================================================== |
| struct MappingEntry |
| { |
| sal_Int32 nRef; |
| uno_Mapping * pMapping; |
| uno_freeMappingFunc freeMapping; |
| OUString aMappingName; |
| |
| MappingEntry( |
| uno_Mapping * pMapping_, uno_freeMappingFunc freeMapping_, |
| const OUString & rMappingName_ ) |
| SAL_THROW( () ) |
| : nRef( 1 ) |
| , pMapping( pMapping_ ) |
| , freeMapping( freeMapping_ ) |
| , aMappingName( rMappingName_ ) |
| {} |
| }; |
| //-------------------------------------------------------------------------------------------------- |
| struct FctOUStringHash : public unary_function< const OUString &, size_t > |
| { |
| size_t operator()( const OUString & rKey ) const SAL_THROW( () ) |
| { return (size_t)rKey.hashCode(); } |
| }; |
| //-------------------------------------------------------------------------------------------------- |
| struct FctPtrHash : public unary_function< uno_Mapping *, size_t > |
| { |
| size_t operator()( uno_Mapping * pKey ) const SAL_THROW( () ) |
| { return (size_t)pKey; } |
| }; |
| |
| typedef hash_map< |
| OUString, MappingEntry *, FctOUStringHash, equal_to< OUString > > t_OUString2Entry; |
| typedef hash_map< |
| uno_Mapping *, MappingEntry *, FctPtrHash, equal_to< uno_Mapping * > > t_Mapping2Entry; |
| |
| typedef set< uno_getMappingFunc > t_CallbackSet; |
| typedef set< OUString > t_OUStringSet; |
| |
| //================================================================================================== |
| struct MappingsData |
| { |
| Mutex aMappingsMutex; |
| t_OUString2Entry aName2Entry; |
| t_Mapping2Entry aMapping2Entry; |
| |
| Mutex aCallbacksMutex; |
| t_CallbackSet aCallbacks; |
| |
| Mutex aNegativeLibsMutex; |
| t_OUStringSet aNegativeLibs; |
| }; |
| //-------------------------------------------------------------------------------------------------- |
| static MappingsData & getMappingsData() SAL_THROW( () ) |
| { |
| static MappingsData * s_p = 0; |
| if (! s_p) |
| { |
| MutexGuard aGuard( Mutex::getGlobalMutex() ); |
| if (! s_p) |
| { |
| //TODO This memory is leaked; see #i63473# for when this should be |
| // changed again: |
| s_p = new MappingsData; |
| } |
| } |
| return *s_p; |
| } |
| |
| /** |
| * This class mediates two different mapping via uno, e.g. form any language to uno, |
| * then from uno to any other language. |
| */ |
| struct uno_Mediate_Mapping : public uno_Mapping |
| { |
| sal_Int32 nRef; |
| |
| Environment aFrom; |
| Environment aTo; |
| |
| Mapping aFrom2Uno; |
| Mapping aUno2To; |
| |
| OUString aAddPurpose; |
| |
| uno_Mediate_Mapping( |
| const Environment & rFrom_, const Environment & rTo_, |
| const Mapping & rFrom2Uno_, const Mapping & rUno2To_, |
| const OUString & rAddPurpose ) |
| SAL_THROW( () ); |
| }; |
| extern "C" |
| { |
| //-------------------------------------------------------------------------------------------------- |
| static void SAL_CALL mediate_free( uno_Mapping * pMapping ) |
| SAL_THROW( () ) |
| { |
| delete static_cast< uno_Mediate_Mapping * >( pMapping ); |
| } |
| //-------------------------------------------------------------------------------------------------- |
| static void SAL_CALL mediate_acquire( uno_Mapping * pMapping ) |
| SAL_THROW( () ) |
| { |
| if (1 == ::osl_incrementInterlockedCount( |
| & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef )) |
| { |
| uno_registerMapping( |
| &pMapping, mediate_free, |
| static_cast< uno_Mediate_Mapping * >( pMapping )->aFrom.get(), |
| static_cast< uno_Mediate_Mapping * >( pMapping )->aTo.get(), |
| static_cast< uno_Mediate_Mapping * >( pMapping )->aAddPurpose.pData ); |
| } |
| } |
| //-------------------------------------------------------------------------------------------------- |
| static void SAL_CALL mediate_release( uno_Mapping * pMapping ) |
| SAL_THROW( () ) |
| { |
| if (! ::osl_decrementInterlockedCount( |
| & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef )) |
| { |
| uno_revokeMapping( pMapping ); |
| } |
| } |
| //-------------------------------------------------------------------------------------------------- |
| static void SAL_CALL mediate_mapInterface( |
| uno_Mapping * pMapping, |
| void ** ppOut, void * pInterface, |
| typelib_InterfaceTypeDescription * pInterfaceTypeDescr ) |
| SAL_THROW( () ) |
| { |
| OSL_ENSURE( pMapping && ppOut, "### null ptr!" ); |
| if (pMapping && ppOut) |
| { |
| uno_Mediate_Mapping * that = static_cast< uno_Mediate_Mapping * >( pMapping ); |
| uno_Mapping * pFrom2Uno = that->aFrom2Uno.get(); |
| |
| uno_Interface * pUnoI = 0; |
| (*pFrom2Uno->mapInterface)( pFrom2Uno, (void **) &pUnoI, pInterface, pInterfaceTypeDescr ); |
| if (0 == pUnoI) |
| { |
| void * pOut = *ppOut; |
| if (0 != pOut) |
| { |
| uno_ExtEnvironment * pTo = that->aTo.get()->pExtEnv; |
| OSL_ENSURE( 0 != pTo, "### cannot release out interface: leaking!" ); |
| if (0 != pTo) |
| (*pTo->releaseInterface)( pTo, pOut ); |
| *ppOut = 0; // set to 0 anyway, because mapping was not successful! |
| } |
| } |
| else |
| { |
| uno_Mapping * pUno2To = that->aUno2To.get(); |
| (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr ); |
| (*pUnoI->release)( pUnoI ); |
| } |
| } |
| } |
| } |
| //__________________________________________________________________________________________________ |
| uno_Mediate_Mapping::uno_Mediate_Mapping( |
| const Environment & rFrom_, const Environment & rTo_, |
| const Mapping & rFrom2Uno_, const Mapping & rUno2To_, |
| const OUString & rAddPurpose_ ) |
| SAL_THROW( () ) |
| : nRef( 1 ) |
| , aFrom( rFrom_ ) |
| , aTo( rTo_ ) |
| , aFrom2Uno( rFrom2Uno_ ) |
| , aUno2To( rUno2To_ ) |
| , aAddPurpose( rAddPurpose_ ) |
| { |
| uno_Mapping::acquire = mediate_acquire; |
| uno_Mapping::release = mediate_release; |
| uno_Mapping::mapInterface = mediate_mapInterface; |
| } |
| |
| //================================================================================================== |
| static inline OUString getMappingName( |
| const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) |
| SAL_THROW( () ) |
| { |
| OUStringBuffer aKey( 64 ); |
| aKey.append( rAddPurpose ); |
| aKey.append( (sal_Unicode)';' ); |
| aKey.append( rFrom.getTypeName() ); |
| aKey.append( (sal_Unicode)'[' ); |
| aKey.append( reinterpret_cast< sal_IntPtr >(rFrom.get()), 16 ); |
| aKey.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") ); |
| aKey.append( rTo.getTypeName() ); |
| aKey.append( (sal_Unicode)'[' ); |
| aKey.append( reinterpret_cast< sal_IntPtr >(rTo.get()), 16 ); |
| aKey.append( (sal_Unicode)']' ); |
| return aKey.makeStringAndClear(); |
| } |
| //================================================================================================== |
| static inline OUString getBridgeName( |
| const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) |
| SAL_THROW( () ) |
| { |
| OUStringBuffer aBridgeName( 16 ); |
| if (rAddPurpose.getLength()) |
| { |
| aBridgeName.append( rAddPurpose ); |
| aBridgeName.append( (sal_Unicode)'_' ); |
| } |
| aBridgeName.append( EnvDcp::getTypeName(rFrom.getTypeName()) ); |
| aBridgeName.append( (sal_Unicode)'_' ); |
| aBridgeName.append( EnvDcp::getTypeName(rTo.getTypeName()) ); |
| return aBridgeName.makeStringAndClear(); |
| } |
| //================================================================================================== |
| static inline void setNegativeBridge( const OUString & rBridgeName ) |
| SAL_THROW( () ) |
| { |
| MappingsData & rData = getMappingsData(); |
| MutexGuard aGuard( rData.aNegativeLibsMutex ); |
| rData.aNegativeLibs.insert( rBridgeName ); |
| } |
| //================================================================================================== |
| static inline oslModule loadModule( const OUString & rBridgeName ) |
| SAL_THROW( () ) |
| { |
| sal_Bool bNeg; |
| { |
| MappingsData & rData = getMappingsData(); |
| MutexGuard aGuard( rData.aNegativeLibsMutex ); |
| const t_OUStringSet::const_iterator iFind( rData.aNegativeLibs.find( rBridgeName ) ); |
| bNeg = (iFind != rData.aNegativeLibs.end()); |
| } |
| |
| if (! bNeg) |
| { |
| oslModule hModule = cppu::detail::loadModule( rBridgeName ); |
| |
| if (hModule) |
| return hModule; |
| |
| setNegativeBridge( rBridgeName ); // no load again |
| } |
| return 0; |
| } |
| //================================================================================================== |
| static Mapping loadExternalMapping( |
| const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) |
| SAL_THROW( () ) |
| { |
| OSL_ASSERT( rFrom.is() && rTo.is() ); |
| if (rFrom.is() && rTo.is()) |
| { |
| // find proper lib |
| oslModule hModule = 0; |
| OUString aName; |
| |
| if (EnvDcp::getTypeName(rFrom.getTypeName()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) )) |
| hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) ); |
| if (! hModule) |
| hModule = loadModule( aName = getBridgeName( rFrom, rTo, rAddPurpose ) ); |
| if (! hModule) |
| hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) ); |
| |
| if (hModule) |
| { |
| OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM(UNO_EXT_GETMAPPING) ); |
| uno_ext_getMappingFunc fpGetMapFunc = |
| (uno_ext_getMappingFunc)::osl_getFunctionSymbol( |
| hModule, aSymbolName.pData ); |
| |
| if (fpGetMapFunc) |
| { |
| Mapping aExt; |
| (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() ); |
| OSL_ASSERT( aExt.is() ); |
| if (aExt.is()) |
| { |
| ::rtl_registerModuleForUnloading( hModule ); |
| return aExt; |
| } |
| } |
| ::osl_unloadModule( hModule ); |
| setNegativeBridge( aName ); |
| } |
| } |
| return Mapping(); |
| } |
| |
| //================================================================================================== |
| static Mapping getDirectMapping( |
| const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose = OUString() ) |
| SAL_THROW( () ) |
| { |
| OSL_ASSERT( rFrom.is() && rTo.is() ); |
| if (rFrom.is() && rTo.is()) |
| { |
| MappingsData & rData = getMappingsData(); |
| ClearableMutexGuard aGuard( rData.aMappingsMutex ); |
| |
| // try to find registered mapping |
| const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find( |
| getMappingName( rFrom, rTo, rAddPurpose ) ) ); |
| |
| if (iFind == rData.aName2Entry.end()) |
| { |
| aGuard.clear(); |
| return loadExternalMapping( rFrom, rTo, rAddPurpose ); |
| } |
| else |
| { |
| return Mapping( (*iFind).second->pMapping ); |
| } |
| } |
| return Mapping(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| static inline Mapping createMediateMapping( |
| const Environment & rFrom, const Environment & rTo, |
| const Mapping & rFrom2Uno, const Mapping & rUno2To, |
| const OUString & rAddPurpose ) |
| SAL_THROW( () ) |
| { |
| uno_Mapping * pRet = new uno_Mediate_Mapping( |
| rFrom, rTo, rFrom2Uno, rUno2To, rAddPurpose ); // ref count initially 1 |
| uno_registerMapping( |
| &pRet, mediate_free, rFrom.get(), rTo.get(), rAddPurpose.pData ); |
| Mapping aRet( pRet ); |
| (*pRet->release)( pRet ); |
| return aRet; |
| } |
| //================================================================================================== |
| static Mapping getMediateMapping( |
| const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose ) |
| SAL_THROW( () ) |
| { |
| Environment aUno; |
| Mapping aUno2To; |
| |
| // backwards: from dest to source of mapping chain |
| |
| // connect to uno |
| OUString aUnoEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ); |
| if (rTo.getTypeName() == aUnoEnvTypeName) // to is uno |
| { |
| aUno = rTo; |
| // no Uno2To mapping necessary |
| } |
| else |
| { |
| // get registered uno env |
| ::uno_getEnvironment( (uno_Environment **)&aUno, aUnoEnvTypeName.pData, 0 ); |
| |
| aUno2To = getDirectMapping( aUno, rTo ); |
| // : uno <-> to |
| if (! aUno2To.is()) |
| return Mapping(); |
| } |
| |
| // connect to uno |
| if (rAddPurpose.getLength()) // insert purpose mapping between new ano_uno <-> uno |
| { |
| // create anonymous uno env |
| Environment aAnUno; |
| ::uno_createEnvironment( (uno_Environment **)&aAnUno, aUnoEnvTypeName.pData, 0 ); |
| |
| Mapping aAnUno2Uno( getDirectMapping( aAnUno, aUno, rAddPurpose ) ); |
| if (! aAnUno2Uno.is()) |
| return Mapping(); |
| |
| if (aUno2To.is()) // to is not uno |
| { |
| // create another purposed mediate mapping |
| aUno2To = createMediateMapping( aAnUno, rTo, aAnUno2Uno, aUno2To, rAddPurpose ); |
| // : ano_uno <-> uno <-> to |
| } |
| else |
| { |
| aUno2To = aAnUno2Uno; |
| // : ano_uno <-> to (i.e., uno) |
| } |
| aUno = aAnUno; |
| } |
| |
| Mapping aFrom2Uno( getDirectMapping( rFrom, aUno ) ); |
| if (aFrom2Uno.is() && aUno2To.is()) |
| { |
| return createMediateMapping( rFrom, rTo, aFrom2Uno, aUno2To, rAddPurpose ); |
| // : from <-> some uno ... |
| } |
| |
| return Mapping(); |
| } |
| } |
| |
| using namespace ::cppu; |
| |
| extern "C" |
| { |
| //################################################################################################## |
| void SAL_CALL uno_getMapping( |
| uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo, |
| rtl_uString * pAddPurpose ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" ); |
| if (*ppMapping) |
| { |
| (*(*ppMapping)->release)( *ppMapping ); |
| *ppMapping = 0; |
| } |
| |
| Mapping aRet; |
| Environment aFrom( pFrom ), aTo( pTo ); |
| |
| OUString aAddPurpose; |
| if (pAddPurpose) |
| aAddPurpose = pAddPurpose; |
| |
| MappingsData & rData = getMappingsData(); |
| |
| // try registered mapping |
| { |
| MutexGuard aGuard( rData.aMappingsMutex ); |
| const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find( |
| getMappingName( aFrom, aTo, aAddPurpose ) ) ); |
| if (iFind != rData.aName2Entry.end()) |
| aRet = (*iFind).second->pMapping; |
| } |
| |
| // See if an identity mapping does fit. |
| if (!aRet.is() && pFrom == pTo && !aAddPurpose.getLength()) |
| aRet = createIdentityMapping(pFrom); |
| |
| if (!aRet.is()) |
| { |
| getCascadeMapping(ppMapping, pFrom, pTo, pAddPurpose); |
| |
| if (*ppMapping) |
| return; |
| } |
| |
| if (! aRet.is()) // try callback chain |
| { |
| MutexGuard aGuard( rData.aCallbacksMutex ); |
| for ( t_CallbackSet::const_iterator iPos( rData.aCallbacks.begin() ); |
| iPos != rData.aCallbacks.end(); ++iPos ) |
| { |
| (**iPos)( ppMapping, pFrom, pTo, aAddPurpose.pData ); |
| if (*ppMapping) |
| return; |
| } |
| } |
| |
| if (! aRet.is()) |
| { |
| aRet = loadExternalMapping( aFrom, aTo, aAddPurpose ); // direct try |
| if (! aRet.is()) |
| aRet = getMediateMapping( aFrom, aTo, aAddPurpose ); // try via uno |
| } |
| |
| if (aRet.is()) |
| { |
| (*aRet.get()->acquire)( aRet.get() ); |
| *ppMapping = aRet.get(); |
| } |
| } |
| //################################################################################################## |
| void SAL_CALL uno_getMappingByName( |
| uno_Mapping ** ppMapping, rtl_uString * pFrom, rtl_uString * pTo, |
| rtl_uString * pAddPurpose ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" ); |
| if (*ppMapping) |
| { |
| (*(*ppMapping)->release)( *ppMapping ); |
| *ppMapping = 0; |
| } |
| |
| uno_Environment * pEFrom = 0; |
| uno_getEnvironment( &pEFrom, pFrom, 0 ); |
| OSL_ENSURE( pEFrom, "### cannot get source environment!" ); |
| if (pEFrom) |
| { |
| uno_Environment * pETo = 0; |
| uno_getEnvironment( &pETo, pTo, 0 ); |
| OSL_ENSURE( pETo, "### cannot get target environment!" ); |
| if (pETo) |
| { |
| ::uno_getMapping( ppMapping, pEFrom, pETo, pAddPurpose ); |
| (*pETo->release)( pETo ); |
| } |
| (*pEFrom->release)( pEFrom ); |
| } |
| } |
| |
| //################################################################################################## |
| void SAL_CALL uno_registerMapping( |
| uno_Mapping ** ppMapping, uno_freeMappingFunc freeMapping, |
| uno_Environment * pFrom, uno_Environment * pTo, rtl_uString * pAddPurpose ) |
| SAL_THROW_EXTERN_C() |
| { |
| MappingsData & rData = getMappingsData(); |
| ClearableMutexGuard aGuard( rData.aMappingsMutex ); |
| |
| const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( *ppMapping ) ); |
| if (iFind == rData.aMapping2Entry.end()) |
| { |
| OUString aMappingName( |
| getMappingName( pFrom, pTo, pAddPurpose ? OUString(pAddPurpose) : OUString() ) ); |
| #if OSL_DEBUG_LEVEL > 1 |
| OString cstr( OUStringToOString( aMappingName, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( "> inserting new mapping: %s", cstr.getStr() ); |
| #endif |
| // count initially 1 |
| MappingEntry * pEntry = new MappingEntry( *ppMapping, freeMapping, aMappingName ); |
| rData.aName2Entry[ aMappingName ] = pEntry; |
| rData.aMapping2Entry[ *ppMapping ] = pEntry; |
| } |
| else |
| { |
| MappingEntry * pEntry = (*iFind).second; |
| ++pEntry->nRef; |
| |
| if (pEntry->pMapping != *ppMapping) // exchange mapping to be registered |
| { |
| (*pEntry->pMapping->acquire)( pEntry->pMapping ); |
| --pEntry->nRef; // correct count; kill mapping to be registered |
| aGuard.clear(); |
| (*freeMapping)( *ppMapping ); |
| *ppMapping = pEntry->pMapping; |
| } |
| } |
| } |
| //################################################################################################## |
| void SAL_CALL uno_revokeMapping( |
| uno_Mapping * pMapping ) |
| SAL_THROW_EXTERN_C() |
| { |
| MappingsData & rData = getMappingsData(); |
| ClearableMutexGuard aGuard( rData.aMappingsMutex ); |
| |
| const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( pMapping ) ); |
| OSL_ASSERT( iFind != rData.aMapping2Entry.end() ); |
| MappingEntry * pEntry = (*iFind).second; |
| if (! --pEntry->nRef) |
| { |
| rData.aMapping2Entry.erase( pEntry->pMapping ); |
| rData.aName2Entry.erase( pEntry->aMappingName ); |
| aGuard.clear(); |
| #if OSL_DEBUG_LEVEL > 1 |
| OString cstr( OUStringToOString( pEntry->aMappingName, RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( "> revoking mapping %s", cstr.getStr() ); |
| #endif |
| (*pEntry->freeMapping)( pEntry->pMapping ); |
| delete pEntry; |
| } |
| } |
| |
| //################################################################################################## |
| void SAL_CALL uno_registerMappingCallback( |
| uno_getMappingFunc pCallback ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( pCallback, "### null ptr!" ); |
| MappingsData & rData = getMappingsData(); |
| MutexGuard aGuard( rData.aCallbacksMutex ); |
| rData.aCallbacks.insert( pCallback ); |
| } |
| //################################################################################################## |
| void SAL_CALL uno_revokeMappingCallback( |
| uno_getMappingFunc pCallback ) |
| SAL_THROW_EXTERN_C() |
| { |
| OSL_ENSURE( pCallback, "### null ptr!" ); |
| MappingsData & rData = getMappingsData(); |
| MutexGuard aGuard( rData.aCallbacksMutex ); |
| rData.aCallbacks.erase( pCallback ); |
| } |
| } // extern "C" |
| |