1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_unotools.hxx" 30*cdf0e10cSrcweir #include "unotools/configitem.hxx" 31*cdf0e10cSrcweir #include "unotools/configmgr.hxx" 32*cdf0e10cSrcweir #include "unotools/configpathes.hxx" 33*cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 34*cdf0e10cSrcweir #include <com/sun/star/beans/XMultiPropertySet.hpp> 35*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 36*cdf0e10cSrcweir #include <com/sun/star/util/XChangesListener.hpp> 37*cdf0e10cSrcweir #include <com/sun/star/util/XChangesNotifier.hpp> 38*cdf0e10cSrcweir #include <com/sun/star/container/XHierarchicalNameAccess.hpp> 39*cdf0e10cSrcweir #include <com/sun/star/container/XHierarchicalName.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/configuration/XTemplateContainer.hpp> 41*cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp> 42*cdf0e10cSrcweir #include <com/sun/star/lang/XSingleServiceFactory.hpp> 43*cdf0e10cSrcweir #include <com/sun/star/lang/XServiceInfo.hpp> 44*cdf0e10cSrcweir #include <com/sun/star/awt/XRequestCallback.hpp> 45*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/util/XStringEscape.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/util/XChangesBatch.hpp> 49*cdf0e10cSrcweir #include <osl/diagnose.h> 50*cdf0e10cSrcweir #include <tools/solarmutex.hxx> 51*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir using namespace utl; 54*cdf0e10cSrcweir using rtl::OUString; 55*cdf0e10cSrcweir using rtl::OString; 56*cdf0e10cSrcweir using namespace com::sun::star::uno; 57*cdf0e10cSrcweir using namespace com::sun::star::util; 58*cdf0e10cSrcweir using namespace com::sun::star::lang; 59*cdf0e10cSrcweir using namespace com::sun::star::beans; 60*cdf0e10cSrcweir using namespace com::sun::star::container; 61*cdf0e10cSrcweir using namespace com::sun::star::configuration; 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir #define C2U(cChar) OUString::createFromAscii(cChar) 64*cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx> // helper for implementations 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir #ifdef DBG_UTIL 67*cdf0e10cSrcweir inline void lcl_CFG_DBG_EXCEPTION(const sal_Char* cText, const Exception& rEx) 68*cdf0e10cSrcweir { 69*cdf0e10cSrcweir OString sMsg(cText); 70*cdf0e10cSrcweir sMsg += OString(rEx.Message.getStr(), rEx.Message.getLength(), RTL_TEXTENCODING_ASCII_US); 71*cdf0e10cSrcweir OSL_ENSURE(sal_False, sMsg.getStr()); 72*cdf0e10cSrcweir } 73*cdf0e10cSrcweir #define CATCH_INFO(a) \ 74*cdf0e10cSrcweir catch(Exception& rEx) \ 75*cdf0e10cSrcweir { \ 76*cdf0e10cSrcweir lcl_CFG_DBG_EXCEPTION(a, rEx);\ 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir #else 79*cdf0e10cSrcweir #define lcl_CFG_DBG_EXCEPTION( a, b) 80*cdf0e10cSrcweir #define CATCH_INFO(a) catch(Exception& ){} 81*cdf0e10cSrcweir #endif 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir /* 84*cdf0e10cSrcweir The ConfigChangeListener_Impl receives notifications from the configuration about changes that 85*cdf0e10cSrcweir have happened. It forwards this notification to the ConfigItem it knows a pParent by calling its 86*cdf0e10cSrcweir "CallNotify" method. As ConfigItems are most probably not thread safe, the SolarMutex is acquired 87*cdf0e10cSrcweir before doing so. 88*cdf0e10cSrcweir */ 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir namespace utl{ 91*cdf0e10cSrcweir class ConfigChangeListener_Impl : public cppu::WeakImplHelper1 92*cdf0e10cSrcweir < 93*cdf0e10cSrcweir com::sun::star::util::XChangesListener 94*cdf0e10cSrcweir > 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir public: 97*cdf0e10cSrcweir ConfigItem* pParent; 98*cdf0e10cSrcweir const Sequence< OUString > aPropertyNames; 99*cdf0e10cSrcweir ConfigChangeListener_Impl(ConfigItem& rItem, const Sequence< OUString >& rNames); 100*cdf0e10cSrcweir ~ConfigChangeListener_Impl(); 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir //XChangesListener 103*cdf0e10cSrcweir virtual void SAL_CALL changesOccurred( const ChangesEvent& Event ) throw(RuntimeException); 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir //XEventListener 106*cdf0e10cSrcweir virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException); 107*cdf0e10cSrcweir }; 108*cdf0e10cSrcweir /* -----------------------------12.02.01 11:38-------------------------------- 109*cdf0e10cSrcweir 110*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 111*cdf0e10cSrcweir struct ConfigItem_Impl 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir utl::ConfigManager* pManager; 114*cdf0e10cSrcweir sal_Int16 nMode; 115*cdf0e10cSrcweir sal_Bool bIsModified; 116*cdf0e10cSrcweir sal_Bool bEnableInternalNotification; 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir sal_Int16 nInValueChange; 119*cdf0e10cSrcweir ConfigItem_Impl() : 120*cdf0e10cSrcweir pManager(0), 121*cdf0e10cSrcweir nMode(0), 122*cdf0e10cSrcweir bIsModified(sal_False), 123*cdf0e10cSrcweir bEnableInternalNotification(sal_False), 124*cdf0e10cSrcweir nInValueChange(0) 125*cdf0e10cSrcweir {} 126*cdf0e10cSrcweir }; 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir /* -----------------------------04.12.00 10:25-------------------------------- 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 131*cdf0e10cSrcweir class ValueCounter_Impl 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir sal_Int16& rCnt; 134*cdf0e10cSrcweir public: 135*cdf0e10cSrcweir ValueCounter_Impl(sal_Int16& rCounter): 136*cdf0e10cSrcweir rCnt(rCounter) 137*cdf0e10cSrcweir {rCnt++;} 138*cdf0e10cSrcweir ~ValueCounter_Impl() 139*cdf0e10cSrcweir { 140*cdf0e10cSrcweir OSL_ENSURE(rCnt>0, "RefCount < 0 ??"); 141*cdf0e10cSrcweir rCnt--; 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir }; 144*cdf0e10cSrcweir /* -----------------------------03.12.02 ------------------------------------- 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 147*cdf0e10cSrcweir namespace 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir // helper to achieve exception - safe handling of an Item under construction 150*cdf0e10cSrcweir template <class TYP> 151*cdf0e10cSrcweir class AutoDeleter // : Noncopyable 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir TYP* m_pItem; 154*cdf0e10cSrcweir public: 155*cdf0e10cSrcweir AutoDeleter(TYP * pItem) 156*cdf0e10cSrcweir : m_pItem(pItem) 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir } 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir ~AutoDeleter() 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir delete m_pItem; 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir void keep() { m_pItem = 0; } 166*cdf0e10cSrcweir }; 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir /* -----------------------------29.08.00 16:34-------------------------------- 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 171*cdf0e10cSrcweir ConfigChangeListener_Impl::ConfigChangeListener_Impl( 172*cdf0e10cSrcweir ConfigItem& rItem, const Sequence< OUString >& rNames) : 173*cdf0e10cSrcweir pParent(&rItem), 174*cdf0e10cSrcweir aPropertyNames(rNames) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir /* -----------------------------29.08.00 16:34-------------------------------- 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 180*cdf0e10cSrcweir ConfigChangeListener_Impl::~ConfigChangeListener_Impl() 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir /* -----------------------------29.08.00 16:34-------------------------------- 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 186*cdf0e10cSrcweir sal_Bool lcl_Find( 187*cdf0e10cSrcweir const rtl::OUString& rTemp, 188*cdf0e10cSrcweir const OUString* pCheckPropertyNames, 189*cdf0e10cSrcweir sal_Int32 nLength) 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir //return true if the path is completely correct or if it is longer 192*cdf0e10cSrcweir //i.e ...Print/Content/Graphic and .../Print 193*cdf0e10cSrcweir for(sal_Int32 nIndex = 0; nIndex < nLength; nIndex++) 194*cdf0e10cSrcweir if( isPrefixOfConfigurationPath(rTemp, pCheckPropertyNames[nIndex]) ) 195*cdf0e10cSrcweir return sal_True; 196*cdf0e10cSrcweir return sal_False; 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir //----------------------------------------------------------------------------- 199*cdf0e10cSrcweir void ConfigChangeListener_Impl::changesOccurred( const ChangesEvent& rEvent ) throw(RuntimeException) 200*cdf0e10cSrcweir { 201*cdf0e10cSrcweir const ElementChange* pElementChanges = rEvent.Changes.getConstArray(); 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir Sequence<OUString> aChangedNames(rEvent.Changes.getLength()); 204*cdf0e10cSrcweir OUString* pNames = aChangedNames.getArray(); 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir const OUString* pCheckPropertyNames = aPropertyNames.getConstArray(); 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir sal_Int32 nNotify = 0; 209*cdf0e10cSrcweir for(int i = 0; i < aChangedNames.getLength(); i++) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir OUString sTemp; 212*cdf0e10cSrcweir pElementChanges[i].Accessor >>= sTemp; 213*cdf0e10cSrcweir if(lcl_Find(sTemp, pCheckPropertyNames, aPropertyNames.getLength())) 214*cdf0e10cSrcweir pNames[nNotify++] = sTemp; 215*cdf0e10cSrcweir } 216*cdf0e10cSrcweir if( nNotify ) 217*cdf0e10cSrcweir { 218*cdf0e10cSrcweir if ( ::tools::SolarMutex::Acquire() ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir aChangedNames.realloc(nNotify); 221*cdf0e10cSrcweir pParent->CallNotify(aChangedNames); 222*cdf0e10cSrcweir ::tools::SolarMutex::Release(); 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir /* -----------------------------29.08.00 16:34-------------------------------- 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 230*cdf0e10cSrcweir void ConfigChangeListener_Impl::disposing( const EventObject& /*rSource*/ ) throw(RuntimeException) 231*cdf0e10cSrcweir { 232*cdf0e10cSrcweir pParent->RemoveChangesListener(); 233*cdf0e10cSrcweir } 234*cdf0e10cSrcweir /* -----------------------------29.08.00 12:50-------------------------------- 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 237*cdf0e10cSrcweir ConfigItem::ConfigItem(const OUString rSubTree, sal_Int16 nSetMode ) : 238*cdf0e10cSrcweir sSubTree(rSubTree), 239*cdf0e10cSrcweir pImpl(new ConfigItem_Impl) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir AutoDeleter<ConfigItem_Impl> aNewImpl(pImpl); 242*cdf0e10cSrcweir 243*cdf0e10cSrcweir pImpl->pManager = ConfigManager::GetConfigManager(); 244*cdf0e10cSrcweir pImpl->nMode = nSetMode; 245*cdf0e10cSrcweir if(0 != (nSetMode&CONFIG_MODE_RELEASE_TREE)) 246*cdf0e10cSrcweir pImpl->pManager->AddConfigItem(*this); 247*cdf0e10cSrcweir else 248*cdf0e10cSrcweir m_xHierarchyAccess = pImpl->pManager->AddConfigItem(*this); 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir // no more exceptions after c'tor has finished 251*cdf0e10cSrcweir aNewImpl.keep(); 252*cdf0e10cSrcweir pImpl->nMode &= ~CONFIG_MODE_PROPAGATE_ERRORS; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir /* -----------------------------17.11.00 13:53-------------------------------- 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 257*cdf0e10cSrcweir ConfigItem::ConfigItem(utl::ConfigManager& rManager, const rtl::OUString rSubTree) : 258*cdf0e10cSrcweir sSubTree(rSubTree), 259*cdf0e10cSrcweir pImpl(new ConfigItem_Impl) 260*cdf0e10cSrcweir { 261*cdf0e10cSrcweir pImpl->pManager = &rManager; 262*cdf0e10cSrcweir pImpl->nMode = CONFIG_MODE_IMMEDIATE_UPDATE; // does not allow exceptions 263*cdf0e10cSrcweir m_xHierarchyAccess = pImpl->pManager->AddConfigItem(*this); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir //--------------------------------------------------------------------- 266*cdf0e10cSrcweir //--- 02.08.2002 16:33:23 ----------------------------------------------- 267*cdf0e10cSrcweir sal_Bool ConfigItem::IsValidConfigMgr() const 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir return ( pImpl->pManager && pImpl->pManager->GetConfigurationProvider().is() ); 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir /* -----------------------------29.08.00 12:52-------------------------------- 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 275*cdf0e10cSrcweir ConfigItem::~ConfigItem() 276*cdf0e10cSrcweir { 277*cdf0e10cSrcweir if(pImpl->pManager) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir RemoveChangesListener(); 280*cdf0e10cSrcweir pImpl->pManager->RemoveConfigItem(*this); 281*cdf0e10cSrcweir } 282*cdf0e10cSrcweir delete pImpl; 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir /* -----------------------------29.08.00 12:52-------------------------------- 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 287*cdf0e10cSrcweir void ConfigItem::ReleaseConfigMgr() 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 290*cdf0e10cSrcweir if(xHierarchyAccess.is()) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir try 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 295*cdf0e10cSrcweir xBatch->commitChanges(); 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir RemoveChangesListener(); 300*cdf0e10cSrcweir OSL_ENSURE(pImpl->pManager, "ConfigManager already released"); 301*cdf0e10cSrcweir pImpl->pManager = 0; 302*cdf0e10cSrcweir } 303*cdf0e10cSrcweir /* -----------------------------29.08.00 12:52-------------------------------- 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 306*cdf0e10cSrcweir void ConfigItem::CallNotify( const com::sun::star::uno::Sequence<OUString>& rPropertyNames ) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir // the call is forwarded to the virtual Notify() method 309*cdf0e10cSrcweir // it is pure virtual, so all classes deriving from ConfigItem have to decide how they 310*cdf0e10cSrcweir // want to notify listeners 311*cdf0e10cSrcweir if(!IsInValueChange() || pImpl->bEnableInternalNotification) 312*cdf0e10cSrcweir Notify(rPropertyNames); 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir /* -----------------------------12.12.00 17:09-------------------------------- 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 318*cdf0e10cSrcweir sal_Bool lcl_IsLocalProperty(const OUString& rSubTree, const OUString& rProperty) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir static const sal_Char* aLocalProperties[] = 321*cdf0e10cSrcweir { 322*cdf0e10cSrcweir "Office.Common/Path/Current/Storage", 323*cdf0e10cSrcweir "Office.Common/Path/Current/Temp" 324*cdf0e10cSrcweir }; 325*cdf0e10cSrcweir static const int aLocalPropLen[] = 326*cdf0e10cSrcweir { 327*cdf0e10cSrcweir 34, 328*cdf0e10cSrcweir 31 329*cdf0e10cSrcweir }; 330*cdf0e10cSrcweir OUString sProperty(rSubTree); 331*cdf0e10cSrcweir sProperty += C2U("/"); 332*cdf0e10cSrcweir sProperty += rProperty; 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir if(sProperty.equalsAsciiL( aLocalProperties[0], aLocalPropLen[0]) || 335*cdf0e10cSrcweir sProperty.equalsAsciiL( aLocalProperties[1], aLocalPropLen[1])) 336*cdf0e10cSrcweir return sal_True; 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir return sal_False; 339*cdf0e10cSrcweir } 340*cdf0e10cSrcweir /* -----------------------------10.04.01 15:00-------------------------------- 341*cdf0e10cSrcweir 342*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 343*cdf0e10cSrcweir void ConfigItem::impl_packLocalizedProperties( const Sequence< OUString >& lInNames , 344*cdf0e10cSrcweir const Sequence< Any >& lInValues , 345*cdf0e10cSrcweir Sequence< Any >& lOutValues ) 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir // Safe impossible cases. 348*cdf0e10cSrcweir // This method should be called for special ConfigItem-mode only! 349*cdf0e10cSrcweir OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_packLocalizedProperties()\nWrong call of this method detected!\n" ); 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir sal_Int32 nSourceCounter ; // used to step during input lists 352*cdf0e10cSrcweir sal_Int32 nSourceSize ; // marks end of loop over input lists 353*cdf0e10cSrcweir sal_Int32 nDestinationCounter ; // actual position in output lists 354*cdf0e10cSrcweir sal_Int32 nPropertyCounter ; // counter of inner loop for Sequence< PropertyValue > 355*cdf0e10cSrcweir sal_Int32 nPropertiesSize ; // marks end of inner loop 356*cdf0e10cSrcweir Sequence< OUString > lPropertyNames ; // list of all locales for localized entry 357*cdf0e10cSrcweir Sequence< PropertyValue > lProperties ; // localized values of an configuration entry packed for return 358*cdf0e10cSrcweir Reference< XInterface > xLocalizedNode ; // if cfg entry is localized ... lInValues contains an XInterface! 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir // Optimise follow algorithm ... A LITTLE BIT :-) 361*cdf0e10cSrcweir // There exist two different possibilities: 362*cdf0e10cSrcweir // i ) There exist no localized entries ... => size of lOutValues will be the same like lInNames/lInValues! 363*cdf0e10cSrcweir // ii) There exist some (mostly one or two) localized entries ... => size of lOutValues will be the same like lInNames/lInValues! 364*cdf0e10cSrcweir // ... Why? If a localized value exist - the any is filled with an XInterface object (is a SetNode-service). 365*cdf0e10cSrcweir // We read all his child nodes and pack it into Sequence< PropertyValue >. 366*cdf0e10cSrcweir // The result list we pack into the return any. We never change size of lists! 367*cdf0e10cSrcweir nSourceSize = lInNames.getLength(); 368*cdf0e10cSrcweir lOutValues.realloc( nSourceSize ); 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir // Algorithm: 371*cdf0e10cSrcweir // Copy all names and values from in to out lists. 372*cdf0e10cSrcweir // Look for special localized entries ... You can detect it as "XInterface" packed into an Any. 373*cdf0e10cSrcweir // Use this XInterface-object to read all localized values and pack it into Sequence< PropertValue >. 374*cdf0e10cSrcweir // Add this list to out lists then. 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir nDestinationCounter = 0; 377*cdf0e10cSrcweir for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter ) 378*cdf0e10cSrcweir { 379*cdf0e10cSrcweir // If item a special localized one ... convert and pack it ... 380*cdf0e10cSrcweir if( lInValues[nSourceCounter].getValueTypeName() == C2U("com.sun.star.uno.XInterface") ) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir lInValues[nSourceCounter] >>= xLocalizedNode; 383*cdf0e10cSrcweir Reference< XNameContainer > xSetAccess( xLocalizedNode, UNO_QUERY ); 384*cdf0e10cSrcweir if( xSetAccess.is() == sal_True ) 385*cdf0e10cSrcweir { 386*cdf0e10cSrcweir lPropertyNames = xSetAccess->getElementNames() ; 387*cdf0e10cSrcweir nPropertiesSize = lPropertyNames.getLength() ; 388*cdf0e10cSrcweir lProperties.realloc( nPropertiesSize ) ; 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter ) 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 393*cdf0e10cSrcweir // Sometimes it's better to see what's going on :-) 394*cdf0e10cSrcweir OUString sPropName = lInNames[nSourceCounter]; 395*cdf0e10cSrcweir OUString sLocaleName = lPropertyNames[nPropertyCounter]; 396*cdf0e10cSrcweir #endif 397*cdf0e10cSrcweir lProperties[nPropertyCounter].Name = lPropertyNames[nPropertyCounter] ; 398*cdf0e10cSrcweir OUString sLocaleValue; 399*cdf0e10cSrcweir xSetAccess->getByName( lPropertyNames[nPropertyCounter] ) >>= sLocaleValue ; 400*cdf0e10cSrcweir lProperties[nPropertyCounter].Value <<= sLocaleValue; 401*cdf0e10cSrcweir } 402*cdf0e10cSrcweir 403*cdf0e10cSrcweir lOutValues[nDestinationCounter] <<= lProperties; 404*cdf0e10cSrcweir } 405*cdf0e10cSrcweir } 406*cdf0e10cSrcweir // ... or copy normal items to return lists directly. 407*cdf0e10cSrcweir else 408*cdf0e10cSrcweir { 409*cdf0e10cSrcweir lOutValues[nDestinationCounter] = lInValues[nSourceCounter]; 410*cdf0e10cSrcweir } 411*cdf0e10cSrcweir ++nDestinationCounter; 412*cdf0e10cSrcweir } 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir /* -----------------------------10.04.01 15:00-------------------------------- 415*cdf0e10cSrcweir 416*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 417*cdf0e10cSrcweir void ConfigItem::impl_unpackLocalizedProperties( const Sequence< OUString >& lInNames , 418*cdf0e10cSrcweir const Sequence< Any >& lInValues , 419*cdf0e10cSrcweir Sequence< OUString >& lOutNames , 420*cdf0e10cSrcweir Sequence< Any >& lOutValues ) 421*cdf0e10cSrcweir { 422*cdf0e10cSrcweir // Safe impossible cases. 423*cdf0e10cSrcweir // This method should be called for special ConfigItem-mode only! 424*cdf0e10cSrcweir OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_unpackLocalizedProperties()\nWrong call of this method detected!\n" ); 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir sal_Int32 nSourceCounter ; // used to step during input lists 427*cdf0e10cSrcweir sal_Int32 nSourceSize ; // marks end of loop over input lists 428*cdf0e10cSrcweir sal_Int32 nDestinationCounter ; // actual position in output lists 429*cdf0e10cSrcweir sal_Int32 nPropertyCounter ; // counter of inner loop for Sequence< PropertyValue > 430*cdf0e10cSrcweir sal_Int32 nPropertiesSize ; // marks end of inner loop 431*cdf0e10cSrcweir OUString sNodeName ; // base name of node ( e.g. "UIName/" ) ... expand to locale ( e.g. "UIName/de" ) 432*cdf0e10cSrcweir Sequence< PropertyValue > lProperties ; // localized values of an configuration entry getted from lInValues-Any 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir // Optimise follow algorithm ... A LITTLE BIT :-) 435*cdf0e10cSrcweir // There exist two different possibilities: 436*cdf0e10cSrcweir // i ) There exist no localized entries ... => size of lOutNames/lOutValues will be the same like lInNames/lInValues! 437*cdf0e10cSrcweir // ii) There exist some (mostly one or two) localized entries ... => size of lOutNames/lOutValues will be some bytes greater then lInNames/lInValues. 438*cdf0e10cSrcweir // => I think we should make it fast for i). ii) is a special case and mustn't be SOOOO... fast. 439*cdf0e10cSrcweir // We should reserve same space for output list like input ones first. 440*cdf0e10cSrcweir // Follow algorithm looks for these borders and change it for ii) only! 441*cdf0e10cSrcweir // It will be faster then a "realloc()" call in every loop ... 442*cdf0e10cSrcweir nSourceSize = lInNames.getLength(); 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir lOutNames.realloc ( nSourceSize ); 445*cdf0e10cSrcweir lOutValues.realloc ( nSourceSize ); 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir // Algorithm: 448*cdf0e10cSrcweir // Copy all names and values from const to return lists. 449*cdf0e10cSrcweir // Look for special localized entries ... You can detect it as Sequence< PropertyValue > packed into an Any. 450*cdf0e10cSrcweir // Split it ... insert PropertyValue.Name to lOutNames and PropertyValue.Value to lOutValues. 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir nDestinationCounter = 0; 453*cdf0e10cSrcweir for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter ) 454*cdf0e10cSrcweir { 455*cdf0e10cSrcweir // If item a special localized one ... split it and insert his parts to output lists ... 456*cdf0e10cSrcweir if( lInValues[nSourceCounter].getValueType() == ::getCppuType( (const Sequence< PropertyValue >*)NULL ) ) 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir lInValues[nSourceCounter] >>= lProperties ; 459*cdf0e10cSrcweir sNodeName = lInNames[nSourceCounter] ; 460*cdf0e10cSrcweir sNodeName += C2U("/") ; 461*cdf0e10cSrcweir nPropertiesSize = lProperties.getLength() ; 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir if( (nDestinationCounter+nPropertiesSize) > lOutNames.getLength() ) 464*cdf0e10cSrcweir { 465*cdf0e10cSrcweir lOutNames.realloc ( nDestinationCounter+nPropertiesSize ); 466*cdf0e10cSrcweir lOutValues.realloc ( nDestinationCounter+nPropertiesSize ); 467*cdf0e10cSrcweir } 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter ) 470*cdf0e10cSrcweir { 471*cdf0e10cSrcweir lOutNames [nDestinationCounter] = sNodeName + lProperties[nPropertyCounter].Name ; 472*cdf0e10cSrcweir lOutValues[nDestinationCounter] = lProperties[nPropertyCounter].Value ; 473*cdf0e10cSrcweir ++nDestinationCounter; 474*cdf0e10cSrcweir } 475*cdf0e10cSrcweir } 476*cdf0e10cSrcweir // ... or copy normal items to return lists directly. 477*cdf0e10cSrcweir else 478*cdf0e10cSrcweir { 479*cdf0e10cSrcweir if( (nDestinationCounter+1) > lOutNames.getLength() ) 480*cdf0e10cSrcweir { 481*cdf0e10cSrcweir lOutNames.realloc ( nDestinationCounter+1 ); 482*cdf0e10cSrcweir lOutValues.realloc ( nDestinationCounter+1 ); 483*cdf0e10cSrcweir } 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir lOutNames [nDestinationCounter] = lInNames [nSourceCounter]; 486*cdf0e10cSrcweir lOutValues[nDestinationCounter] = lInValues[nSourceCounter]; 487*cdf0e10cSrcweir ++nDestinationCounter; 488*cdf0e10cSrcweir } 489*cdf0e10cSrcweir } 490*cdf0e10cSrcweir } 491*cdf0e10cSrcweir /* -----------------------------03.02.2003 14:44------------------------------ 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 494*cdf0e10cSrcweir Sequence< sal_Bool > ConfigItem::GetReadOnlyStates(const com::sun::star::uno::Sequence< rtl::OUString >& rNames) 495*cdf0e10cSrcweir { 496*cdf0e10cSrcweir sal_Int32 i; 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir // size of return list is fix! 499*cdf0e10cSrcweir // Every item must match to length of incoming name list. 500*cdf0e10cSrcweir sal_Int32 nCount = rNames.getLength(); 501*cdf0e10cSrcweir Sequence< sal_Bool > lStates(nCount); 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir // We must be shure to return a valid information everytime! 504*cdf0e10cSrcweir // Set default to non readonly ... similar to the configuration handling of this property. 505*cdf0e10cSrcweir for ( i=0; i<nCount; ++i) 506*cdf0e10cSrcweir lStates[i] = sal_False; 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir // no access - no informations ... 509*cdf0e10cSrcweir Reference< XHierarchicalNameAccess > xHierarchyAccess = GetTree(); 510*cdf0e10cSrcweir if (!xHierarchyAccess.is()) 511*cdf0e10cSrcweir return lStates; 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir for (i=0; i<nCount; ++i) 514*cdf0e10cSrcweir { 515*cdf0e10cSrcweir try 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, rNames[i])) 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nlocal mode seams to be used!?\n"); 520*cdf0e10cSrcweir continue; 521*cdf0e10cSrcweir } 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir OUString sName = rNames[i]; 524*cdf0e10cSrcweir OUString sPath; 525*cdf0e10cSrcweir OUString sProperty; 526*cdf0e10cSrcweir 527*cdf0e10cSrcweir ::utl::splitLastFromConfigurationPath(sName,sPath,sProperty); 528*cdf0e10cSrcweir if (!sPath.getLength() && !sProperty.getLength()) 529*cdf0e10cSrcweir { 530*cdf0e10cSrcweir OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nsplitt failed\n"); 531*cdf0e10cSrcweir continue; 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir Reference< XInterface > xNode; 535*cdf0e10cSrcweir Reference< XPropertySet > xSet ; 536*cdf0e10cSrcweir Reference< XPropertySetInfo > xInfo; 537*cdf0e10cSrcweir if (sPath.getLength()) 538*cdf0e10cSrcweir { 539*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(sPath); 540*cdf0e10cSrcweir if (!(aNode >>= xNode) || !xNode.is()) 541*cdf0e10cSrcweir { 542*cdf0e10cSrcweir OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nno set available\n"); 543*cdf0e10cSrcweir continue; 544*cdf0e10cSrcweir } 545*cdf0e10cSrcweir } 546*cdf0e10cSrcweir else 547*cdf0e10cSrcweir { 548*cdf0e10cSrcweir xNode = Reference< XInterface >(xHierarchyAccess, UNO_QUERY); 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir xSet = Reference< XPropertySet >(xNode, UNO_QUERY); 552*cdf0e10cSrcweir if (xSet.is()) 553*cdf0e10cSrcweir { 554*cdf0e10cSrcweir xInfo = xSet->getPropertySetInfo(); 555*cdf0e10cSrcweir OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\ngetPropertySetInfo failed ...\n"); 556*cdf0e10cSrcweir } 557*cdf0e10cSrcweir else 558*cdf0e10cSrcweir { 559*cdf0e10cSrcweir xInfo = Reference< XPropertySetInfo >(xNode, UNO_QUERY); 560*cdf0e10cSrcweir OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\nUNO_QUERY failed ...\n"); 561*cdf0e10cSrcweir } 562*cdf0e10cSrcweir 563*cdf0e10cSrcweir if (!xInfo.is()) 564*cdf0e10cSrcweir { 565*cdf0e10cSrcweir OSL_ENSURE(sal_False, "ConfigItem::IsReadonly()\nno prop info available\n"); 566*cdf0e10cSrcweir continue; 567*cdf0e10cSrcweir } 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir Property aProp = xInfo->getPropertyByName(sProperty); 570*cdf0e10cSrcweir lStates[i] = ((aProp.Attributes & PropertyAttribute::READONLY) == PropertyAttribute::READONLY); 571*cdf0e10cSrcweir } 572*cdf0e10cSrcweir catch(Exception&){} 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir 575*cdf0e10cSrcweir return lStates; 576*cdf0e10cSrcweir } 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir /* -----------------------------29.08.00 15:10-------------------------------- 579*cdf0e10cSrcweir 580*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 581*cdf0e10cSrcweir Sequence< Any > ConfigItem::GetProperties(const Sequence< OUString >& rNames) 582*cdf0e10cSrcweir { 583*cdf0e10cSrcweir Sequence< Any > aRet(rNames.getLength()); 584*cdf0e10cSrcweir const OUString* pNames = rNames.getConstArray(); 585*cdf0e10cSrcweir Any* pRet = aRet.getArray(); 586*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 587*cdf0e10cSrcweir if(xHierarchyAccess.is()) 588*cdf0e10cSrcweir { 589*cdf0e10cSrcweir for(int i = 0; i < rNames.getLength(); i++) 590*cdf0e10cSrcweir { 591*cdf0e10cSrcweir try 592*cdf0e10cSrcweir { 593*cdf0e10cSrcweir if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, pNames[i])) 594*cdf0e10cSrcweir { 595*cdf0e10cSrcweir OUString sProperty(sSubTree); 596*cdf0e10cSrcweir sProperty += C2U("/"); 597*cdf0e10cSrcweir sProperty += pNames[i]; 598*cdf0e10cSrcweir pRet[i] = pImpl->pManager->GetLocalProperty(sProperty); 599*cdf0e10cSrcweir } 600*cdf0e10cSrcweir else 601*cdf0e10cSrcweir pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]); 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir catch(Exception& rEx) 604*cdf0e10cSrcweir { 605*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 606*cdf0e10cSrcweir OString sMsg("XHierarchicalNameAccess: "); 607*cdf0e10cSrcweir sMsg += OString(rEx.Message.getStr(), 608*cdf0e10cSrcweir rEx.Message.getLength(), 609*cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 610*cdf0e10cSrcweir sMsg += OString("\n"); 611*cdf0e10cSrcweir sMsg += OString(ConfigManager::GetConfigBaseURL().getStr(), 612*cdf0e10cSrcweir ConfigManager::GetConfigBaseURL().getLength(), 613*cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 614*cdf0e10cSrcweir sMsg += OString(sSubTree.getStr(), 615*cdf0e10cSrcweir sSubTree.getLength(), 616*cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 617*cdf0e10cSrcweir sMsg += OString("/"); 618*cdf0e10cSrcweir sMsg += OString(pNames[i].getStr(), 619*cdf0e10cSrcweir pNames[i].getLength(), 620*cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 621*cdf0e10cSrcweir OSL_ENSURE(sal_False, sMsg.getStr()); 622*cdf0e10cSrcweir #else 623*cdf0e10cSrcweir (void) rEx; // avoid warning 624*cdf0e10cSrcweir #endif 625*cdf0e10cSrcweir } 626*cdf0e10cSrcweir } 627*cdf0e10cSrcweir 628*cdf0e10cSrcweir // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >. 629*cdf0e10cSrcweir if((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES) 630*cdf0e10cSrcweir { 631*cdf0e10cSrcweir Sequence< Any > lValues; 632*cdf0e10cSrcweir impl_packLocalizedProperties( rNames, aRet, lValues ); 633*cdf0e10cSrcweir aRet = lValues; 634*cdf0e10cSrcweir } 635*cdf0e10cSrcweir } 636*cdf0e10cSrcweir return aRet; 637*cdf0e10cSrcweir } 638*cdf0e10cSrcweir /* -----------------------------29.08.00 17:28-------------------------------- 639*cdf0e10cSrcweir 640*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 641*cdf0e10cSrcweir sal_Bool ConfigItem::PutProperties( const Sequence< OUString >& rNames, 642*cdf0e10cSrcweir const Sequence< Any>& rValues) 643*cdf0e10cSrcweir { 644*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 645*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 646*cdf0e10cSrcweir Reference<XNameReplace> xTopNodeReplace(xHierarchyAccess, UNO_QUERY); 647*cdf0e10cSrcweir sal_Bool bRet = xHierarchyAccess.is() && xTopNodeReplace.is(); 648*cdf0e10cSrcweir if(bRet) 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir Sequence< OUString > lNames ; 651*cdf0e10cSrcweir Sequence< Any > lValues ; 652*cdf0e10cSrcweir const OUString* pNames = NULL ; 653*cdf0e10cSrcweir const Any* pValues = NULL ; 654*cdf0e10cSrcweir sal_Int32 nNameCount ; 655*cdf0e10cSrcweir if(( pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES ) 656*cdf0e10cSrcweir { 657*cdf0e10cSrcweir // If ConfigItem works in "ALL_LOCALES"-mode ... we must support a Sequence< PropertyValue > 658*cdf0e10cSrcweir // as value of an localized configuration entry! 659*cdf0e10cSrcweir // How we can do that? 660*cdf0e10cSrcweir // We must split all PropertyValues to "Sequence< OUString >" AND "Sequence< Any >"! 661*cdf0e10cSrcweir impl_unpackLocalizedProperties( rNames, rValues, lNames, lValues ); 662*cdf0e10cSrcweir pNames = lNames.getConstArray (); 663*cdf0e10cSrcweir pValues = lValues.getConstArray (); 664*cdf0e10cSrcweir nNameCount = lNames.getLength (); 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir else 667*cdf0e10cSrcweir { 668*cdf0e10cSrcweir // This is the normal mode ... 669*cdf0e10cSrcweir // Use given input lists directly. 670*cdf0e10cSrcweir pNames = rNames.getConstArray (); 671*cdf0e10cSrcweir pValues = rValues.getConstArray (); 672*cdf0e10cSrcweir nNameCount = rNames.getLength (); 673*cdf0e10cSrcweir } 674*cdf0e10cSrcweir for(int i = 0; i < nNameCount; i++) 675*cdf0e10cSrcweir { 676*cdf0e10cSrcweir if(pImpl->pManager->IsLocalConfigProvider() && lcl_IsLocalProperty(sSubTree, pNames[i])) 677*cdf0e10cSrcweir { 678*cdf0e10cSrcweir OUString sProperty(sSubTree); 679*cdf0e10cSrcweir sProperty += C2U("/"); 680*cdf0e10cSrcweir sProperty += pNames[i]; 681*cdf0e10cSrcweir pImpl->pManager->PutLocalProperty(sProperty, pValues[i]); 682*cdf0e10cSrcweir } 683*cdf0e10cSrcweir else 684*cdf0e10cSrcweir { 685*cdf0e10cSrcweir try 686*cdf0e10cSrcweir { 687*cdf0e10cSrcweir OUString sNode, sProperty; 688*cdf0e10cSrcweir if (splitLastFromConfigurationPath(pNames[i],sNode, sProperty)) 689*cdf0e10cSrcweir { 690*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(sNode); 691*cdf0e10cSrcweir 692*cdf0e10cSrcweir Reference<XNameAccess> xNodeAcc; 693*cdf0e10cSrcweir aNode >>= xNodeAcc; 694*cdf0e10cSrcweir Reference<XNameReplace> xNodeReplace(xNodeAcc, UNO_QUERY); 695*cdf0e10cSrcweir Reference<XNameContainer> xNodeCont (xNodeAcc, UNO_QUERY); 696*cdf0e10cSrcweir 697*cdf0e10cSrcweir sal_Bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty)); 698*cdf0e10cSrcweir if (bExist && xNodeReplace.is()) 699*cdf0e10cSrcweir xNodeReplace->replaceByName(sProperty, pValues[i]); 700*cdf0e10cSrcweir else 701*cdf0e10cSrcweir if (!bExist && xNodeCont.is()) 702*cdf0e10cSrcweir xNodeCont->insertByName(sProperty, pValues[i]); 703*cdf0e10cSrcweir else 704*cdf0e10cSrcweir bRet = sal_False; 705*cdf0e10cSrcweir } 706*cdf0e10cSrcweir else //direct value 707*cdf0e10cSrcweir { 708*cdf0e10cSrcweir xTopNodeReplace->replaceByName(sProperty, pValues[i]); 709*cdf0e10cSrcweir } 710*cdf0e10cSrcweir } 711*cdf0e10cSrcweir CATCH_INFO("Exception from PutProperties: "); 712*cdf0e10cSrcweir } 713*cdf0e10cSrcweir } 714*cdf0e10cSrcweir try 715*cdf0e10cSrcweir { 716*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 717*cdf0e10cSrcweir xBatch->commitChanges(); 718*cdf0e10cSrcweir } 719*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 720*cdf0e10cSrcweir } 721*cdf0e10cSrcweir 722*cdf0e10cSrcweir return bRet; 723*cdf0e10cSrcweir } 724*cdf0e10cSrcweir /* -----------------------------08.12.05 15:27-------------------------------- 725*cdf0e10cSrcweir 726*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 727*cdf0e10cSrcweir void ConfigItem::DisableNotification() 728*cdf0e10cSrcweir { 729*cdf0e10cSrcweir OSL_ENSURE( xChangeLstnr.is(), "ConfigItem::DisableNotification: notifications not enabled currently!" ); 730*cdf0e10cSrcweir RemoveChangesListener(); 731*cdf0e10cSrcweir } 732*cdf0e10cSrcweir /* -----------------------------29.08.00 16:19-------------------------------- 733*cdf0e10cSrcweir 734*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 735*cdf0e10cSrcweir sal_Bool ConfigItem::EnableNotification(const Sequence< OUString >& rNames, 736*cdf0e10cSrcweir sal_Bool bEnableInternalNotification ) 737*cdf0e10cSrcweir 738*cdf0e10cSrcweir { 739*cdf0e10cSrcweir OSL_ENSURE(0 == (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "notification in CONFIG_MODE_RELEASE_TREE mode not possible"); 740*cdf0e10cSrcweir pImpl->bEnableInternalNotification = bEnableInternalNotification; 741*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 742*cdf0e10cSrcweir Reference<XChangesNotifier> xChgNot(xHierarchyAccess, UNO_QUERY); 743*cdf0e10cSrcweir if(!xChgNot.is()) 744*cdf0e10cSrcweir return sal_False; 745*cdf0e10cSrcweir 746*cdf0e10cSrcweir OSL_ENSURE(!xChangeLstnr.is(), "EnableNotification already called"); 747*cdf0e10cSrcweir if(xChangeLstnr.is()) 748*cdf0e10cSrcweir xChgNot->removeChangesListener( xChangeLstnr ); 749*cdf0e10cSrcweir sal_Bool bRet = sal_True; 750*cdf0e10cSrcweir 751*cdf0e10cSrcweir try 752*cdf0e10cSrcweir { 753*cdf0e10cSrcweir xChangeLstnr = new ConfigChangeListener_Impl(*this, rNames); 754*cdf0e10cSrcweir xChgNot->addChangesListener( xChangeLstnr ); 755*cdf0e10cSrcweir } 756*cdf0e10cSrcweir catch(RuntimeException& ) 757*cdf0e10cSrcweir { 758*cdf0e10cSrcweir bRet = sal_False; 759*cdf0e10cSrcweir } 760*cdf0e10cSrcweir return bRet; 761*cdf0e10cSrcweir } 762*cdf0e10cSrcweir /* -----------------------------29.08.00 16:47-------------------------------- 763*cdf0e10cSrcweir 764*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 765*cdf0e10cSrcweir void ConfigItem::RemoveChangesListener() 766*cdf0e10cSrcweir { 767*cdf0e10cSrcweir Reference<XChangesNotifier> xChgNot(m_xHierarchyAccess, UNO_QUERY); 768*cdf0e10cSrcweir if(xChgNot.is() && xChangeLstnr.is()) 769*cdf0e10cSrcweir { 770*cdf0e10cSrcweir try 771*cdf0e10cSrcweir { 772*cdf0e10cSrcweir xChgNot->removeChangesListener( xChangeLstnr ); 773*cdf0e10cSrcweir xChangeLstnr = 0; 774*cdf0e10cSrcweir } 775*cdf0e10cSrcweir catch(Exception & ) 776*cdf0e10cSrcweir { 777*cdf0e10cSrcweir } 778*cdf0e10cSrcweir } 779*cdf0e10cSrcweir } 780*cdf0e10cSrcweir /* -----------------------------10.07.00 -------------------------------- 781*cdf0e10cSrcweir 782*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 783*cdf0e10cSrcweir void lcl_normalizeLocalNames(Sequence< OUString >& _rNames, ConfigNameFormat _eFormat, Reference<XInterface> const& _xParentNode) 784*cdf0e10cSrcweir { 785*cdf0e10cSrcweir switch (_eFormat) 786*cdf0e10cSrcweir { 787*cdf0e10cSrcweir case CONFIG_NAME_LOCAL_NAME: 788*cdf0e10cSrcweir // unaltered - this is our input format 789*cdf0e10cSrcweir break; 790*cdf0e10cSrcweir 791*cdf0e10cSrcweir case CONFIG_NAME_FULL_PATH: 792*cdf0e10cSrcweir { 793*cdf0e10cSrcweir Reference<XHierarchicalName> xFormatter(_xParentNode, UNO_QUERY); 794*cdf0e10cSrcweir if (xFormatter.is()) 795*cdf0e10cSrcweir { 796*cdf0e10cSrcweir OUString * pNames = _rNames.getArray(); 797*cdf0e10cSrcweir for(int i = 0; i<_rNames.getLength(); ++i) 798*cdf0e10cSrcweir try 799*cdf0e10cSrcweir { 800*cdf0e10cSrcweir pNames[i] = xFormatter->composeHierarchicalName(pNames[i]); 801*cdf0e10cSrcweir } 802*cdf0e10cSrcweir CATCH_INFO("Exception from composeHierarchicalName(): ") 803*cdf0e10cSrcweir break; 804*cdf0e10cSrcweir } 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir OSL_ENSURE(false, "Cannot create absolute pathes: missing interface"); 807*cdf0e10cSrcweir // make local pathes instaed 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir case CONFIG_NAME_LOCAL_PATH: 810*cdf0e10cSrcweir { 811*cdf0e10cSrcweir Reference<XTemplateContainer> xTypeContainer(_xParentNode, UNO_QUERY); 812*cdf0e10cSrcweir if (xTypeContainer.is()) 813*cdf0e10cSrcweir { 814*cdf0e10cSrcweir OUString sTypeName = xTypeContainer->getElementTemplateName(); 815*cdf0e10cSrcweir sTypeName = sTypeName.copy(sTypeName.lastIndexOf('/')+1); 816*cdf0e10cSrcweir 817*cdf0e10cSrcweir OUString * pNames = _rNames.getArray(); 818*cdf0e10cSrcweir for(int i = 0; i<_rNames.getLength(); ++i) 819*cdf0e10cSrcweir { 820*cdf0e10cSrcweir pNames[i] = wrapConfigurationElementName(pNames[i],sTypeName); 821*cdf0e10cSrcweir } 822*cdf0e10cSrcweir } 823*cdf0e10cSrcweir else 824*cdf0e10cSrcweir { 825*cdf0e10cSrcweir static const OUString sSetService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.SetAccess")); 826*cdf0e10cSrcweir Reference<XServiceInfo> xSVI(_xParentNode, UNO_QUERY); 827*cdf0e10cSrcweir if (xSVI.is() && xSVI->supportsService(sSetService)) 828*cdf0e10cSrcweir { 829*cdf0e10cSrcweir OUString * pNames = _rNames.getArray(); 830*cdf0e10cSrcweir for(int i = 0; i<_rNames.getLength(); ++i) 831*cdf0e10cSrcweir { 832*cdf0e10cSrcweir pNames[i] = wrapConfigurationElementName(pNames[i]); 833*cdf0e10cSrcweir } 834*cdf0e10cSrcweir } 835*cdf0e10cSrcweir } 836*cdf0e10cSrcweir } 837*cdf0e10cSrcweir break; 838*cdf0e10cSrcweir 839*cdf0e10cSrcweir case CONFIG_NAME_PLAINTEXT_NAME: 840*cdf0e10cSrcweir { 841*cdf0e10cSrcweir Reference<XStringEscape> xEscaper(_xParentNode, UNO_QUERY); 842*cdf0e10cSrcweir if (xEscaper.is()) 843*cdf0e10cSrcweir { 844*cdf0e10cSrcweir OUString * pNames = _rNames.getArray(); 845*cdf0e10cSrcweir for(int i = 0; i<_rNames.getLength(); ++i) 846*cdf0e10cSrcweir try 847*cdf0e10cSrcweir { 848*cdf0e10cSrcweir pNames[i] = xEscaper->unescapeString(pNames[i]); 849*cdf0e10cSrcweir } 850*cdf0e10cSrcweir CATCH_INFO("Exception from unescapeString(): ") 851*cdf0e10cSrcweir } 852*cdf0e10cSrcweir } 853*cdf0e10cSrcweir break; 854*cdf0e10cSrcweir 855*cdf0e10cSrcweir } 856*cdf0e10cSrcweir } 857*cdf0e10cSrcweir /* -----------------------------10.07.00 -------------------------------- 858*cdf0e10cSrcweir 859*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 860*cdf0e10cSrcweir Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode) 861*cdf0e10cSrcweir { 862*cdf0e10cSrcweir ConfigNameFormat const eDefaultFormat = CONFIG_NAME_LOCAL_NAME; // CONFIG_NAME_DEFAULT; 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir return GetNodeNames(rNode, eDefaultFormat); 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir /* -----------------------------15.09.00 12:06-------------------------------- 867*cdf0e10cSrcweir 868*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 869*cdf0e10cSrcweir Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode, ConfigNameFormat eFormat) 870*cdf0e10cSrcweir { 871*cdf0e10cSrcweir Sequence< OUString > aRet; 872*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 873*cdf0e10cSrcweir if(xHierarchyAccess.is()) 874*cdf0e10cSrcweir { 875*cdf0e10cSrcweir try 876*cdf0e10cSrcweir { 877*cdf0e10cSrcweir Reference<XNameAccess> xCont; 878*cdf0e10cSrcweir if(rNode.getLength()) 879*cdf0e10cSrcweir { 880*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 881*cdf0e10cSrcweir aNode >>= xCont; 882*cdf0e10cSrcweir } 883*cdf0e10cSrcweir else 884*cdf0e10cSrcweir xCont = Reference<XNameAccess> (xHierarchyAccess, UNO_QUERY); 885*cdf0e10cSrcweir if(xCont.is()) 886*cdf0e10cSrcweir { 887*cdf0e10cSrcweir aRet = xCont->getElementNames(); 888*cdf0e10cSrcweir lcl_normalizeLocalNames(aRet,eFormat,xCont); 889*cdf0e10cSrcweir } 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir } 892*cdf0e10cSrcweir CATCH_INFO("Exception from GetNodeNames: "); 893*cdf0e10cSrcweir } 894*cdf0e10cSrcweir return aRet; 895*cdf0e10cSrcweir } 896*cdf0e10cSrcweir /* -----------------------------15.09.00 15:52-------------------------------- 897*cdf0e10cSrcweir 898*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 899*cdf0e10cSrcweir sal_Bool ConfigItem::ClearNodeSet(const OUString& rNode) 900*cdf0e10cSrcweir { 901*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 902*cdf0e10cSrcweir sal_Bool bRet = sal_False; 903*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 904*cdf0e10cSrcweir if(xHierarchyAccess.is()) 905*cdf0e10cSrcweir { 906*cdf0e10cSrcweir try 907*cdf0e10cSrcweir { 908*cdf0e10cSrcweir Reference<XNameContainer> xCont; 909*cdf0e10cSrcweir if(rNode.getLength()) 910*cdf0e10cSrcweir { 911*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 912*cdf0e10cSrcweir aNode >>= xCont; 913*cdf0e10cSrcweir } 914*cdf0e10cSrcweir else 915*cdf0e10cSrcweir xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); 916*cdf0e10cSrcweir if(!xCont.is()) 917*cdf0e10cSrcweir return sal_False; 918*cdf0e10cSrcweir Sequence< OUString > aNames = xCont->getElementNames(); 919*cdf0e10cSrcweir const OUString* pNames = aNames.getConstArray(); 920*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 921*cdf0e10cSrcweir for(sal_Int32 i = 0; i < aNames.getLength(); i++) 922*cdf0e10cSrcweir { 923*cdf0e10cSrcweir try 924*cdf0e10cSrcweir { 925*cdf0e10cSrcweir xCont->removeByName(pNames[i]); 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir CATCH_INFO("Exception from removeByName(): ") 928*cdf0e10cSrcweir } 929*cdf0e10cSrcweir xBatch->commitChanges(); 930*cdf0e10cSrcweir bRet = sal_True; 931*cdf0e10cSrcweir } 932*cdf0e10cSrcweir CATCH_INFO("Exception from ClearNodeSet") 933*cdf0e10cSrcweir } 934*cdf0e10cSrcweir return bRet; 935*cdf0e10cSrcweir } 936*cdf0e10cSrcweir /* -----------------------------24.11.00 10:58-------------------------------- 937*cdf0e10cSrcweir 938*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 939*cdf0e10cSrcweir sal_Bool ConfigItem::ClearNodeElements(const OUString& rNode, Sequence< OUString >& rElements) 940*cdf0e10cSrcweir { 941*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 942*cdf0e10cSrcweir sal_Bool bRet = sal_False; 943*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 944*cdf0e10cSrcweir if(xHierarchyAccess.is()) 945*cdf0e10cSrcweir { 946*cdf0e10cSrcweir const OUString* pElements = rElements.getConstArray(); 947*cdf0e10cSrcweir try 948*cdf0e10cSrcweir { 949*cdf0e10cSrcweir Reference<XNameContainer> xCont; 950*cdf0e10cSrcweir if(rNode.getLength()) 951*cdf0e10cSrcweir { 952*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 953*cdf0e10cSrcweir aNode >>= xCont; 954*cdf0e10cSrcweir } 955*cdf0e10cSrcweir else 956*cdf0e10cSrcweir xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); 957*cdf0e10cSrcweir if(!xCont.is()) 958*cdf0e10cSrcweir return sal_False; 959*cdf0e10cSrcweir try 960*cdf0e10cSrcweir { 961*cdf0e10cSrcweir for(sal_Int32 nElement = 0; nElement < rElements.getLength(); nElement++) 962*cdf0e10cSrcweir { 963*cdf0e10cSrcweir xCont->removeByName(pElements[nElement]); 964*cdf0e10cSrcweir } 965*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 966*cdf0e10cSrcweir xBatch->commitChanges(); 967*cdf0e10cSrcweir } 968*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 969*cdf0e10cSrcweir bRet = sal_True; 970*cdf0e10cSrcweir } 971*cdf0e10cSrcweir CATCH_INFO("Exception from GetNodeNames: ") 972*cdf0e10cSrcweir } 973*cdf0e10cSrcweir return bRet; 974*cdf0e10cSrcweir } 975*cdf0e10cSrcweir //---------------------------------------------------------------------------- 976*cdf0e10cSrcweir static inline 977*cdf0e10cSrcweir OUString lcl_extractSetPropertyName( const OUString& rInPath, const OUString& rPrefix ) 978*cdf0e10cSrcweir { 979*cdf0e10cSrcweir OUString const sSubPath = dropPrefixFromConfigurationPath( rInPath, rPrefix); 980*cdf0e10cSrcweir return extractFirstFromConfigurationPath( sSubPath ); 981*cdf0e10cSrcweir } 982*cdf0e10cSrcweir //---------------------------------------------------------------------------- 983*cdf0e10cSrcweir static 984*cdf0e10cSrcweir Sequence< OUString > lcl_extractSetPropertyNames( const Sequence< PropertyValue >& rValues, const OUString& rPrefix ) 985*cdf0e10cSrcweir { 986*cdf0e10cSrcweir const PropertyValue* pProperties = rValues.getConstArray(); 987*cdf0e10cSrcweir 988*cdf0e10cSrcweir Sequence< OUString > aSubNodeNames(rValues.getLength()); 989*cdf0e10cSrcweir OUString* pSubNodeNames = aSubNodeNames.getArray(); 990*cdf0e10cSrcweir 991*cdf0e10cSrcweir OUString sLastSubNode; 992*cdf0e10cSrcweir sal_Int32 nSubIndex = 0; 993*cdf0e10cSrcweir 994*cdf0e10cSrcweir for(sal_Int32 i = 0; i < rValues.getLength(); i++) 995*cdf0e10cSrcweir { 996*cdf0e10cSrcweir OUString const sSubPath = dropPrefixFromConfigurationPath( pProperties[i].Name, rPrefix); 997*cdf0e10cSrcweir OUString const sSubNode = extractFirstFromConfigurationPath( sSubPath ); 998*cdf0e10cSrcweir 999*cdf0e10cSrcweir if(sLastSubNode != sSubNode) 1000*cdf0e10cSrcweir { 1001*cdf0e10cSrcweir pSubNodeNames[nSubIndex++] = sSubNode; 1002*cdf0e10cSrcweir } 1003*cdf0e10cSrcweir 1004*cdf0e10cSrcweir sLastSubNode = sSubNode; 1005*cdf0e10cSrcweir } 1006*cdf0e10cSrcweir aSubNodeNames.realloc(nSubIndex); 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir return aSubNodeNames; 1009*cdf0e10cSrcweir } 1010*cdf0e10cSrcweir /* -----------------------------15.09.00 15:52-------------------------------- 1011*cdf0e10cSrcweir add or change properties 1012*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1013*cdf0e10cSrcweir sal_Bool ConfigItem::SetSetProperties( 1014*cdf0e10cSrcweir const OUString& rNode, Sequence< PropertyValue > rValues) 1015*cdf0e10cSrcweir { 1016*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 1017*cdf0e10cSrcweir sal_Bool bRet = sal_True; 1018*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 1019*cdf0e10cSrcweir if(xHierarchyAccess.is()) 1020*cdf0e10cSrcweir { 1021*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 1022*cdf0e10cSrcweir try 1023*cdf0e10cSrcweir { 1024*cdf0e10cSrcweir Reference<XNameContainer> xCont; 1025*cdf0e10cSrcweir if(rNode.getLength()) 1026*cdf0e10cSrcweir { 1027*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 1028*cdf0e10cSrcweir aNode >>= xCont; 1029*cdf0e10cSrcweir } 1030*cdf0e10cSrcweir else 1031*cdf0e10cSrcweir xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); 1032*cdf0e10cSrcweir if(!xCont.is()) 1033*cdf0e10cSrcweir return sal_False; 1034*cdf0e10cSrcweir 1035*cdf0e10cSrcweir Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); 1036*cdf0e10cSrcweir 1037*cdf0e10cSrcweir if(xFac.is()) 1038*cdf0e10cSrcweir { 1039*cdf0e10cSrcweir const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir const sal_Int32 nSubNodeCount = aSubNodeNames.getLength(); 1042*cdf0e10cSrcweir 1043*cdf0e10cSrcweir for(sal_Int32 j = 0; j <nSubNodeCount ; j++) 1044*cdf0e10cSrcweir { 1045*cdf0e10cSrcweir if(!xCont->hasByName(aSubNodeNames[j])) 1046*cdf0e10cSrcweir { 1047*cdf0e10cSrcweir Reference<XInterface> xInst = xFac->createInstance(); 1048*cdf0e10cSrcweir Any aVal; aVal <<= xInst; 1049*cdf0e10cSrcweir xCont->insertByName(aSubNodeNames[j], aVal); 1050*cdf0e10cSrcweir } 1051*cdf0e10cSrcweir //set values 1052*cdf0e10cSrcweir } 1053*cdf0e10cSrcweir try 1054*cdf0e10cSrcweir { 1055*cdf0e10cSrcweir xBatch->commitChanges(); 1056*cdf0e10cSrcweir } 1057*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 1058*cdf0e10cSrcweir 1059*cdf0e10cSrcweir const PropertyValue* pProperties = rValues.getConstArray(); 1060*cdf0e10cSrcweir 1061*cdf0e10cSrcweir Sequence< OUString > aSetNames(rValues.getLength()); 1062*cdf0e10cSrcweir OUString* pSetNames = aSetNames.getArray(); 1063*cdf0e10cSrcweir 1064*cdf0e10cSrcweir Sequence< Any> aSetValues(rValues.getLength()); 1065*cdf0e10cSrcweir Any* pSetValues = aSetValues.getArray(); 1066*cdf0e10cSrcweir 1067*cdf0e10cSrcweir sal_Bool bEmptyNode = rNode.getLength() == 0; 1068*cdf0e10cSrcweir for(sal_Int32 k = 0; k < rValues.getLength(); k++) 1069*cdf0e10cSrcweir { 1070*cdf0e10cSrcweir pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); 1071*cdf0e10cSrcweir pSetValues[k] = pProperties[k].Value; 1072*cdf0e10cSrcweir } 1073*cdf0e10cSrcweir bRet = PutProperties(aSetNames, aSetValues); 1074*cdf0e10cSrcweir } 1075*cdf0e10cSrcweir else 1076*cdf0e10cSrcweir { 1077*cdf0e10cSrcweir //if no factory is available then the node contains basic data elements 1078*cdf0e10cSrcweir const PropertyValue* pValues = rValues.getConstArray(); 1079*cdf0e10cSrcweir for(int nValue = 0; nValue < rValues.getLength();nValue++) 1080*cdf0e10cSrcweir { 1081*cdf0e10cSrcweir try 1082*cdf0e10cSrcweir { 1083*cdf0e10cSrcweir OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode ); 1084*cdf0e10cSrcweir 1085*cdf0e10cSrcweir if(xCont->hasByName(sSubNode)) 1086*cdf0e10cSrcweir xCont->replaceByName(sSubNode, pValues[nValue].Value); 1087*cdf0e10cSrcweir else 1088*cdf0e10cSrcweir xCont->insertByName(sSubNode, pValues[nValue].Value); 1089*cdf0e10cSrcweir 1090*cdf0e10cSrcweir OSL_ENSURE( xHierarchyAccess->hasByHierarchicalName(pValues[nValue].Name), 1091*cdf0e10cSrcweir "Invalid config path" ); 1092*cdf0e10cSrcweir } 1093*cdf0e10cSrcweir CATCH_INFO("Exception form insert/replaceByName(): ") 1094*cdf0e10cSrcweir } 1095*cdf0e10cSrcweir xBatch->commitChanges(); 1096*cdf0e10cSrcweir } 1097*cdf0e10cSrcweir } 1098*cdf0e10cSrcweir #ifdef DBG_UTIL 1099*cdf0e10cSrcweir catch(Exception& rEx) 1100*cdf0e10cSrcweir { 1101*cdf0e10cSrcweir lcl_CFG_DBG_EXCEPTION("Exception from SetSetProperties: ", rEx); 1102*cdf0e10cSrcweir #else 1103*cdf0e10cSrcweir catch(Exception&) 1104*cdf0e10cSrcweir { 1105*cdf0e10cSrcweir #endif 1106*cdf0e10cSrcweir bRet = sal_False; 1107*cdf0e10cSrcweir } 1108*cdf0e10cSrcweir } 1109*cdf0e10cSrcweir return bRet; 1110*cdf0e10cSrcweir } 1111*cdf0e10cSrcweir /* -----------------------------15.09.00 15:52-------------------------------- 1112*cdf0e10cSrcweir 1113*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1114*cdf0e10cSrcweir sal_Bool ConfigItem::ReplaceSetProperties( 1115*cdf0e10cSrcweir const OUString& rNode, Sequence< PropertyValue > rValues) 1116*cdf0e10cSrcweir { 1117*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 1118*cdf0e10cSrcweir sal_Bool bRet = sal_True; 1119*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 1120*cdf0e10cSrcweir if(xHierarchyAccess.is()) 1121*cdf0e10cSrcweir { 1122*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 1123*cdf0e10cSrcweir try 1124*cdf0e10cSrcweir { 1125*cdf0e10cSrcweir Reference<XNameContainer> xCont; 1126*cdf0e10cSrcweir if(rNode.getLength()) 1127*cdf0e10cSrcweir { 1128*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 1129*cdf0e10cSrcweir aNode >>= xCont; 1130*cdf0e10cSrcweir } 1131*cdf0e10cSrcweir else 1132*cdf0e10cSrcweir xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); 1133*cdf0e10cSrcweir if(!xCont.is()) 1134*cdf0e10cSrcweir return sal_False; 1135*cdf0e10cSrcweir 1136*cdf0e10cSrcweir // JB: Change: now the same name handling for sets of simple values 1137*cdf0e10cSrcweir const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode); 1138*cdf0e10cSrcweir const OUString* pSubNodeNames = aSubNodeNames.getConstArray(); 1139*cdf0e10cSrcweir const sal_Int32 nSubNodeCount = aSubNodeNames.getLength(); 1140*cdf0e10cSrcweir 1141*cdf0e10cSrcweir Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); 1142*cdf0e10cSrcweir const bool isSimpleValueSet = !xFac.is(); 1143*cdf0e10cSrcweir 1144*cdf0e10cSrcweir //remove unknown members first 1145*cdf0e10cSrcweir { 1146*cdf0e10cSrcweir const Sequence<OUString> aContainerSubNodes = xCont->getElementNames(); 1147*cdf0e10cSrcweir const OUString* pContainerSubNodes = aContainerSubNodes.getConstArray(); 1148*cdf0e10cSrcweir 1149*cdf0e10cSrcweir for(sal_Int32 nContSub = 0; nContSub < aContainerSubNodes.getLength(); nContSub++) 1150*cdf0e10cSrcweir { 1151*cdf0e10cSrcweir sal_Bool bFound = sal_False; 1152*cdf0e10cSrcweir for(sal_Int32 j = 0; j < nSubNodeCount; j++) 1153*cdf0e10cSrcweir { 1154*cdf0e10cSrcweir if(pSubNodeNames[j] == pContainerSubNodes[nContSub]) 1155*cdf0e10cSrcweir { 1156*cdf0e10cSrcweir bFound = sal_True; 1157*cdf0e10cSrcweir break; 1158*cdf0e10cSrcweir } 1159*cdf0e10cSrcweir } 1160*cdf0e10cSrcweir if(!bFound) 1161*cdf0e10cSrcweir try 1162*cdf0e10cSrcweir { 1163*cdf0e10cSrcweir xCont->removeByName(pContainerSubNodes[nContSub]); 1164*cdf0e10cSrcweir } 1165*cdf0e10cSrcweir catch (Exception & ) 1166*cdf0e10cSrcweir { 1167*cdf0e10cSrcweir if (isSimpleValueSet) 1168*cdf0e10cSrcweir try 1169*cdf0e10cSrcweir { 1170*cdf0e10cSrcweir // #i37322#: fallback action: replace with <void/> 1171*cdf0e10cSrcweir xCont->replaceByName(pContainerSubNodes[nContSub], Any()); 1172*cdf0e10cSrcweir // fallback successfull: continue looping 1173*cdf0e10cSrcweir continue; 1174*cdf0e10cSrcweir } 1175*cdf0e10cSrcweir catch (Exception &) 1176*cdf0e10cSrcweir {} // propagate original exception, if fallback fails 1177*cdf0e10cSrcweir 1178*cdf0e10cSrcweir throw; 1179*cdf0e10cSrcweir } 1180*cdf0e10cSrcweir } 1181*cdf0e10cSrcweir try { xBatch->commitChanges(); } 1182*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 1183*cdf0e10cSrcweir } 1184*cdf0e10cSrcweir 1185*cdf0e10cSrcweir if(xFac.is()) // !isSimpleValueSet 1186*cdf0e10cSrcweir { 1187*cdf0e10cSrcweir for(sal_Int32 j = 0; j < nSubNodeCount; j++) 1188*cdf0e10cSrcweir { 1189*cdf0e10cSrcweir if(!xCont->hasByName(pSubNodeNames[j])) 1190*cdf0e10cSrcweir { 1191*cdf0e10cSrcweir //create if not available 1192*cdf0e10cSrcweir Reference<XInterface> xInst = xFac->createInstance(); 1193*cdf0e10cSrcweir Any aVal; aVal <<= xInst; 1194*cdf0e10cSrcweir xCont->insertByName(pSubNodeNames[j], aVal); 1195*cdf0e10cSrcweir } 1196*cdf0e10cSrcweir } 1197*cdf0e10cSrcweir try { xBatch->commitChanges(); } 1198*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 1199*cdf0e10cSrcweir 1200*cdf0e10cSrcweir const PropertyValue* pProperties = rValues.getConstArray(); 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir Sequence< OUString > aSetNames(rValues.getLength()); 1203*cdf0e10cSrcweir OUString* pSetNames = aSetNames.getArray(); 1204*cdf0e10cSrcweir 1205*cdf0e10cSrcweir Sequence< Any> aSetValues(rValues.getLength()); 1206*cdf0e10cSrcweir Any* pSetValues = aSetValues.getArray(); 1207*cdf0e10cSrcweir 1208*cdf0e10cSrcweir sal_Bool bEmptyNode = rNode.getLength() == 0; 1209*cdf0e10cSrcweir for(sal_Int32 k = 0; k < rValues.getLength(); k++) 1210*cdf0e10cSrcweir { 1211*cdf0e10cSrcweir pSetNames[k] = pProperties[k].Name.copy( bEmptyNode ? 1 : 0); 1212*cdf0e10cSrcweir pSetValues[k] = pProperties[k].Value; 1213*cdf0e10cSrcweir } 1214*cdf0e10cSrcweir bRet = PutProperties(aSetNames, aSetValues); 1215*cdf0e10cSrcweir } 1216*cdf0e10cSrcweir else 1217*cdf0e10cSrcweir { 1218*cdf0e10cSrcweir const PropertyValue* pValues = rValues.getConstArray(); 1219*cdf0e10cSrcweir 1220*cdf0e10cSrcweir //if no factory is available then the node contains basic data elements 1221*cdf0e10cSrcweir for(int nValue = 0; nValue < rValues.getLength();nValue++) 1222*cdf0e10cSrcweir { 1223*cdf0e10cSrcweir try 1224*cdf0e10cSrcweir { 1225*cdf0e10cSrcweir OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode ); 1226*cdf0e10cSrcweir 1227*cdf0e10cSrcweir if(xCont->hasByName(sSubNode)) 1228*cdf0e10cSrcweir xCont->replaceByName(sSubNode, pValues[nValue].Value); 1229*cdf0e10cSrcweir else 1230*cdf0e10cSrcweir xCont->insertByName(sSubNode, pValues[nValue].Value); 1231*cdf0e10cSrcweir } 1232*cdf0e10cSrcweir CATCH_INFO("Exception from insert/replaceByName(): "); 1233*cdf0e10cSrcweir } 1234*cdf0e10cSrcweir xBatch->commitChanges(); 1235*cdf0e10cSrcweir } 1236*cdf0e10cSrcweir } 1237*cdf0e10cSrcweir #ifdef DBG_UTIL 1238*cdf0e10cSrcweir catch(Exception& rEx) 1239*cdf0e10cSrcweir { 1240*cdf0e10cSrcweir lcl_CFG_DBG_EXCEPTION("Exception from ReplaceSetProperties: ", rEx); 1241*cdf0e10cSrcweir #else 1242*cdf0e10cSrcweir catch(Exception&) 1243*cdf0e10cSrcweir { 1244*cdf0e10cSrcweir #endif 1245*cdf0e10cSrcweir bRet = sal_False; 1246*cdf0e10cSrcweir } 1247*cdf0e10cSrcweir } 1248*cdf0e10cSrcweir return bRet; 1249*cdf0e10cSrcweir } 1250*cdf0e10cSrcweir /* -----------------------------07.05.01 12:15-------------------------------- 1251*cdf0e10cSrcweir 1252*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1253*cdf0e10cSrcweir sal_Bool ConfigItem::getUniqueSetElementName( const ::rtl::OUString& _rSetNode, ::rtl::OUString& _rName) 1254*cdf0e10cSrcweir { 1255*cdf0e10cSrcweir ::rtl::OUString sNewElementName; 1256*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 1257*cdf0e10cSrcweir sal_Bool bRet = sal_False; 1258*cdf0e10cSrcweir if(xHierarchyAccess.is()) 1259*cdf0e10cSrcweir { 1260*cdf0e10cSrcweir try 1261*cdf0e10cSrcweir { 1262*cdf0e10cSrcweir Reference< XNameAccess > xSetNode; 1263*cdf0e10cSrcweir xHierarchyAccess->getByHierarchicalName(_rSetNode) >>= xSetNode; 1264*cdf0e10cSrcweir if (xSetNode.is()) 1265*cdf0e10cSrcweir { 1266*cdf0e10cSrcweir const sal_uInt32 nPrime = 65521; // a prime number 1267*cdf0e10cSrcweir const sal_uInt32 nPrimeLess2 = nPrime - 2; 1268*cdf0e10cSrcweir sal_uInt32 nEngendering = (rand() % nPrimeLess2) + 2; // the engendering of the field 1269*cdf0e10cSrcweir 1270*cdf0e10cSrcweir // the element which will loop through the field 1271*cdf0e10cSrcweir sal_uInt32 nFieldElement = nEngendering; 1272*cdf0e10cSrcweir 1273*cdf0e10cSrcweir for (; 1 != nFieldElement; nFieldElement = (nFieldElement * nEngendering) % nPrime) 1274*cdf0e10cSrcweir { 1275*cdf0e10cSrcweir ::rtl::OUString sThisRoundTrial = _rName; 1276*cdf0e10cSrcweir sThisRoundTrial += ::rtl::OUString::valueOf((sal_Int32)nFieldElement); 1277*cdf0e10cSrcweir 1278*cdf0e10cSrcweir if (!xSetNode->hasByName(sThisRoundTrial)) 1279*cdf0e10cSrcweir { 1280*cdf0e10cSrcweir _rName = sThisRoundTrial; 1281*cdf0e10cSrcweir bRet = sal_True; 1282*cdf0e10cSrcweir break; 1283*cdf0e10cSrcweir } 1284*cdf0e10cSrcweir } 1285*cdf0e10cSrcweir } 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir CATCH_INFO("Exception from getUniqueSetElementName(): ") 1288*cdf0e10cSrcweir } 1289*cdf0e10cSrcweir return bRet; 1290*cdf0e10cSrcweir } 1291*cdf0e10cSrcweir /* -----------------------------23.01.01 12:49-------------------------------- 1292*cdf0e10cSrcweir 1293*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1294*cdf0e10cSrcweir sal_Bool ConfigItem::AddNode(const rtl::OUString& rNode, const rtl::OUString& rNewNode) 1295*cdf0e10cSrcweir { 1296*cdf0e10cSrcweir ValueCounter_Impl aCounter(pImpl->nInValueChange); 1297*cdf0e10cSrcweir sal_Bool bRet = sal_True; 1298*cdf0e10cSrcweir Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree(); 1299*cdf0e10cSrcweir if(xHierarchyAccess.is()) 1300*cdf0e10cSrcweir { 1301*cdf0e10cSrcweir Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY); 1302*cdf0e10cSrcweir try 1303*cdf0e10cSrcweir { 1304*cdf0e10cSrcweir Reference<XNameContainer> xCont; 1305*cdf0e10cSrcweir if(rNode.getLength()) 1306*cdf0e10cSrcweir { 1307*cdf0e10cSrcweir Any aNode = xHierarchyAccess->getByHierarchicalName(rNode); 1308*cdf0e10cSrcweir aNode >>= xCont; 1309*cdf0e10cSrcweir } 1310*cdf0e10cSrcweir else 1311*cdf0e10cSrcweir xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY); 1312*cdf0e10cSrcweir if(!xCont.is()) 1313*cdf0e10cSrcweir return sal_False; 1314*cdf0e10cSrcweir 1315*cdf0e10cSrcweir Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY); 1316*cdf0e10cSrcweir 1317*cdf0e10cSrcweir if(xFac.is()) 1318*cdf0e10cSrcweir { 1319*cdf0e10cSrcweir if(!xCont->hasByName(rNewNode)) 1320*cdf0e10cSrcweir { 1321*cdf0e10cSrcweir Reference<XInterface> xInst = xFac->createInstance(); 1322*cdf0e10cSrcweir Any aVal; aVal <<= xInst; 1323*cdf0e10cSrcweir xCont->insertByName(rNewNode, aVal); 1324*cdf0e10cSrcweir } 1325*cdf0e10cSrcweir try 1326*cdf0e10cSrcweir { 1327*cdf0e10cSrcweir xBatch->commitChanges(); 1328*cdf0e10cSrcweir } 1329*cdf0e10cSrcweir CATCH_INFO("Exception from commitChanges(): ") 1330*cdf0e10cSrcweir } 1331*cdf0e10cSrcweir else 1332*cdf0e10cSrcweir { 1333*cdf0e10cSrcweir //if no factory is available then the node contains basic data elements 1334*cdf0e10cSrcweir try 1335*cdf0e10cSrcweir { 1336*cdf0e10cSrcweir if(!xCont->hasByName(rNewNode)) 1337*cdf0e10cSrcweir xCont->insertByName(rNewNode, Any()); 1338*cdf0e10cSrcweir } 1339*cdf0e10cSrcweir CATCH_INFO("Exception from AddNode(): ") 1340*cdf0e10cSrcweir } 1341*cdf0e10cSrcweir xBatch->commitChanges(); 1342*cdf0e10cSrcweir } 1343*cdf0e10cSrcweir #ifdef DBG_UTIL 1344*cdf0e10cSrcweir catch(Exception& rEx) 1345*cdf0e10cSrcweir { 1346*cdf0e10cSrcweir lcl_CFG_DBG_EXCEPTION("Exception from AddNode(): ", rEx); 1347*cdf0e10cSrcweir #else 1348*cdf0e10cSrcweir catch(Exception&) 1349*cdf0e10cSrcweir { 1350*cdf0e10cSrcweir #endif 1351*cdf0e10cSrcweir bRet = sal_False; 1352*cdf0e10cSrcweir } 1353*cdf0e10cSrcweir } 1354*cdf0e10cSrcweir return bRet; 1355*cdf0e10cSrcweir } 1356*cdf0e10cSrcweir /* -----------------------------12.02.01 11:38-------------------------------- 1357*cdf0e10cSrcweir 1358*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1359*cdf0e10cSrcweir sal_Int16 ConfigItem::GetMode() const 1360*cdf0e10cSrcweir { 1361*cdf0e10cSrcweir return pImpl->nMode; 1362*cdf0e10cSrcweir } 1363*cdf0e10cSrcweir /* -----------------------------12.02.01 13:31-------------------------------- 1364*cdf0e10cSrcweir 1365*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1366*cdf0e10cSrcweir void ConfigItem::SetModified() 1367*cdf0e10cSrcweir { 1368*cdf0e10cSrcweir pImpl->bIsModified = sal_True; 1369*cdf0e10cSrcweir } 1370*cdf0e10cSrcweir /* -----------------------------05.05.01 14:07-------------------------------- 1371*cdf0e10cSrcweir 1372*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1373*cdf0e10cSrcweir void ConfigItem::ClearModified() 1374*cdf0e10cSrcweir { 1375*cdf0e10cSrcweir pImpl->bIsModified = sal_False; 1376*cdf0e10cSrcweir } 1377*cdf0e10cSrcweir /* -----------------------------12.02.01 13:31-------------------------------- 1378*cdf0e10cSrcweir 1379*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1380*cdf0e10cSrcweir sal_Bool ConfigItem::IsModified() const 1381*cdf0e10cSrcweir { 1382*cdf0e10cSrcweir return pImpl->bIsModified; 1383*cdf0e10cSrcweir } 1384*cdf0e10cSrcweir /* -----------------------------12.02.01 13:33-------------------------------- 1385*cdf0e10cSrcweir 1386*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1387*cdf0e10cSrcweir sal_Bool ConfigItem::IsInValueChange() const 1388*cdf0e10cSrcweir { 1389*cdf0e10cSrcweir return pImpl->nInValueChange > 0; 1390*cdf0e10cSrcweir } 1391*cdf0e10cSrcweir /* -----------------------------21.06.01 12:26-------------------------------- 1392*cdf0e10cSrcweir 1393*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1394*cdf0e10cSrcweir Reference< XHierarchicalNameAccess> ConfigItem::GetTree() 1395*cdf0e10cSrcweir { 1396*cdf0e10cSrcweir Reference< XHierarchicalNameAccess> xRet; 1397*cdf0e10cSrcweir if(!m_xHierarchyAccess.is()) 1398*cdf0e10cSrcweir xRet = pImpl->pManager->AcquireTree(*this); 1399*cdf0e10cSrcweir else 1400*cdf0e10cSrcweir xRet = m_xHierarchyAccess; 1401*cdf0e10cSrcweir OSL_ENSURE(xRet.is(), "AcquireTree failed"); 1402*cdf0e10cSrcweir return xRet; 1403*cdf0e10cSrcweir } 1404*cdf0e10cSrcweir /* -----------------------------22.06.01 08:42-------------------------------- 1405*cdf0e10cSrcweir 1406*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1407*cdf0e10cSrcweir void ConfigItem::LockTree() 1408*cdf0e10cSrcweir { 1409*cdf0e10cSrcweir OSL_ENSURE(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "call LockTree in CONFIG_MODE_RELEASE_TREE mode, only"); 1410*cdf0e10cSrcweir m_xHierarchyAccess = GetTree(); 1411*cdf0e10cSrcweir } 1412*cdf0e10cSrcweir /* -----------------------------22.06.01 08:42-------------------------------- 1413*cdf0e10cSrcweir 1414*cdf0e10cSrcweir ---------------------------------------------------------------------------*/ 1415*cdf0e10cSrcweir void ConfigItem::UnlockTree() 1416*cdf0e10cSrcweir { 1417*cdf0e10cSrcweir OSL_ENSURE(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "call UnlockTree in CONFIG_MODE_RELEASE_TREE mode, only"); 1418*cdf0e10cSrcweir if(0 != (pImpl->nMode&CONFIG_MODE_RELEASE_TREE)) 1419*cdf0e10cSrcweir m_xHierarchyAccess = 0; 1420*cdf0e10cSrcweir } 1421*cdf0e10cSrcweir 1422*cdf0e10cSrcweir 1423