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>
35 #include <boost/container/small_vector.hpp>
37 namespace com::sun::star::lang
{
38 class XSingleComponentFactory
;
40 namespace cppu
{ struct ContextEntry_Init
; }
41 namespace com :: sun :: star :: lang
{ class XSingleServiceFactory
; }
42 namespace com :: sun :: star :: uno
{ class XComponentContext
; }
46 namespace cppuhelper
{
50 typedef css::uno::XInterface
* ImplementationConstructorFn(
51 css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const &);
55 typedef std::function
<css::uno::XInterface
* (css::uno::XComponentContext
*, css::uno::Sequence
<css::uno::Any
> const&)> WrapperConstructorFn
;
57 typedef WeakComponentImplHelper2
<
58 css::lang::XServiceInfo
, css::lang::XMultiServiceFactory
,
59 css::lang::XMultiComponentFactory
, css::container::XSet
,
60 css::container::XContentEnumerationAccess
, css::beans::XPropertySet
,
61 css::beans::XPropertySetInfo
, css::lang::XEventListener
,
62 css::lang::XInitialization
>
65 class ServiceManager
: public ServiceManagerBase
70 Data(const Data
&) = delete;
71 const Data
& operator=(const Data
&) = delete;
73 struct Implementation
{
75 OUString theName
, OUString theLoader
,
76 OUString theUri
, OUString theEnvironment
,
77 OUString theConstructorName
,
79 bool theIsSingleInstance
,
80 css::uno::Reference
< css::uno::XComponentContext
> theAlienContext
,
82 name(std::move(theName
)), loader(std::move(theLoader
)), uri(std::move(theUri
)), environment(std::move(theEnvironment
)),
83 constructorName(std::move(theConstructorName
)), prefix(std::move(thePrefix
)),
84 isSingleInstance(theIsSingleInstance
),
85 alienContext(std::move(theAlienContext
)), rdbFile(std::move(theRdbFile
)),
86 constructorFn(nullptr), status(STATUS_NEW
), dispose(true)
91 css::uno::Reference
< css::lang::XSingleComponentFactory
>
93 css::uno::Reference
< css::lang::XSingleServiceFactory
> const &
95 css::uno::Reference
< css::lang::XComponent
> theComponent
):
96 name(std::move(theName
)), isSingleInstance(false), constructorFn(nullptr),
97 factory1(theFactory1
), factory2(theFactory2
),
98 component(std::move(theComponent
)), status(STATUS_LOADED
), dispose(true)
99 { assert(theFactory1
.is() || theFactory2
.is()); }
101 Implementation(const Implementation
&) = delete;
102 const Implementation
& operator=(const Implementation
&) = delete;
104 css::uno::Reference
<css::uno::XInterface
> createInstance(
105 css::uno::Reference
<css::uno::XComponentContext
> const &
107 bool singletonRequest
);
109 css::uno::Reference
<css::uno::XInterface
>
110 createInstanceWithArguments(
111 css::uno::Reference
<css::uno::XComponentContext
> const &
113 bool singletonRequest
,
114 css::uno::Sequence
<css::uno::Any
> const & arguments
);
116 bool shallDispose() const { return isSingleInstance
|| !singletons
.empty(); }
118 enum Status
{ STATUS_NEW
, STATUS_WRAPPER
, STATUS_LOADED
};
120 // Logically, exactly one of constructorFn, factory1, factory2 should
121 // be set. However, there are two exceptions: For one, when
122 // constructorFn is set, ServiceManager::createContentEnumeration will
123 // store the necessary ImplementationWrapper in factory1 (so that
124 // multiple calls to createContentEnumeration will return the same
125 // wrapper). For another, when factory1 should be set but status is
126 // STATUS_NEW, factory1 is not yet set (and when status is
127 // STATUS_WRAPPER, factory1 is merely set to an
128 // ImplementationWrapper---also due to a
129 // ServiceManager::createContentEnumeration call---and will be
134 OUString environment
;
135 OUString constructorName
;
137 bool isSingleInstance
;
138 css::uno::Reference
< css::uno::XComponentContext
> alienContext
;
140 std::vector
< OUString
> services
;
141 std::vector
< OUString
> singletons
;
142 WrapperConstructorFn constructorFn
;
143 css::uno::Reference
< css::lang::XSingleComponentFactory
> factory1
;
144 css::uno::Reference
< css::lang::XSingleServiceFactory
> factory2
;
145 css::uno::Reference
< css::lang::XComponent
> component
;
149 css::uno::Reference
<css::uno::XInterface
> singleInstance
;
150 css::uno::Reference
< css::lang::XComponent
> disposeInstance
;
154 css::uno::Reference
<css::uno::XInterface
> doCreateInstance(
155 css::uno::Reference
<css::uno::XComponentContext
> const & context
);
157 css::uno::Reference
<css::uno::XInterface
> doCreateInstanceWithArguments(
158 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
159 css::uno::Sequence
<css::uno::Any
> const & arguments
);
161 void updateDisposeInstance(
162 bool singletonRequest
,
163 css::uno::Reference
<css::uno::XInterface
> const & instance
);
166 typedef std::unordered_map
< OUString
, std::shared_ptr
< Implementation
> >
167 NamedImplementations
;
171 css::uno::Reference
< css::lang::XServiceInfo
>,
172 std::shared_ptr
< Implementation
> >
173 DynamicImplementations
;
178 boost::container::small_vector
< std::shared_ptr
< Implementation
>, 2 > >
181 NamedImplementations namedImplementations
;
182 DynamicImplementations dynamicImplementations
;
183 ImplementationMap services
;
184 ImplementationMap singletons
;
189 ServiceManager(const ServiceManager
&) = delete;
190 const ServiceManager
& operator=(const ServiceManager
&) = delete;
192 using ServiceManagerBase::acquire
;
193 using ServiceManagerBase::release
;
195 void init(std::u16string_view rdbUris
);
198 css::uno::Reference
< css::uno::XComponentContext
> const & context
)
200 assert(context
.is());
201 assert(!context_
.is());
205 void addSingletonContextEntries(
206 std::vector
< cppu::ContextEntry_Init
> * entries
);
208 css::uno::Reference
< css::uno::XComponentContext
> const & getContext()
211 assert(context_
.is());
215 void loadImplementation(
216 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
217 std::shared_ptr
< Data::Implementation
> const & implementation
);
220 virtual ~ServiceManager() override
;
222 virtual void disposing(std::unique_lock
<std::mutex
>&) override
;
224 virtual OUString SAL_CALL
getImplementationName() override
;
226 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
) override
;
228 virtual css::uno::Sequence
< OUString
> SAL_CALL
229 getSupportedServiceNames() override
;
231 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
createInstance(
232 OUString
const & aServiceSpecifier
) override
;
234 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
235 createInstanceWithArguments(
236 OUString
const & ServiceSpecifier
,
237 css::uno::Sequence
< css::uno::Any
> const & Arguments
) override
;
239 virtual css::uno::Sequence
< OUString
> SAL_CALL
240 getAvailableServiceNames() override
;
242 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
243 createInstanceWithContext(
244 OUString
const & aServiceSpecifier
,
245 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
247 virtual css::uno::Reference
< css::uno::XInterface
> SAL_CALL
248 createInstanceWithArgumentsAndContext(
249 OUString
const & ServiceSpecifier
,
250 css::uno::Sequence
< css::uno::Any
> const & Arguments
,
251 css::uno::Reference
< css::uno::XComponentContext
> const & Context
) override
;
253 virtual css::uno::Type SAL_CALL
getElementType() override
;
255 virtual sal_Bool SAL_CALL
hasElements() override
;
257 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
258 createEnumeration() override
;
260 virtual sal_Bool SAL_CALL
has(css::uno::Any
const & aElement
) override
;
262 virtual void SAL_CALL
insert(css::uno::Any
const & aElement
) override
;
264 virtual void SAL_CALL
remove(css::uno::Any
const & aElement
) override
;
266 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
267 createContentEnumeration(OUString
const & aServiceName
) override
;
269 virtual css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
270 getPropertySetInfo() override
;
272 virtual void SAL_CALL
setPropertyValue(
273 OUString
const & aPropertyName
, css::uno::Any
const & aValue
) override
;
275 virtual css::uno::Any SAL_CALL
getPropertyValue(
276 OUString
const & PropertyName
) override
;
278 virtual void SAL_CALL
addPropertyChangeListener(
279 OUString
const & aPropertyName
,
280 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
283 virtual void SAL_CALL
removePropertyChangeListener(
284 OUString
const & aPropertyName
,
285 css::uno::Reference
< css::beans::XPropertyChangeListener
> const &
288 virtual void SAL_CALL
addVetoableChangeListener(
289 OUString
const & PropertyName
,
290 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
293 virtual void SAL_CALL
removeVetoableChangeListener(
294 OUString
const & PropertyName
,
295 css::uno::Reference
< css::beans::XVetoableChangeListener
> const &
298 virtual css::uno::Sequence
< css::beans::Property
> SAL_CALL
getProperties() override
;
300 virtual css::beans::Property SAL_CALL
getPropertyByName(
301 OUString
const & aName
) override
;
303 virtual sal_Bool SAL_CALL
hasPropertyByName(OUString
const & Name
) override
;
305 virtual void SAL_CALL
disposing(css::lang::EventObject
const & Source
) override
;
307 virtual void SAL_CALL
initialize(
308 css::uno::Sequence
<css::uno::Any
> const & aArguments
)
311 void removeEventListenerFromComponent(
312 css::uno::Reference
< css::lang::XComponent
> const & component
);
314 void readRdbDirectory(std::u16string_view uri
, bool optional
);
316 void readRdbFile(OUString
const & uri
, bool optional
);
318 bool readLegacyRdbFile(OUString
const & uri
);
320 OUString
readLegacyRdbString(
321 std::u16string_view uri
, RegistryKey
& key
,
322 OUString
const & path
);
324 void readLegacyRdbStrings(
325 std::u16string_view uri
, RegistryKey
& key
,
326 OUString
const & path
, std::vector
< OUString
> * strings
);
329 std::vector
< OUString
> const & uris
,
330 css::uno::Reference
< css::uno::XComponentContext
> const &
333 void insertLegacyFactory(
334 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
);
336 bool insertExtraData(Data
const & extra
);
338 void removeRdbFiles(std::vector
< OUString
> const & uris
);
340 bool removeLegacyFactory(
341 css::uno::Reference
< css::lang::XServiceInfo
> const & factoryInfo
,
342 bool removeListener
);
344 void removeImplementation(const OUString
& name
);
346 std::shared_ptr
< Data::Implementation
> findServiceImplementation(
347 css::uno::Reference
< css::uno::XComponentContext
> const & context
,
348 OUString
const & specifier
);
350 void preloadImplementations();
352 css::uno::Reference
< css::uno::XComponentContext
> context_
;
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */