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 : #ifdef DIAG
22 : #define CONTEXT_DIAG
23 : #endif
24 :
25 : #if OSL_DEBUG_LEVEL > 0
26 : #include <stdio.h>
27 : #endif
28 :
29 : #include <unordered_map>
30 : #ifdef CONTEXT_DIAG
31 : #include <map>
32 : #endif
33 :
34 : #include <osl/diagnose.h>
35 : #include <osl/mutex.hxx>
36 :
37 : #include <rtl/ustrbuf.hxx>
38 : #include <sal/log.hxx>
39 :
40 : #include <uno/lbnames.h>
41 : #include <uno/mapping.hxx>
42 :
43 : #include <cppuhelper/implbase1.hxx>
44 : #include <cppuhelper/compbase.hxx>
45 : #include <cppuhelper/component_context.hxx>
46 : #include <cppuhelper/exc_hlp.hxx>
47 :
48 : #include <com/sun/star/container/XNameContainer.hpp>
49 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
50 : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
51 : #include <com/sun/star/lang/XSingleComponentFactory.hpp>
52 : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
53 : #include <com/sun/star/lang/XComponent.hpp>
54 : #include <com/sun/star/beans/XPropertySet.hpp>
55 : #include <com/sun/star/uno/DeploymentException.hpp>
56 : #include <com/sun/star/uno/RuntimeException.hpp>
57 :
58 : #include <boost/scoped_array.hpp>
59 :
60 : #define SMGR_SINGLETON "/singletons/com.sun.star.lang.theServiceManager"
61 : #define TDMGR_SINGLETON "/singletons/com.sun.star.reflection.theTypeDescriptionManager"
62 : #define AC_SINGLETON "/singletons/com.sun.star.security.theAccessController"
63 :
64 : using namespace ::osl;
65 : using namespace ::com::sun::star::uno;
66 : using namespace ::com::sun::star;
67 :
68 : using rtl::OUString;
69 : using rtl::OUStringBuffer;
70 : using rtl::OUStringHash;
71 :
72 : namespace cppu
73 : {
74 :
75 : #ifdef CONTEXT_DIAG
76 :
77 : static OUString val2str( void const * pVal, typelib_TypeDescriptionReference * pTypeRef )
78 : {
79 : OSL_ASSERT( pVal );
80 : if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
81 : return "void";
82 :
83 : OUStringBuffer buf( 64 );
84 : buf.append( "(" + pTypeRef->pTypeName + ")" );
85 :
86 : switch (pTypeRef->eTypeClass)
87 : {
88 : case typelib_TypeClass_INTERFACE:
89 : buf.append( "0x" );
90 : buf.append( (sal_Int64)*(void **)pVal, 16 );
91 : break;
92 : case typelib_TypeClass_STRUCT:
93 : case typelib_TypeClass_EXCEPTION:
94 : {
95 : buf.append( "{ " );
96 : typelib_TypeDescription * pTypeDescr = 0;
97 : ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
98 : OSL_ASSERT( pTypeDescr );
99 : if (! pTypeDescr->bComplete)
100 : ::typelib_typedescription_complete( &pTypeDescr );
101 :
102 : typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
103 : sal_Int32 nDescr = pCompType->nMembers;
104 :
105 : if (pCompType->pBaseTypeDescription)
106 : {
107 : buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef ) );
108 : if (nDescr)
109 : buf.append( ", " );
110 : }
111 :
112 : typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
113 : sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
114 : rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
115 :
116 : for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
117 : {
118 : buf.append( ppMemberNames[ nPos ] );
119 : buf.append( " = " );
120 : typelib_TypeDescription * pMemberType = 0;
121 : TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[ nPos ] );
122 : buf.append( val2str( (char *)pVal + pMemberOffsets[ nPos ], pMemberType->pWeakRef ) );
123 : TYPELIB_DANGER_RELEASE( pMemberType );
124 : if (nPos < (nDescr -1))
125 : buf.append( ", " );
126 : }
127 :
128 : ::typelib_typedescription_release( pTypeDescr );
129 :
130 : buf.append( " }" );
131 : break;
132 : }
133 : case typelib_TypeClass_SEQUENCE:
134 : {
135 : typelib_TypeDescription * pTypeDescr = 0;
136 : TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
137 :
138 : uno_Sequence * pSequence = *(uno_Sequence **)pVal;
139 : typelib_TypeDescription * pElementTypeDescr = 0;
140 : TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
141 :
142 : sal_Int32 nElementSize = pElementTypeDescr->nSize;
143 : sal_Int32 nElements = pSequence->nElements;
144 :
145 : if (nElements)
146 : {
147 : buf.append( "{ " );
148 : char * pElements = pSequence->elements;
149 : for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
150 : {
151 : buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef ) );
152 : if (nPos < (nElements -1))
153 : buf.append( ", " );
154 : }
155 : buf.append( " }" );
156 : }
157 : else
158 : {
159 : buf.append( "{}" );
160 : }
161 : TYPELIB_DANGER_RELEASE( pElementTypeDescr );
162 : TYPELIB_DANGER_RELEASE( pTypeDescr );
163 : break;
164 : }
165 : case typelib_TypeClass_ANY:
166 : buf.append( "{ " );
167 : buf.append( val2str( ((uno_Any *)pVal)->pData,
168 : ((uno_Any *)pVal)->pType ) );
169 : buf.append( " }" );
170 : break;
171 : case typelib_TypeClass_TYPE:
172 : buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
173 : break;
174 : case typelib_TypeClass_STRING:
175 : buf.append( '\"' );
176 : buf.append( *(rtl_uString **)pVal );
177 : buf.append( '\"' );
178 : break;
179 : case typelib_TypeClass_ENUM:
180 : {
181 : typelib_TypeDescription * pTypeDescr = 0;
182 : ::typelib_typedescriptionreference_getDescription( &pTypeDescr, pTypeRef );
183 : OSL_ASSERT( pTypeDescr );
184 : if (! pTypeDescr->bComplete)
185 : ::typelib_typedescription_complete( &pTypeDescr );
186 :
187 : sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
188 : sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
189 : while (nPos--)
190 : {
191 : if (pValues[ nPos ] == *(sal_Int32 *)pVal)
192 : break;
193 : }
194 : if (nPos >= 0)
195 : buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[ nPos ] );
196 : else
197 : buf.append( '?' );
198 :
199 : ::typelib_typedescription_release( pTypeDescr );
200 : break;
201 : }
202 : case typelib_TypeClass_BOOLEAN:
203 : if (*(sal_Bool *)pVal)
204 : buf.append( "true" );
205 : else
206 : buf.append( "false" );
207 : break;
208 : case typelib_TypeClass_CHAR:
209 : buf.append( '\'' );
210 : buf.append( *(sal_Unicode *)pVal );
211 : buf.append( '\'' );
212 : break;
213 : case typelib_TypeClass_FLOAT:
214 : buf.append( *(float *)pVal );
215 : break;
216 : case typelib_TypeClass_DOUBLE:
217 : buf.append( *(double *)pVal );
218 : break;
219 : case typelib_TypeClass_BYTE:
220 : buf.append( "0x" );
221 : buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
222 : break;
223 : case typelib_TypeClass_SHORT:
224 : buf.append( "0x" );
225 : buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
226 : break;
227 : case typelib_TypeClass_UNSIGNED_SHORT:
228 : buf.append( "0x" );
229 : buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
230 : break;
231 : case typelib_TypeClass_LONG:
232 : buf.append( "0x" );
233 : buf.append( *(sal_Int32 *)pVal, 16 );
234 : break;
235 : case typelib_TypeClass_UNSIGNED_LONG:
236 : buf.append( "0x" );
237 : buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
238 : break;
239 : case typelib_TypeClass_HYPER:
240 : case typelib_TypeClass_UNSIGNED_HYPER:
241 : buf.append( "0x" );
242 : #if defined(__GNUC__) && defined(SPARC)
243 : // I guess this really should check if there are strict alignment
244 : // requirements, not just "GCC on SPARC".
245 : {
246 : sal_Int64 aVal;
247 : *(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
248 : *((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
249 : buf.append( aVal, 16 );
250 : }
251 : #else
252 : buf.append( *(sal_Int64 *)pVal, 16 );
253 : #endif
254 : break;
255 : default:
256 : buf.append( '?' );
257 : }
258 :
259 : return buf.makeStringAndClear();
260 : }
261 :
262 : static void dumpEntry( OUString const & key, Any const & value )
263 : {
264 : OUString val( val2str( value.getValue(), value.getValueTypeRef() ) );
265 : OString key_str( OUStringToOString( key, RTL_TEXTENCODING_ASCII_US ) );
266 : OString val_str( OUStringToOString( val, RTL_TEXTENCODING_ASCII_US ) );
267 : ::fprintf( stderr, "| %s = %s\n", key_str.getStr(), val_str.getStr() );
268 : }
269 : #endif
270 :
271 521 : static inline void try_dispose( Reference< XInterface > const & xInstance )
272 : {
273 521 : Reference< lang::XComponent > xComp( xInstance, UNO_QUERY );
274 521 : if (xComp.is())
275 : {
276 521 : xComp->dispose();
277 521 : }
278 521 : }
279 :
280 1042 : static inline void try_dispose( Reference< lang::XComponent > const & xComp )
281 : {
282 1042 : if (xComp.is())
283 : {
284 516 : xComp->dispose();
285 : }
286 1042 : }
287 :
288 12 : class DisposingForwarder
289 : : public WeakImplHelper1< lang::XEventListener >
290 : {
291 : Reference< lang::XComponent > m_xTarget;
292 :
293 6 : explicit DisposingForwarder( Reference< lang::XComponent > const & xTarget )
294 6 : : m_xTarget( xTarget )
295 : {
296 : OSL_ASSERT( m_xTarget.is() );
297 6 : }
298 : public:
299 : // listens at source for disposing, then disposes target
300 : static inline void listen(
301 : Reference< lang::XComponent > const & xSource,
302 : Reference< lang::XComponent > const & xTarget );
303 :
304 : virtual void SAL_CALL disposing( lang::EventObject const & rSource )
305 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
306 : };
307 :
308 554 : inline void DisposingForwarder::listen(
309 : Reference< lang::XComponent > const & xSource,
310 : Reference< lang::XComponent > const & xTarget )
311 : {
312 554 : if (xSource.is())
313 : {
314 6 : xSource->addEventListener( new DisposingForwarder( xTarget ) );
315 : }
316 554 : }
317 :
318 6 : void DisposingForwarder::disposing( lang::EventObject const & )
319 : throw (RuntimeException, std::exception)
320 : {
321 6 : m_xTarget->dispose();
322 6 : m_xTarget.clear();
323 6 : }
324 :
325 :
326 931 : struct MutexHolder
327 : {
328 : protected:
329 : Mutex m_mutex;
330 : };
331 :
332 :
333 : class ComponentContext
334 : : private MutexHolder
335 : , public WeakComponentImplHelper< XComponentContext,
336 : container::XNameContainer >
337 : {
338 : protected:
339 : Reference< XComponentContext > m_xDelegate;
340 :
341 18251 : struct ContextEntry
342 : {
343 : Any value;
344 : bool lateInit;
345 :
346 18506 : inline ContextEntry( Any const & value_, bool lateInit_ )
347 : : value( value_ )
348 18506 : , lateInit( lateInit_ )
349 18506 : {}
350 : };
351 : typedef std::unordered_map< OUString, ContextEntry * , OUStringHash > t_map;
352 : t_map m_map;
353 :
354 : Reference< lang::XMultiComponentFactory > m_xSMgr;
355 :
356 : protected:
357 : Any lookupMap( OUString const & rName );
358 :
359 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
360 : public:
361 : ComponentContext(
362 : ContextEntry_Init const * pEntries, sal_Int32 nEntries,
363 : Reference< XComponentContext > const & xDelegate );
364 : virtual ~ComponentContext();
365 :
366 : // XComponentContext
367 : virtual Any SAL_CALL getValueByName( OUString const & rName )
368 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
369 : virtual Reference<lang::XMultiComponentFactory> SAL_CALL getServiceManager()
370 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
371 :
372 : // XNameContainer
373 : virtual void SAL_CALL insertByName(
374 : OUString const & name, Any const & element )
375 : throw (lang::IllegalArgumentException, container::ElementExistException,
376 : lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
377 : virtual void SAL_CALL removeByName( OUString const & name )
378 : throw (container::NoSuchElementException,
379 : lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
380 : // XNameReplace
381 : virtual void SAL_CALL replaceByName(
382 : OUString const & name, Any const & element )
383 : throw (lang::IllegalArgumentException,container::NoSuchElementException,
384 : lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
385 : // XNameAccess
386 : virtual Any SAL_CALL getByName( OUString const & name )
387 : throw (container::NoSuchElementException,
388 : lang::WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
389 : virtual Sequence<OUString> SAL_CALL getElementNames()
390 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
391 : virtual sal_Bool SAL_CALL hasByName( OUString const & name )
392 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
393 : // XElementAccess
394 : virtual Type SAL_CALL getElementType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
395 : virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException, std::exception) SAL_OVERRIDE;
396 : };
397 :
398 : // XNameContainer
399 :
400 0 : void ComponentContext::insertByName(
401 : OUString const & name, Any const & element )
402 : throw (lang::IllegalArgumentException, container::ElementExistException,
403 : lang::WrappedTargetException, RuntimeException, std::exception)
404 : {
405 : t_map::mapped_type entry(
406 : new ContextEntry(
407 : element,
408 : /* lateInit_: */
409 0 : name.startsWith( "/singletons/" ) &&
410 0 : !element.hasValue() ) );
411 0 : MutexGuard guard( m_mutex );
412 : ::std::pair<t_map::iterator, bool> insertion( m_map.insert(
413 0 : t_map::value_type( name, entry ) ) );
414 0 : if (! insertion.second)
415 : throw container::ElementExistException(
416 0 : "element already exists: " + name,
417 0 : static_cast<OWeakObject *>(this) );
418 0 : }
419 :
420 :
421 58 : void ComponentContext::removeByName( OUString const & name )
422 : throw (container::NoSuchElementException,
423 : lang::WrappedTargetException, RuntimeException, std::exception)
424 : {
425 58 : MutexGuard guard( m_mutex );
426 58 : t_map::iterator iFind( m_map.find( name ) );
427 58 : if (iFind == m_map.end())
428 : throw container::NoSuchElementException(
429 0 : "no such element: " + name,
430 0 : static_cast<OWeakObject *>(this) );
431 :
432 58 : delete iFind->second;
433 58 : m_map.erase(iFind);
434 58 : }
435 :
436 : // XNameReplace
437 :
438 58 : void ComponentContext::replaceByName(
439 : OUString const & name, Any const & element )
440 : throw (lang::IllegalArgumentException,container::NoSuchElementException,
441 : lang::WrappedTargetException, RuntimeException, std::exception)
442 : {
443 58 : MutexGuard guard( m_mutex );
444 58 : t_map::const_iterator const iFind( m_map.find( name ) );
445 58 : if (iFind == m_map.end())
446 : throw container::NoSuchElementException(
447 0 : "no such element: " + name,
448 0 : static_cast<OWeakObject *>(this) );
449 58 : if (name.startsWith( "/singletons/" ) &&
450 0 : !element.hasValue())
451 : {
452 0 : iFind->second->value.clear();
453 0 : iFind->second->lateInit = true;
454 : }
455 : else
456 : {
457 58 : iFind->second->value = element;
458 58 : iFind->second->lateInit = false;
459 58 : }
460 58 : }
461 :
462 : // XNameAccess
463 :
464 275 : Any ComponentContext::getByName( OUString const & name )
465 : throw (container::NoSuchElementException,
466 : lang::WrappedTargetException, RuntimeException, std::exception)
467 : {
468 275 : return getValueByName( name );
469 : }
470 :
471 :
472 0 : Sequence<OUString> ComponentContext::getElementNames()
473 : throw (RuntimeException, std::exception)
474 : {
475 0 : MutexGuard guard( m_mutex );
476 0 : Sequence<OUString> ret( m_map.size() );
477 0 : OUString * pret = ret.getArray();
478 0 : sal_Int32 pos = 0;
479 0 : t_map::const_iterator iPos( m_map.begin() );
480 0 : t_map::const_iterator const iEnd( m_map.end() );
481 0 : for ( ; iPos != iEnd; ++iPos )
482 0 : pret[pos++] = iPos->first;
483 0 : return ret;
484 : }
485 :
486 :
487 0 : sal_Bool ComponentContext::hasByName( OUString const & name )
488 : throw (RuntimeException, std::exception)
489 : {
490 0 : MutexGuard guard( m_mutex );
491 0 : return m_map.find( name ) != m_map.end();
492 : }
493 :
494 : // XElementAccess
495 :
496 0 : Type ComponentContext::getElementType() throw (RuntimeException, std::exception)
497 : {
498 0 : return cppu::UnoType<void>::get();
499 : }
500 :
501 :
502 0 : sal_Bool ComponentContext::hasElements() throw (RuntimeException, std::exception)
503 : {
504 0 : MutexGuard guard( m_mutex );
505 0 : return ! m_map.empty();
506 : }
507 :
508 :
509 27169134 : Any ComponentContext::lookupMap( OUString const & rName )
510 : {
511 : #ifdef CONTEXT_DIAG
512 : if ( rName == "dump_maps" )
513 : {
514 : ::fprintf( stderr, ">>> dumping out ComponentContext %p m_map:\n", this );
515 : typedef ::std::map< OUString, ContextEntry * > t_sorted; // sorted map
516 : t_sorted sorted;
517 : for ( t_map::const_iterator iPos( m_map.begin() ); iPos != m_map.end(); ++iPos )
518 : {
519 : sorted[ iPos->first ] = iPos->second;
520 : }
521 : {
522 : for ( t_sorted::const_iterator iPos( sorted.begin() ); iPos != sorted.end(); ++iPos )
523 : {
524 : dumpEntry( iPos->first, iPos->second->value );
525 : }
526 : }
527 : return Any();
528 : }
529 : #endif
530 :
531 27169134 : ResettableMutexGuard guard( m_mutex );
532 27169134 : t_map::const_iterator iFind( m_map.find( rName ) );
533 27169134 : if (iFind == m_map.end())
534 2820 : return Any();
535 :
536 27166314 : t_map::mapped_type pEntry = iFind->second;
537 27166314 : if (! pEntry->lateInit)
538 27163662 : return pEntry->value;
539 :
540 : // late init singleton entry
541 5304 : Reference< XInterface > xInstance;
542 2652 : guard.clear();
543 :
544 : try
545 : {
546 2652 : Any usesService( getValueByName( rName + "/service" ) );
547 5304 : Any args_( getValueByName( rName + "/arguments" ) );
548 5304 : Sequence<Any> args;
549 2652 : if (args_.hasValue() && !(args_ >>= args))
550 : {
551 0 : args.realloc( 1 );
552 0 : args[ 0 ] = args_;
553 : }
554 :
555 5304 : Reference< lang::XSingleComponentFactory > xFac;
556 2652 : if (usesService >>= xFac) // try via factory
557 : {
558 7953 : xInstance = args.getLength()
559 0 : ? xFac->createInstanceWithArgumentsAndContext( args, this )
560 7953 : : xFac->createInstanceWithContext( this );
561 : }
562 : else
563 : {
564 1 : Reference< lang::XSingleServiceFactory > xFac2;
565 1 : if (usesService >>= xFac2)
566 : {
567 : // try via old XSingleServiceFactory
568 : #if OSL_DEBUG_LEVEL > 0
569 : ::fprintf(
570 : stderr,
571 : "### omitting context for service instantiation!\n" );
572 : #endif
573 0 : xInstance = args.getLength()
574 0 : ? xFac2->createInstanceWithArguments( args )
575 0 : : xFac2->createInstance();
576 : }
577 1 : else if (m_xSMgr.is()) // optionally service name
578 : {
579 1 : OUString serviceName;
580 2 : if ((usesService >>= serviceName) &&
581 1 : !serviceName.isEmpty())
582 : {
583 3 : xInstance = args.getLength()
584 0 : ? m_xSMgr->createInstanceWithArgumentsAndContext(
585 0 : serviceName, args, this )
586 1 : : m_xSMgr->createInstanceWithContext(
587 3 : serviceName, this );
588 1 : }
589 1 : }
590 2652 : }
591 : }
592 0 : catch (const RuntimeException &)
593 : {
594 0 : throw;
595 : }
596 0 : catch (const Exception & exc)
597 : {
598 : SAL_WARN(
599 : "cppuhelper",
600 : "exception occurred raising singleton \"" << rName << "\": "
601 : << exc.Message);
602 : }
603 :
604 : SAL_WARN_IF(!xInstance.is(),
605 : "cppuhelper", "no service object raising singleton " << rName);
606 :
607 5304 : Any ret;
608 2652 : guard.reset();
609 2652 : iFind = m_map.find( rName );
610 2652 : if (iFind != m_map.end())
611 : {
612 2652 : pEntry = iFind->second;
613 2652 : if (pEntry->lateInit)
614 : {
615 2652 : pEntry->value <<= xInstance;
616 2652 : pEntry->lateInit = false;
617 2652 : return pEntry->value;
618 : }
619 : else
620 0 : ret = pEntry->value;
621 : }
622 0 : guard.clear();
623 0 : try_dispose( xInstance );
624 27169134 : return ret;
625 : }
626 :
627 :
628 27169136 : Any ComponentContext::getValueByName( OUString const & rName )
629 : throw (RuntimeException, std::exception)
630 : {
631 : // to determine the root context:
632 27169136 : if ( rName == "_root" )
633 : {
634 2 : if (m_xDelegate.is())
635 0 : return m_xDelegate->getValueByName( rName );
636 : else
637 2 : return makeAny( Reference<XComponentContext>(this) );
638 : }
639 :
640 27169134 : Any ret( lookupMap( rName ) );
641 27169134 : if (!ret.hasValue() && m_xDelegate.is())
642 : {
643 0 : return m_xDelegate->getValueByName( rName );
644 : }
645 27169134 : return ret;
646 : }
647 :
648 197173679 : Reference< lang::XMultiComponentFactory > ComponentContext::getServiceManager()
649 : throw (RuntimeException, std::exception)
650 : {
651 197173679 : if ( !m_xSMgr.is() )
652 : {
653 : throw DeploymentException(
654 : "null component context service manager",
655 0 : static_cast<OWeakObject *>(this) );
656 : }
657 197173679 : return m_xSMgr;
658 : }
659 :
660 1131 : ComponentContext::~ComponentContext()
661 : {
662 : #ifdef CONTEXT_DIAG
663 : ::fprintf( stderr, "> destructed context %p\n", this );
664 : #endif
665 377 : t_map::const_iterator iPos( m_map.begin() );
666 377 : t_map::const_iterator const iEnd( m_map.end() );
667 377 : for ( ; iPos != iEnd; ++iPos )
668 0 : delete iPos->second;
669 377 : m_map.clear();
670 754 : }
671 :
672 521 : void ComponentContext::disposing()
673 : {
674 : #ifdef CONTEXT_DIAG
675 : ::fprintf( stderr, "> disposing context %p\n", this );
676 : #endif
677 :
678 1042 : Reference< lang::XComponent > xTDMgr, xAC; // to be disposed separately
679 :
680 : // dispose all context objects
681 521 : t_map::const_iterator iPos( m_map.begin() );
682 521 : t_map::const_iterator const iEnd( m_map.end() );
683 18714 : for ( ; iPos != iEnd; ++iPos )
684 : {
685 18193 : t_map::mapped_type pEntry = iPos->second;
686 :
687 : // service manager disposed separately
688 36386 : if (!m_xSMgr.is() ||
689 18193 : !iPos->first.startsWith( SMGR_SINGLETON ))
690 : {
691 17678 : if (pEntry->lateInit)
692 : {
693 : // late init
694 5700 : MutexGuard guard( m_mutex );
695 5700 : if (pEntry->lateInit)
696 : {
697 5700 : pEntry->value.clear(); // release factory
698 5700 : pEntry->lateInit = false;
699 5700 : continue;
700 0 : }
701 : }
702 :
703 11978 : Reference< lang::XComponent > xComp;
704 11978 : pEntry->value >>= xComp;
705 11978 : if (xComp.is())
706 : {
707 3206 : if ( iPos->first == TDMGR_SINGLETON )
708 : {
709 515 : xTDMgr = xComp;
710 : }
711 2691 : else if ( iPos->first == AC_SINGLETON )
712 : {
713 1 : xAC = xComp;
714 : }
715 : else // dispose immediately
716 : {
717 2690 : xComp->dispose();
718 : }
719 11978 : }
720 : }
721 : }
722 :
723 : // dispose service manager
724 521 : try_dispose( m_xSMgr );
725 521 : m_xSMgr.clear();
726 : // dispose ac
727 521 : try_dispose( xAC );
728 : // dispose tdmgr; revokes callback from cppu runtime
729 521 : try_dispose( xTDMgr );
730 :
731 521 : iPos = m_map.begin();
732 18714 : for ( ; iPos != iEnd; ++iPos )
733 18193 : delete iPos->second;
734 521 : m_map.clear();
735 :
736 : // Hack to terminate any JNI bridge's AsynchronousFinalizer thread (as JNI
737 : // proxies get finalized with arbitrary delay, so the bridge typically does
738 : // not dispose itself early enough before the process exits):
739 : uno_Environment ** envs;
740 : sal_Int32 envCount;
741 : uno_getRegisteredEnvironments(
742 521 : &envs, &envCount, &rtl_allocateMemory, OUString("java").pData);
743 : assert(envCount >= 0);
744 : assert(envCount == 0 || envs != nullptr);
745 521 : if (envs) {
746 6 : for (sal_Int32 i = 0; i != envCount; ++i) {
747 : assert(envs[i] != nullptr);
748 : assert(envs[i]->dispose != nullptr);
749 3 : (*envs[i]->dispose)(envs[i]);
750 : }
751 3 : rtl_freeMemory(envs);
752 521 : }
753 521 : }
754 :
755 554 : ComponentContext::ComponentContext(
756 : ContextEntry_Init const * pEntries, sal_Int32 nEntries,
757 : Reference< XComponentContext > const & xDelegate )
758 : : WeakComponentImplHelper( m_mutex ),
759 554 : m_xDelegate( xDelegate )
760 : {
761 10632 : for ( sal_Int32 nPos = 0; nPos < nEntries; ++nPos )
762 : {
763 10078 : ContextEntry_Init const & rEntry = pEntries[ nPos ];
764 :
765 10078 : if ( rEntry.name == SMGR_SINGLETON )
766 : {
767 548 : rEntry.value >>= m_xSMgr;
768 : }
769 :
770 10078 : if (rEntry.bLateInitService)
771 : {
772 : // singleton entry
773 8428 : m_map[ rEntry.name ] = new ContextEntry( Any(), true );
774 : // /service
775 8428 : m_map[ rEntry.name + "/service" ] = new ContextEntry( rEntry.value, false );
776 : // /initial-arguments are provided as optional context entry
777 : }
778 : else
779 : {
780 : // only value, no late init factory nor string
781 1650 : m_map[ rEntry.name ] = new ContextEntry( rEntry.value, false );
782 : }
783 : }
784 :
785 554 : if (!m_xSMgr.is() && m_xDelegate.is())
786 : {
787 : // wrap delegate's smgr XPropertySet into new smgr
788 6 : Reference< lang::XMultiComponentFactory > xMgr( m_xDelegate->getServiceManager() );
789 6 : if (xMgr.is())
790 : {
791 6 : osl_atomic_increment( &m_refCount );
792 : try
793 : {
794 : // create new smgr based on delegate's one
795 : m_xSMgr.set(
796 6 : xMgr->createInstanceWithContext(
797 6 : "com.sun.star.comp.stoc.OServiceManagerWrapper", xDelegate ),
798 6 : UNO_QUERY );
799 : // patch DefaultContext property of new one
800 6 : Reference< beans::XPropertySet > xProps( m_xSMgr, UNO_QUERY );
801 : OSL_ASSERT( xProps.is() );
802 6 : if (xProps.is())
803 : {
804 6 : Reference< XComponentContext > xThis( this );
805 6 : xProps->setPropertyValue( "DefaultContext", makeAny( xThis ) );
806 6 : }
807 : }
808 0 : catch (...)
809 : {
810 0 : osl_atomic_decrement( &m_refCount );
811 0 : throw;
812 : }
813 6 : osl_atomic_decrement( &m_refCount );
814 : OSL_ASSERT( m_xSMgr.is() );
815 6 : }
816 : }
817 554 : }
818 :
819 :
820 :
821 554 : extern "C" { static void s_createComponentContext_v(va_list * pParam)
822 : {
823 554 : ContextEntry_Init const * pEntries = va_arg(*pParam, ContextEntry_Init const *);
824 554 : sal_Int32 nEntries = va_arg(*pParam, sal_Int32);
825 554 : XComponentContext * pDelegatee = va_arg(*pParam, XComponentContext *);
826 554 : void ** ppContext = va_arg(*pParam, void **);
827 554 : uno::Mapping * pTarget2curr = va_arg(*pParam, uno::Mapping *);
828 :
829 554 : Reference<XComponentContext> xDelegate(pDelegatee, SAL_NO_ACQUIRE);
830 1108 : Reference<XComponentContext> xContext;
831 :
832 554 : if (nEntries > 0)
833 : {
834 : try
835 : {
836 554 : ComponentContext * p = new ComponentContext( pEntries, nEntries, xDelegate );
837 554 : xContext.set(p);
838 : // listen delegate for disposing, to dispose this (wrapping) context first.
839 554 : DisposingForwarder::listen( Reference< lang::XComponent >::query( xDelegate ), p );
840 : }
841 0 : catch (Exception & exc)
842 : {
843 : (void) exc; // avoid warning about unused variable
844 : OSL_FAIL( OUStringToOString(
845 : exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
846 0 : xContext.clear();
847 : }
848 : }
849 : else
850 : {
851 0 : xContext = xDelegate;
852 : }
853 :
854 1108 : *ppContext = pTarget2curr->mapInterface(xContext.get(), cppu::UnoType<decltype(xContext)>::get());
855 554 : }}
856 :
857 554 : Reference< XComponentContext > SAL_CALL createComponentContext(
858 : ContextEntry_Init const * pEntries, sal_Int32 nEntries,
859 : Reference< XComponentContext > const & xDelegate )
860 : {
861 554 : uno::Environment curr_env(Environment::getCurrent());
862 1108 : uno::Environment source_env(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
863 :
864 1108 : uno::Mapping curr2source(curr_env, source_env);
865 1108 : uno::Mapping source2curr(source_env, curr_env);
866 :
867 1108 : boost::scoped_array<ContextEntry_Init> mapped_entries(new ContextEntry_Init[nEntries]);
868 10632 : for (sal_Int32 nPos = 0; nPos < nEntries; ++ nPos)
869 : {
870 10078 : mapped_entries[nPos].bLateInitService = pEntries[nPos].bLateInitService;
871 10078 : mapped_entries[nPos].name = pEntries[nPos].name;
872 :
873 10078 : uno_type_any_constructAndConvert(&mapped_entries[nPos].value,
874 10078 : const_cast<void *>(pEntries[nPos].value.getValue()),
875 10078 : pEntries[nPos].value.getValueTypeRef(),
876 30234 : curr2source.get());
877 : }
878 :
879 554 : void * mapped_delegate = curr2source.mapInterface(xDelegate.get(), cppu::UnoType<decltype(xDelegate)>::get());
880 554 : XComponentContext * pXComponentContext = NULL;
881 554 : source_env.invoke(s_createComponentContext_v, mapped_entries.get(), nEntries, mapped_delegate, &pXComponentContext, &source2curr);
882 554 : mapped_entries.reset();
883 :
884 1108 : return Reference<XComponentContext>(pXComponentContext, SAL_NO_ACQUIRE);
885 : }
886 :
887 : }
888 :
889 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|