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