Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "IdentityMapping.hxx"
22 :
23 : #include <boost/unordered_map.hpp>
24 : #include <set>
25 : #include <algorithm>
26 :
27 : #include "rtl/ustring.hxx"
28 : #include "rtl/ustrbuf.hxx"
29 : #include "osl/module.h"
30 : #include "osl/diagnose.h"
31 : #include "osl/mutex.hxx"
32 : #include "osl/interlck.h"
33 :
34 : #include "uno/dispatcher.h"
35 : #include "uno/mapping.h"
36 : #include "uno/lbnames.h"
37 : #include "uno/environment.hxx"
38 :
39 : #include "typelib/typedescription.h"
40 :
41 : #include "cppu/EnvDcp.hxx"
42 : #include "cascade_mapping.hxx"
43 : #include "loadmodule.hxx"
44 :
45 : using namespace std;
46 : using namespace osl;
47 : using namespace com::sun::star::uno;
48 : using ::rtl::OUString;
49 : using ::rtl::OUStringBuffer;
50 : using ::rtl::OUStringToOString;
51 : using ::rtl::OString;
52 :
53 : namespace cppu
54 : {
55 :
56 : class Mapping
57 : {
58 : uno_Mapping * _pMapping;
59 :
60 : public:
61 : inline explicit Mapping( uno_Mapping * pMapping = 0 ) SAL_THROW(());
62 : inline Mapping( const Mapping & rMapping ) SAL_THROW(());
63 : inline ~Mapping() SAL_THROW(());
64 : inline Mapping & SAL_CALL operator = ( uno_Mapping * pMapping ) SAL_THROW(());
65 8838 : inline Mapping & SAL_CALL operator = ( const Mapping & rMapping ) SAL_THROW(())
66 8838 : { return operator = ( rMapping._pMapping ); }
67 109108 : inline uno_Mapping * SAL_CALL get() const SAL_THROW(())
68 109108 : { return _pMapping; }
69 199514 : inline sal_Bool SAL_CALL is() const SAL_THROW(())
70 199514 : { return (_pMapping != 0); }
71 : };
72 : //__________________________________________________________________________________________________
73 45210 : inline Mapping::Mapping( uno_Mapping * pMapping ) SAL_THROW(())
74 45210 : : _pMapping( pMapping )
75 : {
76 45210 : if (_pMapping)
77 4 : (*_pMapping->acquire)( _pMapping );
78 45210 : }
79 : //__________________________________________________________________________________________________
80 8838 : inline Mapping::Mapping( const Mapping & rMapping ) SAL_THROW(())
81 8838 : : _pMapping( rMapping._pMapping )
82 : {
83 8838 : if (_pMapping)
84 8838 : (*_pMapping->acquire)( _pMapping );
85 8838 : }
86 : //__________________________________________________________________________________________________
87 54048 : inline Mapping::~Mapping() SAL_THROW(())
88 : {
89 54048 : if (_pMapping)
90 54046 : (*_pMapping->release)( _pMapping );
91 54048 : }
92 : //__________________________________________________________________________________________________
93 36372 : inline Mapping & Mapping::operator = ( uno_Mapping * pMapping ) SAL_THROW(())
94 : {
95 36372 : if (pMapping)
96 36370 : (*pMapping->acquire)( pMapping );
97 36372 : if (_pMapping)
98 0 : (*_pMapping->release)( _pMapping );
99 36372 : _pMapping = pMapping;
100 36372 : return *this;
101 : }
102 :
103 : //==================================================================================================
104 20438 : struct MappingEntry
105 : {
106 : sal_Int32 nRef;
107 : uno_Mapping * pMapping;
108 : uno_freeMappingFunc freeMapping;
109 : OUString aMappingName;
110 :
111 20464 : MappingEntry(
112 : uno_Mapping * pMapping_, uno_freeMappingFunc freeMapping_,
113 : const OUString & rMappingName_ )
114 : SAL_THROW(())
115 : : nRef( 1 )
116 : , pMapping( pMapping_ )
117 : , freeMapping( freeMapping_ )
118 20464 : , aMappingName( rMappingName_ )
119 20464 : {}
120 : };
121 : //--------------------------------------------------------------------------------------------------
122 : struct FctOUStringHash : public std::unary_function< const OUString &, size_t >
123 : {
124 77274 : size_t operator()( const OUString & rKey ) const SAL_THROW(())
125 77274 : { return (size_t)rKey.hashCode(); }
126 : };
127 : //--------------------------------------------------------------------------------------------------
128 : struct FctPtrHash : public std::unary_function< uno_Mapping *, size_t >
129 : {
130 81804 : size_t operator()( uno_Mapping * pKey ) const SAL_THROW(())
131 81804 : { return (size_t)pKey; }
132 : };
133 :
134 : typedef boost::unordered_map<
135 : OUString, MappingEntry *, FctOUStringHash, equal_to< OUString > > t_OUString2Entry;
136 : typedef boost::unordered_map<
137 : uno_Mapping *, MappingEntry *, FctPtrHash, equal_to< uno_Mapping * > > t_Mapping2Entry;
138 :
139 : typedef set< uno_getMappingFunc > t_CallbackSet;
140 : typedef set< OUString > t_OUStringSet;
141 :
142 : //==================================================================================================
143 384 : struct MappingsData
144 : {
145 : Mutex aMappingsMutex;
146 : t_OUString2Entry aName2Entry;
147 : t_Mapping2Entry aMapping2Entry;
148 :
149 : Mutex aCallbacksMutex;
150 : t_CallbackSet aCallbacks;
151 :
152 : Mutex aNegativeLibsMutex;
153 : t_OUStringSet aNegativeLibs;
154 : };
155 : //--------------------------------------------------------------------------------------------------
156 86116 : static MappingsData & getMappingsData() SAL_THROW(())
157 : {
158 : static MappingsData * s_p = 0;
159 86116 : if (! s_p)
160 : {
161 384 : MutexGuard aGuard( Mutex::getGlobalMutex() );
162 384 : if (! s_p)
163 : {
164 : //TODO This memory is leaked; see #i63473# for when this should be
165 : // changed again:
166 384 : s_p = new MappingsData;
167 384 : }
168 : }
169 86116 : return *s_p;
170 : }
171 :
172 : /**
173 : * This class mediates two different mapping via uno, e.g. form any language to uno,
174 : * then from uno to any other language.
175 : */
176 2 : struct uno_Mediate_Mapping : public uno_Mapping
177 : {
178 : sal_Int32 nRef;
179 :
180 : Environment aFrom;
181 : Environment aTo;
182 :
183 : Mapping aFrom2Uno;
184 : Mapping aUno2To;
185 :
186 : OUString aAddPurpose;
187 :
188 : uno_Mediate_Mapping(
189 : const Environment & rFrom_, const Environment & rTo_,
190 : const Mapping & rFrom2Uno_, const Mapping & rUno2To_,
191 : const OUString & rAddPurpose )
192 : SAL_THROW(());
193 : };
194 : extern "C"
195 : {
196 : //--------------------------------------------------------------------------------------------------
197 2 : static void SAL_CALL mediate_free( uno_Mapping * pMapping )
198 : SAL_THROW(())
199 : {
200 2 : delete static_cast< uno_Mediate_Mapping * >( pMapping );
201 2 : }
202 : //--------------------------------------------------------------------------------------------------
203 6 : static void SAL_CALL mediate_acquire( uno_Mapping * pMapping )
204 : SAL_THROW(())
205 : {
206 6 : if (1 == osl_atomic_increment(
207 : & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
208 : {
209 : uno_registerMapping(
210 : &pMapping, mediate_free,
211 : static_cast< uno_Mediate_Mapping * >( pMapping )->aFrom.get(),
212 : static_cast< uno_Mediate_Mapping * >( pMapping )->aTo.get(),
213 0 : static_cast< uno_Mediate_Mapping * >( pMapping )->aAddPurpose.pData );
214 : }
215 6 : }
216 : //--------------------------------------------------------------------------------------------------
217 8 : static void SAL_CALL mediate_release( uno_Mapping * pMapping )
218 : SAL_THROW(())
219 : {
220 8 : if (! osl_atomic_decrement(
221 : & static_cast< uno_Mediate_Mapping * >( pMapping )->nRef ))
222 : {
223 2 : uno_revokeMapping( pMapping );
224 : }
225 8 : }
226 : //--------------------------------------------------------------------------------------------------
227 2 : static void SAL_CALL mediate_mapInterface(
228 : uno_Mapping * pMapping,
229 : void ** ppOut, void * pInterface,
230 : typelib_InterfaceTypeDescription * pInterfaceTypeDescr )
231 : SAL_THROW(())
232 : {
233 : OSL_ENSURE( pMapping && ppOut, "### null ptr!" );
234 2 : if (pMapping && ppOut)
235 : {
236 2 : uno_Mediate_Mapping * that = static_cast< uno_Mediate_Mapping * >( pMapping );
237 2 : uno_Mapping * pFrom2Uno = that->aFrom2Uno.get();
238 :
239 2 : uno_Interface * pUnoI = 0;
240 2 : (*pFrom2Uno->mapInterface)( pFrom2Uno, (void **) &pUnoI, pInterface, pInterfaceTypeDescr );
241 2 : if (0 == pUnoI)
242 : {
243 0 : void * pOut = *ppOut;
244 0 : if (0 != pOut)
245 : {
246 0 : uno_ExtEnvironment * pTo = that->aTo.get()->pExtEnv;
247 : OSL_ENSURE( 0 != pTo, "### cannot release out interface: leaking!" );
248 0 : if (0 != pTo)
249 0 : (*pTo->releaseInterface)( pTo, pOut );
250 0 : *ppOut = 0; // set to 0 anyway, because mapping was not successful!
251 : }
252 : }
253 : else
254 : {
255 2 : uno_Mapping * pUno2To = that->aUno2To.get();
256 2 : (*pUno2To->mapInterface)( pUno2To, ppOut, pUnoI, pInterfaceTypeDescr );
257 2 : (*pUnoI->release)( pUnoI );
258 : }
259 : }
260 2 : }
261 : }
262 : //__________________________________________________________________________________________________
263 2 : uno_Mediate_Mapping::uno_Mediate_Mapping(
264 : const Environment & rFrom_, const Environment & rTo_,
265 : const Mapping & rFrom2Uno_, const Mapping & rUno2To_,
266 : const OUString & rAddPurpose_ )
267 : SAL_THROW(())
268 : : nRef( 1 )
269 : , aFrom( rFrom_ )
270 : , aTo( rTo_ )
271 : , aFrom2Uno( rFrom2Uno_ )
272 : , aUno2To( rUno2To_ )
273 2 : , aAddPurpose( rAddPurpose_ )
274 : {
275 2 : uno_Mapping::acquire = mediate_acquire;
276 2 : uno_Mapping::release = mediate_release;
277 2 : uno_Mapping::mapInterface = mediate_mapInterface;
278 2 : }
279 :
280 : //==================================================================================================
281 56836 : static inline OUString getMappingName(
282 : const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
283 : SAL_THROW(())
284 : {
285 56836 : OUStringBuffer aKey( 64 );
286 56836 : aKey.append( rAddPurpose );
287 56836 : aKey.append( (sal_Unicode)';' );
288 56836 : aKey.append( rFrom.getTypeName() );
289 56836 : aKey.append( (sal_Unicode)'[' );
290 56836 : aKey.append( reinterpret_cast< sal_IntPtr >(rFrom.get()), 16 );
291 56836 : aKey.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
292 56836 : aKey.append( rTo.getTypeName() );
293 56836 : aKey.append( (sal_Unicode)'[' );
294 56836 : aKey.append( reinterpret_cast< sal_IntPtr >(rTo.get()), 16 );
295 56836 : aKey.append( (sal_Unicode)']' );
296 56836 : return aKey.makeStringAndClear();
297 : }
298 : //==================================================================================================
299 8838 : static inline OUString getBridgeName(
300 : const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
301 : SAL_THROW(())
302 : {
303 8838 : OUStringBuffer aBridgeName( 16 );
304 8838 : if (!rAddPurpose.isEmpty())
305 : {
306 0 : aBridgeName.append( rAddPurpose );
307 0 : aBridgeName.append( (sal_Unicode)'_' );
308 : }
309 8838 : aBridgeName.append( EnvDcp::getTypeName(rFrom.getTypeName()) );
310 8838 : aBridgeName.append( (sal_Unicode)'_' );
311 8838 : aBridgeName.append( EnvDcp::getTypeName(rTo.getTypeName()) );
312 8838 : return aBridgeName.makeStringAndClear();
313 : }
314 : //==================================================================================================
315 4 : static inline void setNegativeBridge( const OUString & rBridgeName )
316 : SAL_THROW(())
317 : {
318 4 : MappingsData & rData = getMappingsData();
319 4 : MutexGuard aGuard( rData.aNegativeLibsMutex );
320 4 : rData.aNegativeLibs.insert( rBridgeName );
321 4 : }
322 :
323 : #ifdef DISABLE_DYNLOADING
324 :
325 : static uno_ext_getMappingFunc selectMapFunc( const OUString & rBridgeName )
326 : SAL_THROW(())
327 : {
328 : if (rBridgeName.equalsAscii( CPPU_CURRENT_LANGUAGE_BINDING_NAME "_uno" ))
329 : return CPPU_ENV_uno_ext_getMapping;
330 : #ifdef SOLAR_JAVA
331 : if (rBridgeName.equalsAscii( "java" "_uno" ))
332 : return java_uno_ext_getMapping;
333 : #endif
334 :
335 : #if 0
336 : // I don't think the affine or log bridges will be needed on any
337 : // DISABLE_DYNLOADING platform (iOS at least, possibly Android), but if
338 : // somebody wants to experiment, need to find out then whether these are
339 : // needed.
340 : if (rBridgeName.equalsAscii( "affine_uno_uno" ))
341 : return affine_uno_uno_ext_getMapping;
342 : if (rBridgeName.equalsAscii( "log_uno_uno" ))
343 : return log_uno_uno_ext_getMapping;
344 : #endif
345 : return 0;
346 : }
347 :
348 : #else
349 :
350 8838 : static inline oslModule loadModule( const OUString & rBridgeName )
351 : SAL_THROW(())
352 : {
353 : sal_Bool bNeg;
354 : {
355 8838 : MappingsData & rData = getMappingsData();
356 8838 : MutexGuard aGuard( rData.aNegativeLibsMutex );
357 8838 : const t_OUStringSet::const_iterator iFind( rData.aNegativeLibs.find( rBridgeName ) );
358 8838 : bNeg = (iFind != rData.aNegativeLibs.end());
359 : }
360 :
361 8838 : if (! bNeg)
362 : {
363 8838 : oslModule hModule = cppu::detail::loadModule( rBridgeName );
364 :
365 8838 : if (hModule)
366 8834 : return hModule;
367 :
368 4 : setNegativeBridge( rBridgeName ); // no load again
369 : }
370 4 : return 0;
371 : }
372 :
373 : #endif
374 :
375 : //==================================================================================================
376 8836 : static Mapping loadExternalMapping(
377 : const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
378 : SAL_THROW(())
379 : {
380 : OSL_ASSERT( rFrom.is() && rTo.is() );
381 8836 : if (rFrom.is() && rTo.is())
382 : {
383 : #ifdef DISABLE_DYNLOADING
384 : OUString aName;
385 : uno_ext_getMappingFunc fpGetMapFunc = 0;
386 :
387 : if (EnvDcp::getTypeName(rFrom.getTypeName()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO) ))
388 : {
389 : aName = getBridgeName( rTo, rFrom, rAddPurpose );
390 : fpGetMapFunc = selectMapFunc( aName );
391 : }
392 : if (! fpGetMapFunc)
393 : {
394 : aName = getBridgeName( rFrom, rTo, rAddPurpose );
395 : fpGetMapFunc = selectMapFunc( aName );
396 : }
397 : if (! fpGetMapFunc)
398 : {
399 : aName = getBridgeName( rTo, rFrom, rAddPurpose );
400 : fpGetMapFunc = selectMapFunc( aName );
401 : }
402 :
403 : if (! fpGetMapFunc)
404 : {
405 : #if OSL_DEBUG_LEVEL > 1
406 : OSL_TRACE( "Could not find mapfunc for %s", OUStringToOString( aName, RTL_TEXTENCODING_ASCII_US ).getStr());
407 : #endif
408 : return Mapping();
409 : }
410 :
411 : if (fpGetMapFunc)
412 : {
413 : Mapping aExt;
414 : (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() );
415 : OSL_ASSERT( aExt.is() );
416 : if (aExt.is())
417 : return aExt;
418 : }
419 : #else
420 : // find proper lib
421 8836 : oslModule hModule = 0;
422 8836 : OUString aName;
423 :
424 8836 : if ( EnvDcp::getTypeName(rFrom.getTypeName()) == UNO_LB_UNO )
425 8314 : hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) );
426 8836 : if (! hModule)
427 522 : hModule = loadModule( aName = getBridgeName( rFrom, rTo, rAddPurpose ) );
428 8836 : if (! hModule)
429 2 : hModule = loadModule( aName = getBridgeName( rTo, rFrom, rAddPurpose ) );
430 :
431 8836 : if (hModule)
432 : {
433 8834 : OUString aSymbolName( UNO_EXT_GETMAPPING );
434 : uno_ext_getMappingFunc fpGetMapFunc =
435 : (uno_ext_getMappingFunc)::osl_getFunctionSymbol(
436 8834 : hModule, aSymbolName.pData );
437 :
438 8834 : if (fpGetMapFunc)
439 : {
440 8834 : Mapping aExt;
441 8834 : (*fpGetMapFunc)( (uno_Mapping **)&aExt, rFrom.get(), rTo.get() );
442 : OSL_ASSERT( aExt.is() );
443 8834 : if (aExt.is())
444 : {
445 8834 : return aExt;
446 0 : }
447 : }
448 0 : ::osl_unloadModule( hModule );
449 0 : setNegativeBridge( aName );
450 2 : }
451 : #endif
452 : }
453 2 : return Mapping();
454 : }
455 :
456 : //==================================================================================================
457 4 : static Mapping getDirectMapping(
458 : const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose = OUString() )
459 : SAL_THROW(())
460 : {
461 : OSL_ASSERT( rFrom.is() && rTo.is() );
462 4 : if (rFrom.is() && rTo.is())
463 : {
464 4 : MappingsData & rData = getMappingsData();
465 4 : ClearableMutexGuard aGuard( rData.aMappingsMutex );
466 :
467 : // try to find registered mapping
468 : const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
469 4 : getMappingName( rFrom, rTo, rAddPurpose ) ) );
470 :
471 4 : if (iFind == rData.aName2Entry.end())
472 : {
473 2 : aGuard.clear();
474 2 : return loadExternalMapping( rFrom, rTo, rAddPurpose );
475 : }
476 : else
477 : {
478 2 : return Mapping( (*iFind).second->pMapping );
479 4 : }
480 : }
481 0 : return Mapping();
482 : }
483 :
484 : //--------------------------------------------------------------------------------------------------
485 2 : static inline Mapping createMediateMapping(
486 : const Environment & rFrom, const Environment & rTo,
487 : const Mapping & rFrom2Uno, const Mapping & rUno2To,
488 : const OUString & rAddPurpose )
489 : SAL_THROW(())
490 : {
491 : uno_Mapping * pRet = new uno_Mediate_Mapping(
492 2 : rFrom, rTo, rFrom2Uno, rUno2To, rAddPurpose ); // ref count initially 1
493 : uno_registerMapping(
494 2 : &pRet, mediate_free, rFrom.get(), rTo.get(), rAddPurpose.pData );
495 2 : Mapping aRet( pRet );
496 2 : (*pRet->release)( pRet );
497 2 : return aRet;
498 : }
499 : //==================================================================================================
500 2 : static Mapping getMediateMapping(
501 : const Environment & rFrom, const Environment & rTo, const OUString & rAddPurpose )
502 : SAL_THROW(())
503 : {
504 2 : Environment aUno;
505 4 : Mapping aUno2To;
506 :
507 : // backwards: from dest to source of mapping chain
508 :
509 : // connect to uno
510 4 : OUString aUnoEnvTypeName( UNO_LB_UNO );
511 2 : if (rTo.getTypeName() == aUnoEnvTypeName) // to is uno
512 : {
513 0 : aUno = rTo;
514 : // no Uno2To mapping necessary
515 : }
516 : else
517 : {
518 : // get registered uno env
519 2 : ::uno_getEnvironment( (uno_Environment **)&aUno, aUnoEnvTypeName.pData, 0 );
520 :
521 2 : aUno2To = getDirectMapping( aUno, rTo );
522 : // : uno <-> to
523 2 : if (! aUno2To.is())
524 0 : return Mapping();
525 : }
526 :
527 : // connect to uno
528 2 : if (!rAddPurpose.isEmpty()) // insert purpose mapping between new ano_uno <-> uno
529 : {
530 : // create anonymous uno env
531 0 : Environment aAnUno;
532 0 : ::uno_createEnvironment( (uno_Environment **)&aAnUno, aUnoEnvTypeName.pData, 0 );
533 :
534 0 : Mapping aAnUno2Uno( getDirectMapping( aAnUno, aUno, rAddPurpose ) );
535 0 : if (! aAnUno2Uno.is())
536 0 : return Mapping();
537 :
538 0 : if (aUno2To.is()) // to is not uno
539 : {
540 : // create another purposed mediate mapping
541 0 : aUno2To = createMediateMapping( aAnUno, rTo, aAnUno2Uno, aUno2To, rAddPurpose );
542 : // : ano_uno <-> uno <-> to
543 : }
544 : else
545 : {
546 0 : aUno2To = aAnUno2Uno;
547 : // : ano_uno <-> to (i.e., uno)
548 : }
549 0 : aUno = aAnUno;
550 : }
551 :
552 4 : Mapping aFrom2Uno( getDirectMapping( rFrom, aUno ) );
553 2 : if (aFrom2Uno.is() && aUno2To.is())
554 : {
555 2 : return createMediateMapping( rFrom, rTo, aFrom2Uno, aUno2To, rAddPurpose );
556 : // : from <-> some uno ...
557 : }
558 :
559 2 : return Mapping();
560 : }
561 : }
562 :
563 : using namespace ::cppu;
564 :
565 : extern "C"
566 : {
567 : //##################################################################################################
568 36368 : void SAL_CALL uno_getMapping(
569 : uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo,
570 : rtl_uString * pAddPurpose )
571 : SAL_THROW_EXTERN_C()
572 : {
573 : OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" );
574 36368 : if (*ppMapping)
575 : {
576 0 : (*(*ppMapping)->release)( *ppMapping );
577 0 : *ppMapping = 0;
578 : }
579 :
580 36368 : Mapping aRet;
581 72736 : Environment aFrom( pFrom ), aTo( pTo );
582 :
583 72736 : OUString aAddPurpose;
584 36368 : if (pAddPurpose)
585 36264 : aAddPurpose = pAddPurpose;
586 :
587 36368 : MappingsData & rData = getMappingsData();
588 :
589 : // try registered mapping
590 : {
591 36368 : MutexGuard aGuard( rData.aMappingsMutex );
592 : const t_OUString2Entry::const_iterator iFind( rData.aName2Entry.find(
593 36368 : getMappingName( aFrom, aTo, aAddPurpose ) ) );
594 36368 : if (iFind != rData.aName2Entry.end())
595 15906 : aRet = (*iFind).second->pMapping;
596 : }
597 :
598 : // See if an identity mapping does fit.
599 36368 : if (!aRet.is() && pFrom == pTo && aAddPurpose.isEmpty())
600 11628 : aRet = createIdentityMapping(pFrom);
601 :
602 36368 : if (!aRet.is())
603 : {
604 8834 : getCascadeMapping(ppMapping, pFrom, pTo, pAddPurpose);
605 :
606 8834 : if (*ppMapping)
607 0 : return;
608 : }
609 :
610 36368 : if (! aRet.is()) // try callback chain
611 : {
612 8834 : MutexGuard aGuard( rData.aCallbacksMutex );
613 26502 : for ( t_CallbackSet::const_iterator iPos( rData.aCallbacks.begin() );
614 17668 : iPos != rData.aCallbacks.end(); ++iPos )
615 : {
616 0 : (**iPos)( ppMapping, pFrom, pTo, aAddPurpose.pData );
617 0 : if (*ppMapping)
618 0 : return;
619 8834 : }
620 : }
621 :
622 36368 : if (! aRet.is())
623 : {
624 8834 : aRet = loadExternalMapping( aFrom, aTo, aAddPurpose ); // direct try
625 8834 : if (! aRet.is())
626 2 : aRet = getMediateMapping( aFrom, aTo, aAddPurpose ); // try via uno
627 : }
628 :
629 36368 : if (aRet.is())
630 : {
631 36368 : (*aRet.get()->acquire)( aRet.get() );
632 36368 : *ppMapping = aRet.get();
633 36368 : }
634 : }
635 : //##################################################################################################
636 248 : void SAL_CALL uno_getMappingByName(
637 : uno_Mapping ** ppMapping, rtl_uString * pFrom, rtl_uString * pTo,
638 : rtl_uString * pAddPurpose )
639 : SAL_THROW_EXTERN_C()
640 : {
641 : OSL_ENSURE( ppMapping && pFrom && pTo, "### null ptr!" );
642 248 : if (*ppMapping)
643 : {
644 0 : (*(*ppMapping)->release)( *ppMapping );
645 0 : *ppMapping = 0;
646 : }
647 :
648 248 : uno_Environment * pEFrom = 0;
649 248 : uno_getEnvironment( &pEFrom, pFrom, 0 );
650 : OSL_ENSURE( pEFrom, "### cannot get source environment!" );
651 248 : if (pEFrom)
652 : {
653 248 : uno_Environment * pETo = 0;
654 248 : uno_getEnvironment( &pETo, pTo, 0 );
655 : OSL_ENSURE( pETo, "### cannot get target environment!" );
656 248 : if (pETo)
657 : {
658 248 : ::uno_getMapping( ppMapping, pEFrom, pETo, pAddPurpose );
659 248 : (*pETo->release)( pETo );
660 : }
661 248 : (*pEFrom->release)( pEFrom );
662 : }
663 248 : }
664 :
665 : //##################################################################################################
666 20464 : CPPU_DLLPUBLIC void SAL_CALL uno_registerMapping(
667 : uno_Mapping ** ppMapping, uno_freeMappingFunc freeMapping,
668 : uno_Environment * pFrom, uno_Environment * pTo, rtl_uString * pAddPurpose )
669 : SAL_THROW_EXTERN_C()
670 : {
671 20464 : MappingsData & rData = getMappingsData();
672 20464 : ClearableMutexGuard aGuard( rData.aMappingsMutex );
673 :
674 20464 : const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( *ppMapping ) );
675 20464 : if (iFind == rData.aMapping2Entry.end())
676 : {
677 : OUString aMappingName(
678 20464 : getMappingName( pFrom, pTo, pAddPurpose ? OUString(pAddPurpose) : OUString() ) );
679 : #if OSL_DEBUG_LEVEL > 2
680 : OString cstr( OUStringToOString( aMappingName, RTL_TEXTENCODING_ASCII_US ) );
681 : OSL_TRACE( "> inserting new mapping: %s", cstr.getStr() );
682 : #endif
683 : // count initially 1
684 20464 : MappingEntry * pEntry = new MappingEntry( *ppMapping, freeMapping, aMappingName );
685 20464 : rData.aName2Entry[ aMappingName ] = pEntry;
686 20464 : rData.aMapping2Entry[ *ppMapping ] = pEntry;
687 : }
688 : else
689 : {
690 0 : MappingEntry * pEntry = (*iFind).second;
691 0 : ++pEntry->nRef;
692 :
693 0 : if (pEntry->pMapping != *ppMapping) // exchange mapping to be registered
694 : {
695 0 : (*pEntry->pMapping->acquire)( pEntry->pMapping );
696 0 : --pEntry->nRef; // correct count; kill mapping to be registered
697 0 : aGuard.clear();
698 0 : (*freeMapping)( *ppMapping );
699 0 : *ppMapping = pEntry->pMapping;
700 : }
701 20464 : }
702 20464 : }
703 : //##################################################################################################
704 20438 : CPPU_DLLPUBLIC void SAL_CALL uno_revokeMapping(
705 : uno_Mapping * pMapping )
706 : SAL_THROW_EXTERN_C()
707 : {
708 20438 : MappingsData & rData = getMappingsData();
709 20438 : ClearableMutexGuard aGuard( rData.aMappingsMutex );
710 :
711 20438 : const t_Mapping2Entry::const_iterator iFind( rData.aMapping2Entry.find( pMapping ) );
712 : OSL_ASSERT( iFind != rData.aMapping2Entry.end() );
713 20438 : MappingEntry * pEntry = (*iFind).second;
714 20438 : if (! --pEntry->nRef)
715 : {
716 20438 : rData.aMapping2Entry.erase( pEntry->pMapping );
717 20438 : rData.aName2Entry.erase( pEntry->aMappingName );
718 20438 : aGuard.clear();
719 : #if OSL_DEBUG_LEVEL > 2
720 : OString cstr( OUStringToOString( pEntry->aMappingName, RTL_TEXTENCODING_ASCII_US ) );
721 : OSL_TRACE( "> revoking mapping %s", cstr.getStr() );
722 : #endif
723 20438 : (*pEntry->freeMapping)( pEntry->pMapping );
724 20438 : delete pEntry;
725 20438 : }
726 20438 : }
727 :
728 : //##################################################################################################
729 0 : CPPU_DLLPUBLIC void SAL_CALL uno_registerMappingCallback(
730 : uno_getMappingFunc pCallback )
731 : SAL_THROW_EXTERN_C()
732 : {
733 : OSL_ENSURE( pCallback, "### null ptr!" );
734 0 : MappingsData & rData = getMappingsData();
735 0 : MutexGuard aGuard( rData.aCallbacksMutex );
736 0 : rData.aCallbacks.insert( pCallback );
737 0 : }
738 : //##################################################################################################
739 0 : CPPU_DLLPUBLIC void SAL_CALL uno_revokeMappingCallback(
740 : uno_getMappingFunc pCallback )
741 : SAL_THROW_EXTERN_C()
742 : {
743 : OSL_ENSURE( pCallback, "### null ptr!" );
744 0 : MappingsData & rData = getMappingsData();
745 0 : MutexGuard aGuard( rData.aCallbacksMutex );
746 0 : rData.aCallbacks.erase( pCallback );
747 0 : }
748 : } // extern "C"
749 :
750 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|