LibreOffice Module comphelper (master) 1
configuration.cxx
Go to the documentation of this file.
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
10#include <sal/config.h>
11
12#include <cassert>
13#include <mutex>
14#include <string_view>
15#include <unordered_map>
16
17#include <com/sun/star/beans/NamedValue.hpp>
18#include <com/sun/star/beans/PropertyAttribute.hpp>
19#include <com/sun/star/configuration/ReadOnlyAccess.hpp>
20#include <com/sun/star/configuration/ReadWriteAccess.hpp>
21#include <com/sun/star/configuration/XReadWriteAccess.hpp>
22#include <com/sun/star/configuration/theDefaultProvider.hpp>
23#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
24#include <com/sun/star/container/XHierarchicalNameReplace.hpp>
25#include <com/sun/star/container/XNameAccess.hpp>
26#include <com/sun/star/container/XNameContainer.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 <com/sun/star/util/XChangesListener.hpp>
31#include <com/sun/star/util/XChangesNotifier.hpp>
36#include <rtl/ustring.hxx>
37#include <sal/log.hxx>
39
40namespace com::sun::star::uno { class XComponentContext; }
41
42namespace {
43
44OUString getDefaultLocale(
45 css::uno::Reference< css::uno::XComponentContext > const & context)
46{
47 return LanguageTag(
48 css::uno::Reference< css::lang::XLocalizable >(
49 css::configuration::theDefaultProvider::get(context),
50 css::uno::UNO_QUERY_THROW)->
51 getLocale()).getBcp47(false);
52}
53
54OUString extendLocalizedPath(std::u16string_view path, OUString const & locale) {
56 locale.match("*"), "comphelper",
57 "Locale \"" << locale << "\" starts with \"*\"");
58 assert(locale.indexOf('&') == -1);
59 assert(locale.indexOf('"') == -1);
60 assert(locale.indexOf('\'') == -1);
61 return OUString::Concat(path) + "/['*" + locale + "']";
62}
63
64}
65
66std::shared_ptr< comphelper::ConfigurationChanges >
68{
70}
71
73
75 access_->commitChanges();
76}
77
79 css::uno::Reference< css::uno::XComponentContext > const & context):
80 access_(
81 css::configuration::ReadWriteAccess::create(
82 context, getDefaultLocale(context)))
83{}
84
86 OUString const & path, css::uno::Any const & value) const
87{
88 access_->replaceByHierarchicalName(path, value);
89}
90
91css::uno::Reference< css::container::XHierarchicalNameReplace >
93{
94 return css::uno::Reference< css::container::XHierarchicalNameReplace >(
95 access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
96}
97
98css::uno::Reference< css::container::XNameContainer >
99comphelper::ConfigurationChanges::getSet(OUString const & path) const
100{
101 return css::uno::Reference< css::container::XNameContainer >(
102 access_->getByHierarchicalName(path), css::uno::UNO_QUERY_THROW);
103}
104
107{
109 return WRAPPER;
110}
111
112namespace
113{
114std::mutex gMutex;
115std::unordered_map<OUString, css::uno::Any> gPropertyCache;
116css::uno::Reference< css::util::XChangesNotifier > gNotifier;
117css::uno::Reference< css::util::XChangesListener > gListener;
118
119class ConfigurationChangesListener
120 : public ::cppu::WeakImplHelper<css::util::XChangesListener>
121{
122public:
123 ConfigurationChangesListener()
124 {}
125 // util::XChangesListener
126 virtual void SAL_CALL changesOccurred( const css::util::ChangesEvent& ) override
127 {
128 std::scoped_lock aGuard(gMutex);
129 gPropertyCache.clear();
130 }
131 virtual void SAL_CALL disposing(const css::lang::EventObject&) override {}
132};
133
134} // namespace
135
138 access_(css::configuration::ReadWriteAccess::create(context_, "*"))
139{
140 // Set up a configuration notifier to invalidate the cache as needed.
141 try
142 {
143 css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
144 css::configuration::theDefaultProvider::get( context_ ) );
145
146 // set root path
147 css::uno::Sequence< css::uno::Any > params {
148 css::uno::Any( css::beans::NamedValue{ "nodepath", css::uno::Any( OUString("/"))} ),
149 css::uno::Any( css::beans::NamedValue{ "locale", css::uno::Any( OUString("*"))} ) };
150
151 css::uno::Reference< css::uno::XInterface > xCfg
152 = xConfigProvider->createInstanceWithArguments(u"com.sun.star.configuration.ConfigurationAccess",
153 params);
154
155 gNotifier = css::uno::Reference< css::util::XChangesNotifier >(xCfg, css::uno::UNO_QUERY);
156 assert(gNotifier.is());
157 gListener = css::uno::Reference< ConfigurationChangesListener >(new ConfigurationChangesListener());
158 gNotifier->addChangesListener(gListener);
159 }
160 catch(const css::uno::Exception&)
161 {
162 assert(false);
163 }
164}
165
167{
168 gPropertyCache.clear();
169 gNotifier.clear();
170 gListener.clear();
171}
172
174 const
175{
176 return
177 (access_->getPropertyByHierarchicalName(path).Attributes
178 & css::beans::PropertyAttribute::READONLY)
179 != 0;
180}
181
182css::uno::Any comphelper::detail::ConfigurationWrapper::getPropertyValue(OUString const& path) const
183{
184 std::scoped_lock aGuard(gMutex);
185 // Cache the configuration access, since some of the keys are used in hot code.
186 auto it = gPropertyCache.find(path);
187 if( it != gPropertyCache.end())
188 return it->second;
189
190 sal_Int32 idx = path.lastIndexOf("/");
191 assert(idx!=-1);
192 OUString parentPath = path.copy(0, idx);
193 OUString childName = path.copy(idx+1);
194
195 css::uno::Reference<css::container::XNameAccess> access(
196 access_->getByHierarchicalName(parentPath), css::uno::UNO_QUERY_THROW);
197 css::uno::Any property = access->getByName(childName);
198 gPropertyCache.emplace(path, property);
199 return property;
200}
201
203 std::shared_ptr< ConfigurationChanges > const & batch,
204 OUString const & path, css::uno::Any const & value)
205{
206 assert(batch);
207 batch->setPropertyValue(path, value);
208}
209
210css::uno::Any
212 std::u16string_view path) const
213{
214 return access_->getByHierarchicalName(
215 extendLocalizedPath(path, getDefaultLocale(context_)));
216}
217
219 std::shared_ptr< ConfigurationChanges > const & batch,
220 OUString const & path, css::uno::Any const & value)
221{
222 assert(batch);
223 batch->setPropertyValue(path, value);
224}
225
226css::uno::Reference< css::container::XHierarchicalNameAccess >
228 OUString const & path) const
229{
230 return css::uno::Reference< css::container::XHierarchicalNameAccess >(
231 (css::configuration::ReadOnlyAccess::create(
232 context_, getDefaultLocale(context_))->
233 getByHierarchicalName(path)),
234 css::uno::UNO_QUERY_THROW);
235}
236
237css::uno::Reference< css::container::XHierarchicalNameReplace >
239 std::shared_ptr< ConfigurationChanges > const & batch,
240 OUString const & path)
241{
242 assert(batch);
243 return batch->getGroup(path);
244}
245
246css::uno::Reference< css::container::XNameAccess >
248 OUString const & path) const
249{
250 return css::uno::Reference< css::container::XNameAccess >(
251 (css::configuration::ReadOnlyAccess::create(
252 context_, getDefaultLocale(context_))->
253 getByHierarchicalName(path)),
254 css::uno::UNO_QUERY_THROW);
255}
256
257css::uno::Reference< css::container::XNameContainer >
259 std::shared_ptr< ConfigurationChanges > const & batch,
260 OUString const & path)
261{
262 assert(batch);
263 return batch->getSet(path);
264}
265
266std::shared_ptr< comphelper::ConfigurationChanges >
268 return std::shared_ptr< ConfigurationChanges >(
270}
271
273{
274 maListeners.push_back( pListener );
275 mxConfig->addPropertyChangeListener( pListener->maName, this );
276 pListener->setProperty( mxConfig->getPropertyValue( pListener->maName ) );
277}
278
280{
281 auto it = std::find( maListeners.begin(), maListeners.end(), pListener );
282 if ( it != maListeners.end() )
283 {
284 maListeners.erase( it );
285 mxConfig->removePropertyChangeListener( pListener->maName, this );
286 }
287}
288
290{
291 for (auto const& listener : maListeners)
292 {
293 mxConfig->removePropertyChangeListener( listener->maName, this );
294 listener->dispose();
295 }
296 maListeners.clear();
297 mbDisposed = true;
298}
299
300void SAL_CALL comphelper::ConfigurationListener::disposing(css::lang::EventObject const &)
301{
302 dispose();
303}
304
306 css::beans::PropertyChangeEvent const &rEvt )
307{
308 // Code is commonly used inside the SolarMutexGuard
309 // so to avoid concurrent writes to the property,
310 // and allow fast, lock-less access, guard here.
311 //
312 // Note that we are abusing rtl::Reference here to do acquire/release because,
313 // unlike osl::Guard, it is tolerant of null pointers, and on some code paths, the
314 // SolarMutex does not exist.
316
317 assert( rEvt.Source == mxConfig );
318 for (auto const& listener : maListeners)
319 {
320 if ( listener->maName == rEvt.PropertyName )
321 {
322 // ignore rEvt.NewValue - in theory it could be stale => not set.
323 css::uno::Any aValue = mxConfig->getPropertyValue( listener->maName );
324 listener->setProperty( aValue );
325 }
326 }
327}
328
329/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUString & getBcp47(bool bResolveSystem=true) const
A batch of configuration changes that is committed as a whole.
SAL_DLLPRIVATE css::uno::Reference< css::container::XHierarchicalNameReplace > getGroup(OUString const &path) const
static std::shared_ptr< ConfigurationChanges > create()
SAL_DLLPRIVATE void setPropertyValue(OUString const &path, css::uno::Any const &value) const
ConfigurationChanges(const ConfigurationChanges &)=delete
SAL_DLLPRIVATE css::uno::Reference< css::container::XNameContainer > getSet(OUString const &path) const
virtual void setProperty(const css::uno::Any &aProperty)=0
void removeListener(ConfigurationListenerPropertyBase *pListener)
Stop listening.
virtual void SAL_CALL propertyChange(css::beans::PropertyChangeEvent const &rEvt) override
Notify of the property change.
void addListener(ConfigurationListenerPropertyBase *pListener)
Listen for the specific property denoted by the listener.
void dispose()
Release various circular references.
virtual void SAL_CALL disposing(css::lang::EventObject const &) override
static SolarMutex * get()
Help components to get the SolarMutex easily.
Definition: solarmutex.cxx:34
css::uno::Reference< css::container::XHierarchicalNameAccess > getGroupReadOnly(OUString const &path) const
css::uno::Any getLocalizedPropertyValue(std::u16string_view path) const
bool isReadOnly(OUString const &path) const
css::uno::Any getPropertyValue(OUString const &path) const
static void setPropertyValue(std::shared_ptr< ConfigurationChanges > const &batch, OUString const &path, css::uno::Any const &value)
css::uno::Reference< css::uno::XComponentContext > context_
static void setLocalizedPropertyValue(std::shared_ptr< ConfigurationChanges > const &batch, OUString const &path, css::uno::Any const &value)
css::uno::Reference< css::container::XNameAccess > getSetReadOnly(OUString const &path) const
static css::uno::Reference< css::container::XNameContainer > getSetReadWrite(std::shared_ptr< ConfigurationChanges > const &batch, OUString const &path)
static ConfigurationWrapper const & get()
static css::uno::Reference< css::container::XHierarchicalNameReplace > getGroupReadWrite(std::shared_ptr< ConfigurationChanges > const &batch, OUString const &path)
std::shared_ptr< ConfigurationChanges > createChanges() const
Any value
css::uno::Reference< css::uno::XInterface > access_
float u
const sal_uInt16 idx[]
#define SAL_WARN_IF(condition, area, stream)
const LanguageTag & getLocale()
Get the current LOK's locale.
Definition: lok.cxx:189
Reference< XComponentContext > getProcessComponentContext()
This function gets the process service factory's default component context.
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
void dispose()
static PropertyMapEntry const * find(const rtl::Reference< PropertySetInfo > &mxInfo, const OUString &aName) noexcept
std::mutex mutex
Definition: random.cxx:41
uno::Reference< uno::XComponentContext > context_