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 381 : Service(
95 : css::uno::Reference< css::uno::XComponentContext > const context):
96 381 : ServiceBase(m_aMutex), context_(context), default_(true)
97 : {
98 381 : lock_ = lock();
99 : assert(context.is());
100 381 : }
101 :
102 2 : Service(
103 : css::uno::Reference< css::uno::XComponentContext > const context,
104 : OUString const & locale):
105 : ServiceBase(m_aMutex), context_(context), locale_(locale),
106 2 : default_(false)
107 : {
108 2 : lock_ = lock();
109 : assert(context.is());
110 2 : }
111 :
112 : private:
113 736 : virtual ~Service() {}
114 :
115 379 : 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 163338 : 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 163338 : OUString nodepath;
199 326676 : OUString locale;
200 371506 : for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
201 208408 : css::beans::NamedValue v1;
202 416576 : css::beans::PropertyValue v2;
203 416576 : OUString name;
204 416576 : css::uno::Any value;
205 208408 : if (Arguments[i] >>= v1) {
206 120229 : name = v1.Name;
207 120229 : value = v1.Value;
208 88179 : } else if (Arguments[i] >>= v2) {
209 87939 : name = v2.Name;
210 87939 : value = v2.Value;
211 240 : } else if (Arguments.getLength() == 1 && (Arguments[i] >>= nodepath)) {
212 : // For backwards compatibility, allow a single string argument that
213 : // denotes nodepath.
214 240 : if (nodepath.isEmpty()) {
215 0 : badNodePath();
216 : }
217 240 : 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 208168 : if (name.equalsIgnoreAsciiCase("nodepath")) {
227 326196 : if (!nodepath.isEmpty() || !(value >>= nodepath) ||
228 163098 : nodepath.isEmpty())
229 : {
230 0 : badNodePath();
231 : }
232 45070 : } else if (name.equalsIgnoreAsciiCase("locale")) {
233 8104 : if (!locale.isEmpty() || !(value >>= locale) ||
234 4052 : 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 208168 : }
243 163338 : if (nodepath.isEmpty()) {
244 0 : badNodePath();
245 : }
246 : // For backwards compatibility, allow a nodepath that misses the leading
247 : // slash:
248 163338 : if (nodepath[0] != '/') {
249 31844 : nodepath = "/" + nodepath;
250 : }
251 163338 : if (locale.isEmpty()) {
252 : //TODO: should the Access use the dynamically changing locale_ instead?
253 159286 : locale = locale_;
254 159286 : if (locale.isEmpty()) {
255 96109 : locale = "en-US";
256 : }
257 : }
258 : bool update;
259 163338 : if (ServiceSpecifier == accessServiceName) {
260 105791 : update = false;
261 57547 : } else if (ServiceSpecifier == updateAccessServiceName) {
262 57547 : 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 326676 : osl::MutexGuard guard(*lock_);
270 163338 : Components & components = Components::getSingleton(context_);
271 : rtl::Reference< RootAccess > root(
272 326676 : new RootAccess(components, nodepath, locale, update));
273 163338 : 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 163338 : components.addRootAccess(root);
280 326676 : return static_cast< cppu::OWeakObject * >(root.get());
281 : }
282 :
283 4 : css::uno::Sequence< OUString > Service::getAvailableServiceNames()
284 : throw (css::uno::RuntimeException, std::exception)
285 : {
286 4 : css::uno::Sequence< OUString > names(2);
287 4 : names[0] = accessServiceName;
288 4 : names[1] = updateAccessServiceName;
289 4 : return names;
290 : }
291 :
292 4 : void Service::refresh() throw (css::uno::RuntimeException, std::exception) {
293 : //TODO
294 : cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
295 4 : cppu::UnoType< css::util::XRefreshListener >::get());
296 4 : if (cont != 0) {
297 4 : css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
298 4 : cont->notifyEach(&css::util::XRefreshListener::refreshed, ev);
299 : }
300 4 : }
301 :
302 2 : void Service::addRefreshListener(
303 : css::uno::Reference< css::util::XRefreshListener > const & l)
304 : throw (css::uno::RuntimeException, std::exception)
305 : {
306 : rBHelper.addListener(
307 2 : cppu::UnoType< css::util::XRefreshListener >::get(), l);
308 2 : }
309 :
310 2 : void Service::removeRefreshListener(
311 : css::uno::Reference< css::util::XRefreshListener > const & l)
312 : throw (css::uno::RuntimeException, std::exception)
313 : {
314 : rBHelper.removeListener(
315 2 : cppu::UnoType< css::util::XRefreshListener >::get(), l);
316 2 : }
317 :
318 518 : void Service::flush() throw (css::uno::RuntimeException, std::exception) {
319 518 : flushModifications();
320 : cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
321 518 : cppu::UnoType< css::util::XFlushListener >::get());
322 518 : if (cont != 0) {
323 2 : css::lang::EventObject ev(static_cast< cppu::OWeakObject * >(this));
324 2 : cont->notifyEach(&css::util::XFlushListener::flushed, ev);
325 : }
326 518 : }
327 :
328 4 : void Service::addFlushListener(
329 : css::uno::Reference< css::util::XFlushListener > const & l)
330 : throw (css::uno::RuntimeException, std::exception)
331 : {
332 4 : rBHelper.addListener(cppu::UnoType< css::util::XFlushListener >::get(), l);
333 4 : }
334 :
335 2 : void Service::removeFlushListener(
336 : css::uno::Reference< css::util::XFlushListener > const & l)
337 : throw (css::uno::RuntimeException, std::exception)
338 : {
339 : rBHelper.removeListener(
340 2 : cppu::UnoType< css::util::XFlushListener >::get(), l);
341 2 : }
342 :
343 164 : void Service::setLocale(css::lang::Locale const & eLocale)
344 : throw (css::uno::RuntimeException, std::exception)
345 : {
346 164 : osl::MutexGuard guard(*lock_);
347 164 : locale_ = LanguageTag::convertToBcp47( eLocale, false);
348 164 : }
349 :
350 14553 : css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException, std::exception) {
351 14553 : osl::MutexGuard guard(*lock_);
352 14553 : css::lang::Locale loc;
353 14553 : if (! locale_.isEmpty()) {
354 3714 : loc = LanguageTag::convertToLocale( locale_, false);
355 : }
356 14553 : return loc;
357 : }
358 :
359 897 : void Service::flushModifications() const {
360 : Components * components;
361 : {
362 897 : osl::MutexGuard guard(*lock_);
363 897 : components = &Components::getSingleton(context_);
364 : }
365 897 : components->flushModifications();
366 897 : }
367 :
368 : class Factory:
369 : public cppu::WeakImplHelper2<
370 : css::lang::XSingleComponentFactory, css::lang::XServiceInfo >,
371 : private boost::noncopyable
372 : {
373 : public:
374 4 : Factory() {}
375 :
376 : private:
377 8 : 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 4 : 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 4 : css::uno::Sequence< css::uno::Any >(), Context);
409 : }
410 :
411 : css::uno::Reference< css::uno::XInterface >
412 6 : 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 6 : if (Arguments.getLength() == 0) {
418 4 : return css::configuration::theDefaultProvider::get(Context);
419 : } else {
420 2 : OUString locale;
421 4 : for (sal_Int32 i = 0; i < Arguments.getLength(); ++i) {
422 2 : css::beans::NamedValue v1;
423 4 : css::beans::PropertyValue v2;
424 4 : OUString name;
425 4 : css::uno::Any value;
426 2 : if (Arguments[i] >>= v1) {
427 2 : name = v1.Name;
428 2 : 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 2 : if (name.equalsIgnoreAsciiCase("locale")) {
441 4 : if (!locale.isEmpty() || !(value >>= locale) ||
442 2 : 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 2 : }
457 2 : return static_cast< cppu::OWeakObject * >(new Service(Context, locale));
458 : }
459 : }
460 :
461 : }
462 :
463 381 : css::uno::Reference< css::uno::XInterface > createDefault(
464 : css::uno::Reference< css::uno::XComponentContext > const & context)
465 : {
466 381 : return static_cast< cppu::OWeakObject * >(new Service(context));
467 : }
468 :
469 976 : OUString getImplementationName() {
470 976 : return OUString("com.sun.star.comp.configuration.ConfigurationProvider");
471 : }
472 :
473 4 : css::uno::Sequence< OUString > getSupportedServiceNames() {
474 4 : OUString name("com.sun.star.configuration.ConfigurationProvider");
475 4 : return css::uno::Sequence< OUString >(&name, 1);
476 : }
477 :
478 : css::uno::Reference< css::lang::XSingleComponentFactory >
479 4 : 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 : {
485 4 : return new Factory;
486 : }
487 :
488 : } }
489 :
490 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|