1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pathsettings.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 // ______________________________________________
36 /** Attention: stl headers must(!) be included at first. Otherwhise it can make trouble
37 with solaris headers ...
40 #include <services/pathsettings.hxx>
41 #include <threadhelp/readguard.hxx>
42 #include <threadhelp/writeguard.hxx>
45 // ______________________________________________
47 #include <com/sun/star/beans/Property.hpp>
48 #include <com/sun/star/beans/XProperty.hpp>
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/container/XContainer.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/util/XChangesNotifier.hpp>
54 // ______________________________________________
55 // includes of other projects
56 #include <tools/urlobj.hxx>
57 #include <rtl/ustrbuf.hxx>
58 #include <rtl/logfile.hxx>
60 #include <comphelper/configurationhelper.hxx>
61 #include <unotools/configpathes.hxx>
63 // ______________________________________________
66 #define CFG_READONLY_DEFAULT sal_False
68 const ::rtl::OUString CFGPROP_INTERNALPATHES
= ::rtl::OUString::createFromAscii("InternalPaths");
69 const ::rtl::OUString CFGPROP_USERPATHES
= ::rtl::OUString::createFromAscii("UserPaths" );
70 const ::rtl::OUString CFGPROP_WRITEPATH
= ::rtl::OUString::createFromAscii("WritePath" );
71 const ::rtl::OUString CFGPROP_ISSINGLEPATH
= ::rtl::OUString::createFromAscii("IsSinglePath" );
74 0 : old style "Template" string using ";" as seperator
75 1 : internal paths "Template_internal" string list
76 2 : user paths "Template_user" string list
77 3 : write path "Template_write" string
80 const ::rtl::OUString POSTFIX_INTERNAL_PATHES
= ::rtl::OUString::createFromAscii("_internal");
81 const ::rtl::OUString POSTFIX_USER_PATHES
= ::rtl::OUString::createFromAscii("_user" );
82 const ::rtl::OUString POSTFIX_WRITE_PATH
= ::rtl::OUString::createFromAscii("_writable");
84 const sal_Int32 IDGROUP_OLDSTYLE
= 0;
85 const sal_Int32 IDGROUP_INTERNAL_PATHES
= 1;
86 const sal_Int32 IDGROUP_USER_PATHES
= 2;
87 const sal_Int32 IDGROUP_WRITE_PATH
= 3;
89 const sal_Int32 IDGROUP_COUNT
= 4;
91 sal_Int32
impl_getPropGroup(sal_Int32 nID
)
93 return (nID
% IDGROUP_COUNT
);
96 // ______________________________________________
102 //-----------------------------------------------------------------------------
103 // XInterface, XTypeProvider, XServiceInfo
105 DEFINE_XINTERFACE_7 ( PathSettings
,
107 DIRECT_INTERFACE ( css::lang::XTypeProvider
),
108 DIRECT_INTERFACE ( css::lang::XServiceInfo
),
109 DERIVED_INTERFACE( css::lang::XEventListener
, css::util::XChangesListener
),
110 DIRECT_INTERFACE ( css::util::XChangesListener
),
111 DIRECT_INTERFACE ( css::beans::XPropertySet
),
112 DIRECT_INTERFACE ( css::beans::XFastPropertySet
),
113 DIRECT_INTERFACE ( css::beans::XMultiPropertySet
)
116 DEFINE_XTYPEPROVIDER_7 ( PathSettings
,
117 css::lang::XTypeProvider
,
118 css::lang::XServiceInfo
,
119 css::lang::XEventListener
,
120 css::util::XChangesListener
,
121 css::beans::XPropertySet
,
122 css::beans::XFastPropertySet
,
123 css::beans::XMultiPropertySet
126 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE ( PathSettings
,
127 ::cppu::OWeakObject
,
128 SERVICENAME_PATHSETTINGS
,
129 IMPLEMENTATIONNAME_PATHSETTINGS
132 DEFINE_INIT_SERVICE ( PathSettings
,
135 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
136 to create a new instance of this class by our own supported service factory.
137 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
145 //-----------------------------------------------------------------------------
146 PathSettings::PathSettings( const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
147 // Init baseclasses first
148 // Attention: Don't change order of initialization!
149 // ThreadHelpBase is a struct with a lock as member. We can't use a lock as direct member!
150 // We must garant right initialization and a valid value of this to initialize other baseclasses!
152 , ::cppu::OBroadcastHelperVar
< ::cppu::OMultiTypeInterfaceContainerHelper
, ::cppu::OMultiTypeInterfaceContainerHelper::keyType
>(m_aLock
.getShareableOslMutex())
153 , ::cppu::OPropertySetHelper(*(static_cast< ::cppu::OBroadcastHelper
* >(this)))
154 , ::cppu::OWeakObject()
158 , m_bIgnoreEvents(sal_False
)
160 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::PathSettings" );
163 //-----------------------------------------------------------------------------
164 PathSettings::~PathSettings()
170 //-----------------------------------------------------------------------------
171 void SAL_CALL
PathSettings::changesOccurred(const css::util::ChangesEvent
& aEvent
)
172 throw (css::uno::RuntimeException
)
174 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::changesOccurred" );
180 sal_Int32 c
= aEvent
.Changes
.getLength();
182 sal_Bool bUpdateDescriptor
= sal_False
;
186 const css::util::ElementChange
& aChange
= aEvent
.Changes
[i
];
188 ::rtl::OUString sChanged
;
189 aChange
.Accessor
>>= sChanged
;
191 ::rtl::OUString sPath
= ::utl::extractFirstFromConfigurationPath(sChanged
);
192 if (sPath
.getLength())
194 PathSettings::EChangeOp eOp
= impl_updatePath(sPath
, sal_True
);
196 (eOp
== PathSettings::E_ADDED
) ||
197 (eOp
== PathSettings::E_REMOVED
)
199 bUpdateDescriptor
= sal_True
;
203 if (bUpdateDescriptor
)
204 impl_rebuildPropertyDescriptor();
207 //-----------------------------------------------------------------------------
208 void SAL_CALL
PathSettings::disposing(const css::lang::EventObject
& aSource
)
209 throw(css::uno::RuntimeException
)
211 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::disposing" );
213 WriteGuard
aWriteLock(m_aLock
);
215 if (aSource
.Source
== m_xCfgNew
)
222 //-----------------------------------------------------------------------------
223 void PathSettings::impl_readAll()
225 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_readAll" );
226 RTL_LOGFILE_CONTEXT(aLog
, "framework (as96863) ::PathSettings::load config (all)");
228 // TODO think about me
229 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgNew();
230 css::uno::Sequence
< ::rtl::OUString
> lPaths
= xCfg
->getElementNames();
232 sal_Int32 c
= lPaths
.getLength();
237 const ::rtl::OUString
& sPath
= lPaths
[i
];
238 impl_updatePath(sPath
, sal_False
);
241 impl_rebuildPropertyDescriptor();
244 //-----------------------------------------------------------------------------
245 // NO substitution here ! It's done outside ...
246 OUStringList
PathSettings::impl_readOldFormat(const ::rtl::OUString
& sPath
)
248 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_readOldFormat" );
249 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgOld();
250 css::uno::Any aVal
= xCfg
->getByName(sPath
);
252 ::rtl::OUString sStringVal
;
253 css::uno::Sequence
< ::rtl::OUString
> lStringListVal
;
254 OUStringList aPathVal
;
256 if (aVal
>>= sStringVal
)
258 aPathVal
.push_back(sStringVal
);
261 if (aVal
>>= lStringListVal
)
263 aPathVal
<< lStringListVal
;
269 //-----------------------------------------------------------------------------
270 // NO substitution here ! It's done outside ...
271 PathSettings::PathInfo
PathSettings::impl_readNewFormat(const ::rtl::OUString
& sPath
)
273 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgNew();
275 // get access to the "queried" path
276 css::uno::Reference
< css::container::XNameAccess
> xPath
;
277 xCfg
->getByName(sPath
) >>= xPath
;
279 PathSettings::PathInfo aPathVal
;
281 // read internal path list
282 css::uno::Reference
< css::container::XNameAccess
> xIPath
;
283 xPath
->getByName(CFGPROP_INTERNALPATHES
) >>= xIPath
;
284 aPathVal
.lInternalPaths
<< xIPath
->getElementNames();
286 // read user defined path list
287 aPathVal
.lUserPaths
<< xPath
->getByName(CFGPROP_USERPATHES
);
289 // read the writeable path
290 xPath
->getByName(CFGPROP_WRITEPATH
) >>= aPathVal
.sWritePath
;
293 xPath
->getByName(CFGPROP_ISSINGLEPATH
) >>= aPathVal
.bIsSinglePath
;
295 // analyze finalized/mandatory states
296 aPathVal
.bIsReadonly
= sal_False
;
297 css::uno::Reference
< css::beans::XProperty
> xInfo(xPath
, css::uno::UNO_QUERY
);
300 css::beans::Property aInfo
= xInfo
->getAsProperty();
301 sal_Bool bFinalized
= ((aInfo
.Attributes
& css::beans::PropertyAttribute::READONLY
) == css::beans::PropertyAttribute::READONLY
);
302 //sal_Bool bMandatory = ((aInfo.Attributes & css::beans::PropertyAttribute::REMOVEABLE) != css::beans::PropertyAttribute::REMOVEABLE);
304 // Note: Till we support finalized / mandatory on our API more in detail we handle
305 // all states simple as READONLY ! But because all realy needed pathes are "mandatory" by default
306 // we have to handle "finalized" as the real "readonly" indicator .
307 aPathVal
.bIsReadonly
= bFinalized
;
313 //-----------------------------------------------------------------------------
314 void PathSettings::impl_storePath(const PathSettings::PathInfo
& aPath
)
316 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_storePath" );
317 m_bIgnoreEvents
= sal_True
;
319 css::uno::Reference
< css::container::XNameAccess
> xCfgNew
= fa_getCfgNew();
320 css::uno::Reference
< css::container::XNameAccess
> xCfgOld
= fa_getCfgOld();
322 // try to replace path-parts with well known and uspported variables.
323 // So an office can be moved easialy to another location without loosing
324 // it's related pathes.
325 PathInfo
aResubstPath(aPath
);
326 impl_subst(aResubstPath
, sal_True
);
328 // update new configuration
329 if (! aResubstPath
.bIsSinglePath
)
331 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew
,
332 aResubstPath
.sPathName
,
334 css::uno::makeAny(aResubstPath
.lUserPaths
.getAsConstList()));
337 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew
,
338 aResubstPath
.sPathName
,
340 css::uno::makeAny(aResubstPath
.sWritePath
));
342 ::comphelper::ConfigurationHelper::flush(xCfgNew
);
344 // remove the whole path from the old configuration !
345 // Otherwise we cant make sure that the diff between new and old configuration
346 // on loading time realy represent an user setting !!!
348 // Check if the given path exists inside the old configuration.
349 // Because our new configuration knows more then the list of old pathes ... !
350 if (xCfgOld
->hasByName(aResubstPath
.sPathName
))
352 css::uno::Reference
< css::beans::XPropertySet
> xProps(xCfgOld
, css::uno::UNO_QUERY_THROW
);
353 xProps
->setPropertyValue(aResubstPath
.sPathName
, css::uno::Any());
354 ::comphelper::ConfigurationHelper::flush(xCfgOld
);
357 m_bIgnoreEvents
= sal_False
;
360 //-----------------------------------------------------------------------------
361 #ifdef MIGRATE_OLD_USER_PATHES
362 void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo
& rPath
,
363 const OUStringList
& lOld
)
365 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger
, "framework", "Ocke.Janssen@sun.com", "PathSettings::impl_mergeOldUserPaths" );
366 OUStringList::const_iterator pIt
;
367 for ( pIt
= lOld
.begin();
371 const ::rtl::OUString
& sOld
= *pIt
;
373 if (rPath
.bIsSinglePath
)
375 LOG_ASSERT2(lOld
.size()>1, "PathSettings::impl_mergeOldUserPaths()", "Single path has more then one path value inside old configuration (Common.xcu)!")
376 if (! rPath
.sWritePath
.equals(sOld
))
377 rPath
.sWritePath
= sOld
;
382 ( rPath
.lInternalPaths
.findConst(sOld
) == rPath
.lInternalPaths
.end()) &&
383 ( rPath
.lUserPaths
.findConst(sOld
) == rPath
.lUserPaths
.end() ) &&
384 (! rPath
.sWritePath
.equals(sOld
) )
386 rPath
.lUserPaths
.push_back(sOld
);
390 #endif // MIGRATE_OLD_USER_PATHES
392 //-----------------------------------------------------------------------------
393 PathSettings::EChangeOp
PathSettings::impl_updatePath(const ::rtl::OUString
& sPath
,
394 sal_Bool bNotifyListener
)
397 WriteGuard
aWriteLock(m_aLock
);
399 PathSettings::PathInfo
* pPathOld
= 0;
400 PathSettings::PathInfo
* pPathNew
= 0;
401 PathSettings::EChangeOp eOp
= PathSettings::E_UNDEFINED
;
402 PathSettings::PathInfo aPath
;
406 aPath
= impl_readNewFormat(sPath
);
407 aPath
.sPathName
= sPath
;
408 // replace all might existing variables with real values
409 // Do it before these old pathes will be compared against the
410 // new path configuration. Otherwise some striungs uses different variables ... but substitution
411 // will produce strings with same content (because some variables are redundant!)
412 impl_subst(aPath
, sal_False
);
414 catch(const css::uno::RuntimeException
& exRun
)
416 catch(const css::container::NoSuchElementException
&)
417 { eOp
= PathSettings::E_REMOVED
; }
418 catch(const css::uno::Exception
& exAny
)
421 #ifdef MIGRATE_OLD_USER_PATHES
424 // migration of old user defined values on demand
425 // can be disabled for a new major
426 OUStringList lOldVals
= impl_readOldFormat(sPath
);
427 // replace all might existing variables with real values
428 // Do it before these old pathes will be compared against the
429 // new path configuration. Otherwise some striungs uses different variables ... but substitution
430 // will produce strings with same content (because some variables are redundant!)
431 impl_subst(lOldVals
, fa_getSubstitution(), sal_False
);
432 impl_mergeOldUserPaths(aPath
, lOldVals
);
434 catch(const css::uno::RuntimeException
& exRun
)
436 // Normal(!) exceptions can be ignored!
437 // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
438 // we cant find a value for it inside the "old" configuration. So a NoSuchElementException
439 // will be normal .-)
440 catch(const css::uno::Exception
&)
442 #endif // MIGRATE_OLD_USER_PATHES
444 PathSettings::PathHash::iterator pPath
= m_lPaths
.find(sPath
);
445 if (eOp
== PathSettings::E_UNDEFINED
)
447 if (pPath
!= m_lPaths
.end())
448 eOp
= PathSettings::E_CHANGED
;
450 eOp
= PathSettings::E_ADDED
;
455 case PathSettings::E_ADDED
:
461 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
463 m_lPaths
[sPath
] = aPath
;
467 case PathSettings::E_CHANGED
:
471 pPathOld
= &(pPath
->second
);
473 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
475 m_lPaths
[sPath
] = aPath
;
479 case PathSettings::E_REMOVED
:
481 if (pPath
!= m_lPaths
.end())
485 pPathOld
= &(pPath
->second
);
487 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
489 m_lPaths
.erase(pPath
);
494 default: // to let compiler be happy
501 //-----------------------------------------------------------------------------
502 css::uno::Sequence
< sal_Int32
> PathSettings::impl_mapPathName2IDList(const ::rtl::OUString
& sPath
)
504 ::rtl::OUString sOldStyleProp
= sPath
;
505 ::rtl::OUString sInternalProp
= sPath
+POSTFIX_INTERNAL_PATHES
;
506 ::rtl::OUString sUserProp
= sPath
+POSTFIX_USER_PATHES
;
507 ::rtl::OUString sWriteProp
= sPath
+POSTFIX_WRITE_PATH
;
509 // Attention: The default set of IDs is fix and must follow these schema.
510 // Otherwhise the outside code ant work for new added properties.
512 // The outside code must fire N events for every changed property.
513 // And the knowing about packaging of variables of the structure PathInfo
514 // follow these group IDs ! But if such ID isnt in the range of [0..IDGROUP_COUNT]
515 // the outside cant determine the right group ... and cant fire the right events .-)
517 css::uno::Sequence
< sal_Int32
> lIDs(IDGROUP_COUNT
);
518 lIDs
[0] = IDGROUP_OLDSTYLE
;
519 lIDs
[1] = IDGROUP_INTERNAL_PATHES
;
520 lIDs
[2] = IDGROUP_USER_PATHES
;
521 lIDs
[3] = IDGROUP_WRITE_PATH
;
523 sal_Int32 c
= m_lPropDesc
.getLength();
527 const css::beans::Property
& rProp
= m_lPropDesc
[i
];
529 if (rProp
.Name
.equals(sOldStyleProp
))
530 lIDs
[IDGROUP_OLDSTYLE
] = rProp
.Handle
;
532 if (rProp
.Name
.equals(sInternalProp
))
533 lIDs
[IDGROUP_INTERNAL_PATHES
] = rProp
.Handle
;
535 if (rProp
.Name
.equals(sUserProp
))
536 lIDs
[IDGROUP_USER_PATHES
] = rProp
.Handle
;
538 if (rProp
.Name
.equals(sWriteProp
))
539 lIDs
[IDGROUP_WRITE_PATH
] = rProp
.Handle
;
545 //-----------------------------------------------------------------------------
546 void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp
/*eOp*/ ,
547 const ::rtl::OUString
& sPath
,
548 const PathSettings::PathInfo
* pPathOld
,
549 const PathSettings::PathInfo
* pPathNew
)
551 css::uno::Sequence
< sal_Int32
> lHandles(1);
552 css::uno::Sequence
< css::uno::Any
> lOldVals(1);
553 css::uno::Sequence
< css::uno::Any
> lNewVals(1);
555 css::uno::Sequence
< sal_Int32
> lIDs
= impl_mapPathName2IDList(sPath
);
556 sal_Int32 c
= lIDs
.getLength();
558 sal_Int32 nMaxID
= m_lPropDesc
.getLength()-1;
561 sal_Int32 nID
= lIDs
[i
];
570 switch(impl_getPropGroup(nID
))
572 case IDGROUP_OLDSTYLE
:
576 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPathOld
);
577 lOldVals
[0] <<= sVal
;
581 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPathNew
);
582 lNewVals
[0] <<= sVal
;
587 case IDGROUP_INTERNAL_PATHES
:
590 lOldVals
[0] <<= pPathOld
->lInternalPaths
.getAsConstList();
592 lNewVals
[0] <<= pPathNew
->lInternalPaths
.getAsConstList();
596 case IDGROUP_USER_PATHES
:
599 lOldVals
[0] <<= pPathOld
->lUserPaths
.getAsConstList();
601 lNewVals
[0] <<= pPathNew
->lUserPaths
.getAsConstList();
605 case IDGROUP_WRITE_PATH
:
608 lOldVals
[0] <<= pPathOld
->sWritePath
;
610 lNewVals
[0] <<= pPathNew
->sWritePath
;
615 fire(lHandles
.getArray(),
623 //-----------------------------------------------------------------------------
624 void PathSettings::impl_subst( OUStringList
& lVals
,
625 const css::uno::Reference
< css::util::XStringSubstitution
>& xSubst
,
628 OUStringList::iterator pIt
;
630 for ( pIt
= lVals
.begin();
634 const ::rtl::OUString
& sOld
= *pIt
;
635 ::rtl::OUString sNew
;
637 sNew
= xSubst
->reSubstituteVariables(sOld
);
639 sNew
= xSubst
->substituteVariables(sOld
, sal_False
);
645 //-----------------------------------------------------------------------------
646 void PathSettings::impl_subst(PathSettings::PathInfo
& aPath
,
649 css::uno::Reference
< css::util::XStringSubstitution
> xSubst
= fa_getSubstitution();
651 impl_subst(aPath
.lInternalPaths
, xSubst
, bReSubst
);
652 impl_subst(aPath
.lUserPaths
, xSubst
, bReSubst
);
654 aPath
.sWritePath
= xSubst
->reSubstituteVariables(aPath
.sWritePath
);
656 aPath
.sWritePath
= xSubst
->substituteVariables(aPath
.sWritePath
, sal_False
);
659 //-----------------------------------------------------------------------------
660 ::rtl::OUString
PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo
& rPath
) const
662 OUStringList::const_iterator pIt
;
664 lTemp
.reserve(rPath
.lInternalPaths
.size() + rPath
.lUserPaths
.size() + 1);
666 for ( pIt
= rPath
.lInternalPaths
.begin();
667 pIt
!= rPath
.lInternalPaths
.end() ;
670 lTemp
.push_back(*pIt
);
672 for ( pIt
= rPath
.lUserPaths
.begin();
673 pIt
!= rPath
.lUserPaths
.end() ;
676 lTemp
.push_back(*pIt
);
679 if (rPath
.sWritePath
.getLength() > 0)
680 lTemp
.push_back(rPath
.sWritePath
);
682 ::rtl::OUStringBuffer
sPathVal(256);
683 for ( pIt
= lTemp
.begin();
687 sPathVal
.append(*pIt
);
689 if (pIt
!= lTemp
.end())
690 sPathVal
.appendAscii(";");
693 return sPathVal
.makeStringAndClear();
696 //-----------------------------------------------------------------------------
697 OUStringList
PathSettings::impl_convertOldStyle2Path(const ::rtl::OUString
& sOldStylePath
) const
700 sal_Int32 nToken
= 0;
703 ::rtl::OUString sToken
= sOldStylePath
.getToken(0, ';', nToken
);
704 if (sToken
.getLength())
705 lList
.push_back(sToken
);
712 //-----------------------------------------------------------------------------
713 void PathSettings::impl_purgeKnownPaths(const PathSettings::PathInfo
& rPath
,
716 OUStringList::const_iterator pIt
;
717 for ( pIt
= rPath
.lInternalPaths
.begin();
718 pIt
!= rPath
.lInternalPaths
.end() ;
721 const ::rtl::OUString
& rItem
= *pIt
;
722 OUStringList::iterator pItem
= lList
.find(rItem
);
723 if (pItem
!= lList
.end())
726 for ( pIt
= rPath
.lUserPaths
.begin();
727 pIt
!= rPath
.lUserPaths
.end() ;
730 const ::rtl::OUString
& rItem
= *pIt
;
731 OUStringList::iterator pItem
= lList
.find(rItem
);
732 if (pItem
!= lList
.end())
736 OUStringList::iterator pItem
= lList
.find(rPath
.sWritePath
);
737 if (pItem
!= lList
.end())
741 //-----------------------------------------------------------------------------
742 void PathSettings::impl_rebuildPropertyDescriptor()
745 WriteGuard
aWriteLock(m_aLock
);
747 sal_Int32 c
= (sal_Int32
)m_lPaths
.size();
749 m_lPropDesc
.realloc(c
*IDGROUP_COUNT
);
751 PathHash::const_iterator pIt
;
752 for ( pIt
= m_lPaths
.begin();
753 pIt
!= m_lPaths
.end() ;
756 const PathSettings::PathInfo
& rPath
= pIt
->second
;
757 css::beans::Property
* pProp
= 0;
759 pProp
= &(m_lPropDesc
[i
]);
760 pProp
->Name
= rPath
.sPathName
;
762 pProp
->Type
= ::getCppuType((::rtl::OUString
*)0);
763 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
764 if (rPath
.bIsReadonly
)
765 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
768 pProp
= &(m_lPropDesc
[i
]);
769 pProp
->Name
= rPath
.sPathName
+POSTFIX_INTERNAL_PATHES
;
771 pProp
->Type
= ::getCppuType((css::uno::Sequence
< ::rtl::OUString
>*)0);
772 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
|
773 css::beans::PropertyAttribute::READONLY
;
776 pProp
= &(m_lPropDesc
[i
]);
777 pProp
->Name
= rPath
.sPathName
+POSTFIX_USER_PATHES
;
779 pProp
->Type
= ::getCppuType((css::uno::Sequence
< ::rtl::OUString
>*)0);
780 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
781 if (rPath
.bIsReadonly
)
782 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
785 pProp
= &(m_lPropDesc
[i
]);
786 pProp
->Name
= rPath
.sPathName
+POSTFIX_WRITE_PATH
;
788 pProp
->Type
= ::getCppuType((::rtl::OUString
*)0);
789 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
790 if (rPath
.bIsReadonly
)
791 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
797 m_pPropHelp
= new ::cppu::OPropertyArrayHelper(m_lPropDesc
, sal_False
); // false => not sorted ... must be done inside helper
803 //-----------------------------------------------------------------------------
804 css::uno::Any
PathSettings::impl_getPathValue(sal_Int32 nID
) const
806 const PathSettings::PathInfo
* pPath
= impl_getPathAccessConst(nID
);
808 throw css::container::NoSuchElementException();
811 switch(impl_getPropGroup(nID
))
813 case IDGROUP_OLDSTYLE
:
815 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPath
);
820 case IDGROUP_INTERNAL_PATHES
:
822 aVal
<<= pPath
->lInternalPaths
.getAsConstList();
826 case IDGROUP_USER_PATHES
:
828 aVal
<<= pPath
->lUserPaths
.getAsConstList();
832 case IDGROUP_WRITE_PATH
:
834 aVal
<<= pPath
->sWritePath
;
842 //-----------------------------------------------------------------------------
843 void PathSettings::impl_setPathValue( sal_Int32 nID
,
844 const css::uno::Any
& aVal
)
846 PathSettings::PathInfo
* pOrgPath
= impl_getPathAccess(nID
);
848 throw css::container::NoSuchElementException();
850 // We work on a copied path ... so we can be sure that errors during this operation
851 // does not make our internal cache invalid .-)
852 PathSettings::PathInfo
aChangePath(*pOrgPath
);
854 switch(impl_getPropGroup(nID
))
856 case IDGROUP_OLDSTYLE
:
858 ::rtl::OUString sVal
;
860 OUStringList lList
= impl_convertOldStyle2Path(sVal
);
861 impl_purgeKnownPaths(aChangePath
, lList
);
862 if (! impl_isValidPath(lList
))
863 throw css::lang::IllegalArgumentException();
865 if (aChangePath
.bIsSinglePath
)
867 LOG_ASSERT2(lList
.size()>1, "PathSettings::impl_setPathValue()", "You try to set more then path value for a defined SINGLE_PATH!")
868 if ( !lList
.empty() )
869 aChangePath
.sWritePath
= *(lList
.begin());
871 aChangePath
.sWritePath
= ::rtl::OUString();
875 OUStringList::const_iterator pIt
;
876 for ( pIt
= lList
.begin();
880 aChangePath
.lUserPaths
.push_back(*pIt
);
886 case IDGROUP_INTERNAL_PATHES
:
888 if (aChangePath
.bIsSinglePath
)
890 ::rtl::OUStringBuffer
sMsg(256);
891 sMsg
.appendAscii("The path '" );
892 sMsg
.append (aChangePath
.sPathName
);
893 sMsg
.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
894 throw css::uno::Exception(sMsg
.makeStringAndClear(),
895 static_cast< ::cppu::OWeakObject
* >(this));
900 if (! impl_isValidPath(lList
))
901 throw css::lang::IllegalArgumentException();
902 aChangePath
.lInternalPaths
= lList
;
906 case IDGROUP_USER_PATHES
:
908 if (aChangePath
.bIsSinglePath
)
910 ::rtl::OUStringBuffer
sMsg(256);
911 sMsg
.appendAscii("The path '" );
912 sMsg
.append (aChangePath
.sPathName
);
913 sMsg
.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
914 throw css::uno::Exception(sMsg
.makeStringAndClear(),
915 static_cast< ::cppu::OWeakObject
* >(this));
920 if (! impl_isValidPath(lList
))
921 throw css::lang::IllegalArgumentException();
922 aChangePath
.lUserPaths
= lList
;
926 case IDGROUP_WRITE_PATH
:
928 ::rtl::OUString sVal
;
930 if (! impl_isValidPath(sVal
))
931 throw css::lang::IllegalArgumentException();
932 aChangePath
.sWritePath
= sVal
;
937 // TODO check if path has at least one path value set
938 // At least it depends from the feature using this path, if an empty path list is allowed.
940 if (impl_isPathEmpty(aChangePath))
942 ::rtl::OUStringBuffer sMsg(256);
943 sMsg.appendAscii("The path '" );
944 sMsg.append (aChangePath.sPathName);
945 sMsg.appendAscii("' is empty now ... Not a real good idea.");
946 throw css::uno::Exception(sMsg.makeStringAndClear(),
947 static_cast< ::cppu::OWeakObject* >(this));
951 // first we should try to store the changed (copied!) path ...
952 // In case an error occure on saving time an exception is thrown ...
953 // If no exception occures we can update our internal cache (means
954 // we can overwrite pOrgPath !
955 impl_storePath(aChangePath
);
956 pOrgPath
->takeOver(aChangePath
);
959 //-----------------------------------------------------------------------------
960 sal_Bool
PathSettings::impl_isValidPath(const OUStringList
& lPath
) const
962 OUStringList::const_iterator pIt
;
963 for ( pIt
= lPath
.begin();
967 const ::rtl::OUString
& rVal
= *pIt
;
968 if (! impl_isValidPath(rVal
))
975 //-----------------------------------------------------------------------------
976 sal_Bool
PathSettings::impl_isValidPath(const ::rtl::OUString
& sPath
) const
978 return (! INetURLObject(sPath
).HasError());
981 //-----------------------------------------------------------------------------
982 ::rtl::OUString
impl_extractBaseFromPropName(const ::rtl::OUString
& sPropName
)
986 i
= sPropName
.indexOf(POSTFIX_INTERNAL_PATHES
);
988 return sPropName
.copy(0, i
);
989 i
= sPropName
.indexOf(POSTFIX_USER_PATHES
);
991 return sPropName
.copy(0, i
);
992 i
= sPropName
.indexOf(POSTFIX_WRITE_PATH
);
994 return sPropName
.copy(0, i
);
999 //-----------------------------------------------------------------------------
1000 PathSettings::PathInfo
* PathSettings::impl_getPathAccess(sal_Int32 nHandle
)
1003 ReadGuard
aReadLock(m_aLock
);
1005 if (nHandle
> (m_lPropDesc
.getLength()-1))
1008 const css::beans::Property
& rProp
= m_lPropDesc
[nHandle
];
1009 ::rtl::OUString sProp
= impl_extractBaseFromPropName(rProp
.Name
);
1010 PathSettings::PathHash::iterator rPath
= m_lPaths
.find(sProp
);
1012 if (rPath
!= m_lPaths
.end())
1013 return &(rPath
->second
);
1019 //-----------------------------------------------------------------------------
1020 const PathSettings::PathInfo
* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle
) const
1023 ReadGuard
aReadLock(m_aLock
);
1025 if (nHandle
> (m_lPropDesc
.getLength()-1))
1028 const css::beans::Property
& rProp
= m_lPropDesc
[nHandle
];
1029 ::rtl::OUString sProp
= impl_extractBaseFromPropName(rProp
.Name
);
1030 PathSettings::PathHash::const_iterator rPath
= m_lPaths
.find(sProp
);
1032 if (rPath
!= m_lPaths
.end())
1033 return &(rPath
->second
);
1039 //-----------------------------------------------------------------------------
1040 sal_Bool SAL_CALL
PathSettings::convertFastPropertyValue( css::uno::Any
& aConvertedValue
,
1041 css::uno::Any
& aOldValue
,
1043 const css::uno::Any
& aValue
)
1044 throw(css::lang::IllegalArgumentException
)
1046 // throws NoSuchElementException !
1047 css::uno::Any aCurrentVal
= impl_getPathValue(nHandle
);
1049 return PropHelper::willPropertyBeChanged(
1056 //-----------------------------------------------------------------------------
1057 void SAL_CALL
PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
,
1058 const css::uno::Any
& aValue
)
1059 throw(css::uno::Exception
)
1061 // throws NoSuchElement- and IllegalArgumentException !
1062 impl_setPathValue(nHandle
, aValue
);
1065 //-----------------------------------------------------------------------------
1066 void SAL_CALL
PathSettings::getFastPropertyValue(css::uno::Any
& aValue
,
1067 sal_Int32 nHandle
) const
1069 aValue
= impl_getPathValue(nHandle
);
1072 //-----------------------------------------------------------------------------
1073 ::cppu::IPropertyArrayHelper
& SAL_CALL
PathSettings::getInfoHelper()
1075 return *m_pPropHelp
;
1078 //-----------------------------------------------------------------------------
1079 css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
PathSettings::getPropertySetInfo()
1080 throw(css::uno::RuntimeException
)
1082 return css::uno::Reference
< css::beans::XPropertySetInfo
>(createPropertySetInfo(getInfoHelper()));
1085 //-----------------------------------------------------------------------------
1086 css::uno::Reference
< css::util::XStringSubstitution
> PathSettings::fa_getSubstitution()
1089 ReadGuard
aReadLock(m_aLock
);
1090 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1091 css::uno::Reference
< css::util::XStringSubstitution
> xSubst
= m_xSubstitution
;
1097 // create the needed substitution service.
1098 // We must replace all used variables inside readed path values.
1099 // In case we can't do so ... the whole office can't work realy.
1100 // That's why it seams to be OK to throw a RuntimeException then.
1101 xSubst
= css::uno::Reference
< css::util::XStringSubstitution
>(
1102 xSMGR
->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES
),
1103 css::uno::UNO_QUERY_THROW
);
1106 WriteGuard
aWriteLock(m_aLock
);
1107 m_xSubstitution
= xSubst
;
1108 aWriteLock
.unlock();
1114 //-----------------------------------------------------------------------------
1115 css::uno::Reference
< css::container::XNameAccess
> PathSettings::fa_getCfgOld()
1117 const static ::rtl::OUString CFG_NODE_OLD
= ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/Path/Current");
1120 ReadGuard
aReadLock(m_aLock
);
1121 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1122 css::uno::Reference
< css::container::XNameAccess
> xCfg
= m_xCfgOld
;
1128 xCfg
= css::uno::Reference
< css::container::XNameAccess
>(
1129 ::comphelper::ConfigurationHelper::openConfig(
1132 ::comphelper::ConfigurationHelper::E_STANDARD
), // not readonly! Somtimes we need write access there !!!
1133 css::uno::UNO_QUERY_THROW
);
1136 WriteGuard
aWriteLock(m_aLock
);
1138 aWriteLock
.unlock();
1144 //-----------------------------------------------------------------------------
1145 css::uno::Reference
< css::container::XNameAccess
> PathSettings::fa_getCfgNew()
1147 const static ::rtl::OUString CFG_NODE_NEW
= ::rtl::OUString::createFromAscii("org.openoffice.Office.Paths/Paths");
1150 ReadGuard
aReadLock(m_aLock
);
1151 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1152 css::uno::Reference
< css::container::XNameAccess
> xCfg
= m_xCfgNew
;
1158 xCfg
= css::uno::Reference
< css::container::XNameAccess
>(
1159 ::comphelper::ConfigurationHelper::openConfig(
1162 ::comphelper::ConfigurationHelper::E_STANDARD
),
1163 css::uno::UNO_QUERY_THROW
);
1166 WriteGuard
aWriteLock(m_aLock
);
1168 aWriteLock
.unlock();
1170 css::uno::Reference
< css::util::XChangesNotifier
> xBroadcaster(xCfg
, css::uno::UNO_QUERY_THROW
);
1171 xBroadcaster
->addChangesListener(static_cast< css::util::XChangesListener
* >(this));
1177 } // namespace framework