Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <cassert>
23 : #include <vector>
24 :
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/basemutex.hxx"
48 : #include "cppuhelper/compbase5.hxx"
49 : #include "cppuhelper/factory.hxx"
50 : #include "cppuhelper/implbase2.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"
58 :
59 : #include <i18nlangtag/languagetag.hxx>
60 :
61 : #include "components.hxx"
62 : #include "configurationprovider.hxx"
63 : #include "lock.hxx"
64 : #include "defaultprovider.hxx"
65 : #include "rootaccess.hxx"
66 :
67 : namespace configmgr { namespace configuration_provider {
68 :
69 : namespace {
70 :
71 : char const accessServiceName[] =
72 : "com.sun.star.configuration.ConfigurationAccess";
73 : char const updateAccessServiceName[] =
74 : "com.sun.star.configuration.ConfigurationUpdateAccess";
75 :
76 0 : void badNodePath() {
77 : throw css::uno::Exception(
78 : ("com.sun.star.configuration.ConfigurationProvider expects a single,"
79 : " non-empty, string nodepath argument"),
80 0 : 0);
81 : }
82 :
83 : typedef
84 : cppu::WeakComponentImplHelper5<
85 : css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
86 : css::util::XRefreshable, css::util::XFlushable,
87 : css::lang::XLocalizable >
88 : ServiceBase;
89 :
90 : class Service:
91 : private cppu::BaseMutex, public ServiceBase, private boost::noncopyable
92 : {
93 : public:
94 0 : Service(
95 : css::uno::Reference< css::uno::XComponentContext > const context):
96 0 : ServiceBase(m_aMutex), context_(context), default_(true)
97 : {
98 0 : lock_ = lock();
99 : assert(context.is());
100 0 : }
101 :
102 0 : Service(
103 : css::uno::Reference< css::uno::XComponentContext > const context,
104 : OUString const & locale):
105 : ServiceBase(m_aMutex), context_(context), locale_(locale),
106 0 : default_(false)
107 : {
108 0 : lock_ = lock();
109 : assert(context.is());
110 0 : }
111 :
112 : private:
113 0 : virtual ~Service() {}
114 :
115 0 : virtual void SAL_CALL disposing() SAL_OVERRIDE { flushModifications(); }
116 :
117 0 : virtual OUString SAL_CALL getImplementationName()
118 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
119 : {
120 : return default_
121 : ? default_provider::getImplementationName()
122 0 : : configuration_provider::getImplementationName();
123 : }
124 :
125 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
126 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
127 0 : { return cppu::supportsService(this, ServiceName); }
128 :
129 : virtual css::uno::Sequence< OUString > SAL_CALL
130 0 : getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
131 : {
132 : return default_
133 : ? default_provider::getSupportedServiceNames()
134 0 : : configuration_provider::getSupportedServiceNames();
135 : }
136 :
137 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
138 : OUString const & aServiceSpecifier)
139 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
140 :
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)
145 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
146 :
147 : virtual css::uno::Sequence< OUString > SAL_CALL
148 : getAvailableServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
149 :
150 : virtual void SAL_CALL refresh() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
151 :
152 : virtual void SAL_CALL addRefreshListener(
153 : css::uno::Reference< css::util::XRefreshListener > const & l)
154 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
155 :
156 : virtual void SAL_CALL removeRefreshListener(
157 : css::uno::Reference< css::util::XRefreshListener > const & l)
158 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
159 :
160 : virtual void SAL_CALL flush() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
161 :
162 : virtual void SAL_CALL addFlushListener(
163 : css::uno::Reference< css::util::XFlushListener > const & l)
164 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
165 :
166 : virtual void SAL_CALL removeFlushListener(
167 : css::uno::Reference< css::util::XFlushListener > const & l)
168 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
169 :
170 : virtual void SAL_CALL setLocale(css::lang::Locale const & eLocale)
171 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
172 :
173 : virtual css::lang::Locale SAL_CALL getLocale()
174 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
175 :
176 : void flushModifications() const;
177 :
178 : css::uno::Reference< css::uno::XComponentContext > context_;
179 : OUString locale_;
180 : bool default_;
181 : boost::shared_ptr<osl::Mutex> lock_;
182 : };
183 :
184 0 : css::uno::Reference< css::uno::XInterface > Service::createInstance(
185 : OUString const & aServiceSpecifier)
186 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
187 : {
188 : return createInstanceWithArguments(
189 0 : aServiceSpecifier, css::uno::Sequence< css::uno::Any >());
190 : }
191 :
192 : css::uno::Reference< css::uno::XInterface >
193 0 : Service::createInstanceWithArguments(
194 : OUString const & ServiceSpecifier,
195 : css::uno::Sequence< css::uno::Any > const & Arguments)
196 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
197 : {
198 0 : OUString nodepath;
199 0 : OUString locale;
200 0 : for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
201 0 : css::beans::NamedValue v1;
202 0 : css::beans::PropertyValue v2;
203 0 : OUString name;
204 0 : css::uno::Any value;
205 0 : if (Arguments[i] >>= v1) {
206 0 : name = v1.Name;
207 0 : value = v1.Value;
208 0 : } else if (Arguments[i] >>= v2) {
209 0 : name = v2.Name;
210 0 : value = v2.Value;
211 0 : } else if (Arguments.getLength() == 1 && (Arguments[i] >>= nodepath)) {
212 : // For backwards compatibility, allow a single string argument that
213 : // denotes nodepath.
214 0 : if (nodepath.isEmpty()) {
215 0 : badNodePath();
216 : }
217 0 : break;
218 : } else {
219 : throw css::uno::Exception(
220 : ("com.sun.star.configuration.ConfigurationProvider expects"
221 : " NamedValue or PropertyValue arguments"),
222 0 : 0);
223 : }
224 : // For backwards compatibility, allow "nodepath" and "Locale" in any
225 : // case:
226 0 : if (name.equalsIgnoreAsciiCase("nodepath")) {
227 0 : if (!nodepath.isEmpty() || !(value >>= nodepath) ||
228 0 : nodepath.isEmpty())
229 : {
230 0 : badNodePath();
231 : }
232 0 : } else if (name.equalsIgnoreAsciiCase("locale")) {
233 0 : if (!locale.isEmpty() || !(value >>= locale) ||
234 0 : locale.isEmpty())
235 : {
236 : throw css::uno::Exception(
237 : ("com.sun.star.configuration.ConfigurationProvider expects"
238 : " at most one, non-empty, string Locale argument"),
239 0 : 0);
240 : }
241 : }
242 0 : }
243 0 : if (nodepath.isEmpty()) {
244 0 : badNodePath();
245 : }
246 : // For backwards compatibility, allow a nodepath that misses the leading
247 : // slash:
248 0 : if (nodepath[0] != '/') {
249 0 : nodepath = "/" + nodepath;
250 : }
251 0 : if (locale.isEmpty()) {
252 : //TODO: should the Access use the dynamically changing locale_ instead?
253 0 : locale = locale_;
254 0 : if (locale.isEmpty()) {
255 0 : locale = "en-US";
256 : }
257 : }
258 : bool update;
259 0 : if (ServiceSpecifier == accessServiceName) {
260 0 : update = false;
261 0 : } else if (ServiceSpecifier == updateAccessServiceName) {
262 0 : update = true;
263 : } else {
264 : throw css::uno::Exception(
265 : ("com.sun.star.configuration.ConfigurationProvider does not support"
266 0 : " service " + ServiceSpecifier),
267 0 : static_cast< cppu::OWeakObject * >(this));
268 : }
269 0 : osl::MutexGuard guard(*lock_);
270 0 : Components & components = Components::getSingleton(context_);
271 : rtl::Reference< RootAccess > root(
272 0 : new RootAccess(components, nodepath, locale, update));
273 0 : if (root->isValue()) {
274 : throw css::uno::Exception(
275 : ("com.sun.star.configuration.ConfigurationProvider: there is a leaf"
276 0 : " value at nodepath " + nodepath),
277 0 : static_cast< cppu::OWeakObject * >(this));
278 : }
279 0 : components.addRootAccess(root);
280 0 : return static_cast< cppu::OWeakObject * >(root.get());
281 : }
282 :
283 0 : css::uno::Sequence< OUString > Service::getAvailableServiceNames()
284 : throw (css::uno::RuntimeException, std::exception)
285 : {
286 0 : css::uno::Sequence< OUString > names(2);
287 0 : names[0] = accessServiceName;
288 0 : names[1] = updateAccessServiceName;
289 0 : return names;
290 : }
291 :
292 0 : void Service::refresh() throw (css::uno::RuntimeException, std::exception) {
293 : //TODO
294 : cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
295 0 : cppu::UnoType< css::util::XRefreshListener >::get());
296 0 : if (cont != 0) {
297 0 : css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
298 0 : cont->notifyEach(&css::util::XRefreshListener::refreshed, ev);
299 : }
300 0 : }
301 :
302 0 : void Service::addRefreshListener(
303 : css::uno::Reference< css::util::XRefreshListener > const & l)
304 : throw (css::uno::RuntimeException, std::exception)
305 : {
306 : rBHelper.addListener(
307 0 : cppu::UnoType< css::util::XRefreshListener >::get(), l);
308 0 : }
309 :
310 0 : void Service::removeRefreshListener(
311 : css::uno::Reference< css::util::XRefreshListener > const & l)
312 : throw (css::uno::RuntimeException, std::exception)
313 : {
314 : rBHelper.removeListener(
315 0 : cppu::UnoType< css::util::XRefreshListener >::get(), l);
316 0 : }
317 :
318 0 : void Service::flush() throw (css::uno::RuntimeException, std::exception) {
319 0 : flushModifications();
320 : cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
321 0 : cppu::UnoType< css::util::XFlushListener >::get());
322 0 : if (cont != 0) {
323 0 : css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
324 0 : cont->notifyEach(&css::util::XFlushListener::flushed, ev);
325 : }
326 0 : }
327 :
328 0 : void Service::addFlushListener(
329 : css::uno::Reference< css::util::XFlushListener > const & l)
330 : throw (css::uno::RuntimeException, std::exception)
331 : {
332 0 : rBHelper.addListener(cppu::UnoType< css::util::XFlushListener >::get(), l);
333 0 : }
334 :
335 0 : void Service::removeFlushListener(
336 : css::uno::Reference< css::util::XFlushListener > const & l)
337 : throw (css::uno::RuntimeException, std::exception)
338 : {
339 : rBHelper.removeListener(
340 0 : cppu::UnoType< css::util::XFlushListener >::get(), l);
341 0 : }
342 :
343 0 : void Service::setLocale(css::lang::Locale const & eLocale)
344 : throw (css::uno::RuntimeException, std::exception)
345 : {
346 0 : osl::MutexGuard guard(*lock_);
347 0 : locale_ = LanguageTag::convertToBcp47( eLocale, false);
348 0 : }
349 :
350 0 : css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException, std::exception) {
351 0 : osl::MutexGuard guard(*lock_);
352 0 : css::lang::Locale loc;
353 0 : if (! locale_.isEmpty()) {
354 0 : loc = LanguageTag::convertToLocale( locale_, false);
355 : }
356 0 : return loc;
357 : }
358 :
359 0 : void Service::flushModifications() const {
360 : Components * components;
361 : {
362 0 : osl::MutexGuard guard(*lock_);
363 0 : components = &Components::getSingleton(context_);
364 : }
365 0 : components->flushModifications();
366 0 : }
367 :
368 : class Factory:
369 : public cppu::WeakImplHelper2<
370 : css::lang::XSingleComponentFactory, css::lang::XServiceInfo >,
371 : private boost::noncopyable
372 : {
373 : public:
374 0 : Factory() {}
375 :
376 : private:
377 0 : virtual ~Factory() {}
378 :
379 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
380 : createInstanceWithContext(
381 : css::uno::Reference< css::uno::XComponentContext > const & Context)
382 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
383 :
384 : virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
385 : createInstanceWithArgumentsAndContext(
386 : css::uno::Sequence< css::uno::Any > const & Arguments,
387 : css::uno::Reference< css::uno::XComponentContext > const & Context)
388 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
389 :
390 0 : virtual OUString SAL_CALL getImplementationName()
391 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
392 0 : { return configuration_provider::getImplementationName(); }
393 :
394 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
395 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
396 0 : { return cppu::supportsService(this, ServiceName); }
397 :
398 : virtual css::uno::Sequence< OUString > SAL_CALL
399 0 : getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
400 0 : { return configuration_provider::getSupportedServiceNames(); }
401 : };
402 :
403 0 : css::uno::Reference< css::uno::XInterface > Factory::createInstanceWithContext(
404 : css::uno::Reference< css::uno::XComponentContext > const & Context)
405 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
406 : {
407 : return createInstanceWithArgumentsAndContext(
408 0 : css::uno::Sequence< css::uno::Any >(), Context);
409 : }
410 :
411 : css::uno::Reference< css::uno::XInterface >
412 0 : Factory::createInstanceWithArgumentsAndContext(
413 : css::uno::Sequence< css::uno::Any > const & Arguments,
414 : css::uno::Reference< css::uno::XComponentContext > const & Context)
415 : throw (css::uno::Exception, css::uno::RuntimeException, std::exception)
416 : {
417 0 : if (Arguments.getLength() == 0) {
418 0 : return css::configuration::theDefaultProvider::get(Context);
419 : } else {
420 0 : OUString locale;
421 0 : for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
422 0 : css::beans::NamedValue v1;
423 0 : css::beans::PropertyValue v2;
424 0 : OUString name;
425 0 : css::uno::Any value;
426 0 : if (Arguments[i] >>= v1) {
427 0 : name = v1.Name;
428 0 : value = v1.Value;
429 0 : } else if (Arguments[i] >>= v2) {
430 0 : name = v2.Name;
431 0 : value = v2.Value;
432 : } else {
433 : throw css::uno::Exception(
434 : ("com.sun.star.configuration.ConfigurationProvider factory"
435 : " expects NamedValue or PropertyValue arguments"),
436 0 : 0);
437 : }
438 : // For backwards compatibility, allow "Locale" and (ignored)
439 : // "EnableAsync" in any case:
440 0 : if (name.equalsIgnoreAsciiCase("locale")) {
441 0 : if (!locale.isEmpty() || !(value >>= locale) ||
442 0 : locale.isEmpty())
443 : {
444 : throw css::uno::Exception(
445 : ("com.sun.star.configuration.ConfigurationProvider"
446 : " factory expects at most one, non-empty, string"
447 : " Locale argument"),
448 0 : 0);
449 : }
450 0 : } else if (!name.equalsIgnoreAsciiCase("enableasync")) {
451 : throw css::uno::Exception(
452 : ("com.sun.star.configuration.ConfigurationProvider factory:"
453 0 : " unknown argument " + name),
454 0 : 0);
455 : }
456 0 : }
457 0 : return static_cast< cppu::OWeakObject * >(new Service(Context, locale));
458 : }
459 : }
460 :
461 : }
462 :
463 0 : css::uno::Reference< css::uno::XInterface > createDefault(
464 : css::uno::Reference< css::uno::XComponentContext > const & context)
465 : {
466 0 : return static_cast< cppu::OWeakObject * >(new Service(context));
467 : }
468 :
469 0 : OUString getImplementationName() {
470 0 : return OUString("com.sun.star.comp.configuration.ConfigurationProvider");
471 : }
472 :
473 0 : css::uno::Sequence< OUString > getSupportedServiceNames() {
474 0 : OUString name("com.sun.star.configuration.ConfigurationProvider");
475 0 : return css::uno::Sequence< OUString >(&name, 1);
476 : }
477 :
478 : css::uno::Reference< css::lang::XSingleComponentFactory >
479 0 : createFactory(
480 : SAL_UNUSED_PARAMETER cppu::ComponentFactoryFunc,
481 : SAL_UNUSED_PARAMETER OUString const &,
482 : SAL_UNUSED_PARAMETER css::uno::Sequence< OUString > const &,
483 : SAL_UNUSED_PARAMETER rtl_ModuleCount *)
484 : SAL_THROW(())
485 : {
486 0 : return new Factory;
487 : }
488 :
489 : } }
490 :
491 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|