bump product version to 4.1.6.2
[LibreOffice.git] / configmgr / source / configurationprovider.cxx
blobd5edfabdbaec969fd1d52b05ee5a69318226af70
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 <vector>
25 #include "boost/noncopyable.hpp"
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/compbase5.hxx"
48 #include "cppuhelper/factory.hxx"
49 #include "cppuhelper/implbase2.hxx"
50 #include "cppuhelper/interfacecontainer.hxx"
51 #include "cppuhelper/weak.hxx"
52 #include "osl/mutex.hxx"
53 #include "sal/types.h"
54 #include "rtl/ref.hxx"
55 #include "rtl/ustring.h"
56 #include "rtl/ustring.hxx"
58 #include <i18nlangtag/languagetag.hxx>
60 #include "components.hxx"
61 #include "configurationprovider.hxx"
62 #include "lock.hxx"
63 #include "rootaccess.hxx"
65 namespace configmgr { namespace configuration_provider {
67 namespace {
69 char const accessServiceName[] =
70 "com.sun.star.configuration.ConfigurationAccess";
71 char const updateAccessServiceName[] =
72 "com.sun.star.configuration.ConfigurationUpdateAccess";
74 void badNodePath() {
75 throw css::uno::Exception(
76 OUString("com.sun.star.configuration.ConfigurationProvider expects a"
77 " single, non-empty, string nodepath argument"),
78 0);
81 typedef
82 cppu::WeakComponentImplHelper5<
83 css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
84 css::util::XRefreshable, css::util::XFlushable,
85 css::lang::XLocalizable >
86 ServiceBase;
88 class Service:
89 private osl::Mutex, public ServiceBase, private boost::noncopyable
91 public:
92 Service(
93 css::uno::Reference< css::uno::XComponentContext > const context,
94 OUString const & locale):
95 ServiceBase(*static_cast< osl::Mutex * >(this)), context_(context),
96 locale_(locale)
98 lock_ = lock();
99 assert(context.is());
102 private:
103 virtual ~Service() {}
105 virtual void SAL_CALL disposing() { flushModifications(); }
107 virtual OUString SAL_CALL getImplementationName()
108 throw (css::uno::RuntimeException)
109 { return configuration_provider::getImplementationName(); }
111 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
112 throw (css::uno::RuntimeException)
113 { return ServiceName == getSupportedServiceNames()[0]; } //TODO
115 virtual css::uno::Sequence< OUString > SAL_CALL
116 getSupportedServiceNames() throw (css::uno::RuntimeException)
117 { return configuration_provider::getSupportedServiceNames(); }
119 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
120 OUString const & aServiceSpecifier)
121 throw (css::uno::Exception, css::uno::RuntimeException);
123 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
124 createInstanceWithArguments(
125 OUString const & ServiceSpecifier,
126 css::uno::Sequence< css::uno::Any > const & Arguments)
127 throw (css::uno::Exception, css::uno::RuntimeException);
129 virtual css::uno::Sequence< OUString > SAL_CALL
130 getAvailableServiceNames() throw (css::uno::RuntimeException);
132 virtual void SAL_CALL refresh() throw (css::uno::RuntimeException);
134 virtual void SAL_CALL addRefreshListener(
135 css::uno::Reference< css::util::XRefreshListener > const & l)
136 throw (css::uno::RuntimeException);
138 virtual void SAL_CALL removeRefreshListener(
139 css::uno::Reference< css::util::XRefreshListener > const & l)
140 throw (css::uno::RuntimeException);
142 virtual void SAL_CALL flush() throw (css::uno::RuntimeException);
144 virtual void SAL_CALL addFlushListener(
145 css::uno::Reference< css::util::XFlushListener > const & l)
146 throw (css::uno::RuntimeException);
148 virtual void SAL_CALL removeFlushListener(
149 css::uno::Reference< css::util::XFlushListener > const & l)
150 throw (css::uno::RuntimeException);
152 virtual void SAL_CALL setLocale(css::lang::Locale const & eLocale)
153 throw (css::uno::RuntimeException);
155 virtual css::lang::Locale SAL_CALL getLocale()
156 throw (css::uno::RuntimeException);
158 void flushModifications() const;
160 css::uno::Reference< css::uno::XComponentContext > context_;
161 OUString locale_;
162 boost::shared_ptr<osl::Mutex> lock_;
165 css::uno::Reference< css::uno::XInterface > Service::createInstance(
166 OUString const & aServiceSpecifier)
167 throw (css::uno::Exception, css::uno::RuntimeException)
169 return createInstanceWithArguments(
170 aServiceSpecifier, css::uno::Sequence< css::uno::Any >());
173 css::uno::Reference< css::uno::XInterface >
174 Service::createInstanceWithArguments(
175 OUString const & ServiceSpecifier,
176 css::uno::Sequence< css::uno::Any > const & Arguments)
177 throw (css::uno::Exception, css::uno::RuntimeException)
179 OUString nodepath;
180 OUString locale;
181 for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
182 css::beans::NamedValue v1;
183 css::beans::PropertyValue v2;
184 OUString name;
185 css::uno::Any value;
186 if (Arguments[i] >>= v1) {
187 name = v1.Name;
188 value = v1.Value;
189 } else if (Arguments[i] >>= v2) {
190 name = v2.Name;
191 value = v2.Value;
192 } else if (Arguments.getLength() == 1 && (Arguments[i] >>= nodepath)) {
193 // For backwards compatibility, allow a single string argument that
194 // denotes nodepath.
195 if (nodepath.isEmpty()) {
196 badNodePath();
198 break;
199 } else {
200 throw css::uno::Exception(
201 OUString("com.sun.star.configuration.ConfigurationProvider"
202 " expects NamedValue or PropertyValue arguments"),
205 // For backwards compatibility, allow "nodepath" and "Locale" in any
206 // case:
207 if (name.equalsIgnoreAsciiCase("nodepath")) {
208 if (!nodepath.isEmpty() || !(value >>= nodepath) ||
209 nodepath.isEmpty())
211 badNodePath();
213 } else if (name.equalsIgnoreAsciiCase("locale")) {
214 if (!locale.isEmpty() || !(value >>= locale) ||
215 locale.isEmpty())
217 throw css::uno::Exception(
218 OUString("com.sun.star.configuration.ConfigurationProvider"
219 " expects at most one, non-empty, string Locale"
220 " argument"),
225 if (nodepath.isEmpty()) {
226 badNodePath();
228 // For backwards compatibility, allow a nodepath that misses the leading
229 // slash:
230 if (nodepath[0] != '/') {
231 nodepath = OUString("/") + nodepath;
233 if (locale.isEmpty()) {
234 //TODO: should the Access use the dynamically changing locale_ instead?
235 locale = locale_;
236 if (locale.isEmpty()) {
237 locale = OUString("en-US");
240 bool update;
241 if ( ServiceSpecifier == accessServiceName )
243 update = false;
244 } else if ( ServiceSpecifier == updateAccessServiceName )
246 update = true;
247 } else {
248 throw css::uno::Exception(
249 (OUString("com.sun.star.configuration.ConfigurationProvider does not"
250 " support service ") +
251 ServiceSpecifier),
252 static_cast< cppu::OWeakObject * >(this));
254 osl::MutexGuard guard(*lock_);
255 Components & components = Components::getSingleton(context_);
256 rtl::Reference< RootAccess > root(
257 new RootAccess(components, nodepath, locale, update));
258 if (root->isValue()) {
259 throw css::uno::Exception(
260 (OUString("com.sun.star.configuration.ConfigurationProvider: there is"
261 " a leaf value at nodepath ") +
262 nodepath),
263 static_cast< cppu::OWeakObject * >(this));
265 components.addRootAccess(root);
266 return static_cast< cppu::OWeakObject * >(root.get());
269 css::uno::Sequence< OUString > Service::getAvailableServiceNames()
270 throw (css::uno::RuntimeException)
272 css::uno::Sequence< OUString > names(2);
273 names[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(accessServiceName));
274 names[1] = OUString(RTL_CONSTASCII_USTRINGPARAM(updateAccessServiceName));
275 return names;
278 void Service::refresh() throw (css::uno::RuntimeException) {
279 //TODO
280 cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
281 cppu::UnoType< css::util::XRefreshListener >::get());
282 if (cont != 0) {
283 css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
284 cont->notifyEach(&css::util::XRefreshListener::refreshed, ev);
288 void Service::addRefreshListener(
289 css::uno::Reference< css::util::XRefreshListener > const & l)
290 throw (css::uno::RuntimeException)
292 rBHelper.addListener(
293 cppu::UnoType< css::util::XRefreshListener >::get(), l);
296 void Service::removeRefreshListener(
297 css::uno::Reference< css::util::XRefreshListener > const & l)
298 throw (css::uno::RuntimeException)
300 rBHelper.removeListener(
301 cppu::UnoType< css::util::XRefreshListener >::get(), l);
304 void Service::flush() throw (css::uno::RuntimeException) {
305 flushModifications();
306 cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
307 cppu::UnoType< css::util::XFlushListener >::get());
308 if (cont != 0) {
309 css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
310 cont->notifyEach(&css::util::XFlushListener::flushed, ev);
314 void Service::addFlushListener(
315 css::uno::Reference< css::util::XFlushListener > const & l)
316 throw (css::uno::RuntimeException)
318 rBHelper.addListener(cppu::UnoType< css::util::XFlushListener >::get(), l);
321 void Service::removeFlushListener(
322 css::uno::Reference< css::util::XFlushListener > const & l)
323 throw (css::uno::RuntimeException)
325 rBHelper.removeListener(
326 cppu::UnoType< css::util::XFlushListener >::get(), l);
329 void Service::setLocale(css::lang::Locale const & eLocale)
330 throw (css::uno::RuntimeException)
332 osl::MutexGuard guard(*lock_);
333 locale_ = LanguageTag( eLocale).getBcp47();
336 css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException) {
337 osl::MutexGuard guard(*lock_);
338 css::lang::Locale loc;
339 if (! locale_.isEmpty()) {
340 loc = LanguageTag( locale_).getLocale( false);
342 return loc;
345 void Service::flushModifications() const {
346 Components * components;
348 osl::MutexGuard guard(*lock_);
349 components = &Components::getSingleton(context_);
351 components->flushModifications();
354 class Factory:
355 public cppu::WeakImplHelper2<
356 css::lang::XSingleComponentFactory, css::lang::XServiceInfo >,
357 private boost::noncopyable
359 public:
360 Factory() {}
362 private:
363 virtual ~Factory() {}
365 virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
366 createInstanceWithContext(
367 css::uno::Reference< css::uno::XComponentContext > const & Context)
368 throw (css::uno::Exception, css::uno::RuntimeException);
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)
374 throw (css::uno::Exception, css::uno::RuntimeException);
376 virtual OUString SAL_CALL getImplementationName()
377 throw (css::uno::RuntimeException)
378 { return configuration_provider::getImplementationName(); }
380 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
381 throw (css::uno::RuntimeException)
382 { return ServiceName == getSupportedServiceNames()[0]; } //TODO
384 virtual css::uno::Sequence< OUString > SAL_CALL
385 getSupportedServiceNames() throw (css::uno::RuntimeException)
386 { return configuration_provider::getSupportedServiceNames(); }
389 css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
390 css::uno::Reference< css::uno::XComponentContext > const & Context)
391 throw (css::uno::Exception, css::uno::RuntimeException)
393 return createInstanceWithArgumentsAndContext(
394 css::uno::Sequence< css::uno::Any >(), Context);
397 css::uno::Reference< css::uno::XInterface >
398 Factory::createInstanceWithArgumentsAndContext(
399 css::uno::Sequence< css::uno::Any > const & Arguments,
400 css::uno::Reference< css::uno::XComponentContext > const & Context)
401 throw (css::uno::Exception, css::uno::RuntimeException)
403 if (Arguments.getLength() == 0) {
404 return css::configuration::theDefaultProvider::get(Context);
405 } else {
406 OUString locale;
407 for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
408 css::beans::NamedValue v1;
409 css::beans::PropertyValue v2;
410 OUString name;
411 css::uno::Any value;
412 if (Arguments[i] >>= v1) {
413 name = v1.Name;
414 value = v1.Value;
415 } else if (Arguments[i] >>= v2) {
416 name = v2.Name;
417 value = v2.Value;
418 } else {
419 throw css::uno::Exception(
420 OUString("com.sun.star.configuration.ConfigurationProvider"
421 " factory expects NamedValue or PropertyValue"
422 " arguments"),
425 // For backwards compatibility, allow "Locale" and (ignored)
426 // "EnableAsync" in any case:
427 if (name.equalsIgnoreAsciiCase("locale")) {
428 if (!locale.isEmpty() || !(value >>= locale) ||
429 locale.isEmpty())
431 throw css::uno::Exception(
432 OUString("com.sun.star.configuration."
433 "ConfigurationProvider factory expects at most"
434 " one, non-empty, string Locale argument"),
437 } else if (!name.equalsIgnoreAsciiCase("enableasync")) {
438 throw css::uno::Exception(
439 OUString("com.sun.star.configuration.ConfigurationProvider"
440 " factory: unknown argument ") + name,
444 return static_cast< cppu::OWeakObject * >(new Service(Context, locale));
450 css::uno::Reference< css::uno::XInterface > createDefault(
451 css::uno::Reference< css::uno::XComponentContext > const & context)
453 return static_cast< cppu::OWeakObject * >(
454 new Service(context, OUString()));
457 OUString getImplementationName() {
458 return OUString("com.sun.star.comp.configuration.ConfigurationProvider");
461 css::uno::Sequence< OUString > getSupportedServiceNames() {
462 OUString name("com.sun.star.configuration.ConfigurationProvider");
463 return css::uno::Sequence< OUString >(&name, 1);
466 css::uno::Reference< css::lang::XSingleComponentFactory >
467 createFactory(
468 SAL_UNUSED_PARAMETER cppu::ComponentFactoryFunc,
469 SAL_UNUSED_PARAMETER OUString const &,
470 SAL_UNUSED_PARAMETER css::uno::Sequence< OUString > const &,
471 SAL_UNUSED_PARAMETER rtl_ModuleCount *)
472 SAL_THROW(())
474 return new Factory;
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */