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 19932 : sal_Int32 impl_getPropGroup(sal_Int32 nID)
74 : {
75 19932 : 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 25152 : struct PathInfo
93 : {
94 : public:
95 :
96 15120 : PathInfo()
97 : : sPathName ()
98 : , lInternalPaths()
99 : , lUserPaths ()
100 : , sWritePath ()
101 : , bIsSinglePath (false)
102 15120 : , bIsReadonly (false)
103 15120 : {}
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 1 : virtual OUString SAL_CALL getImplementationName()
189 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
190 : {
191 1 : 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 1 : virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
201 : throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
202 : {
203 1 : css::uno::Sequence< OUString > aSeq(1);
204 1 : aSeq[0] = "com.sun.star.util.PathSettings";
205 1 : 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 10108 : virtual void SAL_CALL acquire() throw () SAL_OVERRIDE
211 10108 : { OWeakObject::acquire(); }
212 10104 : virtual void SAL_CALL release() throw () SAL_OVERRIDE
213 10104 : { 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 1877 : virtual OUString SAL_CALL getBasePathShareLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
325 1877 : { 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 107 : virtual OUString SAL_CALL getBasePathUserLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
329 107 : { 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 691 : 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 691 : { 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(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 210 : 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 210 : , m_bIgnoreEvents(false)
464 : {
465 210 : }
466 :
467 624 : PathSettings::~PathSettings()
468 : {
469 208 : disposing();
470 416 : }
471 :
472 416 : void SAL_CALL PathSettings::disposing()
473 : {
474 416 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
475 :
476 : css::uno::Reference< css::util::XChangesNotifier >
477 832 : xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY);
478 416 : if (xBroadcaster.is())
479 208 : xBroadcaster->removeChangesListener(m_xCfgNewListener);
480 :
481 416 : m_xSubstitution.clear();
482 416 : m_xCfgOld.clear();
483 416 : m_xCfgNew.clear();
484 416 : m_xCfgNewListener.clear();
485 :
486 416 : delete m_pPropHelp;
487 832 : m_pPropHelp = 0;
488 416 : }
489 :
490 3359 : css::uno::Any SAL_CALL PathSettings::queryInterface( const css::uno::Type& _rType )
491 : throw(css::uno::RuntimeException, std::exception)
492 : {
493 3359 : css::uno::Any aRet = PathSettings_BASE::queryInterface( _rType );
494 3359 : if ( !aRet.hasValue() )
495 210 : aRet = ::cppu::OPropertySetHelper::queryInterface( _rType );
496 3359 : 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 1984 : OUString PathSettings::getStringProperty(const OUString& p1)
548 : throw(css::uno::RuntimeException)
549 : {
550 1984 : css::uno::Any a = ::cppu::OPropertySetHelper::getPropertyValue(p1);
551 1984 : OUString s;
552 1984 : a >>= s;
553 1984 : 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 210 : void PathSettings::impl_readAll()
563 : {
564 : try
565 : {
566 : // TODO think about me
567 210 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
568 420 : css::uno::Sequence< OUString > lPaths = xCfg->getElementNames();
569 :
570 210 : sal_Int32 c = lPaths.getLength();
571 5250 : for (sal_Int32 i = 0; i < c; ++i)
572 : {
573 5040 : const OUString& sPath = lPaths[i];
574 5040 : impl_updatePath(sPath, false);
575 210 : }
576 : }
577 0 : catch(const css::uno::RuntimeException& )
578 : {
579 : }
580 :
581 210 : impl_rebuildPropertyDescriptor();
582 210 : }
583 :
584 : // NO substitution here ! It's done outside ...
585 5040 : OUStringList PathSettings::impl_readOldFormat(const OUString& sPath)
586 : {
587 5040 : css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
588 5040 : OUStringList aPathVal;
589 :
590 5040 : if( xCfg->hasByName(sPath) )
591 : {
592 4830 : css::uno::Any aVal( xCfg->getByName(sPath) );
593 :
594 9660 : OUString sStringVal;
595 9660 : css::uno::Sequence< OUString > lStringListVal;
596 :
597 4830 : if (aVal >>= sStringVal)
598 : {
599 3150 : aPathVal.push_back(sStringVal);
600 : }
601 1680 : else if (aVal >>= lStringListVal)
602 : {
603 1680 : aPathVal = comphelper::sequenceToContainer<OUStringList>(lStringListVal);
604 4830 : }
605 : }
606 :
607 5040 : return aPathVal;
608 : }
609 :
610 : // NO substitution here ! It's done outside ...
611 5040 : PathSettings::PathInfo PathSettings::impl_readNewFormat(const OUString& sPath)
612 : {
613 5040 : const OUString CFGPROP_INTERNALPATHS("InternalPaths");
614 10080 : const OUString CFGPROP_ISSINGLEPATH("IsSinglePath");
615 :
616 10080 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
617 :
618 : // get access to the "queried" path
619 10080 : css::uno::Reference< css::container::XNameAccess > xPath;
620 5040 : xCfg->getByName(sPath) >>= xPath;
621 :
622 5040 : PathSettings::PathInfo aPathVal;
623 :
624 : // read internal path list
625 10080 : css::uno::Reference< css::container::XNameAccess > xIPath;
626 5040 : xPath->getByName(CFGPROP_INTERNALPATHS) >>= xIPath;
627 5040 : aPathVal.lInternalPaths = comphelper::sequenceToContainer<OUStringList>(xIPath->getElementNames());
628 :
629 : // read user defined path list
630 10080 : css::uno::Sequence<OUString> vTmpUserPathsSeq;
631 5040 : xPath->getByName(CFGPROP_USERPATHS) >>= vTmpUserPathsSeq;
632 5040 : aPathVal.lUserPaths = comphelper::sequenceToContainer<OUStringList>(vTmpUserPathsSeq);
633 :
634 : // read the writeable path
635 5040 : xPath->getByName(CFGPROP_WRITEPATH) >>= aPathVal.sWritePath;
636 :
637 : // avoid duplicates, by removing the writeable path from
638 : // the user defined path list if it happens to be there too
639 5040 : OUStringList::iterator aI = find(aPathVal.lUserPaths, aPathVal.sWritePath);
640 5040 : if (aI != aPathVal.lUserPaths.end())
641 210 : aPathVal.lUserPaths.erase(aI);
642 :
643 : // read state props
644 5040 : xPath->getByName(CFGPROP_ISSINGLEPATH) >>= aPathVal.bIsSinglePath;
645 :
646 : // analyze finalized/mandatory states
647 5040 : aPathVal.bIsReadonly = false;
648 10080 : css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
649 5040 : if (xInfo.is())
650 : {
651 5040 : css::beans::Property aInfo = xInfo->getAsProperty();
652 5040 : bool bFinalized = ((aInfo.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
653 :
654 : // Note: 'till we support finalized/mandatory on our API more in detail we handle
655 : // all states simple as READONLY! But because all really needed paths are "mandatory" by default
656 : // we have to handle "finalized" as the real "readonly" indicator.
657 5040 : aPathVal.bIsReadonly = bFinalized;
658 : }
659 :
660 10080 : return aPathVal;
661 : }
662 :
663 0 : void PathSettings::impl_storePath(const PathSettings::PathInfo& aPath)
664 : {
665 0 : m_bIgnoreEvents = true;
666 :
667 0 : css::uno::Reference< css::container::XNameAccess > xCfgNew = fa_getCfgNew();
668 0 : css::uno::Reference< css::container::XNameAccess > xCfgOld = fa_getCfgOld();
669 :
670 : // try to replace path-parts with well known and supported variables.
671 : // So an office can be moved easialy to another location without losing
672 : // it's related paths.
673 0 : PathInfo aResubstPath(aPath);
674 0 : impl_subst(aResubstPath, true);
675 :
676 : // update new configuration
677 0 : if (! aResubstPath.bIsSinglePath)
678 : {
679 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
680 : aResubstPath.sPathName,
681 : CFGPROP_USERPATHS,
682 0 : css::uno::makeAny(comphelper::containerToSequence(aResubstPath.lUserPaths)));
683 : }
684 :
685 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
686 : aResubstPath.sPathName,
687 : CFGPROP_WRITEPATH,
688 0 : css::uno::makeAny(aResubstPath.sWritePath));
689 :
690 0 : ::comphelper::ConfigurationHelper::flush(xCfgNew);
691 :
692 : // remove the whole path from the old configuration!
693 : // Otherwise we can't make sure that the diff between new and old configuration
694 : // on loading time really represents a user setting!!!
695 :
696 : // Check if the given path exists inside the old configuration.
697 : // Because our new configuration knows more than the list of old paths ... !
698 0 : if (xCfgOld->hasByName(aResubstPath.sPathName))
699 : {
700 0 : css::uno::Reference< css::beans::XPropertySet > xProps(xCfgOld, css::uno::UNO_QUERY_THROW);
701 0 : xProps->setPropertyValue(aResubstPath.sPathName, css::uno::Any());
702 0 : ::comphelper::ConfigurationHelper::flush(xCfgOld);
703 : }
704 :
705 0 : m_bIgnoreEvents = false;
706 0 : }
707 :
708 5040 : void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
709 : const OUStringList& lOld )
710 : {
711 5040 : OUStringList::const_iterator pIt;
712 34020 : for ( pIt = lOld.begin();
713 22680 : pIt != lOld.end();
714 : ++pIt )
715 : {
716 6300 : const OUString& sOld = *pIt;
717 :
718 6300 : if (rPath.bIsSinglePath)
719 : {
720 : SAL_WARN_IF(lOld.size()>1, "fwk", "PathSettings::impl_mergeOldUserPaths(): Single path has more than one path value inside old configuration (Common.xcu)!");
721 1050 : if (! rPath.sWritePath.equals(sOld))
722 0 : rPath.sWritePath = sOld;
723 : }
724 : else
725 : {
726 10500 : if (
727 31533 : ( find(rPath.lInternalPaths, sOld) == rPath.lInternalPaths.end()) &&
728 31533 : ( find(rPath.lUserPaths, sOld) == rPath.lUserPaths.end() ) &&
729 1761 : (! rPath.sWritePath.equals(sOld) )
730 : )
731 81 : rPath.lUserPaths.push_back(sOld);
732 : }
733 : }
734 5040 : }
735 :
736 5040 : PathSettings::EChangeOp PathSettings::impl_updatePath(const OUString& sPath ,
737 : bool bNotifyListener)
738 : {
739 : // SAFE ->
740 5040 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
741 :
742 5040 : PathSettings::PathInfo* pPathOld = 0;
743 5040 : PathSettings::PathInfo* pPathNew = 0;
744 5040 : PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
745 10080 : PathSettings::PathInfo aPath;
746 :
747 : try
748 : {
749 5040 : aPath = impl_readNewFormat(sPath);
750 5040 : aPath.sPathName = sPath;
751 : // replace all might existing variables with real values
752 : // Do it before these old paths will be compared against the
753 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
754 : // will produce strings with same content (because some variables are redundant!)
755 5040 : impl_subst(aPath, false);
756 : }
757 0 : catch(const css::uno::RuntimeException&)
758 0 : { throw; }
759 0 : catch(const css::container::NoSuchElementException&)
760 0 : { eOp = PathSettings::E_REMOVED; }
761 0 : catch(const css::uno::Exception&)
762 0 : { throw; }
763 :
764 : try
765 : {
766 : // migration of old user defined values on demand
767 : // can be disabled for a new major
768 5040 : OUStringList lOldVals = impl_readOldFormat(sPath);
769 : // replace all might existing variables with real values
770 : // Do it before these old paths will be compared against the
771 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
772 : // will produce strings with same content (because some variables are redundant!)
773 5040 : impl_subst(lOldVals, fa_getSubstitution(), false);
774 5040 : impl_mergeOldUserPaths(aPath, lOldVals);
775 : }
776 0 : catch(const css::uno::RuntimeException&)
777 0 : { throw; }
778 : // Normal(!) exceptions can be ignored!
779 : // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
780 : // we can't find a value for it inside the "old" configuration. So a NoSuchElementException
781 : // will be normal .-)
782 0 : catch(const css::uno::Exception&)
783 : {}
784 :
785 5040 : PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
786 5040 : if (eOp == PathSettings::E_UNDEFINED)
787 : {
788 5040 : if (pPath != m_lPaths.end())
789 0 : eOp = PathSettings::E_CHANGED;
790 : else
791 5040 : eOp = PathSettings::E_ADDED;
792 : }
793 :
794 5040 : switch(eOp)
795 : {
796 : case PathSettings::E_ADDED :
797 : {
798 5040 : if (bNotifyListener)
799 : {
800 0 : pPathOld = 0;
801 0 : pPathNew = &aPath;
802 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
803 : }
804 5040 : m_lPaths[sPath] = aPath;
805 : }
806 5040 : break;
807 :
808 : case PathSettings::E_CHANGED :
809 : {
810 0 : if (bNotifyListener)
811 : {
812 0 : pPathOld = &(pPath->second);
813 0 : pPathNew = &aPath;
814 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
815 : }
816 0 : m_lPaths[sPath] = aPath;
817 : }
818 0 : break;
819 :
820 : case PathSettings::E_REMOVED :
821 : {
822 0 : if (pPath != m_lPaths.end())
823 : {
824 0 : if (bNotifyListener)
825 : {
826 0 : pPathOld = &(pPath->second);
827 0 : pPathNew = 0;
828 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
829 : }
830 0 : m_lPaths.erase(pPath);
831 : }
832 : }
833 0 : break;
834 :
835 : default: // to let compiler be happy
836 0 : break;
837 : }
838 :
839 10080 : return eOp;
840 : }
841 :
842 0 : css::uno::Sequence< sal_Int32 > PathSettings::impl_mapPathName2IDList(const OUString& sPath)
843 : {
844 0 : OUString sOldStyleProp = sPath;
845 0 : OUString sInternalProp = sPath+POSTFIX_INTERNAL_PATHS;
846 0 : OUString sUserProp = sPath+POSTFIX_USER_PATHS;
847 0 : OUString sWriteProp = sPath+POSTFIX_WRITE_PATH;
848 :
849 : // Attention: The default set of IDs is fix and must follow these schema.
850 : // Otherwhise the outside code ant work for new added properties.
851 : // Why?
852 : // The outside code must fire N events for every changed property.
853 : // And the knowing about packaging of variables of the structure PathInfo
854 : // follow these group IDs! But if such ID is not in the range of [0..IDGROUP_COUNT]
855 : // the outside can't determine the right group ... and can not fire the right events .-)
856 :
857 0 : css::uno::Sequence< sal_Int32 > lIDs(IDGROUP_COUNT);
858 0 : lIDs[0] = IDGROUP_OLDSTYLE;
859 0 : lIDs[1] = IDGROUP_INTERNAL_PATHS;
860 0 : lIDs[2] = IDGROUP_USER_PATHS;
861 0 : lIDs[3] = IDGROUP_WRITE_PATH;
862 :
863 0 : sal_Int32 c = m_lPropDesc.getLength();
864 0 : sal_Int32 i = 0;
865 0 : for (i=0; i<c; ++i)
866 : {
867 0 : const css::beans::Property& rProp = m_lPropDesc[i];
868 :
869 0 : if (rProp.Name.equals(sOldStyleProp))
870 0 : lIDs[IDGROUP_OLDSTYLE] = rProp.Handle;
871 : else
872 0 : if (rProp.Name.equals(sInternalProp))
873 0 : lIDs[IDGROUP_INTERNAL_PATHS] = rProp.Handle;
874 : else
875 0 : if (rProp.Name.equals(sUserProp))
876 0 : lIDs[IDGROUP_USER_PATHS] = rProp.Handle;
877 : else
878 0 : if (rProp.Name.equals(sWriteProp))
879 0 : lIDs[IDGROUP_WRITE_PATH] = rProp.Handle;
880 : }
881 :
882 0 : return lIDs;
883 : }
884 :
885 0 : void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp /*eOp*/ ,
886 : const OUString& sPath ,
887 : const PathSettings::PathInfo* pPathOld,
888 : const PathSettings::PathInfo* pPathNew)
889 : {
890 0 : css::uno::Sequence< sal_Int32 > lHandles(1);
891 0 : css::uno::Sequence< css::uno::Any > lOldVals(1);
892 0 : css::uno::Sequence< css::uno::Any > lNewVals(1);
893 :
894 0 : css::uno::Sequence< sal_Int32 > lIDs = impl_mapPathName2IDList(sPath);
895 0 : sal_Int32 c = lIDs.getLength();
896 0 : sal_Int32 i = 0;
897 0 : sal_Int32 nMaxID = m_lPropDesc.getLength()-1;
898 0 : for (i=0; i<c; ++i)
899 : {
900 0 : sal_Int32 nID = lIDs[i];
901 :
902 0 : if (
903 0 : (nID < 0 ) ||
904 : (nID > nMaxID)
905 : )
906 0 : continue;
907 :
908 0 : lHandles[0] = nID;
909 0 : switch(impl_getPropGroup(nID))
910 : {
911 : case IDGROUP_OLDSTYLE :
912 : {
913 0 : if (pPathOld)
914 : {
915 0 : OUString sVal = impl_convertPath2OldStyle(*pPathOld);
916 0 : lOldVals[0] <<= sVal;
917 : }
918 0 : if (pPathNew)
919 : {
920 0 : OUString sVal = impl_convertPath2OldStyle(*pPathNew);
921 0 : lNewVals[0] <<= sVal;
922 : }
923 : }
924 0 : break;
925 :
926 : case IDGROUP_INTERNAL_PATHS :
927 : {
928 0 : if (pPathOld)
929 0 : lOldVals[0] <<= comphelper::containerToSequence(pPathOld->lInternalPaths);
930 0 : if (pPathNew)
931 0 : lNewVals[0] <<= comphelper::containerToSequence(pPathNew->lInternalPaths);
932 : }
933 0 : break;
934 :
935 : case IDGROUP_USER_PATHS :
936 : {
937 0 : if (pPathOld)
938 0 : lOldVals[0] <<= comphelper::containerToSequence(pPathOld->lUserPaths);
939 0 : if (pPathNew)
940 0 : lNewVals[0] <<= comphelper::containerToSequence(pPathNew->lUserPaths);
941 : }
942 0 : break;
943 :
944 : case IDGROUP_WRITE_PATH :
945 : {
946 0 : if (pPathOld)
947 0 : lOldVals[0] <<= pPathOld->sWritePath;
948 0 : if (pPathNew)
949 0 : lNewVals[0] <<= pPathNew->sWritePath;
950 : }
951 0 : break;
952 : }
953 :
954 : fire(lHandles.getArray(),
955 0 : lNewVals.getArray(),
956 0 : lOldVals.getArray(),
957 : 1,
958 0 : sal_False);
959 0 : }
960 0 : }
961 :
962 15120 : void PathSettings::impl_subst( OUStringList& lVals ,
963 : const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
964 : bool bReSubst)
965 : {
966 15120 : OUStringList::iterator pIt;
967 :
968 76860 : for ( pIt = lVals.begin();
969 51240 : pIt != lVals.end();
970 : ++pIt )
971 : {
972 10500 : const OUString& sOld = *pIt;
973 10500 : OUString sNew;
974 10500 : if (bReSubst)
975 0 : sNew = xSubst->reSubstituteVariables(sOld);
976 : else
977 10500 : sNew = xSubst->substituteVariables(sOld, sal_False);
978 :
979 10500 : *pIt = sNew;
980 10500 : }
981 15120 : }
982 :
983 5040 : void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
984 : bool bReSubst)
985 : {
986 5040 : css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
987 :
988 5040 : impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
989 5040 : impl_subst(aPath.lUserPaths , xSubst, bReSubst);
990 5040 : if (bReSubst)
991 0 : aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
992 : else
993 5040 : aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, sal_False);
994 5040 : }
995 :
996 19590 : OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
997 : {
998 19590 : OUStringList::const_iterator pIt;
999 19590 : OUStringList lTemp;
1000 19590 : lTemp.reserve(rPath.lInternalPaths.size() + rPath.lUserPaths.size() + 1);
1001 :
1002 112923 : for ( pIt = rPath.lInternalPaths.begin();
1003 75282 : pIt != rPath.lInternalPaths.end();
1004 : ++pIt )
1005 : {
1006 18051 : lTemp.push_back(*pIt);
1007 : }
1008 59352 : for ( pIt = rPath.lUserPaths.begin();
1009 39568 : pIt != rPath.lUserPaths.end();
1010 : ++pIt )
1011 : {
1012 194 : lTemp.push_back(*pIt);
1013 : }
1014 :
1015 19590 : if (!rPath.sWritePath.isEmpty())
1016 17525 : lTemp.push_back(rPath.sWritePath);
1017 :
1018 39180 : OUStringBuffer sPathVal(256);
1019 130310 : for ( pIt = lTemp.begin();
1020 110720 : pIt != lTemp.end();
1021 : )
1022 : {
1023 35770 : sPathVal.append(*pIt);
1024 35770 : ++pIt;
1025 35770 : if (pIt != lTemp.end())
1026 16180 : sPathVal.appendAscii(";");
1027 : }
1028 :
1029 39180 : return sPathVal.makeStringAndClear();
1030 : }
1031 :
1032 0 : OUStringList PathSettings::impl_convertOldStyle2Path(const OUString& sOldStylePath) const
1033 : {
1034 0 : OUStringList lList;
1035 0 : sal_Int32 nToken = 0;
1036 0 : do
1037 : {
1038 0 : OUString sToken = sOldStylePath.getToken(0, ';', nToken);
1039 0 : if (!sToken.isEmpty())
1040 0 : lList.push_back(sToken);
1041 : }
1042 0 : while(nToken >= 0);
1043 :
1044 0 : return lList;
1045 : }
1046 :
1047 0 : void PathSettings::impl_purgeKnownPaths(PathSettings::PathInfo& rPath,
1048 : OUStringList& lList)
1049 : {
1050 0 : OUStringList::iterator pIt;
1051 :
1052 : // Erase items in the internal path list from lList.
1053 : // Also erase items in the internal path list from the user path list.
1054 0 : for ( pIt = rPath.lInternalPaths.begin();
1055 0 : pIt != rPath.lInternalPaths.end();
1056 : ++pIt )
1057 : {
1058 0 : const OUString& rItem = *pIt;
1059 0 : OUStringList::iterator pItem = find(lList, rItem);
1060 0 : if (pItem != lList.end())
1061 0 : lList.erase(pItem);
1062 0 : pItem = find(rPath.lUserPaths, rItem);
1063 0 : if (pItem != rPath.lUserPaths.end())
1064 0 : rPath.lUserPaths.erase(pItem);
1065 : }
1066 :
1067 : // Erase itsems not in lList from the user path list.
1068 0 : pIt = rPath.lUserPaths.begin();
1069 0 : while ( pIt != rPath.lUserPaths.end() )
1070 : {
1071 0 : const OUString& rItem = *pIt;
1072 0 : OUStringList::iterator pItem = find(lList, rItem);
1073 0 : if ( pItem == lList.end() )
1074 : {
1075 0 : rPath.lUserPaths.erase(pIt);
1076 0 : pIt = rPath.lUserPaths.begin();
1077 : }
1078 : else
1079 : {
1080 0 : ++pIt;
1081 : }
1082 : }
1083 :
1084 : // Erase items in the user path list from lList.
1085 0 : for ( pIt = rPath.lUserPaths.begin();
1086 0 : pIt != rPath.lUserPaths.end();
1087 : ++pIt )
1088 : {
1089 0 : const OUString& rItem = *pIt;
1090 0 : OUStringList::iterator pItem = find(lList, rItem);
1091 0 : if (pItem != lList.end())
1092 0 : lList.erase(pItem);
1093 : }
1094 :
1095 : // Erase the write path from lList
1096 0 : OUStringList::iterator pItem = find(lList, rPath.sWritePath);
1097 0 : if (pItem != lList.end())
1098 0 : lList.erase(pItem);
1099 0 : }
1100 :
1101 210 : void PathSettings::impl_rebuildPropertyDescriptor()
1102 : {
1103 : // SAFE ->
1104 210 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1105 :
1106 210 : sal_Int32 c = (sal_Int32)m_lPaths.size();
1107 210 : sal_Int32 i = 0;
1108 210 : m_lPropDesc.realloc(c*IDGROUP_COUNT);
1109 :
1110 210 : PathHash::const_iterator pIt;
1111 15750 : for ( pIt = m_lPaths.begin();
1112 10500 : pIt != m_lPaths.end();
1113 : ++pIt )
1114 : {
1115 5040 : const PathSettings::PathInfo& rPath = pIt->second;
1116 5040 : css::beans::Property* pProp = 0;
1117 :
1118 5040 : pProp = &(m_lPropDesc[i]);
1119 5040 : pProp->Name = rPath.sPathName;
1120 5040 : pProp->Handle = i;
1121 5040 : pProp->Type = cppu::UnoType<OUString>::get();
1122 5040 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1123 5040 : if (rPath.bIsReadonly)
1124 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1125 5040 : ++i;
1126 :
1127 5040 : pProp = &(m_lPropDesc[i]);
1128 5040 : pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHS;
1129 5040 : pProp->Handle = i;
1130 5040 : pProp->Type = cppu::UnoType<css::uno::Sequence< OUString >>::get();
1131 : pProp->Attributes = css::beans::PropertyAttribute::BOUND |
1132 5040 : css::beans::PropertyAttribute::READONLY;
1133 5040 : ++i;
1134 :
1135 5040 : pProp = &(m_lPropDesc[i]);
1136 5040 : pProp->Name = rPath.sPathName+POSTFIX_USER_PATHS;
1137 5040 : pProp->Handle = i;
1138 5040 : pProp->Type = cppu::UnoType<css::uno::Sequence< OUString >>::get();
1139 5040 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1140 5040 : if (rPath.bIsReadonly)
1141 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1142 5040 : ++i;
1143 :
1144 5040 : pProp = &(m_lPropDesc[i]);
1145 5040 : pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
1146 5040 : pProp->Handle = i;
1147 5040 : pProp->Type = cppu::UnoType<OUString>::get();
1148 5040 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1149 5040 : if (rPath.bIsReadonly)
1150 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1151 5040 : ++i;
1152 : }
1153 :
1154 210 : delete m_pPropHelp;
1155 210 : m_pPropHelp = new ::cppu::OPropertyArrayHelper(m_lPropDesc, sal_False); // false => not sorted ... must be done inside helper
1156 :
1157 : // <- SAFE
1158 210 : }
1159 :
1160 19932 : css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
1161 : {
1162 19932 : const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
1163 19932 : if (! pPath)
1164 0 : throw css::lang::IllegalArgumentException();
1165 :
1166 19932 : css::uno::Any aVal;
1167 19932 : switch(impl_getPropGroup(nID))
1168 : {
1169 : case IDGROUP_OLDSTYLE :
1170 : {
1171 19590 : OUString sVal = impl_convertPath2OldStyle(*pPath);
1172 19590 : aVal <<= sVal;
1173 : }
1174 19590 : break;
1175 :
1176 : case IDGROUP_INTERNAL_PATHS :
1177 : {
1178 114 : aVal <<= comphelper::containerToSequence(pPath->lInternalPaths);
1179 : }
1180 114 : break;
1181 :
1182 : case IDGROUP_USER_PATHS :
1183 : {
1184 114 : aVal <<= comphelper::containerToSequence(pPath->lUserPaths);
1185 : }
1186 114 : break;
1187 :
1188 : case IDGROUP_WRITE_PATH :
1189 : {
1190 114 : aVal <<= pPath->sWritePath;
1191 : }
1192 114 : break;
1193 : }
1194 :
1195 19932 : return aVal;
1196 : }
1197 :
1198 0 : void PathSettings::impl_setPathValue( sal_Int32 nID ,
1199 : const css::uno::Any& aVal)
1200 : {
1201 0 : PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
1202 0 : if (! pOrgPath)
1203 0 : throw css::container::NoSuchElementException();
1204 :
1205 : // We work on a copied path ... so we can be sure that errors during this operation
1206 : // does not make our internal cache invalid .-)
1207 0 : PathSettings::PathInfo aChangePath(*pOrgPath);
1208 :
1209 0 : switch(impl_getPropGroup(nID))
1210 : {
1211 : case IDGROUP_OLDSTYLE :
1212 : {
1213 0 : OUString sVal;
1214 0 : aVal >>= sVal;
1215 0 : OUStringList lList = impl_convertOldStyle2Path(sVal);
1216 0 : impl_subst(lList, fa_getSubstitution(), false);
1217 0 : impl_purgeKnownPaths(aChangePath, lList);
1218 0 : if (! impl_isValidPath(lList))
1219 0 : throw css::lang::IllegalArgumentException();
1220 :
1221 0 : if (aChangePath.bIsSinglePath)
1222 : {
1223 : SAL_WARN_IF(lList.size()>1, "fwk", "PathSettings::impl_setPathValue(): You try to set more than path value for a defined SINGLE_PATH!");
1224 0 : if ( !lList.empty() )
1225 0 : aChangePath.sWritePath = *(lList.begin());
1226 : else
1227 0 : aChangePath.sWritePath.clear();
1228 : }
1229 : else
1230 : {
1231 0 : OUStringList::const_iterator pIt;
1232 0 : for ( pIt = lList.begin();
1233 0 : pIt != lList.end();
1234 : ++pIt )
1235 : {
1236 0 : aChangePath.lUserPaths.push_back(*pIt);
1237 : }
1238 0 : }
1239 : }
1240 0 : break;
1241 :
1242 : case IDGROUP_INTERNAL_PATHS :
1243 : {
1244 0 : if (aChangePath.bIsSinglePath)
1245 : {
1246 0 : OUStringBuffer sMsg(256);
1247 0 : sMsg.appendAscii("The path '" );
1248 0 : sMsg.append (aChangePath.sPathName);
1249 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.");
1250 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1251 0 : static_cast< ::cppu::OWeakObject* >(this));
1252 : }
1253 :
1254 0 : css::uno::Sequence<OUString> lTmpList;
1255 0 : aVal >>= lTmpList;
1256 0 : OUStringList lList = comphelper::sequenceToContainer<OUStringList>(lTmpList);
1257 0 : if (! impl_isValidPath(lList))
1258 0 : throw css::lang::IllegalArgumentException();
1259 0 : aChangePath.lInternalPaths = lList;
1260 : }
1261 0 : break;
1262 :
1263 : case IDGROUP_USER_PATHS :
1264 : {
1265 0 : if (aChangePath.bIsSinglePath)
1266 : {
1267 0 : OUStringBuffer sMsg(256);
1268 0 : sMsg.appendAscii("The path '" );
1269 0 : sMsg.append (aChangePath.sPathName);
1270 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.");
1271 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1272 0 : static_cast< ::cppu::OWeakObject* >(this));
1273 : }
1274 :
1275 0 : css::uno::Sequence<OUString> lTmpList;
1276 0 : aVal >>= lTmpList;
1277 0 : OUStringList lList = comphelper::sequenceToContainer<OUStringList>(lTmpList);
1278 0 : if (! impl_isValidPath(lList))
1279 0 : throw css::lang::IllegalArgumentException();
1280 0 : aChangePath.lUserPaths = lList;
1281 : }
1282 0 : break;
1283 :
1284 : case IDGROUP_WRITE_PATH :
1285 : {
1286 0 : OUString sVal;
1287 0 : aVal >>= sVal;
1288 0 : if (! impl_isValidPath(sVal))
1289 0 : throw css::lang::IllegalArgumentException();
1290 0 : aChangePath.sWritePath = sVal;
1291 : }
1292 0 : break;
1293 : }
1294 :
1295 : // TODO check if path has at least one path value set
1296 : // At least it depends from the feature using this path, if an empty path list is allowed.
1297 :
1298 : // first we should try to store the changed (copied!) path ...
1299 : // In case an error occurs on saving time an exception is thrown ...
1300 : // If no exception occurs we can update our internal cache (means
1301 : // we can overwrite pOrgPath !
1302 0 : impl_storePath(aChangePath);
1303 0 : pOrgPath->takeOver(aChangePath);
1304 0 : }
1305 :
1306 0 : bool PathSettings::impl_isValidPath(const OUStringList& lPath) const
1307 : {
1308 0 : OUStringList::const_iterator pIt;
1309 0 : for ( pIt = lPath.begin();
1310 0 : pIt != lPath.end();
1311 : ++pIt )
1312 : {
1313 0 : const OUString& rVal = *pIt;
1314 0 : if (! impl_isValidPath(rVal))
1315 0 : return false;
1316 : }
1317 :
1318 0 : return true;
1319 : }
1320 :
1321 0 : bool PathSettings::impl_isValidPath(const OUString& sPath) const
1322 : {
1323 : // allow empty path to reset a path.
1324 : // idea by LLA to support empty paths
1325 : // if (sPath.getLength() == 0)
1326 : // {
1327 : // return sal_True;
1328 : // }
1329 :
1330 0 : return (! INetURLObject(sPath).HasError());
1331 : }
1332 :
1333 19932 : OUString impl_extractBaseFromPropName(const OUString& sPropName)
1334 : {
1335 19932 : sal_Int32 i = sPropName.indexOf(POSTFIX_INTERNAL_PATHS);
1336 19932 : if (i > -1)
1337 114 : return sPropName.copy(0, i);
1338 19818 : i = sPropName.indexOf(POSTFIX_USER_PATHS);
1339 19818 : if (i > -1)
1340 114 : return sPropName.copy(0, i);
1341 19704 : i = sPropName.indexOf(POSTFIX_WRITE_PATH);
1342 19704 : if (i > -1)
1343 114 : return sPropName.copy(0, i);
1344 :
1345 19590 : return sPropName;
1346 : }
1347 :
1348 0 : PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
1349 : {
1350 : // SAFE ->
1351 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1352 :
1353 0 : if (nHandle > (m_lPropDesc.getLength()-1))
1354 0 : return 0;
1355 :
1356 0 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1357 0 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1358 0 : PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
1359 :
1360 0 : if (rPath != m_lPaths.end())
1361 0 : return &(rPath->second);
1362 :
1363 0 : return 0;
1364 : // <- SAFE
1365 : }
1366 :
1367 19932 : const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
1368 : {
1369 : // SAFE ->
1370 19932 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1371 :
1372 19932 : if (nHandle > (m_lPropDesc.getLength()-1))
1373 0 : return 0;
1374 :
1375 19932 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1376 39864 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1377 19932 : PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
1378 :
1379 19932 : if (rPath != m_lPaths.end())
1380 19932 : return &(rPath->second);
1381 :
1382 19932 : return 0;
1383 : // <- SAFE
1384 : }
1385 :
1386 0 : sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
1387 : css::uno::Any& aOldValue ,
1388 : sal_Int32 nHandle ,
1389 : const css::uno::Any& aValue )
1390 : throw(css::lang::IllegalArgumentException)
1391 : {
1392 : // throws NoSuchElementException !
1393 0 : css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
1394 :
1395 : return PropHelper::willPropertyBeChanged(
1396 : aCurrentVal,
1397 : aValue,
1398 : aOldValue,
1399 0 : aConvertedValue);
1400 : }
1401 :
1402 0 : void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
1403 : const css::uno::Any& aValue )
1404 : throw(css::uno::Exception, std::exception)
1405 : {
1406 : // throws NoSuchElement- and IllegalArgumentException !
1407 0 : impl_setPathValue(nHandle, aValue);
1408 0 : }
1409 :
1410 19932 : void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
1411 : sal_Int32 nHandle) const
1412 : {
1413 19932 : aValue = impl_getPathValue(nHandle);
1414 19932 : }
1415 :
1416 22817 : ::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
1417 : {
1418 22817 : return *m_pPropHelp;
1419 : }
1420 :
1421 210 : css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
1422 : throw(css::uno::RuntimeException, std::exception)
1423 : {
1424 : return css::uno::Reference< css::beans::XPropertySetInfo >(
1425 210 : ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()));
1426 : }
1427 :
1428 10080 : css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
1429 : {
1430 10080 : css::uno::Reference< css::util::XStringSubstitution > xSubst;
1431 : { // SAFE ->
1432 10080 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1433 10080 : xSubst = m_xSubstitution;
1434 : }
1435 :
1436 10080 : if (! xSubst.is())
1437 : {
1438 : // create the needed substitution service.
1439 : // We must replace all used variables inside readed path values.
1440 : // In case we can't do so ... the whole office can't work really.
1441 : // That's why it seems to be OK to throw a RuntimeException then.
1442 210 : xSubst = css::util::PathSubstitution::create(m_xContext);
1443 :
1444 : { // SAFE ->
1445 210 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1446 210 : m_xSubstitution = xSubst;
1447 : }
1448 : }
1449 :
1450 10080 : return xSubst;
1451 : }
1452 :
1453 5040 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
1454 : {
1455 5040 : const OUString CFG_NODE_OLD("org.openoffice.Office.Common/Path/Current");
1456 :
1457 5040 : css::uno::Reference< css::container::XNameAccess > xCfg;
1458 : { // SAFE ->
1459 5040 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1460 5040 : xCfg = m_xCfgOld;
1461 : } // <- SAFE
1462 :
1463 5040 : if (! xCfg.is())
1464 : {
1465 420 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1466 : ::comphelper::ConfigurationHelper::openConfig(
1467 : m_xContext,
1468 : CFG_NODE_OLD,
1469 : ::comphelper::ConfigurationHelper::E_STANDARD), // not readonly! Sometimes we need write access there !!!
1470 210 : css::uno::UNO_QUERY_THROW);
1471 :
1472 : { // SAFE ->
1473 210 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1474 210 : m_xCfgOld = xCfg;
1475 : }
1476 : }
1477 :
1478 5040 : return xCfg;
1479 : }
1480 :
1481 5250 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
1482 : {
1483 5250 : const OUString CFG_NODE_NEW("org.openoffice.Office.Paths/Paths");
1484 :
1485 5250 : css::uno::Reference< css::container::XNameAccess > xCfg;
1486 : { // SAFE ->
1487 5250 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1488 5250 : xCfg = m_xCfgNew;
1489 : } // <- SAFE
1490 :
1491 5250 : if (! xCfg.is())
1492 : {
1493 420 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1494 : ::comphelper::ConfigurationHelper::openConfig(
1495 : m_xContext,
1496 : CFG_NODE_NEW,
1497 : ::comphelper::ConfigurationHelper::E_STANDARD),
1498 210 : css::uno::UNO_QUERY_THROW);
1499 :
1500 : { // SAFE ->
1501 210 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1502 210 : m_xCfgNew = xCfg;
1503 210 : m_xCfgNewListener = new WeakChangesListener(this);
1504 : }
1505 :
1506 210 : css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
1507 210 : xBroadcaster->addChangesListener(m_xCfgNewListener);
1508 : }
1509 :
1510 5250 : return xCfg;
1511 : }
1512 :
1513 210 : struct Instance {
1514 210 : explicit Instance(
1515 : css::uno::Reference<css::uno::XComponentContext> const & context):
1516 : instance(
1517 210 : static_cast<cppu::OWeakObject *>(new PathSettings(context)))
1518 : {
1519 : // fill cache
1520 : static_cast<PathSettings *>(static_cast<cppu::OWeakObject *>
1521 210 : (instance.get()))->impl_readAll();
1522 210 : }
1523 :
1524 : css::uno::Reference<css::uno::XInterface> instance;
1525 : };
1526 :
1527 : struct Singleton:
1528 : public rtl::StaticWithArg<
1529 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
1530 : {};
1531 :
1532 : }
1533 :
1534 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1535 555 : com_sun_star_comp_framework_PathSettings_get_implementation(
1536 : css::uno::XComponentContext *context,
1537 : css::uno::Sequence<css::uno::Any> const &)
1538 : {
1539 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
1540 555 : Singleton::get(context).instance.get()));
1541 : }
1542 :
1543 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|