1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <o3tl/any.hxx>
23 #include <osl/mutex.hxx>
24 #include <osl/diagnose.h>
25 #include <sal/log.hxx>
27 #include <cppuhelper/basemutex.hxx>
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>
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>
55 #include <string_view>
56 #include <unordered_map>
57 #include <unordered_set>
60 using namespace com::sun::star
;
61 using namespace css::uno
;
62 using namespace css::beans
;
63 using namespace css::registry
;
64 using namespace css::lang
;
65 using namespace css::container
;
71 Sequence
< OUString
> retrieveAsciiValueList(
72 const Reference
< XSimpleRegistry
> &xReg
, const OUString
&keyName
)
74 Reference
< XEnumerationAccess
> xAccess( xReg
, UNO_QUERY
);
75 Sequence
< OUString
> seq
;
78 Reference
< XEnumeration
> xEnum
= xAccess
->createEnumeration();
79 while( xEnum
.is() && xEnum
->hasMoreElements() )
81 Reference
< XSimpleRegistry
> xTempReg
;
82 xEnum
->nextElement() >>= xTempReg
;
85 const Sequence
< OUString
> seq2
= retrieveAsciiValueList( xTempReg
, keyName
);
87 if( seq2
.hasElements() )
89 sal_Int32 n1Len
= seq
.getLength();
90 sal_Int32 n2Len
= seq2
.getLength();
92 seq
.realloc( n1Len
+ n2Len
);
93 std::copy(seq2
.begin(), seq2
.end(), std::next(seq
.getArray(), n1Len
));
102 Reference
< XRegistryKey
> rRootKey
= xReg
->getRootKey();
105 Reference
<XRegistryKey
> xKey
= rRootKey
->openKey(keyName
);
108 seq
= xKey
->getAsciiListValue();
112 catch( InvalidRegistryException
& )
115 catch (InvalidValueException
&)
122 /*****************************************************************************
123 Enumeration by ServiceName
124 *****************************************************************************/
126 typedef std::unordered_set
< Reference
<XInterface
> > HashSet_Ref
;
129 class ServiceEnumeration_Impl
: public WeakImplHelper
< XEnumeration
>
132 explicit ServiceEnumeration_Impl( const Sequence
< Reference
<XInterface
> > & rFactories
)
133 : aFactories( rFactories
)
138 sal_Bool SAL_CALL
hasMoreElements() override
;
139 Any SAL_CALL
nextElement() override
;
142 Sequence
< Reference
<XInterface
> > aFactories
;
147 sal_Bool
ServiceEnumeration_Impl::hasMoreElements()
149 std::scoped_lock
aGuard( aMutex
);
150 return nIt
!= aFactories
.getLength();
154 Any
ServiceEnumeration_Impl::nextElement()
156 std::scoped_lock
aGuard( aMutex
);
157 if( nIt
== aFactories
.getLength() )
158 throw NoSuchElementException("no more elements");
160 return Any( &aFactories
.getConstArray()[nIt
++], cppu::UnoType
<XInterface
>::get());
164 class PropertySetInfo_Impl
: public WeakImplHelper
< beans::XPropertySetInfo
>
166 Sequence
< beans::Property
> m_properties
;
169 explicit PropertySetInfo_Impl( Sequence
< beans::Property
> const & properties
)
170 : m_properties( properties
)
173 // XPropertySetInfo impl
174 virtual Sequence
< beans::Property
> SAL_CALL
getProperties() override
;
175 virtual beans::Property SAL_CALL
getPropertyByName( OUString
const & name
) override
;
176 virtual sal_Bool SAL_CALL
hasPropertyByName( OUString
const & name
) override
;
179 Sequence
< beans::Property
> PropertySetInfo_Impl::getProperties()
184 beans::Property
PropertySetInfo_Impl::getPropertyByName( OUString
const & name
)
186 beans::Property
const * p
= m_properties
.getConstArray();
187 for ( sal_Int32 nPos
= m_properties
.getLength(); nPos
--; )
189 if (p
[ nPos
].Name
== name
)
192 throw beans::UnknownPropertyException(
193 "unknown property: " + name
);
196 sal_Bool
PropertySetInfo_Impl::hasPropertyByName( OUString
const & name
)
198 return std::any_of(std::cbegin(m_properties
), std::cend(m_properties
),
199 [&name
](const beans::Property
& rProp
) { return rProp
.Name
== name
; });
203 /*****************************************************************************
204 Enumeration by implementation
205 *****************************************************************************/
206 class ImplementationEnumeration_Impl
: public WeakImplHelper
< XEnumeration
>
209 explicit ImplementationEnumeration_Impl( HashSet_Ref xImplementationMap
)
210 : aImplementationMap(std::move( xImplementationMap
))
211 , aIt( aImplementationMap
.begin() )
215 virtual sal_Bool SAL_CALL
hasMoreElements() override
;
216 virtual Any SAL_CALL
nextElement() override
;
220 HashSet_Ref aImplementationMap
;
221 HashSet_Ref::iterator aIt
;
225 sal_Bool
ImplementationEnumeration_Impl::hasMoreElements()
227 std::scoped_lock
aGuard( aMutex
);
228 return aIt
!= aImplementationMap
.end();
232 Any
ImplementationEnumeration_Impl::nextElement()
234 std::scoped_lock
aGuard( aMutex
);
235 if( aIt
== aImplementationMap
.end() )
236 throw NoSuchElementException("no more elements");
238 Any
ret( &(*aIt
), cppu::UnoType
<XInterface
>::get());
243 /*****************************************************************************
245 *****************************************************************************/
246 typedef std::unordered_set
251 typedef std::unordered_multimap
254 Reference
<XInterface
>
255 > HashMultimap_OWString_Interface
;
257 typedef std::unordered_map
260 Reference
<XInterface
>
261 > HashMap_OWString_Interface
;
263 /*****************************************************************************
264 class OServiceManager_Listener
265 *****************************************************************************/
266 class OServiceManager_Listener
: public WeakImplHelper
< XEventListener
>
269 WeakReference
<XSet
> xSMgr
;
272 explicit OServiceManager_Listener( const Reference
<XSet
> & rSMgr
)
277 virtual void SAL_CALL
disposing(const EventObject
& rEvt
) override
;
280 void OServiceManager_Listener::disposing(const EventObject
& rEvt
)
282 Reference
<XSet
> x( xSMgr
);
288 x
->remove( Any( &rEvt
.Source
, cppu::UnoType
<XInterface
>::get()) );
290 catch( const IllegalArgumentException
& )
292 OSL_FAIL( "IllegalArgumentException caught" );
294 catch( const NoSuchElementException
& )
296 OSL_FAIL( "NoSuchElementException caught" );
301 /*****************************************************************************
302 class OServiceManager
303 *****************************************************************************/
305 typedef WeakComponentImplHelper
<
306 lang::XMultiServiceFactory
, lang::XMultiComponentFactory
, lang::XServiceInfo
,
307 lang::XInitialization
,
308 container::XSet
, container::XContentEnumerationAccess
,
309 beans::XPropertySet
> t_OServiceManager_impl
;
311 class OServiceManager
312 : public cppu::BaseMutex
313 , public t_OServiceManager_impl
316 explicit OServiceManager( Reference
< XComponentContext
> const & xContext
);
319 void SAL_CALL
initialize( Sequence
< Any
> const & args
) override
;
322 virtual OUString SAL_CALL
getImplementationName() override
;
323 virtual sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
;
324 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
326 // XMultiComponentFactory
327 virtual Reference
< XInterface
> SAL_CALL
createInstanceWithContext(
328 OUString
const & rServiceSpecifier
, Reference
< XComponentContext
> const & xContext
) override
;
329 virtual Reference
< XInterface
> SAL_CALL
createInstanceWithArgumentsAndContext(
330 OUString
const & rServiceSpecifier
,
331 Sequence
< Any
> const & rArguments
,
332 Reference
< XComponentContext
> const & xContext
) override
;
333 // virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
334 // throw (RuntimeException);
336 // XMultiServiceFactory
337 virtual Sequence
< OUString
> SAL_CALL
getAvailableServiceNames() override
;
338 virtual Reference
<XInterface
> SAL_CALL
createInstance(const OUString
&) override
;
339 virtual Reference
<XInterface
> SAL_CALL
createInstanceWithArguments(const OUString
&, const Sequence
<Any
>& Arguments
) override
;
341 // The same as the getAvailableServiceNames, but only unique names
342 Sequence
< OUString
> getUniqueAvailableServiceNames(
343 HashSet_OWString
& aNameSet
);
346 virtual Type SAL_CALL
getElementType() override
;
347 virtual sal_Bool SAL_CALL
hasElements() override
;
349 // XEnumerationAccess
350 virtual Reference
<XEnumeration
> SAL_CALL
createEnumeration() override
;
353 virtual sal_Bool SAL_CALL
has( const Any
& Element
) override
;
354 virtual void SAL_CALL
insert( const Any
& Element
) override
;
355 virtual void SAL_CALL
remove( const Any
& Element
) override
;
357 // XContentEnumerationAccess
358 //Sequence< OUString > getAvailableServiceNames() throw( (Exception) );
359 virtual Reference
<XEnumeration
> SAL_CALL
createContentEnumeration(const OUString
& aServiceName
) override
;
362 virtual void SAL_CALL
dispose() override
;
365 Reference
<XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
;
366 void SAL_CALL
setPropertyValue(const OUString
& PropertyName
, const Any
& aValue
) override
;
367 Any SAL_CALL
getPropertyValue(const OUString
& PropertyName
) override
;
368 void SAL_CALL
addPropertyChangeListener(const OUString
& PropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
;
369 void SAL_CALL
removePropertyChangeListener(const OUString
& PropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
;
370 void SAL_CALL
addVetoableChangeListener(const OUString
& PropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
;
371 void SAL_CALL
removeVetoableChangeListener(const OUString
& PropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
;
374 bool is_disposed() const;
375 void check_undisposed() const;
376 virtual void SAL_CALL
disposing() override
;
378 bool haveFactoryWithThisImplementation(const OUString
& aImplName
);
380 virtual Sequence
< Reference
< XInterface
> > queryServiceFactories(
381 const OUString
& aServiceName
, Reference
< XComponentContext
> const & xContext
);
383 Reference
< XComponentContext
> m_xContext
;
385 Reference
< beans::XPropertySetInfo
> m_xPropertyInfo
;
387 // factories which have been loaded and not inserted( by XSet::insert)
388 // are remembered by this set.
389 HashSet_Ref m_SetLoadedFactories
;
392 Reference
<XEventListener
> getFactoryListener();
395 HashMultimap_OWString_Interface m_ServiceMap
;
396 HashSet_Ref m_ImplementationMap
;
397 HashMap_OWString_Interface m_ImplementationNameMap
;
398 Reference
<XEventListener
> xFactoryListener
;
403 bool OServiceManager::is_disposed() const
405 // ought to be guarded by m_mutex:
406 return (m_bInDisposing
|| rBHelper
.bDisposed
);
410 void OServiceManager::check_undisposed() const
414 throw lang::DisposedException(
415 "service manager instance has already been disposed!",
416 static_cast<OWeakObject
*>(const_cast<OServiceManager
*>(this)) );
421 typedef WeakComponentImplHelper
<
422 lang::XMultiServiceFactory
, lang::XMultiComponentFactory
, lang::XServiceInfo
,
423 container::XSet
, container::XContentEnumerationAccess
,
424 beans::XPropertySet
> t_OServiceManagerWrapper_impl
;
426 class OServiceManagerWrapper
: public cppu::BaseMutex
, public t_OServiceManagerWrapper_impl
428 Reference
< XComponentContext
> m_xContext
;
429 Reference
< XMultiComponentFactory
> m_root
;
430 Reference
< XMultiComponentFactory
> const & getRoot() const
434 throw lang::DisposedException(
435 "service manager instance has already been disposed!" );
441 virtual void SAL_CALL
disposing() override
;
444 explicit OServiceManagerWrapper(
445 Reference
< XComponentContext
> const & xContext
);
448 virtual OUString SAL_CALL
getImplementationName() override
449 { return Reference
< XServiceInfo
>(getRoot(), UNO_QUERY_THROW
)->getImplementationName(); }
450 virtual sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) override
451 { return Reference
< XServiceInfo
>(getRoot(), UNO_QUERY_THROW
)->supportsService( ServiceName
); }
452 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
453 { return Reference
< XServiceInfo
>(getRoot(), UNO_QUERY_THROW
)->getSupportedServiceNames(); }
455 // XMultiComponentFactory
456 virtual Reference
< XInterface
> SAL_CALL
createInstanceWithContext(
457 OUString
const & rServiceSpecifier
, Reference
< XComponentContext
> const & xContext
) override
458 { return getRoot()->createInstanceWithContext( rServiceSpecifier
, xContext
); }
459 virtual Reference
< XInterface
> SAL_CALL
createInstanceWithArgumentsAndContext(
460 OUString
const & rServiceSpecifier
,
461 Sequence
< Any
> const & rArguments
,
462 Reference
< XComponentContext
> const & xContext
) override
463 { return getRoot()->createInstanceWithArgumentsAndContext( rServiceSpecifier
, rArguments
, xContext
); }
464 // virtual Sequence< OUString > SAL_CALL getAvailableServiceNames()
465 // throw (RuntimeException);
467 // XMultiServiceFactory
468 virtual Sequence
< OUString
> SAL_CALL
getAvailableServiceNames() override
469 { return getRoot()->getAvailableServiceNames(); }
470 virtual Reference
<XInterface
> SAL_CALL
createInstance(const OUString
& name
) override
471 { return getRoot()->createInstanceWithContext( name
, m_xContext
); }
472 virtual Reference
<XInterface
> SAL_CALL
createInstanceWithArguments(const OUString
& name
, const Sequence
<Any
>& Arguments
) override
473 { return getRoot()->createInstanceWithArgumentsAndContext( name
, Arguments
, m_xContext
); }
476 virtual Type SAL_CALL
getElementType() override
477 { return Reference
< XElementAccess
>(getRoot(), UNO_QUERY_THROW
)->getElementType(); }
478 virtual sal_Bool SAL_CALL
hasElements() override
479 { return Reference
< XElementAccess
>(getRoot(), UNO_QUERY_THROW
)->hasElements(); }
481 // XEnumerationAccess
482 virtual Reference
<XEnumeration
> SAL_CALL
createEnumeration() override
483 { return Reference
< XEnumerationAccess
>(getRoot(), UNO_QUERY_THROW
)->createEnumeration(); }
486 virtual sal_Bool SAL_CALL
has( const Any
& Element
) override
487 { return Reference
< XSet
>(getRoot(), UNO_QUERY_THROW
)->has( Element
); }
488 virtual void SAL_CALL
insert( const Any
& Element
) override
489 { Reference
< XSet
>(getRoot(), UNO_QUERY_THROW
)->insert( Element
); }
490 virtual void SAL_CALL
remove( const Any
& Element
) override
491 { Reference
< XSet
>(getRoot(), UNO_QUERY_THROW
)->remove( Element
); }
493 // XContentEnumerationAccess
494 //Sequence< OUString > getAvailableServiceNames() throw( (Exception) );
495 virtual Reference
<XEnumeration
> SAL_CALL
createContentEnumeration(const OUString
& aServiceName
) override
496 { return Reference
< XContentEnumerationAccess
>(getRoot(), UNO_QUERY_THROW
)->createContentEnumeration( aServiceName
); }
499 Reference
<XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
500 { return Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->getPropertySetInfo(); }
502 void SAL_CALL
setPropertyValue(const OUString
& PropertyName
, const Any
& aValue
) override
;
503 Any SAL_CALL
getPropertyValue(const OUString
& PropertyName
) override
;
505 void SAL_CALL
addPropertyChangeListener(const OUString
& PropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
506 { Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->addPropertyChangeListener( PropertyName
, aListener
); }
507 void SAL_CALL
removePropertyChangeListener(const OUString
& PropertyName
, const Reference
<XPropertyChangeListener
>& aListener
) override
508 { Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->removePropertyChangeListener( PropertyName
, aListener
); }
509 void SAL_CALL
addVetoableChangeListener(const OUString
& PropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
510 { Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->addVetoableChangeListener( PropertyName
, aListener
); }
511 void SAL_CALL
removeVetoableChangeListener(const OUString
& PropertyName
, const Reference
<XVetoableChangeListener
>& aListener
) override
512 { Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->removeVetoableChangeListener( PropertyName
, aListener
); }
515 void SAL_CALL
OServiceManagerWrapper::setPropertyValue(
516 const OUString
& PropertyName
, const Any
& aValue
)
518 if ( PropertyName
== "DefaultContext" )
520 Reference
< XComponentContext
> xContext
;
521 if (!(aValue
>>= xContext
))
523 throw IllegalArgumentException(
524 "no XComponentContext given!",
525 static_cast<OWeakObject
*>(this), 1 );
528 MutexGuard
aGuard( m_aMutex
);
529 m_xContext
= xContext
;
534 Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->setPropertyValue( PropertyName
, aValue
);
538 Any SAL_CALL
OServiceManagerWrapper::getPropertyValue(
539 const OUString
& PropertyName
)
541 if ( PropertyName
== "DefaultContext" )
543 MutexGuard
aGuard( m_aMutex
);
544 if( m_xContext
.is() )
545 return Any( m_xContext
);
551 return Reference
< XPropertySet
>(getRoot(), UNO_QUERY_THROW
)->getPropertyValue( PropertyName
);
555 void OServiceManagerWrapper::disposing()
559 // no m_root->dispose(), because every context disposes its service manager...
563 OServiceManagerWrapper::OServiceManagerWrapper(
564 Reference
< XComponentContext
> const & xContext
)
565 : t_OServiceManagerWrapper_impl( m_aMutex
)
566 , m_xContext( xContext
)
567 , m_root( xContext
->getServiceManager() )
571 throw RuntimeException(
572 "no service manager to wrap" );
578 * Create a ServiceManager
580 OServiceManager::OServiceManager( Reference
< XComponentContext
> const & xContext
)
581 : t_OServiceManager_impl( m_aMutex
)
582 , m_xContext( xContext
)
583 , m_bInDisposing( false )
587 void OServiceManager::dispose()
589 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
591 t_OServiceManager_impl::dispose();
594 void OServiceManager::disposing()
596 // dispose all factories
599 MutexGuard
aGuard( m_aMutex
);
600 m_bInDisposing
= true;
601 aImpls
= m_ImplementationMap
;
603 for( const auto& rxImpl
: aImpls
)
607 Reference
<XComponent
> xComp( Reference
<XComponent
>::query( rxImpl
) );
611 catch (const RuntimeException
& exc
)
613 SAL_INFO("stoc", "RuntimeException occurred upon disposing factory: " << exc
);
618 HashSet_Ref aImplMap
;
620 MutexGuard
aGuard( m_aMutex
);
622 m_ServiceMap
= HashMultimap_OWString_Interface();
623 aImplMap
= m_ImplementationMap
;
624 m_ImplementationMap
= HashSet_Ref();
625 m_ImplementationNameMap
= HashMap_OWString_Interface();
626 m_SetLoadedFactories
= HashSet_Ref();
631 // not only the Event should hold the object
632 OSL_ASSERT( m_refCount
!= 1 );
636 Reference
<XPropertySetInfo
> OServiceManager::getPropertySetInfo()
639 if (! m_xPropertyInfo
.is())
641 Sequence
< beans::Property
> seq
{ beans::Property(
642 "DefaultContext", -1, cppu::UnoType
<decltype(m_xContext
)>::get(), 0 ) };
643 Reference
< beans::XPropertySetInfo
> xInfo( new PropertySetInfo_Impl( seq
) );
645 MutexGuard
aGuard( m_aMutex
);
646 if (! m_xPropertyInfo
.is())
648 m_xPropertyInfo
= xInfo
;
651 return m_xPropertyInfo
;
654 void OServiceManager::setPropertyValue(
655 const OUString
& PropertyName
, const Any
& aValue
)
658 if ( PropertyName
!= "DefaultContext" )
660 throw UnknownPropertyException(
661 "unknown property " + PropertyName
,
662 static_cast<OWeakObject
*>(this) );
665 Reference
< XComponentContext
> xContext
;
666 if (!(aValue
>>= xContext
))
668 throw IllegalArgumentException(
669 "no XComponentContext given!",
670 static_cast<OWeakObject
*>(this), 1 );
673 MutexGuard
aGuard( m_aMutex
);
674 m_xContext
= xContext
;
677 Any
OServiceManager::getPropertyValue(const OUString
& PropertyName
)
680 if ( PropertyName
== "DefaultContext" )
682 MutexGuard
aGuard( m_aMutex
);
683 if( m_xContext
.is() )
684 return Any( m_xContext
);
690 UnknownPropertyException except
;
691 except
.Message
= "ServiceManager : unknown property " + PropertyName
;
696 void OServiceManager::addPropertyChangeListener(
697 const OUString
&, const Reference
<XPropertyChangeListener
>&)
700 throw UnknownPropertyException("unsupported");
703 void OServiceManager::removePropertyChangeListener(
704 const OUString
&, const Reference
<XPropertyChangeListener
>&)
707 throw UnknownPropertyException("unsupported");
710 void OServiceManager::addVetoableChangeListener(
711 const OUString
&, const Reference
<XVetoableChangeListener
>&)
714 throw UnknownPropertyException("unsupported");
717 void OServiceManager::removeVetoableChangeListener(
718 const OUString
&, const Reference
<XVetoableChangeListener
>&)
721 throw UnknownPropertyException("unsupported");
725 Reference
<XEventListener
> OServiceManager::getFactoryListener()
728 MutexGuard
aGuard( m_aMutex
);
729 if( !xFactoryListener
.is() )
730 xFactoryListener
= new OServiceManager_Listener( this );
731 return xFactoryListener
;
734 // XMultiServiceFactory, XContentEnumeration
735 Sequence
< OUString
> OServiceManager::getUniqueAvailableServiceNames(
736 HashSet_OWString
& aNameSet
)
739 MutexGuard
aGuard( m_aMutex
);
740 for( const auto& rEntry
: m_ServiceMap
)
741 aNameSet
.insert( rEntry
.first
);
743 /* do not return the implementation names
744 HashMap_OWString_Interface m_ImplementationNameMap;
745 HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin();
746 while( aIt != m_ImplementationNameMap.end() )
747 aNameSet.insert( (*aIt++).first );
750 return comphelper::containerToSequence(aNameSet
);
753 // XMultiComponentFactory
754 Reference
< XInterface
> OServiceManager::createInstanceWithContext(
755 OUString
const & rServiceSpecifier
,
756 Reference
< XComponentContext
> const & xContext
)
759 #if OSL_DEBUG_LEVEL > 0
760 Reference
< beans::XPropertySet
> xProps( xContext
->getServiceManager(), UNO_QUERY
);
761 OSL_ASSERT( xProps
.is() );
764 Reference
< XComponentContext
> xDefContext
;
765 xProps
->getPropertyValue( "DefaultContext" ) >>= xDefContext
;
767 xContext
== xDefContext
,
768 "### default context of service manager singleton differs from context holding it!" );
772 const Sequence
< Reference
< XInterface
> > factories(
773 queryServiceFactories( rServiceSpecifier
, xContext
) );
774 for ( Reference
< XInterface
> const & xFactory
: factories
)
780 Reference
< XSingleComponentFactory
> xFac( xFactory
, UNO_QUERY
);
783 return xFac
->createInstanceWithContext( xContext
);
787 Reference
< XSingleServiceFactory
> xFac2( xFactory
, UNO_QUERY
);
790 SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier
<< "!!!");
791 return xFac2
->createInstance();
796 catch (const lang::DisposedException
& exc
)
798 SAL_INFO("stoc", "DisposedException occurred: " << exc
);
802 return Reference
< XInterface
>();
804 // XMultiComponentFactory
805 Reference
< XInterface
> OServiceManager::createInstanceWithArgumentsAndContext(
806 OUString
const & rServiceSpecifier
,
807 Sequence
< Any
> const & rArguments
,
808 Reference
< XComponentContext
> const & xContext
)
811 #if OSL_DEBUG_LEVEL > 0
812 Reference
< beans::XPropertySet
> xProps( xContext
->getServiceManager(), UNO_QUERY
);
813 OSL_ASSERT( xProps
.is() );
816 Reference
< XComponentContext
> xDefContext
;
817 xProps
->getPropertyValue( "DefaultContext" ) >>= xDefContext
;
819 xContext
== xDefContext
,
820 "### default context of service manager singleton differs from context holding it!" );
824 const Sequence
< Reference
< XInterface
> > factories(
825 queryServiceFactories( rServiceSpecifier
, xContext
) );
826 for ( Reference
< XInterface
> const & xFactory
: factories
)
832 Reference
< XSingleComponentFactory
> xFac( xFactory
, UNO_QUERY
);
835 return xFac
->createInstanceWithArgumentsAndContext( rArguments
, xContext
);
839 Reference
< XSingleServiceFactory
> xFac2( xFactory
, UNO_QUERY
);
842 SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier
<< "!!!");
843 return xFac2
->createInstanceWithArguments( rArguments
);
848 catch (const lang::DisposedException
& exc
)
850 SAL_INFO("stoc", "DisposedException occurred: " << exc
);
854 return Reference
< XInterface
>();
857 // XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration
858 Sequence
< OUString
> OServiceManager::getAvailableServiceNames()
862 HashSet_OWString aNameSet
;
863 return getUniqueAvailableServiceNames( aNameSet
);
866 // XMultipleServiceFactory
867 Reference
<XInterface
> OServiceManager::createInstance(
868 const OUString
& rServiceSpecifier
)
870 return createInstanceWithContext(
871 rServiceSpecifier
, m_xContext
);
874 // XMultipleServiceFactory
875 Reference
<XInterface
> OServiceManager::createInstanceWithArguments(
876 const OUString
& rServiceSpecifier
,
877 const Sequence
<Any
>& rArguments
)
879 return createInstanceWithArgumentsAndContext(
880 rServiceSpecifier
, rArguments
, m_xContext
);
884 void OServiceManager::initialize( Sequence
< Any
> const & )
887 OSL_FAIL( "not impl!" );
891 OUString
OServiceManager::getImplementationName()
893 return "com.sun.star.comp.stoc.OServiceManager";
897 sal_Bool
OServiceManager::supportsService(const OUString
& ServiceName
)
899 return cppu::supportsService(this, ServiceName
);
903 Sequence
< OUString
> OServiceManager::getSupportedServiceNames()
905 return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.ServiceManager" };
909 Sequence
< Reference
< XInterface
> > OServiceManager::queryServiceFactories(
910 const OUString
& aServiceName
, Reference
< XComponentContext
> const & )
912 Sequence
< Reference
< XInterface
> > ret
;
914 MutexGuard
aGuard( m_aMutex
);
916 HashMultimap_OWString_Interface::iterator
,
917 HashMultimap_OWString_Interface::iterator
> p(
918 m_ServiceMap
.equal_range( aServiceName
) );
920 if (p
.first
== p
.second
) // no factories
922 // no service found, look for an implementation
923 HashMap_OWString_Interface::iterator aIt
= m_ImplementationNameMap
.find( aServiceName
);
924 if( aIt
!= m_ImplementationNameMap
.end() )
926 Reference
< XInterface
> const & x
= aIt
->second
;
927 // an implementation found
928 ret
= Sequence
< Reference
< XInterface
> >( &x
, 1 );
933 ::std::vector
< Reference
< XInterface
> > vec
;
935 while (p
.first
!= p
.second
)
937 vec
.push_back( p
.first
->second
);
940 ret
= Sequence
< Reference
< XInterface
> >( vec
.data(), vec
.size() );
946 // XContentEnumerationAccess
947 Reference
<XEnumeration
> OServiceManager::createContentEnumeration(
948 const OUString
& aServiceName
)
951 Sequence
< Reference
< XInterface
> > factories(
952 OServiceManager::queryServiceFactories( aServiceName
, m_xContext
) );
953 if (factories
.hasElements())
954 return new ServiceEnumeration_Impl( factories
);
956 return Reference
< XEnumeration
>();
960 Reference
<XEnumeration
> OServiceManager::createEnumeration()
963 MutexGuard
aGuard( m_aMutex
);
964 return new ImplementationEnumeration_Impl( m_ImplementationMap
);
968 Type
OServiceManager::getElementType()
971 return cppu::UnoType
<XInterface
>::get();
975 sal_Bool
OServiceManager::hasElements()
978 MutexGuard
aGuard( m_aMutex
);
979 return !m_ImplementationMap
.empty();
983 sal_Bool
OServiceManager::has( const Any
& Element
)
986 if( Element
.getValueTypeClass() == TypeClass_INTERFACE
)
988 Reference
<XInterface
> xEle( Element
, UNO_QUERY_THROW
);
989 MutexGuard
aGuard( m_aMutex
);
990 return m_ImplementationMap
.find( xEle
) !=
991 m_ImplementationMap
.end();
993 else if (auto implName
= o3tl::tryAccess
<OUString
>(Element
))
995 MutexGuard
aGuard( m_aMutex
);
996 return m_ImplementationNameMap
.find( *implName
) !=
997 m_ImplementationNameMap
.end();
1003 void OServiceManager::insert( const Any
& Element
)
1006 if( Element
.getValueTypeClass() != TypeClass_INTERFACE
)
1008 throw IllegalArgumentException(
1009 "exception interface, got " + Element
.getValueType().getTypeName(),
1010 Reference
< XInterface
>(), 0 );
1012 Reference
<XInterface
> xEle( Element
, UNO_QUERY_THROW
);
1015 MutexGuard
aGuard( m_aMutex
);
1016 HashSet_Ref::iterator aIt
= m_ImplementationMap
.find( xEle
);
1017 if( aIt
!= m_ImplementationMap
.end() )
1019 throw ElementExistException( "element already exists!" );
1022 // put into the implementation hashmap
1023 m_ImplementationMap
.insert( xEle
);
1025 // put into the implementation name hashmap
1026 Reference
<XServiceInfo
> xInfo( Reference
<XServiceInfo
>::query( xEle
) );
1029 OUString aImplName
= xInfo
->getImplementationName();
1030 if( !aImplName
.isEmpty() )
1031 m_ImplementationNameMap
[ aImplName
] = xEle
;
1033 //put into the service map
1034 const Sequence
< OUString
> aServiceNames
= xInfo
->getSupportedServiceNames();
1035 for( const OUString
& rServiceName
: aServiceNames
)
1037 m_ServiceMap
.emplace(
1038 rServiceName
, *o3tl::doAccess
<Reference
<XInterface
>>(Element
) );
1042 // add the disposing listener to the factory
1043 Reference
<XComponent
> xComp( Reference
<XComponent
>::query( xEle
) );
1045 xComp
->addEventListener( getFactoryListener() );
1049 bool OServiceManager::haveFactoryWithThisImplementation(const OUString
& aImplName
)
1051 return ( m_ImplementationNameMap
.find(aImplName
) != m_ImplementationNameMap
.end());
1055 void OServiceManager::remove( const Any
& Element
)
1060 Reference
<XInterface
> xEle
;
1061 if (Element
.getValueTypeClass() == TypeClass_INTERFACE
)
1063 xEle
.set( Element
, UNO_QUERY_THROW
);
1065 else if (auto implName
= o3tl::tryAccess
<OUString
>(Element
))
1067 MutexGuard
aGuard( m_aMutex
);
1068 HashMap_OWString_Interface::const_iterator
const iFind(
1069 m_ImplementationNameMap
.find( *implName
) );
1070 if (iFind
== m_ImplementationNameMap
.end())
1072 throw NoSuchElementException(
1073 "element is not in: " + *implName
,
1074 static_cast< OWeakObject
* >(this) );
1076 xEle
= iFind
->second
;
1080 throw IllegalArgumentException(
1081 "expected interface or string, got " + Element
.getValueType().getTypeName(),
1082 Reference
< XInterface
>(), 0 );
1085 // remove the disposing listener from the factory
1086 Reference
<XComponent
> xComp( Reference
<XComponent
>::query( xEle
) );
1088 xComp
->removeEventListener( getFactoryListener() );
1090 MutexGuard
aGuard( m_aMutex
);
1091 HashSet_Ref::iterator aIt
= m_ImplementationMap
.find( xEle
);
1092 if( aIt
== m_ImplementationMap
.end() )
1094 throw NoSuchElementException(
1095 "element not found",
1096 static_cast< OWeakObject
* >(this) );
1098 //First remove all factories which have been loaded by ORegistryServiceManager.
1099 m_SetLoadedFactories
.erase( *aIt
);
1100 //Remove from the implementation map. It contains all factories of m_SetLoadedFactories
1101 //which have been added directly through XSet, that is not via ORegistryServiceManager
1102 m_ImplementationMap
.erase( aIt
);
1104 // remove from the implementation name hashmap
1105 Reference
<XServiceInfo
> xInfo( Reference
<XServiceInfo
>::query( xEle
) );
1108 OUString aImplName
= xInfo
->getImplementationName();
1109 if( !aImplName
.isEmpty() )
1110 m_ImplementationNameMap
.erase( aImplName
);
1113 //remove from the service map
1114 Reference
<XServiceInfo
> xSF( Reference
<XServiceInfo
>::query( xEle
) );
1118 const Sequence
< OUString
> aServiceNames
= xSF
->getSupportedServiceNames();
1119 for( const OUString
& rServiceName
: aServiceNames
)
1121 std::pair
<HashMultimap_OWString_Interface::iterator
, HashMultimap_OWString_Interface::iterator
> p
=
1122 m_ServiceMap
.equal_range( rServiceName
);
1124 while( p
.first
!= p
.second
)
1126 if( xEle
== (*p
.first
).second
)
1128 m_ServiceMap
.erase( p
.first
);
1136 /*****************************************************************************
1137 class ORegistryServiceManager
1138 *****************************************************************************/
1139 class ORegistryServiceManager
: public OServiceManager
1142 explicit ORegistryServiceManager( Reference
< XComponentContext
> const & xContext
);
1145 void SAL_CALL
initialize(const Sequence
< Any
>& Arguments
) override
;
1148 OUString SAL_CALL
getImplementationName() override
1149 { return "com.sun.star.comp.stoc.ORegistryServiceManager"; }
1151 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1153 // XMultiServiceFactory
1154 Sequence
< OUString
> SAL_CALL
getAvailableServiceNames() override
;
1156 // XContentEnumerationAccess
1157 //Sequence< OUString > getAvailableServiceNames() throw( (Exception) );
1158 Reference
<XEnumeration
> SAL_CALL
createContentEnumeration(const OUString
& aServiceName
) override
;
1161 void SAL_CALL
dispose() override
;
1164 Reference
<XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
;
1165 Any SAL_CALL
getPropertyValue(const OUString
& PropertyName
) override
;
1169 Sequence
< Reference
< XInterface
> > queryServiceFactories(
1170 const OUString
& aServiceName
, Reference
< XComponentContext
> const & xContext
) override
;
1172 Reference
<XRegistryKey
> getRootKey();
1173 Reference
<XInterface
> loadWithImplementationName(
1174 const OUString
& rImplName
, Reference
< XComponentContext
> const & xContext
);
1175 Sequence
<OUString
> getFromServiceName(std::u16string_view serviceName
) const;
1176 Reference
<XInterface
> loadWithServiceName(
1177 std::u16string_view rImplName
, Reference
< XComponentContext
> const & xContext
);
1178 void fillAllNamesFromRegistry( HashSet_OWString
& );
1180 bool m_searchedRegistry
;
1181 Reference
<XSimpleRegistry
> m_xRegistry
; // readonly property Registry
1182 Reference
<XRegistryKey
> m_xRootKey
;
1184 #if OSL_DEBUG_LEVEL > 0
1190 * Create a ServiceManager
1192 ORegistryServiceManager::ORegistryServiceManager( Reference
< XComponentContext
> const & xContext
)
1193 : OServiceManager( xContext
)
1194 , m_searchedRegistry(false)
1195 #if OSL_DEBUG_LEVEL > 0
1202 void ORegistryServiceManager::dispose()
1204 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
1206 OServiceManager::dispose();
1208 MutexGuard
aGuard( m_aMutex
);
1209 // erase all members
1210 m_xRegistry
.clear();
1215 * Return the root key of the registry. The Default registry service is ordered
1216 * if no registry is set.
1218 //Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider();
1220 Reference
<XRegistryKey
> ORegistryServiceManager::getRootKey()
1222 if( !m_xRootKey
.is() )
1224 MutexGuard
aGuard( m_aMutex
);
1225 // DefaultRegistry suchen !!!!
1226 if( !m_xRegistry
.is() && !m_searchedRegistry
)
1228 // NB. we only search this once
1229 m_searchedRegistry
= true;
1232 createInstanceWithContext(
1233 "com.sun.star.registry.DefaultRegistry",
1237 if( m_xRegistry
.is() && !m_xRootKey
.is() )
1238 m_xRootKey
= m_xRegistry
->getRootKey();
1245 * Create a service provider from the registry with an implementation name
1247 Reference
<XInterface
> ORegistryServiceManager::loadWithImplementationName(
1248 const OUString
& name
, Reference
< XComponentContext
> const & xContext
)
1250 Reference
<XInterface
> ret
;
1252 Reference
<XRegistryKey
> xRootKey
= getRootKey();
1253 if( !xRootKey
.is() )
1258 OUString implementationName
= "/IMPLEMENTATIONS/" + name
;
1259 Reference
<XRegistryKey
> xImpKey
= m_xRootKey
->openKey(implementationName
);
1263 Reference
< lang::XMultiServiceFactory
> xMgr
;
1265 xMgr
.set( xContext
->getServiceManager(), UNO_QUERY_THROW
);
1268 ret
= createSingleRegistryFactory( xMgr
, name
, xImpKey
);
1269 insert( Any( ret
) );
1270 // Remember this factory as loaded in contrast to inserted ( XSet::insert)
1271 // factories. Those loaded factories in this set are candidates for being
1272 // released on an unloading notification.
1273 m_SetLoadedFactories
.insert( ret
);
1276 catch (InvalidRegistryException
&)
1284 * Return all implementation out of the registry.
1286 Sequence
<OUString
> ORegistryServiceManager::getFromServiceName(
1287 std::u16string_view serviceName
) const
1289 OUString buf
= OUString::Concat("/SERVICES/") + serviceName
;
1290 return retrieveAsciiValueList( m_xRegistry
, buf
);
1294 * Create a service provider from the registry
1296 Reference
<XInterface
> ORegistryServiceManager::loadWithServiceName(
1297 std::u16string_view serviceName
, Reference
< XComponentContext
> const & xContext
)
1299 const Sequence
<OUString
> implEntries
= getFromServiceName( serviceName
);
1300 for (const auto& rEntry
: implEntries
)
1302 Reference
< XInterface
> x( loadWithImplementationName( rEntry
, xContext
) );
1307 return Reference
<XInterface
>();
1311 * Return a sequence of all service names from the registry.
1313 void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString
& rSet
)
1315 Reference
<XRegistryKey
> xRootKey
= getRootKey();
1316 if( !xRootKey
.is() )
1321 Reference
<XRegistryKey
> xServicesKey
= xRootKey
->openKey( "SERVICES" );
1322 // root + /Services + /
1323 if( xServicesKey
.is() )
1325 sal_Int32 nPrefix
= xServicesKey
->getKeyName().getLength() +1;
1326 const Sequence
<Reference
<XRegistryKey
> > aKeys
= xServicesKey
->openKeys();
1327 std::transform(aKeys
.begin(), aKeys
.end(), std::inserter(rSet
, rSet
.end()),
1328 [nPrefix
](const Reference
<XRegistryKey
>& rKey
) -> OUString
{
1329 return rKey
->getKeyName().copy( nPrefix
); });
1332 catch (InvalidRegistryException
&)
1338 void ORegistryServiceManager::initialize(const Sequence
< Any
>& Arguments
)
1341 MutexGuard
aGuard( m_aMutex
);
1342 if (Arguments
.hasElements())
1345 Arguments
[ 0 ] >>= m_xRegistry
;
1347 #if OSL_DEBUG_LEVEL > 0
1348 // to find all bootstrapping processes to be fixed...
1349 OSL_ENSURE( !m_init
, "### second init of service manager instance!" );
1354 // XMultiServiceFactory, XContentEnumeration
1355 Sequence
< OUString
> ORegistryServiceManager::getAvailableServiceNames()
1358 MutexGuard
aGuard( m_aMutex
);
1360 HashSet_OWString aNameSet
;
1362 // all names from the registry
1363 fillAllNamesFromRegistry( aNameSet
);
1365 return OServiceManager::getUniqueAvailableServiceNames( aNameSet
);
1369 Sequence
< OUString
> ORegistryServiceManager::getSupportedServiceNames()
1371 return { "com.sun.star.lang.MultiServiceFactory", "com.sun.star.lang.RegistryServiceManager" };
1376 Sequence
< Reference
< XInterface
> > ORegistryServiceManager::queryServiceFactories(
1377 const OUString
& aServiceName
, Reference
< XComponentContext
> const & xContext
)
1379 Sequence
< Reference
< XInterface
> > ret(
1380 OServiceManager::queryServiceFactories( aServiceName
, xContext
) );
1381 if (ret
.hasElements())
1387 MutexGuard
aGuard( m_aMutex
);
1388 Reference
< XInterface
> x( loadWithServiceName( aServiceName
, xContext
) );
1390 x
= loadWithImplementationName( aServiceName
, xContext
);
1391 return Sequence
< Reference
< XInterface
> >( &x
, 1 );
1395 // XContentEnumerationAccess
1396 Reference
<XEnumeration
> ORegistryServiceManager::createContentEnumeration(
1397 const OUString
& aServiceName
)
1400 MutexGuard
aGuard(m_aMutex
);
1401 // get all implementation names registered under this service name from the registry
1402 const Sequence
<OUString
> aImpls
= getFromServiceName( aServiceName
);
1403 // load and insert all factories specified by the registry
1404 for( const OUString
& aImplName
: aImpls
)
1406 if ( !haveFactoryWithThisImplementation(aImplName
) )
1408 loadWithImplementationName( aImplName
, m_xContext
);
1411 // call the superclass to enumerate all contents
1412 return OServiceManager::createContentEnumeration( aServiceName
);
1416 Reference
<XPropertySetInfo
> ORegistryServiceManager::getPropertySetInfo()
1419 if (! m_xPropertyInfo
.is())
1421 Sequence
< beans::Property
> seq
{
1422 beans::Property("DefaultContext", -1, cppu::UnoType
<decltype(m_xContext
)>::get(), 0),
1423 beans::Property("Registry", -1, cppu::UnoType
<decltype(m_xRegistry
)>::get(),
1424 beans::PropertyAttribute::READONLY
)
1426 Reference
< beans::XPropertySetInfo
> xInfo( new PropertySetInfo_Impl( seq
) );
1428 MutexGuard
aGuard( m_aMutex
);
1429 if (! m_xPropertyInfo
.is())
1431 m_xPropertyInfo
= xInfo
;
1434 return m_xPropertyInfo
;
1437 Any
ORegistryServiceManager::getPropertyValue(const OUString
& PropertyName
)
1440 if ( PropertyName
== "Registry" )
1442 MutexGuard
aGuard( m_aMutex
);
1443 if( m_xRegistry
.is() )
1444 return Any( m_xRegistry
);
1448 return OServiceManager::getPropertyValue( PropertyName
);
1453 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1454 com_sun_star_comp_stoc_OServiceManager_get_implementation(
1455 css::uno::XComponentContext
*context
,
1456 css::uno::Sequence
<css::uno::Any
> const &)
1458 return cppu::acquire(new OServiceManager(context
));
1461 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1462 com_sun_star_comp_stoc_ORegistryServiceManager_get_implementation(
1463 css::uno::XComponentContext
*context
,
1464 css::uno::Sequence
<css::uno::Any
> const &)
1466 return cppu::acquire(new ORegistryServiceManager(context
));
1469 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1470 com_sun_star_comp_stoc_OServiceManagerWrapper_get_implementation(
1471 css::uno::XComponentContext
*context
,
1472 css::uno::Sequence
<css::uno::Any
> const &)
1474 return cppu::acquire(new OServiceManagerWrapper(context
));
1477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */