Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / framework / source / services / pathsettings.cxx
blob9457ad8627876038c3d86c5f4923100f2dfa3d4f
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
23 #include <utility>
24 #include <unordered_map>
26 #include <properties.h>
27 #include <helper/mischelper.hxx>
29 #include <com/sun/star/beans/Property.hpp>
30 #include <com/sun/star/beans/XProperty.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/util/XChangesNotifier.hpp>
34 #include <com/sun/star/util/PathSubstitution.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/lang/XServiceInfo.hpp>
37 #include <com/sun/star/util/XStringSubstitution.hpp>
38 #include <com/sun/star/util/XChangesListener.hpp>
39 #include <com/sun/star/util/XPathSettings.hpp>
41 #include <tools/urlobj.hxx>
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/ref.hxx>
44 #include <sal/log.hxx>
46 #include <cppuhelper/basemutex.hxx>
47 #include <cppuhelper/propshlp.hxx>
48 #include <cppuhelper/compbase.hxx>
49 #include <cppuhelper/supportsservice.hxx>
50 #include <comphelper/sequence.hxx>
51 #include <comphelper/configurationhelper.hxx>
52 #include <unotools/configpaths.hxx>
53 #include <o3tl/string_view.hxx>
55 using namespace framework;
57 constexpr OUStringLiteral CFGPROP_USERPATHS = u"UserPaths";
58 constexpr OUStringLiteral CFGPROP_WRITEPATH = u"WritePath";
61 0 : old style "Template" string using ";" as separator
62 1 : internal paths "Template_internal" string list
63 2 : user paths "Template_user" string list
64 3 : write path "Template_write" string
67 constexpr OUStringLiteral POSTFIX_INTERNAL_PATHS = u"_internal";
68 constexpr OUStringLiteral POSTFIX_USER_PATHS = u"_user";
69 constexpr OUStringLiteral POSTFIX_WRITE_PATH = u"_writable";
71 namespace {
73 const sal_Int32 IDGROUP_OLDSTYLE = 0;
74 const sal_Int32 IDGROUP_INTERNAL_PATHS = 1;
75 const sal_Int32 IDGROUP_USER_PATHS = 2;
76 const sal_Int32 IDGROUP_WRITE_PATH = 3;
78 const sal_Int32 IDGROUP_COUNT = 4;
80 sal_Int32 impl_getPropGroup(sal_Int32 nID)
82 return (nID % IDGROUP_COUNT);
85 /* enable it if you wish to migrate old user settings (using the old cfg schema) on demand...
86 disable it in case only the new schema must be used.
89 typedef ::cppu::WeakComponentImplHelper<
90 css::lang::XServiceInfo,
91 css::util::XChangesListener, // => XEventListener
92 css::util::XPathSettings> // => XPropertySet
93 PathSettings_BASE;
95 class PathSettings : private cppu::BaseMutex
96 , public PathSettings_BASE
97 , public ::cppu::OPropertySetHelper
99 struct PathInfo
101 public:
103 PathInfo()
104 : bIsSinglePath (false)
105 , bIsReadonly (false)
108 /// an internal name describing this path
109 OUString sPathName;
111 /// contains all paths, which are used internally - but are not visible for the user.
112 std::vector<OUString> lInternalPaths;
114 /// contains all paths configured by the user
115 std::vector<OUString> lUserPaths;
117 /// this special path is used to generate feature depending content there
118 OUString sWritePath;
120 /// indicates real single paths, which uses WritePath property only
121 bool bIsSinglePath;
123 /// simple handling of finalized/mandatory states ... => we know one state READONLY only .-)
124 bool bIsReadonly;
127 typedef std::unordered_map<OUString, PathSettings::PathInfo> PathHash;
129 enum EChangeOp
131 E_UNDEFINED,
132 E_ADDED,
133 E_CHANGED,
134 E_REMOVED
137 private:
139 /** reference to factory, which has create this instance. */
140 css::uno::Reference< css::uno::XComponentContext > m_xContext;
142 /** list of all path variables and her corresponding values. */
143 PathSettings::PathHash m_lPaths;
145 /** describes all properties available on our interface.
146 Will be generated on demand based on our path list m_lPaths. */
147 css::uno::Sequence< css::beans::Property > m_lPropDesc;
149 /** helper needed to (re-)substitute all internal save path values. */
150 css::uno::Reference< css::util::XStringSubstitution > m_xSubstitution;
152 /** provides access to the old configuration schema (which will be migrated on demand). */
153 css::uno::Reference< css::container::XNameAccess > m_xCfgOld;
155 /** provides access to the new configuration schema. */
156 css::uno::Reference< css::container::XNameAccess > m_xCfgNew;
158 /** helper to listen for configuration changes without ownership cycle problems */
159 css::uno::Reference< css::util::XChangesListener > m_xCfgNewListener;
161 std::unique_ptr<::cppu::OPropertyArrayHelper> m_pPropHelp;
163 public:
165 /** initialize a new instance of this class.
166 Attention: It's necessary for right function of this class, that the order of base
167 classes is the right one. Because we transfer information from one base to another
168 during this ctor runs! */
169 explicit PathSettings(css::uno::Reference< css::uno::XComponentContext > xContext);
171 /** free all used resources ... if it was not already done. */
172 virtual ~PathSettings() override;
174 virtual OUString SAL_CALL getImplementationName() override
176 return "com.sun.star.comp.framework.PathSettings";
179 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
181 return cppu::supportsService(this, ServiceName);
184 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
186 return {"com.sun.star.util.PathSettings"};
189 // XInterface
190 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& type) override;
191 virtual void SAL_CALL acquire() noexcept override
192 { OWeakObject::acquire(); }
193 virtual void SAL_CALL release() noexcept override
194 { OWeakObject::release(); }
196 // XTypeProvider
197 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
199 // css::util::XChangesListener
200 virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) override;
202 // css::lang::XEventListener
203 virtual void SAL_CALL disposing(const css::lang::EventObject& aSource) override;
206 * XPathSettings attribute methods
208 virtual OUString SAL_CALL getAddin() override
209 { return getStringProperty("Addin"); }
210 virtual void SAL_CALL setAddin(const OUString& p1) override
211 { setStringProperty("Addin", p1); }
212 virtual OUString SAL_CALL getAutoCorrect() override
213 { return getStringProperty("AutoCorrect"); }
214 virtual void SAL_CALL setAutoCorrect(const OUString& p1) override
215 { setStringProperty("AutoCorrect", p1); }
216 virtual OUString SAL_CALL getAutoText() override
217 { return getStringProperty("AutoText"); }
218 virtual void SAL_CALL setAutoText(const OUString& p1) override
219 { setStringProperty("AutoText", p1); }
220 virtual OUString SAL_CALL getBackup() override
221 { return getStringProperty("Backup"); }
222 virtual void SAL_CALL setBackup(const OUString& p1) override
223 { setStringProperty("Backup", p1); }
224 virtual OUString SAL_CALL getBasic() override
225 { return getStringProperty("Basic"); }
226 virtual void SAL_CALL setBasic(const OUString& p1) override
227 { setStringProperty("Basic", p1); }
228 virtual OUString SAL_CALL getBitmap() override
229 { return getStringProperty("Bitmap"); }
230 virtual void SAL_CALL setBitmap(const OUString& p1) override
231 { setStringProperty("Bitmap", p1); }
232 virtual OUString SAL_CALL getConfig() override
233 { return getStringProperty("Config"); }
234 virtual void SAL_CALL setConfig(const OUString& p1) override
235 { setStringProperty("Config", p1); }
236 virtual OUString SAL_CALL getDictionary() override
237 { return getStringProperty("Dictionary"); }
238 virtual void SAL_CALL setDictionary(const OUString& p1) override
239 { setStringProperty("Dictionary", p1); }
240 virtual OUString SAL_CALL getFavorite() override
241 { return getStringProperty("Favorite"); }
242 virtual void SAL_CALL setFavorite(const OUString& p1) override
243 { setStringProperty("Favorite", p1); }
244 virtual OUString SAL_CALL getFilter() override
245 { return getStringProperty("Filter"); }
246 virtual void SAL_CALL setFilter(const OUString& p1) override
247 { setStringProperty("Filter", p1); }
248 virtual OUString SAL_CALL getGallery() override
249 { return getStringProperty("Gallery"); }
250 virtual void SAL_CALL setGallery(const OUString& p1) override
251 { setStringProperty("Gallery", p1); }
252 virtual OUString SAL_CALL getGraphic() override
253 { return getStringProperty("Graphic"); }
254 virtual void SAL_CALL setGraphic(const OUString& p1) override
255 { setStringProperty("Graphic", p1); }
256 virtual OUString SAL_CALL getHelp() override
257 { return getStringProperty("Help"); }
258 virtual void SAL_CALL setHelp(const OUString& p1) override
259 { setStringProperty("Help", p1); }
260 virtual OUString SAL_CALL getLinguistic() override
261 { return getStringProperty("Linguistic"); }
262 virtual void SAL_CALL setLinguistic(const OUString& p1) override
263 { setStringProperty("Linguistic", p1); }
264 virtual OUString SAL_CALL getModule() override
265 { return getStringProperty("Module"); }
266 virtual void SAL_CALL setModule(const OUString& p1) override
267 { setStringProperty("Module", p1); }
268 virtual OUString SAL_CALL getPalette() override
269 { return getStringProperty("Palette"); }
270 virtual void SAL_CALL setPalette(const OUString& p1) override
271 { setStringProperty("Palette", p1); }
272 virtual OUString SAL_CALL getPlugin() override
273 { return getStringProperty("Plugin"); }
274 virtual void SAL_CALL setPlugin(const OUString& p1) override
275 { setStringProperty("Plugin", p1); }
276 virtual OUString SAL_CALL getStorage() override
277 { return getStringProperty("Storage"); }
278 virtual void SAL_CALL setStorage(const OUString& p1) override
279 { setStringProperty("Storage", p1); }
280 virtual OUString SAL_CALL getTemp() override
281 { return getStringProperty("Temp"); }
282 virtual void SAL_CALL setTemp(const OUString& p1) override
283 { setStringProperty("Temp", p1); }
284 virtual OUString SAL_CALL getTemplate() override
285 { return getStringProperty("Template"); }
286 virtual void SAL_CALL setTemplate(const OUString& p1) override
287 { setStringProperty("Template", p1); }
288 virtual OUString SAL_CALL getUIConfig() override
289 { return getStringProperty("UIConfig"); }
290 virtual void SAL_CALL setUIConfig(const OUString& p1) override
291 { setStringProperty("UIConfig", p1); }
292 virtual OUString SAL_CALL getUserConfig() override
293 { return getStringProperty("UserConfig"); }
294 virtual void SAL_CALL setUserConfig(const OUString& p1) override
295 { setStringProperty("UserConfig", p1); }
296 virtual OUString SAL_CALL getUserDictionary() override
297 { return getStringProperty("UserDictionary"); }
298 virtual void SAL_CALL setUserDictionary(const OUString& p1) override
299 { setStringProperty("UserDictionary", p1); }
300 virtual OUString SAL_CALL getWork() override
301 { return getStringProperty("Work"); }
302 virtual void SAL_CALL setWork(const OUString& p1) override
303 { setStringProperty("Work", p1); }
304 virtual OUString SAL_CALL getBasePathShareLayer() override
305 { return getStringProperty("UIConfig"); }
306 virtual void SAL_CALL setBasePathShareLayer(const OUString& p1) override
307 { setStringProperty("UIConfig", p1); }
308 virtual OUString SAL_CALL getBasePathUserLayer() override
309 { return getStringProperty("UserConfig"); }
310 virtual void SAL_CALL setBasePathUserLayer(const OUString& p1) override
311 { setStringProperty("UserConfig", p1); }
314 * overrides to resolve inheritance ambiguity
316 virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2) override
317 { ::cppu::OPropertySetHelper::setPropertyValue(p1, p2); }
318 virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1) override
319 { return ::cppu::OPropertySetHelper::getPropertyValue(p1); }
320 virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
321 { ::cppu::OPropertySetHelper::addPropertyChangeListener(p1, p2); }
322 virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2) override
323 { ::cppu::OPropertySetHelper::removePropertyChangeListener(p1, p2); }
324 virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
325 { ::cppu::OPropertySetHelper::addVetoableChangeListener(p1, p2); }
326 virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2) override
327 { ::cppu::OPropertySetHelper::removeVetoableChangeListener(p1, p2); }
328 /** read all configured paths and create all needed internal structures. */
329 void impl_readAll();
331 private:
332 virtual void SAL_CALL disposing() final override;
334 /// @throws css::uno::RuntimeException
335 OUString getStringProperty(const OUString& p1);
337 /// @throws css::uno::RuntimeException
338 void setStringProperty(const OUString& p1, const OUString& p2);
340 /** read a path info using the old cfg schema.
341 This is needed for "migration on demand" reasons only.
342 Can be removed for next major release .-) */
343 std::vector<OUString> impl_readOldFormat(const OUString& sPath);
345 /** read a path info using the new cfg schema. */
346 PathSettings::PathInfo impl_readNewFormat(const OUString& sPath);
348 /** filter "real user defined paths" from the old configuration schema
349 and set it as UserPaths on the new schema.
350 Can be removed with new major release ... */
352 void impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
353 const std::vector<OUString>& lOld );
355 /** reload one path directly from the new configuration schema (because
356 it was updated by any external code) */
357 PathSettings::EChangeOp impl_updatePath(const OUString& sPath ,
358 bool bNotifyListener);
360 /** replace all might existing placeholder variables inside the given path ...
361 or check if the given path value uses paths, which can be replaced with predefined
362 placeholder variables ...
364 void impl_subst(std::vector<OUString>& lVals ,
365 const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
366 bool bReSubst);
368 void impl_subst(PathSettings::PathInfo& aPath ,
369 bool bReSubst);
371 /** converts our new string list schema to the old ";" separated schema ... */
372 OUString impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath ) const;
373 std::vector<OUString> impl_convertOldStyle2Path(std::u16string_view sOldStylePath) const;
375 /** remove still known paths from the given lList argument.
376 So real user defined paths can be extracted from the list of
377 fix internal paths !
379 void impl_purgeKnownPaths(PathSettings::PathInfo& rPath,
380 std::vector<OUString>& lList);
382 /** rebuild the member m_lPropDesc using the path list m_lPaths. */
383 void impl_rebuildPropertyDescriptor();
385 /** provides direct access to the list of path values
386 using its internal property id.
388 css::uno::Any impl_getPathValue( sal_Int32 nID ) const;
389 void impl_setPathValue( sal_Int32 nID ,
390 const css::uno::Any& aVal);
392 /** check the given handle and return the corresponding PathInfo reference.
393 These reference can be used then directly to manipulate these path. */
394 PathSettings::PathInfo* impl_getPathAccess (sal_Int32 nHandle);
395 const PathSettings::PathInfo* impl_getPathAccessConst(sal_Int32 nHandle) const;
397 /** it checks, if the given path value seems to be a valid URL or system path. */
398 bool impl_isValidPath(std::u16string_view sPath) const;
399 bool impl_isValidPath(const std::vector<OUString>& lPath) const;
401 void impl_storePath(const PathSettings::PathInfo& aPath);
403 css::uno::Sequence< sal_Int32 > impl_mapPathName2IDList(std::u16string_view sPath);
405 void impl_notifyPropListener( std::u16string_view sPath ,
406 const PathSettings::PathInfo* pPathOld,
407 const PathSettings::PathInfo* pPathNew);
409 // OPropertySetHelper
410 virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& aConvertedValue,
411 css::uno::Any& aOldValue,
412 sal_Int32 nHandle,
413 const css::uno::Any& aValue ) override;
414 virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
415 const css::uno::Any& aValue ) override;
416 virtual void SAL_CALL getFastPropertyValue( css::uno::Any& aValue,
417 sal_Int32 nHandle ) const override;
418 // Avoid:
419 // warning: 'virtual css::uno::Any cppu::OPropertySetHelper::getFastPropertyValue(sal_Int32)' was hidden [-Woverloaded-virtual]
420 // warning: by ‘virtual void {anonymous}::PathSettings::getFastPropertyValue(css::uno::Any&, sal_Int32) const’ [-Woverloaded-virtual]
421 using cppu::OPropertySetHelper::getFastPropertyValue;
422 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
423 virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
425 /** factory methods to guarantee right (but on demand) initialized members ... */
426 css::uno::Reference< css::util::XStringSubstitution > fa_getSubstitution();
427 css::uno::Reference< css::container::XNameAccess > fa_getCfgOld();
428 css::uno::Reference< css::container::XNameAccess > fa_getCfgNew();
431 PathSettings::PathSettings( css::uno::Reference< css::uno::XComponentContext > xContext )
432 : PathSettings_BASE(m_aMutex)
433 , ::cppu::OPropertySetHelper(cppu::WeakComponentImplHelperBase::rBHelper)
434 , m_xContext (std::move(xContext))
438 PathSettings::~PathSettings()
440 disposing();
443 void SAL_CALL PathSettings::disposing()
445 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
447 css::uno::Reference< css::util::XChangesNotifier >
448 xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY);
449 if (xBroadcaster.is())
450 xBroadcaster->removeChangesListener(m_xCfgNewListener);
452 m_xSubstitution.clear();
453 m_xCfgOld.clear();
454 m_xCfgNew.clear();
455 m_xCfgNewListener.clear();
457 m_pPropHelp.reset();
460 css::uno::Any SAL_CALL PathSettings::queryInterface( const css::uno::Type& _rType )
462 css::uno::Any aRet = PathSettings_BASE::queryInterface( _rType );
463 if ( !aRet.hasValue() )
464 aRet = ::cppu::OPropertySetHelper::queryInterface( _rType );
465 return aRet;
468 css::uno::Sequence< css::uno::Type > SAL_CALL PathSettings::getTypes( )
470 return comphelper::concatSequences(
471 PathSettings_BASE::getTypes(),
472 ::cppu::OPropertySetHelper::getTypes()
476 void SAL_CALL PathSettings::changesOccurred(const css::util::ChangesEvent& aEvent)
478 sal_Int32 c = aEvent.Changes.getLength();
479 sal_Int32 i = 0;
480 bool bUpdateDescriptor = false;
482 for (i=0; i<c; ++i)
484 const css::util::ElementChange& aChange = aEvent.Changes[i];
486 OUString sChanged;
487 aChange.Accessor >>= sChanged;
489 OUString sPath = ::utl::extractFirstFromConfigurationPath(sChanged);
490 if (!sPath.isEmpty())
492 PathSettings::EChangeOp eOp = impl_updatePath(sPath, true);
493 if (
494 (eOp == PathSettings::E_ADDED ) ||
495 (eOp == PathSettings::E_REMOVED)
497 bUpdateDescriptor = true;
501 if (bUpdateDescriptor)
502 impl_rebuildPropertyDescriptor();
505 void SAL_CALL PathSettings::disposing(const css::lang::EventObject& aSource)
507 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
509 if (aSource.Source == m_xCfgNew)
510 m_xCfgNew.clear();
513 OUString PathSettings::getStringProperty(const OUString& p1)
515 css::uno::Any a = ::cppu::OPropertySetHelper::getPropertyValue(p1);
516 OUString s;
517 a >>= s;
518 return s;
521 void PathSettings::setStringProperty(const OUString& p1, const OUString& p2)
523 ::cppu::OPropertySetHelper::setPropertyValue(p1, css::uno::Any(p2));
526 void PathSettings::impl_readAll()
530 // TODO think about me
531 css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
532 css::uno::Sequence< OUString > lPaths = xCfg->getElementNames();
534 sal_Int32 c = lPaths.getLength();
535 for (sal_Int32 i = 0; i < c; ++i)
537 const OUString& sPath = lPaths[i];
538 impl_updatePath(sPath, false);
541 catch(const css::uno::RuntimeException& )
545 impl_rebuildPropertyDescriptor();
548 // NO substitution here ! It's done outside ...
549 std::vector<OUString> PathSettings::impl_readOldFormat(const OUString& sPath)
551 css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
552 std::vector<OUString> aPathVal;
554 if( xCfg->hasByName(sPath) )
556 css::uno::Any aVal( xCfg->getByName(sPath) );
558 OUString sStringVal;
559 css::uno::Sequence< OUString > lStringListVal;
561 if (aVal >>= sStringVal)
563 aPathVal.push_back(sStringVal);
565 else if (aVal >>= lStringListVal)
567 aPathVal = comphelper::sequenceToContainer<std::vector<OUString>>(lStringListVal);
571 return aPathVal;
574 // NO substitution here ! It's done outside ...
575 PathSettings::PathInfo PathSettings::impl_readNewFormat(const OUString& sPath)
577 css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
579 // get access to the "queried" path
580 css::uno::Reference< css::container::XNameAccess > xPath;
581 xCfg->getByName(sPath) >>= xPath;
583 PathSettings::PathInfo aPathVal;
585 // read internal path list
586 css::uno::Reference< css::container::XNameAccess > xIPath;
587 xPath->getByName("InternalPaths") >>= xIPath;
588 aPathVal.lInternalPaths = comphelper::sequenceToContainer<std::vector<OUString>>(xIPath->getElementNames());
590 // read user defined path list
591 css::uno::Sequence<OUString> vTmpUserPathsSeq;
592 xPath->getByName(CFGPROP_USERPATHS) >>= vTmpUserPathsSeq;
593 aPathVal.lUserPaths = comphelper::sequenceToContainer<std::vector<OUString>>(vTmpUserPathsSeq);
595 // read the writeable path
596 xPath->getByName(CFGPROP_WRITEPATH) >>= aPathVal.sWritePath;
598 // avoid duplicates, by removing the writeable path from
599 // the user defined path list if it happens to be there too
600 std::vector<OUString>::iterator aI = std::find(aPathVal.lUserPaths.begin(), aPathVal.lUserPaths.end(), aPathVal.sWritePath);
601 if (aI != aPathVal.lUserPaths.end())
602 aPathVal.lUserPaths.erase(aI);
604 // read state props
605 xPath->getByName("IsSinglePath") >>= aPathVal.bIsSinglePath;
607 // analyze finalized/mandatory states
608 aPathVal.bIsReadonly = false;
609 css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
610 if (xInfo.is())
612 css::beans::Property aInfo = xInfo->getAsProperty();
613 bool bFinalized = ((aInfo.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
615 // Note: 'till we support finalized/mandatory on our API more in detail we handle
616 // all states simple as READONLY! But because all really needed paths are "mandatory" by default
617 // we have to handle "finalized" as the real "readonly" indicator.
618 aPathVal.bIsReadonly = bFinalized;
621 return aPathVal;
624 void PathSettings::impl_storePath(const PathSettings::PathInfo& aPath)
626 css::uno::Reference< css::container::XNameAccess > xCfgNew = fa_getCfgNew();
627 css::uno::Reference< css::container::XNameAccess > xCfgOld = fa_getCfgOld();
629 // try to replace path-parts with well known and supported variables.
630 // So an office can be moved easily to another location without losing
631 // its related paths.
632 PathInfo aResubstPath(aPath);
633 impl_subst(aResubstPath, true);
635 // update new configuration
636 if (! aResubstPath.bIsSinglePath)
638 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
639 aResubstPath.sPathName,
640 CFGPROP_USERPATHS,
641 css::uno::Any(comphelper::containerToSequence(aResubstPath.lUserPaths)));
644 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
645 aResubstPath.sPathName,
646 CFGPROP_WRITEPATH,
647 css::uno::Any(aResubstPath.sWritePath));
649 ::comphelper::ConfigurationHelper::flush(xCfgNew);
651 // remove the whole path from the old configuration!
652 // Otherwise we can't make sure that the diff between new and old configuration
653 // on loading time really represents a user setting!!!
655 // Check if the given path exists inside the old configuration.
656 // Because our new configuration knows more than the list of old paths ... !
657 if (xCfgOld->hasByName(aResubstPath.sPathName))
659 css::uno::Reference< css::beans::XPropertySet > xProps(xCfgOld, css::uno::UNO_QUERY_THROW);
660 xProps->setPropertyValue(aResubstPath.sPathName, css::uno::Any());
661 ::comphelper::ConfigurationHelper::flush(xCfgOld);
665 void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
666 const std::vector<OUString>& lOld )
668 for (auto const& old : lOld)
670 if (rPath.bIsSinglePath)
672 SAL_WARN_IF(lOld.size()>1, "fwk", "PathSettings::impl_mergeOldUserPaths(): Single path has more than one path value inside old configuration (Common.xcu)!");
673 if ( rPath.sWritePath != old )
674 rPath.sWritePath = old;
676 else
678 if (
679 ( std::find(rPath.lInternalPaths.begin(), rPath.lInternalPaths.end(), old) == rPath.lInternalPaths.end()) &&
680 ( std::find(rPath.lUserPaths.begin(), rPath.lUserPaths.end(), old) == rPath.lUserPaths.end() ) &&
681 ( rPath.sWritePath != old )
683 rPath.lUserPaths.push_back(old);
688 PathSettings::EChangeOp PathSettings::impl_updatePath(const OUString& sPath ,
689 bool bNotifyListener)
691 // SAFE ->
692 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
694 PathSettings::PathInfo* pPathOld = nullptr;
695 PathSettings::PathInfo* pPathNew = nullptr;
696 PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
697 PathSettings::PathInfo aPath;
701 aPath = impl_readNewFormat(sPath);
702 aPath.sPathName = sPath;
703 // replace all might existing variables with real values
704 // Do it before these old paths will be compared against the
705 // new path configuration. Otherwise some strings uses different variables ... but substitution
706 // will produce strings with same content (because some variables are redundant!)
707 impl_subst(aPath, false);
709 catch(const css::uno::RuntimeException&)
710 { throw; }
711 catch(const css::container::NoSuchElementException&)
712 { eOp = PathSettings::E_REMOVED; }
713 catch(const css::uno::Exception&)
714 { throw; }
718 // migration of old user defined values on demand
719 // can be disabled for a new major
720 std::vector<OUString> lOldVals = impl_readOldFormat(sPath);
721 // replace all might existing variables with real values
722 // Do it before these old paths will be compared against the
723 // new path configuration. Otherwise some strings uses different variables ... but substitution
724 // will produce strings with same content (because some variables are redundant!)
725 impl_subst(lOldVals, fa_getSubstitution(), false);
726 impl_mergeOldUserPaths(aPath, lOldVals);
728 catch(const css::uno::RuntimeException&)
729 { throw; }
730 // Normal(!) exceptions can be ignored!
731 // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
732 // we can't find a value for it inside the "old" configuration. So a NoSuchElementException
733 // will be normal .-)
734 catch(const css::uno::Exception&)
737 PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
738 if (eOp == PathSettings::E_UNDEFINED)
740 if (pPath != m_lPaths.end())
741 eOp = PathSettings::E_CHANGED;
742 else
743 eOp = PathSettings::E_ADDED;
746 switch(eOp)
748 case PathSettings::E_ADDED :
750 if (bNotifyListener)
752 pPathOld = nullptr;
753 pPathNew = &aPath;
754 impl_notifyPropListener(sPath, pPathOld, pPathNew);
756 m_lPaths[sPath] = aPath;
758 break;
760 case PathSettings::E_CHANGED :
762 if (bNotifyListener)
764 pPathOld = &(pPath->second);
765 pPathNew = &aPath;
766 impl_notifyPropListener(sPath, pPathOld, pPathNew);
768 m_lPaths[sPath] = aPath;
770 break;
772 case PathSettings::E_REMOVED :
774 if (pPath != m_lPaths.end())
776 if (bNotifyListener)
778 pPathOld = &(pPath->second);
779 pPathNew = nullptr;
780 impl_notifyPropListener(sPath, pPathOld, pPathNew);
782 m_lPaths.erase(pPath);
785 break;
787 default: // to let compiler be happy
788 break;
791 return eOp;
794 css::uno::Sequence< sal_Int32 > PathSettings::impl_mapPathName2IDList(std::u16string_view sPath)
796 OUString sInternalProp = OUString::Concat(sPath)+POSTFIX_INTERNAL_PATHS;
797 OUString sUserProp = OUString::Concat(sPath)+POSTFIX_USER_PATHS;
798 OUString sWriteProp = OUString::Concat(sPath)+POSTFIX_WRITE_PATH;
800 // Attention: The default set of IDs is fix and must follow these schema.
801 // Otherwise the outside code ant work for new added properties.
802 // Why?
803 // The outside code must fire N events for every changed property.
804 // And the knowing about packaging of variables of the structure PathInfo
805 // follow these group IDs! But if such ID is not in the range of [0..IDGROUP_COUNT]
806 // the outside can't determine the right group ... and can not fire the right events .-)
808 css::uno::Sequence<sal_Int32> lIDs{ IDGROUP_OLDSTYLE, IDGROUP_INTERNAL_PATHS,
809 IDGROUP_USER_PATHS, IDGROUP_WRITE_PATH };
810 assert(lIDs.getLength() == IDGROUP_COUNT);
811 auto plIDs = lIDs.getArray();
813 sal_Int32 c = m_lPropDesc.getLength();
814 sal_Int32 i = 0;
815 for (i=0; i<c; ++i)
817 const css::beans::Property& rProp = m_lPropDesc[i];
819 if (rProp.Name == sPath)
820 plIDs[IDGROUP_OLDSTYLE] = rProp.Handle;
821 else
822 if (rProp.Name == sInternalProp)
823 plIDs[IDGROUP_INTERNAL_PATHS] = rProp.Handle;
824 else
825 if (rProp.Name == sUserProp)
826 plIDs[IDGROUP_USER_PATHS] = rProp.Handle;
827 else
828 if (rProp.Name == sWriteProp)
829 plIDs[IDGROUP_WRITE_PATH] = rProp.Handle;
832 return lIDs;
835 void PathSettings::impl_notifyPropListener( std::u16string_view sPath,
836 const PathSettings::PathInfo* pPathOld,
837 const PathSettings::PathInfo* pPathNew)
839 css::uno::Sequence< sal_Int32 > lHandles(1);
840 auto plHandles = lHandles.getArray();
841 css::uno::Sequence< css::uno::Any > lOldVals(1);
842 auto plOldVals = lOldVals.getArray();
843 css::uno::Sequence< css::uno::Any > lNewVals(1);
844 auto plNewVals = lNewVals.getArray();
846 css::uno::Sequence< sal_Int32 > lIDs = impl_mapPathName2IDList(sPath);
847 sal_Int32 c = lIDs.getLength();
848 sal_Int32 i = 0;
849 sal_Int32 nMaxID = m_lPropDesc.getLength()-1;
850 for (i=0; i<c; ++i)
852 sal_Int32 nID = lIDs[i];
854 if (
855 (nID < 0 ) ||
856 (nID > nMaxID)
858 continue;
860 plHandles[0] = nID;
861 switch(impl_getPropGroup(nID))
863 case IDGROUP_OLDSTYLE :
865 if (pPathOld)
867 OUString sVal = impl_convertPath2OldStyle(*pPathOld);
868 plOldVals[0] <<= sVal;
870 if (pPathNew)
872 OUString sVal = impl_convertPath2OldStyle(*pPathNew);
873 plNewVals[0] <<= sVal;
876 break;
878 case IDGROUP_INTERNAL_PATHS :
880 if (pPathOld)
881 plOldVals[0] <<= comphelper::containerToSequence(pPathOld->lInternalPaths);
882 if (pPathNew)
883 plNewVals[0] <<= comphelper::containerToSequence(pPathNew->lInternalPaths);
885 break;
887 case IDGROUP_USER_PATHS :
889 if (pPathOld)
890 plOldVals[0] <<= comphelper::containerToSequence(pPathOld->lUserPaths);
891 if (pPathNew)
892 plNewVals[0] <<= comphelper::containerToSequence(pPathNew->lUserPaths);
894 break;
896 case IDGROUP_WRITE_PATH :
898 if (pPathOld)
899 plOldVals[0] <<= pPathOld->sWritePath;
900 if (pPathNew)
901 plNewVals[0] <<= pPathNew->sWritePath;
903 break;
906 fire(plHandles,
907 plNewVals,
908 plOldVals,
910 false);
914 void PathSettings::impl_subst(std::vector<OUString>& lVals ,
915 const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
916 bool bReSubst)
918 for (auto & old : lVals)
920 OUString sNew;
921 if (bReSubst)
922 sNew = xSubst->reSubstituteVariables(old);
923 else
924 sNew = xSubst->substituteVariables(old, false);
926 old = sNew;
930 void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
931 bool bReSubst)
933 css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
935 impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
936 impl_subst(aPath.lUserPaths , xSubst, bReSubst);
937 if (bReSubst)
938 aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
939 else
940 aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, false);
943 OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
945 OUStringBuffer sPathVal(256);
947 for (auto const& internalPath : rPath.lInternalPaths)
949 if (sPathVal.getLength())
950 sPathVal.append(";");
951 sPathVal.append(internalPath);
953 for (auto const& userPath : rPath.lUserPaths)
955 if (sPathVal.getLength())
956 sPathVal.append(";");
957 sPathVal.append(userPath);
959 if (!rPath.sWritePath.isEmpty())
961 if (sPathVal.getLength())
962 sPathVal.append(";");
963 sPathVal.append(rPath.sWritePath);
966 return sPathVal.makeStringAndClear();
969 std::vector<OUString> PathSettings::impl_convertOldStyle2Path(std::u16string_view sOldStylePath) const
971 std::vector<OUString> lList;
972 sal_Int32 nToken = 0;
975 OUString sToken( o3tl::getToken(sOldStylePath, 0, ';', nToken) );
976 if (!sToken.isEmpty())
977 lList.push_back(sToken);
979 while(nToken >= 0);
981 return lList;
984 void PathSettings::impl_purgeKnownPaths(PathSettings::PathInfo& rPath,
985 std::vector<OUString>& lList)
987 // Erase items in the internal path list from lList.
988 // Also erase items in the internal path list from the user path list.
989 for (auto const& internalPath : rPath.lInternalPaths)
991 std::vector<OUString>::iterator pItem = std::find(lList.begin(), lList.end(), internalPath);
992 if (pItem != lList.end())
993 lList.erase(pItem);
994 pItem = std::find(rPath.lUserPaths.begin(), rPath.lUserPaths.end(), internalPath);
995 if (pItem != rPath.lUserPaths.end())
996 rPath.lUserPaths.erase(pItem);
999 // Erase items not in lList from the user path list.
1000 rPath.lUserPaths.erase(std::remove_if(rPath.lUserPaths.begin(), rPath.lUserPaths.end(),
1001 [&lList](const OUString& rItem) {
1002 return std::find(lList.begin(), lList.end(), rItem) == lList.end();
1004 rPath.lUserPaths.end());
1006 // Erase items in the user path list from lList.
1007 for (auto const& userPath : rPath.lUserPaths)
1009 std::vector<OUString>::iterator pItem = std::find(lList.begin(), lList.end(), userPath);
1010 if (pItem != lList.end())
1011 lList.erase(pItem);
1014 // Erase the write path from lList
1015 std::vector<OUString>::iterator pItem = std::find(lList.begin(), lList.end(), rPath.sWritePath);
1016 if (pItem != lList.end())
1017 lList.erase(pItem);
1020 void PathSettings::impl_rebuildPropertyDescriptor()
1022 // SAFE ->
1023 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1025 sal_Int32 c = static_cast<sal_Int32>(m_lPaths.size());
1026 sal_Int32 i = 0;
1027 m_lPropDesc.realloc(c*IDGROUP_COUNT);
1028 auto plPropDesc = m_lPropDesc.getArray();
1030 for (auto const& path : m_lPaths)
1032 const PathSettings::PathInfo& rPath = path.second;
1033 css::beans::Property* pProp = nullptr;
1035 pProp = &(plPropDesc[i]);
1036 pProp->Name = rPath.sPathName;
1037 pProp->Handle = i;
1038 pProp->Type = cppu::UnoType<OUString>::get();
1039 pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1040 if (rPath.bIsReadonly)
1041 pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1042 ++i;
1044 pProp = &(plPropDesc[i]);
1045 pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHS;
1046 pProp->Handle = i;
1047 pProp->Type = cppu::UnoType<css::uno::Sequence< OUString >>::get();
1048 pProp->Attributes = css::beans::PropertyAttribute::BOUND |
1049 css::beans::PropertyAttribute::READONLY;
1050 ++i;
1052 pProp = &(plPropDesc[i]);
1053 pProp->Name = rPath.sPathName+POSTFIX_USER_PATHS;
1054 pProp->Handle = i;
1055 pProp->Type = cppu::UnoType<css::uno::Sequence< OUString >>::get();
1056 pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1057 if (rPath.bIsReadonly)
1058 pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1059 ++i;
1061 pProp = &(plPropDesc[i]);
1062 pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
1063 pProp->Handle = i;
1064 pProp->Type = cppu::UnoType<OUString>::get();
1065 pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1066 if (rPath.bIsReadonly)
1067 pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1068 ++i;
1071 m_pPropHelp.reset(new ::cppu::OPropertyArrayHelper(m_lPropDesc, false)); // false => not sorted ... must be done inside helper
1073 // <- SAFE
1076 css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
1078 const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
1079 if (! pPath)
1080 throw css::lang::IllegalArgumentException();
1082 css::uno::Any aVal;
1083 switch(impl_getPropGroup(nID))
1085 case IDGROUP_OLDSTYLE :
1087 OUString sVal = impl_convertPath2OldStyle(*pPath);
1088 aVal <<= sVal;
1090 break;
1092 case IDGROUP_INTERNAL_PATHS :
1094 aVal <<= comphelper::containerToSequence(pPath->lInternalPaths);
1096 break;
1098 case IDGROUP_USER_PATHS :
1100 aVal <<= comphelper::containerToSequence(pPath->lUserPaths);
1102 break;
1104 case IDGROUP_WRITE_PATH :
1106 aVal <<= pPath->sWritePath;
1108 break;
1111 return aVal;
1114 void PathSettings::impl_setPathValue( sal_Int32 nID ,
1115 const css::uno::Any& aVal)
1117 PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
1118 if (! pOrgPath)
1119 throw css::container::NoSuchElementException();
1121 // We work on a copied path ... so we can be sure that errors during this operation
1122 // does not make our internal cache invalid .-)
1123 PathSettings::PathInfo aChangePath(*pOrgPath);
1125 switch(impl_getPropGroup(nID))
1127 case IDGROUP_OLDSTYLE :
1129 OUString sVal;
1130 aVal >>= sVal;
1131 std::vector<OUString> lList = impl_convertOldStyle2Path(sVal);
1132 impl_subst(lList, fa_getSubstitution(), false);
1133 impl_purgeKnownPaths(aChangePath, lList);
1134 if (! impl_isValidPath(lList))
1135 throw css::lang::IllegalArgumentException();
1137 if (aChangePath.bIsSinglePath)
1139 SAL_WARN_IF(lList.size()>1, "fwk", "PathSettings::impl_setPathValue(): You try to set more than path value for a defined SINGLE_PATH!");
1140 if ( !lList.empty() )
1141 aChangePath.sWritePath = *(lList.begin());
1142 else
1143 aChangePath.sWritePath.clear();
1145 else
1147 for (auto const& elem : lList)
1149 aChangePath.lUserPaths.push_back(elem);
1153 break;
1155 case IDGROUP_INTERNAL_PATHS :
1157 if (aChangePath.bIsSinglePath)
1159 throw css::uno::Exception(
1160 "The path '" + aChangePath.sPathName
1161 + "' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.",
1162 static_cast< ::cppu::OWeakObject* >(this));
1165 css::uno::Sequence<OUString> lTmpList;
1166 aVal >>= lTmpList;
1167 std::vector<OUString> lList = comphelper::sequenceToContainer<std::vector<OUString>>(lTmpList);
1168 if (! impl_isValidPath(lList))
1169 throw css::lang::IllegalArgumentException();
1170 aChangePath.lInternalPaths = lList;
1172 break;
1174 case IDGROUP_USER_PATHS :
1176 if (aChangePath.bIsSinglePath)
1178 throw css::uno::Exception(
1179 "The path '" + aChangePath.sPathName
1180 + "' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.",
1181 static_cast< ::cppu::OWeakObject* >(this));
1184 css::uno::Sequence<OUString> lTmpList;
1185 aVal >>= lTmpList;
1186 std::vector<OUString> lList = comphelper::sequenceToContainer<std::vector<OUString>>(lTmpList);
1187 if (! impl_isValidPath(lList))
1188 throw css::lang::IllegalArgumentException();
1189 aChangePath.lUserPaths = lList;
1191 break;
1193 case IDGROUP_WRITE_PATH :
1195 OUString sVal;
1196 aVal >>= sVal;
1197 if (! impl_isValidPath(sVal))
1198 throw css::lang::IllegalArgumentException();
1199 aChangePath.sWritePath = sVal;
1201 break;
1204 // TODO check if path has at least one path value set
1205 // At least it depends from the feature using this path, if an empty path list is allowed.
1207 // first we should try to store the changed (copied!) path ...
1208 // In case an error occurs on saving time an exception is thrown ...
1209 // If no exception occurs we can update our internal cache (means
1210 // we can overwrite pOrgPath !
1211 impl_storePath(aChangePath);
1212 *pOrgPath = std::move(aChangePath);
1215 bool PathSettings::impl_isValidPath(const std::vector<OUString>& lPath) const
1217 for (auto const& path : lPath)
1219 if (! impl_isValidPath(path))
1220 return false;
1223 return true;
1226 bool PathSettings::impl_isValidPath(std::u16string_view sPath) const
1228 // allow empty path to reset a path.
1229 // idea by LLA to support empty paths
1230 // if (sPath.getLength() == 0)
1231 // {
1232 // return sal_True;
1233 // }
1235 return (! INetURLObject(sPath).HasError());
1238 OUString impl_extractBaseFromPropName(const OUString& sPropName)
1240 sal_Int32 i = sPropName.indexOf(POSTFIX_INTERNAL_PATHS);
1241 if (i > -1)
1242 return sPropName.copy(0, i);
1243 i = sPropName.indexOf(POSTFIX_USER_PATHS);
1244 if (i > -1)
1245 return sPropName.copy(0, i);
1246 i = sPropName.indexOf(POSTFIX_WRITE_PATH);
1247 if (i > -1)
1248 return sPropName.copy(0, i);
1250 return sPropName;
1253 PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
1255 // SAFE ->
1256 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1258 if (nHandle > (m_lPropDesc.getLength()-1))
1259 return nullptr;
1261 const css::beans::Property& rProp = m_lPropDesc[nHandle];
1262 OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1263 PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
1265 if (rPath != m_lPaths.end())
1266 return &(rPath->second);
1268 return nullptr;
1269 // <- SAFE
1272 const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
1274 // SAFE ->
1275 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1277 if (nHandle > (m_lPropDesc.getLength()-1))
1278 return nullptr;
1280 const css::beans::Property& rProp = m_lPropDesc[nHandle];
1281 OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1282 PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
1284 if (rPath != m_lPaths.end())
1285 return &(rPath->second);
1287 return nullptr;
1288 // <- SAFE
1291 sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
1292 css::uno::Any& aOldValue ,
1293 sal_Int32 nHandle ,
1294 const css::uno::Any& aValue )
1296 // throws NoSuchElementException !
1297 css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
1299 return PropHelper::willPropertyBeChanged(
1300 aCurrentVal,
1301 aValue,
1302 aOldValue,
1303 aConvertedValue);
1306 void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
1307 const css::uno::Any& aValue )
1309 // throws NoSuchElement- and IllegalArgumentException !
1310 impl_setPathValue(nHandle, aValue);
1313 void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
1314 sal_Int32 nHandle) const
1316 aValue = impl_getPathValue(nHandle);
1319 ::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
1321 return *m_pPropHelp;
1324 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
1326 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1329 css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
1331 css::uno::Reference< css::util::XStringSubstitution > xSubst;
1332 { // SAFE ->
1333 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1334 xSubst = m_xSubstitution;
1337 if (! xSubst.is())
1339 // create the needed substitution service.
1340 // We must replace all used variables inside read path values.
1341 // In case we can't do so... the whole office can't work really.
1342 // That's why it seems to be OK to throw a RuntimeException then.
1343 xSubst = css::util::PathSubstitution::create(m_xContext);
1345 { // SAFE ->
1346 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1347 m_xSubstitution = xSubst;
1351 return xSubst;
1354 css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
1356 css::uno::Reference< css::container::XNameAccess > xCfg;
1357 { // SAFE ->
1358 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1359 xCfg = m_xCfgOld;
1360 } // <- SAFE
1362 if (! xCfg.is())
1364 xCfg.set( ::comphelper::ConfigurationHelper::openConfig(
1365 m_xContext,
1366 "org.openoffice.Office.Common/Path/Current",
1367 ::comphelper::EConfigurationModes::Standard), // not readonly! Sometimes we need write access there !!!
1368 css::uno::UNO_QUERY_THROW);
1370 { // SAFE ->
1371 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1372 m_xCfgOld = xCfg;
1376 return xCfg;
1379 css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
1381 css::uno::Reference< css::container::XNameAccess > xCfg;
1382 { // SAFE ->
1383 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1384 xCfg = m_xCfgNew;
1385 } // <- SAFE
1387 if (! xCfg.is())
1389 xCfg.set( ::comphelper::ConfigurationHelper::openConfig(
1390 m_xContext,
1391 "org.openoffice.Office.Paths/Paths",
1392 ::comphelper::EConfigurationModes::Standard),
1393 css::uno::UNO_QUERY_THROW);
1395 { // SAFE ->
1396 osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1397 m_xCfgNew = xCfg;
1398 m_xCfgNewListener = new WeakChangesListener(this);
1401 css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
1402 xBroadcaster->addChangesListener(m_xCfgNewListener);
1405 return xCfg;
1410 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
1411 com_sun_star_comp_framework_PathSettings_get_implementation(
1412 css::uno::XComponentContext *context,
1413 css::uno::Sequence<css::uno::Any> const &)
1415 rtl::Reference<PathSettings> xPathSettings = new PathSettings(context);
1416 // fill cache
1417 xPathSettings->impl_readAll();
1419 return cppu::acquire(xPathSettings.get());
1422 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */