xref: /trunk/main/cppu/source/uno/lbmap.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cppu.hxx"
30 
31 #include "IdentityMapping.hxx"
32 
33 #include <hash_map>
34 #include <set>
35 #include <algorithm>
36 
37 #include "rtl/unload.h"
38 #include "rtl/ustring.hxx"
39 #include "rtl/ustrbuf.hxx"
40 #include "osl/module.h"
41 #include "osl/diagnose.h"
42 #include "osl/mutex.hxx"
43 #include "osl/interlck.h"
44 
45 #include "uno/dispatcher.h"
46 #include "uno/mapping.h"
47 #include "uno/lbnames.h"
48 #include "uno/environment.hxx"
49 
50 #include "typelib/typedescription.h"
51 
52 #include "cppu/EnvDcp.hxx"
53 #include "cascade_mapping.hxx"
54 #include "IdentityMapping.hxx"
55 #include "loadmodule.hxx"
56 
57 using namespace std;
58 using namespace osl;
59 using namespace rtl;
60 using namespace com::sun::star::uno;
61 
62 
63 namespace cppu
64 {
65 
66 class Mapping
67 {
68     uno_Mapping * _pMapping;
69 
70 public:
71     inline Mapping( uno_Mapping * pMapping = 0 ) SAL_THROW( () );
72     inline Mapping( const Mapping & rMapping ) SAL_THROW( () );
73     inline ~Mapping() SAL_THROW( () );
74     inline Mapping & SAL_CALL operator = ( uno_Mapping * pMapping ) SAL_THROW( () );
75     inline Mapping & SAL_CALL operator = ( const Mapping & rMapping ) SAL_THROW( () )
76         { return operator = ( rMapping._pMapping ); }
77     inline uno_Mapping * SAL_CALL get() const SAL_THROW( () )
78         { return _pMapping; }
79     inline sal_Bool SAL_CALL is() const SAL_THROW( () )
80         { return (_pMapping != 0); }
81 };
82 //__________________________________________________________________________________________________
83 inline Mapping::Mapping( uno_Mapping * pMapping ) SAL_THROW( () )
84     : _pMapping( pMapping )
85 {
86     if (_pMapping)
87         (*_pMapping->acquire)( _pMapping );
88 }
89 //__________________________________________________________________________________________________
90 inline Mapping::Mapping( const Mapping & rMapping ) SAL_THROW( () )
91     : _pMapping( rMapping._pMapping )
92 {
93     if (_pMapping)
94         (*_pMapping->acquire)( _pMapping );
95 }
96 //__________________________________________________________________________________________________
97 inline Mapping::~Mapping() SAL_THROW( () )
98 {
99     if (_pMapping)
100         (*_pMapping->release)( _pMapping );
101 }
102 //__________________________________________________________________________________________________
103 inline Mapping & Mapping::operator = ( uno_Mapping * pMapping ) SAL_THROW( () )
104 {
105     if (pMapping)
106         (*pMapping->acquire)( pMapping );
107     if (_pMapping)
108         (*_pMapping->release)( _pMapping );
109     _pMapping = pMapping;
110     return *this;
111 }
112 
113 //==================================================================================================
114 struct MappingEntry
115 {
116     sal_Int32           nRef;
117     uno_Mapping *       pMapping;
118     uno_freeMappingFunc freeMapping;
119     OUString            aMappingName;
120 
121     MappingEntry(
122         uno_Mapping * pMapping_, uno_freeMappingFunc freeMapping_,
123         const OUString & rMappingName_ )
124         SAL_THROW( () )
125         : nRef( 1 )
126         , pMapping( pMapping_ )
127         , freeMapping( freeMapping_ )
128         , aMappingName( rMappingName_ )
129         {}
130 };
131 //--------------------------------------------------------------------------------------------------
132 struct FctOUStringHash : public unary_function< const OUString &, size_t >
133 {
134     size_t operator()( const OUString & rKey ) const SAL_THROW( () )
135         { return (size_t)rKey.hashCode(); }
136 };
137 //--------------------------------------------------------------------------------------------------
138 struct FctPtrHash : public unary_function< uno_Mapping *, size_t >
139 {
140     size_t operator()( uno_Mapping * pKey ) const SAL_THROW( () )
141         { return (size_t)pKey; }
142 };
143 
144 typedef hash_map<
145     OUString, MappingEntry *, FctOUStringHash, equal_to< OUString > > t_OUString2Entry;
146 typedef hash_map<
147     uno_Mapping *, MappingEntry *, FctPtrHash, equal_to< uno_Mapping * > > t_Mapping2Entry;
148 
149 typedef set< uno_getMappingFunc > t_CallbackSet;
150 typedef set< OUString > t_OUStringSet;
151 
152 //==================================================================================================
153 struct MappingsData
154 {
155     Mutex               aMappingsMutex;
156     t_OUString2Entry    aName2Entry;
157     t_Mapping2Entry     aMapping2Entry;
158 
159     Mutex               aCallbacksMutex;
160     t_CallbackSet       aCallbacks;
161 
162     Mutex               aNegativeLibsMutex;
163     t_OUStringSet       aNegativeLibs;
164 };
165 //--------------------------------------------------------------------------------------------------
166 static MappingsData & getMappingsData() SAL_THROW( () )
167 {
168     static MappingsData * s_p = 0;
169     if (! s_p)
170     {
171         MutexGuard aGuard( Mutex::getGlobalMutex() );
172         if (! s_p)
173         {
174             //TODO  This memory is leaked; see #i63473# for when this should be
175             // changed again:
176             s_p = new MappingsData;
177         }
178     }
179     return *s_p;
180 }
181 
182 /**
183  * This class mediates two different mapping via uno, e.g. form any language to uno,
184  * then from uno to any other language.
185  */
186 struct uno_Mediate_Mapping : public uno_Mapping
187 {
188     sal_Int32   nRef;
189 
190     Environment aFrom;
191     Environment aTo;
192 
193     Mapping     aFrom2Uno;
194     Mapping     aUno2To;
195 
196     OUString    aAddPurpose;
197 
198     uno_Mediate_Mapping(
199         const Environment & rFrom_, const Environment & rTo_,
200         const Mapping & rFrom2Uno_, const Mapping & rUno2To_,
201         const OUString & rAddPurpose )
202         SAL_THROW( () );
203 };
204 extern "C"
205 {
206 //--------------------------------------------------------------------------------------------------
207 static void SAL_CALL mediate_free( uno_Mapping * pMapping )
208     SAL_THROW( () )
209 {
210     delete static_cast< uno_Mediate_Mapping * >( pMapping );
211 }
212 //--------------------------------------------------------------------------------------------------
213 static void SAL_CALL mediate_acquire( uno_Mapping * pMapping )
214     SAL_THROW( () )
215 {
216     if (1 == ::osl_incrementInterlockedCount(
217         & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
218     {
219         uno_registerMapping(
220             &pMapping, mediate_free,
221             static_cast< uno_Mediate_Mapping * >( pMapping )->aFrom.get(),
222             static_cast< uno_Mediate_Mapping * >( pMapping )->aTo.get(),
223             static_cast< uno_Mediate_Mapping * >( pMapping )->aAddPurpose.pData );
224     }
225 }
226 //--------------------------------------------------------------------------------------------------
227 static void SAL_CALL mediate_release( uno_Mapping * pMapping )
228     SAL_THROW( () )
229 {
230     if (! ::osl_decrementInterlockedCount(
231         & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
232     {
233         uno_revokeMapping( pMapping );
234     }
235 }
236 //--------------------------------------------------------------------------------------------------
237 static void SAL_CALL mediate_mapInterface(
238     uno_Mapping * pMapping,
239     void ** ppOut, void * pInterface,
240     typelib_InterfaceTypeDescription * pInterfaceTypeDescr )
241     SAL_THROW( () )
242 {
243     OSL_ENSURE( pMapping && ppOut, "### null ptr!" );
244     if (pMapping && ppOut)
245     {
246         uno_Mediate_Mapping * that = static_cast< uno_Mediate_Mapping * >( pMapping );
247         uno_Mapping * pFrom2Uno = that->aFrom2Uno.get();
248 
249         uno_Interface * pUnoI = 0;
250         (*pFrom2Uno->mapInterface)( pFrom2Uno, (void **) &pUnoI, pInterface, pInterfaceTypeDescr );
251         if (0 == pUnoI)
252         {
253             void * pOut = *ppOut;
254             if (0 != pOut)
255             {
256                 uno_ExtEnvironment * pTo = that->aTo.get()->pExtEnv;
257                 OSL_ENSURE( 0 != pTo, "### cannot release out interface: leaking!" );
258                 if (0 != pTo)
259                     (*pTo->releaseInterface)( pTo, pOut );
260                 *ppOut = 0; // set to 0 anyway, because mapping was not successfull!
261             }
262         }
263         else
264         {
265             uno_Mapping * pUno2To = that->aUno2To.get();
266             (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr );
267             (*pUnoI->release)( pUnoI );
268         }
269     }
270 }
271 }
272 //__________________________________________________________________________________________________
273 uno_Mediate_Mapping::uno_Mediate_Mapping(
274     const Environment & rFrom_, const Environment & rTo_,
275     const Mapping & rFrom2Uno_, const Mapping & rUno2To_,
276     const OUString & rAddPurpose_ )
277     SAL_THROW( () )
278     : nRef( 1 )
279     , aFrom( rFrom_ )
280     , aTo( rTo_ )
281     , aFrom2Uno( rFrom2Uno_ )
282     , aUno2To( rUno2To_ )
283     , aAddPurpose( rAddPurpose_ )
284 {
285     uno_Mapping::acquire        = mediate_acquire;
286     uno_Mapping::release        = mediate_release;
287     uno_Mapping::mapInterface   = mediate_mapInterface;
288 }
289 
290 //==================================================================================================
291 static inline OUString getMappingName(
292     const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
293     SAL_THROW( () )
294 {
295     OUStringBuffer aKey( 64 );
296     aKey.append( rAddPurpose );
297     aKey.append( (sal_Unicode)';' );
298     aKey.append( rFrom.getTypeName() );
299     aKey.append( (sal_Unicode)'[' );
300     aKey.append( reinterpret_cast< sal_IntPtr >(rFrom.get()), 16 );
301     aKey.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
302     aKey.append( rTo.getTypeName() );
303     aKey.append( (sal_Unicode)'[' );
304     aKey.append( reinterpret_cast< sal_IntPtr >(rTo.get()), 16 );
305     aKey.append( (sal_Unicode)']' );
306     return aKey.makeStringAndClear();
307 }
308 //==================================================================================================
309 static inline OUString getBridgeName(
310     const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
311     SAL_THROW( () )
312 {
313     OUStringBuffer aBridgeName( 16 );
314     if (rAddPurpose.getLength())
315     {
316         aBridgeName.append( rAddPurpose );
317         aBridgeName.append( (sal_Unicode)'_' );
318     }
319     aBridgeName.append( EnvDcp::getTypeName(rFrom.getTypeName()) );
320     aBridgeName.append( (sal_Unicode)'_' );
321     aBridgeName.append( EnvDcp::getTypeName(rTo.getTypeName()) );
322     return aBridgeName.makeStringAndClear();
323 }
324 //==================================================================================================
325 static inline void setNegativeBridge( const OUString & rBridgeName )
326     SAL_THROW( () )
327 {
328     MappingsData & rData = getMappingsData();
329     MutexGuard aGuard( rData.aNegativeLibsMutex );
330     rData.aNegativeLibs.insert( rBridgeName );
331 }
332 //==================================================================================================
333 static inline oslModule loadModule( const OUString & rBridgeName )
334     SAL_THROW( () )
335 {
336     sal_Bool bNeg;
337     {
338     MappingsData & rData = getMappingsData();
339     MutexGuard aGuard( rData.aNegativeLibsMutex );
340     const t_OUStringSet::const_iterator iFind( rData.aNegativeLibs.find( rBridgeName ) );
341     bNeg = (iFind != rData.aNegativeLibs.end());
342     }
343 
344     if (! bNeg)
345     {
346         oslModule hModule = cppu::detail::loadModule( rBridgeName );
347 
348         if (hModule)
349             return hModule;
350 
351         setNegativeBridge( rBridgeName ); // no load again
352     }
353     return 0;
354 }
355 //==================================================================================================
356 static Mapping loadExternalMapping(
357     const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
358     SAL_THROW( () )
359 {
360     OSL_ASSERT( rFrom.is() && rTo.is() );
361     if (rFrom.is() && rTo.is())
362     {
363         // find proper lib
364         oslModule hModule = 0;
365         OUString aName;
366 
367         if (EnvDcp::getTypeName(rFrom.getTypeName()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
368             hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) );
369         if (! hModule)
370             hModule = loadModule( aName = getBridgeName( rFrom, rTo, rAddPurpose ) );
371         if (! hModule)
372             hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) );
373 
374         if (hModule)
375         {
376             OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM(UNO_EXT_GETMAPPING) );
377             uno_ext_getMappingFunc fpGetMapFunc =
378                 (uno_ext_getMappingFunc)::osl_getFunctionSymbol(
379                     hModule, aSymbolName.pData );
380 
381             if (fpGetMapFunc)
382             {
383                 Mapping aExt;
384                 (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() );
385                 OSL_ASSERT( aExt.is() );
386                 if (aExt.is())
387                 {
388                     ::rtl_registerModuleForUnloading( hModule );
389                     return aExt;
390                 }
391             }
392             ::osl_unloadModule( hModule );
393             setNegativeBridge( aName );
394         }
395     }
396     return Mapping();
397 }
398 
399 //==================================================================================================
400 static Mapping getDirectMapping(
401     const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose = OUString() )
402     SAL_THROW( () )
403 {
404     OSL_ASSERT( rFrom.is() && rTo.is() );
405     if (rFrom.is() && rTo.is())
406     {
407         MappingsData & rData = getMappingsData();
408         ClearableMutexGuard aGuard( rData.aMappingsMutex );
409 
410         // try to find registered mapping
411         const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
412             getMappingName( rFrom, rTo, rAddPurpose ) ) );
413 
414         if (iFind == rData.aName2Entry.end())
415         {
416             aGuard.clear();
417             return loadExternalMapping( rFrom, rTo, rAddPurpose );
418         }
419         else
420         {
421             return Mapping( (*iFind).second->pMapping );
422         }
423     }
424     return Mapping();
425 }
426 
427 //--------------------------------------------------------------------------------------------------
428 static inline Mapping createMediateMapping(
429     const Environment & rFrom, const Environment & rTo,
430     const Mapping & rFrom2Uno, const Mapping & rUno2To,
431     const OUString & rAddPurpose )
432     SAL_THROW( () )
433 {
434     uno_Mapping * pRet = new uno_Mediate_Mapping(
435         rFrom, rTo, rFrom2Uno, rUno2To, rAddPurpose ); // ref count initially 1
436     uno_registerMapping(
437         &pRet, mediate_free, rFrom.get(), rTo.get(), rAddPurpose.pData );
438     Mapping aRet( pRet );
439     (*pRet->release)( pRet );
440     return aRet;
441 }
442 //==================================================================================================
443 static Mapping getMediateMapping(
444     const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
445     SAL_THROW( () )
446 {
447     Environment aUno;
448     Mapping aUno2To;
449 
450     // backwards: from dest to source of mapping chain
451 
452     // connect to uno
453     OUString aUnoEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) );
454     if (rTo.getTypeName() == aUnoEnvTypeName) // to is uno
455     {
456         aUno = rTo;
457         // no Uno2To mapping necessary
458     }
459     else
460     {
461         // get registered uno env
462         ::uno_getEnvironment( (uno_Environment **)&aUno, aUnoEnvTypeName.pData, 0 );
463 
464         aUno2To = getDirectMapping( aUno, rTo );
465         // : uno <-> to
466         if (! aUno2To.is())
467             return Mapping();
468     }
469 
470     // connect to uno
471     if (rAddPurpose.getLength()) // insert purpose mapping between new ano_uno <-> uno
472     {
473         // create anonymous uno env
474         Environment aAnUno;
475         ::uno_createEnvironment( (uno_Environment **)&aAnUno, aUnoEnvTypeName.pData, 0 );
476 
477         Mapping aAnUno2Uno( getDirectMapping( aAnUno, aUno, rAddPurpose ) );
478         if (! aAnUno2Uno.is())
479             return Mapping();
480 
481         if (aUno2To.is()) // to is not uno
482         {
483             // create another purposed mediate mapping
484             aUno2To = createMediateMapping( aAnUno, rTo, aAnUno2Uno, aUno2To, rAddPurpose );
485             // : ano_uno <-> uno <-> to
486         }
487         else
488         {
489             aUno2To = aAnUno2Uno;
490             // : ano_uno <-> to (i.e., uno)
491         }
492         aUno = aAnUno;
493     }
494 
495     Mapping aFrom2Uno( getDirectMapping( rFrom, aUno ) );
496     if (aFrom2Uno.is() && aUno2To.is())
497     {
498         return createMediateMapping( rFrom, rTo, aFrom2Uno, aUno2To, rAddPurpose );
499         // : from <-> some uno ...
500     }
501 
502     return Mapping();
503 }
504 }
505 
506 using namespace ::cppu;
507 
508 extern "C"
509 {
510 //##################################################################################################
511 void SAL_CALL uno_getMapping(
512     uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo,
513     rtl_uString * pAddPurpose )
514     SAL_THROW_EXTERN_C()
515 {
516     OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" );
517     if (*ppMapping)
518     {
519         (*(*ppMapping)->release)( *ppMapping );
520         *ppMapping = 0;
521     }
522 
523     Mapping aRet;
524     Environment aFrom( pFrom ), aTo( pTo );
525 
526     OUString aAddPurpose;
527     if (pAddPurpose)
528         aAddPurpose = pAddPurpose;
529 
530     MappingsData & rData = getMappingsData();
531 
532     // try registered mapping
533     {
534     MutexGuard aGuard( rData.aMappingsMutex );
535     const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
536         getMappingName( aFrom, aTo, aAddPurpose ) ) );
537     if (iFind != rData.aName2Entry.end())
538         aRet = (*iFind).second->pMapping;
539     }
540 
541     // See if an identity mapping does fit.
542     if (!aRet.is() && pFrom == pTo && !aAddPurpose.getLength())
543         aRet = createIdentityMapping(pFrom);
544 
545     if (!aRet.is())
546     {
547         getCascadeMapping(ppMapping, pFrom, pTo, pAddPurpose);
548 
549         if (*ppMapping)
550             return;
551     }
552 
553     if (! aRet.is()) // try callback chain
554     {
555         MutexGuard aGuard( rData.aCallbacksMutex );
556         for ( t_CallbackSet::const_iterator iPos( rData.aCallbacks.begin() );
557               iPos != rData.aCallbacks.end(); ++iPos )
558         {
559             (**iPos)( ppMapping, pFrom, pTo, aAddPurpose.pData );
560             if (*ppMapping)
561                 return;
562         }
563     }
564 
565     if (! aRet.is())
566     {
567         aRet = loadExternalMapping( aFrom, aTo, aAddPurpose ); // direct try
568         if (! aRet.is())
569             aRet = getMediateMapping( aFrom, aTo, aAddPurpose ); // try via uno
570     }
571 
572     if (aRet.is())
573     {
574         (*aRet.get()->acquire)( aRet.get() );
575         *ppMapping = aRet.get();
576     }
577 }
578 //##################################################################################################
579 void SAL_CALL uno_getMappingByName(
580     uno_Mapping ** ppMapping, rtl_uString * pFrom, rtl_uString * pTo,
581     rtl_uString * pAddPurpose )
582     SAL_THROW_EXTERN_C()
583 {
584     OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" );
585     if (*ppMapping)
586     {
587         (*(*ppMapping)->release)( *ppMapping );
588         *ppMapping = 0;
589     }
590 
591     uno_Environment * pEFrom = 0;
592     uno_getEnvironment( &pEFrom, pFrom, 0 );
593     OSL_ENSURE( pEFrom, "### cannot get source environment!" );
594     if (pEFrom)
595     {
596         uno_Environment * pETo = 0;
597         uno_getEnvironment( &pETo, pTo, 0 );
598         OSL_ENSURE( pETo, "### cannot get target environment!" );
599         if (pETo)
600         {
601             ::uno_getMapping( ppMapping, pEFrom, pETo, pAddPurpose );
602             (*pETo->release)( pETo );
603         }
604         (*pEFrom->release)( pEFrom );
605     }
606 }
607 
608 //##################################################################################################
609 void SAL_CALL uno_registerMapping(
610     uno_Mapping ** ppMapping, uno_freeMappingFunc freeMapping,
611     uno_Environment * pFrom, uno_Environment * pTo, rtl_uString * pAddPurpose )
612     SAL_THROW_EXTERN_C()
613 {
614     MappingsData & rData = getMappingsData();
615     ClearableMutexGuard aGuard( rData.aMappingsMutex );
616 
617     const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( *ppMapping ) );
618     if (iFind == rData.aMapping2Entry.end())
619     {
620         OUString aMappingName(
621             getMappingName( pFrom, pTo, pAddPurpose ? OUString(pAddPurpose) : OUString() ) );
622 #if OSL_DEBUG_LEVEL > 1
623         OString cstr( OUStringToOString( aMappingName, RTL_TEXTENCODING_ASCII_US ) );
624         OSL_TRACE( "> inserting new mapping: %s", cstr.getStr() );
625 #endif
626         // count initially 1
627         MappingEntry * pEntry = new MappingEntry( *ppMapping, freeMapping, aMappingName );
628         rData.aName2Entry[ aMappingName ] = pEntry;
629         rData.aMapping2Entry[ *ppMapping ] = pEntry;
630     }
631     else
632     {
633         MappingEntry * pEntry = (*iFind).second;
634         ++pEntry->nRef;
635 
636         if (pEntry->pMapping != *ppMapping) // exchange mapping to be registered
637         {
638             (*pEntry->pMapping->acquire)( pEntry->pMapping );
639             --pEntry->nRef; // correct count; kill mapping to be registered
640             aGuard.clear();
641             (*freeMapping)( *ppMapping );
642             *ppMapping = pEntry->pMapping;
643         }
644     }
645 }
646 //##################################################################################################
647 void SAL_CALL uno_revokeMapping(
648     uno_Mapping * pMapping )
649     SAL_THROW_EXTERN_C()
650 {
651     MappingsData & rData = getMappingsData();
652     ClearableMutexGuard aGuard( rData.aMappingsMutex );
653 
654     const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( pMapping ) );
655     OSL_ASSERT( iFind != rData.aMapping2Entry.end() );
656     MappingEntry * pEntry = (*iFind).second;
657     if (! --pEntry->nRef)
658     {
659         rData.aMapping2Entry.erase( pEntry->pMapping );
660         rData.aName2Entry.erase( pEntry->aMappingName );
661         aGuard.clear();
662 #if OSL_DEBUG_LEVEL > 1
663         OString cstr( OUStringToOString( pEntry->aMappingName, RTL_TEXTENCODING_ASCII_US  ) );
664         OSL_TRACE( "> revoking mapping %s", cstr.getStr() );
665 #endif
666         (*pEntry->freeMapping)( pEntry->pMapping );
667         delete pEntry;
668     }
669 }
670 
671 //##################################################################################################
672 void SAL_CALL uno_registerMappingCallback(
673     uno_getMappingFunc pCallback )
674     SAL_THROW_EXTERN_C()
675 {
676     OSL_ENSURE( pCallback, "### null ptr!" );
677     MappingsData & rData = getMappingsData();
678     MutexGuard aGuard( rData.aCallbacksMutex );
679     rData.aCallbacks.insert( pCallback );
680 }
681 //##################################################################################################
682 void SAL_CALL uno_revokeMappingCallback(
683     uno_getMappingFunc pCallback )
684     SAL_THROW_EXTERN_C()
685 {
686     OSL_ENSURE( pCallback, "### null ptr!" );
687     MappingsData & rData = getMappingsData();
688     MutexGuard aGuard( rData.aCallbacksMutex );
689     rData.aCallbacks.erase( pCallback );
690 }
691 } // extern "C"
692 
693