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