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 : /** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble
21 : with solaris headers ...
22 : */
23 : #include <vector>
24 : #include <services/pathsettings.hxx>
25 : #include <threadhelp/readguard.hxx>
26 : #include <threadhelp/writeguard.hxx>
27 : #include <services.h>
28 :
29 : #include "helper/mischelper.hxx"
30 :
31 : #include <com/sun/star/beans/Property.hpp>
32 : #include <com/sun/star/beans/XProperty.hpp>
33 : #include <com/sun/star/beans/PropertyAttribute.hpp>
34 : #include <com/sun/star/container/XContainer.hpp>
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 : #include <com/sun/star/util/XChangesNotifier.hpp>
37 : #include <com/sun/star/util/PathSubstitution.hpp>
38 :
39 : #include <tools/urlobj.hxx>
40 : #include <rtl/ustrbuf.hxx>
41 :
42 : #include <comphelper/configurationhelper.hxx>
43 : #include <comphelper/processfactory.hxx>
44 : #include <unotools/configpaths.hxx>
45 :
46 : #include <fwkdllapi.h>
47 :
48 :
49 : #define CFGPROP_USERPATHS OUString("UserPaths")
50 : #define CFGPROP_WRITEPATH OUString("WritePath")
51 :
52 : /*
53 : 0 : old style "Template" string using ";" as separator
54 : 1 : internal paths "Template_internal" string list
55 : 2 : user paths "Template_user" string list
56 : 3 : write path "Template_write" string
57 : */
58 :
59 : #define POSTFIX_INTERNAL_PATHS OUString("_internal")
60 : #define POSTFIX_USER_PATHS OUString("_user")
61 : #define POSTFIX_WRITE_PATH OUString("_writable")
62 :
63 : const sal_Int32 IDGROUP_OLDSTYLE = 0;
64 : const sal_Int32 IDGROUP_INTERNAL_PATHS = 1;
65 : const sal_Int32 IDGROUP_USER_PATHS = 2;
66 : const sal_Int32 IDGROUP_WRITE_PATH = 3;
67 :
68 : const sal_Int32 IDGROUP_COUNT = 4;
69 :
70 4717 : sal_Int32 impl_getPropGroup(sal_Int32 nID)
71 : {
72 4717 : return (nID % IDGROUP_COUNT);
73 : }
74 :
75 :
76 : #define SERVICENAME_PATHSETTINGS DECLARE_ASCII("com.sun.star.util.PathSettings" )
77 : #define IMPLEMENTATIONNAME_PATHSETTINGS DECLARE_ASCII("com.sun.star.comp.framework.PathSettings" )
78 :
79 : namespace framework
80 : {
81 :
82 : //-----------------------------------------------------------------------------
83 : // XInterface, XTypeProvider, XServiceInfo
84 :
85 6028 : DEFINE_XINTERFACE_8 ( PathSettings ,
86 : OWeakObject ,
87 : DIRECT_INTERFACE ( css::lang::XTypeProvider ),
88 : DIRECT_INTERFACE ( css::lang::XServiceInfo ),
89 : DERIVED_INTERFACE( css::lang::XEventListener, css::util::XChangesListener),
90 : DIRECT_INTERFACE ( css::util::XChangesListener ),
91 : DIRECT_INTERFACE ( css::util::XPathSettings ),
92 : DERIVED_INTERFACE( css::beans::XPropertySet, css::util::XPathSettings),
93 : DIRECT_INTERFACE ( css::beans::XFastPropertySet ),
94 : DIRECT_INTERFACE ( css::beans::XMultiPropertySet )
95 : )
96 :
97 0 : DEFINE_XTYPEPROVIDER_8 ( PathSettings ,
98 : css::lang::XTypeProvider ,
99 : css::lang::XServiceInfo ,
100 : css::lang::XEventListener ,
101 : css::util::XChangesListener ,
102 : css::util::XPathSettings ,
103 : css::beans::XPropertySet ,
104 : css::beans::XFastPropertySet ,
105 : css::beans::XMultiPropertySet
106 : )
107 :
108 761 : DEFINE_XSERVICEINFO_ONEINSTANCESERVICE_2( PathSettings ,
109 : ::cppu::OWeakObject ,
110 : SERVICENAME_PATHSETTINGS ,
111 : IMPLEMENTATIONNAME_PATHSETTINGS
112 : )
113 :
114 133 : DEFINE_INIT_SERVICE ( PathSettings,
115 : {
116 : /*Attention
117 : I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
118 : to create a new instance of this class by our own supported service factory.
119 : see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further information!
120 : */
121 :
122 : // fill cache
123 : impl_readAll();
124 : }
125 : )
126 :
127 : //-----------------------------------------------------------------------------
128 133 : PathSettings::PathSettings( const css::uno::Reference< css::uno::XComponentContext >& xContext )
129 : // Init baseclasses first
130 : // Attention: Don't change order of initialization!
131 : // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
132 : // We must garant right initialization and a valid value of this to initialize other baseclasses!
133 : : ThreadHelpBase()
134 133 : , ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >(m_aLock.getShareableOslMutex())
135 : , ::cppu::OPropertySetHelper(*(static_cast< ::cppu::OBroadcastHelper* >(this)))
136 : , ::cppu::OWeakObject()
137 : // Init member
138 : , m_xContext (xContext)
139 : , m_pPropHelp(0 )
140 266 : , m_bIgnoreEvents(sal_False)
141 : {
142 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::PathSettings" );
143 133 : }
144 :
145 : //-----------------------------------------------------------------------------
146 396 : PathSettings::~PathSettings()
147 : {
148 132 : css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(m_xCfgNew, css::uno::UNO_QUERY);
149 132 : if (xBroadcaster.is())
150 132 : xBroadcaster->removeChangesListener(m_xCfgNewListener);
151 132 : if (m_pPropHelp)
152 132 : delete m_pPropHelp;
153 264 : }
154 :
155 : //-----------------------------------------------------------------------------
156 0 : void SAL_CALL PathSettings::changesOccurred(const css::util::ChangesEvent& aEvent)
157 : throw (css::uno::RuntimeException)
158 : {
159 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::changesOccurred" );
160 :
161 0 : sal_Int32 c = aEvent.Changes.getLength();
162 0 : sal_Int32 i = 0;
163 0 : sal_Bool bUpdateDescriptor = sal_False;
164 :
165 0 : for (i=0; i<c; ++i)
166 : {
167 0 : const css::util::ElementChange& aChange = aEvent.Changes[i];
168 :
169 0 : OUString sChanged;
170 0 : aChange.Accessor >>= sChanged;
171 :
172 0 : OUString sPath = ::utl::extractFirstFromConfigurationPath(sChanged);
173 0 : if (!sPath.isEmpty())
174 : {
175 0 : PathSettings::EChangeOp eOp = impl_updatePath(sPath, sal_True);
176 0 : if (
177 0 : (eOp == PathSettings::E_ADDED ) ||
178 : (eOp == PathSettings::E_REMOVED)
179 : )
180 0 : bUpdateDescriptor = sal_True;
181 : }
182 0 : }
183 :
184 0 : if (bUpdateDescriptor)
185 0 : impl_rebuildPropertyDescriptor();
186 0 : }
187 :
188 : //-----------------------------------------------------------------------------
189 0 : void SAL_CALL PathSettings::disposing(const css::lang::EventObject& aSource)
190 : throw(css::uno::RuntimeException)
191 : {
192 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::disposing" );
193 0 : WriteGuard aWriteLock(m_aLock);
194 :
195 0 : if (aSource.Source == m_xCfgNew)
196 0 : m_xCfgNew.clear();
197 :
198 0 : aWriteLock.unlock();
199 0 : }
200 :
201 : //-----------------------------------------------------------------------------
202 118 : OUString PathSettings::getStringProperty(const OUString& p1)
203 : throw(css::uno::RuntimeException)
204 : {
205 118 : css::uno::Any a = ::cppu::OPropertySetHelper::getPropertyValue(p1);
206 118 : OUString s;
207 118 : a >>= s;
208 118 : return s;
209 : }
210 :
211 : //-----------------------------------------------------------------------------
212 0 : void PathSettings::setStringProperty(const OUString& p1, const OUString& p2)
213 : throw(css::uno::RuntimeException)
214 : {
215 0 : ::cppu::OPropertySetHelper::setPropertyValue(p1, css::uno::Any(p2));
216 0 : }
217 :
218 : //-----------------------------------------------------------------------------
219 133 : void PathSettings::impl_readAll()
220 : {
221 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::impl_readAll" );
222 : SAL_INFO( "fwk", "framework (as96863) ::PathSettings::load config (all)");
223 :
224 : try
225 : {
226 : // TODO think about me
227 133 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
228 266 : css::uno::Sequence< OUString > lPaths = xCfg->getElementNames();
229 :
230 133 : sal_Int32 c = lPaths.getLength();
231 3325 : for (sal_Int32 i = 0; i < c; ++i)
232 : {
233 3192 : const OUString& sPath = lPaths[i];
234 3192 : impl_updatePath(sPath, sal_False);
235 133 : }
236 : }
237 0 : catch(const css::uno::RuntimeException& )
238 : {
239 : }
240 :
241 133 : impl_rebuildPropertyDescriptor();
242 133 : }
243 :
244 : //-----------------------------------------------------------------------------
245 : // NO substitution here ! It's done outside ...
246 3192 : OUStringList PathSettings::impl_readOldFormat(const OUString& sPath)
247 : {
248 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::impl_readOldFormat" );
249 3192 : css::uno::Reference< css::container::XNameAccess > xCfg( fa_getCfgOld() );
250 3192 : OUStringList aPathVal;
251 :
252 3192 : if( xCfg->hasByName(sPath) )
253 : {
254 3059 : css::uno::Any aVal( xCfg->getByName(sPath) );
255 :
256 6118 : OUString sStringVal;
257 6118 : css::uno::Sequence< OUString > lStringListVal;
258 :
259 3059 : if (aVal >>= sStringVal)
260 : {
261 2128 : aPathVal.push_back(sStringVal);
262 : }
263 931 : else if (aVal >>= lStringListVal)
264 : {
265 931 : aPathVal << lStringListVal;
266 3059 : }
267 : }
268 :
269 3192 : return aPathVal;
270 : }
271 :
272 : //-----------------------------------------------------------------------------
273 : // NO substitution here ! It's done outside ...
274 3192 : PathSettings::PathInfo PathSettings::impl_readNewFormat(const OUString& sPath)
275 : {
276 3192 : const OUString CFGPROP_INTERNALPATHS("InternalPaths");
277 6384 : const OUString CFGPROP_ISSINGLEPATH("IsSinglePath");
278 :
279 6384 : css::uno::Reference< css::container::XNameAccess > xCfg = fa_getCfgNew();
280 :
281 : // get access to the "queried" path
282 6384 : css::uno::Reference< css::container::XNameAccess > xPath;
283 3192 : xCfg->getByName(sPath) >>= xPath;
284 :
285 3192 : PathSettings::PathInfo aPathVal;
286 :
287 : // read internal path list
288 6384 : css::uno::Reference< css::container::XNameAccess > xIPath;
289 3192 : xPath->getByName(CFGPROP_INTERNALPATHS) >>= xIPath;
290 3192 : aPathVal.lInternalPaths << xIPath->getElementNames();
291 :
292 : // read user defined path list
293 3192 : aPathVal.lUserPaths << xPath->getByName(CFGPROP_USERPATHS);
294 :
295 : // read the writeable path
296 3192 : xPath->getByName(CFGPROP_WRITEPATH) >>= aPathVal.sWritePath;
297 :
298 : // read state props
299 3192 : xPath->getByName(CFGPROP_ISSINGLEPATH) >>= aPathVal.bIsSinglePath;
300 :
301 : // analyze finalized/mandatory states
302 3192 : aPathVal.bIsReadonly = sal_False;
303 6384 : css::uno::Reference< css::beans::XProperty > xInfo(xPath, css::uno::UNO_QUERY);
304 3192 : if (xInfo.is())
305 : {
306 3192 : css::beans::Property aInfo = xInfo->getAsProperty();
307 3192 : sal_Bool bFinalized = ((aInfo.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
308 :
309 : // Note: Till we support finalized / mandatory on our API more in detail we handle
310 : // all states simple as READONLY ! But because all realy needed paths are "mandatory" by default
311 : // we have to handle "finalized" as the real "readonly" indicator .
312 3192 : aPathVal.bIsReadonly = bFinalized;
313 : }
314 :
315 6384 : return aPathVal;
316 : }
317 :
318 : //-----------------------------------------------------------------------------
319 0 : void PathSettings::impl_storePath(const PathSettings::PathInfo& aPath)
320 : {
321 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::impl_storePath" );
322 0 : m_bIgnoreEvents = sal_True;
323 :
324 0 : css::uno::Reference< css::container::XNameAccess > xCfgNew = fa_getCfgNew();
325 0 : css::uno::Reference< css::container::XNameAccess > xCfgOld = fa_getCfgOld();
326 :
327 : // try to replace path-parts with well known and uspported variables.
328 : // So an office can be moved easialy to another location without loosing
329 : // it's related paths.
330 0 : PathInfo aResubstPath(aPath);
331 0 : impl_subst(aResubstPath, sal_True);
332 :
333 : // update new configuration
334 0 : if (! aResubstPath.bIsSinglePath)
335 : {
336 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
337 : aResubstPath.sPathName,
338 : CFGPROP_USERPATHS,
339 0 : css::uno::makeAny(aResubstPath.lUserPaths.getAsConstList()));
340 : }
341 :
342 : ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew,
343 : aResubstPath.sPathName,
344 : CFGPROP_WRITEPATH,
345 0 : css::uno::makeAny(aResubstPath.sWritePath));
346 :
347 0 : ::comphelper::ConfigurationHelper::flush(xCfgNew);
348 :
349 : // remove the whole path from the old configuration !
350 : // Otherwise we cant make sure that the diff between new and old configuration
351 : // on loading time realy represent an user setting !!!
352 :
353 : // Check if the given path exists inside the old configuration.
354 : // Because our new configuration knows more then the list of old paths ... !
355 0 : if (xCfgOld->hasByName(aResubstPath.sPathName))
356 : {
357 0 : css::uno::Reference< css::beans::XPropertySet > xProps(xCfgOld, css::uno::UNO_QUERY_THROW);
358 0 : xProps->setPropertyValue(aResubstPath.sPathName, css::uno::Any());
359 0 : ::comphelper::ConfigurationHelper::flush(xCfgOld);
360 : }
361 :
362 0 : m_bIgnoreEvents = sal_False;
363 0 : }
364 :
365 : //-----------------------------------------------------------------------------
366 3192 : void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo& rPath,
367 : const OUStringList& lOld )
368 : {
369 : SAL_INFO( "fwk", "framework Ocke.Janssen@sun.com PathSettings::impl_mergeOldUserPaths" );
370 3192 : OUStringList::const_iterator pIt;
371 21147 : for ( pIt = lOld.begin();
372 14098 : pIt != lOld.end() ;
373 : ++pIt )
374 : {
375 3857 : const OUString& sOld = *pIt;
376 :
377 3857 : if (rPath.bIsSinglePath)
378 : {
379 : LOG_ASSERT2(lOld.size()>1, "PathSettings::impl_mergeOldUserPaths()", "Single path has more then one path value inside old configuration (Common.xcu)!")
380 665 : if (! rPath.sWritePath.equals(sOld))
381 0 : rPath.sWritePath = sOld;
382 : }
383 : else
384 : {
385 6384 : if (
386 19638 : ( rPath.lInternalPaths.findConst(sOld) == rPath.lInternalPaths.end()) &&
387 19638 : ( rPath.lUserPaths.findConst(sOld) == rPath.lUserPaths.end() ) &&
388 1226 : (! rPath.sWritePath.equals(sOld) )
389 : )
390 162 : rPath.lUserPaths.push_back(sOld);
391 : }
392 : }
393 3192 : }
394 :
395 : //-----------------------------------------------------------------------------
396 3192 : PathSettings::EChangeOp PathSettings::impl_updatePath(const OUString& sPath ,
397 : sal_Bool bNotifyListener)
398 : {
399 : // SAFE ->
400 3192 : WriteGuard aWriteLock(m_aLock);
401 :
402 3192 : PathSettings::PathInfo* pPathOld = 0;
403 3192 : PathSettings::PathInfo* pPathNew = 0;
404 3192 : PathSettings::EChangeOp eOp = PathSettings::E_UNDEFINED;
405 6384 : PathSettings::PathInfo aPath;
406 :
407 : try
408 : {
409 3192 : aPath = impl_readNewFormat(sPath);
410 3192 : aPath.sPathName = sPath;
411 : // replace all might existing variables with real values
412 : // Do it before these old paths will be compared against the
413 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
414 : // will produce strings with same content (because some variables are redundant!)
415 3192 : impl_subst(aPath, sal_False);
416 : }
417 0 : catch(const css::uno::RuntimeException&)
418 0 : { throw; }
419 0 : catch(const css::container::NoSuchElementException&)
420 0 : { eOp = PathSettings::E_REMOVED; }
421 0 : catch(const css::uno::Exception&)
422 0 : { throw; }
423 :
424 : try
425 : {
426 : // migration of old user defined values on demand
427 : // can be disabled for a new major
428 3192 : OUStringList lOldVals = impl_readOldFormat(sPath);
429 : // replace all might existing variables with real values
430 : // Do it before these old paths will be compared against the
431 : // new path configuration. Otherwise some striungs uses different variables ... but substitution
432 : // will produce strings with same content (because some variables are redundant!)
433 3192 : impl_subst(lOldVals, fa_getSubstitution(), sal_False);
434 3192 : impl_mergeOldUserPaths(aPath, lOldVals);
435 : }
436 0 : catch(const css::uno::RuntimeException&)
437 0 : { throw; }
438 : // Normal(!) exceptions can be ignored!
439 : // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
440 : // we cant find a value for it inside the "old" configuration. So a NoSuchElementException
441 : // will be normal .-)
442 0 : catch(const css::uno::Exception&)
443 : {}
444 :
445 3192 : PathSettings::PathHash::iterator pPath = m_lPaths.find(sPath);
446 3192 : if (eOp == PathSettings::E_UNDEFINED)
447 : {
448 3192 : if (pPath != m_lPaths.end())
449 0 : eOp = PathSettings::E_CHANGED;
450 : else
451 3192 : eOp = PathSettings::E_ADDED;
452 : }
453 :
454 3192 : switch(eOp)
455 : {
456 : case PathSettings::E_ADDED :
457 : {
458 3192 : if (bNotifyListener)
459 : {
460 0 : pPathOld = 0;
461 0 : pPathNew = &aPath;
462 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
463 : }
464 3192 : m_lPaths[sPath] = aPath;
465 : }
466 3192 : break;
467 :
468 : case PathSettings::E_CHANGED :
469 : {
470 0 : if (bNotifyListener)
471 : {
472 0 : pPathOld = &(pPath->second);
473 0 : pPathNew = &aPath;
474 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
475 : }
476 0 : m_lPaths[sPath] = aPath;
477 : }
478 0 : break;
479 :
480 : case PathSettings::E_REMOVED :
481 : {
482 0 : if (pPath != m_lPaths.end())
483 : {
484 0 : if (bNotifyListener)
485 : {
486 0 : pPathOld = &(pPath->second);
487 0 : pPathNew = 0;
488 0 : impl_notifyPropListener(eOp, sPath, pPathOld, pPathNew);
489 : }
490 0 : m_lPaths.erase(pPath);
491 : }
492 : }
493 0 : break;
494 :
495 : default: // to let compiler be happy
496 0 : break;
497 : }
498 :
499 6384 : return eOp;
500 : }
501 :
502 : //-----------------------------------------------------------------------------
503 0 : css::uno::Sequence< sal_Int32 > PathSettings::impl_mapPathName2IDList(const OUString& sPath)
504 : {
505 0 : OUString sOldStyleProp = sPath;
506 0 : OUString sInternalProp = sPath+POSTFIX_INTERNAL_PATHS;
507 0 : OUString sUserProp = sPath+POSTFIX_USER_PATHS;
508 0 : OUString sWriteProp = sPath+POSTFIX_WRITE_PATH;
509 :
510 : // Attention: The default set of IDs is fix and must follow these schema.
511 : // Otherwhise the outside code ant work for new added properties.
512 : // Why ?
513 : // The outside code must fire N events for every changed property.
514 : // And the knowing about packaging of variables of the structure PathInfo
515 : // follow these group IDs ! But if such ID isnt in the range of [0..IDGROUP_COUNT]
516 : // the outside cant determine the right group ... and cant fire the right events .-)
517 :
518 0 : css::uno::Sequence< sal_Int32 > lIDs(IDGROUP_COUNT);
519 0 : lIDs[0] = IDGROUP_OLDSTYLE ;
520 0 : lIDs[1] = IDGROUP_INTERNAL_PATHS;
521 0 : lIDs[2] = IDGROUP_USER_PATHS ;
522 0 : lIDs[3] = IDGROUP_WRITE_PATH ;
523 :
524 0 : sal_Int32 c = m_lPropDesc.getLength();
525 0 : sal_Int32 i = 0;
526 0 : for (i=0; i<c; ++i)
527 : {
528 0 : const css::beans::Property& rProp = m_lPropDesc[i];
529 :
530 0 : if (rProp.Name.equals(sOldStyleProp))
531 0 : lIDs[IDGROUP_OLDSTYLE] = rProp.Handle;
532 : else
533 0 : if (rProp.Name.equals(sInternalProp))
534 0 : lIDs[IDGROUP_INTERNAL_PATHS] = rProp.Handle;
535 : else
536 0 : if (rProp.Name.equals(sUserProp))
537 0 : lIDs[IDGROUP_USER_PATHS] = rProp.Handle;
538 : else
539 0 : if (rProp.Name.equals(sWriteProp))
540 0 : lIDs[IDGROUP_WRITE_PATH] = rProp.Handle;
541 : }
542 :
543 0 : return lIDs;
544 : }
545 :
546 : //-----------------------------------------------------------------------------
547 0 : void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp /*eOp*/ ,
548 : const OUString& sPath ,
549 : const PathSettings::PathInfo* pPathOld,
550 : const PathSettings::PathInfo* pPathNew)
551 : {
552 0 : css::uno::Sequence< sal_Int32 > lHandles(1);
553 0 : css::uno::Sequence< css::uno::Any > lOldVals(1);
554 0 : css::uno::Sequence< css::uno::Any > lNewVals(1);
555 :
556 0 : css::uno::Sequence< sal_Int32 > lIDs = impl_mapPathName2IDList(sPath);
557 0 : sal_Int32 c = lIDs.getLength();
558 0 : sal_Int32 i = 0;
559 0 : sal_Int32 nMaxID = m_lPropDesc.getLength()-1;
560 0 : for (i=0; i<c; ++i)
561 : {
562 0 : sal_Int32 nID = lIDs[i];
563 :
564 0 : if (
565 0 : (nID < 0 ) ||
566 : (nID > nMaxID)
567 : )
568 0 : continue;
569 :
570 0 : lHandles[0] = nID;
571 0 : switch(impl_getPropGroup(nID))
572 : {
573 : case IDGROUP_OLDSTYLE :
574 : {
575 0 : if (pPathOld)
576 : {
577 0 : OUString sVal = impl_convertPath2OldStyle(*pPathOld);
578 0 : lOldVals[0] <<= sVal;
579 : }
580 0 : if (pPathNew)
581 : {
582 0 : OUString sVal = impl_convertPath2OldStyle(*pPathNew);
583 0 : lNewVals[0] <<= sVal;
584 : }
585 : }
586 0 : break;
587 :
588 : case IDGROUP_INTERNAL_PATHS :
589 : {
590 0 : if (pPathOld)
591 0 : lOldVals[0] <<= pPathOld->lInternalPaths.getAsConstList();
592 0 : if (pPathNew)
593 0 : lNewVals[0] <<= pPathNew->lInternalPaths.getAsConstList();
594 : }
595 0 : break;
596 :
597 : case IDGROUP_USER_PATHS :
598 : {
599 0 : if (pPathOld)
600 0 : lOldVals[0] <<= pPathOld->lUserPaths.getAsConstList();
601 0 : if (pPathNew)
602 0 : lNewVals[0] <<= pPathNew->lUserPaths.getAsConstList();
603 : }
604 0 : break;
605 :
606 : case IDGROUP_WRITE_PATH :
607 : {
608 0 : if (pPathOld)
609 0 : lOldVals[0] <<= pPathOld->sWritePath;
610 0 : if (pPathNew)
611 0 : lNewVals[0] <<= pPathNew->sWritePath;
612 : }
613 0 : break;
614 : }
615 :
616 : fire(lHandles.getArray(),
617 0 : lNewVals.getArray(),
618 0 : lOldVals.getArray(),
619 : 1,
620 0 : sal_False);
621 0 : }
622 0 : }
623 :
624 : //-----------------------------------------------------------------------------
625 9576 : void PathSettings::impl_subst( OUStringList& lVals ,
626 : const css::uno::Reference< css::util::XStringSubstitution >& xSubst ,
627 : sal_Bool bReSubst)
628 : {
629 9576 : OUStringList::iterator pIt;
630 :
631 47604 : for ( pIt = lVals.begin();
632 31736 : pIt != lVals.end() ;
633 : ++pIt )
634 : {
635 6292 : const OUString& sOld = *pIt;
636 6292 : OUString sNew ;
637 6292 : if (bReSubst)
638 0 : sNew = xSubst->reSubstituteVariables(sOld);
639 : else
640 6292 : sNew = xSubst->substituteVariables(sOld, sal_False);
641 :
642 6292 : *pIt = sNew;
643 6292 : }
644 9576 : }
645 :
646 : //-----------------------------------------------------------------------------
647 3192 : void PathSettings::impl_subst(PathSettings::PathInfo& aPath ,
648 : sal_Bool bReSubst)
649 : {
650 3192 : css::uno::Reference< css::util::XStringSubstitution > xSubst = fa_getSubstitution();
651 :
652 3192 : impl_subst(aPath.lInternalPaths, xSubst, bReSubst);
653 3192 : impl_subst(aPath.lUserPaths , xSubst, bReSubst);
654 3192 : if (bReSubst)
655 0 : aPath.sWritePath = xSubst->reSubstituteVariables(aPath.sWritePath);
656 : else
657 3192 : aPath.sWritePath = xSubst->substituteVariables(aPath.sWritePath, sal_False);
658 3192 : }
659 :
660 : //-----------------------------------------------------------------------------
661 4504 : OUString PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath) const
662 : {
663 4504 : OUStringList::const_iterator pIt;
664 4504 : OUStringList lTemp;
665 4504 : lTemp.reserve(rPath.lInternalPaths.size() + rPath.lUserPaths.size() + 1);
666 :
667 20961 : for ( pIt = rPath.lInternalPaths.begin();
668 13974 : pIt != rPath.lInternalPaths.end() ;
669 : ++pIt )
670 : {
671 2483 : lTemp.push_back(*pIt);
672 : }
673 13620 : for ( pIt = rPath.lUserPaths.begin();
674 9080 : pIt != rPath.lUserPaths.end() ;
675 : ++pIt )
676 : {
677 36 : lTemp.push_back(*pIt);
678 : }
679 :
680 4504 : if (!rPath.sWritePath.isEmpty())
681 4353 : lTemp.push_back(rPath.sWritePath);
682 :
683 9008 : OUStringBuffer sPathVal(256);
684 27256 : for ( pIt = lTemp.begin();
685 22752 : pIt != lTemp.end() ;
686 : )
687 : {
688 6872 : sPathVal.append(*pIt);
689 6872 : ++pIt;
690 6872 : if (pIt != lTemp.end())
691 2368 : sPathVal.appendAscii(";");
692 : }
693 :
694 9008 : return sPathVal.makeStringAndClear();
695 : }
696 :
697 : //-----------------------------------------------------------------------------
698 0 : OUStringList PathSettings::impl_convertOldStyle2Path(const OUString& sOldStylePath) const
699 : {
700 0 : OUStringList lList;
701 0 : sal_Int32 nToken = 0;
702 0 : do
703 : {
704 0 : OUString sToken = sOldStylePath.getToken(0, ';', nToken);
705 0 : if (!sToken.isEmpty())
706 0 : lList.push_back(sToken);
707 : }
708 0 : while(nToken >= 0);
709 :
710 0 : return lList;
711 : }
712 :
713 : //-----------------------------------------------------------------------------
714 0 : void PathSettings::impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
715 : OUStringList& lList)
716 : {
717 0 : OUStringList::const_iterator pIt;
718 0 : for ( pIt = rPath.lInternalPaths.begin();
719 0 : pIt != rPath.lInternalPaths.end() ;
720 : ++pIt )
721 : {
722 0 : const OUString& rItem = *pIt;
723 0 : OUStringList::iterator pItem = lList.find(rItem);
724 0 : if (pItem != lList.end())
725 0 : lList.erase(pItem);
726 : }
727 0 : for ( pIt = rPath.lUserPaths.begin();
728 0 : pIt != rPath.lUserPaths.end() ;
729 : ++pIt )
730 : {
731 0 : const OUString& rItem = *pIt;
732 0 : OUStringList::iterator pItem = lList.find(rItem);
733 0 : if (pItem != lList.end())
734 0 : lList.erase(pItem);
735 : }
736 :
737 0 : OUStringList::iterator pItem = lList.find(rPath.sWritePath);
738 0 : if (pItem != lList.end())
739 0 : lList.erase(pItem);
740 0 : }
741 :
742 : //-----------------------------------------------------------------------------
743 133 : void PathSettings::impl_rebuildPropertyDescriptor()
744 : {
745 : // SAFE ->
746 133 : WriteGuard aWriteLock(m_aLock);
747 :
748 133 : sal_Int32 c = (sal_Int32)m_lPaths.size();
749 133 : sal_Int32 i = 0;
750 133 : m_lPropDesc.realloc(c*IDGROUP_COUNT);
751 :
752 133 : PathHash::const_iterator pIt;
753 9975 : for ( pIt = m_lPaths.begin();
754 6650 : pIt != m_lPaths.end() ;
755 : ++pIt )
756 : {
757 3192 : const PathSettings::PathInfo& rPath = pIt->second;
758 3192 : css::beans::Property* pProp = 0;
759 :
760 3192 : pProp = &(m_lPropDesc[i]);
761 3192 : pProp->Name = rPath.sPathName;
762 3192 : pProp->Handle = i;
763 3192 : pProp->Type = ::getCppuType((OUString*)0);
764 3192 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
765 3192 : if (rPath.bIsReadonly)
766 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
767 3192 : ++i;
768 :
769 3192 : pProp = &(m_lPropDesc[i]);
770 3192 : pProp->Name = rPath.sPathName+POSTFIX_INTERNAL_PATHS;
771 3192 : pProp->Handle = i;
772 3192 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
773 : pProp->Attributes = css::beans::PropertyAttribute::BOUND |
774 3192 : css::beans::PropertyAttribute::READONLY;
775 3192 : ++i;
776 :
777 3192 : pProp = &(m_lPropDesc[i]);
778 3192 : pProp->Name = rPath.sPathName+POSTFIX_USER_PATHS;
779 3192 : pProp->Handle = i;
780 3192 : pProp->Type = ::getCppuType((css::uno::Sequence< OUString >*)0);
781 3192 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
782 3192 : if (rPath.bIsReadonly)
783 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
784 3192 : ++i;
785 :
786 3192 : pProp = &(m_lPropDesc[i]);
787 3192 : pProp->Name = rPath.sPathName+POSTFIX_WRITE_PATH;
788 3192 : pProp->Handle = i;
789 3192 : pProp->Type = ::getCppuType((OUString*)0);
790 3192 : pProp->Attributes = css::beans::PropertyAttribute::BOUND;
791 3192 : if (rPath.bIsReadonly)
792 0 : pProp->Attributes |= css::beans::PropertyAttribute::READONLY;
793 3192 : ++i;
794 : }
795 :
796 133 : if (m_pPropHelp)
797 0 : delete m_pPropHelp;
798 133 : m_pPropHelp = new ::cppu::OPropertyArrayHelper(m_lPropDesc, sal_False); // false => not sorted ... must be done inside helper
799 :
800 133 : aWriteLock.unlock();
801 : // <- SAFE
802 133 : }
803 :
804 : //-----------------------------------------------------------------------------
805 4717 : css::uno::Any PathSettings::impl_getPathValue(sal_Int32 nID) const
806 : {
807 4717 : const PathSettings::PathInfo* pPath = impl_getPathAccessConst(nID);
808 4717 : if (! pPath)
809 0 : throw css::container::NoSuchElementException();
810 :
811 4717 : css::uno::Any aVal;
812 4717 : switch(impl_getPropGroup(nID))
813 : {
814 : case IDGROUP_OLDSTYLE :
815 : {
816 4504 : OUString sVal = impl_convertPath2OldStyle(*pPath);
817 4504 : aVal <<= sVal;
818 : }
819 4504 : break;
820 :
821 : case IDGROUP_INTERNAL_PATHS :
822 : {
823 71 : aVal <<= pPath->lInternalPaths.getAsConstList();
824 : }
825 71 : break;
826 :
827 : case IDGROUP_USER_PATHS :
828 : {
829 71 : aVal <<= pPath->lUserPaths.getAsConstList();
830 : }
831 71 : break;
832 :
833 : case IDGROUP_WRITE_PATH :
834 : {
835 71 : aVal <<= pPath->sWritePath;
836 : }
837 71 : break;
838 : }
839 :
840 4717 : return aVal;
841 : }
842 :
843 : //-----------------------------------------------------------------------------
844 0 : void PathSettings::impl_setPathValue( sal_Int32 nID ,
845 : const css::uno::Any& aVal)
846 : {
847 0 : PathSettings::PathInfo* pOrgPath = impl_getPathAccess(nID);
848 0 : if (! pOrgPath)
849 0 : throw css::container::NoSuchElementException();
850 :
851 : // We work on a copied path ... so we can be sure that errors during this operation
852 : // does not make our internal cache invalid .-)
853 0 : PathSettings::PathInfo aChangePath(*pOrgPath);
854 :
855 0 : switch(impl_getPropGroup(nID))
856 : {
857 : case IDGROUP_OLDSTYLE :
858 : {
859 0 : OUString sVal;
860 0 : aVal >>= sVal;
861 0 : OUStringList lList = impl_convertOldStyle2Path(sVal);
862 0 : impl_subst(lList, fa_getSubstitution(), sal_False);
863 0 : impl_purgeKnownPaths(aChangePath, lList);
864 0 : if (! impl_isValidPath(lList))
865 0 : throw css::lang::IllegalArgumentException();
866 :
867 0 : if (aChangePath.bIsSinglePath)
868 : {
869 : LOG_ASSERT2(lList.size()>1, "PathSettings::impl_setPathValue()", "You try to set more then path value for a defined SINGLE_PATH!")
870 0 : if ( !lList.empty() )
871 0 : aChangePath.sWritePath = *(lList.begin());
872 : else
873 0 : aChangePath.sWritePath = OUString();
874 : }
875 : else
876 : {
877 0 : OUStringList::const_iterator pIt;
878 0 : for ( pIt = lList.begin();
879 0 : pIt != lList.end() ;
880 : ++pIt )
881 : {
882 0 : aChangePath.lUserPaths.push_back(*pIt);
883 : }
884 0 : }
885 : }
886 0 : break;
887 :
888 : case IDGROUP_INTERNAL_PATHS :
889 : {
890 0 : if (aChangePath.bIsSinglePath)
891 : {
892 0 : OUStringBuffer sMsg(256);
893 0 : sMsg.appendAscii("The path '" );
894 0 : sMsg.append (aChangePath.sPathName);
895 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths cant be set.");
896 : throw css::uno::Exception(sMsg.makeStringAndClear(),
897 0 : static_cast< ::cppu::OWeakObject* >(this));
898 : }
899 :
900 0 : OUStringList lList;
901 0 : lList << aVal;
902 0 : if (! impl_isValidPath(lList))
903 0 : throw css::lang::IllegalArgumentException();
904 0 : aChangePath.lInternalPaths = lList;
905 : }
906 0 : break;
907 :
908 : case IDGROUP_USER_PATHS :
909 : {
910 0 : if (aChangePath.bIsSinglePath)
911 : {
912 0 : OUStringBuffer sMsg(256);
913 0 : sMsg.appendAscii("The path '" );
914 0 : sMsg.append (aChangePath.sPathName);
915 0 : sMsg.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal paths cant be set.");
916 : throw css::uno::Exception(sMsg.makeStringAndClear(),
917 0 : static_cast< ::cppu::OWeakObject* >(this));
918 : }
919 :
920 0 : OUStringList lList;
921 0 : lList << aVal;
922 0 : if (! impl_isValidPath(lList))
923 0 : throw css::lang::IllegalArgumentException();
924 0 : aChangePath.lUserPaths = lList;
925 : }
926 0 : break;
927 :
928 : case IDGROUP_WRITE_PATH :
929 : {
930 0 : OUString sVal;
931 0 : aVal >>= sVal;
932 0 : if (! impl_isValidPath(sVal))
933 0 : throw css::lang::IllegalArgumentException();
934 0 : aChangePath.sWritePath = sVal;
935 : }
936 0 : break;
937 : }
938 :
939 : // TODO check if path has at least one path value set
940 : // At least it depends from the feature using this path, if an empty path list is allowed.
941 :
942 : // first we should try to store the changed (copied!) path ...
943 : // In case an error occure on saving time an exception is thrown ...
944 : // If no exception occures we can update our internal cache (means
945 : // we can overwrite pOrgPath !
946 0 : impl_storePath(aChangePath);
947 0 : pOrgPath->takeOver(aChangePath);
948 0 : }
949 :
950 : //-----------------------------------------------------------------------------
951 0 : sal_Bool PathSettings::impl_isValidPath(const OUStringList& lPath) const
952 : {
953 0 : OUStringList::const_iterator pIt;
954 0 : for ( pIt = lPath.begin();
955 0 : pIt != lPath.end() ;
956 : ++pIt )
957 : {
958 0 : const OUString& rVal = *pIt;
959 0 : if (! impl_isValidPath(rVal))
960 0 : return sal_False;
961 : }
962 :
963 0 : return sal_True;
964 : }
965 :
966 : //-----------------------------------------------------------------------------
967 0 : sal_Bool PathSettings::impl_isValidPath(const OUString& sPath) const
968 : {
969 : // allow empty path to reset a path.
970 : // idea by LLA to support empty paths
971 : // if (sPath.getLength() == 0)
972 : // {
973 : // return sal_True;
974 : // }
975 :
976 0 : return (! INetURLObject(sPath).HasError());
977 : }
978 :
979 : //-----------------------------------------------------------------------------
980 4717 : OUString impl_extractBaseFromPropName(const OUString& sPropName)
981 : {
982 4717 : sal_Int32 i = sPropName.indexOf(POSTFIX_INTERNAL_PATHS);
983 4717 : if (i > -1)
984 71 : return sPropName.copy(0, i);
985 4646 : i = sPropName.indexOf(POSTFIX_USER_PATHS);
986 4646 : if (i > -1)
987 71 : return sPropName.copy(0, i);
988 4575 : i = sPropName.indexOf(POSTFIX_WRITE_PATH);
989 4575 : if (i > -1)
990 71 : return sPropName.copy(0, i);
991 :
992 4504 : return sPropName;
993 : }
994 :
995 : //-----------------------------------------------------------------------------
996 0 : PathSettings::PathInfo* PathSettings::impl_getPathAccess(sal_Int32 nHandle)
997 : {
998 : // SAFE ->
999 0 : ReadGuard aReadLock(m_aLock);
1000 :
1001 0 : if (nHandle > (m_lPropDesc.getLength()-1))
1002 0 : return 0;
1003 :
1004 0 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1005 0 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1006 0 : PathSettings::PathHash::iterator rPath = m_lPaths.find(sProp);
1007 :
1008 0 : if (rPath != m_lPaths.end())
1009 0 : return &(rPath->second);
1010 :
1011 0 : return 0;
1012 : // <- SAFE
1013 : }
1014 :
1015 : //-----------------------------------------------------------------------------
1016 4717 : const PathSettings::PathInfo* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle) const
1017 : {
1018 : // SAFE ->
1019 4717 : ReadGuard aReadLock(m_aLock);
1020 :
1021 4717 : if (nHandle > (m_lPropDesc.getLength()-1))
1022 0 : return 0;
1023 :
1024 4717 : const css::beans::Property& rProp = m_lPropDesc[nHandle];
1025 9434 : OUString sProp = impl_extractBaseFromPropName(rProp.Name);
1026 4717 : PathSettings::PathHash::const_iterator rPath = m_lPaths.find(sProp);
1027 :
1028 4717 : if (rPath != m_lPaths.end())
1029 4717 : return &(rPath->second);
1030 :
1031 4717 : return 0;
1032 : // <- SAFE
1033 : }
1034 :
1035 : //-----------------------------------------------------------------------------
1036 0 : sal_Bool SAL_CALL PathSettings::convertFastPropertyValue( css::uno::Any& aConvertedValue,
1037 : css::uno::Any& aOldValue ,
1038 : sal_Int32 nHandle ,
1039 : const css::uno::Any& aValue )
1040 : throw(css::lang::IllegalArgumentException)
1041 : {
1042 : // throws NoSuchElementException !
1043 0 : css::uno::Any aCurrentVal = impl_getPathValue(nHandle);
1044 :
1045 : return PropHelper::willPropertyBeChanged(
1046 : aCurrentVal,
1047 : aValue,
1048 : aOldValue,
1049 0 : aConvertedValue);
1050 : }
1051 :
1052 : //-----------------------------------------------------------------------------
1053 0 : void SAL_CALL PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle,
1054 : const css::uno::Any& aValue )
1055 : throw(css::uno::Exception)
1056 : {
1057 : // throws NoSuchElement- and IllegalArgumentException !
1058 0 : impl_setPathValue(nHandle, aValue);
1059 0 : }
1060 :
1061 : //-----------------------------------------------------------------------------
1062 4717 : void SAL_CALL PathSettings::getFastPropertyValue(css::uno::Any& aValue ,
1063 : sal_Int32 nHandle) const
1064 : {
1065 4717 : aValue = impl_getPathValue(nHandle);
1066 4717 : }
1067 :
1068 : //-----------------------------------------------------------------------------
1069 5547 : ::cppu::IPropertyArrayHelper& SAL_CALL PathSettings::getInfoHelper()
1070 : {
1071 5547 : return *m_pPropHelp;
1072 : }
1073 :
1074 : //-----------------------------------------------------------------------------
1075 133 : css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL PathSettings::getPropertySetInfo()
1076 : throw(css::uno::RuntimeException)
1077 : {
1078 133 : return css::uno::Reference< css::beans::XPropertySetInfo >(createPropertySetInfo(getInfoHelper()));
1079 : }
1080 :
1081 : //-----------------------------------------------------------------------------
1082 6384 : css::uno::Reference< css::util::XStringSubstitution > PathSettings::fa_getSubstitution()
1083 : {
1084 : // SAFE ->
1085 6384 : ReadGuard aReadLock(m_aLock);
1086 12768 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
1087 6384 : css::uno::Reference< css::util::XStringSubstitution > xSubst = m_xSubstitution;
1088 6384 : aReadLock.unlock();
1089 : // <- SAFE
1090 :
1091 6384 : if (! xSubst.is())
1092 : {
1093 : // create the needed substitution service.
1094 : // We must replace all used variables inside readed path values.
1095 : // In case we can't do so ... the whole office can't work really.
1096 : // That's why it seams to be OK to throw a RuntimeException then.
1097 133 : xSubst = css::util::PathSubstitution::create(xContext);
1098 :
1099 : // SAFE ->
1100 133 : WriteGuard aWriteLock(m_aLock);
1101 133 : m_xSubstitution = xSubst;
1102 133 : aWriteLock.unlock();
1103 : }
1104 :
1105 12768 : return xSubst;
1106 : }
1107 :
1108 : //-----------------------------------------------------------------------------
1109 3192 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgOld()
1110 : {
1111 3192 : const OUString CFG_NODE_OLD("org.openoffice.Office.Common/Path/Current");
1112 :
1113 : // SAFE ->
1114 6384 : ReadGuard aReadLock(m_aLock);
1115 6384 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
1116 3192 : css::uno::Reference< css::container::XNameAccess > xCfg = m_xCfgOld;
1117 3192 : aReadLock.unlock();
1118 : // <- SAFE
1119 :
1120 3192 : if (! xCfg.is())
1121 : {
1122 266 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1123 : ::comphelper::ConfigurationHelper::openConfig(
1124 : xContext,
1125 : CFG_NODE_OLD,
1126 : ::comphelper::ConfigurationHelper::E_STANDARD), // not readonly! Sometimes we need write access there !!!
1127 133 : css::uno::UNO_QUERY_THROW);
1128 :
1129 : // SAFE ->
1130 133 : WriteGuard aWriteLock(m_aLock);
1131 133 : m_xCfgOld = xCfg;
1132 133 : aWriteLock.unlock();
1133 : }
1134 :
1135 6384 : return xCfg;
1136 : }
1137 :
1138 : //-----------------------------------------------------------------------------
1139 3325 : css::uno::Reference< css::container::XNameAccess > PathSettings::fa_getCfgNew()
1140 : {
1141 3325 : const OUString CFG_NODE_NEW("org.openoffice.Office.Paths/Paths");
1142 :
1143 : // SAFE ->
1144 6650 : ReadGuard aReadLock(m_aLock);
1145 6650 : css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
1146 3325 : css::uno::Reference< css::container::XNameAccess > xCfg = m_xCfgNew;
1147 3325 : if (xCfg.is())
1148 3192 : return xCfg;
1149 133 : aReadLock.unlock();
1150 : // <- SAFE
1151 :
1152 133 : if (! xCfg.is())
1153 : {
1154 266 : xCfg = css::uno::Reference< css::container::XNameAccess >(
1155 : ::comphelper::ConfigurationHelper::openConfig(
1156 : xContext,
1157 : CFG_NODE_NEW,
1158 : ::comphelper::ConfigurationHelper::E_STANDARD),
1159 133 : css::uno::UNO_QUERY_THROW);
1160 :
1161 : // SAFE ->
1162 133 : WriteGuard aWriteLock(m_aLock);
1163 133 : m_xCfgNew = xCfg;
1164 133 : m_xCfgNewListener = new WeakChangesListener(this);
1165 133 : aWriteLock.unlock();
1166 :
1167 266 : css::uno::Reference< css::util::XChangesNotifier > xBroadcaster(xCfg, css::uno::UNO_QUERY_THROW);
1168 266 : xBroadcaster->addChangesListener(m_xCfgNewListener);
1169 : }
1170 :
1171 3458 : return xCfg;
1172 : }
1173 :
1174 : } // namespace framework
1175 :
1176 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|