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 <rtl/ustrbuf.hxx>
26 #include <sal/log.hxx>
27 #include <tools/diagnose_ex.h>
28
29 #include <cppuhelper/factory.hxx>
30 #include <cppuhelper/weakref.hxx>
31 #include <cppuhelper/implbase.hxx>
32 #include <cppuhelper/compbase.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <comphelper/sequence.hxx>
35
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
40 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
41 #include <com/sun/star/lang/XInitialization.hpp>
42 #include <com/sun/star/lang/XEventListener.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/registry/XRegistryKey.hpp>
47 #include <com/sun/star/registry/XSimpleRegistry.hpp>
48 #include <com/sun/star/container/XSet.hpp>
49 #include <com/sun/star/container/XElementAccess.hpp>
50 #include <com/sun/star/container/XEnumeration.hpp>
51 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
52 #include <com/sun/star/uno/XComponentContext.hpp>
53
54 #include <iterator>
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 > const 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 OSL_FAIL( "IllegalArgumentException caught" );
292 }
293 catch( const NoSuchElementException & )
294 {
295 OSL_FAIL( "NoSuchElementException caught" );
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 // XMultibleServiceFactory
createInstance(const OUString & rServiceSpecifier)871 Reference<XInterface > OServiceManager::createInstance(
872 const OUString& rServiceSpecifier )
873 {
874 return createInstanceWithContext(
875 rServiceSpecifier, m_xContext );
876 }
877
878 // XMultibleServiceFactory
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(const OUString& serviceName) const;
1180 Reference<XInterface > loadWithServiceName(
1181 const OUString & 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(const OUString & serviceName) const1290 Sequence<OUString> ORegistryServiceManager::getFromServiceName(
1291 const OUString& serviceName ) const
1292 {
1293 OUString buf = "/SERVICES/" + serviceName;
1294 return retrieveAsciiValueList( m_xRegistry, buf );
1295 }
1296
1297 /**
1298 * Create a service provider from the registry
1299 */
loadWithServiceName(const OUString & serviceName,Reference<XComponentContext> const & xContext)1300 Reference<XInterface > ORegistryServiceManager::loadWithServiceName(
1301 const OUString& 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