1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <o3tl/any.hxx>
23 #include <osl/mutex.hxx>
24 #include <osl/diagnose.h>
25 #include <sal/log.hxx>
26 #include <tools/diagnose_ex.h>
27 
28 #include <cppuhelper/factory.hxx>
29 #include <cppuhelper/weakref.hxx>
30 #include <cppuhelper/implbase.hxx>
31 #include <cppuhelper/compbase.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <comphelper/sequence.hxx>
34 
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
39 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
40 #include <com/sun/star/lang/XInitialization.hpp>
41 #include <com/sun/star/lang/XEventListener.hpp>
42 #include <com/sun/star/lang/DisposedException.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/registry/XRegistryKey.hpp>
46 #include <com/sun/star/registry/XSimpleRegistry.hpp>
47 #include <com/sun/star/container/XSet.hpp>
48 #include <com/sun/star/container/XElementAccess.hpp>
49 #include <com/sun/star/container/XEnumeration.hpp>
50 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
51 #include <com/sun/star/uno/XComponentContext.hpp>
52 
53 #include <iterator>
54 #include <string_view>
55 #include <unordered_map>
56 #include <unordered_set>
57 
58 using namespace com::sun::star;
59 using namespace css::uno;
60 using namespace css::beans;
61 using namespace css::registry;
62 using namespace css::lang;
63 using namespace css::container;
64 using namespace cppu;
65 using namespace osl;
66 using namespace std;
67 
68 namespace {
69 
retrieveAsciiValueList(const Reference<XSimpleRegistry> & xReg,const OUString & keyName)70 Sequence< OUString > retrieveAsciiValueList(
71     const Reference< XSimpleRegistry > &xReg, const OUString &keyName )
72 {
73     Reference< XEnumerationAccess > xAccess( xReg, UNO_QUERY );
74     Sequence< OUString > seq;
75     if( xAccess.is() )
76     {
77         Reference< XEnumeration > xEnum = xAccess->createEnumeration();
78         while( xEnum.is() && xEnum->hasMoreElements() )
79         {
80             Reference< XSimpleRegistry > xTempReg;
81             xEnum->nextElement() >>= xTempReg;
82             if( xTempReg.is() )
83             {
84                 Sequence< OUString > seq2 = retrieveAsciiValueList( xTempReg, keyName );
85 
86                 if( seq2.hasElements() )
87                 {
88                     sal_Int32 n1Len = seq.getLength();
89                     sal_Int32 n2Len = seq2.getLength();
90 
91                     seq.realloc( n1Len + n2Len );
92                     std::copy(seq2.begin(), seq2.end(), std::next(seq.begin(), n1Len));
93                 }
94             }
95         }
96     }
97     else if( xReg.is () )
98     {
99         try
100         {
101             Reference< XRegistryKey > rRootKey = xReg->getRootKey();
102             if( rRootKey.is() )
103             {
104                 Reference<XRegistryKey > xKey = rRootKey->openKey(keyName);
105                 if( xKey.is() )
106                 {
107                     seq = xKey->getAsciiListValue();
108                 }
109             }
110         }
111         catch( InvalidRegistryException & )
112         {
113         }
114         catch (InvalidValueException &)
115         {
116         }
117     }
118     return seq;
119 }
120 
121 /*****************************************************************************
122     Enumeration by ServiceName
123 *****************************************************************************/
124 
125 typedef std::unordered_set< Reference<XInterface > > HashSet_Ref;
126 
127 
128 class ServiceEnumeration_Impl : public WeakImplHelper< XEnumeration >
129 {
130 public:
ServiceEnumeration_Impl(const Sequence<Reference<XInterface>> & rFactories)131     explicit ServiceEnumeration_Impl( const Sequence< Reference<XInterface > > & rFactories )
132         : aFactories( rFactories )
133         , nIt( 0 )
134         {}
135 
136     // XEnumeration
137     sal_Bool SAL_CALL hasMoreElements() override;
138     Any SAL_CALL nextElement() override;
139 private:
140     Mutex                               aMutex;
141     Sequence< Reference<XInterface > >  aFactories;
142     sal_Int32                           nIt;
143 };
144 
145 // XEnumeration
hasMoreElements()146 sal_Bool ServiceEnumeration_Impl::hasMoreElements()
147 {
148     MutexGuard aGuard( aMutex );
149     return nIt != aFactories.getLength();
150 }
151 
152 // XEnumeration
nextElement()153 Any ServiceEnumeration_Impl::nextElement()
154 {
155     MutexGuard aGuard( aMutex );
156     if( nIt == aFactories.getLength() )
157         throw NoSuchElementException("no more elements");
158 
159     return Any( &aFactories.getConstArray()[nIt++], cppu::UnoType<XInterface>::get());
160 }
161 
162 
163 class PropertySetInfo_Impl : public WeakImplHelper< beans::XPropertySetInfo >
164 {
165     Sequence< beans::Property > m_properties;
166 
167 public:
PropertySetInfo_Impl(Sequence<beans::Property> const & properties)168     explicit PropertySetInfo_Impl( Sequence< beans::Property > const & properties )
169         : m_properties( properties )
170         {}
171 
172     // XPropertySetInfo impl
173     virtual Sequence< beans::Property > SAL_CALL getProperties() override;
174     virtual beans::Property SAL_CALL getPropertyByName( OUString const & name ) override;
175     virtual sal_Bool SAL_CALL hasPropertyByName( OUString const & name ) override;
176 };
177 
getProperties()178 Sequence< beans::Property > PropertySetInfo_Impl::getProperties()
179 {
180     return m_properties;
181 }
182 
getPropertyByName(OUString const & name)183 beans::Property PropertySetInfo_Impl::getPropertyByName( OUString const & name )
184 {
185     beans::Property const * p = m_properties.getConstArray();
186     for ( sal_Int32 nPos = m_properties.getLength(); nPos--; )
187     {
188         if (p[ nPos ].Name == name)
189             return p[ nPos ];
190     }
191     throw beans::UnknownPropertyException(
192         "unknown property: " + name );
193 }
194 
hasPropertyByName(OUString const & name)195 sal_Bool PropertySetInfo_Impl::hasPropertyByName( OUString const & name )
196 {
197     return std::any_of(m_properties.begin(), m_properties.end(),
198         [&name](const beans::Property& rProp) { return rProp.Name == name; });
199 }
200 
201 
202 /*****************************************************************************
203     Enumeration by implementation
204 *****************************************************************************/
205 class ImplementationEnumeration_Impl : public WeakImplHelper< XEnumeration >
206 {
207 public:
ImplementationEnumeration_Impl(const HashSet_Ref & rImplementationMap)208     explicit ImplementationEnumeration_Impl( const HashSet_Ref & rImplementationMap )
209         : aImplementationMap( rImplementationMap )
210         , aIt( aImplementationMap.begin() )
211         {}
212 
213     // XEnumeration
214     virtual sal_Bool SAL_CALL hasMoreElements() override;
215     virtual Any SAL_CALL nextElement() override;
216 
217 private:
218     Mutex                           aMutex;
219     HashSet_Ref                     aImplementationMap;
220     HashSet_Ref::iterator           aIt;
221 };
222 
223 // XEnumeration
hasMoreElements()224 sal_Bool ImplementationEnumeration_Impl::hasMoreElements()
225 {
226     MutexGuard aGuard( aMutex );
227     return aIt != aImplementationMap.end();
228 }
229 
230 // XEnumeration
nextElement()231 Any ImplementationEnumeration_Impl::nextElement()
232 {
233     MutexGuard aGuard( aMutex );
234     if( aIt == aImplementationMap.end() )
235         throw NoSuchElementException("no more elements");
236 
237     Any ret( &(*aIt), cppu::UnoType<XInterface>::get());
238     ++aIt;
239     return ret;
240 }
241 
242 /*****************************************************************************
243     Hash tables
244 *****************************************************************************/
245 typedef std::unordered_set
246 <
247     OUString
248 > HashSet_OWString;
249 
250 typedef std::unordered_multimap
251 <
252     OUString,
253     Reference<XInterface >
254 > HashMultimap_OWString_Interface;
255 
256 typedef std::unordered_map
257 <
258     OUString,
259     Reference<XInterface >
260 > HashMap_OWString_Interface;
261 
262 /*****************************************************************************
263     class OServiceManager_Listener
264 *****************************************************************************/
265 class OServiceManager_Listener : public WeakImplHelper< XEventListener >
266 {
267 private:
268     WeakReference<XSet > xSMgr;
269 
270 public:
OServiceManager_Listener(const Reference<XSet> & rSMgr)271     explicit OServiceManager_Listener( const Reference<XSet > & rSMgr )
272         : xSMgr( rSMgr )
273         {}
274 
275     // XEventListener
276     virtual void SAL_CALL disposing(const EventObject & rEvt ) override;
277 };
278 
disposing(const EventObject & rEvt)279 void OServiceManager_Listener::disposing(const EventObject & rEvt )
280 {
281     Reference<XSet > x( xSMgr );
282     if( !x.is() )
283         return;
284 
285     try
286     {
287         x->remove( Any( &rEvt.Source, cppu::UnoType<XInterface>::get()) );
288     }
289     catch( const IllegalArgumentException & )
290     {
291         TOOLS_WARN_EXCEPTION( "stoc", "" );
292     }
293     catch( const NoSuchElementException & )
294     {
295         TOOLS_WARN_EXCEPTION( "stoc", "" );
296     }
297 }
298 
299 
300 /*****************************************************************************
301     class OServiceManager
302 *****************************************************************************/
303 struct OServiceManagerMutex
304 {
305     Mutex m_mutex;
306 };
307 
308 typedef WeakComponentImplHelper<
309     lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo,
310     lang::XInitialization,
311     container::XSet, container::XContentEnumerationAccess,
312     beans::XPropertySet > t_OServiceManager_impl;
313 
314 class OServiceManager
315     : public OServiceManagerMutex
316     , public t_OServiceManager_impl
317 {
318 public:
319     explicit OServiceManager( Reference< XComponentContext > const & xContext );
320 
321     // XInitialization
322     void SAL_CALL initialize( Sequence< Any > const & args ) override;
323 
324     // XServiceInfo
325     virtual OUString SAL_CALL getImplementationName() override;
326     virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
327     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
328 
329     // XMultiComponentFactory
330     virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
331         OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) override;
332     virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
333         OUString const & rServiceSpecifier,
334         Sequence< Any > const & rArguments,
335         Reference< XComponentContext > const & xContext ) override;
336 //      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
337 //          throw (RuntimeException);
338 
339     // XMultiServiceFactory
340     virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
341     virtual Reference<XInterface > SAL_CALL createInstance(const OUString &) override;
342     virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString &, const Sequence<Any >& Arguments) override;
343 
344     // The same as the getAvailableServiceNames, but only unique names
345     Sequence< OUString > getUniqueAvailableServiceNames(
346         HashSet_OWString & aNameSet );
347 
348     // XElementAccess
349     virtual Type SAL_CALL getElementType() override;
350     virtual sal_Bool SAL_CALL hasElements() override;
351 
352     // XEnumerationAccess
353     virtual Reference<XEnumeration > SAL_CALL createEnumeration() override;
354 
355     // XSet
356     virtual sal_Bool SAL_CALL has( const Any & Element ) override;
357     virtual void SAL_CALL insert( const Any & Element ) override;
358     virtual void SAL_CALL remove( const Any & Element ) override;
359 
360     // XContentEnumerationAccess
361     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
362     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override;
363 
364     // XComponent
365     virtual void SAL_CALL dispose() override;
366 
367     // XPropertySet
368     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
369     void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) override;
370     Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
371     void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override;
372     void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override;
373     void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override;
374     void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override;
375 
376 protected:
377     bool is_disposed() const;
378     void check_undisposed() const;
379     virtual void SAL_CALL disposing() override;
380 
381     bool haveFactoryWithThisImplementation(const OUString& aImplName);
382 
383     virtual Sequence< Reference< XInterface > > queryServiceFactories(
384         const OUString& aServiceName, Reference< XComponentContext > const & xContext );
385 
386     Reference< XComponentContext >  m_xContext;
387 
388     Reference< beans::XPropertySetInfo > m_xPropertyInfo;
389 
390     // factories which have been loaded and not inserted( by XSet::insert)
391     // are remembered by this set.
392     HashSet_Ref m_SetLoadedFactories;
393 private:
394 
395     Reference<XEventListener >      getFactoryListener();
396 
397 
398     HashMultimap_OWString_Interface m_ServiceMap;
399     HashSet_Ref                     m_ImplementationMap;
400     HashMap_OWString_Interface      m_ImplementationNameMap;
401     Reference<XEventListener >      xFactoryListener;
402     bool                            m_bInDisposing;
403 };
404 
405 
is_disposed() const406 bool OServiceManager::is_disposed() const
407 {
408     // ought to be guarded by m_mutex:
409     return (m_bInDisposing || rBHelper.bDisposed);
410 }
411 
412 
check_undisposed() const413 void OServiceManager::check_undisposed() const
414 {
415     if (is_disposed())
416     {
417         throw lang::DisposedException(
418             "service manager instance has already been disposed!",
419             static_cast<OWeakObject *>(const_cast<OServiceManager *>(this)) );
420     }
421 }
422 
423 
424 typedef WeakComponentImplHelper<
425     lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo,
426     container::XSet, container::XContentEnumerationAccess,
427     beans::XPropertySet > t_OServiceManagerWrapper_impl;
428 
429 class OServiceManagerWrapper : public OServiceManagerMutex, public t_OServiceManagerWrapper_impl
430 {
431     Reference< XComponentContext > m_xContext;
432     Reference< XMultiComponentFactory > m_root;
getRoot() const433     Reference< XMultiComponentFactory > const & getRoot() const
434     {
435         if (! m_root.is())
436         {
437             throw lang::DisposedException(
438                 "service manager instance has already been disposed!" );
439         }
440         return m_root;
441     }
442 
443 protected:
444     virtual void SAL_CALL disposing() override;
445 
446 public:
447     explicit OServiceManagerWrapper(
448         Reference< XComponentContext > const & xContext );
449 
450     // XServiceInfo
getImplementationName()451     virtual OUString SAL_CALL getImplementationName() override
452         { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->getImplementationName(); }
supportsService(const OUString & ServiceName)453     virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override
454         { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->supportsService( ServiceName ); }
getSupportedServiceNames()455     virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
456         { return Reference< XServiceInfo >(getRoot(), UNO_QUERY_THROW)->getSupportedServiceNames(); }
457 
458     // XMultiComponentFactory
createInstanceWithContext(OUString const & rServiceSpecifier,Reference<XComponentContext> const & xContext)459     virtual Reference< XInterface > SAL_CALL createInstanceWithContext(
460         OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) override
461         { return getRoot()->createInstanceWithContext( rServiceSpecifier, xContext ); }
createInstanceWithArgumentsAndContext(OUString const & rServiceSpecifier,Sequence<Any> const & rArguments,Reference<XComponentContext> const & xContext)462     virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext(
463         OUString const & rServiceSpecifier,
464         Sequence< Any > const & rArguments,
465         Reference< XComponentContext > const & xContext ) override
466         { return getRoot()->createInstanceWithArgumentsAndContext( rServiceSpecifier, rArguments, xContext ); }
467 //      virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
468 //          throw (RuntimeException);
469 
470     // XMultiServiceFactory
getAvailableServiceNames()471     virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() override
472         { return getRoot()->getAvailableServiceNames(); }
createInstance(const OUString & name)473     virtual Reference<XInterface > SAL_CALL createInstance(const OUString & name) override
474         { return getRoot()->createInstanceWithContext( name, m_xContext ); }
createInstanceWithArguments(const OUString & name,const Sequence<Any> & Arguments)475     virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString & name, const Sequence<Any >& Arguments) override
476         { return getRoot()->createInstanceWithArgumentsAndContext( name, Arguments, m_xContext ); }
477 
478     // XElementAccess
getElementType()479     virtual Type SAL_CALL getElementType() override
480         { return Reference< XElementAccess >(getRoot(), UNO_QUERY_THROW)->getElementType(); }
hasElements()481     virtual sal_Bool SAL_CALL hasElements() override
482         { return Reference< XElementAccess >(getRoot(), UNO_QUERY_THROW)->hasElements(); }
483 
484     // XEnumerationAccess
createEnumeration()485     virtual Reference<XEnumeration > SAL_CALL createEnumeration() override
486         { return Reference< XEnumerationAccess >(getRoot(), UNO_QUERY_THROW)->createEnumeration(); }
487 
488     // XSet
has(const Any & Element)489     virtual sal_Bool SAL_CALL has( const Any & Element ) override
490         { return Reference< XSet >(getRoot(), UNO_QUERY_THROW)->has( Element ); }
insert(const Any & Element)491     virtual void SAL_CALL insert( const Any & Element ) override
492         { Reference< XSet >(getRoot(), UNO_QUERY_THROW)->insert( Element ); }
remove(const Any & Element)493     virtual void SAL_CALL remove( const Any & Element ) override
494         { Reference< XSet >(getRoot(), UNO_QUERY_THROW)->remove( Element ); }
495 
496     // XContentEnumerationAccess
497     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
createContentEnumeration(const OUString & aServiceName)498     virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override
499         { return Reference< XContentEnumerationAccess >(getRoot(), UNO_QUERY_THROW)->createContentEnumeration( aServiceName ); }
500 
501     // XPropertySet
getPropertySetInfo()502     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override
503         { return Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->getPropertySetInfo(); }
504 
505     void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) override;
506     Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
507 
addPropertyChangeListener(const OUString & PropertyName,const Reference<XPropertyChangeListener> & aListener)508     void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override
509         { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->addPropertyChangeListener( PropertyName, aListener ); }
removePropertyChangeListener(const OUString & PropertyName,const Reference<XPropertyChangeListener> & aListener)510     void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) override
511         { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->removePropertyChangeListener( PropertyName, aListener ); }
addVetoableChangeListener(const OUString & PropertyName,const Reference<XVetoableChangeListener> & aListener)512     void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override
513         { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->addVetoableChangeListener( PropertyName, aListener ); }
removeVetoableChangeListener(const OUString & PropertyName,const Reference<XVetoableChangeListener> & aListener)514     void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) override
515         { Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->removeVetoableChangeListener( PropertyName, aListener ); }
516 };
517 
setPropertyValue(const OUString & PropertyName,const Any & aValue)518 void SAL_CALL OServiceManagerWrapper::setPropertyValue(
519     const OUString& PropertyName, const Any& aValue )
520 {
521     if ( PropertyName == "DefaultContext" )
522     {
523         Reference< XComponentContext > xContext;
524         if (!(aValue >>= xContext))
525         {
526             throw IllegalArgumentException(
527                 "no XComponentContext given!",
528                 static_cast<OWeakObject *>(this), 1 );
529         }
530 
531         MutexGuard aGuard( m_mutex );
532         m_xContext = xContext;
533 
534     }
535     else
536     {
537         Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->setPropertyValue( PropertyName, aValue );
538     }
539 }
540 
getPropertyValue(const OUString & PropertyName)541 Any SAL_CALL OServiceManagerWrapper::getPropertyValue(
542     const OUString& PropertyName )
543 {
544     if ( PropertyName == "DefaultContext" )
545     {
546         MutexGuard aGuard( m_mutex );
547         if( m_xContext.is() )
548             return makeAny( m_xContext );
549         else
550             return Any();
551     }
552     else
553     {
554         return Reference< XPropertySet >(getRoot(), UNO_QUERY_THROW)->getPropertyValue( PropertyName );
555     }
556 }
557 
disposing()558 void OServiceManagerWrapper::disposing()
559 {
560     m_xContext.clear();
561 
562 // no m_root->dispose(), because every context disposes its service manager...
563     m_root.clear();
564 }
565 
OServiceManagerWrapper(Reference<XComponentContext> const & xContext)566 OServiceManagerWrapper::OServiceManagerWrapper(
567     Reference< XComponentContext > const & xContext )
568     : t_OServiceManagerWrapper_impl( m_mutex )
569     , m_xContext( xContext )
570     , m_root( xContext->getServiceManager() )
571 {
572     if (! m_root.is())
573     {
574         throw RuntimeException(
575             "no service manager to wrap" );
576     }
577 }
578 
579 
580 /**
581  * Create a ServiceManager
582  */
OServiceManager(Reference<XComponentContext> const & xContext)583 OServiceManager::OServiceManager( Reference< XComponentContext > const & xContext )
584     : t_OServiceManager_impl( m_mutex )
585     , m_xContext( xContext )
586     , m_bInDisposing( false )
587 {}
588 
589 // XComponent
dispose()590 void OServiceManager::dispose()
591 {
592     if (rBHelper.bDisposed || rBHelper.bInDispose)
593         return;
594     t_OServiceManager_impl::dispose();
595 }
596 
disposing()597 void OServiceManager::disposing()
598 {
599     // dispose all factories
600     HashSet_Ref aImpls;
601     {
602         MutexGuard aGuard( m_mutex );
603         m_bInDisposing = true;
604         aImpls = m_ImplementationMap;
605     }
606     for( const auto& rxImpl : aImpls )
607     {
608         try
609         {
610             Reference<XComponent > xComp( Reference<XComponent >::query( rxImpl ) );
611             if( xComp.is() )
612                 xComp->dispose();
613         }
614         catch (const RuntimeException &)
615         {
616             TOOLS_INFO_EXCEPTION("stoc", "RuntimeException occurred upon disposing factory:");
617         }
618     }
619 
620     // dispose
621     HashSet_Ref aImplMap;
622     {
623         MutexGuard aGuard( m_mutex );
624         // erase all members
625         m_ServiceMap = HashMultimap_OWString_Interface();
626         aImplMap = m_ImplementationMap;
627         m_ImplementationMap = HashSet_Ref();
628         m_ImplementationNameMap = HashMap_OWString_Interface();
629         m_SetLoadedFactories= HashSet_Ref();
630     }
631 
632     m_xContext.clear();
633 
634     // not only the Event should hold the object
635     OSL_ASSERT( m_refCount != 1 );
636 }
637 
638 // XPropertySet
getPropertySetInfo()639 Reference<XPropertySetInfo > OServiceManager::getPropertySetInfo()
640 {
641     check_undisposed();
642     if (! m_xPropertyInfo.is())
643     {
644         Sequence< beans::Property > seq( 1 );
645         seq[ 0 ] = beans::Property(
646             "DefaultContext", -1, cppu::UnoType<decltype(m_xContext)>::get(), 0 );
647         Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
648 
649         MutexGuard aGuard( m_mutex );
650         if (! m_xPropertyInfo.is())
651         {
652             m_xPropertyInfo = xInfo;
653         }
654     }
655     return m_xPropertyInfo;
656 }
657 
setPropertyValue(const OUString & PropertyName,const Any & aValue)658 void OServiceManager::setPropertyValue(
659     const OUString& PropertyName, const Any& aValue )
660 {
661     check_undisposed();
662     if ( PropertyName != "DefaultContext" )
663     {
664         throw UnknownPropertyException(
665             "unknown property " + PropertyName,
666             static_cast<OWeakObject *>(this) );
667     }
668 
669     Reference< XComponentContext > xContext;
670     if (!(aValue >>= xContext))
671     {
672         throw IllegalArgumentException(
673             "no XComponentContext given!",
674             static_cast<OWeakObject *>(this), 1 );
675     }
676 
677     MutexGuard aGuard( m_mutex );
678     m_xContext = xContext;
679 }
680 
getPropertyValue(const OUString & PropertyName)681 Any OServiceManager::getPropertyValue(const OUString& PropertyName)
682 {
683     check_undisposed();
684     if ( PropertyName == "DefaultContext" )
685     {
686         MutexGuard aGuard( m_mutex );
687         if( m_xContext.is() )
688             return makeAny( m_xContext );
689         else
690             return Any();
691     }
692     else
693     {
694         UnknownPropertyException except;
695         except.Message =  "ServiceManager : unknown property " + PropertyName;
696         throw except;
697     }
698 }
699 
addPropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)700 void OServiceManager::addPropertyChangeListener(
701     const OUString&, const Reference<XPropertyChangeListener >&)
702 {
703     check_undisposed();
704     throw UnknownPropertyException("unsupported");
705 }
706 
removePropertyChangeListener(const OUString &,const Reference<XPropertyChangeListener> &)707 void OServiceManager::removePropertyChangeListener(
708     const OUString&, const Reference<XPropertyChangeListener >&)
709 {
710     check_undisposed();
711     throw UnknownPropertyException("unsupported");
712 }
713 
addVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)714 void OServiceManager::addVetoableChangeListener(
715     const OUString&, const Reference<XVetoableChangeListener >&)
716 {
717     check_undisposed();
718     throw UnknownPropertyException("unsupported");
719 }
720 
removeVetoableChangeListener(const OUString &,const Reference<XVetoableChangeListener> &)721 void OServiceManager::removeVetoableChangeListener(
722     const OUString&, const Reference<XVetoableChangeListener >&)
723 {
724     check_undisposed();
725     throw UnknownPropertyException("unsupported");
726 }
727 
728 // OServiceManager
getFactoryListener()729 Reference<XEventListener > OServiceManager::getFactoryListener()
730 {
731     check_undisposed();
732     MutexGuard aGuard( m_mutex );
733     if( !xFactoryListener.is() )
734         xFactoryListener = new OServiceManager_Listener( this );
735     return xFactoryListener;
736 }
737 
738 // XMultiServiceFactory, XContentEnumeration
getUniqueAvailableServiceNames(HashSet_OWString & aNameSet)739 Sequence< OUString > OServiceManager::getUniqueAvailableServiceNames(
740     HashSet_OWString & aNameSet )
741 {
742     check_undisposed();
743     MutexGuard aGuard( m_mutex );
744     for( const auto& rEntry : m_ServiceMap )
745         aNameSet.insert( rEntry.first );
746 
747     /* do not return the implementation names
748     HashMap_OWString_Interface      m_ImplementationNameMap;
749     HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin();
750     while( aIt != m_ImplementationNameMap.end() )
751         aNameSet.insert( (*aIt++).first );
752     */
753 
754     return comphelper::containerToSequence(aNameSet);
755 }
756 
757 // XMultiComponentFactory
createInstanceWithContext(OUString const & rServiceSpecifier,Reference<XComponentContext> const & xContext)758 Reference< XInterface > OServiceManager::createInstanceWithContext(
759     OUString const & rServiceSpecifier,
760     Reference< XComponentContext > const & xContext )
761 {
762     check_undisposed();
763 #if OSL_DEBUG_LEVEL > 0
764     Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
765     OSL_ASSERT( xProps.is() );
766     if (xProps.is())
767     {
768         Reference< XComponentContext > xDefContext;
769         xProps->getPropertyValue( "DefaultContext" ) >>= xDefContext;
770         OSL_ENSURE(
771             xContext == xDefContext,
772             "### default context of service manager singleton differs from context holding it!" );
773     }
774 #endif
775 
776     const Sequence< Reference< XInterface > > factories(
777         queryServiceFactories( rServiceSpecifier, xContext ) );
778     for ( Reference< XInterface > const & xFactory : factories )
779     {
780         try
781         {
782             if (xFactory.is())
783             {
784                 Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
785                 if (xFac.is())
786                 {
787                     return xFac->createInstanceWithContext( xContext );
788                 }
789                 else
790                 {
791                     Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
792                     if (xFac2.is())
793                     {
794                         SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier << "!!!");
795                         return xFac2->createInstance();
796                     }
797                 }
798             }
799         }
800         catch (const lang::DisposedException &)
801         {
802             TOOLS_INFO_EXCEPTION("stoc", "");
803         }
804     }
805 
806     return Reference< XInterface >();
807 }
808 // XMultiComponentFactory
createInstanceWithArgumentsAndContext(OUString const & rServiceSpecifier,Sequence<Any> const & rArguments,Reference<XComponentContext> const & xContext)809 Reference< XInterface > OServiceManager::createInstanceWithArgumentsAndContext(
810     OUString const & rServiceSpecifier,
811     Sequence< Any > const & rArguments,
812     Reference< XComponentContext > const & xContext )
813 {
814     check_undisposed();
815 #if OSL_DEBUG_LEVEL > 0
816     Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY );
817     OSL_ASSERT( xProps.is() );
818     if (xProps.is())
819     {
820         Reference< XComponentContext > xDefContext;
821         xProps->getPropertyValue( "DefaultContext" ) >>= xDefContext;
822         OSL_ENSURE(
823             xContext == xDefContext,
824             "### default context of service manager singleton differs from context holding it!" );
825     }
826 #endif
827 
828     const Sequence< Reference< XInterface > > factories(
829         queryServiceFactories( rServiceSpecifier, xContext ) );
830     for ( Reference< XInterface > const & xFactory : factories )
831     {
832         try
833         {
834             if (xFactory.is())
835             {
836                 Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY );
837                 if (xFac.is())
838                 {
839                     return xFac->createInstanceWithArgumentsAndContext( rArguments, xContext );
840                 }
841                 else
842                 {
843                     Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY );
844                     if (xFac2.is())
845                     {
846                         SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier << "!!!");
847                         return xFac2->createInstanceWithArguments( rArguments );
848                     }
849                 }
850             }
851         }
852         catch (const lang::DisposedException &)
853         {
854             TOOLS_INFO_EXCEPTION("stoc", "DisposedException occurred:");
855         }
856     }
857 
858     return Reference< XInterface >();
859 }
860 
861 // XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration
getAvailableServiceNames()862 Sequence< OUString > OServiceManager::getAvailableServiceNames()
863 {
864     check_undisposed();
865     // all names
866     HashSet_OWString aNameSet;
867     return getUniqueAvailableServiceNames( aNameSet );
868 }
869 
870 // XMultipleServiceFactory
createInstance(const OUString & rServiceSpecifier)871 Reference<XInterface > OServiceManager::createInstance(
872     const OUString& rServiceSpecifier )
873 {
874     return createInstanceWithContext(
875         rServiceSpecifier, m_xContext );
876 }
877 
878 // XMultipleServiceFactory
createInstanceWithArguments(const OUString & rServiceSpecifier,const Sequence<Any> & rArguments)879 Reference<XInterface > OServiceManager::createInstanceWithArguments(
880     const OUString& rServiceSpecifier,
881     const Sequence<Any >& rArguments )
882 {
883     return createInstanceWithArgumentsAndContext(
884         rServiceSpecifier, rArguments, m_xContext );
885 }
886 
887 // XInitialization
initialize(Sequence<Any> const &)888 void OServiceManager::initialize( Sequence< Any > const & )
889 {
890     check_undisposed();
891     OSL_FAIL( "not impl!" );
892 }
893 
894 // XServiceInfo
getImplementationName()895 OUString OServiceManager::getImplementationName()
896 {
897     return "com.sun.star.comp.stoc.OServiceManager";
898 }
899 
900 // XServiceInfo
supportsService(const OUString & ServiceName)901 sal_Bool OServiceManager::supportsService(const OUString& ServiceName)
902 {
903     return cppu::supportsService(this, ServiceName);
904 }
905 
906 // XServiceInfo
getSupportedServiceNames()907 Sequence< OUString > OServiceManager::getSupportedServiceNames()
908 {
909     return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.ServiceManager" };
910 }
911 
912 
queryServiceFactories(const OUString & aServiceName,Reference<XComponentContext> const &)913 Sequence< Reference< XInterface > > OServiceManager::queryServiceFactories(
914     const OUString& aServiceName, Reference< XComponentContext > const & )
915 {
916     Sequence< Reference< XInterface > > ret;
917 
918     MutexGuard aGuard( m_mutex );
919     ::std::pair<
920           HashMultimap_OWString_Interface::iterator,
921           HashMultimap_OWString_Interface::iterator> p(
922               m_ServiceMap.equal_range( aServiceName ) );
923 
924     if (p.first == p.second) // no factories
925     {
926         // no service found, look for an implementation
927         HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.find( aServiceName );
928         if( aIt != m_ImplementationNameMap.end() )
929         {
930             Reference< XInterface > const & x = aIt->second;
931             // an implementation found
932             ret = Sequence< Reference< XInterface > >( &x, 1 );
933         }
934     }
935     else
936     {
937         ::std::vector< Reference< XInterface > > vec;
938         vec.reserve( 4 );
939         while (p.first != p.second)
940         {
941             vec.push_back( p.first->second );
942             ++p.first;
943         }
944         ret = Sequence< Reference< XInterface > >( vec.data(), vec.size() );
945     }
946 
947     return ret;
948 }
949 
950 // XContentEnumerationAccess
createContentEnumeration(const OUString & aServiceName)951 Reference<XEnumeration > OServiceManager::createContentEnumeration(
952     const OUString& aServiceName )
953 {
954     check_undisposed();
955     Sequence< Reference< XInterface > > factories(
956         OServiceManager::queryServiceFactories( aServiceName, m_xContext ) );
957     if (factories.hasElements())
958         return new ServiceEnumeration_Impl( factories );
959     else
960         return Reference< XEnumeration >();
961 }
962 
963 // XEnumeration
createEnumeration()964 Reference<XEnumeration > OServiceManager::createEnumeration()
965 {
966     check_undisposed();
967     MutexGuard aGuard( m_mutex );
968     return new ImplementationEnumeration_Impl( m_ImplementationMap );
969 }
970 
971 // XElementAccess
getElementType()972 Type OServiceManager::getElementType()
973 {
974     check_undisposed();
975     return cppu::UnoType<XInterface>::get();
976 }
977 
978 // XElementAccess
hasElements()979 sal_Bool OServiceManager::hasElements()
980 {
981     check_undisposed();
982     MutexGuard aGuard( m_mutex );
983     return !m_ImplementationMap.empty();
984 }
985 
986 // XSet
has(const Any & Element)987 sal_Bool OServiceManager::has( const Any & Element )
988 {
989     check_undisposed();
990     if( Element.getValueTypeClass() == TypeClass_INTERFACE )
991     {
992         Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
993         MutexGuard aGuard( m_mutex );
994         return m_ImplementationMap.find( xEle ) !=
995             m_ImplementationMap.end();
996     }
997     else if (auto implName = o3tl::tryAccess<OUString>(Element))
998     {
999         MutexGuard aGuard( m_mutex );
1000         return m_ImplementationNameMap.find( *implName ) !=
1001             m_ImplementationNameMap.end();
1002     }
1003     return false;
1004 }
1005 
1006 // XSet
insert(const Any & Element)1007 void OServiceManager::insert( const Any & Element )
1008 {
1009     check_undisposed();
1010     if( Element.getValueTypeClass() != TypeClass_INTERFACE )
1011     {
1012         throw IllegalArgumentException(
1013             "exception interface, got " + Element.getValueType().getTypeName(),
1014             Reference< XInterface >(), 0 );
1015     }
1016     Reference<XInterface > xEle( Element, UNO_QUERY_THROW );
1017 
1018     {
1019     MutexGuard aGuard( m_mutex );
1020     HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1021     if( aIt != m_ImplementationMap.end() )
1022     {
1023         throw ElementExistException( "element already exists!" );
1024     }
1025 
1026     // put into the implementation hashmap
1027     m_ImplementationMap.insert( xEle );
1028 
1029     // put into the implementation name hashmap
1030     Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1031     if( xInfo.is() )
1032     {
1033         OUString aImplName = xInfo->getImplementationName();
1034         if( !aImplName.isEmpty() )
1035             m_ImplementationNameMap[ aImplName ] = xEle;
1036 
1037         //put into the service map
1038         const Sequence< OUString > aServiceNames = xInfo->getSupportedServiceNames();
1039         for( const OUString& rServiceName : aServiceNames )
1040         {
1041             m_ServiceMap.emplace(
1042                 rServiceName, *o3tl::doAccess<Reference<XInterface>>(Element) );
1043         }
1044     }
1045     }
1046     // add the disposing listener to the factory
1047     Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1048     if( xComp.is() )
1049         xComp->addEventListener( getFactoryListener() );
1050 }
1051 
1052 // helper function
haveFactoryWithThisImplementation(const OUString & aImplName)1053 bool OServiceManager::haveFactoryWithThisImplementation(const OUString& aImplName)
1054 {
1055     return ( m_ImplementationNameMap.find(aImplName) != m_ImplementationNameMap.end());
1056 }
1057 
1058 // XSet
remove(const Any & Element)1059 void OServiceManager::remove( const Any & Element )
1060 {
1061     if (is_disposed())
1062         return;
1063 
1064     Reference<XInterface > xEle;
1065     if (Element.getValueTypeClass() == TypeClass_INTERFACE)
1066     {
1067         xEle.set( Element, UNO_QUERY_THROW );
1068     }
1069     else if (auto implName = o3tl::tryAccess<OUString>(Element))
1070     {
1071         MutexGuard aGuard( m_mutex );
1072         HashMap_OWString_Interface::const_iterator const iFind(
1073             m_ImplementationNameMap.find( *implName ) );
1074         if (iFind == m_ImplementationNameMap.end())
1075         {
1076             throw NoSuchElementException(
1077                 "element is not in: " + *implName,
1078                 static_cast< OWeakObject * >(this) );
1079         }
1080         xEle = iFind->second;
1081     }
1082     else
1083     {
1084         throw IllegalArgumentException(
1085             "expected interface or string, got " + Element.getValueType().getTypeName(),
1086             Reference< XInterface >(), 0 );
1087     }
1088 
1089     // remove the disposing listener from the factory
1090     Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) );
1091     if( xComp.is() )
1092         xComp->removeEventListener( getFactoryListener() );
1093 
1094     MutexGuard aGuard( m_mutex );
1095     HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle );
1096     if( aIt == m_ImplementationMap.end() )
1097     {
1098         throw NoSuchElementException(
1099             "element not found",
1100             static_cast< OWeakObject * >(this) );
1101     }
1102     //First remove all factories which have been loaded by ORegistryServiceManager.
1103     m_SetLoadedFactories.erase( *aIt);
1104     //Remove from the implementation map. It contains all factories of m_SetLoadedFactories
1105     //which have been added directly through XSet, that is not via ORegistryServiceManager
1106     m_ImplementationMap.erase( aIt );
1107 
1108     // remove from the implementation name hashmap
1109     Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) );
1110     if( xInfo.is() )
1111     {
1112         OUString aImplName = xInfo->getImplementationName();
1113         if( !aImplName.isEmpty() )
1114             m_ImplementationNameMap.erase( aImplName );
1115     }
1116 
1117     //remove from the service map
1118     Reference<XServiceInfo > xSF( Reference<XServiceInfo >::query( xEle ) );
1119     if( !xSF.is() )
1120         return;
1121 
1122     const Sequence< OUString > aServiceNames = xSF->getSupportedServiceNames();
1123     for( const OUString& rServiceName : aServiceNames )
1124     {
1125         pair<HashMultimap_OWString_Interface::iterator, HashMultimap_OWString_Interface::iterator> p =
1126             m_ServiceMap.equal_range( rServiceName );
1127 
1128         while( p.first != p.second )
1129         {
1130             if( xEle == (*p.first).second )
1131             {
1132                 m_ServiceMap.erase( p.first );
1133                 break;
1134             }
1135             ++p.first;
1136         }
1137     }
1138 }
1139 
1140 /*****************************************************************************
1141     class ORegistryServiceManager
1142 *****************************************************************************/
1143 class ORegistryServiceManager : public OServiceManager
1144 {
1145 public:
1146     explicit ORegistryServiceManager( Reference< XComponentContext > const & xContext );
1147 
1148     // XInitialization
1149     void SAL_CALL initialize(const Sequence< Any >& Arguments) override;
1150 
1151     // XServiceInfo
getImplementationName()1152     OUString SAL_CALL getImplementationName() override
1153         { return "com.sun.star.comp.stoc.ORegistryServiceManager"; }
1154 
1155     Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
1156 
1157     // XMultiServiceFactory
1158     Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
1159 
1160     // XContentEnumerationAccess
1161     //Sequence< OUString >          getAvailableServiceNames() throw( (Exception) );
1162     Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) override;
1163 
1164     // XComponent
1165     void SAL_CALL dispose() override;
1166 
1167     // OServiceManager
1168     Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
1169     Any SAL_CALL getPropertyValue(const OUString& PropertyName) override;
1170 
1171 protected:
1172     //OServiceManager
1173     Sequence< Reference< XInterface > > queryServiceFactories(
1174         const OUString& aServiceName, Reference< XComponentContext > const & xContext ) override;
1175 private:
1176     Reference<XRegistryKey >        getRootKey();
1177     Reference<XInterface > loadWithImplementationName(
1178         const OUString & rImplName, Reference< XComponentContext > const & xContext );
1179     Sequence<OUString>          getFromServiceName(std::u16string_view serviceName) const;
1180     Reference<XInterface > loadWithServiceName(
1181         std::u16string_view rImplName, Reference< XComponentContext > const & xContext );
1182     void                        fillAllNamesFromRegistry( HashSet_OWString & );
1183 
1184     bool                    m_searchedRegistry;
1185     Reference<XSimpleRegistry > m_xRegistry;    // readonly property Registry
1186     Reference<XRegistryKey >    m_xRootKey;
1187 
1188 #if OSL_DEBUG_LEVEL > 0
1189     bool m_init;
1190 #endif
1191 };
1192 
1193 /**
1194  * Create a ServiceManager
1195  */
ORegistryServiceManager(Reference<XComponentContext> const & xContext)1196 ORegistryServiceManager::ORegistryServiceManager( Reference< XComponentContext > const & xContext )
1197     : OServiceManager( xContext )
1198     , m_searchedRegistry(false)
1199 #if OSL_DEBUG_LEVEL > 0
1200     , m_init( false )
1201 #endif
1202 {
1203 }
1204 
1205 // XComponent
dispose()1206 void ORegistryServiceManager::dispose()
1207 {
1208     if (rBHelper.bDisposed || rBHelper.bInDispose)
1209         return;
1210     OServiceManager::dispose();
1211     // dispose
1212     MutexGuard aGuard( m_mutex );
1213     // erase all members
1214     m_xRegistry.clear();
1215     m_xRootKey.clear();
1216 }
1217 
1218 /**
1219  * Return the root key of the registry. The Default registry service is ordered
1220  * if no registry is set.
1221  */
1222 //Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider();
1223 
getRootKey()1224 Reference<XRegistryKey > ORegistryServiceManager::getRootKey()
1225 {
1226     if( !m_xRootKey.is() )
1227     {
1228         MutexGuard aGuard( m_mutex );
1229         //  DefaultRegistry suchen !!!!
1230         if( !m_xRegistry.is() && !m_searchedRegistry )
1231         {
1232             // NB. we only search this once
1233             m_searchedRegistry = true;
1234 
1235             m_xRegistry.set(
1236                 createInstanceWithContext(
1237                     "com.sun.star.registry.DefaultRegistry",
1238                     m_xContext ),
1239                 UNO_QUERY );
1240         }
1241         if( m_xRegistry.is() && !m_xRootKey.is() )
1242             m_xRootKey = m_xRegistry->getRootKey();
1243     }
1244 
1245     return m_xRootKey;
1246 }
1247 
1248 /**
1249  * Create a service provider from the registry with an implementation name
1250  */
loadWithImplementationName(const OUString & name,Reference<XComponentContext> const & xContext)1251 Reference<XInterface > ORegistryServiceManager::loadWithImplementationName(
1252     const OUString& name, Reference< XComponentContext > const & xContext )
1253 {
1254     Reference<XInterface > ret;
1255 
1256     Reference<XRegistryKey > xRootKey = getRootKey();
1257     if( !xRootKey.is() )
1258         return ret;
1259 
1260     try
1261     {
1262         OUString implementationName = "/IMPLEMENTATIONS/" + name;
1263         Reference<XRegistryKey > xImpKey = m_xRootKey->openKey(implementationName);
1264 
1265         if( xImpKey.is() )
1266         {
1267             Reference< lang::XMultiServiceFactory > xMgr;
1268             if (xContext.is())
1269                 xMgr.set( xContext->getServiceManager(), UNO_QUERY_THROW );
1270             else
1271                 xMgr.set( this );
1272             ret = createSingleRegistryFactory( xMgr, name, xImpKey );
1273             insert( makeAny( ret ) );
1274             // Remember this factory as loaded in contrast to inserted ( XSet::insert)
1275             // factories. Those loaded factories in this set are candidates for being
1276             // released on an unloading notification.
1277             m_SetLoadedFactories.insert( ret);
1278         }
1279     }
1280     catch (InvalidRegistryException &)
1281     {
1282     }
1283 
1284     return ret;
1285 }
1286 
1287 /**
1288  * Return all implementation out of the registry.
1289  */
getFromServiceName(std::u16string_view serviceName) const1290 Sequence<OUString> ORegistryServiceManager::getFromServiceName(
1291     std::u16string_view serviceName ) const
1292 {
1293     OUString buf = OUString::Concat("/SERVICES/") + serviceName;
1294     return retrieveAsciiValueList( m_xRegistry, buf );
1295 }
1296 
1297 /**
1298  * Create a service provider from the registry
1299  */
loadWithServiceName(std::u16string_view serviceName,Reference<XComponentContext> const & xContext)1300 Reference<XInterface > ORegistryServiceManager::loadWithServiceName(
1301     std::u16string_view serviceName, Reference< XComponentContext > const & xContext )
1302 {
1303     const Sequence<OUString> implEntries = getFromServiceName( serviceName );
1304     for (const auto& rEntry : implEntries)
1305     {
1306         Reference< XInterface > x( loadWithImplementationName( rEntry, xContext ) );
1307         if (x.is())
1308             return x;
1309     }
1310 
1311     return Reference<XInterface >();
1312 }
1313 
1314 /**
1315  * Return a sequence of all service names from the registry.
1316  */
fillAllNamesFromRegistry(HashSet_OWString & rSet)1317 void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString & rSet )
1318 {
1319     Reference<XRegistryKey > xRootKey = getRootKey();
1320     if( !xRootKey.is() )
1321         return;
1322 
1323     try
1324     {
1325         Reference<XRegistryKey > xServicesKey = xRootKey->openKey( "SERVICES" );
1326         // root + /Services + /
1327         if( xServicesKey.is() )
1328         {
1329             sal_Int32 nPrefix = xServicesKey->getKeyName().getLength() +1;
1330             Sequence<Reference<XRegistryKey > > aKeys = xServicesKey->openKeys();
1331             std::transform(aKeys.begin(), aKeys.end(), std::inserter(rSet, rSet.end()),
1332                 [nPrefix](const Reference<XRegistryKey>& rKey) -> OUString {
1333                     return rKey->getKeyName().copy( nPrefix ); });
1334         }
1335     }
1336     catch (InvalidRegistryException &)
1337     {
1338     }
1339 }
1340 
1341 // XInitialization
initialize(const Sequence<Any> & Arguments)1342 void ORegistryServiceManager::initialize(const Sequence< Any >& Arguments)
1343 {
1344     check_undisposed();
1345     MutexGuard aGuard( m_mutex );
1346     if (Arguments.hasElements())
1347     {
1348         m_xRootKey.clear();
1349         Arguments[ 0 ] >>= m_xRegistry;
1350     }
1351 #if OSL_DEBUG_LEVEL > 0
1352     // to find all bootstrapping processes to be fixed...
1353     OSL_ENSURE( !m_init, "### second init of service manager instance!" );
1354     m_init = true;
1355 #endif
1356 }
1357 
1358 // XMultiServiceFactory, XContentEnumeration
getAvailableServiceNames()1359 Sequence< OUString > ORegistryServiceManager::getAvailableServiceNames()
1360 {
1361     check_undisposed();
1362     MutexGuard aGuard( m_mutex );
1363     // all names
1364     HashSet_OWString aNameSet;
1365 
1366     // all names from the registry
1367     fillAllNamesFromRegistry( aNameSet );
1368 
1369     return OServiceManager::getUniqueAvailableServiceNames( aNameSet );
1370 }
1371 
1372 // XServiceInfo
getSupportedServiceNames()1373 Sequence< OUString > ORegistryServiceManager::getSupportedServiceNames()
1374 {
1375     return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.RegistryServiceManager" };
1376 }
1377 
1378 
1379 // OServiceManager
queryServiceFactories(const OUString & aServiceName,Reference<XComponentContext> const & xContext)1380 Sequence< Reference< XInterface > > ORegistryServiceManager::queryServiceFactories(
1381     const OUString& aServiceName, Reference< XComponentContext > const & xContext )
1382 {
1383     Sequence< Reference< XInterface > > ret(
1384         OServiceManager::queryServiceFactories( aServiceName, xContext ) );
1385     if (ret.hasElements())
1386     {
1387         return ret;
1388     }
1389     else
1390     {
1391         MutexGuard aGuard( m_mutex );
1392         Reference< XInterface > x( loadWithServiceName( aServiceName, xContext ) );
1393         if (! x.is())
1394             x = loadWithImplementationName( aServiceName, xContext );
1395         return Sequence< Reference< XInterface > >( &x, 1 );
1396     }
1397 }
1398 
1399 // XContentEnumerationAccess
createContentEnumeration(const OUString & aServiceName)1400 Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration(
1401     const OUString& aServiceName )
1402 {
1403     check_undisposed();
1404     MutexGuard aGuard(m_mutex);
1405     // get all implementation names registered under this service name from the registry
1406     const Sequence<OUString> aImpls = getFromServiceName( aServiceName );
1407     // load and insert all factories specified by the registry
1408     for( const OUString& aImplName : aImpls )
1409     {
1410         if ( !haveFactoryWithThisImplementation(aImplName) )
1411         {
1412             loadWithImplementationName( aImplName, m_xContext );
1413         }
1414     }
1415     // call the superclass to enumerate all contents
1416     return OServiceManager::createContentEnumeration( aServiceName );
1417 }
1418 
1419 // OServiceManager
getPropertySetInfo()1420 Reference<XPropertySetInfo > ORegistryServiceManager::getPropertySetInfo()
1421 {
1422     check_undisposed();
1423     if (! m_xPropertyInfo.is())
1424     {
1425         Sequence< beans::Property > seq( 2 );
1426         seq[ 0 ] = beans::Property(
1427             "DefaultContext", -1, cppu::UnoType<decltype(m_xContext)>::get(), 0 );
1428         seq[ 1 ] = beans::Property(
1429             "Registry", -1, cppu::UnoType<decltype(m_xRegistry)>::get(),
1430             beans::PropertyAttribute::READONLY );
1431         Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) );
1432 
1433         MutexGuard aGuard( m_mutex );
1434         if (! m_xPropertyInfo.is())
1435         {
1436             m_xPropertyInfo = xInfo;
1437         }
1438     }
1439     return m_xPropertyInfo;
1440 }
1441 
getPropertyValue(const OUString & PropertyName)1442 Any ORegistryServiceManager::getPropertyValue(const OUString& PropertyName)
1443 {
1444     check_undisposed();
1445     if ( PropertyName == "Registry" )
1446     {
1447         MutexGuard aGuard( m_mutex );
1448         if( m_xRegistry.is() )
1449             return makeAny( m_xRegistry );
1450         else
1451             return Any();
1452     }
1453     return OServiceManager::getPropertyValue( PropertyName );
1454 }
1455 
1456 } // namespace
1457 
1458 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_stoc_OServiceManager_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)1459 com_sun_star_comp_stoc_OServiceManager_get_implementation(
1460     css::uno::XComponentContext *context,
1461     css::uno::Sequence<css::uno::Any> const &)
1462 {
1463     return cppu::acquire(new OServiceManager(context));
1464 }
1465 
1466 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_stoc_ORegistryServiceManager_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)1467 com_sun_star_comp_stoc_ORegistryServiceManager_get_implementation(
1468     css::uno::XComponentContext *context,
1469     css::uno::Sequence<css::uno::Any> const &)
1470 {
1471     return cppu::acquire(new ORegistryServiceManager(context));
1472 }
1473 
1474 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_stoc_OServiceManagerWrapper_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)1475 com_sun_star_comp_stoc_OServiceManagerWrapper_get_implementation(
1476     css::uno::XComponentContext *context,
1477     css::uno::Sequence<css::uno::Any> const &)
1478 {
1479     return cppu::acquire(new OServiceManagerWrapper(context));
1480 }
1481 
1482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1483