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