summaryrefslogtreecommitdiffstats
path: root/comphelper/source/misc/configuration.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comphelper/source/misc/configuration.cxx265
1 files changed, 265 insertions, 0 deletions
diff --git a/comphelper/source/misc/configuration.cxx b/comphelper/source/misc/configuration.cxx
new file mode 100644
index 000000000..6c5b5c41d
--- /dev/null
+++ b/comphelper/source/misc/configuration.cxx
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cassert>
+#include <memory>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/configuration/ReadOnlyAccess.hpp>
+#include <com/sun/star/configuration/ReadWriteAccess.hpp>
+#include <com/sun/star/configuration/XReadWriteAccess.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameReplace.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XLocalizable.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <comphelper/solarmutex.hxx>
+#include <comphelper/configuration.hxx>
+#include <comphelper/configurationlistener.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace {
+
+struct TheConfigurationWrapper:
+ public rtl::StaticWithArg<
+ comphelper::detail::ConfigurationWrapper,
+ css::uno::Reference< css::uno::XComponentContext >,
+ TheConfigurationWrapper >
+{};
+
+OUString getDefaultLocale(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ return LanguageTag(
+ css::uno::Reference< css::lang::XLocalizable >(
+ css::configuration::theDefaultProvider::get(context),
+ css::uno::UNO_QUERY_THROW)->
+ getLocale()).getBcp47(false);
+}
+
+OUString extendLocalizedPath(OUString const & path, OUString const & locale) {
+ SAL_WARN_IF(
+ locale.match("*"), "comphelper",
+ "Locale \"" << locale << "\" starts with \"*\"");
+ assert(locale.indexOf('&') == -1);
+ assert(locale.indexOf('"') == -1);
+ assert(locale.indexOf('\'') == -1);
+ return path + "/['*" + locale + "']";
+}
+
+}
+
+std::shared_ptr< comphelper::ConfigurationChanges >
+comphelper::ConfigurationChanges::create(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ return TheConfigurationWrapper::get(context).createChanges();
+}
+
+comphelper::ConfigurationChanges::~ConfigurationChanges() {}
+
+void comphelper::ConfigurationChanges::commit() const {
+ access_->commitChanges();
+}
+
+comphelper::ConfigurationChanges::ConfigurationChanges(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ access_(
+ css::configuration::ReadWriteAccess::create(
+ context, getDefaultLocale(context)))
+{}
+
+void comphelper::ConfigurationChanges::setPropertyValue(
+ OUString const & path, css::uno::Any const & value) const
+{
+ access_->replaceByHierarchicalName(path, value);
+}
+
+css::uno::Reference< css::container::XHierarchicalNameReplace >
+comphelper::ConfigurationChanges::getGroup(OUString const & path) const
+{
+ return css::uno::Reference< css::container::XHierarchicalNameReplace >(
+ access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
+}
+
+css::uno::Reference< css::container::XNameContainer >
+comphelper::ConfigurationChanges::getSet(OUString const & path) const
+{
+ return css::uno::Reference< css::container::XNameContainer >(
+ access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
+}
+
+comphelper::detail::ConfigurationWrapper const &
+comphelper::detail::ConfigurationWrapper::get(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+{
+ return TheConfigurationWrapper::get(context);
+}
+
+comphelper::detail::ConfigurationWrapper::ConfigurationWrapper(
+ css::uno::Reference< css::uno::XComponentContext > const & context):
+ context_(context),
+ access_(css::configuration::ReadWriteAccess::create(context, "*"))
+{}
+
+comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper() {}
+
+bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path)
+ const
+{
+ return
+ (access_->getPropertyByHierarchicalName(path).Attributes
+ & css::beans::PropertyAttribute::READONLY)
+ != 0;
+}
+
+css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(
+ OUString const & path) const
+{
+ return access_->getByHierarchicalName(path);
+}
+
+void comphelper::detail::ConfigurationWrapper::setPropertyValue(
+ std::shared_ptr< ConfigurationChanges > const & batch,
+ OUString const & path, css::uno::Any const & value)
+{
+ assert(batch.get() != nullptr);
+ batch->setPropertyValue(path, value);
+}
+
+css::uno::Any
+comphelper::detail::ConfigurationWrapper::getLocalizedPropertyValue(
+ OUString const & path) const
+{
+ return access_->getByHierarchicalName(
+ extendLocalizedPath(path, getDefaultLocale(context_)));
+}
+
+void comphelper::detail::ConfigurationWrapper::setLocalizedPropertyValue(
+ std::shared_ptr< ConfigurationChanges > const & batch,
+ OUString const & path, css::uno::Any const & value)
+{
+ assert(batch.get() != nullptr);
+ batch->setPropertyValue(path, value);
+}
+
+css::uno::Reference< css::container::XHierarchicalNameAccess >
+comphelper::detail::ConfigurationWrapper::getGroupReadOnly(
+ OUString const & path) const
+{
+ return css::uno::Reference< css::container::XHierarchicalNameAccess >(
+ (css::configuration::ReadOnlyAccess::create(
+ context_, getDefaultLocale(context_))->
+ getByHierarchicalName(path)),
+ css::uno::UNO_QUERY_THROW);
+}
+
+css::uno::Reference< css::container::XHierarchicalNameReplace >
+comphelper::detail::ConfigurationWrapper::getGroupReadWrite(
+ std::shared_ptr< ConfigurationChanges > const & batch,
+ OUString const & path)
+{
+ assert(batch.get() != nullptr);
+ return batch->getGroup(path);
+}
+
+css::uno::Reference< css::container::XNameAccess >
+comphelper::detail::ConfigurationWrapper::getSetReadOnly(
+ OUString const & path) const
+{
+ return css::uno::Reference< css::container::XNameAccess >(
+ (css::configuration::ReadOnlyAccess::create(
+ context_, getDefaultLocale(context_))->
+ getByHierarchicalName(path)),
+ css::uno::UNO_QUERY_THROW);
+}
+
+css::uno::Reference< css::container::XNameContainer >
+comphelper::detail::ConfigurationWrapper::getSetReadWrite(
+ std::shared_ptr< ConfigurationChanges > const & batch,
+ OUString const & path)
+{
+ assert(batch.get() != nullptr);
+ return batch->getSet(path);
+}
+
+std::shared_ptr< comphelper::ConfigurationChanges >
+comphelper::detail::ConfigurationWrapper::createChanges() const {
+ return std::shared_ptr< ConfigurationChanges >(
+ new ConfigurationChanges(context_));
+}
+
+void comphelper::ConfigurationListener::addListener(ConfigurationListenerPropertyBase *pListener)
+{
+ maListeners.push_back( pListener );
+ mxConfig->addPropertyChangeListener( pListener->maName, this );
+ pListener->setProperty( mxConfig->getPropertyValue( pListener->maName ) );
+}
+
+void comphelper::ConfigurationListener::removeListener(ConfigurationListenerPropertyBase *pListener)
+{
+ auto it = std::find( maListeners.begin(), maListeners.end(), pListener );
+ if ( it != maListeners.end() )
+ {
+ maListeners.erase( it );
+ mxConfig->removePropertyChangeListener( pListener->maName, this );
+ }
+}
+
+void comphelper::ConfigurationListener::dispose()
+{
+ for (auto const& listener : maListeners)
+ {
+ mxConfig->removePropertyChangeListener( listener->maName, this );
+ listener->dispose();
+ }
+ maListeners.clear();
+}
+
+void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &)
+{
+ dispose();
+}
+
+void SAL_CALL comphelper::ConfigurationListener::propertyChange(
+ css::beans::PropertyChangeEvent const &rEvt )
+{
+ // Code is commonly used inside the SolarMutexGuard
+ // so to avoid concurrent writes to the property,
+ // and allow fast, lock-less access, guard here.
+ //
+ // Note that we are abusing rtl::Reference here to do acquire/release because,
+ // unlike osl::Guard, it is tolerant of null pointers, and on some code paths, the
+ // SolarMutex does not exist.
+ rtl::Reference<comphelper::SolarMutex> xMutexGuard( comphelper::SolarMutex::get() );
+
+ assert( rEvt.Source == mxConfig );
+ for (auto const& listener : maListeners)
+ {
+ if ( listener->maName == rEvt.PropertyName )
+ {
+ // ignore rEvt.NewValue - in theory it could be stale => not set.
+ css::uno::Any aValue = mxConfig->getPropertyValue( listener->maName );
+ listener->setProperty( aValue );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */