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