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