| /************************************************************** | |
| * | |
| * 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 successfull! | |
| } | |
| } | |
| 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" | |