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
)
162 //-----------------------------------------------------------------------------
163 PathSettings::~PathSettings()
169 //-----------------------------------------------------------------------------
170 void SAL_CALL
PathSettings::changesOccurred(const css::util::ChangesEvent
& aEvent
)
171 throw (css::uno::RuntimeException
)
178 sal_Int32 c
= aEvent
.Changes
.getLength();
180 sal_Bool bUpdateDescriptor
= sal_False
;
184 const css::util::ElementChange
& aChange
= aEvent
.Changes
[i
];
186 ::rtl::OUString sChanged
;
187 aChange
.Accessor
>>= sChanged
;
189 ::rtl::OUString sPath
= ::utl::extractFirstFromConfigurationPath(sChanged
);
190 if (sPath
.getLength())
192 PathSettings::EChangeOp eOp
= impl_updatePath(sPath
, sal_True
);
194 (eOp
== PathSettings::E_ADDED
) ||
195 (eOp
== PathSettings::E_REMOVED
)
197 bUpdateDescriptor
= sal_True
;
201 if (bUpdateDescriptor
)
202 impl_rebuildPropertyDescriptor();
205 //-----------------------------------------------------------------------------
206 void SAL_CALL
PathSettings::disposing(const css::lang::EventObject
& aSource
)
207 throw(css::uno::RuntimeException
)
210 WriteGuard
aWriteLock(m_aLock
);
212 if (aSource
.Source
== m_xCfgNew
)
219 //-----------------------------------------------------------------------------
220 void PathSettings::impl_readAll()
222 RTL_LOGFILE_CONTEXT(aLog
, "framework (as96863) ::PathSettings::load config (all)");
224 // TODO think about me
225 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgNew();
226 css::uno::Sequence
< ::rtl::OUString
> lPaths
= xCfg
->getElementNames();
228 sal_Int32 c
= lPaths
.getLength();
233 const ::rtl::OUString
& sPath
= lPaths
[i
];
234 impl_updatePath(sPath
, sal_False
);
237 impl_rebuildPropertyDescriptor();
240 //-----------------------------------------------------------------------------
241 // NO substitution here ! It's done outside ...
242 OUStringList
PathSettings::impl_readOldFormat(const ::rtl::OUString
& sPath
)
244 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgOld();
245 css::uno::Any aVal
= xCfg
->getByName(sPath
);
247 ::rtl::OUString sStringVal
;
248 css::uno::Sequence
< ::rtl::OUString
> lStringListVal
;
249 OUStringList aPathVal
;
251 if (aVal
>>= sStringVal
)
253 aPathVal
.push_back(sStringVal
);
256 if (aVal
>>= lStringListVal
)
258 aPathVal
<< lStringListVal
;
264 //-----------------------------------------------------------------------------
265 // NO substitution here ! It's done outside ...
266 PathSettings::PathInfo
PathSettings::impl_readNewFormat(const ::rtl::OUString
& sPath
)
268 css::uno::Reference
< css::container::XNameAccess
> xCfg
= fa_getCfgNew();
270 // get access to the "queried" path
271 css::uno::Reference
< css::container::XNameAccess
> xPath
;
272 xCfg
->getByName(sPath
) >>= xPath
;
274 PathSettings::PathInfo aPathVal
;
276 // read internal path list
277 css::uno::Reference
< css::container::XNameAccess
> xIPath
;
278 xPath
->getByName(CFGPROP_INTERNALPATHES
) >>= xIPath
;
279 aPathVal
.lInternalPaths
<< xIPath
->getElementNames();
281 // read user defined path list
282 aPathVal
.lUserPaths
<< xPath
->getByName(CFGPROP_USERPATHES
);
284 // read the writeable path
285 xPath
->getByName(CFGPROP_WRITEPATH
) >>= aPathVal
.sWritePath
;
288 xPath
->getByName(CFGPROP_ISSINGLEPATH
) >>= aPathVal
.bIsSinglePath
;
290 // analyze finalized/mandatory states
291 aPathVal
.bIsReadonly
= sal_False
;
292 css::uno::Reference
< css::beans::XProperty
> xInfo(xPath
, css::uno::UNO_QUERY
);
295 css::beans::Property aInfo
= xInfo
->getAsProperty();
296 sal_Bool bFinalized
= ((aInfo
.Attributes
& css::beans::PropertyAttribute::READONLY
) == css::beans::PropertyAttribute::READONLY
);
297 //sal_Bool bMandatory = ((aInfo.Attributes & css::beans::PropertyAttribute::REMOVEABLE) != css::beans::PropertyAttribute::REMOVEABLE);
299 // Note: Till we support finalized / mandatory on our API more in detail we handle
300 // all states simple as READONLY ! But because all realy needed pathes are "mandatory" by default
301 // we have to handle "finalized" as the real "readonly" indicator .
302 aPathVal
.bIsReadonly
= bFinalized
;
308 //-----------------------------------------------------------------------------
309 void PathSettings::impl_storePath(const PathSettings::PathInfo
& aPath
)
311 m_bIgnoreEvents
= sal_True
;
313 css::uno::Reference
< css::container::XNameAccess
> xCfgNew
= fa_getCfgNew();
314 css::uno::Reference
< css::container::XNameAccess
> xCfgOld
= fa_getCfgOld();
316 // try to replace path-parts with well known and uspported variables.
317 // So an office can be moved easialy to another location without loosing
318 // it's related pathes.
319 PathInfo
aResubstPath(aPath
);
320 impl_subst(aResubstPath
, sal_True
);
322 // update new configuration
323 if (! aResubstPath
.bIsSinglePath
)
325 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew
,
326 aResubstPath
.sPathName
,
328 css::uno::makeAny(aResubstPath
.lUserPaths
.getAsConstList()));
331 ::comphelper::ConfigurationHelper::writeRelativeKey(xCfgNew
,
332 aResubstPath
.sPathName
,
334 css::uno::makeAny(aResubstPath
.sWritePath
));
336 ::comphelper::ConfigurationHelper::flush(xCfgNew
);
338 // remove the whole path from the old configuration !
339 // Otherwise we cant make sure that the diff between new and old configuration
340 // on loading time realy represent an user setting !!!
342 // Check if the given path exists inside the old configuration.
343 // Because our new configuration knows more then the list of old pathes ... !
344 if (xCfgOld
->hasByName(aResubstPath
.sPathName
))
346 css::uno::Reference
< css::beans::XPropertySet
> xProps(xCfgOld
, css::uno::UNO_QUERY_THROW
);
347 xProps
->setPropertyValue(aResubstPath
.sPathName
, css::uno::Any());
348 ::comphelper::ConfigurationHelper::flush(xCfgOld
);
351 m_bIgnoreEvents
= sal_False
;
354 //-----------------------------------------------------------------------------
355 #ifdef MIGRATE_OLD_USER_PATHES
356 void PathSettings::impl_mergeOldUserPaths( PathSettings::PathInfo
& rPath
,
357 const OUStringList
& lOld
)
359 OUStringList::const_iterator pIt
;
360 for ( pIt
= lOld
.begin();
364 const ::rtl::OUString
& sOld
= *pIt
;
366 if (rPath
.bIsSinglePath
)
368 LOG_ASSERT2(lOld
.size()>1, "PathSettings::impl_mergeOldUserPaths()", "Single path has more then one path value inside old configuration (Common.xcu)!")
369 if (! rPath
.sWritePath
.equals(sOld
))
370 rPath
.sWritePath
= sOld
;
375 ( rPath
.lInternalPaths
.findConst(sOld
) == rPath
.lInternalPaths
.end()) &&
376 ( rPath
.lUserPaths
.findConst(sOld
) == rPath
.lUserPaths
.end() ) &&
377 (! rPath
.sWritePath
.equals(sOld
) )
379 rPath
.lUserPaths
.push_back(sOld
);
383 #endif // MIGRATE_OLD_USER_PATHES
385 //-----------------------------------------------------------------------------
386 PathSettings::EChangeOp
PathSettings::impl_updatePath(const ::rtl::OUString
& sPath
,
387 sal_Bool bNotifyListener
)
390 WriteGuard
aWriteLock(m_aLock
);
392 PathSettings::PathInfo
* pPathOld
= 0;
393 PathSettings::PathInfo
* pPathNew
= 0;
394 PathSettings::EChangeOp eOp
= PathSettings::E_UNDEFINED
;
395 PathSettings::PathInfo aPath
;
399 aPath
= impl_readNewFormat(sPath
);
400 aPath
.sPathName
= sPath
;
401 // replace all might existing variables with real values
402 // Do it before these old pathes will be compared against the
403 // new path configuration. Otherwise some striungs uses different variables ... but substitution
404 // will produce strings with same content (because some variables are redundant!)
405 impl_subst(aPath
, sal_False
);
407 catch(const css::uno::RuntimeException
& exRun
)
409 catch(const css::container::NoSuchElementException
&)
410 { eOp
= PathSettings::E_REMOVED
; }
411 catch(const css::uno::Exception
& exAny
)
414 #ifdef MIGRATE_OLD_USER_PATHES
417 // migration of old user defined values on demand
418 // can be disabled for a new major
419 OUStringList lOldVals
= impl_readOldFormat(sPath
);
420 // replace all might existing variables with real values
421 // Do it before these old pathes will be compared against the
422 // new path configuration. Otherwise some striungs uses different variables ... but substitution
423 // will produce strings with same content (because some variables are redundant!)
424 impl_subst(lOldVals
, fa_getSubstitution(), sal_False
);
425 impl_mergeOldUserPaths(aPath
, lOldVals
);
427 catch(const css::uno::RuntimeException
& exRun
)
429 // Normal(!) exceptions can be ignored!
430 // E.g. in case an addon installs a new path, which was not well known for an OOo 1.x installation
431 // we cant find a value for it inside the "old" configuration. So a NoSuchElementException
432 // will be normal .-)
433 catch(const css::uno::Exception
&)
435 #endif // MIGRATE_OLD_USER_PATHES
437 PathSettings::PathHash::iterator pPath
= m_lPaths
.find(sPath
);
438 if (eOp
== PathSettings::E_UNDEFINED
)
440 if (pPath
!= m_lPaths
.end())
441 eOp
= PathSettings::E_CHANGED
;
443 eOp
= PathSettings::E_ADDED
;
448 case PathSettings::E_ADDED
:
454 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
456 m_lPaths
[sPath
] = aPath
;
460 case PathSettings::E_CHANGED
:
464 pPathOld
= &(pPath
->second
);
466 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
468 m_lPaths
[sPath
] = aPath
;
472 case PathSettings::E_REMOVED
:
474 if (pPath
!= m_lPaths
.end())
478 pPathOld
= &(pPath
->second
);
480 impl_notifyPropListener(eOp
, sPath
, pPathOld
, pPathNew
);
482 m_lPaths
.erase(pPath
);
487 default: // to let compiler be happy
494 //-----------------------------------------------------------------------------
495 css::uno::Sequence
< sal_Int32
> PathSettings::impl_mapPathName2IDList(const ::rtl::OUString
& sPath
)
497 ::rtl::OUString sOldStyleProp
= sPath
;
498 ::rtl::OUString sInternalProp
= sPath
+POSTFIX_INTERNAL_PATHES
;
499 ::rtl::OUString sUserProp
= sPath
+POSTFIX_USER_PATHES
;
500 ::rtl::OUString sWriteProp
= sPath
+POSTFIX_WRITE_PATH
;
502 // Attention: The default set of IDs is fix and must follow these schema.
503 // Otherwhise the outside code ant work for new added properties.
505 // The outside code must fire N events for every changed property.
506 // And the knowing about packaging of variables of the structure PathInfo
507 // follow these group IDs ! But if such ID isnt in the range of [0..IDGROUP_COUNT]
508 // the outside cant determine the right group ... and cant fire the right events .-)
510 css::uno::Sequence
< sal_Int32
> lIDs(IDGROUP_COUNT
);
511 lIDs
[0] = IDGROUP_OLDSTYLE
;
512 lIDs
[1] = IDGROUP_INTERNAL_PATHES
;
513 lIDs
[2] = IDGROUP_USER_PATHES
;
514 lIDs
[3] = IDGROUP_WRITE_PATH
;
516 sal_Int32 c
= m_lPropDesc
.getLength();
520 const css::beans::Property
& rProp
= m_lPropDesc
[i
];
522 if (rProp
.Name
.equals(sOldStyleProp
))
523 lIDs
[IDGROUP_OLDSTYLE
] = rProp
.Handle
;
525 if (rProp
.Name
.equals(sInternalProp
))
526 lIDs
[IDGROUP_INTERNAL_PATHES
] = rProp
.Handle
;
528 if (rProp
.Name
.equals(sUserProp
))
529 lIDs
[IDGROUP_USER_PATHES
] = rProp
.Handle
;
531 if (rProp
.Name
.equals(sWriteProp
))
532 lIDs
[IDGROUP_WRITE_PATH
] = rProp
.Handle
;
538 //-----------------------------------------------------------------------------
539 void PathSettings::impl_notifyPropListener( PathSettings::EChangeOp
/*eOp*/ ,
540 const ::rtl::OUString
& sPath
,
541 const PathSettings::PathInfo
* pPathOld
,
542 const PathSettings::PathInfo
* pPathNew
)
544 css::uno::Sequence
< sal_Int32
> lHandles(1);
545 css::uno::Sequence
< css::uno::Any
> lOldVals(1);
546 css::uno::Sequence
< css::uno::Any
> lNewVals(1);
548 css::uno::Sequence
< sal_Int32
> lIDs
= impl_mapPathName2IDList(sPath
);
549 sal_Int32 c
= lIDs
.getLength();
551 sal_Int32 nMaxID
= m_lPropDesc
.getLength()-1;
554 sal_Int32 nID
= lIDs
[i
];
563 switch(impl_getPropGroup(nID
))
565 case IDGROUP_OLDSTYLE
:
569 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPathOld
);
570 lOldVals
[0] <<= sVal
;
574 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPathNew
);
575 lNewVals
[0] <<= sVal
;
580 case IDGROUP_INTERNAL_PATHES
:
583 lOldVals
[0] <<= pPathOld
->lInternalPaths
.getAsConstList();
585 lNewVals
[0] <<= pPathNew
->lInternalPaths
.getAsConstList();
589 case IDGROUP_USER_PATHES
:
592 lOldVals
[0] <<= pPathOld
->lUserPaths
.getAsConstList();
594 lNewVals
[0] <<= pPathNew
->lUserPaths
.getAsConstList();
598 case IDGROUP_WRITE_PATH
:
601 lOldVals
[0] <<= pPathOld
->sWritePath
;
603 lNewVals
[0] <<= pPathNew
->sWritePath
;
608 fire(lHandles
.getArray(),
616 //-----------------------------------------------------------------------------
617 void PathSettings::impl_subst( OUStringList
& lVals
,
618 const css::uno::Reference
< css::util::XStringSubstitution
>& xSubst
,
621 OUStringList::iterator pIt
;
623 for ( pIt
= lVals
.begin();
627 const ::rtl::OUString
& sOld
= *pIt
;
628 ::rtl::OUString sNew
;
630 sNew
= xSubst
->reSubstituteVariables(sOld
);
632 sNew
= xSubst
->substituteVariables(sOld
, sal_False
);
638 //-----------------------------------------------------------------------------
639 void PathSettings::impl_subst(PathSettings::PathInfo
& aPath
,
642 css::uno::Reference
< css::util::XStringSubstitution
> xSubst
= fa_getSubstitution();
644 impl_subst(aPath
.lInternalPaths
, xSubst
, bReSubst
);
645 impl_subst(aPath
.lUserPaths
, xSubst
, bReSubst
);
647 aPath
.sWritePath
= xSubst
->reSubstituteVariables(aPath
.sWritePath
);
649 aPath
.sWritePath
= xSubst
->substituteVariables(aPath
.sWritePath
, sal_False
);
652 //-----------------------------------------------------------------------------
653 ::rtl::OUString
PathSettings::impl_convertPath2OldStyle(const PathSettings::PathInfo
& rPath
) const
655 OUStringList::const_iterator pIt
;
658 for ( pIt
= rPath
.lInternalPaths
.begin();
659 pIt
!= rPath
.lInternalPaths
.end() ;
662 lTemp
.push_back(*pIt
);
664 for ( pIt
= rPath
.lUserPaths
.begin();
665 pIt
!= rPath
.lUserPaths
.end() ;
668 lTemp
.push_back(*pIt
);
671 if (rPath
.sWritePath
.getLength() > 0)
672 lTemp
.push_back(rPath
.sWritePath
);
674 ::rtl::OUStringBuffer
sPathVal(256);
675 for ( pIt
= lTemp
.begin();
679 sPathVal
.append(*pIt
);
681 if (pIt
!= lTemp
.end())
682 sPathVal
.appendAscii(";");
685 return sPathVal
.makeStringAndClear();
688 //-----------------------------------------------------------------------------
689 OUStringList
PathSettings::impl_convertOldStyle2Path(const ::rtl::OUString
& sOldStylePath
) const
692 sal_Int32 nToken
= 0;
695 ::rtl::OUString sToken
= sOldStylePath
.getToken(0, ';', nToken
);
696 if (sToken
.getLength())
697 lList
.push_back(sToken
);
704 //-----------------------------------------------------------------------------
705 void PathSettings::impl_purgeKnownPaths(const PathSettings::PathInfo
& rPath
,
708 OUStringList::const_iterator pIt
;
709 for ( pIt
= rPath
.lInternalPaths
.begin();
710 pIt
!= rPath
.lInternalPaths
.end() ;
713 const ::rtl::OUString
& rItem
= *pIt
;
714 OUStringList::iterator pItem
= lList
.find(rItem
);
715 if (pItem
!= lList
.end())
718 for ( pIt
= rPath
.lUserPaths
.begin();
719 pIt
!= rPath
.lUserPaths
.end() ;
722 const ::rtl::OUString
& rItem
= *pIt
;
723 OUStringList::iterator pItem
= lList
.find(rItem
);
724 if (pItem
!= lList
.end())
728 OUStringList::iterator pItem
= lList
.find(rPath
.sWritePath
);
729 if (pItem
!= lList
.end())
733 //-----------------------------------------------------------------------------
734 void PathSettings::impl_rebuildPropertyDescriptor()
737 WriteGuard
aWriteLock(m_aLock
);
739 sal_Int32 c
= (sal_Int32
)m_lPaths
.size();
741 m_lPropDesc
.realloc(c
*IDGROUP_COUNT
);
743 PathHash::const_iterator pIt
;
744 for ( pIt
= m_lPaths
.begin();
745 pIt
!= m_lPaths
.end() ;
748 const PathSettings::PathInfo
& rPath
= pIt
->second
;
749 css::beans::Property
* pProp
= 0;
751 pProp
= &(m_lPropDesc
[i
]);
752 pProp
->Name
= rPath
.sPathName
;
754 pProp
->Type
= ::getCppuType((::rtl::OUString
*)0);
755 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
756 if (rPath
.bIsReadonly
)
757 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
760 pProp
= &(m_lPropDesc
[i
]);
761 pProp
->Name
= rPath
.sPathName
+POSTFIX_INTERNAL_PATHES
;
763 pProp
->Type
= ::getCppuType((css::uno::Sequence
< ::rtl::OUString
>*)0);
764 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
|
765 css::beans::PropertyAttribute::READONLY
;
768 pProp
= &(m_lPropDesc
[i
]);
769 pProp
->Name
= rPath
.sPathName
+POSTFIX_USER_PATHES
;
771 pProp
->Type
= ::getCppuType((css::uno::Sequence
< ::rtl::OUString
>*)0);
772 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
773 if (rPath
.bIsReadonly
)
774 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
777 pProp
= &(m_lPropDesc
[i
]);
778 pProp
->Name
= rPath
.sPathName
+POSTFIX_WRITE_PATH
;
780 pProp
->Type
= ::getCppuType((::rtl::OUString
*)0);
781 pProp
->Attributes
= css::beans::PropertyAttribute::BOUND
;
782 if (rPath
.bIsReadonly
)
783 pProp
->Attributes
|= css::beans::PropertyAttribute::READONLY
;
789 m_pPropHelp
= new ::cppu::OPropertyArrayHelper(m_lPropDesc
, sal_False
); // false => not sorted ... must be done inside helper
795 //-----------------------------------------------------------------------------
796 css::uno::Any
PathSettings::impl_getPathValue(sal_Int32 nID
) const
798 const PathSettings::PathInfo
* pPath
= impl_getPathAccessConst(nID
);
800 throw css::container::NoSuchElementException();
803 switch(impl_getPropGroup(nID
))
805 case IDGROUP_OLDSTYLE
:
807 ::rtl::OUString sVal
= impl_convertPath2OldStyle(*pPath
);
812 case IDGROUP_INTERNAL_PATHES
:
814 aVal
<<= pPath
->lInternalPaths
.getAsConstList();
818 case IDGROUP_USER_PATHES
:
820 aVal
<<= pPath
->lUserPaths
.getAsConstList();
824 case IDGROUP_WRITE_PATH
:
826 aVal
<<= pPath
->sWritePath
;
834 //-----------------------------------------------------------------------------
835 void PathSettings::impl_setPathValue( sal_Int32 nID
,
836 const css::uno::Any
& aVal
)
838 PathSettings::PathInfo
* pOrgPath
= impl_getPathAccess(nID
);
840 throw css::container::NoSuchElementException();
842 // We work on a copied path ... so we can be sure that errors during this operation
843 // does not make our internal cache invalid .-)
844 PathSettings::PathInfo
aChangePath(*pOrgPath
);
846 switch(impl_getPropGroup(nID
))
848 case IDGROUP_OLDSTYLE
:
850 ::rtl::OUString sVal
;
852 OUStringList lList
= impl_convertOldStyle2Path(sVal
);
853 impl_purgeKnownPaths(aChangePath
, lList
);
854 if (! impl_isValidPath(lList
))
855 throw css::lang::IllegalArgumentException();
857 if (aChangePath
.bIsSinglePath
)
859 LOG_ASSERT2(lList
.size()>1, "PathSettings::impl_setPathValue()", "You try to set more then path value for a defined SINGLE_PATH!")
861 aChangePath
.sWritePath
= *(lList
.begin());
863 aChangePath
.sWritePath
= ::rtl::OUString();
867 OUStringList::const_iterator pIt
;
868 for ( pIt
= lList
.begin();
872 aChangePath
.lUserPaths
.push_back(*pIt
);
878 case IDGROUP_INTERNAL_PATHES
:
880 if (aChangePath
.bIsSinglePath
)
882 ::rtl::OUStringBuffer
sMsg(256);
883 sMsg
.appendAscii("The path '" );
884 sMsg
.append (aChangePath
.sPathName
);
885 sMsg
.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
886 throw css::uno::Exception(sMsg
.makeStringAndClear(),
887 static_cast< ::cppu::OWeakObject
* >(this));
892 if (! impl_isValidPath(lList
))
893 throw css::lang::IllegalArgumentException();
894 aChangePath
.lInternalPaths
= lList
;
898 case IDGROUP_USER_PATHES
:
900 if (aChangePath
.bIsSinglePath
)
902 ::rtl::OUStringBuffer
sMsg(256);
903 sMsg
.appendAscii("The path '" );
904 sMsg
.append (aChangePath
.sPathName
);
905 sMsg
.appendAscii("' is defined as SINGLE_PATH. It's sub set of internal pathes cant be set.");
906 throw css::uno::Exception(sMsg
.makeStringAndClear(),
907 static_cast< ::cppu::OWeakObject
* >(this));
912 if (! impl_isValidPath(lList
))
913 throw css::lang::IllegalArgumentException();
914 aChangePath
.lUserPaths
= lList
;
918 case IDGROUP_WRITE_PATH
:
920 ::rtl::OUString sVal
;
922 if (! impl_isValidPath(sVal
))
923 throw css::lang::IllegalArgumentException();
924 aChangePath
.sWritePath
= sVal
;
929 // TODO check if path has at least one path value set
930 // At least it depends from the feature using this path, if an empty path list is allowed.
932 if (impl_isPathEmpty(aChangePath))
934 ::rtl::OUStringBuffer sMsg(256);
935 sMsg.appendAscii("The path '" );
936 sMsg.append (aChangePath.sPathName);
937 sMsg.appendAscii("' is empty now ... Not a real good idea.");
938 throw css::uno::Exception(sMsg.makeStringAndClear(),
939 static_cast< ::cppu::OWeakObject* >(this));
943 // first we should try to store the changed (copied!) path ...
944 // In case an error occure on saving time an exception is thrown ...
945 // If no exception occures we can update our internal cache (means
946 // we can overwrite pOrgPath !
947 impl_storePath(aChangePath
);
948 pOrgPath
->takeOver(aChangePath
);
951 //-----------------------------------------------------------------------------
952 sal_Bool
PathSettings::impl_isValidPath(const OUStringList
& lPath
) const
954 OUStringList::const_iterator pIt
;
955 for ( pIt
= lPath
.begin();
959 const ::rtl::OUString
& rVal
= *pIt
;
960 if (! impl_isValidPath(rVal
))
967 //-----------------------------------------------------------------------------
968 sal_Bool
PathSettings::impl_isValidPath(const ::rtl::OUString
& sPath
) const
970 return (! INetURLObject(sPath
).HasError());
973 //-----------------------------------------------------------------------------
974 ::rtl::OUString
impl_extractBaseFromPropName(const ::rtl::OUString
& sPropName
)
978 i
= sPropName
.indexOf(POSTFIX_INTERNAL_PATHES
);
980 return sPropName
.copy(0, i
);
981 i
= sPropName
.indexOf(POSTFIX_USER_PATHES
);
983 return sPropName
.copy(0, i
);
984 i
= sPropName
.indexOf(POSTFIX_WRITE_PATH
);
986 return sPropName
.copy(0, i
);
991 //-----------------------------------------------------------------------------
992 PathSettings::PathInfo
* PathSettings::impl_getPathAccess(sal_Int32 nHandle
)
995 ReadGuard
aReadLock(m_aLock
);
997 if (nHandle
> (m_lPropDesc
.getLength()-1))
1000 const css::beans::Property
& rProp
= m_lPropDesc
[nHandle
];
1001 ::rtl::OUString sProp
= impl_extractBaseFromPropName(rProp
.Name
);
1002 PathSettings::PathHash::iterator rPath
= m_lPaths
.find(sProp
);
1004 if (rPath
!= m_lPaths
.end())
1005 return &(rPath
->second
);
1011 //-----------------------------------------------------------------------------
1012 const PathSettings::PathInfo
* PathSettings::impl_getPathAccessConst(sal_Int32 nHandle
) const
1015 ReadGuard
aReadLock(m_aLock
);
1017 if (nHandle
> (m_lPropDesc
.getLength()-1))
1020 const css::beans::Property
& rProp
= m_lPropDesc
[nHandle
];
1021 ::rtl::OUString sProp
= impl_extractBaseFromPropName(rProp
.Name
);
1022 PathSettings::PathHash::const_iterator rPath
= m_lPaths
.find(sProp
);
1024 if (rPath
!= m_lPaths
.end())
1025 return &(rPath
->second
);
1031 //-----------------------------------------------------------------------------
1032 sal_Bool SAL_CALL
PathSettings::convertFastPropertyValue( css::uno::Any
& aConvertedValue
,
1033 css::uno::Any
& aOldValue
,
1035 const css::uno::Any
& aValue
)
1036 throw(css::lang::IllegalArgumentException
)
1038 // throws NoSuchElementException !
1039 css::uno::Any aCurrentVal
= impl_getPathValue(nHandle
);
1041 return PropHelper::willPropertyBeChanged(
1048 //-----------------------------------------------------------------------------
1049 void SAL_CALL
PathSettings::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
,
1050 const css::uno::Any
& aValue
)
1051 throw(css::uno::Exception
)
1053 // throws NoSuchElement- and IllegalArgumentException !
1054 impl_setPathValue(nHandle
, aValue
);
1057 //-----------------------------------------------------------------------------
1058 void SAL_CALL
PathSettings::getFastPropertyValue(css::uno::Any
& aValue
,
1059 sal_Int32 nHandle
) const
1061 aValue
= impl_getPathValue(nHandle
);
1064 //-----------------------------------------------------------------------------
1065 ::cppu::IPropertyArrayHelper
& SAL_CALL
PathSettings::getInfoHelper()
1067 return *m_pPropHelp
;
1070 //-----------------------------------------------------------------------------
1071 css::uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
PathSettings::getPropertySetInfo()
1072 throw(css::uno::RuntimeException
)
1074 return css::uno::Reference
< css::beans::XPropertySetInfo
>(createPropertySetInfo(getInfoHelper()));
1077 //-----------------------------------------------------------------------------
1078 css::uno::Reference
< css::util::XStringSubstitution
> PathSettings::fa_getSubstitution()
1081 ReadGuard
aReadLock(m_aLock
);
1082 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1083 css::uno::Reference
< css::util::XStringSubstitution
> xSubst
= m_xSubstitution
;
1089 // create the needed substitution service.
1090 // We must replace all used variables inside readed path values.
1091 // In case we can't do so ... the whole office can't work realy.
1092 // That's why it seams to be OK to throw a RuntimeException then.
1093 xSubst
= css::uno::Reference
< css::util::XStringSubstitution
>(
1094 xSMGR
->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES
),
1095 css::uno::UNO_QUERY_THROW
);
1098 WriteGuard
aWriteLock(m_aLock
);
1099 m_xSubstitution
= xSubst
;
1100 aWriteLock
.unlock();
1106 //-----------------------------------------------------------------------------
1107 css::uno::Reference
< css::container::XNameAccess
> PathSettings::fa_getCfgOld()
1109 const static ::rtl::OUString CFG_NODE_OLD
= ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/Path/Current");
1112 ReadGuard
aReadLock(m_aLock
);
1113 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1114 css::uno::Reference
< css::container::XNameAccess
> xCfg
= m_xCfgOld
;
1120 xCfg
= css::uno::Reference
< css::container::XNameAccess
>(
1121 ::comphelper::ConfigurationHelper::openConfig(
1124 ::comphelper::ConfigurationHelper::E_STANDARD
), // not readonly! Somtimes we need write access there !!!
1125 css::uno::UNO_QUERY_THROW
);
1128 WriteGuard
aWriteLock(m_aLock
);
1130 aWriteLock
.unlock();
1136 //-----------------------------------------------------------------------------
1137 css::uno::Reference
< css::container::XNameAccess
> PathSettings::fa_getCfgNew()
1139 const static ::rtl::OUString CFG_NODE_NEW
= ::rtl::OUString::createFromAscii("org.openoffice.Office.Paths/Paths");
1142 ReadGuard
aReadLock(m_aLock
);
1143 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
1144 css::uno::Reference
< css::container::XNameAccess
> xCfg
= m_xCfgNew
;
1150 xCfg
= css::uno::Reference
< css::container::XNameAccess
>(
1151 ::comphelper::ConfigurationHelper::openConfig(
1154 ::comphelper::ConfigurationHelper::E_STANDARD
),
1155 css::uno::UNO_QUERY_THROW
);
1158 WriteGuard
aWriteLock(m_aLock
);
1160 aWriteLock
.unlock();
1162 css::uno::Reference
< css::util::XChangesNotifier
> xBroadcaster(xCfg
, css::uno::UNO_QUERY_THROW
);
1163 xBroadcaster
->addChangesListener(static_cast< css::util::XChangesListener
* >(this));
1169 } // namespace framework