Avoid potential negative array index access to cached text.
[LibreOffice.git] / cppuhelper / source / servicemanager.hxx
blobaf80be25a183c9201b6ee0b03b92eb52d9e6e80f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #pragma once
12 #include <sal/config.h>
14 #include <cassert>
15 #include <functional>
16 #include <memory>
17 #include <mutex>
18 #include <string_view>
19 #include <unordered_map>
20 #include <utility>
21 #include <vector>
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; }
43 class RegistryKey;
45 namespace cppuhelper {
47 extern "C" {
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>
62 ServiceManagerBase;
64 class ServiceManager : public ServiceManagerBase
66 public:
67 struct Data {
68 Data() = default;
69 Data(const Data&) = delete;
70 const Data& operator=(const Data&) = delete;
72 struct Implementation {
73 Implementation(
74 OUString theName, OUString theLoader,
75 OUString theUri, OUString theEnvironment,
76 OUString theConstructorName,
77 OUString thePrefix,
78 bool theIsSingleInstance,
79 css::uno::Reference< css::uno::XComponentContext > theAlienContext,
80 OUString theRdbFile):
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)
88 Implementation(
89 OUString theName,
90 css::uno::Reference< css::lang::XSingleComponentFactory >
91 const & theFactory1,
92 css::uno::Reference< css::lang::XSingleServiceFactory > const &
93 theFactory2,
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 &
105 context,
106 bool singletonRequest);
108 css::uno::Reference<css::uno::XInterface>
109 createInstanceWithArguments(
110 css::uno::Reference<css::uno::XComponentContext> const &
111 context,
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
129 // loaded later).
130 OUString name;
131 OUString loader;
132 OUString uri;
133 OUString environment;
134 OUString constructorName;
135 OUString prefix;
136 bool isSingleInstance;
137 css::uno::Reference< css::uno::XComponentContext > alienContext;
138 OUString rdbFile;
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;
145 Status status;
147 std::mutex mutex;
148 css::uno::Reference<css::uno::XInterface> singleInstance;
149 css::uno::Reference< css::lang::XComponent > disposeInstance;
150 bool dispose;
152 private:
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;
168 typedef
169 std::unordered_map<
170 css::uno::Reference< css::lang::XServiceInfo >,
171 std::shared_ptr< Implementation > >
172 DynamicImplementations;
174 typedef
175 std::unordered_map<
176 OUString,
177 std::vector< std::shared_ptr< Implementation > > >
178 ImplementationMap;
180 NamedImplementations namedImplementations;
181 DynamicImplementations dynamicImplementations;
182 ImplementationMap services;
183 ImplementationMap singletons;
186 ServiceManager() {}
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);
196 void setContext(
197 css::uno::Reference< css::uno::XComponentContext > const & context)
199 assert(context.is());
200 assert(!context_.is());
201 context_ = context;
204 void addSingletonContextEntries(
205 std::vector< cppu::ContextEntry_Init > * entries);
207 css::uno::Reference< css::uno::XComponentContext > const & getContext()
208 const
210 assert(context_.is());
211 return context_;
214 void loadImplementation(
215 css::uno::Reference< css::uno::XComponentContext > const & context,
216 std::shared_ptr< Data::Implementation > const & implementation);
218 private:
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 &
280 xListener) override;
282 virtual void SAL_CALL removePropertyChangeListener(
283 OUString const & aPropertyName,
284 css::uno::Reference< css::beans::XPropertyChangeListener > const &
285 aListener) override;
287 virtual void SAL_CALL addVetoableChangeListener(
288 OUString const & PropertyName,
289 css::uno::Reference< css::beans::XVetoableChangeListener > const &
290 aListener) override;
292 virtual void SAL_CALL removeVetoableChangeListener(
293 OUString const & PropertyName,
294 css::uno::Reference< css::beans::XVetoableChangeListener > const &
295 aListener) override;
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)
308 override;
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);
327 void insertRdbFiles(
328 std::vector< OUString > const & uris,
329 css::uno::Reference< css::uno::XComponentContext > const &
330 alientContext);
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_;
352 Data data_;
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */