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