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 <properties.h>
21 : #include <stdtypes.h>
22 : #include <helper/mischelper.hxx>
23 :
24 : #include <com/sun/star/beans/Property.hpp>
25 : #include <com/sun/star/beans/XProperty.hpp>
26 : #include <com/sun/star/beans/PropertyAttribute.hpp>
27 : #include <com/sun/star/beans/XPropertySet.hpp>
28 : #include <com/sun/star/util/XChangesNotifier.hpp>
29 : #include <com/sun/star/util/PathSubstitution.hpp>
30 : #include <com/sun/star/container/XNameAccess.hpp>
31 : #include <com/sun/star/lang/XServiceInfo.hpp>
32 : #include <com/sun/star/util/XStringSubstitution.hpp>
33 : #include <com/sun/star/util/XChangesListener.hpp>
34 : #include <com/sun/star/util/XPathSettings.hpp>
35 :
36 : #include <tools/urlobj.hxx>
37 : #include <rtl/ustrbuf.hxx>
38 :
39 : #include <cppuhelper/basemutex.hxx>
40 : #include <cppuhelper/propshlp.hxx>
41 : #include <cppuhelper/compbase3.hxx>
42 : #include <cppuhelper/supportsservice.hxx>
43 : #include <comphelper/sequence.hxx>
44 : #include <comphelper/configurationhelper.hxx>
45 : #include <unotools/configitem.hxx>
46 : #include <unotools/configpaths.hxx>
47 :
48 : using namespace framework;
49 :
50 : #define CFGPROP_USERPATHS "UserPaths"
51 : #define CFGPROP_WRITEPATH "WritePath"
52 :
53 : /*
54 : 0 : old style "Template" string using ";" as separator
55 : 1 : internal paths "Template_internal" string list
56 : 2 : user paths "Template_user" string list
57 : 3 : write path "Template_write" string
58 : */
59 :
60 : #define POSTFIX_INTERNAL_PATHS "_internal"
61 : #define POSTFIX_USER_PATHS "_user"
62 : #define POSTFIX_WRITE_PATH "_writable"
63 :
64 : namespace {
65 :
66 : const sal_Int32 IDGROUP_OLDSTYLE = 0;
67 : const sal_Int32 IDGROUP_INTERNAL_PATHS = 1;
68 : const sal_Int32 IDGROUP_USER_PATHS = 2;
69 : const sal_Int32 IDGROUP_WRITE_PATH = 3;
70 :
71 : const sal_Int32 IDGROUP_COUNT = 4;
72 :
73 0 : sal_Int32 impl_getPropGroup(sal_Int32 nID)
74 : {
75 0 : return (nID % IDGROUP_COUNT);
76 : }
77 :
78 : /* enable it if you wish to migrate old user settings (using the old cfg schema) on demand ....
79 : disable it in case only the new schema must be used.
80 : */
81 :
82 : typedef ::cppu::WeakComponentImplHelper3<
83 : css::lang::XServiceInfo,
84 : css::util::XChangesListener, // => XEventListener
85 : css::util::XPathSettings> // => XPropertySet
86 : PathSettings_BASE;
87 :
88 : class PathSettings : private cppu::BaseMutex
89 : , public PathSettings_BASE
90 : , public ::cppu::OPropertySetHelper
91 : {
92 0 : struct PathInfo
93 : {
94 : public:
95 :
96 0 : PathInfo()
97 : : sPathName ()
98 : , lInternalPaths()
99 : , lUserPaths ()
100 : , sWritePath ()
101 : , bIsSinglePath (false)
102 0 : , bIsReadonly (false)
103 0 : {}
104 :
105 0 : PathInfo(const PathInfo& rCopy)
106 0 : {
107 0 : takeOver(rCopy);
108 0 : }
109 :
110 0 : void takeOver(const PathInfo& rCopy)
111 : {
112 0 : sPathName = rCopy.sPathName;
113 0 : lInternalPaths = rCopy.lInternalPaths;
114 0 : lUserPaths = rCopy.lUserPaths;
115 0 : sWritePath = rCopy.sWritePath;
116 0 : bIsSinglePath = rCopy.bIsSinglePath;
117 0 : bIsReadonly = rCopy.bIsReadonly;
118 0 : }
119 :
120 : /// an internal name describing this path
121 : OUString sPathName;
122 :
123 : /// contains all paths, which are used internally - but are not visible for the user.
124 : OUStringList lInternalPaths;
125 :
126 : /// contains all paths configured by the user
127 : OUStringList lUserPaths;
128 :
129 : /// this special path is used to generate feature depending content there
130 : OUString sWritePath;
131 :
132 : /// indicates real single paths, which uses WritePath property only
133 : bool bIsSinglePath;
134 :
135 : /// simple handling of finalized/mandatory states ... => we know one state READONLY only .-)
136 : bool bIsReadonly;
137 : };
138 :
139 : typedef BaseHash< PathSettings::PathInfo > PathHash;
140 :
141 : enum EChangeOp
142 : {
143 : E_UNDEFINED,
144 : E_ADDED,
145 : E_CHANGED,
146 : E_REMOVED
147 : };
148 :
149 : private:
150 :
151 : /** reference to factory, which has create this instance. */
152 : css::uno::Reference< css::uno::XComponentContext > m_xContext;
153 :
154 : /** list of all path variables and her corresponding values. */
155 : PathSettings::PathHash m_lPaths;
156 :
157 : /** describes all properties available on our interface.
158 : Will be generated on demand based on our path list m_lPaths. */
159 : css::uno::Sequence< css::beans::Property > m_lPropDesc;
160 :
161 : /** helper needed to (re-)substitute all internal save path values. */
162 : css::uno::Reference< css::util::XStringSubstitution > m_xSubstitution;
163 :
164 : /** provides access to the old configuration schema (which will be migrated on demand). */
165 : css::uno::Reference< css::container::XNameAccess > m_xCfgOld;
166 :
167 : /** provides access to the new configuration schema. */
168 : css::uno::Reference< css::container::XNameAccess > m_xCfgNew;
169 :
170 : /** helper to listen for configuration changes without ownership cycle problems */
171 : css::uno::Reference< css::util::XChangesListener > m_xCfgNewListener;
172 :
173 : ::cppu::OPropertyArrayHelper* m_pPropHelp;
174 :
175 : bool m_bIgnoreEvents;
176 :
177 : public:
178 :
179 : /** initialize a new instance of this class.
180 : Attention: It's necessary for right function of this class, that the order of base
181 : classes is the right one. Because we transfer information from one base to another
182 : during this ctor runs! */
183 : PathSettings(const css::uno::Reference< css::uno::XComponentContext >& xContext);
184 :
185 : /** free all used resources ... if it was not already done. */
186 : virtual ~PathSettings();
187 :
188 0 : virtual OUString SAL_CALL getImplementationName()
189 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
190 : {
191 0 : return OUString("com.sun.star.comp.framework.PathSettings");
192 : }
193 :
194 0 : virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
195 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
196 : {
197 0 : return cppu::supportsService(this, ServiceName);
198 : }
199 :
200 0 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
201 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
202 : {
203 0 : css::uno::Sequence< OUString > aSeq(1);
204 0 : aSeq[0] = OUString("com.sun.star.util.PathSettings");
205 0 : return aSeq;
206 : }
207 :
208 : // XInterface
209 : virtual ::css::uno::Any SAL_CALL queryInterface( const ::css::uno::Type& type) throw ( ::css::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
210 0 : virtual void SAL_CALL acquire() throw () SAL_OVERRIDE
211 0 : { OWeakObject::acquire(); }
212 0 : virtual void SAL_CALL release() throw () SAL_OVERRIDE
213 0 : { OWeakObject::release(); }
214 :
215 : // XTypeProvider
216 : virtual ::css::uno::Sequence< ::css::uno::Type > SAL_CALL getTypes( ) throw(::css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
217 :
218 : // css::util::XChangesListener
219 : virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
220 :
221 : // css::lang::XEventListener
222 : virtual void SAL_CALL disposing(const css::lang::EventObject& aSource)
223 : throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
224 :
225 : /**
226 : * XPathSettings attribute methods
227 : */
228 0 : virtual OUString SAL_CALL getAddin() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
229 0 : { return getStringProperty("Addin"); }
230 0 : virtual void SAL_CALL setAddin(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
231 0 : { setStringProperty("Addin", p1); }
232 0 : virtual OUString SAL_CALL getAutoCorrect() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
233 0 : { return getStringProperty("AutoCorrect"); }
234 0 : virtual void SAL_CALL setAutoCorrect(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
235 0 : { setStringProperty("AutoCorrect", p1); }
236 0 : virtual OUString SAL_CALL getAutoText() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
237 0 : { return getStringProperty("AutoText"); }
238 0 : virtual void SAL_CALL setAutoText(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
239 0 : { setStringProperty("AutoText", p1); }
240 0 : virtual OUString SAL_CALL getBackup() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
241 0 : { return getStringProperty("Backup"); }
242 0 : virtual void SAL_CALL setBackup(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
243 0 : { setStringProperty("Backup", p1); }
244 0 : virtual OUString SAL_CALL getBasic() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
245 0 : { return getStringProperty("Basic"); }
246 0 : virtual void SAL_CALL setBasic(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
247 0 : { setStringProperty("Basic", p1); }
248 0 : virtual OUString SAL_CALL getBitmap() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
249 0 : { return getStringProperty("Bitmap"); }
250 0 : virtual void SAL_CALL setBitmap(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
251 0 : { setStringProperty("Bitmap", p1); }
252 0 : virtual OUString SAL_CALL getConfig() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
253 0 : { return getStringProperty("Config"); }
254 0 : virtual void SAL_CALL setConfig(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
255 0 : { setStringProperty("Config", p1); }
256 0 : virtual OUString SAL_CALL getDictionary() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
257 0 : { return getStringProperty("Dictionary"); }
258 0 : virtual void SAL_CALL setDictionary(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
259 0 : { setStringProperty("Dictionary", p1); }
260 0 : virtual OUString SAL_CALL getFavorite() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
261 0 : { return getStringProperty("Favorite"); }
262 0 : virtual void SAL_CALL setFavorite(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
263 0 : { setStringProperty("Favorite", p1); }
264 0 : virtual OUString SAL_CALL getFilter() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
265 0 : { return getStringProperty("Filter"); }
266 0 : virtual void SAL_CALL setFilter(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
267 0 : { setStringProperty("Filter", p1); }
268 0 : virtual OUString SAL_CALL getGallery() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
269 0 : { return getStringProperty("Gallery"); }
270 0 : virtual void SAL_CALL setGallery(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
271 0 : { setStringProperty("Gallery", p1); }
272 0 : virtual OUString SAL_CALL getGraphic() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
273 0 : { return getStringProperty("Graphic"); }
274 0 : virtual void SAL_CALL setGraphic(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
275 0 : { setStringProperty("Graphic", p1); }
276 0 : virtual OUString SAL_CALL getHelp() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
277 0 : { return getStringProperty("Help"); }
278 0 : virtual void SAL_CALL setHelp(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
279 0 : { setStringProperty("Help", p1); }
280 0 : virtual OUString SAL_CALL getLinguistic() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
281 0 : { return getStringProperty("Linguistic"); }
282 0 : virtual void SAL_CALL setLinguistic(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
283 0 : { setStringProperty("Linguistic", p1); }
284 0 : virtual OUString SAL_CALL getModule() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
285 0 : { return getStringProperty("Module"); }
286 0 : virtual void SAL_CALL setModule(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
287 0 : { setStringProperty("Module", p1); }
288 0 : virtual OUString SAL_CALL getPalette() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
289 0 : { return getStringProperty("Palette"); }
290 0 : virtual void SAL_CALL setPalette(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
291 0 : { setStringProperty("Palette", p1); }
292 0 : virtual OUString SAL_CALL getPlugin() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
293 0 : { return getStringProperty("Plugin"); }
294 0 : virtual void SAL_CALL setPlugin(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
295 0 : { setStringProperty("Plugin", p1); }
296 0 : virtual OUString SAL_CALL getStorage() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
297 0 : { return getStringProperty("Storage"); }
298 0 : virtual void SAL_CALL setStorage(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
299 0 : { setStringProperty("Storage", p1); }
300 0 : virtual OUString SAL_CALL getTemp() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
301 0 : { return getStringProperty("Temp"); }
302 0 : virtual void SAL_CALL setTemp(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
303 0 : { setStringProperty("Temp", p1); }
304 0 : virtual OUString SAL_CALL getTemplate() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
305 0 : { return getStringProperty("Template"); }
306 0 : virtual void SAL_CALL setTemplate(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
307 0 : { setStringProperty("Template", p1); }
308 0 : virtual OUString SAL_CALL getUIConfig() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
309 0 : { return getStringProperty("UIConfig"); }
310 0 : virtual void SAL_CALL setUIConfig(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
311 0 : { setStringProperty("UIConfig", p1); }
312 0 : virtual OUString SAL_CALL getUserConfig() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
313 0 : { return getStringProperty("UserConfig"); }
314 0 : virtual void SAL_CALL setUserConfig(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
315 0 : { setStringProperty("UserConfig", p1); }
316 0 : virtual OUString SAL_CALL getUserDictionary() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
317 0 : { return getStringProperty("UserDictionary"); }
318 0 : virtual void SAL_CALL setUserDictionary(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
319 0 : { setStringProperty("UserDictionary", p1); }
320 0 : virtual OUString SAL_CALL getWork() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
321 0 : { return getStringProperty("Work"); }
322 0 : virtual void SAL_CALL setWork(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
323 0 : { setStringProperty("Work", p1); }
324 0 : virtual OUString SAL_CALL getBasePathShareLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
325 0 : { return getStringProperty("UIConfig"); }
326 0 : virtual void SAL_CALL setBasePathShareLayer(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
327 0 : { setStringProperty("UIConfig", p1); }
328 0 : virtual OUString SAL_CALL getBasePathUserLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
329 0 : { return getStringProperty("UserConfig"); }
330 0 : virtual void SAL_CALL setBasePathUserLayer(const OUString& p1) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
331 0 : { setStringProperty("UserConfig", p1); }
332 :
333 : /**
334 : * overrides to resolve inheritance ambiguity
335 : */
336 0 : virtual void SAL_CALL setPropertyValue(const OUString& p1, const css::uno::Any& p2)
337 : throw (css::beans::UnknownPropertyException, css::beans::PropertyVetoException, css::lang::IllegalArgumentException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
338 0 : { ::cppu::OPropertySetHelper::setPropertyValue(p1, p2); }
339 0 : virtual css::uno::Any SAL_CALL getPropertyValue(const OUString& p1)
340 : throw (css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
341 0 : { return ::cppu::OPropertySetHelper::getPropertyValue(p1); }
342 0 : virtual void SAL_CALL addPropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2)
343 : throw (css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
344 0 : { ::cppu::OPropertySetHelper::addPropertyChangeListener(p1, p2); }
345 0 : virtual void SAL_CALL removePropertyChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XPropertyChangeListener>& p2)
346 : throw (css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
347 0 : { ::cppu::OPropertySetHelper::removePropertyChangeListener(p1, p2); }
348 0 : virtual void SAL_CALL addVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2)
349 : throw (css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
350 0 : { ::cppu::OPropertySetHelper::addVetoableChangeListener(p1, p2); }
351 0 : virtual void SAL_CALL removeVetoableChangeListener(const OUString& p1, const css::uno::Reference<css::beans::XVetoableChangeListener>& p2)
352 : throw (css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
353 0 : { ::cppu::OPropertySetHelper::removeVetoableChangeListener(p1, p2); }
354 : /** read all configured paths and create all needed internal structures. */
355 : void impl_readAll();
356 :
357 : private:
358 : virtual void SAL_CALL disposing() SAL_OVERRIDE;
359 :
360 : OUString getStringProperty(const OUString& p1)
361 : throw(css::uno::RuntimeException);
362 :
363 : void setStringProperty(const OUString& p1, const OUString& p2)
364 : throw(css::uno::RuntimeException);
365 :
366 : /** read a path info using the old cfg schema.
367 : This is needed for "migration on demand" reasons only.
368 : Can be removed for next major release .-) */
369 : OUStringList impl_readOldFormat(const OUString& sPath);
370 :
371 : /** read a path info using the new cfg schema. */
372 : PathSettings::PathInfo impl_readNewFormat(const OUString& sPath);
373 :
374 : /** filter "real user defined paths" from the old configuration schema
375 : and set it as UserPaths on the new schema.
376 : Can be removed with new major release ... */
377 :
378 : void impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
379 : const OUStringList& lOld );
380 :
381 : /** reload one path directly from the new configuration schema (because
382 : it was updated by any external code) */
383 : PathSettings::EChangeOp impl_updatePath(const OUString& sPath ,
384 : bool bNotifyListener);
385 :
386 : /** replace all might existing placeholder variables inside the given path ...
387 : or check if the given path value uses paths, which can be replaced with predefined
388 : placeholder variables ...
389 : */
390 : void impl_subst( OUStringList& lVals ,
391 : const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
392 : bool bReSubst);
393 :
394 : void impl_subst(PathSettings::PathInfo& aPath ,
395 : bool bReSubst);
396 :
397 : /** converts our new string list schema to the old ";" separated schema ... */
398 : OUString impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath ) const;
399 : OUStringList impl_convertOldStyle2Path(const OUString& sOldStylePath) const;
400 :
401 : /** remove still known paths from the given lList argument.
402 : So real user defined paths can be extracted from the list of
403 : fix internal paths !
404 : */
405 : void impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
406 : OUStringList& lList);
407 :
408 : /** rebuild the member m_lPropDesc using the path list m_lPaths. */
409 : void impl_rebuildPropertyDescriptor();
410 :
411 : /** provides direct access to the list of path values
412 : using it's internal property id.
413 : */
414 : css::uno::Any impl_getPathValue( sal_Int32 nID ) const;
415 : void impl_setPathValue( sal_Int32 nID ,
416 : const css::uno::Any& aVal);
417 :
418 : /** check the given handle and return the corresponding PathInfo reference.
419 : These reference can be used then directly to manipulate these path. */
420 : PathSettings::PathInfo* impl_getPathAccess (sal_Int32 nHandle);
421 : const PathSettings::PathInfo* impl_getPathAccessConst(sal_Int32 nHandle) const;
422 :
423 : /** it checks, if the given path value seems to be a valid URL or system path. */
424 : bool impl_isValidPath(const OUString& sPath) const;
425 : bool impl_isValidPath(const OUStringList& lPath) const;
426 :
427 : void impl_storePath(const PathSettings::PathInfo& aPath);
428 :
429 : css::uno::Sequence< sal_Int32 > impl_mapPathName2IDList(const OUString& sPath);
430 :
431 : void impl_notifyPropListener( PathSettings::EChangeOp eOp ,
432 : const OUString& sPath ,
433 : const PathSettings::PathInfo* pPathOld,
434 : const PathSettings::PathInfo* pPathNew);
435 :
436 : // OPropertySetHelper
437 : virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& aConvertedValue,
438 : css::uno::Any& aOldValue,
439 : sal_Int32 nHandle,
440 : const css::uno::Any& aValue ) throw(css::lang::IllegalArgumentException) SAL_OVERRIDE;
441 : virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
442 : const css::uno::Any& aValue ) throw(css::uno::Exception, std::exception) SAL_OVERRIDE;
443 : virtual void SAL_CALL getFastPropertyValue( css::uno::Any& aValue,
444 : sal_Int32 nHandle ) const SAL_OVERRIDE;
445 : // Avoid:
446 : // warning: ‘virtual com::sun::star::uno::Any cppu::OPropertySetHelper::getFastPropertyValue(sal_Int32)’ was hidden [-Woverloaded-virtual]
447 : // warning: by ‘virtual void {anonymous}::PathSettings::getFastPropertyValue(com::sun::star::uno::Any&, sal_Int32) const’ [-Woverloaded-virtual]
448 : using cppu::OPropertySetHelper::getFastPropertyValue;
449 : virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
450 : virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(::css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
451 :
452 : /** factory methods to guarantee right (but on demand) initialized members ... */
453 : css::uno::Reference< css::util::XStringSubstitution > fa_getSubstitution();
454 : css::uno::Reference< css::container::XNameAccess > fa_getCfgOld();
455 : css::uno::Reference< css::container::XNameAccess > fa_getCfgNew();
456 : };
457 :
458 0 : PathSettings::PathSettings( const css::uno::Reference< css::uno::XComponentContext >& xContext )
459 : : PathSettings_BASE(m_aMutex)
460 : , ::cppu::OPropertySetHelper(cppu::WeakComponentImplHelperBase::rBHelper)
461 : , m_xContext (xContext)
462 : , m_pPropHelp(0 )
463 0 : , m_bIgnoreEvents(false)
464 : {
465 0 : }
466 :
467 0 : PathSettings::~PathSettings()
468 : {
469 0 : disposing();
470 0 : }
471 :
472 0 : void SAL_CALL PathSettings::disposing()
473 : {
474 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
475 :
476 : css::uno::Reference< css::util::XChangesNotifier >
477 0 : xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY);
478 0 : if (xBroadcaster.is())
479 0 : xBroadcaster->removeChangesListener(m_xCfgNewListener);
480 :
481 0 : m_xSubstitution.clear();
482 0 : m_xCfgOld.clear();
483 0 : m_xCfgNew.clear();
484 0 : m_xCfgNewListener.clear();
485 :
486 0 : delete m_pPropHelp;
487 0 : m_pPropHelp = 0;
488 0 : }
489 :
490 0 : css::uno::Any SAL_CALL PathSettings::queryInterface( const css::uno::Type& _rType )
491 : throw(css::uno::RuntimeException, std::exception)
492 : {
493 0 : css::uno::Any aRet = PathSettings_BASE::queryInterface( _rType );
494 0 : if ( !aRet.hasValue() )
495 0 : aRet = ::cppu::OPropertySetHelper::queryInterface( _rType );
496 0 : return aRet;
497 : }
498 :
499 0 : css::uno::Sequence< css::uno::Type > SAL_CALL PathSettings::getTypes( )
500 : throw(css::uno::RuntimeException, std::exception)
501 : {
502 : return comphelper::concatSequences(
503 : PathSettings_BASE::getTypes(),
504 : ::cppu::OPropertySetHelper::getTypes()
505 0 : );
506 : }
507 :
508 0 : void SAL_CALL PathSettings::changesOccurred(const css::util::ChangesEvent& aEvent)
509 : throw (css::uno::RuntimeException, std::exception)
510 : {
511 0 : sal_Int32 c = aEvent.Changes.getLength();
512 0 : sal_Int32 i = 0;
513 0 : bool bUpdateDescriptor = false;
514 :
515 0 : for (i=0; i<c; ++i)
516 : {
517 0 : const css::util::ElementChange& aChange = aEvent.Changes[i];
518 :
519 0 : OUString sChanged;
520 0 : aChange.Accessor >>= sChanged;
521 :
522 0 : OUString sPath = ::utl::extractFirstFromConfigurationPath(sChanged);
523 0 : if (!sPath.isEmpty())
524 : {
525 0 : PathSettings::EChangeOp eOp = impl_updatePath(sPath, true);
526 0 : if (
527 0 : (eOp == PathSettings::E_ADDED ) ||
528 : (eOp == PathSettings::E_REMOVED)
529 : )
530 0 : bUpdateDescriptor = true;
531 : }
532 0 : }
533 :
534 0 : if (bUpdateDescriptor)
535 0 : impl_rebuildPropertyDescriptor();
536 0 : }
537 :
538 0 : void SAL_CALL PathSettings::disposing(const css::lang::EventObject& aSource)
539 : throw(css::uno::RuntimeException, std::exception)
540 : {
541 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
542 :
543 0 : if (aSource.Source == m_xCfgNew)
544 0 : m_xCfgNew.clear();
545 0 : }
546 :
547 0 : OUString PathSettings::getStringProperty(const OUString& p1)
548 : throw(css::uno::RuntimeException)
549 : {
550 0 : css::uno::Any a = ::cppu::OPropertySetHelper::getPropertyValue(p1);
551 0 : OUString s;
552 0 : a >>= s;
553 0 : return s;
554 : }
555 :
556 0 : void PathSettings::setStringProperty(const OUString& p1, const OUString& p2)
557 : throw(css::uno::RuntimeException)
558 : {
559 0 : ::cppu::OPropertySetHelper::setPropertyValue(p1, css::uno::Any(p2));
560 0 : }
561 :
562 0 : void PathSettings::impl_readAll()
563 : {
564 : try
565 : {
566 : // TODO think about me
567 0 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
568 0 : css::uno::Sequence< OUString > lPaths = xCfg->getElementNames();
569 :
570 0 : sal_Int32 c = lPaths.getLength();
571 0 : for (sal_Int32 i = 0; i < c; ++i)
572 : {
573 0 : const OUString& sPath = lPaths[i];
574 0 : impl_updatePath(sPath, false);
575 0 : }
576 : }
577 0 : catch(const css::uno::RuntimeException& )
578 : {
579 : }
580 :
581 0 : impl_rebuildPropertyDescriptor();
582 0 : }
583 :
584 : // NO substitution here ! It's done outside ...
585 0 : OUStringList PathSettings::impl_readOldFormat(const OUString& sPath)
586 : {
587 0 : css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
588 0 : OUStringList aPathVal;
589 :
590 0 : if( xCfg->hasByName(sPath) )
591 : {
592 0 : css::uno::Any aVal( xCfg->getByName(sPath) );
593 :
594 0 : OUString sStringVal;
595 0 : css::uno::Sequence< OUString > lStringListVal;
596 :
597 0 : if (aVal >>= sStringVal)
598 : {
599 0 : aPathVal.push_back(sStringVal);
600 : }
601 0 : else if (aVal >>= lStringListVal)
602 : {
603 0 : aPathVal << lStringListVal;
604 0 : }
605 : }
606 :
607 0 : return aPathVal;
608 : }
609 :
610 : // NO substitution here ! It's done outside ...
611 0 : PathSettings::PathInfo PathSettings::impl_readNewFormat(const OUString& sPath)
612 : {
613 0 : const OUString CFGPROP_INTERNALPATHS("InternalPaths");
614 0 : const OUString CFGPROP_ISSINGLEPATH("IsSinglePath");
615 :
616 0 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
617 :
618 : // get access to the "queried" path
619 0 : css::uno::Reference< css::container::XNameAccess > xPath;
620 0 : xCfg->getByName(sPath) >>= xPath;
621 :
622 0 : PathSettings::PathInfo aPathVal;
623 :
624 : // read internal path list
625 0 : css::uno::Reference< css::container::XNameAccess > xIPath;
626 0 : xPath->getByName(CFGPROP_INTERNALPATHS) >>= xIPath;
627 0 : aPathVal.lInternalPaths << xIPath->getElementNames();
628 :
629 : // read user defined path list
630 0 : aPathVal.lUserPaths << xPath->getByName(CFGPROP_USERPATHS);
631 :
632 : // read the writeable path
633 0 : xPath->getByName(CFGPROP_WRITEPATH) >>= aPathVal.sWritePath;
634 :
635 : // avoid duplicates, by removing the writeable path from
636 : // the user defined path list if it happens to be there too
637 0 : OUStringList::iterator aI = aPathVal.lUserPaths.find(aPathVal.sWritePath);
638 0 : if (aI != aPathVal.lUserPaths.end())
639 0 : aPathVal.lUserPaths.erase(aI);
640 :
641 : // read state props
642 0 : xPath->getByName(CFGPROP_ISSINGLEPATH) >>= aPathVal.bIsSinglePath;
643 :
644 : // analyze finalized/mandatory states
645 0 : aPathVal.bIsReadonly = false;
646 0 : css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
647 0 : if (xInfo.is())
648 : {
649 0 : css::beans::Property aInfo = xInfo->getAsProperty();
650 0 : bool bFinalized = ((aInfo.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
651 :
652 : // Note: Till we support finalized / mandatory on our API more in detail we handle
653 : // all states simple as READONLY ! But because all really needed paths are "mandatory" by default
654 : // we have to handle "finalized" as the real "readonly" indicator .
655 0 : aPathVal.bIsReadonly = bFinalized;
656 : }
657 :
658 0 : return aPathVal;
659 : }
660 :
661 0 : void PathSettings::impl_storePath(const PathSettings::PathInfo& aPath)
662 : {
663 0 : m_bIgnoreEvents = true;
664 :
665 0 : css::uno::Reference< css::container::XNameAccess > xCfgNew = fa_getCfgNew();
666 0 : css::uno::Reference< css::container::XNameAccess > xCfgOld = fa_getCfgOld();
667 :
668 : // try to replace path-parts with well known and uspported variables.
669 : // So an office can be moved easialy to another location without loosing
670 : // it's related paths.
671 0 : PathInfo aResubstPath(aPath);
672 0 : impl_subst(aResubstPath, true);
673 :
674 : // update new configuration
675 0 : if (! aResubstPath.bIsSinglePath)
676 : {
677 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
678 : aResubstPath.sPathName,
679 : CFGPROP_USERPATHS,
680 0 : css::uno::makeAny(aResubstPath.lUserPaths.getAsConstList()));
681 : }
682 :
683 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
684 : aResubstPath.sPathName,
685 : CFGPROP_WRITEPATH,
686 0 : css::uno::makeAny(aResubstPath.sWritePath));
687 :
688 0 : ::comphelper::ConfigurationHelper::flush(xCfgNew);
689 :
690 : // remove the whole path from the old configuration !
691 : // Otherwise we cant make sure that the diff between new and old configuration
692 : // on loading time really represent an user setting !!!
693 :
694 : // Check if the given path exists inside the old configuration.
695 : // Because our new configuration knows more then the list of old paths ... !
696 0 : if (xCfgOld->hasByName(aResubstPath.sPathName))
697 : {
698 0 : css::uno::Reference< css::beans::XPropertySet > xProps(xCfgOld, css::uno::UNO_QUERY_THROW);
699 0 : xProps->setPropertyValue(aResubstPath.sPathName, css::uno::Any());
700 0 : ::comphelper::ConfigurationHelper::flush(xCfgOld);
701 : }
702 :
703 0 : m_bIgnoreEvents = false;
704 0 : }
705 :
706 0 : void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
707 : const OUStringList& lOld )
708 : {
709 0 : OUStringList::const_iterator pIt;
710 0 : for ( pIt = lOld.begin();
711 0 : pIt != lOld.end();
712 : ++pIt )
713 : {
714 0 : const OUString& sOld = *pIt;
715 :
716 0 : if (rPath.bIsSinglePath)
717 : {
718 : SAL_WARN_IF(lOld.size()>1, "fwk", "PathSettings::impl_mergeOldUserPaths(): Single path has more then one path value inside old configuration (Common.xcu)!");
719 0 : if (! rPath.sWritePath.equals(sOld))
720 0 : rPath.sWritePath = sOld;
721 : }
722 : else
723 : {
724 0 : if (
725 0 : ( rPath.lInternalPaths.findConst(sOld) == rPath.lInternalPaths.end()) &&
726 0 : ( rPath.lUserPaths.findConst(sOld) == rPath.lUserPaths.end() ) &&
727 0 : (! rPath.sWritePath.equals(sOld) )
728 : )
729 0 : rPath.lUserPaths.push_back(sOld);
730 : }
731 : }
732 0 : }
733 :
734 0 : PathSettings::EChangeOp PathSettings::impl_updatePath(const OUString& sPath ,
735 : bool bNotifyListener)
736 : {
737 : // SAFE ->
738 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
739 :
740 0 : PathSettings::PathInfo* pPathOld = 0;
741 0 : PathSettings::PathInfo* pPathNew = 0;
742 0 : PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
743 0 : PathSettings::PathInfo aPath;
744 :
745 : try
746 : {
747 0 : aPath = impl_readNewFormat(sPath);
748 0 : aPath.sPathName = sPath;
749 : // replace all might existing variables with real values
750 : // Do it before these old paths will be compared against the
751 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
752 : // will produce strings with same content (because some variables are redundant!)
753 0 : impl_subst(aPath, false);
754 : }
755 0 : catch(const css::uno::RuntimeException&)
756 0 : { throw; }
757 0 : catch(const css::container::NoSuchElementException&)
758 0 : { eOp = PathSettings::E_REMOVED; }
759 0 : catch(const css::uno::Exception&)
760 0 : { throw; }
761 :
762 : try
763 : {
764 : // migration of old user defined values on demand
765 : // can be disabled for a new major
766 0 : OUStringList lOldVals = impl_readOldFormat(sPath);
767 : // replace all might existing variables with real values
768 : // Do it before these old paths will be compared against the
769 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
770 : // will produce strings with same content (because some variables are redundant!)
771 0 : impl_subst(lOldVals, fa_getSubstitution(), false);
772 0 : impl_mergeOldUserPaths(aPath, lOldVals);
773 : }
774 0 : catch(const css::uno::RuntimeException&)
775 0 : { throw; }
776 : // Normal(!) exceptions can be ignored!
777 : // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
778 : // we cant find a value for it inside the "old" configuration. So a NoSuchElementException
779 : // will be normal .-)
780 0 : catch(const css::uno::Exception&)
781 : {}
782 :
783 0 : PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
784 0 : if (eOp == PathSettings::E_UNDEFINED)
785 : {
786 0 : if (pPath != m_lPaths.end())
787 0 : eOp = PathSettings::E_CHANGED;
788 : else
789 0 : eOp = PathSettings::E_ADDED;
790 : }
791 :
792 0 : switch(eOp)
793 : {
794 : case PathSettings::E_ADDED :
795 : {
796 0 : if (bNotifyListener)
797 : {
798 0 : pPathOld = 0;
799 0 : pPathNew = &aPath;
800 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
801 : }
802 0 : m_lPaths[sPath] = aPath;
803 : }
804 0 : break;
805 :
806 : case PathSettings::E_CHANGED :
807 : {
808 0 : if (bNotifyListener)
809 : {
810 0 : pPathOld = &(pPath->second);
811 0 : pPathNew = &aPath;
812 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
813 : }
814 0 : m_lPaths[sPath] = aPath;
815 : }
816 0 : break;
817 :
818 : case PathSettings::E_REMOVED :
819 : {
820 0 : if (pPath != m_lPaths.end())
821 : {
822 0 : if (bNotifyListener)
823 : {
824 0 : pPathOld = &(pPath->second);
825 0 : pPathNew = 0;
826 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
827 : }
828 0 : m_lPaths.erase(pPath);
829 : }
830 : }
831 0 : break;
832 :
833 : default: // to let compiler be happy
834 0 : break;
835 : }
836 :
837 0 : return eOp;
838 : }
839 :
840 0 : css::uno::Sequence< sal_Int32 > PathSettings::impl_mapPathName2IDList(const OUString& sPath)
841 : {
842 0 : OUString sOldStyleProp = sPath;
843 0 : OUString sInternalProp = sPath+POSTFIX_INTERNAL_PATHS;
844 0 : OUString sUserProp = sPath+POSTFIX_USER_PATHS;
845 0 : OUString sWriteProp = sPath+POSTFIX_WRITE_PATH;
846 :
847 : // Attention: The default set of IDs is fix and must follow these schema.
848 : // Otherwhise the outside code ant work for new added properties.
849 : // Why ?
850 : // The outside code must fire N events for every changed property.
851 : // And the knowing about packaging of variables of the structure PathInfo
852 : // follow these group IDs ! But if such ID isnt in the range of [0..IDGROUP_COUNT]
853 : // the outside cant determine the right group ... and cant fire the right events .-)
854 :
855 0 : css::uno::Sequence< sal_Int32 > lIDs(IDGROUP_COUNT);
856 0 : lIDs[0] = IDGROUP_OLDSTYLE;
857 0 : lIDs[1] = IDGROUP_INTERNAL_PATHS;
858 0 : lIDs[2] = IDGROUP_USER_PATHS;
859 0 : lIDs[3] = IDGROUP_WRITE_PATH;
860 :
861 0 : sal_Int32 c = m_lPropDesc.getLength();
862 0 : sal_Int32 i = 0;
863 0 : for (i=0; i<c; ++i)
864 : {
865 0 : const css::beans::Property& rProp = m_lPropDesc[i];
866 :
867 0 : if (rProp.Name.equals(sOldStyleProp))
868 0 : lIDs[IDGROUP_OLDSTYLE] = rProp.Handle;
869 : else
870 0 : if (rProp.Name.equals(sInternalProp))
871 0 : lIDs[IDGROUP_INTERNAL_PATHS] = rProp.Handle;
872 : else
873 0 : if (rProp.Name.equals(sUserProp))
874 0 : lIDs[IDGROUP_USER_PATHS] = rProp.Handle;
875 : else
876 0 : if (rProp.Name.equals(sWriteProp))
877 0 : lIDs[IDGROUP_WRITE_PATH] = rProp.Handle;
878 : }
879 :
880 0 : return lIDs;
881 : }
882 :
883 0 : void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp /*eOp*/ ,
884 : const OUString& sPath ,
885 : const PathSettings::PathInfo* pPathOld,
886 : const PathSettings::PathInfo* pPathNew)
887 : {
888 0 : css::uno::Sequence< sal_Int32 > lHandles(1);
889 0 : css::uno::Sequence< css::uno::Any > lOldVals(1);
890 0 : css::uno::Sequence< css::uno::Any > lNewVals(1);
891 :
892 0 : css::uno::Sequence< sal_Int32 > lIDs = impl_mapPathName2IDList(sPath);
893 0 : sal_Int32 c = lIDs.getLength();
894 0 : sal_Int32 i = 0;
895 0 : sal_Int32 nMaxID = m_lPropDesc.getLength()-1;
896 0 : for (i=0; i<c; ++i)
897 : {
898 0 : sal_Int32 nID = lIDs[i];
899 :
900 0 : if (
901 0 : (nID < 0 ) ||
902 : (nID > nMaxID)
903 : )
904 0 : continue;
905 :
906 0 : lHandles[0] = nID;
907 0 : switch(impl_getPropGroup(nID))
908 : {
909 : case IDGROUP_OLDSTYLE :
910 : {
911 0 : if (pPathOld)
912 : {
913 0 : OUString sVal = impl_convertPath2OldStyle(*pPathOld);
914 0 : lOldVals[0] <<= sVal;
915 : }
916 0 : if (pPathNew)
917 : {
918 0 : OUString sVal = impl_convertPath2OldStyle(*pPathNew);
919 0 : lNewVals[0] <<= sVal;
920 : }
921 : }
922 0 : break;
923 :
924 : case IDGROUP_INTERNAL_PATHS :
925 : {
926 0 : if (pPathOld)
927 0 : lOldVals[0] <<= pPathOld->lInternalPaths.getAsConstList();
928 0 : if (pPathNew)
929 0 : lNewVals[0] <<= pPathNew->lInternalPaths.getAsConstList();
930 : }
931 0 : break;
932 :
933 : case IDGROUP_USER_PATHS :
934 : {
935 0 : if (pPathOld)
936 0 : lOldVals[0] <<= pPathOld->lUserPaths.getAsConstList();
937 0 : if (pPathNew)
938 0 : lNewVals[0] <<= pPathNew->lUserPaths.getAsConstList();
939 : }
940 0 : break;
941 :
942 : case IDGROUP_WRITE_PATH :
943 : {
944 0 : if (pPathOld)
945 0 : lOldVals[0] <<= pPathOld->sWritePath;
946 0 : if (pPathNew)
947 0 : lNewVals[0] <<= pPathNew->sWritePath;
948 : }
949 0 : break;
950 : }
951 :
952 : fire(lHandles.getArray(),
953 0 : lNewVals.getArray(),
954 0 : lOldVals.getArray(),
955 : 1,
956 0 : sal_False);
957 0 : }
958 0 : }
959 :
960 0 : void PathSettings::impl_subst( OUStringList& lVals ,
961 : const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
962 : bool bReSubst)
963 : {
964 0 : OUStringList::iterator pIt;
965 :
966 0 : for ( pIt = lVals.begin();
967 0 : pIt != lVals.end();
968 : ++pIt )
969 : {
970 0 : const OUString& sOld = *pIt;
971 0 : OUString sNew;
972 0 : if (bReSubst)
973 0 : sNew = xSubst->reSubstituteVariables(sOld);
974 : else
975 0 : sNew = xSubst->substituteVariables(sOld, sal_False);
976 :
977 0 : *pIt = sNew;
978 0 : }
979 0 : }
980 :
981 0 : void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
982 : bool bReSubst)
983 : {
984 0 : css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
985 :
986 0 : impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
987 0 : impl_subst(aPath.lUserPaths , xSubst, bReSubst);
988 0 : if (bReSubst)
989 0 : aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
990 : else
991 0 : aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, sal_False);
992 0 : }
993 :
994 0 : OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
995 : {
996 0 : OUStringList::const_iterator pIt;
997 0 : OUStringList lTemp;
998 0 : lTemp.reserve(rPath.lInternalPaths.size() + rPath.lUserPaths.size() + 1);
999 :
1000 0 : for ( pIt = rPath.lInternalPaths.begin();
1001 0 : pIt != rPath.lInternalPaths.end();
1002 : ++pIt )
1003 : {
1004 0 : lTemp.push_back(*pIt);
1005 : }
1006 0 : for ( pIt = rPath.lUserPaths.begin();
1007 0 : pIt != rPath.lUserPaths.end();
1008 : ++pIt )
1009 : {
1010 0 : lTemp.push_back(*pIt);
1011 : }
1012 :
1013 0 : if (!rPath.sWritePath.isEmpty())
1014 0 : lTemp.push_back(rPath.sWritePath);
1015 :
1016 0 : OUStringBuffer sPathVal(256);
1017 0 : for ( pIt = lTemp.begin();
1018 0 : pIt != lTemp.end();
1019 : )
1020 : {
1021 0 : sPathVal.append(*pIt);
1022 0 : ++pIt;
1023 0 : if (pIt != lTemp.end())
1024 0 : sPathVal.appendAscii(";");
1025 : }
1026 :
1027 0 : return sPathVal.makeStringAndClear();
1028 : }
1029 :
1030 0 : OUStringList PathSettings::impl_convertOldStyle2Path(const OUString& sOldStylePath) const
1031 : {
1032 0 : OUStringList lList;
1033 0 : sal_Int32 nToken = 0;
1034 0 : do
1035 : {
1036 0 : OUString sToken = sOldStylePath.getToken(0, ';', nToken);
1037 0 : if (!sToken.isEmpty())
1038 0 : lList.push_back(sToken);
1039 : }
1040 0 : while(nToken >= 0);
1041 :
1042 0 : return lList;
1043 : }
1044 :
1045 0 : void PathSettings::impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
1046 : OUStringList& lList)
1047 : {
1048 0 : OUStringList::const_iterator pIt;
1049 0 : for ( pIt = rPath.lInternalPaths.begin();
1050 0 : pIt != rPath.lInternalPaths.end();
1051 : ++pIt )
1052 : {
1053 0 : const OUString& rItem = *pIt;
1054 0 : OUStringList::iterator pItem = lList.find(rItem);
1055 0 : if (pItem != lList.end())
1056 0 : lList.erase(pItem);
1057 : }
1058 0 : for ( pIt = rPath.lUserPaths.begin();
1059 0 : pIt != rPath.lUserPaths.end();
1060 : ++pIt )
1061 : {
1062 0 : const OUString& rItem = *pIt;
1063 0 : OUStringList::iterator pItem = lList.find(rItem);
1064 0 : if (pItem != lList.end())
1065 0 : lList.erase(pItem);
1066 : }
1067 :
1068 0 : OUStringList::iterator pItem = lList.find(rPath.sWritePath);
1069 0 : if (pItem != lList.end())
1070 0 : lList.erase(pItem);
1071 0 : }
1072 :
1073 0 : void PathSettings::impl_rebuildPropertyDescriptor()
1074 : {
1075 : // SAFE ->
1076 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1077 :
1078 0 : sal_Int32 c = (sal_Int32)m_lPaths.size();
1079 0 : sal_Int32 i = 0;
1080 0 : m_lPropDesc.realloc(c*IDGROUP_COUNT);
1081 :
1082 0 : PathHash::const_iterator pIt;
1083 0 : for ( pIt = m_lPaths.begin();
1084 0 : pIt != m_lPaths.end();
1085 : ++pIt )
1086 : {
1087 0 : const PathSettings::PathInfo& rPath = pIt->second;
1088 0 : css::beans::Property* pProp = 0;
1089 :
1090 0 : pProp = &(m_lPropDesc[i]);
1091 0 : pProp->Name = rPath.sPathName;
1092 0 : pProp->Handle = i;
1093 0 : pProp->Type = ::getCppuType((OUString*)0);
1094 0 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1095 0 : if (rPath.bIsReadonly)
1096 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1097 0 : ++i;
1098 :
1099 0 : pProp = &(m_lPropDesc[i]);
1100 0 : pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHS;
1101 0 : pProp->Handle = i;
1102 0 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
1103 : pProp->Attributes = css::beans::PropertyAttribute::BOUND |
1104 0 : css::beans::PropertyAttribute::READONLY;
1105 0 : ++i;
1106 :
1107 0 : pProp = &(m_lPropDesc[i]);
1108 0 : pProp->Name = rPath.sPathName+POSTFIX_USER_PATHS;
1109 0 : pProp->Handle = i;
1110 0 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
1111 0 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1112 0 : if (rPath.bIsReadonly)
1113 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1114 0 : ++i;
1115 :
1116 0 : pProp = &(m_lPropDesc[i]);
1117 0 : pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
1118 0 : pProp->Handle = i;
1119 0 : pProp->Type = ::getCppuType((OUString*)0);
1120 0 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1121 0 : if (rPath.bIsReadonly)
1122 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1123 0 : ++i;
1124 : }
1125 :
1126 0 : delete m_pPropHelp;
1127 0 : m_pPropHelp = new ::cppu::OPropertyArrayHelper(m_lPropDesc, sal_False); // false => not sorted ... must be done inside helper
1128 :
1129 : // <- SAFE
1130 0 : }
1131 :
1132 0 : css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
1133 : {
1134 0 : const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
1135 0 : if (! pPath)
1136 0 : throw css::lang::IllegalArgumentException();
1137 :
1138 0 : css::uno::Any aVal;
1139 0 : switch(impl_getPropGroup(nID))
1140 : {
1141 : case IDGROUP_OLDSTYLE :
1142 : {
1143 0 : OUString sVal = impl_convertPath2OldStyle(*pPath);
1144 0 : aVal <<= sVal;
1145 : }
1146 0 : break;
1147 :
1148 : case IDGROUP_INTERNAL_PATHS :
1149 : {
1150 0 : aVal <<= pPath->lInternalPaths.getAsConstList();
1151 : }
1152 0 : break;
1153 :
1154 : case IDGROUP_USER_PATHS :
1155 : {
1156 0 : aVal <<= pPath->lUserPaths.getAsConstList();
1157 : }
1158 0 : break;
1159 :
1160 : case IDGROUP_WRITE_PATH :
1161 : {
1162 0 : aVal <<= pPath->sWritePath;
1163 : }
1164 0 : break;
1165 : }
1166 :
1167 0 : return aVal;
1168 : }
1169 :
1170 0 : void PathSettings::impl_setPathValue( sal_Int32 nID ,
1171 : const css::uno::Any& aVal)
1172 : {
1173 0 : PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
1174 0 : if (! pOrgPath)
1175 0 : throw css::container::NoSuchElementException();
1176 :
1177 : // We work on a copied path ... so we can be sure that errors during this operation
1178 : // does not make our internal cache invalid .-)
1179 0 : PathSettings::PathInfo aChangePath(*pOrgPath);
1180 :
1181 0 : switch(impl_getPropGroup(nID))
1182 : {
1183 : case IDGROUP_OLDSTYLE :
1184 : {
1185 0 : OUString sVal;
1186 0 : aVal >>= sVal;
1187 0 : OUStringList lList = impl_convertOldStyle2Path(sVal);
1188 0 : impl_subst(lList, fa_getSubstitution(), false);
1189 0 : impl_purgeKnownPaths(aChangePath, lList);
1190 0 : if (! impl_isValidPath(lList))
1191 0 : throw css::lang::IllegalArgumentException();
1192 :
1193 0 : if (aChangePath.bIsSinglePath)
1194 : {
1195 : SAL_WARN_IF(lList.size()>1, "fwk", "PathSettings::impl_setPathValue(): You try to set more then path value for a defined SINGLE_PATH!");
1196 0 : if ( !lList.empty() )
1197 0 : aChangePath.sWritePath = *(lList.begin());
1198 : else
1199 0 : aChangePath.sWritePath = OUString();
1200 : }
1201 : else
1202 : {
1203 0 : OUStringList::const_iterator pIt;
1204 0 : for ( pIt = lList.begin();
1205 0 : pIt != lList.end();
1206 : ++pIt )
1207 : {
1208 0 : aChangePath.lUserPaths.push_back(*pIt);
1209 : }
1210 0 : }
1211 : }
1212 0 : break;
1213 :
1214 : case IDGROUP_INTERNAL_PATHS :
1215 : {
1216 0 : if (aChangePath.bIsSinglePath)
1217 : {
1218 0 : OUStringBuffer sMsg(256);
1219 0 : sMsg.appendAscii("The path '" );
1220 0 : sMsg.append (aChangePath.sPathName);
1221 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths cant be set.");
1222 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1223 0 : static_cast< ::cppu::OWeakObject* >(this));
1224 : }
1225 :
1226 0 : OUStringList lList;
1227 0 : lList << aVal;
1228 0 : if (! impl_isValidPath(lList))
1229 0 : throw css::lang::IllegalArgumentException();
1230 0 : aChangePath.lInternalPaths = lList;
1231 : }
1232 0 : break;
1233 :
1234 : case IDGROUP_USER_PATHS :
1235 : {
1236 0 : if (aChangePath.bIsSinglePath)
1237 : {
1238 0 : OUStringBuffer sMsg(256);
1239 0 : sMsg.appendAscii("The path '" );
1240 0 : sMsg.append (aChangePath.sPathName);
1241 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths cant be set.");
1242 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1243 0 : static_cast< ::cppu::OWeakObject* >(this));
1244 : }
1245 :
1246 0 : OUStringList lList;
1247 0 : lList << aVal;
1248 0 : if (! impl_isValidPath(lList))
1249 0 : throw css::lang::IllegalArgumentException();
1250 0 : aChangePath.lUserPaths = lList;
1251 : }
1252 0 : break;
1253 :
1254 : case IDGROUP_WRITE_PATH :
1255 : {
1256 0 : OUString sVal;
1257 0 : aVal >>= sVal;
1258 0 : if (! impl_isValidPath(sVal))
1259 0 : throw css::lang::IllegalArgumentException();
1260 0 : aChangePath.sWritePath = sVal;
1261 : }
1262 0 : break;
1263 : }
1264 :
1265 : // TODO check if path has at least one path value set
1266 : // At least it depends from the feature using this path, if an empty path list is allowed.
1267 :
1268 : // first we should try to store the changed (copied!) path ...
1269 : // In case an error occurs on saving time an exception is thrown ...
1270 : // If no exception occurs we can update our internal cache (means
1271 : // we can overwrite pOrgPath !
1272 0 : impl_storePath(aChangePath);
1273 0 : pOrgPath->takeOver(aChangePath);
1274 0 : }
1275 :
1276 0 : bool PathSettings::impl_isValidPath(const OUStringList& lPath) const
1277 : {
1278 0 : OUStringList::const_iterator pIt;
1279 0 : for ( pIt = lPath.begin();
1280 0 : pIt != lPath.end();
1281 : ++pIt )
1282 : {
1283 0 : const OUString& rVal = *pIt;
1284 0 : if (! impl_isValidPath(rVal))
1285 0 : return false;
1286 : }
1287 :
1288 0 : return true;
1289 : }
1290 :
1291 0 : bool PathSettings::impl_isValidPath(const OUString& sPath) const
1292 : {
1293 : // allow empty path to reset a path.
1294 : // idea by LLA to support empty paths
1295 : // if (sPath.getLength() == 0)
1296 : // {
1297 : // return sal_True;
1298 : // }
1299 :
1300 0 : return (! INetURLObject(sPath).HasError());
1301 : }
1302 :
1303 0 : OUString impl_extractBaseFromPropName(const OUString& sPropName)
1304 : {
1305 0 : sal_Int32 i = sPropName.indexOf(POSTFIX_INTERNAL_PATHS);
1306 0 : if (i > -1)
1307 0 : return sPropName.copy(0, i);
1308 0 : i = sPropName.indexOf(POSTFIX_USER_PATHS);
1309 0 : if (i > -1)
1310 0 : return sPropName.copy(0, i);
1311 0 : i = sPropName.indexOf(POSTFIX_WRITE_PATH);
1312 0 : if (i > -1)
1313 0 : return sPropName.copy(0, i);
1314 :
1315 0 : return sPropName;
1316 : }
1317 :
1318 0 : PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
1319 : {
1320 : // SAFE ->
1321 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1322 :
1323 0 : if (nHandle > (m_lPropDesc.getLength()-1))
1324 0 : return 0;
1325 :
1326 0 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1327 0 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1328 0 : PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
1329 :
1330 0 : if (rPath != m_lPaths.end())
1331 0 : return &(rPath->second);
1332 :
1333 0 : return 0;
1334 : // <- SAFE
1335 : }
1336 :
1337 0 : const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
1338 : {
1339 : // SAFE ->
1340 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1341 :
1342 0 : if (nHandle > (m_lPropDesc.getLength()-1))
1343 0 : return 0;
1344 :
1345 0 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1346 0 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1347 0 : PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
1348 :
1349 0 : if (rPath != m_lPaths.end())
1350 0 : return &(rPath->second);
1351 :
1352 0 : return 0;
1353 : // <- SAFE
1354 : }
1355 :
1356 0 : sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
1357 : css::uno::Any& aOldValue ,
1358 : sal_Int32 nHandle ,
1359 : const css::uno::Any& aValue )
1360 : throw(css::lang::IllegalArgumentException)
1361 : {
1362 : // throws NoSuchElementException !
1363 0 : css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
1364 :
1365 : return PropHelper::willPropertyBeChanged(
1366 : aCurrentVal,
1367 : aValue,
1368 : aOldValue,
1369 0 : aConvertedValue);
1370 : }
1371 :
1372 0 : void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
1373 : const css::uno::Any& aValue )
1374 : throw(css::uno::Exception, std::exception)
1375 : {
1376 : // throws NoSuchElement- and IllegalArgumentException !
1377 0 : impl_setPathValue(nHandle, aValue);
1378 0 : }
1379 :
1380 0 : void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
1381 : sal_Int32 nHandle) const
1382 : {
1383 0 : aValue = impl_getPathValue(nHandle);
1384 0 : }
1385 :
1386 0 : ::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
1387 : {
1388 0 : return *m_pPropHelp;
1389 : }
1390 :
1391 0 : css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
1392 : throw(css::uno::RuntimeException, std::exception)
1393 : {
1394 : return css::uno::Reference< css::beans::XPropertySetInfo >(
1395 0 : ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()));
1396 : }
1397 :
1398 0 : css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
1399 : {
1400 0 : css::uno::Reference< css::util::XStringSubstitution > xSubst;
1401 : { // SAFE ->
1402 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1403 0 : xSubst = m_xSubstitution;
1404 : }
1405 :
1406 0 : if (! xSubst.is())
1407 : {
1408 : // create the needed substitution service.
1409 : // We must replace all used variables inside readed path values.
1410 : // In case we can't do so ... the whole office can't work really.
1411 : // That's why it seems to be OK to throw a RuntimeException then.
1412 0 : xSubst = css::util::PathSubstitution::create(m_xContext);
1413 :
1414 : { // SAFE ->
1415 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1416 0 : m_xSubstitution = xSubst;
1417 : }
1418 : }
1419 :
1420 0 : return xSubst;
1421 : }
1422 :
1423 0 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
1424 : {
1425 0 : const OUString CFG_NODE_OLD("org.openoffice.Office.Common/Path/Current");
1426 :
1427 0 : css::uno::Reference< css::container::XNameAccess > xCfg;
1428 : { // SAFE ->
1429 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1430 0 : xCfg = m_xCfgOld;
1431 : } // <- SAFE
1432 :
1433 0 : if (! xCfg.is())
1434 : {
1435 0 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1436 : ::comphelper::ConfigurationHelper::openConfig(
1437 : m_xContext,
1438 : CFG_NODE_OLD,
1439 : ::comphelper::ConfigurationHelper::E_STANDARD), // not readonly! Sometimes we need write access there !!!
1440 0 : css::uno::UNO_QUERY_THROW);
1441 :
1442 : { // SAFE ->
1443 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1444 0 : m_xCfgOld = xCfg;
1445 : }
1446 : }
1447 :
1448 0 : return xCfg;
1449 : }
1450 :
1451 0 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
1452 : {
1453 0 : const OUString CFG_NODE_NEW("org.openoffice.Office.Paths/Paths");
1454 :
1455 0 : css::uno::Reference< css::container::XNameAccess > xCfg;
1456 : { // SAFE ->
1457 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1458 0 : xCfg = m_xCfgNew;
1459 : } // <- SAFE
1460 :
1461 0 : if (! xCfg.is())
1462 : {
1463 0 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1464 : ::comphelper::ConfigurationHelper::openConfig(
1465 : m_xContext,
1466 : CFG_NODE_NEW,
1467 : ::comphelper::ConfigurationHelper::E_STANDARD),
1468 0 : css::uno::UNO_QUERY_THROW);
1469 :
1470 : { // SAFE ->
1471 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1472 0 : m_xCfgNew = xCfg;
1473 0 : m_xCfgNewListener = new WeakChangesListener(this);
1474 : }
1475 :
1476 0 : css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
1477 0 : xBroadcaster->addChangesListener(m_xCfgNewListener);
1478 : }
1479 :
1480 0 : return xCfg;
1481 : }
1482 :
1483 0 : struct Instance {
1484 0 : explicit Instance(
1485 : css::uno::Reference<css::uno::XComponentContext> const & context):
1486 : instance(
1487 0 : static_cast<cppu::OWeakObject *>(new PathSettings(context)))
1488 : {
1489 : // fill cache
1490 : static_cast<PathSettings *>(static_cast<cppu::OWeakObject *>
1491 0 : (instance.get()))->impl_readAll();
1492 0 : }
1493 :
1494 : css::uno::Reference<css::uno::XInterface> instance;
1495 : };
1496 :
1497 : struct Singleton:
1498 : public rtl::StaticWithArg<
1499 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
1500 : {};
1501 :
1502 : }
1503 :
1504 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1505 0 : com_sun_star_comp_framework_PathSettings_get_implementation(
1506 : css::uno::XComponentContext *context,
1507 : css::uno::Sequence<css::uno::Any> const &)
1508 : {
1509 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
1510 0 : Singleton::get(context).instance.get()));
1511 : }
1512 :
1513 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|