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>
34 #include <rtl/ref.hxx>
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>
56 #include <string_view>
57 #include <unordered_map>
58 #include <unordered_set>
61 using namespace com::sun::star
;
62 using namespace css::uno
;
63 using namespace css::beans
;
64 using namespace css::registry
;
65 using namespace css::lang
;
66 using namespace css::container
;
72 Sequence
< OUString
> retrieveAsciiValueList(
73 const Reference
< XSimpleRegistry
> &xReg
, const OUString
&keyName
)
75 Reference
< XEnumerationAccess
> xAccess( xReg
, UNO_QUERY
);
76 Sequence
< OUString
> seq
;
79 Reference
< XEnumeration
> xEnum
= xAccess
->createEnumeration();
80 while( xEnum
.is() && xEnum
->hasMoreElements() )
82 Reference
< XSimpleRegistry
> xTempReg
;
83 xEnum
->nextElement() >>= xTempReg
;
86 const Sequence
< OUString
> seq2
= retrieveAsciiValueList( xTempReg
, keyName
);
88 if( seq2
.hasElements() )
90 sal_Int32 n1Len
= seq
.getLength();
91 sal_Int32 n2Len
= seq2
.getLength();
93 seq
.realloc( n1Len
+ n2Len
);
94 std::copy(seq2
.begin(), seq2
.end(), std::next(seq
.getArray(), n1Len
));
103 Reference
< XRegistryKey
> rRootKey
= xReg
->getRootKey();
106 Reference
<XRegistryKey
> xKey
= rRootKey
->openKey(keyName
);
109 seq
= xKey
->getAsciiListValue();
113 catch( InvalidRegistryException
& )
116 catch (InvalidValueException
&)
123 /*****************************************************************************
124 Enumeration by ServiceName
125 *****************************************************************************/
127 typedef std::unordered_set
< Reference
<XInterface
> > HashSet_Ref
;
130 class ServiceEnumeration_Impl
: public WeakImplHelper
< XEnumeration
>
133 explicit ServiceEnumeration_Impl( const Sequence
< Reference
<XInterface
> > & rFactories
)
134 : aFactories( rFactories
)
139 sal_Bool SAL_CALL
hasMoreElements() override
;
140 Any SAL_CALL
nextElement() override
;
143 Sequence
< Reference
<XInterface
> > aFactories
;
148 sal_Bool
ServiceEnumeration_Impl::hasMoreElements()
150 std::scoped_lock
aGuard( aMutex
);
151 return nIt
!= aFactories
.getLength();
155 Any
ServiceEnumeration_Impl::nextElement()
157 std::scoped_lock
aGuard( aMutex
);
158 if( nIt
== aFactories
.getLength() )
159 throw NoSuchElementException(u
"no more elements"_ustr
);
161 return Any( &aFactories
[nIt
++], cppu::UnoType
<XInterface
>::get());
165 class PropertySetInfo_Impl
: public WeakImplHelper
< beans::XPropertySetInfo
>
167 Sequence
< beans::Property
> m_properties
;
170 explicit PropertySetInfo_Impl( Sequence
< beans::Property
> const & properties
)
171 : m_properties( properties
)
174 // XPropertySetInfo impl
175 virtual Sequence
< beans::Property
> SAL_CALL
getProperties() override
;
176 virtual beans::Property SAL_CALL
getPropertyByName( OUString
const & name
) override
;
177 virtual sal_Bool SAL_CALL
hasPropertyByName( OUString
const & name
) override
;
180 Sequence
< beans::Property
> PropertySetInfo_Impl::getProperties()
185 beans::Property
PropertySetInfo_Impl::getPropertyByName( OUString
const & name
)
187 for ( sal_Int32 nPos
= m_properties
.getLength(); nPos
--; )
189 if (m_properties
[nPos
].Name
== name
)
190 return m_properties
[nPos
];
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(u
"no more elements"_ustr
);
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 rtl::Reference
<OServiceManager_Listener
> 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 u
"service manager instance has already been disposed!"_ustr
,
416 const_cast<OServiceManager
*>(this)->getXWeak() );
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 u
"service manager instance has already been disposed!"_ustr
);
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 u
"no XComponentContext given!"_ustr
,
528 MutexGuard
aGuard( m_aMutex
);
529 m_xContext
= std::move(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 u
"no service manager to wrap"_ustr
);
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 u
"DefaultContext"_ustr
, -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
= std::move(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
,
665 Reference
< XComponentContext
> xContext
;
666 if (!(aValue
>>= xContext
))
668 throw IllegalArgumentException(
669 u
"no XComponentContext given!"_ustr
,
673 MutexGuard
aGuard( m_aMutex
);
674 m_xContext
= std::move(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("ServiceManager : unknown property " + PropertyName
, {});
695 void OServiceManager::addPropertyChangeListener(
696 const OUString
&, const Reference
<XPropertyChangeListener
>&)
699 throw UnknownPropertyException(u
"unsupported"_ustr
);
702 void OServiceManager::removePropertyChangeListener(
703 const OUString
&, const Reference
<XPropertyChangeListener
>&)
706 throw UnknownPropertyException(u
"unsupported"_ustr
);
709 void OServiceManager::addVetoableChangeListener(
710 const OUString
&, const Reference
<XVetoableChangeListener
>&)
713 throw UnknownPropertyException(u
"unsupported"_ustr
);
716 void OServiceManager::removeVetoableChangeListener(
717 const OUString
&, const Reference
<XVetoableChangeListener
>&)
720 throw UnknownPropertyException(u
"unsupported"_ustr
);
724 Reference
<XEventListener
> OServiceManager::getFactoryListener()
727 MutexGuard
aGuard( m_aMutex
);
728 if( !xFactoryListener
.is() )
729 xFactoryListener
= new OServiceManager_Listener( this );
730 return xFactoryListener
;
733 // XMultiServiceFactory, XContentEnumeration
734 Sequence
< OUString
> OServiceManager::getUniqueAvailableServiceNames(
735 HashSet_OWString
& aNameSet
)
738 MutexGuard
aGuard( m_aMutex
);
739 for( const auto& rEntry
: m_ServiceMap
)
740 aNameSet
.insert( rEntry
.first
);
742 /* do not return the implementation names
743 HashMap_OWString_Interface m_ImplementationNameMap;
744 HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin();
745 while( aIt != m_ImplementationNameMap.end() )
746 aNameSet.insert( (*aIt++).first );
749 return comphelper::containerToSequence(aNameSet
);
752 // XMultiComponentFactory
753 Reference
< XInterface
> OServiceManager::createInstanceWithContext(
754 OUString
const & rServiceSpecifier
,
755 Reference
< XComponentContext
> const & xContext
)
758 #if OSL_DEBUG_LEVEL > 0
759 Reference
< beans::XPropertySet
> xProps( xContext
->getServiceManager(), UNO_QUERY
);
760 OSL_ASSERT( xProps
.is() );
763 Reference
< XComponentContext
> xDefContext
;
764 xProps
->getPropertyValue( u
"DefaultContext"_ustr
) >>= xDefContext
;
766 xContext
== xDefContext
,
767 "### default context of service manager singleton differs from context holding it!" );
771 const Sequence
< Reference
< XInterface
> > factories(
772 queryServiceFactories( rServiceSpecifier
, xContext
) );
773 for ( Reference
< XInterface
> const & xFactory
: factories
)
779 Reference
< XSingleComponentFactory
> xFac( xFactory
, UNO_QUERY
);
782 return xFac
->createInstanceWithContext( xContext
);
786 Reference
< XSingleServiceFactory
> xFac2( xFactory
, UNO_QUERY
);
789 SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier
<< "!!!");
790 return xFac2
->createInstance();
795 catch (const lang::DisposedException
& exc
)
797 SAL_INFO("stoc", "DisposedException occurred: " << exc
);
801 return Reference
< XInterface
>();
803 // XMultiComponentFactory
804 Reference
< XInterface
> OServiceManager::createInstanceWithArgumentsAndContext(
805 OUString
const & rServiceSpecifier
,
806 Sequence
< Any
> const & rArguments
,
807 Reference
< XComponentContext
> const & xContext
)
810 #if OSL_DEBUG_LEVEL > 0
811 Reference
< beans::XPropertySet
> xProps( xContext
->getServiceManager(), UNO_QUERY
);
812 OSL_ASSERT( xProps
.is() );
815 Reference
< XComponentContext
> xDefContext
;
816 xProps
->getPropertyValue( u
"DefaultContext"_ustr
) >>= xDefContext
;
818 xContext
== xDefContext
,
819 "### default context of service manager singleton differs from context holding it!" );
823 const Sequence
< Reference
< XInterface
> > factories(
824 queryServiceFactories( rServiceSpecifier
, xContext
) );
825 for ( Reference
< XInterface
> const & xFactory
: factories
)
831 Reference
< XSingleComponentFactory
> xFac( xFactory
, UNO_QUERY
);
834 return xFac
->createInstanceWithArgumentsAndContext( rArguments
, xContext
);
838 Reference
< XSingleServiceFactory
> xFac2( xFactory
, UNO_QUERY
);
841 SAL_INFO("stoc", "ignoring given context raising service " << rServiceSpecifier
<< "!!!");
842 return xFac2
->createInstanceWithArguments( rArguments
);
847 catch (const lang::DisposedException
& exc
)
849 SAL_INFO("stoc", "DisposedException occurred: " << exc
);
853 return Reference
< XInterface
>();
856 // XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration
857 Sequence
< OUString
> OServiceManager::getAvailableServiceNames()
861 HashSet_OWString aNameSet
;
862 return getUniqueAvailableServiceNames( aNameSet
);
865 // XMultipleServiceFactory
866 Reference
<XInterface
> OServiceManager::createInstance(
867 const OUString
& rServiceSpecifier
)
869 return createInstanceWithContext(
870 rServiceSpecifier
, m_xContext
);
873 // XMultipleServiceFactory
874 Reference
<XInterface
> OServiceManager::createInstanceWithArguments(
875 const OUString
& rServiceSpecifier
,
876 const Sequence
<Any
>& rArguments
)
878 return createInstanceWithArgumentsAndContext(
879 rServiceSpecifier
, rArguments
, m_xContext
);
883 void OServiceManager::initialize( Sequence
< Any
> const & )
886 OSL_FAIL( "not impl!" );
890 OUString
OServiceManager::getImplementationName()
892 return u
"com.sun.star.comp.stoc.OServiceManager"_ustr
;
896 sal_Bool
OServiceManager::supportsService(const OUString
& ServiceName
)
898 return cppu::supportsService(this, ServiceName
);
902 Sequence
< OUString
> OServiceManager::getSupportedServiceNames()
904 return { u
"com.sun.star.lang.MultiServiceFactory"_ustr
, u
"com.sun.star.lang.ServiceManager"_ustr
};
908 Sequence
< Reference
< XInterface
> > OServiceManager::queryServiceFactories(
909 const OUString
& aServiceName
, Reference
< XComponentContext
> const & )
911 Sequence
< Reference
< XInterface
> > ret
;
913 MutexGuard
aGuard( m_aMutex
);
915 HashMultimap_OWString_Interface::iterator
,
916 HashMultimap_OWString_Interface::iterator
> p(
917 m_ServiceMap
.equal_range( aServiceName
) );
919 if (p
.first
== p
.second
) // no factories
921 // no service found, look for an implementation
922 HashMap_OWString_Interface::iterator aIt
= m_ImplementationNameMap
.find( aServiceName
);
923 if( aIt
!= m_ImplementationNameMap
.end() )
925 Reference
< XInterface
> const & x
= aIt
->second
;
926 // an implementation found
927 ret
= Sequence
< Reference
< XInterface
> >( &x
, 1 );
932 ::std::vector
< Reference
< XInterface
> > vec
;
934 while (p
.first
!= p
.second
)
936 vec
.push_back( p
.first
->second
);
939 ret
= Sequence
< Reference
< XInterface
> >( vec
.data(), vec
.size() );
945 // XContentEnumerationAccess
946 Reference
<XEnumeration
> OServiceManager::createContentEnumeration(
947 const OUString
& aServiceName
)
950 Sequence
< Reference
< XInterface
> > factories(
951 OServiceManager::queryServiceFactories( aServiceName
, m_xContext
) );
952 if (factories
.hasElements())
953 return new ServiceEnumeration_Impl( factories
);
955 return Reference
< XEnumeration
>();
959 Reference
<XEnumeration
> OServiceManager::createEnumeration()
962 MutexGuard
aGuard( m_aMutex
);
963 return new ImplementationEnumeration_Impl( m_ImplementationMap
);
967 Type
OServiceManager::getElementType()
970 return cppu::UnoType
<XInterface
>::get();
974 sal_Bool
OServiceManager::hasElements()
977 MutexGuard
aGuard( m_aMutex
);
978 return !m_ImplementationMap
.empty();
982 sal_Bool
OServiceManager::has( const Any
& Element
)
985 if( Element
.getValueTypeClass() == TypeClass_INTERFACE
)
987 Reference
<XInterface
> xEle( Element
, UNO_QUERY_THROW
);
988 MutexGuard
aGuard( m_aMutex
);
989 return m_ImplementationMap
.find( xEle
) !=
990 m_ImplementationMap
.end();
992 else if (auto implName
= o3tl::tryAccess
<OUString
>(Element
))
994 MutexGuard
aGuard( m_aMutex
);
995 return m_ImplementationNameMap
.find( *implName
) !=
996 m_ImplementationNameMap
.end();
1002 void OServiceManager::insert( const Any
& Element
)
1005 if( Element
.getValueTypeClass() != TypeClass_INTERFACE
)
1007 throw IllegalArgumentException(
1008 "exception interface, got " + Element
.getValueTypeName(),
1009 Reference
< XInterface
>(), 0 );
1011 Reference
<XInterface
> xEle( Element
, UNO_QUERY_THROW
);
1014 MutexGuard
aGuard( m_aMutex
);
1015 HashSet_Ref::iterator aIt
= m_ImplementationMap
.find( xEle
);
1016 if( aIt
!= m_ImplementationMap
.end() )
1018 throw ElementExistException( u
"element already exists!"_ustr
);
1021 // put into the implementation hashmap
1022 m_ImplementationMap
.insert( xEle
);
1024 // put into the implementation name hashmap
1025 Reference
<XServiceInfo
> xInfo( Reference
<XServiceInfo
>::query( xEle
) );
1028 OUString aImplName
= xInfo
->getImplementationName();
1029 if( !aImplName
.isEmpty() )
1030 m_ImplementationNameMap
[ aImplName
] = xEle
;
1032 //put into the service map
1033 const Sequence
< OUString
> aServiceNames
= xInfo
->getSupportedServiceNames();
1034 for( const OUString
& rServiceName
: aServiceNames
)
1036 m_ServiceMap
.emplace(
1037 rServiceName
, *o3tl::doAccess
<Reference
<XInterface
>>(Element
) );
1041 // add the disposing listener to the factory
1042 Reference
<XComponent
> xComp( Reference
<XComponent
>::query( xEle
) );
1044 xComp
->addEventListener( getFactoryListener() );
1048 bool OServiceManager::haveFactoryWithThisImplementation(const OUString
& aImplName
)
1050 return m_ImplementationNameMap
.contains(aImplName
);
1054 void OServiceManager::remove( const Any
& Element
)
1059 Reference
<XInterface
> xEle
;
1060 if (Element
.getValueTypeClass() == TypeClass_INTERFACE
)
1062 xEle
.set( Element
, UNO_QUERY_THROW
);
1064 else if (auto implName
= o3tl::tryAccess
<OUString
>(Element
))
1066 MutexGuard
aGuard( m_aMutex
);
1067 HashMap_OWString_Interface::const_iterator
const iFind(
1068 m_ImplementationNameMap
.find( *implName
) );
1069 if (iFind
== m_ImplementationNameMap
.end())
1071 throw NoSuchElementException(
1072 "element is not in: " + *implName
,
1075 xEle
= iFind
->second
;
1079 throw IllegalArgumentException(
1080 "expected interface or string, got " + Element
.getValueTypeName(),
1081 Reference
< XInterface
>(), 0 );
1084 // remove the disposing listener from the factory
1085 Reference
<XComponent
> xComp( Reference
<XComponent
>::query( xEle
) );
1087 xComp
->removeEventListener( getFactoryListener() );
1089 MutexGuard
aGuard( m_aMutex
);
1090 HashSet_Ref::iterator aIt
= m_ImplementationMap
.find( xEle
);
1091 if( aIt
== m_ImplementationMap
.end() )
1093 throw NoSuchElementException(
1094 u
"element not found"_ustr
,
1097 //First remove all factories which have been loaded by ORegistryServiceManager.
1098 m_SetLoadedFactories
.erase( *aIt
);
1099 //Remove from the implementation map. It contains all factories of m_SetLoadedFactories
1100 //which have been added directly through XSet, that is not via ORegistryServiceManager
1101 m_ImplementationMap
.erase( aIt
);
1103 // remove from the implementation name hashmap
1104 Reference
<XServiceInfo
> xInfo( Reference
<XServiceInfo
>::query( xEle
) );
1107 OUString aImplName
= xInfo
->getImplementationName();
1108 if( !aImplName
.isEmpty() )
1109 m_ImplementationNameMap
.erase( aImplName
);
1112 //remove from the service map
1113 Reference
<XServiceInfo
> xSF( Reference
<XServiceInfo
>::query( xEle
) );
1117 const Sequence
< OUString
> aServiceNames
= xSF
->getSupportedServiceNames();
1118 for( const OUString
& rServiceName
: aServiceNames
)
1120 std::pair
<HashMultimap_OWString_Interface::iterator
, HashMultimap_OWString_Interface::iterator
> p
=
1121 m_ServiceMap
.equal_range( rServiceName
);
1123 while( p
.first
!= p
.second
)
1125 if( xEle
== (*p
.first
).second
)
1127 m_ServiceMap
.erase( p
.first
);
1135 /*****************************************************************************
1136 class ORegistryServiceManager
1137 *****************************************************************************/
1138 class ORegistryServiceManager
: public OServiceManager
1141 explicit ORegistryServiceManager( Reference
< XComponentContext
> const & xContext
);
1144 void SAL_CALL
initialize(const Sequence
< Any
>& Arguments
) override
;
1147 OUString SAL_CALL
getImplementationName() override
1148 { return u
"com.sun.star.comp.stoc.ORegistryServiceManager"_ustr
; }
1150 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
1152 // XMultiServiceFactory
1153 Sequence
< OUString
> SAL_CALL
getAvailableServiceNames() override
;
1155 // XContentEnumerationAccess
1156 //Sequence< OUString > getAvailableServiceNames() throw( (Exception) );
1157 Reference
<XEnumeration
> SAL_CALL
createContentEnumeration(const OUString
& aServiceName
) override
;
1160 void SAL_CALL
dispose() override
;
1163 Reference
<XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
;
1164 Any SAL_CALL
getPropertyValue(const OUString
& PropertyName
) override
;
1168 Sequence
< Reference
< XInterface
> > queryServiceFactories(
1169 const OUString
& aServiceName
, Reference
< XComponentContext
> const & xContext
) override
;
1171 Reference
<XRegistryKey
> getRootKey();
1172 Reference
<XInterface
> loadWithImplementationName(
1173 const OUString
& rImplName
, Reference
< XComponentContext
> const & xContext
);
1174 Sequence
<OUString
> getFromServiceName(std::u16string_view serviceName
) const;
1175 Reference
<XInterface
> loadWithServiceName(
1176 std::u16string_view rImplName
, Reference
< XComponentContext
> const & xContext
);
1177 void fillAllNamesFromRegistry( HashSet_OWString
& );
1179 bool m_searchedRegistry
;
1180 Reference
<XSimpleRegistry
> m_xRegistry
; // readonly property Registry
1181 Reference
<XRegistryKey
> m_xRootKey
;
1183 #if OSL_DEBUG_LEVEL > 0
1189 * Create a ServiceManager
1191 ORegistryServiceManager::ORegistryServiceManager( Reference
< XComponentContext
> const & xContext
)
1192 : OServiceManager( xContext
)
1193 , m_searchedRegistry(false)
1194 #if OSL_DEBUG_LEVEL > 0
1201 void ORegistryServiceManager::dispose()
1203 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
1205 OServiceManager::dispose();
1207 MutexGuard
aGuard( m_aMutex
);
1208 // erase all members
1209 m_xRegistry
.clear();
1214 * Return the root key of the registry. The Default registry service is ordered
1215 * if no registry is set.
1217 //Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider();
1219 Reference
<XRegistryKey
> ORegistryServiceManager::getRootKey()
1221 if( !m_xRootKey
.is() )
1223 MutexGuard
aGuard( m_aMutex
);
1224 // DefaultRegistry suchen !!!!
1225 if( !m_xRegistry
.is() && !m_searchedRegistry
)
1227 // NB. we only search this once
1228 m_searchedRegistry
= true;
1231 createInstanceWithContext(
1232 u
"com.sun.star.registry.DefaultRegistry"_ustr
,
1236 if( m_xRegistry
.is() && !m_xRootKey
.is() )
1237 m_xRootKey
= m_xRegistry
->getRootKey();
1244 * Create a service provider from the registry with an implementation name
1246 Reference
<XInterface
> ORegistryServiceManager::loadWithImplementationName(
1247 const OUString
& name
, Reference
< XComponentContext
> const & xContext
)
1249 Reference
<XInterface
> ret
;
1251 Reference
<XRegistryKey
> xRootKey
= getRootKey();
1252 if( !xRootKey
.is() )
1257 OUString implementationName
= "/IMPLEMENTATIONS/" + name
;
1258 Reference
<XRegistryKey
> xImpKey
= m_xRootKey
->openKey(implementationName
);
1262 Reference
< lang::XMultiServiceFactory
> xMgr
;
1264 xMgr
.set( xContext
->getServiceManager(), UNO_QUERY_THROW
);
1267 ret
= createSingleRegistryFactory( xMgr
, name
, xImpKey
);
1268 insert( Any( ret
) );
1269 // Remember this factory as loaded in contrast to inserted ( XSet::insert)
1270 // factories. Those loaded factories in this set are candidates for being
1271 // released on an unloading notification.
1272 m_SetLoadedFactories
.insert( ret
);
1275 catch (InvalidRegistryException
&)
1283 * Return all implementation out of the registry.
1285 Sequence
<OUString
> ORegistryServiceManager::getFromServiceName(
1286 std::u16string_view serviceName
) const
1288 OUString buf
= OUString::Concat("/SERVICES/") + serviceName
;
1289 return retrieveAsciiValueList( m_xRegistry
, buf
);
1293 * Create a service provider from the registry
1295 Reference
<XInterface
> ORegistryServiceManager::loadWithServiceName(
1296 std::u16string_view serviceName
, Reference
< XComponentContext
> const & xContext
)
1298 const Sequence
<OUString
> implEntries
= getFromServiceName( serviceName
);
1299 for (const auto& rEntry
: implEntries
)
1301 Reference
< XInterface
> x( loadWithImplementationName( rEntry
, xContext
) );
1306 return Reference
<XInterface
>();
1310 * Return a sequence of all service names from the registry.
1312 void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString
& rSet
)
1314 Reference
<XRegistryKey
> xRootKey
= getRootKey();
1315 if( !xRootKey
.is() )
1320 Reference
<XRegistryKey
> xServicesKey
= xRootKey
->openKey( u
"SERVICES"_ustr
);
1321 // root + /Services + /
1322 if( xServicesKey
.is() )
1324 sal_Int32 nPrefix
= xServicesKey
->getKeyName().getLength() +1;
1325 const Sequence
<Reference
<XRegistryKey
> > aKeys
= xServicesKey
->openKeys();
1326 std::transform(aKeys
.begin(), aKeys
.end(), std::inserter(rSet
, rSet
.end()),
1327 [nPrefix
](const Reference
<XRegistryKey
>& rKey
) -> OUString
{
1328 return rKey
->getKeyName().copy( nPrefix
); });
1331 catch (InvalidRegistryException
&)
1337 void ORegistryServiceManager::initialize(const Sequence
< Any
>& Arguments
)
1340 MutexGuard
aGuard( m_aMutex
);
1341 if (Arguments
.hasElements())
1344 Arguments
[ 0 ] >>= m_xRegistry
;
1346 #if OSL_DEBUG_LEVEL > 0
1347 // to find all bootstrapping processes to be fixed...
1348 OSL_ENSURE( !m_init
, "### second init of service manager instance!" );
1353 // XMultiServiceFactory, XContentEnumeration
1354 Sequence
< OUString
> ORegistryServiceManager::getAvailableServiceNames()
1357 MutexGuard
aGuard( m_aMutex
);
1359 HashSet_OWString aNameSet
;
1361 // all names from the registry
1362 fillAllNamesFromRegistry( aNameSet
);
1364 return OServiceManager::getUniqueAvailableServiceNames( aNameSet
);
1368 Sequence
< OUString
> ORegistryServiceManager::getSupportedServiceNames()
1370 return { u
"com.sun.star.lang.MultiServiceFactory"_ustr
, u
"com.sun.star.lang.RegistryServiceManager"_ustr
};
1375 Sequence
< Reference
< XInterface
> > ORegistryServiceManager::queryServiceFactories(
1376 const OUString
& aServiceName
, Reference
< XComponentContext
> const & xContext
)
1378 Sequence
< Reference
< XInterface
> > ret(
1379 OServiceManager::queryServiceFactories( aServiceName
, xContext
) );
1380 if (ret
.hasElements())
1386 MutexGuard
aGuard( m_aMutex
);
1387 Reference
< XInterface
> x( loadWithServiceName( aServiceName
, xContext
) );
1389 x
= loadWithImplementationName( aServiceName
, xContext
);
1390 return Sequence
< Reference
< XInterface
> >( &x
, 1 );
1394 // XContentEnumerationAccess
1395 Reference
<XEnumeration
> ORegistryServiceManager::createContentEnumeration(
1396 const OUString
& aServiceName
)
1399 MutexGuard
aGuard(m_aMutex
);
1400 // get all implementation names registered under this service name from the registry
1401 const Sequence
<OUString
> aImpls
= getFromServiceName( aServiceName
);
1402 // load and insert all factories specified by the registry
1403 for( const OUString
& aImplName
: aImpls
)
1405 if ( !haveFactoryWithThisImplementation(aImplName
) )
1407 loadWithImplementationName( aImplName
, m_xContext
);
1410 // call the superclass to enumerate all contents
1411 return OServiceManager::createContentEnumeration( aServiceName
);
1415 Reference
<XPropertySetInfo
> ORegistryServiceManager::getPropertySetInfo()
1418 if (! m_xPropertyInfo
.is())
1420 Sequence
< beans::Property
> seq
{
1421 beans::Property(u
"DefaultContext"_ustr
, -1, cppu::UnoType
<decltype(m_xContext
)>::get(), 0),
1422 beans::Property(u
"Registry"_ustr
, -1, cppu::UnoType
<decltype(m_xRegistry
)>::get(),
1423 beans::PropertyAttribute::READONLY
)
1425 Reference
< beans::XPropertySetInfo
> xInfo( new PropertySetInfo_Impl( seq
) );
1427 MutexGuard
aGuard( m_aMutex
);
1428 if (! m_xPropertyInfo
.is())
1430 m_xPropertyInfo
= std::move(xInfo
);
1433 return m_xPropertyInfo
;
1436 Any
ORegistryServiceManager::getPropertyValue(const OUString
& PropertyName
)
1439 if ( PropertyName
== "Registry" )
1441 MutexGuard
aGuard( m_aMutex
);
1442 if( m_xRegistry
.is() )
1443 return Any( m_xRegistry
);
1447 return OServiceManager::getPropertyValue( PropertyName
);
1452 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1453 com_sun_star_comp_stoc_OServiceManager_get_implementation(
1454 css::uno::XComponentContext
*context
,
1455 css::uno::Sequence
<css::uno::Any
> const &)
1457 return cppu::acquire(new OServiceManager(context
));
1460 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1461 com_sun_star_comp_stoc_ORegistryServiceManager_get_implementation(
1462 css::uno::XComponentContext
*context
,
1463 css::uno::Sequence
<css::uno::Any
> const &)
1465 return cppu::acquire(new ORegistryServiceManager(context
));
1468 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1469 com_sun_star_comp_stoc_OServiceManagerWrapper_get_implementation(
1470 css::uno::XComponentContext
*context
,
1471 css::uno::Sequence
<css::uno::Any
> const &)
1473 return cppu::acquire(new OServiceManagerWrapper(context
));
1476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */