android: Update app-specific/MIME type icons
[LibreOffice.git] / comphelper / source / misc / configuration.cxx
blobf91e85852831b6158bd7fa222e9b744f57cfbe65
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
12 #include <cassert>
14 #include <com/sun/star/beans/NamedValue.hpp>
15 #include <com/sun/star/beans/PropertyAttribute.hpp>
16 #include <com/sun/star/configuration/ReadOnlyAccess.hpp>
17 #include <com/sun/star/configuration/ReadWriteAccess.hpp>
18 #include <com/sun/star/configuration/XReadWriteAccess.hpp>
19 #include <com/sun/star/configuration/theDefaultProvider.hpp>
20 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
21 #include <com/sun/star/container/XHierarchicalNameReplace.hpp>
22 #include <com/sun/star/container/XNameAccess.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/util/XChangesListener.hpp>
25 #include <com/sun/star/util/XChangesNotifier.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/lang/XLocalizable.hpp>
28 #include <com/sun/star/uno/Any.hxx>
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <comphelper/solarmutex.hxx>
31 #include <comphelper/configuration.hxx>
32 #include <comphelper/configurationlistener.hxx>
33 #include <cppuhelper/implbase.hxx>
34 #include <rtl/ustring.hxx>
35 #include <sal/log.hxx>
36 #include <i18nlangtag/languagetag.hxx>
38 namespace com::sun::star::uno { class XComponentContext; }
40 namespace {
42 OUString getDefaultLocale(
43 css::uno::Reference< css::uno::XComponentContext > const & context)
45 return LanguageTag(
46 css::uno::Reference< css::lang::XLocalizable >(
47 css::configuration::theDefaultProvider::get(context),
48 css::uno::UNO_QUERY_THROW)->
49 getLocale()).getBcp47(false);
52 OUString extendLocalizedPath(std::u16string_view path, OUString const & locale) {
53 SAL_WARN_IF(
54 locale.match("*"), "comphelper",
55 "Locale \"" << locale << "\" starts with \"*\"");
56 assert(locale.indexOf('&') == -1);
57 assert(locale.indexOf('"') == -1);
58 assert(locale.indexOf('\'') == -1);
59 return OUString::Concat(path) + "/['*" + locale + "']";
64 std::shared_ptr< comphelper::ConfigurationChanges >
65 comphelper::ConfigurationChanges::create()
67 return detail::ConfigurationWrapper::get().createChanges();
70 comphelper::ConfigurationChanges::~ConfigurationChanges() {}
72 void comphelper::ConfigurationChanges::commit() const {
73 access_->commitChanges();
76 comphelper::ConfigurationChanges::ConfigurationChanges(
77 css::uno::Reference< css::uno::XComponentContext > const & context):
78 access_(
79 css::configuration::ReadWriteAccess::create(
80 context, getDefaultLocale(context)))
83 void comphelper::ConfigurationChanges::setPropertyValue(
84 OUString const & path, css::uno::Any const & value) const
86 access_->replaceByHierarchicalName(path, value);
89 css::uno::Reference< css::container::XHierarchicalNameReplace >
90 comphelper::ConfigurationChanges::getGroup(OUString const & path) const
92 return css::uno::Reference< css::container::XHierarchicalNameReplace >(
93 access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
96 css::uno::Reference< css::container::XNameContainer >
97 comphelper::ConfigurationChanges::getSet(OUString const & path) const
99 return css::uno::Reference< css::container::XNameContainer >(
100 access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
103 comphelper::detail::ConfigurationWrapper const &
104 comphelper::detail::ConfigurationWrapper::get()
106 static comphelper::detail::ConfigurationWrapper WRAPPER;
107 return WRAPPER;
110 class comphelper::detail::ConfigurationChangesListener
111 : public ::cppu::WeakImplHelper<css::util::XChangesListener>
113 comphelper::detail::ConfigurationWrapper& mrConfigurationWrapper;
114 public:
115 ConfigurationChangesListener(comphelper::detail::ConfigurationWrapper& rWrapper)
116 : mrConfigurationWrapper(rWrapper)
118 // util::XChangesListener
119 virtual void SAL_CALL changesOccurred( const css::util::ChangesEvent& ) override
121 std::scoped_lock aGuard(mrConfigurationWrapper.maMutex);
122 mrConfigurationWrapper.maPropertyCache.clear();
124 virtual void SAL_CALL disposing(const css::lang::EventObject&) override
126 std::scoped_lock aGuard(mrConfigurationWrapper.maMutex);
127 mrConfigurationWrapper.mbDisposed = true;
128 mrConfigurationWrapper.maPropertyCache.clear();
129 mrConfigurationWrapper.maNotifier.clear();
130 mrConfigurationWrapper.maListener.clear();
134 comphelper::detail::ConfigurationWrapper::ConfigurationWrapper():
135 context_(comphelper::getProcessComponentContext()),
136 access_(css::configuration::ReadWriteAccess::create(context_, "*")),
137 mbDisposed(false)
139 // Set up a configuration notifier to invalidate the cache as needed.
142 css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
143 css::configuration::theDefaultProvider::get( context_ ) );
145 // set root path
146 css::uno::Sequence< css::uno::Any > params {
147 css::uno::Any( css::beans::NamedValue{ "nodepath", css::uno::Any( OUString("/"))} ),
148 css::uno::Any( css::beans::NamedValue{ "locale", css::uno::Any( OUString("*"))} ) };
150 css::uno::Reference< css::uno::XInterface > xCfg
151 = xConfigProvider->createInstanceWithArguments(u"com.sun.star.configuration.ConfigurationAccess",
152 params);
154 maNotifier = css::uno::Reference< css::util::XChangesNotifier >(xCfg, css::uno::UNO_QUERY);
155 assert(maNotifier.is());
156 maListener = css::uno::Reference< ConfigurationChangesListener >(new ConfigurationChangesListener(*this));
157 maNotifier->addChangesListener(maListener);
159 catch(const css::uno::Exception&)
161 assert(false);
165 comphelper::detail::ConfigurationWrapper::~ConfigurationWrapper()
167 maPropertyCache.clear();
168 maNotifier.clear();
169 maListener.clear();
172 bool comphelper::detail::ConfigurationWrapper::isReadOnly(OUString const & path)
173 const
175 return
176 (access_->getPropertyByHierarchicalName(path).Attributes
177 & css::beans::PropertyAttribute::READONLY)
178 != 0;
181 css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(OUString const& path) const
183 std::scoped_lock aGuard(maMutex);
184 if (mbDisposed)
185 throw css::lang::DisposedException();
186 // Cache the configuration access, since some of the keys are used in hot code.
187 auto it = maPropertyCache.find(path);
188 if( it != maPropertyCache.end())
189 return it->second;
191 sal_Int32 idx = path.lastIndexOf("/");
192 assert(idx!=-1);
193 OUString parentPath = path.copy(0, idx);
194 OUString childName = path.copy(idx+1);
196 css::uno::Reference<css::container::XNameAccess> access(
197 access_->getByHierarchicalName(parentPath), css::uno::UNO_QUERY_THROW);
198 css::uno::Any property = access->getByName(childName);
199 maPropertyCache.emplace(path, property);
200 return property;
203 void comphelper::detail::ConfigurationWrapper::setPropertyValue(
204 std::shared_ptr< ConfigurationChanges > const & batch,
205 OUString const & path, css::uno::Any const & value)
207 assert(batch);
208 batch->setPropertyValue(path, value);
211 css::uno::Any
212 comphelper::detail::ConfigurationWrapper::getLocalizedPropertyValue(
213 std::u16string_view path) const
215 return access_->getByHierarchicalName(
216 extendLocalizedPath(path, getDefaultLocale(context_)));
219 void comphelper::detail::ConfigurationWrapper::setLocalizedPropertyValue(
220 std::shared_ptr< ConfigurationChanges > const & batch,
221 OUString const & path, css::uno::Any const & value)
223 assert(batch);
224 batch->setPropertyValue(path, value);
227 css::uno::Reference< css::container::XHierarchicalNameAccess >
228 comphelper::detail::ConfigurationWrapper::getGroupReadOnly(
229 OUString const & path) const
231 return css::uno::Reference< css::container::XHierarchicalNameAccess >(
232 (css::configuration::ReadOnlyAccess::create(
233 context_, getDefaultLocale(context_))->
234 getByHierarchicalName(path)),
235 css::uno::UNO_QUERY_THROW);
238 css::uno::Reference< css::container::XHierarchicalNameReplace >
239 comphelper::detail::ConfigurationWrapper::getGroupReadWrite(
240 std::shared_ptr< ConfigurationChanges > const & batch,
241 OUString const & path)
243 assert(batch);
244 return batch->getGroup(path);
247 css::uno::Reference< css::container::XNameAccess >
248 comphelper::detail::ConfigurationWrapper::getSetReadOnly(
249 OUString const & path) const
251 return css::uno::Reference< css::container::XNameAccess >(
252 (css::configuration::ReadOnlyAccess::create(
253 context_, getDefaultLocale(context_))->
254 getByHierarchicalName(path)),
255 css::uno::UNO_QUERY_THROW);
258 css::uno::Reference< css::container::XNameContainer >
259 comphelper::detail::ConfigurationWrapper::getSetReadWrite(
260 std::shared_ptr< ConfigurationChanges > const & batch,
261 OUString const & path)
263 assert(batch);
264 return batch->getSet(path);
267 std::shared_ptr< comphelper::ConfigurationChanges >
268 comphelper::detail::ConfigurationWrapper::createChanges() const {
269 return std::shared_ptr< ConfigurationChanges >(
270 new ConfigurationChanges(context_));
273 void comphelper::ConfigurationListener::addListener(ConfigurationListenerPropertyBase *pListener)
275 maListeners.push_back( pListener );
276 mxConfig->addPropertyChangeListener( pListener->maName, this );
277 pListener->setProperty( mxConfig->getPropertyValue( pListener->maName ) );
280 void comphelper::ConfigurationListener::removeListener(ConfigurationListenerPropertyBase *pListener)
282 auto it = std::find( maListeners.begin(), maListeners.end(), pListener );
283 if ( it != maListeners.end() )
285 maListeners.erase( it );
286 mxConfig->removePropertyChangeListener( pListener->maName, this );
290 void comphelper::ConfigurationListener::dispose()
292 for (auto const& listener : maListeners)
294 mxConfig->removePropertyChangeListener( listener->maName, this );
295 listener->dispose();
297 maListeners.clear();
298 mbDisposed = true;
301 void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &)
303 dispose();
306 void SAL_CALL comphelper::ConfigurationListener::propertyChange(
307 css::beans::PropertyChangeEvent const &rEvt )
309 // Code is commonly used inside the SolarMutexGuard
310 // so to avoid concurrent writes to the property,
311 // and allow fast, lock-less access, guard here.
313 // Note that we are abusing rtl::Reference here to do acquire/release because,
314 // unlike osl::Guard, it is tolerant of null pointers, and on some code paths, the
315 // SolarMutex does not exist.
316 rtl::Reference<comphelper::SolarMutex> xMutexGuard( comphelper::SolarMutex::get() );
318 assert( rEvt.Source == mxConfig );
319 for (auto const& listener : maListeners)
321 if ( listener->maName == rEvt.PropertyName )
323 // ignore rEvt.NewValue - in theory it could be stale => not set.
324 css::uno::Any aValue = mxConfig->getPropertyValue( listener->maName );
325 listener->setProperty( aValue );
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */