xref: /trunk/main/stoc/source/servicemanager/servicemanager.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_stoc.hxx"
30 #include <osl/mutex.hxx>
31 #include <osl/diagnose.h>
32 #include <rtl/ustrbuf.hxx>
33 
34 #include <hash_map>
35 #include <hash_set>
36 #include <list>
37 #include <uno/mapping.hxx>
38 #include <uno/dispatcher.h>
39 #include <cppuhelper/queryinterface.hxx>
40 #include <cppuhelper/weakref.hxx>
41 #include <cppuhelper/component.hxx>
42 #include <cppuhelper/factory.hxx>
43 #ifndef _CPPUHELPER_IMPLBASE1_HXX
44 #include <cppuhelper/implbase1.hxx>
45 #endif
46 #include <cppuhelper/typeprovider.hxx>
47 #ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_
48 #include <cppuhelper/implementationentry.hxx>
49 #endif
50 #include <rtl/unload.h>
51 #include <cppuhelper/component_context.hxx>
52 #include <cppuhelper/bootstrap.hxx>
53 #include <cppuhelper/compbase8.hxx>
54 
55 
56 #include <com/sun/star/lang/XUnoTunnel.hpp>
57 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
58 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
59 #include <com/sun/star/lang/XServiceInfo.hpp>
60 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
61 #include <com/sun/star/lang/XInitialization.hpp>
62 #include <com/sun/star/lang/XEventListener.hpp>
63 #include <com/sun/star/lang/DisposedException.hpp>
64 #include <com/sun/star/beans/XPropertySet.hpp>
65 #include <com/sun/star/beans/PropertyAttribute.hpp>
66 #include <com/sun/star/registry/XRegistryKey.hpp>
67 #include <com/sun/star/registry/XSimpleRegistry.hpp>
68 #include <com/sun/star/container/XSet.hpp>
69 #include <com/sun/star/container/XElementAccess.hpp>
70 #include <com/sun/star/container/XEnumeration.hpp>
71 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
72 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
73 #include <com/sun/star/uno/XUnloadingPreference.hpp>
74 
75 #include <bootstrapservices.hxx>
76 
77 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
78 
79 
80 using namespace com::sun::star;
81 using namespace com::sun::star::uno;
82 using namespace com::sun::star::beans;
83 using namespace com::sun::star::registry;
84 using namespace com::sun::star::lang;
85 using namespace com::sun::star::container;
86 using namespace cppu;
87 using namespace osl;
88 using namespace rtl;
89 using namespace std;
90 
91 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
92 
93 namespace stoc_bootstrap
94 {
95 Sequence< OUString > smgr_wrapper_getSupportedServiceNames()
96 {
97     static Sequence < OUString > *pNames = 0;
98     if( ! pNames )
99     {
100         MutexGuard guard( Mutex::getGlobalMutex() );
101         if( !pNames )
102         {
103             static Sequence< OUString > seqNames(1);
104             seqNames.getArray()[0] = OUString(
105                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory") );
106             pNames = &seqNames;
107         }
108     }
109     return *pNames;
110 }
111 
112 OUString smgr_wrapper_getImplementationName()
113 {
114     static OUString *pImplName = 0;
115     if( ! pImplName )
116     {
117         MutexGuard guard( Mutex::getGlobalMutex() );
118         if( ! pImplName )
119         {
120             static OUString implName(
121                 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.OServiceManagerWrapper" ) );
122             pImplName = &implName;
123         }
124     }
125     return *pImplName;
126 }
127 
128 Sequence< OUString > smgr_getSupportedServiceNames()
129 {
130     static Sequence < OUString > *pNames = 0;
131     if( ! pNames )
132     {
133         MutexGuard guard( Mutex::getGlobalMutex() );
134         if( !pNames )
135         {
136             static Sequence< OUString > seqNames(2);
137             seqNames.getArray()[0] = OUString(
138                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory") );
139             seqNames.getArray()[1] = OUString(
140                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.ServiceManager") );
141             pNames = &seqNames;
142         }
143     }
144     return *pNames;
145 }
146 
147 OUString smgr_getImplementationName()
148 {
149     static OUString *pImplName = 0;
150     if( ! pImplName )
151     {
152         MutexGuard guard( Mutex::getGlobalMutex() );
153         if( ! pImplName )
154         {
155             static OUString implName(
156                 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.OServiceManager" ) );
157             pImplName = &implName;
158         }
159     }
160     return *pImplName;
161 }
162 
163 Sequence< OUString > regsmgr_getSupportedServiceNames()
164 {
165     static Sequence < OUString > *pNames = 0;
166     if( ! pNames )
167     {
168         MutexGuard guard( Mutex::getGlobalMutex() );
169         if( !pNames )
170         {
171             static Sequence< OUString > seqNames(2);
172             seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory"));
173             seqNames.getArray()[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.RegistryServiceManager"));
174             pNames = &seqNames;
175         }
176     }
177     return *pNames;
178 }
179 
180 OUString regsmgr_getImplementationName()
181 {
182     static OUString *pImplName = 0;
183     if( ! pImplName )
184     {
185         MutexGuard guard( Mutex::getGlobalMutex() );
186         if( ! pImplName )
187         {
188             static OUString implName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.ORegistryServiceManager" ) );
189             pImplName = &implName;
190         }
191     }
192     return *pImplName;
193 }
194 }
195 
196 namespace stoc_smgr
197 {
198 static Sequence< sal_Int8 > smgr_getImplementationId()
199 {
200     static OImplementationId * s_pId = 0;
201     if (! s_pId)
202     {
203         MutexGuard aGuard( Mutex::getGlobalMutex() );
204         if (! s_pId)
205         {
206             static OImplementationId s_aId;
207             s_pId = &s_aId;
208         }
209     }
210     return s_pId->getImplementationId();
211 }
212 
213 
214 static Sequence< OUString > retrieveAsciiValueList(
215     const Reference< XSimpleRegistry > &xReg, const OUString &keyName )
216 {
217     Reference< XEnumerationAccess > xAccess( xReg, UNO_QUERY );
218     Sequence< OUString > seq;
219     if( xAccess.is() )
220     {
221         Reference< XEnumeration > xEnum = xAccess->createEnumeration();
222         while( xEnum.is() && xEnum->hasMoreElements() )
223         {
224             Reference< XSimpleRegistry > xTempReg;
225             xEnum->nextElement() >>= xTempReg;
226             if( xTempReg.is() )
227             {
228                 Sequence< OUString > seq2 = retrieveAsciiValueList( xTempReg, keyName );
229 
230                 if( seq2.getLength() )
231                 {
232                     sal_Int32 n1Len = seq.getLength();
233                     sal_Int32 n2Len = seq2.getLength();
234 
235                     seq.realloc( n1Len + n2Len );
236                     const OUString *pSource = seq2.getConstArray();
237                     OUString *pTarget = seq.getArray();
238                     for( int i = 0 ; i < n2Len ; i ++ )
239                     {
240                         pTarget[i+n1Len] = pSource[i];
241                     }
242                 }
243             }
244         }
245     }
246     else if( xReg.is () )
247     {
248         try
249         {
250             Reference< XRegistryKey > rRootKey = xReg->getRootKey();
251             if( rRootKey.is() )
252             {
253                 Reference<XRegistryKey > xKey = rRootKey->openKey(keyName);
254                 if( xKey.is() )
255                 {
256                     seq = xKey->getAsciiListValue();
257                 }
258             }
259         }
260         catch( InvalidRegistryException & )
261         {
262         }
263         catch (InvalidValueException &)
264         {
265         }
266     }
267     return seq;
268 }
269 
270 /*****************************************************************************
271     Enumeration by ServiceName
272 *****************************************************************************/
273 struct hashRef_Impl
274 {
275     size_t operator()(const Reference<XInterface > & rName) const
276     {
277         // query to XInterface. The cast to XInterface* must be the same for the same object
278         Reference<XInterface > x( Reference<XInterface >::query( rName ) );
279         return (size_t)x.get();
280     }
281 };
282 
283 struct equaltoRef_Impl
284 {
285     size_t operator()(const Reference<XInterface > & rName1, const Reference<XInterface > & rName2 ) const
286         { return rName1 == rName2; }
287 };
288 
289 typedef hash_set
290 <
291     Reference<XInterface >,
292     hashRef_Impl,
293     equaltoRef_Impl
294 > HashSet_Ref;
295 
296 
297 class ServiceEnumeration_Impl : public WeakImplHelper1< XEnumeration >
298 {
299 public:
300     ServiceEnumeration_Impl( const Sequence< Reference<XInterface > > & rFactories )
301         : aFactories( rFactories )
302         , nIt( 0 )
303         { g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); }
304     virtual ~ServiceEnumeration_Impl()
305         { g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); }
306 
307     // XEnumeration
308     sal_Bool SAL_CALL hasMoreElements()
309         throw(::com::sun::star::uno::RuntimeException);
310     Any SAL_CALL nextElement()
311         throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
312 private:
313     Mutex                               aMutex;
314     Sequence< Reference<XInterface > >  aFactories;
315     sal_Int32                           nIt;
316 };
317 
318 // XEnumeration
319 sal_Bool ServiceEnumeration_Impl::hasMoreElements() throw(::com::sun::star::uno::RuntimeException)
320 {
321     MutexGuard aGuard( aMutex );
322     return nIt != aFactories.getLength();
323 }
324 
325 // XEnumeration
326 Any ServiceEnumeration_Impl::nextElement()
327     throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
328 {
329     MutexGuard aGuard( aMutex );
330     if( nIt == aFactories.getLength() )
331         throw NoSuchElementException();
332 
333     return Any( &aFactories.getConstArray()[nIt++], ::getCppuType( (const Reference<XInterface > *)0 ) );
334 }
335 
336 //==================================================================================================
337 class PropertySetInfo_Impl : public WeakImplHelper1< beans::XPropertySetInfo >
338 {
339     Sequence< beans::Property > m_properties;
340 
341 public:
342     inline PropertySetInfo_Impl( Sequence< beans::Property > const & properties ) SAL_THROW( () )
343         : m_properties( properties )
344         {}
345 
346     // XPropertySetInfo impl
347     virtual Sequence< beans::Property > SAL_CALL getProperties()
348         throw (RuntimeException);
349     virtual beans::Property SAL_CALL getPropertyByName( OUString const & name )
350         throw (beans::UnknownPropertyException, RuntimeException);
351     virtual sal_Bool SAL_CALL hasPropertyByName( OUString const & name )
352         throw (RuntimeException);
353 };
354 //__________________________________________________________________________________________________
355 Sequence< beans::Property > PropertySetInfo_Impl::getProperties()
356     throw (RuntimeException)
357 {
358     return m_properties;
359 }
360 //__________________________________________________________________________________________________
361 beans::Property PropertySetInfo_Impl::getPropertyByName( OUString const & name )
362     throw (beans::UnknownPropertyException, RuntimeException)
363 {
364     beans::Property const * p = m_properties.getConstArray();
365     for ( sal_Int32 nPos = m_properties.getLength(); nPos--; )
366     {
367         if (p[ nPos ].Name.equals( name ))
368             return p[ nPos ];
369     }
370     throw beans::UnknownPropertyException(
371         OUSTR("unknown property: ") + name, Reference< XInterface >() );
372 }
373 //__________________________________________________________________________________________________
374 sal_Bool PropertySetInfo_Impl::hasPropertyByName( OUString const & name )
375     throw (RuntimeException)
376 {
377     beans::Property const * p = m_properties.getConstArray();
378     for ( sal_Int32 nPos = m_properties.getLength(); nPos--; )
379     {
380         if (p[ nPos ].Name.equals( name ))
381             return sal_True;
382     }
383     return sal_False;
384 }
385 
386 
387 /*****************************************************************************
388     Enumeration by implementation
389 *****************************************************************************/
390 class ImplementationEnumeration_Impl : public WeakImplHelper1< XEnumeration >
391 {
392 public:
393     ImplementationEnumeration_Impl( const HashSet_Ref & rImplementationMap )
394         : aImplementationMap( rImplementationMap )
395         , aIt( aImplementationMap.begin() )
396         {
397             g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
398         }
399     virtual ~ImplementationEnumeration_Impl();
400 
401     // XEnumeration
402     virtual sal_Bool SAL_CALL hasMoreElements()
403         throw(::com::sun::star::uno::RuntimeException);
404     virtual Any SAL_CALL nextElement()
405         throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
406 
407 private:
408     Mutex                           aMutex;
409     HashSet_Ref                     aImplementationMap;
410     HashSet_Ref::iterator           aIt;
411     sal_Int32                       nNext;
412     Reference<XInterface >          xNext;
413 };
414 
415 ImplementationEnumeration_Impl::~ImplementationEnumeration_Impl()
416 {
417     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
418 }
419 
420 // XEnumeration
421 sal_Bool ImplementationEnumeration_Impl::hasMoreElements()
422     throw(::com::sun::star::uno::RuntimeException)
423 {
424     MutexGuard aGuard( aMutex );
425     return aIt != aImplementationMap.end();
426 }
427 
428 // XEnumeration
429 Any ImplementationEnumeration_Impl::nextElement()
430     throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
431 {
432     MutexGuard aGuard( aMutex );
433     if( aIt == aImplementationMap.end() )
434         throw NoSuchElementException();
435 
436     Any ret( &(*aIt), ::getCppuType( (const Reference<XInterface > *)0 ) );
437     ++aIt;
438     return ret;
439 }
440 
441 /*****************************************************************************
442     Hash tables
443 *****************************************************************************/
444 struct equalOWString_Impl
445 {
446   sal_Bool operator()(const OUString & s1, const OUString & s2) const
447         { return s1 == s2; }
448 };
449 
450 struct hashOWString_Impl
451 {
452     size_t operator()(const OUString & rName) const
453         { return rName.hashCode(); }
454 };
455 
456 typedef hash_set
457 <
458     OUString,
459     hashOWString_Impl,
460     equalOWString_Impl
461 > HashSet_OWString;
462 
463 typedef hash_multimap
464 <
465     OUString,
466     Reference<XInterface >,
467     hashOWString_Impl,
468     equalOWString_Impl
469 > HashMultimap_OWString_Interface;
470 
471 typedef hash_map
472 <
473     OUString,
474     Reference<XInterface >,
475     hashOWString_Impl,
476     equalOWString_Impl
477 > HashMap_OWString_Interface;
478 
479 /*****************************************************************************
480     class OServiceManager_Listener
481 *****************************************************************************/
482 class OServiceManager_Listener : public WeakImplHelper1< XEventListener >
483 {
484 private:
485     WeakReference<XSet > xSMgr;
486 
487 public:
488     OServiceManager_Listener( const Reference<XSet > & rSMgr )
489         : xSMgr( rSMgr )
490         {}
491 
492     // XEventListener
493     virtual void SAL_CALL disposing(const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException);
494 };
495 
496 void OServiceManager_Listener::disposing(const EventObject & rEvt )
497     throw(::com::sun::star::uno::RuntimeException)
498 {
499     Reference<XSet > x( xSMgr );
500     if( x.is() )
501     {
502         try
503         {
504             x->remove( Any( &rEvt.Source, ::getCppuType( (const Reference<XInterface > *)0 ) ) );
505         }
506         catch( const IllegalArgumentException & )
507         {
508             OSL_ENSURE( sal_False, "IllegalArgumentException catched" );
509         }
510         catch( const NoSuchElementException & )
511         {
512             OSL_ENSURE( sal_False, "NoSuchElementException catched" );
513         }
514     }
515 }
516 
517 
518 /*****************************************************************************
519     class OServiceManager
520 *****************************************************************************/
521 struct OServiceManagerMutex
522 {
523     Mutex m_mutex;
524 };
525 
526 extern "C" void SAL_CALL smgrUnloadingListener(void* id);
527 
528 typedef WeakComponentImplHelper8<
529     lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo,
530     lang::XInitialization, lang::XUnoTunnel,
531     container::XSet, container::XContentEnumerationAccess,
532     beans::XPropertySet > t_OServiceManager_impl;
533 
534 class OServiceManager
535     : public OServiceManagerMutex
536     , public t_OServiceManager_impl
537 {
538 public:
539     friend void SAL_CALL smgrUnloadingListener(void* id);
540 
541     OServiceManager( Reference< XComponentContext > const & xContext );
542     virtual ~OServiceManager();
543 
544     // XUnoTunnel
545     sal_Int64 SAL_CALL getSomething( Sequence< sal_Int8 > const & id )
546         throw (RuntimeException);
547 
548     // XInitialization
549     void SAL_CALL initialize( Sequence< Any > const & args )
550         throw (Exception);
551 
552     // XServiceInfo
553     virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException);
554     static OUString getImplementationName_Static() throw(::com::sun::star::uno::RuntimeException)
555         { return stoc_bootstrap::smgr_getImplementationName(); }
556     virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(::com::sun::star::uno::RuntimeException);
557     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
558 
559     // XMultiComponentFactory
560     virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
561         OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext )
562         throw (Exception, RuntimeException);
563     virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
564         OUString const & rServiceSpecifier,
565         Sequence< Any > const & rArguments,
566         Reference< XComponentContext > const & xContext )
567         throw (Exception, RuntimeException);
568 //      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
569 //          throw (RuntimeException);
570 
571     // XMultiServiceFactory
572     virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() throw(::com::sun::star::uno::RuntimeException);
573     virtual Reference<XInterface > SAL_CALL createInstance(const OUString &) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
574     virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString &, const Sequence<Any >& Arguments) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
575 
576     // The same as the getAvailableServiceNames, but only uique names
577     Sequence< OUString > getUniqueAvailableServiceNames(
578         HashSet_OWString & aNameSet );
579 
580     // XElementAccess
581     virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException);
582     virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
583 
584     // XEnumerationAccess
585     virtual Reference<XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException);
586 
587     // XSet
588     virtual sal_Bool SAL_CALL has( const Any & Element ) throw(::com::sun::star::uno::RuntimeException);
589     virtual void SAL_CALL insert( const Any & Element ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
590     virtual void SAL_CALL remove( const Any & Element ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
591 
592     // XContentEnumerationAccess
593     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
594     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw(::com::sun::star::uno::RuntimeException);
595     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(
596         const OUString& aServiceName, Reference< XComponentContext > const & xContext )
597         throw(::com::sun::star::uno::RuntimeException);
598 
599     // XComponent
600     virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
601 
602     // XPropertySet
603     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo()
604         throw(::com::sun::star::uno::RuntimeException);
605     void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue)
606         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
607     Any SAL_CALL getPropertyValue(const OUString& PropertyName)
608         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
609     void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener)
610         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
611     void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener)
612         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
613     void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener)
614         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
615     void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener)
616         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
617 
618 protected:
619     inline bool is_disposed() const SAL_THROW( (lang::DisposedException) );
620     inline void check_undisposed() const SAL_THROW( (lang::DisposedException) );
621     virtual void SAL_CALL disposing();
622 
623     sal_Bool haveFactoryWithThisImplementation(const OUString& aImplName);
624 
625     virtual Sequence< Reference< XInterface > > queryServiceFactories(
626         const OUString& aServiceName, Reference< XComponentContext > const & xContext );
627 
628     Reference< XComponentContext >  m_xContext;
629 
630     Reference< beans::XPropertySetInfo > m_xPropertyInfo;
631 
632     sal_Int32 m_nUnloadingListenerId;
633 
634     // Does clean up when the unloading mechanism has been set off. It is called from
635     // the listener function smgrUnloadingListener.
636     void onUnloadingNotify();
637     // factories which have been loaded and not inserted( by XSet::insert)
638     // are remembered by this set. Those factories
639     // are not released on a call to onUnloadingNotify
640     HashSet_Ref m_SetLoadedFactories;
641 private:
642 
643     Reference<XEventListener >      getFactoryListener();
644 
645 
646     HashMultimap_OWString_Interface m_ServiceMap;
647     HashSet_Ref                     m_ImplementationMap;
648     HashMap_OWString_Interface      m_ImplementationNameMap;
649     Reference<XEventListener >      xFactoryListener;
650     bool                            m_bInDisposing;
651 };
652 
653 
654 //______________________________________________________________________________
655 inline bool OServiceManager::is_disposed() const
656     SAL_THROW( (lang::DisposedException) )
657 {
658     // ought to be guarded by m_mutex:
659     return (m_bInDisposing || rBHelper.bDisposed);
660 }
661 
662 //______________________________________________________________________________
663 inline void OServiceManager::check_undisposed() const
664     SAL_THROW( (lang::DisposedException) )
665 {
666     if (is_disposed())
667     {
668         throw lang::DisposedException(
669             OUSTR("service manager instance has already been disposed!"),
670             (OWeakObject *)this );
671     }
672 }
673 
674 //##################################################################################################
675 //##################################################################################################
676 //##################################################################################################
677 
678 class OServiceManagerWrapper : public OServiceManagerMutex, public t_OServiceManager_impl
679 {
680     Reference< XComponentContext > m_xContext;
681     OServiceManager * m_root;
682     inline OServiceManager * getRoot() SAL_THROW( (RuntimeException) )
683     {
684         if (! m_root)
685         {
686             throw lang::DisposedException(
687                 OUSTR("service manager instance has already been disposed!"),
688                 Reference< XInterface >() );
689         }
690         return m_root;
691     }
692 
693 protected:
694     virtual void SAL_CALL disposing();
695 
696 public:
697     OServiceManagerWrapper(
698         Reference< XComponentContext > const & xContext )
699         SAL_THROW( (RuntimeException) );
700     virtual ~OServiceManagerWrapper() SAL_THROW( () );
701 
702     // XUnoTunnel
703     sal_Int64 SAL_CALL getSomething( Sequence< sal_Int8 > const & id ) throw (RuntimeException)
704         { return getRoot()->getSomething( id ); }
705 
706     // XInitialization
707     void SAL_CALL initialize( Sequence< Any > const & args ) throw (Exception)
708         { getRoot()->initialize( args ); }
709 
710     // XServiceInfo
711     virtual OUString SAL_CALL getImplementationName() throw (RuntimeException)
712         { return getRoot()->getImplementationName(); }
713     virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (RuntimeException)
714         { return getRoot()->supportsService( ServiceName ); }
715     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException)
716         { return getRoot()->getSupportedServiceNames(); }
717 
718     // XMultiComponentFactory
719     virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
720         OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext )
721         throw (Exception, RuntimeException)
722         { return getRoot()->createInstanceWithContext( rServiceSpecifier, xContext ); }
723     virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
724         OUString const & rServiceSpecifier,
725         Sequence< Any > const & rArguments,
726         Reference< XComponentContext > const & xContext )
727         throw (Exception, RuntimeException)
728         { return getRoot()->createInstanceWithArgumentsAndContext( rServiceSpecifier, rArguments, xContext ); }
729 //      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
730 //          throw (RuntimeException);
731 
732     // XMultiServiceFactory
733     virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() throw (RuntimeException)
734         { return getRoot()->getAvailableServiceNames(); }
735     virtual Reference<XInterface > SAL_CALL createInstance(const OUString & name) throw (Exception)
736         { return getRoot()->createInstanceWithContext( name, m_xContext ); }
737     virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString & name, const Sequence<Any >& Arguments) throw (Exception)
738         { return getRoot()->createInstanceWithArgumentsAndContext( name, Arguments, m_xContext ); }
739 
740     // XElementAccess
741     virtual Type SAL_CALL getElementType() throw (RuntimeException)
742         { return getRoot()->getElementType(); }
743     virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException)
744         { return getRoot()->hasElements(); }
745 
746     // XEnumerationAccess
747     virtual Reference<XEnumeration > SAL_CALL createEnumeration() throw (RuntimeException)
748         { return getRoot()->createEnumeration(); }
749 
750     // XSet
751     virtual sal_Bool SAL_CALL has( const Any & Element ) throw (RuntimeException)
752         { return getRoot()->has( Element ); }
753     virtual void SAL_CALL insert( const Any & Element ) throw (lang::IllegalArgumentException, container::ElementExistException, RuntimeException)
754         { getRoot()->insert( Element ); }
755     virtual void SAL_CALL remove( const Any & Element ) throw (lang::IllegalArgumentException, container::NoSuchElementException, RuntimeException)
756         { getRoot()->remove( Element ); }
757 
758     // XContentEnumerationAccess
759     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
760     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw (RuntimeException)
761         { return getRoot()->createContentEnumeration( aServiceName, m_xContext ); }
762 
763     // XPropertySet
764     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() throw (RuntimeException)
765         { return getRoot()->getPropertySetInfo(); }
766 
767     void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue)
768         throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, RuntimeException);
769     Any SAL_CALL getPropertyValue(const OUString& PropertyName)
770         throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException);
771 
772     void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener)
773         throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException)
774         { getRoot()->addPropertyChangeListener( PropertyName, aListener ); }
775     void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener)
776         throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException)
777         { getRoot()->removePropertyChangeListener( PropertyName, aListener ); }
778     void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener)
779         throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException)
780         { getRoot()->addVetoableChangeListener( PropertyName, aListener ); }
781     void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener)
782         throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException)
783         { getRoot()->removeVetoableChangeListener( PropertyName, aListener ); }
784 };
785 //__________________________________________________________________________________________________
786 void SAL_CALL OServiceManagerWrapper::setPropertyValue(
787     const OUString& PropertyName, const Any& aValue )
788     throw (beans::UnknownPropertyException, beans::PropertyVetoException,
789            lang::IllegalArgumentException, lang::WrappedTargetException, RuntimeException)
790 {
791     if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") ))
792     {
793         Reference< XComponentContext > xContext;
794         if (aValue >>= xContext)
795         {
796             MutexGuard aGuard( m_mutex );
797             m_xContext = xContext;
798         }
799         else
800         {
801             throw IllegalArgumentException(
802                 OUString( RTL_CONSTASCII_USTRINGPARAM("no XComponentContext given!") ),
803                 (OWeakObject *)this, 1 );
804         }
805     }
806     else
807     {
808         getRoot()->setPropertyValue( PropertyName, aValue );
809     }
810 }
811 //__________________________________________________________________________________________________
812 Any SAL_CALL OServiceManagerWrapper::getPropertyValue(
813     const OUString& PropertyName )
814     throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException)
815 {
816     if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") ))
817     {
818         MutexGuard aGuard( m_mutex );
819         if( m_xContext.is() )
820             return makeAny( m_xContext );
821         else
822             return Any();
823     }
824     else
825     {
826         return getRoot()->getPropertyValue( PropertyName );
827     }
828 }
829 //__________________________________________________________________________________________________
830 void OServiceManagerWrapper::disposing()
831 {
832     m_xContext.clear();
833 
834     if (m_root)
835     {
836 // no m_root->dispose(), because every context disposes its service manager...
837         m_root->release();
838         m_root = 0;
839     }
840 }
841 //__________________________________________________________________________________________________
842 OServiceManagerWrapper::~OServiceManagerWrapper() SAL_THROW( () )
843 {
844     if (m_root)
845     {
846         m_root->release();
847         m_root = 0;
848     }
849 
850     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
851 }
852 //__________________________________________________________________________________________________
853 OServiceManagerWrapper::OServiceManagerWrapper(
854     Reference< XComponentContext > const & xContext )
855     SAL_THROW( (RuntimeException) )
856     : t_OServiceManager_impl( m_mutex )
857     , m_xContext( xContext )
858     , m_root( 0 )
859 {
860     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
861 
862     Reference< XUnoTunnel > xTunnel( m_xContext->getServiceManager(), UNO_QUERY );
863     OSL_ASSERT( xTunnel.is() );
864     if (xTunnel.is())
865     {
866         m_root = reinterpret_cast< OServiceManager * >(
867             xTunnel->getSomething( smgr_getImplementationId() ) );
868         OSL_ASSERT( m_root );
869         if (m_root)
870         {
871             m_root->acquire();
872         }
873     }
874 
875     if (! m_root)
876     {
877         throw RuntimeException(
878             OUString( RTL_CONSTASCII_USTRINGPARAM("can only wrap OServiceManager instances!") ),
879             Reference< XInterface >() );
880     }
881 }
882 
883 //##################################################################################################
884 //##################################################################################################
885 //##################################################################################################
886 
887 // XUnoTunnel
888 sal_Int64 OServiceManager::getSomething( Sequence< sal_Int8 > const & id )
889     throw (RuntimeException)
890 {
891     check_undisposed();
892     if (id == smgr_getImplementationId())
893         return reinterpret_cast< sal_Int64 >(this);
894     else
895         return 0;
896 }
897 
898 /**
899  * Create a ServiceManager
900  */
901 OServiceManager::OServiceManager( Reference< XComponentContext > const & xContext )
902     : t_OServiceManager_impl( m_mutex )
903     , m_xContext( xContext )
904     , m_bInDisposing( false )
905 {
906     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
907     m_nUnloadingListenerId= rtl_addUnloadingListener( smgrUnloadingListener, this);
908 }
909 
910 /**
911  * Destroy the ServiceManager
912  */
913 OServiceManager::~OServiceManager()
914 {
915     if( m_nUnloadingListenerId != 0)
916         rtl_removeUnloadingListener( m_nUnloadingListenerId );
917 
918     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
919 }
920 
921 // Removes entries in m_ServiceMap, m_ImplementationNameMap and m_ImplementationNameMap
922 // if those entries have not been inserted through XSet::insert. Therefore the entries
923 // are compared with the entries in m_SetLoadedFactories.
924 void OServiceManager::onUnloadingNotify()
925 {
926     MutexGuard aGuard( m_mutex);
927 
928     typedef HashSet_Ref::const_iterator CIT_S;
929     typedef HashMultimap_OWString_Interface::iterator IT_MM;
930 
931     CIT_S it_SetEnd= m_SetLoadedFactories.end();
932     IT_MM it_end1= m_ServiceMap.end();
933     list<IT_MM> listDeleteServiceMap;
934     typedef list<IT_MM>::const_iterator CIT_DMM;
935     // find occurences in m_ServiceMap
936     for(IT_MM it_i1= m_ServiceMap.begin(); it_i1 != it_end1; it_i1++)
937     {
938         if( m_SetLoadedFactories.find( it_i1->second) != it_SetEnd)
939         {
940             Reference<XUnloadingPreference> xunl( it_i1->second, UNO_QUERY);
941             if( xunl.is())
942             {
943                 if( xunl->releaseOnNotification())
944                     listDeleteServiceMap.push_front( it_i1);
945             }
946             else
947                 listDeleteServiceMap.push_front( it_i1);
948         }
949     }
950     // delete elements from m_ServiceMap
951     CIT_DMM it_end2= listDeleteServiceMap.end();
952     for( CIT_DMM it_i2= listDeleteServiceMap.begin(); it_i2 != it_end2; it_i2++)
953         m_ServiceMap.erase( *it_i2);
954 
955     // find elements in m_ImplementationNameMap
956     typedef HashMap_OWString_Interface::iterator IT_M;
957     IT_M it_end3= m_ImplementationNameMap.end();
958     list<IT_M> listDeleteImplementationNameMap;
959     typedef list<IT_M>::const_iterator CIT_DM;
960     for( IT_M it_i3= m_ImplementationNameMap.begin();  it_i3 != it_end3; it_i3++)
961     {
962         if( m_SetLoadedFactories.find( it_i3->second) != it_SetEnd)
963         {
964             Reference<XUnloadingPreference> xunl( it_i3->second, UNO_QUERY);
965             if( xunl.is())
966             {
967                 if( xunl->releaseOnNotification())
968                     listDeleteImplementationNameMap.push_front( it_i3);
969             }
970             else
971                 listDeleteImplementationNameMap.push_front( it_i3);
972         }
973     }
974     // delete elements from m_ImplementationNameMap
975     CIT_DM it_end4= listDeleteImplementationNameMap.end();
976     for( CIT_DM it_i4= listDeleteImplementationNameMap.begin(); it_i4 != it_end4; it_i4++)
977         m_ImplementationNameMap.erase( *it_i4);
978 
979     // find elements in m_ImplementationMap
980     typedef HashSet_Ref::iterator IT_S;
981     IT_S it_end5= m_ImplementationMap.end();
982     list<IT_S> listDeleteImplementationMap;
983     typedef list<IT_S>::const_iterator CIT_DS;
984     for( IT_S it_i5= m_ImplementationMap.begin(); it_i5 != it_end5; it_i5++)
985     {
986         if( m_SetLoadedFactories.find( *it_i5) != it_SetEnd)
987         {
988             Reference<XUnloadingPreference> xunl( *it_i5, UNO_QUERY);
989             if( xunl.is())
990             {
991                 if( xunl->releaseOnNotification())
992                     listDeleteImplementationMap.push_front( it_i5);
993             }
994             else
995                 listDeleteImplementationMap.push_front( it_i5);
996         }
997     }
998     // delete elements from m_ImplementationMap
999     CIT_DS it_end6= listDeleteImplementationMap.end();
1000     for( CIT_DS it_i6= listDeleteImplementationMap.begin(); it_i6 != it_end6; it_i6++)
1001         m_ImplementationMap.erase( *it_i6);
1002 
1003     // remove Event listener before the factories are released.
1004     IT_S it_end7= m_SetLoadedFactories.end();
1005 
1006     Reference<XEventListener> xlistener= getFactoryListener();
1007     for( IT_S it_i7= m_SetLoadedFactories.begin(); it_i7 != it_end7; it_i7++)
1008     {
1009         Reference<XComponent> xcomp( *it_i7, UNO_QUERY);
1010         if( xcomp.is())
1011             xcomp->removeEventListener( xlistener);
1012     }
1013     // release the factories in m_SetLoadedFactories
1014     m_SetLoadedFactories.clear();
1015 }
1016 
1017 // XComponent
1018 void OServiceManager::dispose()
1019     throw(::com::sun::star::uno::RuntimeException)
1020 {
1021     if (rBHelper.bDisposed || rBHelper.bInDispose)
1022         return;
1023     t_OServiceManager_impl::dispose();
1024 }
1025 
1026 void OServiceManager::disposing()
1027 {
1028     // dispose all factories
1029     HashSet_Ref aImpls;
1030     {
1031         MutexGuard aGuard( m_mutex );
1032         m_bInDisposing = true;
1033         aImpls = m_ImplementationMap;
1034     }
1035     HashSet_Ref::iterator aIt = aImpls.begin();
1036     while( aIt != aImpls.end() )
1037     {
1038         try
1039         {
1040             Reference<XComponent > xComp( Reference<XComponent >::query( *aIt++ ) );
1041             if( xComp.is() )
1042                 xComp->dispose();
1043         }
1044         catch (RuntimeException & exc)
1045         {
1046 #if OSL_DEBUG_LEVEL > 1
1047             OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
1048             OSL_TRACE( "### RuntimeException occured upon disposing factory: %s", str.getStr() );
1049 #else
1050             (void) exc; // unused
1051 #endif
1052         }
1053     }
1054 
1055     // dispose
1056     HashSet_Ref aImplMap;
1057     {
1058         MutexGuard aGuard( m_mutex );
1059         // erase all members
1060         m_ServiceMap = HashMultimap_OWString_Interface();
1061         aImplMap = m_ImplementationMap;
1062         m_ImplementationMap = HashSet_Ref();
1063         m_ImplementationNameMap = HashMap_OWString_Interface();
1064         m_SetLoadedFactories= HashSet_Ref();
1065     }
1066 
1067     m_xContext.clear();
1068 
1069     // not only the Event should hold the object
1070     OSL_ASSERT( m_refCount != 1 );
1071 
1072     // Revoke this service manager as unloading listener
1073     rtl_removeUnloadingListener( m_nUnloadingListenerId);
1074     m_nUnloadingListenerId=0;
1075 }
1076 
1077 // XPropertySet
1078 Reference<XPropertySetInfo > OServiceManager::getPropertySetInfo()
1079     throw(::com::sun::star::uno::RuntimeException)
1080 {
1081     check_undisposed();
1082     if (! m_xPropertyInfo.is())
1083     {
1084         Sequence< beans::Property > seq( 1 );
1085         seq[ 0 ] = beans::Property(
1086             OUSTR("DefaultContext"), -1, ::getCppuType( &m_xContext ), 0 );
1087         Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
1088 
1089         MutexGuard aGuard( m_mutex );
1090         if (! m_xPropertyInfo.is())
1091         {
1092             m_xPropertyInfo = xInfo;
1093         }
1094     }
1095     return m_xPropertyInfo;
1096 }
1097 
1098 void OServiceManager::setPropertyValue(
1099     const OUString& PropertyName, const Any& aValue )
1100     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1101 {
1102     check_undisposed();
1103     if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") ))
1104     {
1105         Reference< XComponentContext > xContext;
1106         if (aValue >>= xContext)
1107         {
1108             MutexGuard aGuard( m_mutex );
1109             m_xContext = xContext;
1110         }
1111         else
1112         {
1113             throw IllegalArgumentException(
1114                 OUString( RTL_CONSTASCII_USTRINGPARAM("no XComponentContext given!") ),
1115                 (OWeakObject *)this, 1 );
1116         }
1117     }
1118     else
1119     {
1120         throw UnknownPropertyException(
1121             OUString( RTL_CONSTASCII_USTRINGPARAM("unknown property ") ) + PropertyName,
1122             (OWeakObject *)this );
1123     }
1124 }
1125 
1126 Any OServiceManager::getPropertyValue(const OUString& PropertyName)
1127     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1128 {
1129     check_undisposed();
1130     if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") ))
1131     {
1132         MutexGuard aGuard( m_mutex );
1133         if( m_xContext.is() )
1134             return makeAny( m_xContext );
1135         else
1136             return Any();
1137     }
1138     else
1139     {
1140         UnknownPropertyException except;
1141         except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager : unknown property " ) );
1142         except.Message += PropertyName;
1143         throw except;
1144     }
1145 }
1146 
1147 void OServiceManager::addPropertyChangeListener(
1148     const OUString&, const Reference<XPropertyChangeListener >&)
1149     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1150 {
1151     check_undisposed();
1152     throw UnknownPropertyException();
1153 }
1154 
1155 void OServiceManager::removePropertyChangeListener(
1156     const OUString&, const Reference<XPropertyChangeListener >&)
1157     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1158 {
1159     check_undisposed();
1160     throw UnknownPropertyException();
1161 }
1162 
1163 void OServiceManager::addVetoableChangeListener(
1164     const OUString&, const Reference<XVetoableChangeListener >&)
1165     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1166 {
1167     check_undisposed();
1168     throw UnknownPropertyException();
1169 }
1170 
1171 void OServiceManager::removeVetoableChangeListener(
1172     const OUString&, const Reference<XVetoableChangeListener >&)
1173     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1174 {
1175     check_undisposed();
1176     throw UnknownPropertyException();
1177 }
1178 
1179 // OServiceManager
1180 Reference<XEventListener > OServiceManager::getFactoryListener()
1181 {
1182     check_undisposed();
1183     MutexGuard aGuard( m_mutex );
1184     if( !xFactoryListener.is() )
1185         xFactoryListener = new OServiceManager_Listener( this );
1186     return xFactoryListener;
1187 }
1188 
1189 // XMultiServiceFactory, XContentEnumeration
1190 Sequence< OUString > OServiceManager::getUniqueAvailableServiceNames(
1191     HashSet_OWString & aNameSet )
1192 {
1193     check_undisposed();
1194     MutexGuard aGuard( m_mutex );
1195     HashMultimap_OWString_Interface::iterator aSIt = m_ServiceMap.begin();
1196     while( aSIt != m_ServiceMap.end() )
1197         aNameSet.insert( (*aSIt++).first );
1198 
1199     /* do not return the implementation names
1200     HashMap_OWString_Interface      m_ImplementationNameMap;
1201     HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin();
1202     while( aIt != m_ImplementationNameMap.end() )
1203         aNameSet.insert( (*aIt++).first );
1204     */
1205 
1206     Sequence< OUString > aNames( aNameSet.size() );
1207     OUString * pArray = aNames.getArray();
1208     sal_Int32 i = 0;
1209     HashSet_OWString::iterator next = aNameSet.begin();
1210     while( next != aNameSet.end() )
1211         pArray[i++] = (*next++);
1212 
1213     return aNames;
1214 }
1215 
1216 // XMultiComponentFactory
1217 Reference< XInterface > OServiceManager::createInstanceWithContext(
1218     OUString const & rServiceSpecifier,
1219     Reference< XComponentContext > const & xContext )
1220     throw (Exception, RuntimeException)
1221 {
1222     check_undisposed();
1223 #if OSL_DEBUG_LEVEL > 0
1224     Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
1225     OSL_ASSERT( xProps.is() );
1226     if (xProps.is())
1227     {
1228         Reference< XComponentContext > xDefContext;
1229         xProps->getPropertyValue(
1230             OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xDefContext;
1231         OSL_ENSURE(
1232             xContext == xDefContext,
1233             "### default context of service manager singleton differs from context holding it!" );
1234     }
1235 #endif
1236 
1237     Sequence< Reference< XInterface > > factories(
1238         queryServiceFactories( rServiceSpecifier, xContext ) );
1239     Reference< XInterface > const * p = factories.getConstArray();
1240     for ( sal_Int32 nPos = 0; nPos < factories.getLength(); ++nPos )
1241     {
1242         try
1243         {
1244             Reference< XInterface > const & xFactory = p[ nPos ];
1245             if (xFactory.is())
1246             {
1247                 Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
1248                 if (xFac.is())
1249                 {
1250                     return xFac->createInstanceWithContext( xContext );
1251                 }
1252                 else
1253                 {
1254                     Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
1255                     if (xFac2.is())
1256                     {
1257 #if OSL_DEBUG_LEVEL > 1
1258                         OString aStr( OUStringToOString( rServiceSpecifier, RTL_TEXTENCODING_ASCII_US ) );
1259                         OSL_TRACE( "### ignoring given context raising service %s !!!\n", aStr.getStr() );
1260 #endif
1261                         return xFac2->createInstance();
1262                     }
1263                 }
1264             }
1265         }
1266         catch (lang::DisposedException & exc)
1267         {
1268 #if OSL_DEBUG_LEVEL > 1
1269             OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
1270             OSL_TRACE( "### DisposedException occured: %s", str.getStr() );
1271 #else
1272             (void) exc; // unused
1273 #endif
1274         }
1275     }
1276 
1277     return Reference< XInterface >();
1278 }
1279 // XMultiComponentFactory
1280 Reference< XInterface > OServiceManager::createInstanceWithArgumentsAndContext(
1281     OUString const & rServiceSpecifier,
1282     Sequence< Any > const & rArguments,
1283     Reference< XComponentContext > const & xContext )
1284     throw (Exception, RuntimeException)
1285 {
1286     check_undisposed();
1287 #if OSL_DEBUG_LEVEL > 0
1288     Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
1289     OSL_ASSERT( xProps.is() );
1290     if (xProps.is())
1291     {
1292         Reference< XComponentContext > xDefContext;
1293         xProps->getPropertyValue(
1294             OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xDefContext;
1295         OSL_ENSURE(
1296             xContext == xDefContext,
1297             "### default context of service manager singleton differs from context holding it!" );
1298     }
1299 #endif
1300 
1301     Sequence< Reference< XInterface > > factories(
1302         queryServiceFactories( rServiceSpecifier, xContext ) );
1303     Reference< XInterface > const * p = factories.getConstArray();
1304     for ( sal_Int32 nPos = 0; nPos < factories.getLength(); ++nPos )
1305     {
1306         try
1307         {
1308             Reference< XInterface > const & xFactory = p[ nPos ];
1309             if (xFactory.is())
1310             {
1311                 Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
1312                 if (xFac.is())
1313                 {
1314                     return xFac->createInstanceWithArgumentsAndContext( rArguments, xContext );
1315                 }
1316                 else
1317                 {
1318                     Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
1319                     if (xFac2.is())
1320                     {
1321 #if OSL_DEBUG_LEVEL > 1
1322                         OString aStr( OUStringToOString( rServiceSpecifier, RTL_TEXTENCODING_ASCII_US ) );
1323                         OSL_TRACE( "### ignoring given context raising service %s !!!\n", aStr.getStr() );
1324 #endif
1325                         return xFac2->createInstanceWithArguments( rArguments );
1326                     }
1327                 }
1328             }
1329         }
1330         catch (lang::DisposedException & exc)
1331         {
1332 #if OSL_DEBUG_LEVEL > 1
1333             OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
1334             OSL_TRACE( "### DisposedException occured: %s", str.getStr() );
1335 #else
1336             (void) exc; // unused
1337 #endif
1338         }
1339     }
1340 
1341     return Reference< XInterface >();
1342 }
1343 
1344 // XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration
1345 Sequence< OUString > OServiceManager::getAvailableServiceNames()
1346     throw(::com::sun::star::uno::RuntimeException)
1347 {
1348     check_undisposed();
1349     // all names
1350     HashSet_OWString aNameSet;
1351     return getUniqueAvailableServiceNames( aNameSet );
1352 }
1353 
1354 // XMultibleServiceFactory
1355 Reference<XInterface > OServiceManager::createInstance(
1356     const OUString& rServiceSpecifier )
1357     throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1358 {
1359     return createInstanceWithContext(
1360         rServiceSpecifier, m_xContext );
1361 }
1362 
1363 // XMultibleServiceFactory
1364 Reference<XInterface > OServiceManager::createInstanceWithArguments(
1365     const OUString& rServiceSpecifier,
1366     const Sequence<Any >& rArguments )
1367     throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1368 {
1369     return createInstanceWithArgumentsAndContext(
1370         rServiceSpecifier, rArguments, m_xContext );
1371 }
1372 
1373 // XInitialization
1374 void OServiceManager::initialize( Sequence< Any > const & )
1375     throw (Exception)
1376 {
1377     check_undisposed();
1378     OSL_ENSURE( 0, "not impl!" );
1379 }
1380 
1381 // XServiceInfo
1382 OUString OServiceManager::getImplementationName()
1383     throw(::com::sun::star::uno::RuntimeException)
1384 {
1385     check_undisposed();
1386     return getImplementationName_Static();
1387 }
1388 
1389 // XServiceInfo
1390 sal_Bool OServiceManager::supportsService(const OUString& ServiceName)
1391     throw(::com::sun::star::uno::RuntimeException)
1392 {
1393     check_undisposed();
1394     Sequence< OUString > aSNL = getSupportedServiceNames();
1395     const OUString * pArray = aSNL.getConstArray();
1396     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1397         if( pArray[i] == ServiceName )
1398             return sal_True;
1399     return sal_False;
1400 }
1401 
1402 // XServiceInfo
1403 Sequence< OUString > OServiceManager::getSupportedServiceNames()
1404     throw(::com::sun::star::uno::RuntimeException)
1405 {
1406     check_undisposed();
1407     return stoc_bootstrap::smgr_getSupportedServiceNames();
1408 }
1409 
1410 
1411 Sequence< Reference< XInterface > > OServiceManager::queryServiceFactories(
1412     const OUString& aServiceName, Reference< XComponentContext > const & )
1413 {
1414     Sequence< Reference< XInterface > > ret;
1415 
1416     MutexGuard aGuard( m_mutex );
1417     ::std::pair<
1418           HashMultimap_OWString_Interface::iterator,
1419           HashMultimap_OWString_Interface::iterator> p(
1420               m_ServiceMap.equal_range( aServiceName ) );
1421 
1422     if (p.first == p.second) // no factories
1423     {
1424         // no service found, look for an implementation
1425         HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.find( aServiceName );
1426         if( aIt != m_ImplementationNameMap.end() )
1427         {
1428             Reference< XInterface > const & x = aIt->second;
1429             // an implementation found
1430             ret = Sequence< Reference< XInterface > >( &x, 1 );
1431         }
1432     }
1433     else
1434     {
1435         ::std::vector< Reference< XInterface > > vec;
1436         vec.reserve( 4 );
1437         while (p.first != p.second)
1438         {
1439             vec.push_back( p.first->second );
1440             ++p.first;
1441         }
1442         ret = Sequence< Reference< XInterface > >(
1443             vec.empty() ? 0 : &vec[ 0 ], vec.size() );
1444     }
1445 
1446     return ret;
1447 }
1448 
1449 // XContentEnumerationAccess
1450 Reference<XEnumeration > OServiceManager::createContentEnumeration(
1451     const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1452     throw(::com::sun::star::uno::RuntimeException)
1453 {
1454     check_undisposed();
1455     Sequence< Reference< XInterface > > factories(
1456         OServiceManager::queryServiceFactories( aServiceName, xContext ) );
1457     if (factories.getLength())
1458         return new ServiceEnumeration_Impl( factories );
1459     else
1460         return Reference< XEnumeration >();
1461 }
1462 Reference<XEnumeration > OServiceManager::createContentEnumeration(
1463     const OUString& aServiceName )
1464     throw(::com::sun::star::uno::RuntimeException)
1465 {
1466     return createContentEnumeration( aServiceName, m_xContext );
1467 }
1468 
1469 // XEnumeration
1470 Reference<XEnumeration > OServiceManager::createEnumeration() throw(::com::sun::star::uno::RuntimeException)
1471 {
1472     check_undisposed();
1473     MutexGuard aGuard( m_mutex );
1474     return new ImplementationEnumeration_Impl( m_ImplementationMap );
1475 }
1476 
1477 // XElementAccess
1478 Type OServiceManager::getElementType()
1479     throw(::com::sun::star::uno::RuntimeException)
1480 {
1481     check_undisposed();
1482     return ::getCppuType( (const Reference< XInterface > *)0 );
1483 }
1484 
1485 // XElementAccess
1486 sal_Bool OServiceManager::hasElements()
1487     throw(::com::sun::star::uno::RuntimeException)
1488 {
1489     check_undisposed();
1490     MutexGuard aGuard( m_mutex );
1491     return !m_ImplementationMap.empty();
1492 }
1493 
1494 // XSet
1495 sal_Bool OServiceManager::has( const Any & Element )
1496     throw(::com::sun::star::uno::RuntimeException)
1497 {
1498     check_undisposed();
1499     if( Element.getValueTypeClass() == TypeClass_INTERFACE )
1500     {
1501         Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
1502         MutexGuard aGuard( m_mutex );
1503         return m_ImplementationMap.find( xEle ) !=
1504             m_ImplementationMap.end();
1505     }
1506     else if (Element.getValueTypeClass() == TypeClass_STRING)
1507     {
1508         OUString const & implName =
1509             *reinterpret_cast< OUString const * >(Element.getValue());
1510         MutexGuard aGuard( m_mutex );
1511         return m_ImplementationNameMap.find( implName ) !=
1512             m_ImplementationNameMap.end();
1513     }
1514     return sal_False;
1515 }
1516 
1517 // XSet
1518 void OServiceManager::insert( const Any & Element )
1519     throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
1520 {
1521     check_undisposed();
1522     if( Element.getValueTypeClass() != TypeClass_INTERFACE )
1523     {
1524         throw IllegalArgumentException(
1525             OUString( RTL_CONSTASCII_USTRINGPARAM("no interface given!") ),
1526             Reference< XInterface >(), 0 );
1527     }
1528     Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
1529 
1530     {
1531     MutexGuard aGuard( m_mutex );
1532     HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1533     if( aIt != m_ImplementationMap.end() )
1534     {
1535         throw ElementExistException(
1536             OUString( RTL_CONSTASCII_USTRINGPARAM("element already exists!") ),
1537             Reference< XInterface >() );
1538     }
1539 
1540     // put into the implementation hashmap
1541     m_ImplementationMap.insert( xEle );
1542 
1543     // put into the implementation name hashmap
1544     Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1545     if( xInfo.is() )
1546     {
1547         OUString aImplName = xInfo->getImplementationName();
1548         if( aImplName.getLength() )
1549             m_ImplementationNameMap[ aImplName ] = xEle;
1550 
1551         //put into the service map
1552         Sequence< OUString > aServiceNames = xInfo->getSupportedServiceNames();
1553         const OUString * pArray = aServiceNames.getConstArray();
1554         for( sal_Int32 i = 0; i < aServiceNames.getLength(); i++ )
1555         {
1556             m_ServiceMap.insert( HashMultimap_OWString_Interface::value_type(
1557                 pArray[i], *(Reference<XInterface > *)Element.getValue() ) );
1558         }
1559     }
1560     }
1561     // add the disposing listener to the factory
1562     Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1563     if( xComp.is() )
1564         xComp->addEventListener( getFactoryListener() );
1565 }
1566 
1567 // helper function
1568 sal_Bool OServiceManager::haveFactoryWithThisImplementation(const OUString& aImplName)
1569 {
1570     return ( m_ImplementationNameMap.find(aImplName) != m_ImplementationNameMap.end());
1571 }
1572 
1573 // XSet
1574 void OServiceManager::remove( const Any & Element )
1575      throw(::com::sun::star::lang::IllegalArgumentException,
1576            ::com::sun::star::container::NoSuchElementException,
1577            ::com::sun::star::uno::RuntimeException)
1578 {
1579     if (is_disposed())
1580         return;
1581 
1582     Reference<XInterface > xEle;
1583     if (Element.getValueTypeClass() == TypeClass_INTERFACE)
1584     {
1585         xEle.set( Element, UNO_QUERY_THROW );
1586     }
1587     else if (Element.getValueTypeClass() == TypeClass_STRING)
1588     {
1589         OUString const & implName =
1590             *reinterpret_cast< OUString const * >(Element.getValue());
1591         MutexGuard aGuard( m_mutex );
1592         HashMap_OWString_Interface::const_iterator const iFind(
1593             m_ImplementationNameMap.find( implName ) );
1594         if (iFind == m_ImplementationNameMap.end())
1595         {
1596             throw NoSuchElementException(
1597                 OUString( RTL_CONSTASCII_USTRINGPARAM("element is not in: ") )
1598                 + implName, static_cast< OWeakObject * >(this) );
1599         }
1600         xEle = iFind->second;
1601     }
1602     else
1603     {
1604         throw IllegalArgumentException(
1605             OUString( RTL_CONSTASCII_USTRINGPARAM(
1606                           "neither interface nor string given!") ),
1607             Reference< XInterface >(), 0 );
1608     }
1609 
1610     // remove the disposing listener from the factory
1611     Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1612     if( xComp.is() )
1613         xComp->removeEventListener( getFactoryListener() );
1614 
1615     MutexGuard aGuard( m_mutex );
1616     HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1617     if( aIt == m_ImplementationMap.end() )
1618     {
1619         throw NoSuchElementException(
1620             OUString( RTL_CONSTASCII_USTRINGPARAM("element is not in!") ),
1621             static_cast< OWeakObject * >(this) );
1622     }
1623     //First remove all factories which have been loaded by ORegistryServiceManager.
1624     m_SetLoadedFactories.erase( *aIt);
1625     //Remove from the implementation map. It contains all factories of m_SetLoadedFactories
1626     //which have been added directly through XSet, that is not via ORegistryServiceManager
1627     m_ImplementationMap.erase( aIt );
1628 
1629     // remove from the implementation name hashmap
1630     Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1631     if( xInfo.is() )
1632     {
1633         OUString aImplName = xInfo->getImplementationName();
1634         if( aImplName.getLength() )
1635             m_ImplementationNameMap.erase( aImplName );
1636     }
1637 
1638     //remove from the service map
1639     Reference<XServiceInfo > xSF( Reference<XServiceInfo >::query( xEle ) );
1640     if( xSF.is() )
1641     {
1642         Sequence< OUString > aServiceNames = xSF->getSupportedServiceNames();
1643         const OUString * pArray = aServiceNames.getConstArray();
1644         for( sal_Int32 i = 0; i < aServiceNames.getLength(); i++ )
1645         {
1646             pair<HashMultimap_OWString_Interface::iterator, HashMultimap_OWString_Interface::iterator> p =
1647                 m_ServiceMap.equal_range( pArray[i] );
1648 
1649             while( p.first != p.second )
1650             {
1651                 if( xEle == (*p.first).second )
1652                 {
1653                     m_ServiceMap.erase( p.first );
1654                     break;
1655                 }
1656                 ++p.first;
1657             }
1658         }
1659     }
1660 }
1661 
1662 /*****************************************************************************
1663     class ORegistryServiceManager
1664 *****************************************************************************/
1665 class ORegistryServiceManager : public OServiceManager
1666 {
1667 public:
1668     ORegistryServiceManager( Reference< XComponentContext > const & xContext );
1669     virtual ~ORegistryServiceManager();
1670 
1671     // XInitialization
1672     void SAL_CALL initialize(const Sequence< Any >& Arguments)
1673         throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
1674 
1675     // XServiceInfo
1676     OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException)
1677         { return stoc_bootstrap::regsmgr_getImplementationName(); }
1678 
1679     Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException);
1680 
1681     // XMultiServiceFactory
1682     Sequence< OUString > SAL_CALL getAvailableServiceNames() throw(::com::sun::star::uno::RuntimeException);
1683 
1684     // XContentEnumerationAccess
1685     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
1686     Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw(::com::sun::star::uno::RuntimeException);
1687     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(
1688         const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1689         throw(::com::sun::star::uno::RuntimeException);
1690 
1691     // XComponent
1692     void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
1693 
1694     // OServiceManager
1695     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo()
1696         throw(::com::sun::star::uno::RuntimeException);
1697     Any SAL_CALL getPropertyValue(const OUString& PropertyName)
1698         throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
1699 
1700 protected:
1701     //OServiceManager
1702     Sequence< Reference< XInterface > > queryServiceFactories(
1703         const OUString& aServiceName, Reference< XComponentContext > const & xContext );
1704 private:
1705     Reference<XRegistryKey >        getRootKey();
1706     Reference<XInterface > loadWithImplementationName(
1707         const OUString & rImplName, Reference< XComponentContext > const & xContext );
1708     Sequence<OUString>          getFromServiceName(const OUString& serviceName);
1709     Reference<XInterface > loadWithServiceName(
1710         const OUString & rImplName, Reference< XComponentContext > const & xContext );
1711     void                        fillAllNamesFromRegistry( HashSet_OWString & );
1712 
1713     sal_Bool                    m_searchedRegistry;
1714     Reference<XSimpleRegistry > m_xRegistry;    // readonly property Registry
1715     Reference<XRegistryKey >    m_xRootKey;
1716 
1717 #if OSL_DEBUG_LEVEL > 0
1718     bool m_init;
1719 #endif
1720 };
1721 
1722 /**
1723  * Create a ServiceManager
1724  */
1725 ORegistryServiceManager::ORegistryServiceManager( Reference< XComponentContext > const & xContext )
1726     : OServiceManager( xContext )
1727     , m_searchedRegistry(sal_False)
1728 #if OSL_DEBUG_LEVEL > 0
1729     , m_init( false )
1730 #endif
1731 {
1732 }
1733 
1734 /**
1735  * Destroy the ServiceManager
1736  */
1737 ORegistryServiceManager::~ORegistryServiceManager()
1738 {
1739 }
1740 
1741 // XComponent
1742 void ORegistryServiceManager::dispose()
1743     throw(::com::sun::star::uno::RuntimeException)
1744 {
1745     if (rBHelper.bDisposed || rBHelper.bInDispose)
1746         return;
1747     OServiceManager::dispose();
1748     // dispose
1749     MutexGuard aGuard( m_mutex );
1750     // erase all members
1751     m_xRegistry = Reference<XSimpleRegistry >();
1752     m_xRootKey = Reference<XRegistryKey >();
1753 }
1754 
1755 /**
1756  * Return the root key of the registry. The Default registry service is ordered
1757  * if no registry is set.
1758  */
1759 //Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider();
1760 
1761 Reference<XRegistryKey > ORegistryServiceManager::getRootKey()
1762 {
1763     if( !m_xRootKey.is() )
1764     {
1765         MutexGuard aGuard( m_mutex );
1766         //  DefaultRegistry suchen !!!!
1767         if( !m_xRegistry.is() && !m_searchedRegistry )
1768         {
1769             // merken, es wird nur einmal gesucht
1770             m_searchedRegistry = sal_True;
1771 
1772             m_xRegistry.set(
1773                 createInstanceWithContext(
1774                     OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.DefaultRegistry") ),
1775                     m_xContext ),
1776                 UNO_QUERY );
1777         }
1778         if( m_xRegistry.is() && !m_xRootKey.is() )
1779             m_xRootKey = m_xRegistry->getRootKey();
1780     }
1781 
1782     return m_xRootKey;
1783 }
1784 
1785 /**
1786  * Create a service provider from the registry with an implementation name
1787  */
1788 Reference<XInterface > ORegistryServiceManager::loadWithImplementationName(
1789     const OUString& name, Reference< XComponentContext > const & xContext )
1790 {
1791     Reference<XInterface > ret;
1792 
1793     Reference<XRegistryKey > xRootKey = getRootKey();
1794     if( !xRootKey.is() )
1795         return ret;
1796 
1797     try
1798     {
1799         OUString implementationName = OUString( RTL_CONSTASCII_USTRINGPARAM("/IMPLEMENTATIONS/") ) + name;
1800         Reference<XRegistryKey > xImpKey = m_xRootKey->openKey(implementationName);
1801 
1802         if( xImpKey.is() )
1803         {
1804             Reference< lang::XMultiServiceFactory > xMgr;
1805             if (xContext.is())
1806                 xMgr.set( xContext->getServiceManager(), UNO_QUERY_THROW );
1807             else
1808                 xMgr.set( this );
1809             ret = createSingleRegistryFactory( xMgr, name, xImpKey );
1810             insert( makeAny( ret ) );
1811             // Remember this factory as loaded in contrast to inserted ( XSet::insert)
1812             // factories. Those loaded factories in this set are candidates for being
1813             // released on an unloading notification.
1814             m_SetLoadedFactories.insert( ret);
1815         }
1816     }
1817     catch (InvalidRegistryException &)
1818     {
1819     }
1820 
1821     return ret;
1822 }
1823 
1824 /**
1825  * Return all implementation out of the registry.
1826  */
1827 Sequence<OUString> ORegistryServiceManager::getFromServiceName(
1828     const OUString& serviceName )
1829 {
1830     OUStringBuffer buf;
1831     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "/SERVICES/" ) );
1832     buf.append( serviceName );
1833     return retrieveAsciiValueList( m_xRegistry, buf.makeStringAndClear() );
1834 }
1835 
1836 /**
1837  * Create a service provider from the registry
1838  */
1839 Reference<XInterface > ORegistryServiceManager::loadWithServiceName(
1840     const OUString& serviceName, Reference< XComponentContext > const & xContext )
1841 {
1842     Sequence<OUString> implEntries = getFromServiceName( serviceName );
1843     for (sal_Int32 i = 0; i < implEntries.getLength(); i++)
1844     {
1845         Reference< XInterface > x(
1846             loadWithImplementationName( implEntries.getConstArray()[i], xContext ) );
1847         if (x.is())
1848             return x;
1849     }
1850 
1851     return Reference<XInterface >();
1852 }
1853 
1854 /**
1855  * Return a sequence of all service names from the registry.
1856  */
1857 void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString & rSet )
1858 {
1859     Reference<XRegistryKey > xRootKey = getRootKey();
1860     if( !xRootKey.is() )
1861         return;
1862 
1863     try
1864     {
1865         Reference<XRegistryKey > xServicesKey = xRootKey->openKey(
1866             OUString( RTL_CONSTASCII_USTRINGPARAM("SERVICES") ) );
1867         // root + /Services + /
1868         if( xServicesKey.is() )
1869         {
1870             sal_Int32 nPrefix = xServicesKey->getKeyName().getLength() +1;
1871             Sequence<Reference<XRegistryKey > > aKeys = xServicesKey->openKeys();
1872             for( sal_Int32 i = 0; i < aKeys.getLength(); i++ )
1873                 rSet.insert( aKeys.getConstArray()[i]->getKeyName().copy( nPrefix ) );
1874         }
1875     }
1876     catch (InvalidRegistryException &)
1877     {
1878     }
1879 }
1880 
1881 // XInitialization
1882 void ORegistryServiceManager::initialize(const Sequence< Any >& Arguments)
1883     throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
1884 {
1885     check_undisposed();
1886     MutexGuard aGuard( m_mutex );
1887     if (Arguments.getLength() > 0)
1888     {
1889         m_xRootKey.clear();
1890         Arguments[ 0 ] >>= m_xRegistry;
1891     }
1892 #if OSL_DEBUG_LEVEL > 0
1893     // to find all bootstrapping processes to be fixed...
1894     OSL_ENSURE( !m_init, "### second init of service manager instance!" );
1895     m_init = true;
1896 #endif
1897 }
1898 
1899 // XMultiServiceFactory, XContentEnumeration
1900 Sequence< OUString > ORegistryServiceManager::getAvailableServiceNames()
1901     throw(::com::sun::star::uno::RuntimeException)
1902 {
1903     check_undisposed();
1904     MutexGuard aGuard( m_mutex );
1905     // all names
1906     HashSet_OWString aNameSet;
1907 
1908     // all names from the registry
1909     fillAllNamesFromRegistry( aNameSet );
1910 
1911     return OServiceManager::getUniqueAvailableServiceNames( aNameSet );
1912 }
1913 
1914 // XServiceInfo
1915 Sequence< OUString > ORegistryServiceManager::getSupportedServiceNames()
1916     throw(::com::sun::star::uno::RuntimeException)
1917 {
1918     check_undisposed();
1919     return stoc_bootstrap::regsmgr_getSupportedServiceNames();
1920 }
1921 
1922 
1923 // OServiceManager
1924 Sequence< Reference< XInterface > > ORegistryServiceManager::queryServiceFactories(
1925     const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1926 {
1927     Sequence< Reference< XInterface > > ret(
1928         OServiceManager::queryServiceFactories( aServiceName, xContext ) );
1929     if (ret.getLength())
1930     {
1931         return ret;
1932     }
1933     else
1934     {
1935         MutexGuard aGuard( m_mutex );
1936         Reference< XInterface > x( loadWithServiceName( aServiceName, xContext ) );
1937         if (! x.is())
1938             x = loadWithImplementationName( aServiceName, xContext );
1939         return Sequence< Reference< XInterface > >( &x, 1 );
1940     }
1941 }
1942 
1943 // XContentEnumerationAccess
1944 Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration(
1945     const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1946     throw(::com::sun::star::uno::RuntimeException)
1947 {
1948     check_undisposed();
1949     MutexGuard aGuard( ((ORegistryServiceManager *)this)->m_mutex );
1950     // get all implementation names registered under this service name from the registry
1951     Sequence<OUString> aImpls = ((ORegistryServiceManager *)this)->getFromServiceName( aServiceName );
1952     // load and insert all factories specified by the registry
1953     sal_Int32 i;
1954     OUString aImplName;
1955     for( i = 0; i < aImpls.getLength(); i++ )
1956     {
1957         aImplName = aImpls.getConstArray()[i];
1958         if ( !haveFactoryWithThisImplementation(aImplName) )
1959         {
1960             loadWithImplementationName( aImplName, xContext );
1961         }
1962     }
1963     // call the superclass to enumerate all contents
1964     return OServiceManager::createContentEnumeration( aServiceName, xContext );
1965 }
1966 Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration(
1967     const OUString& aServiceName )
1968     throw(::com::sun::star::uno::RuntimeException)
1969 {
1970     return createContentEnumeration( aServiceName, m_xContext );
1971 }
1972 
1973 // OServiceManager
1974 Reference<XPropertySetInfo > ORegistryServiceManager::getPropertySetInfo()
1975     throw(::com::sun::star::uno::RuntimeException)
1976 {
1977     check_undisposed();
1978     if (! m_xPropertyInfo.is())
1979     {
1980         Sequence< beans::Property > seq( 2 );
1981         seq[ 0 ] = beans::Property(
1982             OUSTR("DefaultContext"), -1, ::getCppuType( &m_xContext ), 0 );
1983         seq[ 1 ] = beans::Property(
1984             OUSTR("Registry"), -1, ::getCppuType( &m_xRegistry ),
1985             beans::PropertyAttribute::READONLY );
1986         Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
1987 
1988         MutexGuard aGuard( m_mutex );
1989         if (! m_xPropertyInfo.is())
1990         {
1991             m_xPropertyInfo = xInfo;
1992         }
1993     }
1994     return m_xPropertyInfo;
1995 }
1996 
1997 Any ORegistryServiceManager::getPropertyValue(const OUString& PropertyName)
1998     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
1999 {
2000     check_undisposed();
2001     if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Registry") ))
2002     {
2003         MutexGuard aGuard( m_mutex );
2004         if( m_xRegistry.is() )
2005             return makeAny( m_xRegistry );
2006         else
2007             return Any();
2008     }
2009     return OServiceManager::getPropertyValue( PropertyName );
2010 }
2011 
2012 /* This is the listener function used by the service manager in order
2013 to implement the unloading mechanism, id is the this pointer of the
2014 service manager instances. On notification, that is the function is being called
2015 by rtl_unloadUnusedModules, the cached factroies are being removed from the
2016 service manager ( except manually inserted factories).
2017 */
2018 extern "C" void SAL_CALL smgrUnloadingListener(void* id)
2019 {
2020     stoc_smgr::OServiceManager* pMgr= reinterpret_cast<stoc_smgr::OServiceManager*>( id);
2021     pMgr->onUnloadingNotify();
2022 }
2023 
2024 } // namespace
2025 
2026 namespace stoc_bootstrap
2027 {
2028 /**
2029  * Create the ServiceManager
2030  */
2031 Reference<XInterface > SAL_CALL OServiceManager_CreateInstance(
2032     const Reference< XComponentContext > & xContext )
2033 {
2034     return Reference<XInterface >(
2035         SAL_STATIC_CAST(
2036             XInterface *, SAL_STATIC_CAST(
2037                 OWeakObject *, new stoc_smgr::OServiceManager( xContext ) ) ) );
2038 }
2039 
2040 /**
2041  * Create the ServiceManager
2042  */
2043 Reference<XInterface > SAL_CALL ORegistryServiceManager_CreateInstance(
2044     const Reference< XComponentContext > & xContext )
2045     throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
2046 {
2047     return Reference<XInterface >(
2048         SAL_STATIC_CAST(
2049             XInterface *, SAL_STATIC_CAST(
2050                 OWeakObject *, new stoc_smgr::ORegistryServiceManager( xContext ) ) ) );
2051 }
2052 
2053 Reference<XInterface > SAL_CALL OServiceManagerWrapper_CreateInstance(
2054     const Reference< XComponentContext > & xContext )
2055     throw (Exception)
2056 {
2057     return (OWeakObject *)new stoc_smgr::OServiceManagerWrapper( xContext );
2058 }
2059 }
2060