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