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/.
12 #include <sal/config.h>
17 #include <string_view>
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/beans/XPropertySetInfo.hpp>
22 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
23 #include <com/sun/star/container/XSet.hpp>
24 #include <com/sun/star/lang/XEventListener.hpp>
25 #include <com/sun/star/lang/XInitialization.hpp>
26 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <cppuhelper/basemutex.hxx>
31 #include <cppuhelper/compbase.hxx>
32 #include <osl/mutex.hxx>
33 #include <rtl/ustring.hxx>
35 namespace com::sun::star::lang
{
36 class XSingleComponentFactory
;
38 namespace cppu
{ struct ContextEntry_Init
; }
39 namespace com :: sun :: star :: lang
{ class XSingleServiceFactory
; }
40 namespace com :: sun :: star :: uno
{ class XComponentContext
; }
44 namespace cppuhelper
{
48 typedef css::uno::XInterface
* ImplementationConstructorFn(
49 css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const &);
53 typedef std::function
<css::uno::XInterface
* (css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const&)> WrapperConstructorFn
;
55 typedef cppu::WeakComponentImplHelper
<
56 css::lang::XServiceInfo
, css::lang::XMultiServiceFactory
,
57 css::lang::XMultiComponentFactory
, css::container::XSet
,
58 css::container::XContentEnumerationAccess
, css::beans::XPropertySet
,
59 css::beans::XPropertySetInfo
, css::lang::XEventListener
,
60 css::lang::XInitialization
>
64 private cppu::BaseMutex
, public ServiceManagerBase
69 Data(const Data
&) = delete;
70 const Data
& operator=(const Data
&) = delete;
72 struct Implementation
{
74 OUString
const & theName
, OUString
const & theLoader
,
75 OUString
const & theUri
, OUString
const & theEnvironment
,
76 OUString
const & theConstructorName
,
77 OUString
const & thePrefix
,
78 bool theIsSingleInstance
,
79 css::uno::Reference
< css::uno::XComponentContext
> const &
81 OUString
const & theRdbFile
):
82 name(theName
), loader(theLoader
), uri(theUri
), environment(theEnvironment
),
83 constructorName(theConstructorName
), prefix(thePrefix
),
84 isSingleInstance(theIsSingleInstance
),
85 alienContext(theAlienContext
), rdbFile(theRdbFile
),
86 constructorFn(nullptr), status(STATUS_NEW
), dispose(true)
90 OUString
const & theName
,
91 css::uno::Reference
< css::lang::XSingleComponentFactory
>
93 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
95 css::uno::Reference
< css::lang::XComponent
> const &
97 name(theName
), isSingleInstance(false), constructorFn(nullptr),
98 factory1(theFactory1
), factory2(theFactory2
),
99 component(theComponent
), status(STATUS_LOADED
), dispose(true)
100 { assert(theFactory1
.is() || theFactory2
.is()); }
102 Implementation(const Implementation
&) = delete;
103 const Implementation
& operator=(const Implementation
&) = delete;
105 css::uno::Reference
<css::uno::XInterface
> createInstance(
106 css::uno::Reference
<css::uno::XComponentContext
> const &
108 bool singletonRequest
);
110 css::uno::Reference
<css::uno::XInterface
>
111 createInstanceWithArguments(
112 css::uno::Reference
<css::uno::XComponentContext
> const &
114 bool singletonRequest
,
115 css::uno::Sequence
<css::uno::Any
> const & arguments
);
117 bool shallDispose() const { return isSingleInstance
|| !singletons
.empty(); }
119 enum Status
{ STATUS_NEW
, STATUS_WRAPPER
, STATUS_LOADED
};
121 // Logically, exactly one of constructorFn, factory1, factory2 should
122 // be set. However, there are two exceptions: For one, when
123 // constructorFn is set, ServiceManager::createContentEnumeration will
124 // store the necessary ImplementationWrapper in factory1 (so that
125 // multiple calls to createContentEnumeration will return the same
126 // wrapper). For another, when factory1 should be set but status is
127 // STATUS_NEW, factory1 is not yet set (and when status is
128 // STATUS_WRAPPER, factory1 is merely set to an
129 // ImplementationWrapper---also due to a
130 // ServiceManager::createContentEnumeration call---and will be
135 OUString environment
;
136 OUString constructorName
;
138 bool isSingleInstance
;
139 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
141 std::vector
< OUString
> services
;
142 std::vector
< OUString
> singletons
;
143 WrapperConstructorFn constructorFn
;
144 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1
;
145 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2
;
146 css::uno::Reference
< css::lang::XComponent
> component
;
150 css::uno::Reference
<css::uno::XInterface
> singleInstance
;
151 css::uno::Reference
< css::lang::XComponent
> disposeInstance
;
155 css::uno::Reference
<css::uno::XInterface
> doCreateInstance(
156 css::uno::Reference
<css::uno::XComponentContext
> const & context
);
158 css::uno::Reference
<css::uno::XInterface
> doCreateInstanceWithArguments(
159 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
160 css::uno::Sequence
<css::uno::Any
> const & arguments
);
162 void updateDisposeInstance(
163 bool singletonRequest
,
164 css::uno::Reference
<css::uno::XInterface
> const & instance
);
167 typedef std::map
< OUString
, std::shared_ptr
< Implementation
> >
168 NamedImplementations
;
172 css::uno::Reference
< css::lang::XServiceInfo
>,
173 std::shared_ptr
< Implementation
> >
174 DynamicImplementations
;
179 std::vector
< std::shared_ptr
< Implementation
> > >
182 NamedImplementations namedImplementations
;
183 DynamicImplementations dynamicImplementations
;
184 ImplementationMap services
;
185 ImplementationMap singletons
;
188 ServiceManager(): ServiceManagerBase(m_aMutex
) {}
190 ServiceManager(const ServiceManager
&) = delete;
191 const ServiceManager
& operator=(const ServiceManager
&) = delete;
193 using ServiceManagerBase::acquire
;
194 using ServiceManagerBase::release
;
196 void init(OUString
const & rdbUris
);
199 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
201 assert(context
.is());
202 assert(!context_
.is());
206 void addSingletonContextEntries(
207 std::vector
< cppu::ContextEntry_Init
> * entries
);
209 css::uno::Reference
< css::uno::XComponentContext
> const & getContext()
212 assert(context_
.is());
216 void loadImplementation(
217 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
218 std::shared_ptr
< Data::Implementation
> const & implementation
);
221 virtual ~ServiceManager() override
;
223 virtual void SAL_CALL
disposing() override
;
225 virtual OUString SAL_CALL
getImplementationName() override
;
227 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
;
229 virtual css::uno::Sequence
< OUString
> SAL_CALL
230 getSupportedServiceNames() override
;
232 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
createInstance(
233 OUString
const & aServiceSpecifier
) override
;
235 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
236 createInstanceWithArguments(
237 OUString
const & ServiceSpecifier
,
238 css::uno::Sequence
< css::uno::Any
> const & Arguments
) override
;
240 virtual css::uno::Sequence
< OUString
> SAL_CALL
241 getAvailableServiceNames() override
;
243 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
244 createInstanceWithContext(
245 OUString
const & aServiceSpecifier
,
246 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
248 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
249 createInstanceWithArgumentsAndContext(
250 OUString
const & ServiceSpecifier
,
251 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
252 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
254 virtual css::uno::Type SAL_CALL
getElementType() override
;
256 virtual sal_Bool SAL_CALL
hasElements() override
;
258 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
259 createEnumeration() override
;
261 virtual sal_Bool SAL_CALL
has(css::uno::Any
const & aElement
) override
;
263 virtual void SAL_CALL
insert(css::uno::Any
const & aElement
) override
;
265 virtual void SAL_CALL
remove(css::uno::Any
const & aElement
) override
;
267 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
268 createContentEnumeration(OUString
const & aServiceName
) override
;
270 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
271 getPropertySetInfo() override
;
273 virtual void SAL_CALL
setPropertyValue(
274 OUString
const & aPropertyName
, css::uno::Any
const & aValue
) override
;
276 virtual css::uno::Any SAL_CALL
getPropertyValue(
277 OUString
const & PropertyName
) override
;
279 virtual void SAL_CALL
addPropertyChangeListener(
280 OUString
const & aPropertyName
,
281 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
284 virtual void SAL_CALL
removePropertyChangeListener(
285 OUString
const & aPropertyName
,
286 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
289 virtual void SAL_CALL
addVetoableChangeListener(
290 OUString
const & PropertyName
,
291 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
294 virtual void SAL_CALL
removeVetoableChangeListener(
295 OUString
const & PropertyName
,
296 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
299 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties() override
;
301 virtual css::beans::Property SAL_CALL
getPropertyByName(
302 OUString
const & aName
) override
;
304 virtual sal_Bool SAL_CALL
hasPropertyByName(OUString
const & Name
) override
;
306 virtual void SAL_CALL
disposing(css::lang::EventObject
const & Source
) override
;
308 virtual void SAL_CALL
initialize(
309 css::uno::Sequence
<css::uno::Any
> const & aArguments
)
312 // needs to be called with rBHelper.rMutex locked:
313 bool isDisposed() const { return rBHelper
.bDisposed
|| rBHelper
.bInDispose
; }
315 void removeEventListenerFromComponent(
316 css::uno::Reference
< css::lang::XComponent
> const & component
);
318 void readRdbDirectory(OUString
const & uri
, bool optional
);
320 void readRdbFile(OUString
const & uri
, bool optional
);
322 bool readLegacyRdbFile(OUString
const & uri
);
324 OUString
readLegacyRdbString(
325 std::u16string_view uri
, RegistryKey
& key
,
326 OUString
const & path
);
328 void readLegacyRdbStrings(
329 std::u16string_view uri
, RegistryKey
& key
,
330 OUString
const & path
, std::vector
< OUString
> * strings
);
333 std::vector
< OUString
> const & uris
,
334 css::uno::Reference
< css::uno::XComponentContext
> const &
337 void insertLegacyFactory(
338 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
);
340 bool insertExtraData(Data
const & extra
);
342 void removeRdbFiles(std::vector
< OUString
> const & uris
);
344 bool removeLegacyFactory(
345 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
346 bool removeListener
);
348 void removeImplementation(const OUString
& name
);
350 std::shared_ptr
< Data::Implementation
> findServiceImplementation(
351 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
352 OUString
const & specifier
);
354 void preloadImplementations();
356 css::uno::Reference
< css::uno::XComponentContext
> context_
;
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */