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 33879 : sal_Int32 impl_getPropGroup(sal_Int32 nID)
74 : {
75 33879 : 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 36744 : struct PathInfo
93 : {
94 : public:
95 :
96 22104 : PathInfo()
97 : : sPathName ()
98 : , lInternalPaths()
99 : , lUserPaths ()
100 : , sWritePath ()
101 : , bIsSinglePath (false)
102 22104 : , bIsReadonly (false)
103 22104 : {}
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 14206 : virtual void SAL_CALL acquire() throw () SAL_OVERRIDE
211 14206 : { OWeakObject::acquire(); }
212 14198 : virtual void SAL_CALL release() throw () SAL_OVERRIDE
213 14198 : { 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 2430 : virtual OUString SAL_CALL getBasePathShareLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
325 2430 : { 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 158 : virtual OUString SAL_CALL getBasePathUserLayer() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
329 158 : { 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 1198 : 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 1198 : { 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 307 : 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 307 : , m_bIgnoreEvents(false)
464 : {
465 307 : }
466 :
467 909 : PathSettings::~PathSettings()
468 : {
469 303 : disposing();
470 606 : }
471 :
472 606 : void SAL_CALL PathSettings::disposing()
473 : {
474 606 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
475 :
476 : css::uno::Reference< css::util::XChangesNotifier >
477 1212 : xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY);
478 606 : if (xBroadcaster.is())
479 303 : xBroadcaster->removeChangesListener(m_xCfgNewListener);
480 :
481 606 : m_xSubstitution.clear();
482 606 : m_xCfgOld.clear();
483 606 : m_xCfgNew.clear();
484 606 : m_xCfgNewListener.clear();
485 :
486 606 : delete m_pPropHelp;
487 1212 : m_pPropHelp = 0;
488 606 : }
489 :
490 4786 : css::uno::Any SAL_CALL PathSettings::queryInterface( const css::uno::Type& _rType )
491 : throw(css::uno::RuntimeException, std::exception)
492 : {
493 4786 : css::uno::Any aRet = PathSettings_BASE::queryInterface( _rType );
494 4786 : if ( !aRet.hasValue() )
495 307 : aRet = ::cppu::OPropertySetHelper::queryInterface( _rType );
496 4786 : 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 2588 : OUString PathSettings::getStringProperty(const OUString& p1)
548 : throw(css::uno::RuntimeException)
549 : {
550 2588 : css::uno::Any a = ::cppu::OPropertySetHelper::getPropertyValue(p1);
551 2588 : OUString s;
552 2588 : a >>= s;
553 2588 : 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 307 : void PathSettings::impl_readAll()
563 : {
564 : try
565 : {
566 : // TODO think about me
567 307 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
568 614 : css::uno::Sequence< OUString > lPaths = xCfg->getElementNames();
569 :
570 307 : sal_Int32 c = lPaths.getLength();
571 7675 : for (sal_Int32 i = 0; i < c; ++i)
572 : {
573 7368 : const OUString& sPath = lPaths[i];
574 7368 : impl_updatePath(sPath, false);
575 307 : }
576 : }
577 0 : catch(const css::uno::RuntimeException& )
578 : {
579 : }
580 :
581 307 : impl_rebuildPropertyDescriptor();
582 307 : }
583 :
584 : // NO substitution here ! It's done outside ...
585 7368 : OUStringList PathSettings::impl_readOldFormat(const OUString& sPath)
586 : {
587 7368 : css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
588 7368 : OUStringList aPathVal;
589 :
590 7368 : if( xCfg->hasByName(sPath) )
591 : {
592 7061 : css::uno::Any aVal( xCfg->getByName(sPath) );
593 :
594 14122 : OUString sStringVal;
595 14122 : css::uno::Sequence< OUString > lStringListVal;
596 :
597 7061 : if (aVal >>= sStringVal)
598 : {
599 4912 : aPathVal.push_back(sStringVal);
600 : }
601 2149 : else if (aVal >>= lStringListVal)
602 : {
603 2149 : aPathVal << lStringListVal;
604 7061 : }
605 : }
606 :
607 7368 : return aPathVal;
608 : }
609 :
610 : // NO substitution here ! It's done outside ...
611 7368 : PathSettings::PathInfo PathSettings::impl_readNewFormat(const OUString& sPath)
612 : {
613 7368 : const OUString CFGPROP_INTERNALPATHS("InternalPaths");
614 14736 : const OUString CFGPROP_ISSINGLEPATH("IsSinglePath");
615 :
616 14736 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
617 :
618 : // get access to the "queried" path
619 14736 : css::uno::Reference< css::container::XNameAccess > xPath;
620 7368 : xCfg->getByName(sPath) >>= xPath;
621 :
622 7368 : PathSettings::PathInfo aPathVal;
623 :
624 : // read internal path list
625 14736 : css::uno::Reference< css::container::XNameAccess > xIPath;
626 7368 : xPath->getByName(CFGPROP_INTERNALPATHS) >>= xIPath;
627 7368 : aPathVal.lInternalPaths << xIPath->getElementNames();
628 :
629 : // read user defined path list
630 7368 : aPathVal.lUserPaths << xPath->getByName(CFGPROP_USERPATHS);
631 :
632 : // read the writeable path
633 7368 : 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 7368 : OUStringList::iterator aI = aPathVal.lUserPaths.find(aPathVal.sWritePath);
638 7368 : if (aI != aPathVal.lUserPaths.end())
639 307 : aPathVal.lUserPaths.erase(aI);
640 :
641 : // read state props
642 7368 : xPath->getByName(CFGPROP_ISSINGLEPATH) >>= aPathVal.bIsSinglePath;
643 :
644 : // analyze finalized/mandatory states
645 7368 : aPathVal.bIsReadonly = false;
646 14736 : css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
647 7368 : if (xInfo.is())
648 : {
649 7368 : css::beans::Property aInfo = xInfo->getAsProperty();
650 7368 : 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 7368 : aPathVal.bIsReadonly = bFinalized;
656 : }
657 :
658 14736 : 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 can't 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 than 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 7368 : void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
707 : const OUStringList& lOld )
708 : {
709 7368 : OUStringList::const_iterator pIt;
710 48813 : for ( pIt = lOld.begin();
711 32542 : pIt != lOld.end();
712 : ++pIt )
713 : {
714 8903 : const OUString& sOld = *pIt;
715 :
716 8903 : if (rPath.bIsSinglePath)
717 : {
718 : SAL_WARN_IF(lOld.size()>1, "fwk", "PathSettings::impl_mergeOldUserPaths(): Single path has more than one path value inside old configuration (Common.xcu)!");
719 1535 : if (! rPath.sWritePath.equals(sOld))
720 0 : rPath.sWritePath = sOld;
721 : }
722 : else
723 : {
724 14736 : if (
725 44502 : ( rPath.lInternalPaths.findConst(sOld) == rPath.lInternalPaths.end()) &&
726 44502 : ( rPath.lUserPaths.findConst(sOld) == rPath.lUserPaths.end() ) &&
727 2554 : (! rPath.sWritePath.equals(sOld) )
728 : )
729 98 : rPath.lUserPaths.push_back(sOld);
730 : }
731 : }
732 7368 : }
733 :
734 7368 : PathSettings::EChangeOp PathSettings::impl_updatePath(const OUString& sPath ,
735 : bool bNotifyListener)
736 : {
737 : // SAFE ->
738 7368 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
739 :
740 7368 : PathSettings::PathInfo* pPathOld = 0;
741 7368 : PathSettings::PathInfo* pPathNew = 0;
742 7368 : PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
743 14736 : PathSettings::PathInfo aPath;
744 :
745 : try
746 : {
747 7368 : aPath = impl_readNewFormat(sPath);
748 7368 : 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 7368 : 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 7368 : 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 7368 : impl_subst(lOldVals, fa_getSubstitution(), false);
772 7368 : 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 can't 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 7368 : PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
784 7368 : if (eOp == PathSettings::E_UNDEFINED)
785 : {
786 7368 : if (pPath != m_lPaths.end())
787 0 : eOp = PathSettings::E_CHANGED;
788 : else
789 7368 : eOp = PathSettings::E_ADDED;
790 : }
791 :
792 7368 : switch(eOp)
793 : {
794 : case PathSettings::E_ADDED :
795 : {
796 7368 : if (bNotifyListener)
797 : {
798 0 : pPathOld = 0;
799 0 : pPathNew = &aPath;
800 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
801 : }
802 7368 : m_lPaths[sPath] = aPath;
803 : }
804 7368 : 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 14736 : 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 can't 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 22104 : void PathSettings::impl_subst( OUStringList& lVals ,
961 : const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
962 : bool bReSubst)
963 : {
964 22104 : OUStringList::iterator pIt;
965 :
966 110520 : for ( pIt = lVals.begin();
967 73680 : pIt != lVals.end();
968 : ++pIt )
969 : {
970 14736 : const OUString& sOld = *pIt;
971 14736 : OUString sNew;
972 14736 : if (bReSubst)
973 0 : sNew = xSubst->reSubstituteVariables(sOld);
974 : else
975 14736 : sNew = xSubst->substituteVariables(sOld, sal_False);
976 :
977 14736 : *pIt = sNew;
978 14736 : }
979 22104 : }
980 :
981 7368 : void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
982 : bool bReSubst)
983 : {
984 7368 : css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
985 :
986 7368 : impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
987 7368 : impl_subst(aPath.lUserPaths , xSubst, bReSubst);
988 7368 : if (bReSubst)
989 0 : aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
990 : else
991 7368 : aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, sal_False);
992 7368 : }
993 :
994 33403 : OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
995 : {
996 33403 : OUStringList::const_iterator pIt;
997 33403 : OUStringList lTemp;
998 33403 : lTemp.reserve(rPath.lInternalPaths.size() + rPath.lUserPaths.size() + 1);
999 :
1000 151740 : for ( pIt = rPath.lInternalPaths.begin();
1001 101160 : pIt != rPath.lInternalPaths.end();
1002 : ++pIt )
1003 : {
1004 17177 : lTemp.push_back(*pIt);
1005 : }
1006 100473 : for ( pIt = rPath.lUserPaths.begin();
1007 66982 : pIt != rPath.lUserPaths.end();
1008 : ++pIt )
1009 : {
1010 88 : lTemp.push_back(*pIt);
1011 : }
1012 :
1013 33403 : if (!rPath.sWritePath.isEmpty())
1014 30702 : lTemp.push_back(rPath.sWritePath);
1015 :
1016 66806 : OUStringBuffer sPathVal(256);
1017 196143 : for ( pIt = lTemp.begin();
1018 162740 : pIt != lTemp.end();
1019 : )
1020 : {
1021 47967 : sPathVal.append(*pIt);
1022 47967 : ++pIt;
1023 47967 : if (pIt != lTemp.end())
1024 14564 : sPathVal.appendAscii(";");
1025 : }
1026 :
1027 66806 : 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(PathSettings::PathInfo& rPath,
1046 : OUStringList& lList)
1047 : {
1048 0 : OUStringList::iterator pIt;
1049 :
1050 : // Erase items in the internal path list from lList.
1051 : // Also erase items in the internal path list from the user path list.
1052 0 : for ( pIt = rPath.lInternalPaths.begin();
1053 0 : pIt != rPath.lInternalPaths.end();
1054 : ++pIt )
1055 : {
1056 0 : const OUString& rItem = *pIt;
1057 0 : OUStringList::iterator pItem = lList.find(rItem);
1058 0 : if (pItem != lList.end())
1059 0 : lList.erase(pItem);
1060 0 : pItem = rPath.lUserPaths.find(rItem);
1061 0 : if (pItem != rPath.lUserPaths.end())
1062 0 : rPath.lUserPaths.erase(pItem);
1063 : }
1064 :
1065 : // Erase itsems not in lList from the user path list.
1066 0 : pIt = rPath.lUserPaths.begin();
1067 0 : while ( pIt != rPath.lUserPaths.end() )
1068 : {
1069 0 : const OUString& rItem = *pIt;
1070 0 : OUStringList::iterator pItem = lList.find(rItem);
1071 0 : if ( pItem == lList.end() )
1072 : {
1073 0 : rPath.lUserPaths.erase(pIt);
1074 0 : pIt = rPath.lUserPaths.begin();
1075 : }
1076 : else
1077 : {
1078 0 : ++pIt;
1079 : }
1080 : }
1081 :
1082 : // Erase items in the user path list from lList.
1083 0 : for ( pIt = rPath.lUserPaths.begin();
1084 0 : pIt != rPath.lUserPaths.end();
1085 : ++pIt )
1086 : {
1087 0 : const OUString& rItem = *pIt;
1088 0 : OUStringList::iterator pItem = lList.find(rItem);
1089 0 : if (pItem != lList.end())
1090 0 : lList.erase(pItem);
1091 : }
1092 :
1093 : // Erase the write path from lList
1094 0 : OUStringList::iterator pItem = lList.find(rPath.sWritePath);
1095 0 : if (pItem != lList.end())
1096 0 : lList.erase(pItem);
1097 0 : }
1098 :
1099 307 : void PathSettings::impl_rebuildPropertyDescriptor()
1100 : {
1101 : // SAFE ->
1102 307 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1103 :
1104 307 : sal_Int32 c = (sal_Int32)m_lPaths.size();
1105 307 : sal_Int32 i = 0;
1106 307 : m_lPropDesc.realloc(c*IDGROUP_COUNT);
1107 :
1108 307 : PathHash::const_iterator pIt;
1109 23025 : for ( pIt = m_lPaths.begin();
1110 15350 : pIt != m_lPaths.end();
1111 : ++pIt )
1112 : {
1113 7368 : const PathSettings::PathInfo& rPath = pIt->second;
1114 7368 : css::beans::Property* pProp = 0;
1115 :
1116 7368 : pProp = &(m_lPropDesc[i]);
1117 7368 : pProp->Name = rPath.sPathName;
1118 7368 : pProp->Handle = i;
1119 7368 : pProp->Type = cppu::UnoType<OUString>::get();
1120 7368 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1121 7368 : if (rPath.bIsReadonly)
1122 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1123 7368 : ++i;
1124 :
1125 7368 : pProp = &(m_lPropDesc[i]);
1126 7368 : pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHS;
1127 7368 : pProp->Handle = i;
1128 7368 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
1129 : pProp->Attributes = css::beans::PropertyAttribute::BOUND |
1130 7368 : css::beans::PropertyAttribute::READONLY;
1131 7368 : ++i;
1132 :
1133 7368 : pProp = &(m_lPropDesc[i]);
1134 7368 : pProp->Name = rPath.sPathName+POSTFIX_USER_PATHS;
1135 7368 : pProp->Handle = i;
1136 7368 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
1137 7368 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1138 7368 : if (rPath.bIsReadonly)
1139 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1140 7368 : ++i;
1141 :
1142 7368 : pProp = &(m_lPropDesc[i]);
1143 7368 : pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
1144 7368 : pProp->Handle = i;
1145 7368 : pProp->Type = cppu::UnoType<OUString>::get();
1146 7368 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
1147 7368 : if (rPath.bIsReadonly)
1148 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
1149 7368 : ++i;
1150 : }
1151 :
1152 307 : delete m_pPropHelp;
1153 307 : m_pPropHelp = new ::cppu::OPropertyArrayHelper(m_lPropDesc, sal_False); // false => not sorted ... must be done inside helper
1154 :
1155 : // <- SAFE
1156 307 : }
1157 :
1158 33879 : css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
1159 : {
1160 33879 : const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
1161 33879 : if (! pPath)
1162 0 : throw css::lang::IllegalArgumentException();
1163 :
1164 33879 : css::uno::Any aVal;
1165 33879 : switch(impl_getPropGroup(nID))
1166 : {
1167 : case IDGROUP_OLDSTYLE :
1168 : {
1169 33403 : OUString sVal = impl_convertPath2OldStyle(*pPath);
1170 33403 : aVal <<= sVal;
1171 : }
1172 33403 : break;
1173 :
1174 : case IDGROUP_INTERNAL_PATHS :
1175 : {
1176 160 : aVal <<= pPath->lInternalPaths.getAsConstList();
1177 : }
1178 160 : break;
1179 :
1180 : case IDGROUP_USER_PATHS :
1181 : {
1182 158 : aVal <<= pPath->lUserPaths.getAsConstList();
1183 : }
1184 158 : break;
1185 :
1186 : case IDGROUP_WRITE_PATH :
1187 : {
1188 158 : aVal <<= pPath->sWritePath;
1189 : }
1190 158 : break;
1191 : }
1192 :
1193 33879 : return aVal;
1194 : }
1195 :
1196 0 : void PathSettings::impl_setPathValue( sal_Int32 nID ,
1197 : const css::uno::Any& aVal)
1198 : {
1199 0 : PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
1200 0 : if (! pOrgPath)
1201 0 : throw css::container::NoSuchElementException();
1202 :
1203 : // We work on a copied path ... so we can be sure that errors during this operation
1204 : // does not make our internal cache invalid .-)
1205 0 : PathSettings::PathInfo aChangePath(*pOrgPath);
1206 :
1207 0 : switch(impl_getPropGroup(nID))
1208 : {
1209 : case IDGROUP_OLDSTYLE :
1210 : {
1211 0 : OUString sVal;
1212 0 : aVal >>= sVal;
1213 0 : OUStringList lList = impl_convertOldStyle2Path(sVal);
1214 0 : impl_subst(lList, fa_getSubstitution(), false);
1215 0 : impl_purgeKnownPaths(aChangePath, lList);
1216 0 : if (! impl_isValidPath(lList))
1217 0 : throw css::lang::IllegalArgumentException();
1218 :
1219 0 : if (aChangePath.bIsSinglePath)
1220 : {
1221 : SAL_WARN_IF(lList.size()>1, "fwk", "PathSettings::impl_setPathValue(): You try to set more than path value for a defined SINGLE_PATH!");
1222 0 : if ( !lList.empty() )
1223 0 : aChangePath.sWritePath = *(lList.begin());
1224 : else
1225 0 : aChangePath.sWritePath = OUString();
1226 : }
1227 : else
1228 : {
1229 0 : OUStringList::const_iterator pIt;
1230 0 : for ( pIt = lList.begin();
1231 0 : pIt != lList.end();
1232 : ++pIt )
1233 : {
1234 0 : aChangePath.lUserPaths.push_back(*pIt);
1235 : }
1236 0 : }
1237 : }
1238 0 : break;
1239 :
1240 : case IDGROUP_INTERNAL_PATHS :
1241 : {
1242 0 : if (aChangePath.bIsSinglePath)
1243 : {
1244 0 : OUStringBuffer sMsg(256);
1245 0 : sMsg.appendAscii("The path '" );
1246 0 : sMsg.append (aChangePath.sPathName);
1247 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.");
1248 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1249 0 : static_cast< ::cppu::OWeakObject* >(this));
1250 : }
1251 :
1252 0 : OUStringList lList;
1253 0 : lList << aVal;
1254 0 : if (! impl_isValidPath(lList))
1255 0 : throw css::lang::IllegalArgumentException();
1256 0 : aChangePath.lInternalPaths = lList;
1257 : }
1258 0 : break;
1259 :
1260 : case IDGROUP_USER_PATHS :
1261 : {
1262 0 : if (aChangePath.bIsSinglePath)
1263 : {
1264 0 : OUStringBuffer sMsg(256);
1265 0 : sMsg.appendAscii("The path '" );
1266 0 : sMsg.append (aChangePath.sPathName);
1267 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths can't be set.");
1268 : throw css::uno::Exception(sMsg.makeStringAndClear(),
1269 0 : static_cast< ::cppu::OWeakObject* >(this));
1270 : }
1271 :
1272 0 : OUStringList lList;
1273 0 : lList << aVal;
1274 0 : if (! impl_isValidPath(lList))
1275 0 : throw css::lang::IllegalArgumentException();
1276 0 : aChangePath.lUserPaths = lList;
1277 : }
1278 0 : break;
1279 :
1280 : case IDGROUP_WRITE_PATH :
1281 : {
1282 0 : OUString sVal;
1283 0 : aVal >>= sVal;
1284 0 : if (! impl_isValidPath(sVal))
1285 0 : throw css::lang::IllegalArgumentException();
1286 0 : aChangePath.sWritePath = sVal;
1287 : }
1288 0 : break;
1289 : }
1290 :
1291 : // TODO check if path has at least one path value set
1292 : // At least it depends from the feature using this path, if an empty path list is allowed.
1293 :
1294 : // first we should try to store the changed (copied!) path ...
1295 : // In case an error occurs on saving time an exception is thrown ...
1296 : // If no exception occurs we can update our internal cache (means
1297 : // we can overwrite pOrgPath !
1298 0 : impl_storePath(aChangePath);
1299 0 : pOrgPath->takeOver(aChangePath);
1300 0 : }
1301 :
1302 0 : bool PathSettings::impl_isValidPath(const OUStringList& lPath) const
1303 : {
1304 0 : OUStringList::const_iterator pIt;
1305 0 : for ( pIt = lPath.begin();
1306 0 : pIt != lPath.end();
1307 : ++pIt )
1308 : {
1309 0 : const OUString& rVal = *pIt;
1310 0 : if (! impl_isValidPath(rVal))
1311 0 : return false;
1312 : }
1313 :
1314 0 : return true;
1315 : }
1316 :
1317 0 : bool PathSettings::impl_isValidPath(const OUString& sPath) const
1318 : {
1319 : // allow empty path to reset a path.
1320 : // idea by LLA to support empty paths
1321 : // if (sPath.getLength() == 0)
1322 : // {
1323 : // return sal_True;
1324 : // }
1325 :
1326 0 : return (! INetURLObject(sPath).HasError());
1327 : }
1328 :
1329 33879 : OUString impl_extractBaseFromPropName(const OUString& sPropName)
1330 : {
1331 33879 : sal_Int32 i = sPropName.indexOf(POSTFIX_INTERNAL_PATHS);
1332 33879 : if (i > -1)
1333 160 : return sPropName.copy(0, i);
1334 33719 : i = sPropName.indexOf(POSTFIX_USER_PATHS);
1335 33719 : if (i > -1)
1336 158 : return sPropName.copy(0, i);
1337 33561 : i = sPropName.indexOf(POSTFIX_WRITE_PATH);
1338 33561 : if (i > -1)
1339 158 : return sPropName.copy(0, i);
1340 :
1341 33403 : return sPropName;
1342 : }
1343 :
1344 0 : PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
1345 : {
1346 : // SAFE ->
1347 0 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1348 :
1349 0 : if (nHandle > (m_lPropDesc.getLength()-1))
1350 0 : return 0;
1351 :
1352 0 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1353 0 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1354 0 : PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
1355 :
1356 0 : if (rPath != m_lPaths.end())
1357 0 : return &(rPath->second);
1358 :
1359 0 : return 0;
1360 : // <- SAFE
1361 : }
1362 :
1363 33879 : const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
1364 : {
1365 : // SAFE ->
1366 33879 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1367 :
1368 33879 : if (nHandle > (m_lPropDesc.getLength()-1))
1369 0 : return 0;
1370 :
1371 33879 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1372 67758 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1373 33879 : PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
1374 :
1375 33879 : if (rPath != m_lPaths.end())
1376 33879 : return &(rPath->second);
1377 :
1378 33879 : return 0;
1379 : // <- SAFE
1380 : }
1381 :
1382 0 : sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
1383 : css::uno::Any& aOldValue ,
1384 : sal_Int32 nHandle ,
1385 : const css::uno::Any& aValue )
1386 : throw(css::lang::IllegalArgumentException)
1387 : {
1388 : // throws NoSuchElementException !
1389 0 : css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
1390 :
1391 : return PropHelper::willPropertyBeChanged(
1392 : aCurrentVal,
1393 : aValue,
1394 : aOldValue,
1395 0 : aConvertedValue);
1396 : }
1397 :
1398 0 : void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
1399 : const css::uno::Any& aValue )
1400 : throw(css::uno::Exception, std::exception)
1401 : {
1402 : // throws NoSuchElement- and IllegalArgumentException !
1403 0 : impl_setPathValue(nHandle, aValue);
1404 0 : }
1405 :
1406 33879 : void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
1407 : sal_Int32 nHandle) const
1408 : {
1409 33879 : aValue = impl_getPathValue(nHandle);
1410 33879 : }
1411 :
1412 37972 : ::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
1413 : {
1414 37972 : return *m_pPropHelp;
1415 : }
1416 :
1417 307 : css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
1418 : throw(css::uno::RuntimeException, std::exception)
1419 : {
1420 : return css::uno::Reference< css::beans::XPropertySetInfo >(
1421 307 : ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()));
1422 : }
1423 :
1424 14736 : css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
1425 : {
1426 14736 : css::uno::Reference< css::util::XStringSubstitution > xSubst;
1427 : { // SAFE ->
1428 14736 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1429 14736 : xSubst = m_xSubstitution;
1430 : }
1431 :
1432 14736 : if (! xSubst.is())
1433 : {
1434 : // create the needed substitution service.
1435 : // We must replace all used variables inside readed path values.
1436 : // In case we can't do so ... the whole office can't work really.
1437 : // That's why it seems to be OK to throw a RuntimeException then.
1438 307 : xSubst = css::util::PathSubstitution::create(m_xContext);
1439 :
1440 : { // SAFE ->
1441 307 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1442 307 : m_xSubstitution = xSubst;
1443 : }
1444 : }
1445 :
1446 14736 : return xSubst;
1447 : }
1448 :
1449 7368 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
1450 : {
1451 7368 : const OUString CFG_NODE_OLD("org.openoffice.Office.Common/Path/Current");
1452 :
1453 7368 : css::uno::Reference< css::container::XNameAccess > xCfg;
1454 : { // SAFE ->
1455 7368 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1456 7368 : xCfg = m_xCfgOld;
1457 : } // <- SAFE
1458 :
1459 7368 : if (! xCfg.is())
1460 : {
1461 614 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1462 : ::comphelper::ConfigurationHelper::openConfig(
1463 : m_xContext,
1464 : CFG_NODE_OLD,
1465 : ::comphelper::ConfigurationHelper::E_STANDARD), // not readonly! Sometimes we need write access there !!!
1466 307 : css::uno::UNO_QUERY_THROW);
1467 :
1468 : { // SAFE ->
1469 307 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1470 307 : m_xCfgOld = xCfg;
1471 : }
1472 : }
1473 :
1474 7368 : return xCfg;
1475 : }
1476 :
1477 7675 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
1478 : {
1479 7675 : const OUString CFG_NODE_NEW("org.openoffice.Office.Paths/Paths");
1480 :
1481 7675 : css::uno::Reference< css::container::XNameAccess > xCfg;
1482 : { // SAFE ->
1483 7675 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1484 7675 : xCfg = m_xCfgNew;
1485 : } // <- SAFE
1486 :
1487 7675 : if (! xCfg.is())
1488 : {
1489 614 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1490 : ::comphelper::ConfigurationHelper::openConfig(
1491 : m_xContext,
1492 : CFG_NODE_NEW,
1493 : ::comphelper::ConfigurationHelper::E_STANDARD),
1494 307 : css::uno::UNO_QUERY_THROW);
1495 :
1496 : { // SAFE ->
1497 307 : osl::MutexGuard g(cppu::WeakComponentImplHelperBase::rBHelper.rMutex);
1498 307 : m_xCfgNew = xCfg;
1499 307 : m_xCfgNewListener = new WeakChangesListener(this);
1500 : }
1501 :
1502 307 : css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
1503 307 : xBroadcaster->addChangesListener(m_xCfgNewListener);
1504 : }
1505 :
1506 7675 : return xCfg;
1507 : }
1508 :
1509 307 : struct Instance {
1510 307 : explicit Instance(
1511 : css::uno::Reference<css::uno::XComponentContext> const & context):
1512 : instance(
1513 307 : static_cast<cppu::OWeakObject *>(new PathSettings(context)))
1514 : {
1515 : // fill cache
1516 : static_cast<PathSettings *>(static_cast<cppu::OWeakObject *>
1517 307 : (instance.get()))->impl_readAll();
1518 307 : }
1519 :
1520 : css::uno::Reference<css::uno::XInterface> instance;
1521 : };
1522 :
1523 : struct Singleton:
1524 : public rtl::StaticWithArg<
1525 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
1526 : {};
1527 :
1528 : }
1529 :
1530 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1531 1021 : com_sun_star_comp_framework_PathSettings_get_implementation(
1532 : css::uno::XComponentContext *context,
1533 : css::uno::Sequence<css::uno::Any> const &)
1534 : {
1535 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
1536 1021 : Singleton::get(context).instance.get()));
1537 : }
1538 :
1539 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|