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