bump product version to 6.3.0.0.beta1
[LibreOffice.git] / configmgr / source / configurationprovider.cxx
blob1adcadafdb77ae5e92ec940db2e0f3469609458d
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/.
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 <cassert>
23 #include <memory>
24 #include <vector>
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/configuration/theDefaultProvider.hpp>
29 #include <com/sun/star/lang/EventObject.hpp>
30 #include <com/sun/star/lang/Locale.hpp>
31 #include <com/sun/star/lang/XLocalizable.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/uno/Exception.hpp>
37 #include <com/sun/star/uno/Reference.hxx>
38 #include <com/sun/star/uno/RuntimeException.hpp>
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <com/sun/star/uno/XComponentContext.hpp>
41 #include <com/sun/star/uno/XInterface.hpp>
42 #include <com/sun/star/util/XFlushListener.hpp>
43 #include <com/sun/star/util/XFlushable.hpp>
44 #include <com/sun/star/util/XRefreshListener.hpp>
45 #include <com/sun/star/util/XRefreshable.hpp>
46 #include <cppu/unotype.hxx>
47 #include <cppuhelper/basemutex.hxx>
48 #include <cppuhelper/compbase.hxx>
49 #include <cppuhelper/factory.hxx>
50 #include <cppuhelper/implbase.hxx>
51 #include <cppuhelper/interfacecontainer.hxx>
52 #include <cppuhelper/supportsservice.hxx>
53 #include <cppuhelper/weak.hxx>
54 #include <osl/mutex.hxx>
55 #include <sal/types.h>
56 #include <rtl/ref.hxx>
57 #include <rtl/ustring.hxx>
59 #include <i18nlangtag/languagetag.hxx>
61 #include "components.hxx"
62 #include "configurationprovider.hxx"
63 #include "lock.hxx"
64 #include "defaultprovider.hxx"
65 #include "rootaccess.hxx"
67 namespace configmgr { namespace configuration_provider {
69 namespace {
71 char const accessServiceName[] =
72 "com.sun.star.configuration.ConfigurationAccess";
73 char const updateAccessServiceName[] =
74 "com.sun.star.configuration.ConfigurationUpdateAccess";
76 void badNodePath() {
77 throw css::uno::Exception(
78 ("com.sun.star.configuration.ConfigurationProvider expects a single,"
79 " non-empty, string nodepath argument"),
80 nullptr);
83 typedef
84 cppu::WeakComponentImplHelper<
85 css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
86 css::util::XRefreshable, css::util::XFlushable,
87 css::lang::XLocalizable >
88 ServiceBase;
90 class Service:
91 private cppu::BaseMutex, public ServiceBase
93 public:
94 explicit Service(
95 const css::uno::Reference< css::uno::XComponentContext >& context):
96 ServiceBase(m_aMutex), context_(context), default_(true),
97 lock_( lock() )
99 assert(context.is());
102 Service(
103 const css::uno::Reference< css::uno::XComponentContext >& context,
104 OUString const & locale):
105 ServiceBase(m_aMutex), context_(context), locale_(locale),
106 default_(false),
107 lock_( lock() )
109 assert(context.is());
112 private:
113 Service(const Service&) = delete;
114 Service& operator=(const Service&) = delete;
116 virtual ~Service() override {}
118 virtual void SAL_CALL disposing() override { flushModifications(); }
120 virtual OUString SAL_CALL getImplementationName() override
122 return default_
123 ? default_provider::getImplementationName()
124 : configuration_provider::getImplementationName();
127 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
128 { return cppu::supportsService(this, ServiceName); }
130 virtual css::uno::Sequence< OUString > SAL_CALL
131 getSupportedServiceNames() override
133 return default_
134 ? default_provider::getSupportedServiceNames()
135 : configuration_provider::getSupportedServiceNames();
138 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
139 OUString const & aServiceSpecifier) override;
141 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
142 createInstanceWithArguments(
143 OUString const & ServiceSpecifier,
144 css::uno::Sequence< css::uno::Any > const & Arguments) override;
146 virtual css::uno::Sequence< OUString > SAL_CALL
147 getAvailableServiceNames() override;
149 virtual void SAL_CALL refresh() override;
151 virtual void SAL_CALL addRefreshListener(
152 css::uno::Reference< css::util::XRefreshListener > const & l) override;
154 virtual void SAL_CALL removeRefreshListener(
155 css::uno::Reference< css::util::XRefreshListener > const & l) override;
157 virtual void SAL_CALL flush() override;
159 virtual void SAL_CALL addFlushListener(
160 css::uno::Reference< css::util::XFlushListener > const & l) override;
162 virtual void SAL_CALL removeFlushListener(
163 css::uno::Reference< css::util::XFlushListener > const & l) override;
165 virtual void SAL_CALL setLocale(css::lang::Locale const & eLocale) override;
167 virtual css::lang::Locale SAL_CALL getLocale() override;
169 void flushModifications() const;
171 css::uno::Reference< css::uno::XComponentContext > context_;
172 OUString locale_;
173 bool default_;
174 std::shared_ptr<osl::Mutex> lock_;
177 css::uno::Reference< css::uno::XInterface > Service::createInstance(
178 OUString const & aServiceSpecifier)
180 return createInstanceWithArguments(
181 aServiceSpecifier, css::uno::Sequence< css::uno::Any >());
184 css::uno::Reference< css::uno::XInterface >
185 Service::createInstanceWithArguments(
186 OUString const & ServiceSpecifier,
187 css::uno::Sequence< css::uno::Any > const & Arguments)
189 OUString nodepath;
190 OUString locale;
191 for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
192 css::beans::NamedValue v1;
193 css::beans::PropertyValue v2;
194 OUString name;
195 css::uno::Any value;
196 if (Arguments[i] >>= v1) {
197 name = v1.Name;
198 value = v1.Value;
199 } else if (Arguments[i] >>= v2) {
200 name = v2.Name;
201 value = v2.Value;
202 } else if (Arguments.getLength() == 1 && (Arguments[i] >>= nodepath)) {
203 // For backwards compatibility, allow a single string argument that
204 // denotes nodepath.
205 if (nodepath.isEmpty()) {
206 badNodePath();
208 break;
209 } else {
210 throw css::uno::Exception(
211 ("com.sun.star.configuration.ConfigurationProvider expects"
212 " NamedValue or PropertyValue arguments"),
213 nullptr);
215 // For backwards compatibility, allow "nodepath" and "Locale" in any
216 // case:
217 if (name.equalsIgnoreAsciiCase("nodepath")) {
218 if (!nodepath.isEmpty() || !(value >>= nodepath) ||
219 nodepath.isEmpty())
221 badNodePath();
223 } else if (name.equalsIgnoreAsciiCase("locale")) {
224 if (!locale.isEmpty() || !(value >>= locale) ||
225 locale.isEmpty())
227 throw css::uno::Exception(
228 ("com.sun.star.configuration.ConfigurationProvider expects"
229 " at most one, non-empty, string Locale argument"),
230 nullptr);
234 if (nodepath.isEmpty()) {
235 badNodePath();
237 // For backwards compatibility, allow a nodepath that misses the leading
238 // slash:
239 if (nodepath[0] != '/') {
240 nodepath = "/" + nodepath;
242 if (locale.isEmpty()) {
243 //TODO: should the Access use the dynamically changing locale_ instead?
244 locale = locale_;
245 if (locale.isEmpty()) {
246 locale = "en-US";
249 bool update;
250 if (ServiceSpecifier == accessServiceName) {
251 update = false;
252 } else if (ServiceSpecifier == updateAccessServiceName) {
253 update = true;
254 } else {
255 throw css::uno::Exception(
256 ("com.sun.star.configuration.ConfigurationProvider does not support"
257 " service " + ServiceSpecifier),
258 static_cast< cppu::OWeakObject * >(this));
260 osl::MutexGuard guard(*lock_);
261 Components & components = Components::getSingleton(context_);
262 rtl::Reference root(
263 new RootAccess(components, nodepath, locale, update));
264 if (root->isValue()) {
265 throw css::uno::Exception(
266 ("com.sun.star.configuration.ConfigurationProvider: there is a leaf"
267 " value at nodepath " + nodepath),
268 static_cast< cppu::OWeakObject * >(this));
270 components.addRootAccess(root);
271 return static_cast< cppu::OWeakObject * >(root.get());
274 css::uno::Sequence< OUString > Service::getAvailableServiceNames()
276 css::uno::Sequence< OUString > names(2);
277 names[0] = accessServiceName;
278 names[1] = updateAccessServiceName;
279 return names;
282 void Service::refresh() {
283 //TODO
284 cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
285 cppu::UnoType< css::util::XRefreshListener >::get());
286 if (cont != nullptr) {
287 css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
288 cont->notifyEach(&css::util::XRefreshListener::refreshed, ev);
292 void Service::addRefreshListener(
293 css::uno::Reference< css::util::XRefreshListener > const & l)
295 rBHelper.addListener(
296 cppu::UnoType< css::util::XRefreshListener >::get(), l);
299 void Service::removeRefreshListener(
300 css::uno::Reference< css::util::XRefreshListener > const & l)
302 rBHelper.removeListener(
303 cppu::UnoType< css::util::XRefreshListener >::get(), l);
306 void Service::flush() {
307 flushModifications();
308 cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
309 cppu::UnoType< css::util::XFlushListener >::get());
310 if (cont != nullptr) {
311 css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
312 cont->notifyEach(&css::util::XFlushListener::flushed, ev);
316 void Service::addFlushListener(
317 css::uno::Reference< css::util::XFlushListener > const & l)
319 rBHelper.addListener(cppu::UnoType< css::util::XFlushListener >::get(), l);
322 void Service::removeFlushListener(
323 css::uno::Reference< css::util::XFlushListener > const & l)
325 rBHelper.removeListener(
326 cppu::UnoType< css::util::XFlushListener >::get(), l);
329 void Service::setLocale(css::lang::Locale const & eLocale)
331 osl::MutexGuard guard(*lock_);
332 locale_ = LanguageTag::convertToBcp47( eLocale, false);
335 css::lang::Locale Service::getLocale() {
336 osl::MutexGuard guard(*lock_);
337 css::lang::Locale loc;
338 if (! locale_.isEmpty()) {
339 loc = LanguageTag::convertToLocale( locale_, false);
341 return loc;
344 void Service::flushModifications() const {
345 Components * components;
347 osl::MutexGuard guard(*lock_);
348 components = &Components::getSingleton(context_);
350 components->flushModifications();
353 class Factory:
354 public cppu::WeakImplHelper<
355 css::lang::XSingleComponentFactory, css::lang::XServiceInfo >
357 public:
358 Factory() {}
360 private:
361 Factory(const Factory&) = delete;
362 Factory& operator=(const Factory&) = delete;
364 virtual ~Factory() override {}
366 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
367 createInstanceWithContext(
368 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
370 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
371 createInstanceWithArgumentsAndContext(
372 css::uno::Sequence< css::uno::Any > const & Arguments,
373 css::uno::Reference< css::uno::XComponentContext > const & Context) override;
375 virtual OUString SAL_CALL getImplementationName() override
376 { return configuration_provider::getImplementationName(); }
378 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
379 { return cppu::supportsService(this, ServiceName); }
381 virtual css::uno::Sequence< OUString > SAL_CALL
382 getSupportedServiceNames() override
383 { return configuration_provider::getSupportedServiceNames(); }
386 css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
387 css::uno::Reference< css::uno::XComponentContext > const & Context)
389 return createInstanceWithArgumentsAndContext(
390 css::uno::Sequence< css::uno::Any >(), Context);
393 css::uno::Reference< css::uno::XInterface >
394 Factory::createInstanceWithArgumentsAndContext(
395 css::uno::Sequence< css::uno::Any > const & Arguments,
396 css::uno::Reference< css::uno::XComponentContext > const & Context)
398 if (Arguments.getLength() == 0) {
399 return css::configuration::theDefaultProvider::get(Context);
400 } else {
401 OUString locale;
402 for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
403 css::beans::NamedValue v1;
404 css::beans::PropertyValue v2;
405 OUString name;
406 css::uno::Any value;
407 if (Arguments[i] >>= v1) {
408 name = v1.Name;
409 value = v1.Value;
410 } else if (Arguments[i] >>= v2) {
411 name = v2.Name;
412 value = v2.Value;
413 } else {
414 throw css::uno::Exception(
415 ("com.sun.star.configuration.ConfigurationProvider factory"
416 " expects NamedValue or PropertyValue arguments"),
417 nullptr);
419 // For backwards compatibility, allow "Locale" and (ignored)
420 // "EnableAsync" in any case:
421 if (name.equalsIgnoreAsciiCase("locale")) {
422 if (!locale.isEmpty() || !(value >>= locale) ||
423 locale.isEmpty())
425 throw css::uno::Exception(
426 ("com.sun.star.configuration.ConfigurationProvider"
427 " factory expects at most one, non-empty, string"
428 " Locale argument"),
429 nullptr);
431 } else if (!name.equalsIgnoreAsciiCase("enableasync")) {
432 throw css::uno::Exception(
433 ("com.sun.star.configuration.ConfigurationProvider factory:"
434 " unknown argument " + name),
435 nullptr);
438 return static_cast< cppu::OWeakObject * >(new Service(Context, locale));
444 css::uno::Reference< css::uno::XInterface > createDefault(
445 css::uno::Reference< css::uno::XComponentContext > const & context)
447 return static_cast< cppu::OWeakObject * >(new Service(context));
450 OUString getImplementationName() {
451 return OUString("com.sun.star.comp.configuration.ConfigurationProvider");
454 css::uno::Sequence< OUString > getSupportedServiceNames() {
455 return css::uno::Sequence< OUString > { "com.sun.star.configuration.ConfigurationProvider" };
458 css::uno::Reference< css::lang::XSingleComponentFactory >
459 createFactory(
460 SAL_UNUSED_PARAMETER cppu::ComponentFactoryFunc,
461 SAL_UNUSED_PARAMETER OUString const &,
462 SAL_UNUSED_PARAMETER css::uno::Sequence< OUString > const &,
463 SAL_UNUSED_PARAMETER rtl_ModuleCount *)
465 return new Factory;
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */