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>
18 #include <string_view>
19 #include <unordered_map>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/beans/XPropertySetInfo.hpp>
25 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
26 #include <com/sun/star/container/XSet.hpp>
27 #include <com/sun/star/lang/XEventListener.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/uno/Reference.hxx>
33 #include <compbase2.hxx>
34 #include <rtl/ustring.hxx>
36 namespace com::sun::star::lang
{
37 class XSingleComponentFactory
;
39 namespace cppu
{ struct ContextEntry_Init
; }
40 namespace com :: sun :: star :: lang
{ class XSingleServiceFactory
; }
41 namespace com :: sun :: star :: uno
{ class XComponentContext
; }
45 namespace cppuhelper
{
49 typedef css::uno::XInterface
* ImplementationConstructorFn(
50 css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const &);
54 typedef std::function
<css::uno::XInterface
* (css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const&)> WrapperConstructorFn
;
56 typedef WeakComponentImplHelper2
<
57 css::lang::XServiceInfo
, css::lang::XMultiServiceFactory
,
58 css::lang::XMultiComponentFactory
, css::container::XSet
,
59 css::container::XContentEnumerationAccess
, css::beans::XPropertySet
,
60 css::beans::XPropertySetInfo
, css::lang::XEventListener
,
61 css::lang::XInitialization
>
64 class ServiceManager
: public ServiceManagerBase
69 Data(const Data
&) = delete;
70 const Data
& operator=(const Data
&) = delete;
72 struct Implementation
{
74 OUString theName
, OUString theLoader
,
75 OUString theUri
, OUString theEnvironment
,
76 OUString theConstructorName
,
78 bool theIsSingleInstance
,
79 css::uno::Reference
< css::uno::XComponentContext
> theAlienContext
,
81 name(std::move(theName
)), loader(std::move(theLoader
)), uri(std::move(theUri
)), environment(std::move(theEnvironment
)),
82 constructorName(std::move(theConstructorName
)), prefix(std::move(thePrefix
)),
83 isSingleInstance(theIsSingleInstance
),
84 alienContext(std::move(theAlienContext
)), rdbFile(std::move(theRdbFile
)),
85 constructorFn(nullptr), status(STATUS_NEW
), dispose(true)
90 css::uno::Reference
< css::lang::XSingleComponentFactory
>
92 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
94 css::uno::Reference
< css::lang::XComponent
> theComponent
):
95 name(std::move(theName
)), isSingleInstance(false), constructorFn(nullptr),
96 factory1(theFactory1
), factory2(theFactory2
),
97 component(std::move(theComponent
)), status(STATUS_LOADED
), dispose(true)
98 { assert(theFactory1
.is() || theFactory2
.is()); }
100 Implementation(const Implementation
&) = delete;
101 const Implementation
& operator=(const Implementation
&) = delete;
103 css::uno::Reference
<css::uno::XInterface
> createInstance(
104 css::uno::Reference
<css::uno::XComponentContext
> const &
106 bool singletonRequest
);
108 css::uno::Reference
<css::uno::XInterface
>
109 createInstanceWithArguments(
110 css::uno::Reference
<css::uno::XComponentContext
> const &
112 bool singletonRequest
,
113 css::uno::Sequence
<css::uno::Any
> const & arguments
);
115 bool shallDispose() const { return isSingleInstance
|| !singletons
.empty(); }
117 enum Status
{ STATUS_NEW
, STATUS_WRAPPER
, STATUS_LOADED
};
119 // Logically, exactly one of constructorFn, factory1, factory2 should
120 // be set. However, there are two exceptions: For one, when
121 // constructorFn is set, ServiceManager::createContentEnumeration will
122 // store the necessary ImplementationWrapper in factory1 (so that
123 // multiple calls to createContentEnumeration will return the same
124 // wrapper). For another, when factory1 should be set but status is
125 // STATUS_NEW, factory1 is not yet set (and when status is
126 // STATUS_WRAPPER, factory1 is merely set to an
127 // ImplementationWrapper---also due to a
128 // ServiceManager::createContentEnumeration call---and will be
133 OUString environment
;
134 OUString constructorName
;
136 bool isSingleInstance
;
137 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
139 std::vector
< OUString
> services
;
140 std::vector
< OUString
> singletons
;
141 WrapperConstructorFn constructorFn
;
142 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1
;
143 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2
;
144 css::uno::Reference
< css::lang::XComponent
> component
;
148 css::uno::Reference
<css::uno::XInterface
> singleInstance
;
149 css::uno::Reference
< css::lang::XComponent
> disposeInstance
;
153 css::uno::Reference
<css::uno::XInterface
> doCreateInstance(
154 css::uno::Reference
<css::uno::XComponentContext
> const & context
);
156 css::uno::Reference
<css::uno::XInterface
> doCreateInstanceWithArguments(
157 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
158 css::uno::Sequence
<css::uno::Any
> const & arguments
);
160 void updateDisposeInstance(
161 bool singletonRequest
,
162 css::uno::Reference
<css::uno::XInterface
> const & instance
);
165 typedef std::unordered_map
< OUString
, std::shared_ptr
< Implementation
> >
166 NamedImplementations
;
170 css::uno::Reference
< css::lang::XServiceInfo
>,
171 std::shared_ptr
< Implementation
> >
172 DynamicImplementations
;
177 std::vector
< std::shared_ptr
< Implementation
> > >
180 NamedImplementations namedImplementations
;
181 DynamicImplementations dynamicImplementations
;
182 ImplementationMap services
;
183 ImplementationMap singletons
;
188 ServiceManager(const ServiceManager
&) = delete;
189 const ServiceManager
& operator=(const ServiceManager
&) = delete;
191 using ServiceManagerBase::acquire
;
192 using ServiceManagerBase::release
;
194 void init(std::u16string_view rdbUris
);
197 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
199 assert(context
.is());
200 assert(!context_
.is());
204 void addSingletonContextEntries(
205 std::vector
< cppu::ContextEntry_Init
> * entries
);
207 css::uno::Reference
< css::uno::XComponentContext
> const & getContext()
210 assert(context_
.is());
214 void loadImplementation(
215 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
216 std::shared_ptr
< Data::Implementation
> const & implementation
);
219 virtual ~ServiceManager() override
;
221 virtual void disposing(std::unique_lock
<std::mutex
>&) override
;
223 virtual OUString SAL_CALL
getImplementationName() override
;
225 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
;
227 virtual css::uno::Sequence
< OUString
> SAL_CALL
228 getSupportedServiceNames() override
;
230 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
createInstance(
231 OUString
const & aServiceSpecifier
) override
;
233 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
234 createInstanceWithArguments(
235 OUString
const & ServiceSpecifier
,
236 css::uno::Sequence
< css::uno::Any
> const & Arguments
) override
;
238 virtual css::uno::Sequence
< OUString
> SAL_CALL
239 getAvailableServiceNames() override
;
241 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
242 createInstanceWithContext(
243 OUString
const & aServiceSpecifier
,
244 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
246 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
247 createInstanceWithArgumentsAndContext(
248 OUString
const & ServiceSpecifier
,
249 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
250 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
252 virtual css::uno::Type SAL_CALL
getElementType() override
;
254 virtual sal_Bool SAL_CALL
hasElements() override
;
256 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
257 createEnumeration() override
;
259 virtual sal_Bool SAL_CALL
has(css::uno::Any
const & aElement
) override
;
261 virtual void SAL_CALL
insert(css::uno::Any
const & aElement
) override
;
263 virtual void SAL_CALL
remove(css::uno::Any
const & aElement
) override
;
265 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
266 createContentEnumeration(OUString
const & aServiceName
) override
;
268 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
269 getPropertySetInfo() override
;
271 virtual void SAL_CALL
setPropertyValue(
272 OUString
const & aPropertyName
, css::uno::Any
const & aValue
) override
;
274 virtual css::uno::Any SAL_CALL
getPropertyValue(
275 OUString
const & PropertyName
) override
;
277 virtual void SAL_CALL
addPropertyChangeListener(
278 OUString
const & aPropertyName
,
279 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
282 virtual void SAL_CALL
removePropertyChangeListener(
283 OUString
const & aPropertyName
,
284 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
287 virtual void SAL_CALL
addVetoableChangeListener(
288 OUString
const & PropertyName
,
289 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
292 virtual void SAL_CALL
removeVetoableChangeListener(
293 OUString
const & PropertyName
,
294 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
297 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties() override
;
299 virtual css::beans::Property SAL_CALL
getPropertyByName(
300 OUString
const & aName
) override
;
302 virtual sal_Bool SAL_CALL
hasPropertyByName(OUString
const & Name
) override
;
304 virtual void SAL_CALL
disposing(css::lang::EventObject
const & Source
) override
;
306 virtual void SAL_CALL
initialize(
307 css::uno::Sequence
<css::uno::Any
> const & aArguments
)
310 void removeEventListenerFromComponent(
311 css::uno::Reference
< css::lang::XComponent
> const & component
);
313 void readRdbDirectory(std::u16string_view uri
, bool optional
);
315 void readRdbFile(OUString
const & uri
, bool optional
);
317 bool readLegacyRdbFile(OUString
const & uri
);
319 OUString
readLegacyRdbString(
320 std::u16string_view uri
, RegistryKey
& key
,
321 OUString
const & path
);
323 void readLegacyRdbStrings(
324 std::u16string_view uri
, RegistryKey
& key
,
325 OUString
const & path
, std::vector
< OUString
> * strings
);
328 std::vector
< OUString
> const & uris
,
329 css::uno::Reference
< css::uno::XComponentContext
> const &
332 void insertLegacyFactory(
333 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
);
335 bool insertExtraData(Data
const & extra
);
337 void removeRdbFiles(std::vector
< OUString
> const & uris
);
339 bool removeLegacyFactory(
340 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
341 bool removeListener
);
343 void removeImplementation(const OUString
& name
);
345 std::shared_ptr
< Data::Implementation
> findServiceImplementation(
346 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
347 OUString
const & specifier
);
349 void preloadImplementations();
351 css::uno::Reference
< css::uno::XComponentContext
> context_
;
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */