LCOV - code coverage report
Current view: top level - configmgr/source - configurationprovider.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 126 159 79.2 %
Date: 2014-11-03 Functions: 25 33 75.8 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10