LCOV - code coverage report
Current view: top level - unotools/source/config - configitem.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 309 489 63.2 %
Date: 2014-11-03 Functions: 28 33 84.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <unotools/configitem.hxx>
      21             : #include <unotools/configmgr.hxx>
      22             : #include <unotools/configpaths.hxx>
      23             : #include <comphelper/processfactory.hxx>
      24             : #include <com/sun/star/beans/XMultiPropertySet.hpp>
      25             : #include <com/sun/star/beans/XPropertySet.hpp>
      26             : #include <com/sun/star/util/XChangesListener.hpp>
      27             : #include <com/sun/star/util/XChangesNotifier.hpp>
      28             : #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
      29             : #include <com/sun/star/container/XHierarchicalName.hpp>
      30             : #include <com/sun/star/configuration/XTemplateContainer.hpp>
      31             : #include <com/sun/star/container/XNameContainer.hpp>
      32             : #include <com/sun/star/lang/XSingleServiceFactory.hpp>
      33             : #include <com/sun/star/lang/XServiceInfo.hpp>
      34             : #include <com/sun/star/awt/XRequestCallback.hpp>
      35             : #include <com/sun/star/beans/PropertyValue.hpp>
      36             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      37             : #include <com/sun/star/util/XStringEscape.hpp>
      38             : #include <com/sun/star/util/XChangesBatch.hpp>
      39             : #include <osl/diagnose.h>
      40             : #include <tools/solarmutex.hxx>
      41             : #include <rtl/ustrbuf.hxx>
      42             : 
      43             : using namespace utl;
      44             : using namespace com::sun::star::uno;
      45             : using namespace com::sun::star::util;
      46             : using namespace com::sun::star::lang;
      47             : using namespace com::sun::star::beans;
      48             : using namespace com::sun::star::container;
      49             : using namespace com::sun::star::configuration;
      50             : 
      51             : #include <cppuhelper/implbase1.hxx>
      52             : 
      53             : #ifdef DBG_UTIL
      54             : static inline void lcl_CFG_DBG_EXCEPTION(const sal_Char* cText, const Exception& rEx)
      55             : {
      56             :     OString sMsg(cText);
      57             :     sMsg += OString(rEx.Message.getStr(), rEx.Message.getLength(), RTL_TEXTENCODING_ASCII_US);
      58             :     OSL_FAIL(sMsg.getStr());
      59             : }
      60             : #define CATCH_INFO(a) \
      61             : catch(const Exception& rEx)   \
      62             : {                       \
      63             :     lcl_CFG_DBG_EXCEPTION(a, rEx);\
      64             : }
      65             : #else
      66             :     #define CATCH_INFO(a) catch(const Exception&){}
      67             : #endif
      68             : 
      69             : /*
      70             :     The ConfigChangeListener_Impl receives notifications from the configuration about changes that
      71             :     have happened. It forwards this notification to the ConfigItem it knows a pParent by calling its
      72             :     "CallNotify" method. As ConfigItems are most probably not thread safe, the SolarMutex is acquired
      73             :     before doing so.
      74             : */
      75             : 
      76             : namespace utl{
      77             :     class ConfigChangeListener_Impl : public cppu::WeakImplHelper1
      78             :     <
      79             :         com::sun::star::util::XChangesListener
      80             :     >
      81             :     {
      82             :         public:
      83             :             ConfigItem*                 pParent;
      84             :             const Sequence< OUString >  aPropertyNames;
      85             :             ConfigChangeListener_Impl(ConfigItem& rItem, const Sequence< OUString >& rNames);
      86             :             virtual ~ConfigChangeListener_Impl();
      87             : 
      88             :         //XChangesListener
      89             :         virtual void SAL_CALL changesOccurred( const ChangesEvent& Event ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
      90             : 
      91             :         //XEventListener
      92             :         virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
      93             :     };
      94             : }
      95             : 
      96             : class ValueCounter_Impl
      97             : {
      98             :     sal_Int16& rCnt;
      99             : public:
     100        4736 :     ValueCounter_Impl(sal_Int16& rCounter):
     101        4736 :         rCnt(rCounter)
     102        4736 :             {rCnt++;}
     103        4736 :     ~ValueCounter_Impl()
     104             :             {
     105             :                 OSL_ENSURE(rCnt>0, "RefCount < 0 ??");
     106        4736 :                 rCnt--;
     107        4736 :             }
     108             : };
     109             : 
     110       20840 : ConfigChangeListener_Impl::ConfigChangeListener_Impl(
     111             :              ConfigItem& rItem, const Sequence< OUString >& rNames) :
     112             :     pParent(&rItem),
     113       20840 :     aPropertyNames(rNames)
     114             : {
     115       20840 : }
     116             : 
     117       38700 : ConfigChangeListener_Impl::~ConfigChangeListener_Impl()
     118             : {
     119       38700 : }
     120             : 
     121       44854 : static bool lcl_Find(
     122             :         const OUString& rTemp,
     123             :         const OUString* pCheckPropertyNames,
     124             :         sal_Int32 nLength)
     125             : {
     126             :     //return true if the path is completely correct or if it is longer
     127             :     //i.e ...Print/Content/Graphic and .../Print
     128      434752 :     for(sal_Int32 nIndex = 0; nIndex < nLength; nIndex++)
     129      417936 :         if( isPrefixOfConfigurationPath(rTemp, pCheckPropertyNames[nIndex]) )
     130       28038 :             return true;
     131       16816 :     return false;
     132             : }
     133             : 
     134       36244 : void ConfigChangeListener_Impl::changesOccurred( const ChangesEvent& rEvent ) throw(RuntimeException, std::exception)
     135             : {
     136       36244 :     const ElementChange* pElementChanges = rEvent.Changes.getConstArray();
     137             : 
     138       36244 :     Sequence<OUString>  aChangedNames(rEvent.Changes.getLength());
     139       36244 :     OUString* pNames = aChangedNames.getArray();
     140             : 
     141       36244 :     const OUString* pCheckPropertyNames = aPropertyNames.getConstArray();
     142             : 
     143       36244 :     sal_Int32 nNotify = 0;
     144       81098 :     for(int i = 0; i < aChangedNames.getLength(); i++)
     145             :     {
     146       44854 :         OUString sTemp;
     147       44854 :         pElementChanges[i].Accessor >>= sTemp;
     148       44854 :         if(lcl_Find(sTemp, pCheckPropertyNames, aPropertyNames.getLength()))
     149       28038 :             pNames[nNotify++] = sTemp;
     150       44854 :     }
     151       36244 :     if( nNotify )
     152             :     {
     153       23746 :         if ( ::tools::SolarMutex::Acquire() )
     154             :         {
     155       23746 :             aChangedNames.realloc(nNotify);
     156       23746 :             pParent->CallNotify(aChangedNames);
     157       23746 :             ::tools::SolarMutex::Release();
     158             :         }
     159       36244 :     }
     160       36244 : }
     161             : 
     162           0 : void ConfigChangeListener_Impl::disposing( const EventObject& /*rSource*/ ) throw(RuntimeException, std::exception)
     163             : {
     164           0 :     pParent->RemoveChangesListener();
     165           0 : }
     166             : 
     167       40035 : ConfigItem::ConfigItem(const OUString &rSubTree, sal_Int16 nSetMode ) :
     168             :     sSubTree(rSubTree),
     169             :     m_nMode(nSetMode),
     170             :     m_bIsModified(false),
     171             :     m_bEnableInternalNotification(false),
     172       40035 :     m_nInValueChange(0)
     173             : {
     174       40035 :     if(0 != (nSetMode&CONFIG_MODE_RELEASE_TREE))
     175        1500 :         ConfigManager::getConfigManager().addConfigItem(*this);
     176             :     else
     177       38535 :         m_xHierarchyAccess = ConfigManager::getConfigManager().addConfigItem(*this);
     178       40035 : }
     179             : 
     180       75306 : ConfigItem::~ConfigItem()
     181             : {
     182       37653 :     RemoveChangesListener();
     183       37653 :     ConfigManager::getConfigManager().removeConfigItem(*this);
     184       37653 : }
     185             : 
     186       23746 : void ConfigItem::CallNotify( const com::sun::star::uno::Sequence<OUString>& rPropertyNames )
     187             : {
     188             :     // the call is forwarded to the virtual Notify() method
     189             :     // it is pure virtual, so all classes deriving from ConfigItem have to decide how they
     190             :     // want to notify listeners
     191       23746 :     if(!IsInValueChange() || m_bEnableInternalNotification)
     192         180 :         Notify(rPropertyNames);
     193       23746 : }
     194             : 
     195           0 : void ConfigItem::impl_packLocalizedProperties(  const   Sequence< OUString >&   lInNames    ,
     196             :                                                 const   Sequence< Any >&        lInValues   ,
     197             :                                                         Sequence< Any >&        lOutValues  )
     198             : {
     199             :     // Safe impossible cases.
     200             :     // This method should be called for special ConfigItem-mode only!
     201             :     OSL_ENSURE( ((m_nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_packLocalizedProperties()\nWrong call of this method detected!\n" );
     202             : 
     203             :     sal_Int32                   nSourceCounter;      // used to step during input lists
     204             :     sal_Int32                   nSourceSize;         // marks end of loop over input lists
     205             :     sal_Int32                   nDestinationCounter; // actual position in output lists
     206             :     sal_Int32                   nPropertyCounter;    // counter of inner loop for Sequence< PropertyValue >
     207             :     sal_Int32                   nPropertiesSize;     // marks end of inner loop
     208           0 :     Sequence< OUString >        lPropertyNames;      // list of all locales for localized entry
     209           0 :     Sequence< PropertyValue >   lProperties;         // localized values of an configuration entry packed for return
     210           0 :     Reference< XInterface >     xLocalizedNode;      // if cfg entry is localized ... lInValues contains an XInterface!
     211             : 
     212             :     // Optimise follow algorithm ... A LITTLE BIT :-)
     213             :     // There exist two different possibilities:
     214             :     //  i ) There exist no localized entries ...                        =>  size of lOutValues will be the same like lInNames/lInValues!
     215             :     //  ii) There exist some (mostly one or two) localized entries ...  =>  size of lOutValues will be the same like lInNames/lInValues!
     216             :     //  ... Why? If a localized value exist - the any is filled with an XInterface object (is a SetNode-service).
     217             :     //      We read all his child nodes and pack it into Sequence< PropertyValue >.
     218             :     //      The result list we pack into the return any. We never change size of lists!
     219           0 :     nSourceSize = lInNames.getLength();
     220           0 :     lOutValues.realloc( nSourceSize );
     221             : 
     222             :     // Algorithm:
     223             :     // Copy all names and values from in to out lists.
     224             :     // Look for special localized entries ... You can detect it as "XInterface" packed into an Any.
     225             :     // Use this XInterface-object to read all localized values and pack it into Sequence< PropertValue >.
     226             :     // Add this list to out lists then.
     227             : 
     228           0 :     nDestinationCounter = 0;
     229           0 :     for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
     230             :     {
     231             :         // If item a special localized one ... convert and pack it ...
     232           0 :         if( lInValues[nSourceCounter].getValueTypeName() == "com.sun.star.uno.XInterface" )
     233             :         {
     234           0 :             lInValues[nSourceCounter] >>= xLocalizedNode;
     235           0 :             Reference< XNameContainer > xSetAccess( xLocalizedNode, UNO_QUERY );
     236           0 :             if( xSetAccess.is() )
     237             :             {
     238           0 :                 lPropertyNames  =   xSetAccess->getElementNames();
     239           0 :                 nPropertiesSize =   lPropertyNames.getLength();
     240           0 :                 lProperties.realloc( nPropertiesSize );
     241             : 
     242           0 :                 for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter )
     243             :                 {
     244           0 :                     lProperties[nPropertyCounter].Name  =   lPropertyNames[nPropertyCounter];
     245           0 :                     OUString sLocaleValue;
     246           0 :                     xSetAccess->getByName( lPropertyNames[nPropertyCounter] ) >>= sLocaleValue;
     247           0 :                     lProperties[nPropertyCounter].Value <<= sLocaleValue;
     248           0 :                 }
     249             : 
     250           0 :                 lOutValues[nDestinationCounter] <<= lProperties;
     251           0 :             }
     252             :         }
     253             :         // ... or copy normal items to return lists directly.
     254             :         else
     255             :         {
     256           0 :             lOutValues[nDestinationCounter] = lInValues[nSourceCounter];
     257             :         }
     258           0 :         ++nDestinationCounter;
     259           0 :     }
     260           0 : }
     261             : 
     262           0 : void ConfigItem::impl_unpackLocalizedProperties(    const   Sequence< OUString >&   lInNames    ,
     263             :                                                     const   Sequence< Any >&        lInValues   ,
     264             :                                                             Sequence< OUString >&   lOutNames   ,
     265             :                                                             Sequence< Any >&        lOutValues  )
     266             : {
     267             :     // Safe impossible cases.
     268             :     // This method should be called for special ConfigItem-mode only!
     269             :     OSL_ENSURE( ((m_nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_unpackLocalizedProperties()\nWrong call of this method detected!\n" );
     270             : 
     271             :     sal_Int32                   nSourceCounter;      // used to step during input lists
     272             :     sal_Int32                   nSourceSize;         // marks end of loop over input lists
     273             :     sal_Int32                   nDestinationCounter; // actual position in output lists
     274             :     sal_Int32                   nPropertyCounter;    // counter of inner loop for Sequence< PropertyValue >
     275             :     sal_Int32                   nPropertiesSize;     // marks end of inner loop
     276           0 :     OUString                    sNodeName;           // base name of node ( e.g. "UIName/" ) ... expand to locale ( e.g. "UIName/de" )
     277           0 :     Sequence< PropertyValue >   lProperties;         // localized values of an configuration entry getted from lInValues-Any
     278             : 
     279             :     // Optimise follow algorithm ... A LITTLE BIT :-)
     280             :     // There exist two different possibilities:
     281             :     //  i ) There exist no localized entries ...                        =>  size of lOutNames/lOutValues will be the same like lInNames/lInValues!
     282             :     //  ii) There exist some (mostly one or two) localized entries ...  =>  size of lOutNames/lOutValues will be some bytes greater then lInNames/lInValues.
     283             :     //  =>  I think we should make it fast for i). ii) is a special case and mustn't be SOOOO... fast.
     284             :     //      We should reserve same space for output list like input ones first.
     285             :     //      Follow algorithm looks for these borders and change it for ii) only!
     286             :     //      It will be faster then a "realloc()" call in every loop ...
     287           0 :     nSourceSize = lInNames.getLength();
     288             : 
     289           0 :     lOutNames.realloc   ( nSourceSize );
     290           0 :     lOutValues.realloc  ( nSourceSize );
     291             : 
     292             :     // Algorithm:
     293             :     // Copy all names and values from const to return lists.
     294             :     // Look for special localized entries ... You can detect it as Sequence< PropertyValue > packed into an Any.
     295             :     // Split it ... insert PropertyValue.Name to lOutNames and PropertyValue.Value to lOutValues.
     296             : 
     297           0 :     nDestinationCounter = 0;
     298           0 :     for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
     299             :     {
     300             :         // If item a special localized one ... split it and insert his parts to output lists ...
     301           0 :         if( lInValues[nSourceCounter].getValueType() == ::getCppuType( (const Sequence< PropertyValue >*)NULL ) )
     302             :         {
     303           0 :             lInValues[nSourceCounter] >>= lProperties;
     304           0 :             nPropertiesSize = lProperties.getLength();
     305             : 
     306           0 :             sNodeName = lInNames[nSourceCounter] + "/";
     307             : 
     308           0 :             if( (nDestinationCounter+nPropertiesSize) > lOutNames.getLength() )
     309             :             {
     310           0 :                 lOutNames.realloc   ( nDestinationCounter+nPropertiesSize );
     311           0 :                 lOutValues.realloc  ( nDestinationCounter+nPropertiesSize );
     312             :             }
     313             : 
     314           0 :             for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter )
     315             :             {
     316           0 :                  lOutNames [nDestinationCounter] = sNodeName + lProperties[nPropertyCounter].Name;
     317           0 :                 lOutValues[nDestinationCounter] = lProperties[nPropertyCounter].Value;
     318           0 :                 ++nDestinationCounter;
     319             :             }
     320             :         }
     321             :         // ... or copy normal items to return lists directly.
     322             :         else
     323             :         {
     324           0 :             if( (nDestinationCounter+1) > lOutNames.getLength() )
     325             :             {
     326           0 :                 lOutNames.realloc   ( nDestinationCounter+1 );
     327           0 :                 lOutValues.realloc  ( nDestinationCounter+1 );
     328             :             }
     329             : 
     330           0 :             lOutNames [nDestinationCounter] = lInNames [nSourceCounter];
     331           0 :             lOutValues[nDestinationCounter] = lInValues[nSourceCounter];
     332           0 :             ++nDestinationCounter;
     333             :         }
     334           0 :     }
     335           0 : }
     336             : 
     337        1630 : Sequence< sal_Bool > ConfigItem::GetReadOnlyStates(const com::sun::star::uno::Sequence< OUString >& rNames)
     338             : {
     339             :     sal_Int32 i;
     340             : 
     341             :     // size of return list is fix!
     342             :     // Every item must match to length of incoming name list.
     343        1630 :     sal_Int32 nCount = rNames.getLength();
     344        1630 :     Sequence< sal_Bool > lStates(nCount);
     345             : 
     346             :     // We must be sure to return a valid information everytime!
     347             :     // Set default to non readonly ... similar to the configuration handling of this property.
     348       21120 :     for ( i=0; i<nCount; ++i)
     349       19490 :         lStates[i] = sal_False;
     350             : 
     351             :     // no access - no information ...
     352        3260 :     Reference< XHierarchicalNameAccess > xHierarchyAccess = GetTree();
     353        1630 :     if (!xHierarchyAccess.is())
     354           0 :         return lStates;
     355             : 
     356       21120 :     for (i=0; i<nCount; ++i)
     357             :     {
     358             :         try
     359             :         {
     360       19490 :             OUString sName = rNames[i];
     361       38980 :             OUString sPath;
     362       38980 :             OUString sProperty;
     363             : 
     364       19490 :             (void)::utl::splitLastFromConfigurationPath(sName,sPath,sProperty);
     365       19490 :             if (sPath.isEmpty() && sProperty.isEmpty())
     366             :             {
     367             :                 OSL_FAIL("ConfigItem::IsReadonly()\nsplitt failed\n");
     368           0 :                 continue;
     369             :             }
     370             : 
     371       38980 :             Reference< XInterface >       xNode;
     372       38980 :             Reference< XPropertySet >     xSet;
     373       38980 :             Reference< XPropertySetInfo > xInfo;
     374       19490 :             if (!sPath.isEmpty())
     375             :             {
     376        7596 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(sPath);
     377        7596 :                 if (!(aNode >>= xNode) || !xNode.is())
     378             :                 {
     379             :                     OSL_FAIL("ConfigItem::IsReadonly()\nno set available\n");
     380           0 :                     continue;
     381        7596 :                 }
     382             :             }
     383             :             else
     384             :             {
     385       11894 :                 xNode = Reference<XInterface>( xHierarchyAccess, UNO_QUERY );
     386             :             }
     387             : 
     388       19490 :         xSet = Reference< XPropertySet >(xNode, UNO_QUERY);
     389       19490 :             if (xSet.is())
     390             :         {
     391       19490 :             xInfo = xSet->getPropertySetInfo();
     392             :                 OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\ngetPropertySetInfo failed ...\n");
     393             :         }
     394             :             else
     395             :         {
     396           0 :                xInfo = Reference< XPropertySetInfo >(xNode, UNO_QUERY);
     397             :                 OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\nUNO_QUERY failed ...\n");
     398             :         }
     399             : 
     400       19490 :             if (!xInfo.is())
     401             :             {
     402             :                 OSL_FAIL("ConfigItem::IsReadonly()\nno prop info available\n");
     403           0 :                 continue;
     404             :             }
     405             : 
     406       38980 :             Property aProp = xInfo->getPropertyByName(sProperty);
     407       38980 :             lStates[i] = ((aProp.Attributes & PropertyAttribute::READONLY) == PropertyAttribute::READONLY);
     408             :         }
     409           0 :         catch (const Exception&)
     410             :         {
     411             :         }
     412             :     }
     413             : 
     414        1630 :     return lStates;
     415             : }
     416             : 
     417      189485 : Sequence< Any > ConfigItem::GetProperties(const Sequence< OUString >& rNames)
     418             : {
     419      189485 :     Sequence< Any > aRet(rNames.getLength());
     420      189485 :     const OUString* pNames = rNames.getConstArray();
     421      189485 :     Any* pRet = aRet.getArray();
     422      378970 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     423      189485 :     if(xHierarchyAccess.is())
     424             :     {
     425     1405068 :         for(int i = 0; i < rNames.getLength(); i++)
     426             :         {
     427             :             try
     428             :             {
     429     1215583 :                 pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]);
     430             :             }
     431           4 :             catch (const Exception& rEx)
     432             :             {
     433             :                 SAL_WARN(
     434             :                     "unotools.config",
     435             :                     "ignoring XHierarchicalNameAccess to /org.openoffice."
     436             :                         << sSubTree << "/" << pNames[i] << " Exception: "
     437             :                         << rEx.Message);
     438             :             }
     439             :         }
     440             : 
     441             :         // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >.
     442      189485 :         if((m_nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES)
     443             :         {
     444           0 :             Sequence< Any > lValues;
     445           0 :             impl_packLocalizedProperties( rNames, aRet, lValues );
     446           0 :             aRet = lValues;
     447             :         }
     448             :     }
     449      378970 :     return aRet;
     450             : }
     451             : 
     452        3724 : bool ConfigItem::PutProperties( const Sequence< OUString >& rNames,
     453             :                                                 const Sequence< Any>& rValues)
     454             : {
     455        3724 :     ValueCounter_Impl aCounter(m_nInValueChange);
     456        7448 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     457        7448 :     Reference<XNameReplace> xTopNodeReplace(xHierarchyAccess, UNO_QUERY);
     458        3724 :     bool bRet = xHierarchyAccess.is() && xTopNodeReplace.is();
     459        3724 :     if(bRet)
     460             :     {
     461        3724 :         Sequence< OUString >    lNames;
     462        7448 :         Sequence< Any >         lValues;
     463        3724 :         const OUString*         pNames  = NULL;
     464        3724 :         const Any*              pValues = NULL;
     465             :         sal_Int32               nNameCount;
     466        3724 :         if(( m_nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES )
     467             :         {
     468             :             // If ConfigItem works in "ALL_LOCALES"-mode ... we must support a Sequence< PropertyValue >
     469             :             // as value of an localized configuration entry!
     470             :             // How we can do that?
     471             :             // We must split all PropertyValues to "Sequence< OUString >" AND "Sequence< Any >"!
     472           0 :             impl_unpackLocalizedProperties( rNames, rValues, lNames, lValues );
     473           0 :             pNames      = lNames.getConstArray  ();
     474           0 :             pValues     = lValues.getConstArray ();
     475           0 :             nNameCount  = lNames.getLength      ();
     476             :         }
     477             :         else
     478             :         {
     479             :             // This is the normal mode ...
     480             :             // Use given input lists directly.
     481        3724 :             pNames      = rNames.getConstArray  ();
     482        3724 :             pValues     = rValues.getConstArray ();
     483        3724 :             nNameCount  = rNames.getLength      ();
     484             :         }
     485       29196 :         for(int i = 0; i < nNameCount; i++)
     486             :         {
     487             :             try
     488             :             {
     489       50944 :                 OUString sNode, sProperty;
     490       25472 :                 if (splitLastFromConfigurationPath(pNames[i],sNode, sProperty))
     491             :                 {
     492        3350 :                     Any aNode = xHierarchyAccess->getByHierarchicalName(sNode);
     493             : 
     494        6700 :                     Reference<XNameAccess> xNodeAcc;
     495        3350 :                     aNode >>= xNodeAcc;
     496        6700 :                     Reference<XNameReplace>   xNodeReplace(xNodeAcc, UNO_QUERY);
     497        6700 :                     Reference<XNameContainer> xNodeCont   (xNodeAcc, UNO_QUERY);
     498             : 
     499        3350 :                     bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty));
     500        3350 :                     if (bExist && xNodeReplace.is())
     501        3350 :                         xNodeReplace->replaceByName(sProperty, pValues[i]);
     502             :                     else
     503           0 :                         if (!bExist && xNodeCont.is())
     504           0 :                             xNodeCont->insertByName(sProperty, pValues[i]);
     505             :                         else
     506        3350 :                             bRet = false;
     507             :                 }
     508             :                 else //direct value
     509             :                 {
     510       22122 :                     xTopNodeReplace->replaceByName(sProperty, pValues[i]);
     511       25472 :                 }
     512             :             }
     513           0 :             CATCH_INFO("Exception from PutProperties: ");
     514             :         }
     515             :         try
     516             :         {
     517        3724 :             Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     518        3724 :             xBatch->commitChanges();
     519             :         }
     520        3724 :         CATCH_INFO("Exception from commitChanges(): ")
     521             :     }
     522             : 
     523        7448 :     return bRet;
     524             : }
     525             : 
     526        5450 : void ConfigItem::DisableNotification()
     527             : {
     528             :     OSL_ENSURE( xChangeLstnr.is(), "ConfigItem::DisableNotification: notifications not enabled currently!" );
     529        5450 :     RemoveChangesListener();
     530        5450 : }
     531             : 
     532       20840 : bool    ConfigItem::EnableNotification(const Sequence< OUString >& rNames,
     533             :                 bool bEnableInternalNotification )
     534             : 
     535             : {
     536             :     OSL_ENSURE(0 == (m_nMode&CONFIG_MODE_RELEASE_TREE), "notification in CONFIG_MODE_RELEASE_TREE mode not possible");
     537       20840 :     m_bEnableInternalNotification = bEnableInternalNotification;
     538       20840 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     539       41680 :     Reference<XChangesNotifier> xChgNot(xHierarchyAccess, UNO_QUERY);
     540       20840 :     if(!xChgNot.is())
     541           0 :         return false;
     542             : 
     543             :     OSL_ENSURE(!xChangeLstnr.is(), "EnableNotification already called");
     544       20840 :     if(xChangeLstnr.is())
     545           0 :         xChgNot->removeChangesListener( xChangeLstnr );
     546       20840 :     bool bRet = true;
     547             : 
     548             :     try
     549             :     {
     550       20840 :         xChangeLstnr = new ConfigChangeListener_Impl(*this, rNames);
     551       20840 :         xChgNot->addChangesListener( xChangeLstnr );
     552             :     }
     553           0 :     catch (const RuntimeException&)
     554             :     {
     555           0 :         bRet = false;
     556             :     }
     557       41680 :     return bRet;
     558             : }
     559             : 
     560       43103 : void ConfigItem::RemoveChangesListener()
     561             : {
     562       43103 :     Reference<XChangesNotifier> xChgNot(m_xHierarchyAccess, UNO_QUERY);
     563       43103 :     if(xChgNot.is() && xChangeLstnr.is())
     564             :     {
     565             :         try
     566             :         {
     567       19350 :             xChgNot->removeChangesListener( xChangeLstnr );
     568       19350 :             xChangeLstnr = 0;
     569             :         }
     570           0 :         catch (const Exception&)
     571             :         {
     572             :         }
     573       43103 :     }
     574       43103 : }
     575             : 
     576       56169 : static void lcl_normalizeLocalNames(Sequence< OUString >& _rNames, ConfigNameFormat _eFormat, Reference<XInterface> const& _xParentNode)
     577             : {
     578       56169 :     switch (_eFormat)
     579             :     {
     580             :     case CONFIG_NAME_LOCAL_NAME:
     581             :         // unaltered - this is our input format
     582       54973 :         break;
     583             : 
     584             :     case CONFIG_NAME_FULL_PATH:
     585             :         {
     586           0 :             Reference<XHierarchicalName> xFormatter(_xParentNode, UNO_QUERY);
     587           0 :             if (xFormatter.is())
     588             :             {
     589           0 :                 OUString * pNames = _rNames.getArray();
     590           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     591             :                 {
     592             :                     try
     593             :                     {
     594           0 :                         pNames[i] = xFormatter->composeHierarchicalName(pNames[i]);
     595             :                     }
     596           0 :                     CATCH_INFO("Exception from composeHierarchicalName(): ")
     597             :                 }
     598           0 :                 break;
     599           0 :             }
     600             :         }
     601             :         OSL_FAIL("Cannot create absolute paths: missing interface");
     602             :         // make local paths instaed
     603             : 
     604             :     case CONFIG_NAME_LOCAL_PATH:
     605             :         {
     606        1196 :             Reference<XTemplateContainer> xTypeContainer(_xParentNode, UNO_QUERY);
     607        1196 :             if (xTypeContainer.is())
     608             :             {
     609           0 :                 OUString sTypeName = xTypeContainer->getElementTemplateName();
     610           0 :                 sTypeName = sTypeName.copy(sTypeName.lastIndexOf('/')+1);
     611             : 
     612           0 :                 OUString * pNames = _rNames.getArray();
     613           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     614             :                 {
     615           0 :                     pNames[i] = wrapConfigurationElementName(pNames[i],sTypeName);
     616           0 :                 }
     617             :             }
     618             :             else
     619             :             {
     620        1196 :                 Reference<XServiceInfo> xSVI(_xParentNode, UNO_QUERY);
     621        1196 :                 if (xSVI.is() && xSVI->supportsService("com.sun.star.configuration.SetAccess"))
     622             :                 {
     623        1196 :                     OUString * pNames = _rNames.getArray();
     624        4286 :                     for(int i = 0; i<_rNames.getLength(); ++i)
     625             :                     {
     626        3090 :                         pNames[i] = wrapConfigurationElementName(pNames[i]);
     627             :                     }
     628        1196 :                 }
     629        1196 :             }
     630             :         }
     631        1196 :         break;
     632             : 
     633             :     case CONFIG_NAME_PLAINTEXT_NAME:
     634             :         {
     635           0 :             Reference<XStringEscape> xEscaper(_xParentNode, UNO_QUERY);
     636           0 :             if (xEscaper.is())
     637             :             {
     638           0 :                 OUString * pNames = _rNames.getArray();
     639           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     640             :                 try
     641             :                 {
     642           0 :                     pNames[i] = xEscaper->unescapeString(pNames[i]);
     643             :                 }
     644           0 :                 CATCH_INFO("Exception from unescapeString(): ")
     645           0 :             }
     646             :         }
     647           0 :         break;
     648             : 
     649             :     }
     650       56169 : }
     651             : 
     652       54973 : Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode)
     653             : {
     654       54973 :     ConfigNameFormat const eDefaultFormat = CONFIG_NAME_LOCAL_NAME; // CONFIG_NAME_DEFAULT;
     655             : 
     656       54973 :     return GetNodeNames(rNode, eDefaultFormat);
     657             : }
     658             : 
     659       56169 : Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode, ConfigNameFormat eFormat)
     660             : {
     661       56169 :     Sequence< OUString > aRet;
     662      112338 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     663       56169 :     if(xHierarchyAccess.is())
     664             :     {
     665             :         try
     666             :         {
     667       56169 :             Reference<XNameAccess> xCont;
     668       56169 :             if(!rNode.isEmpty())
     669             :             {
     670       55675 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     671       55675 :                 aNode >>= xCont;
     672             :             }
     673             :             else
     674         494 :                 xCont = Reference<XNameAccess> (xHierarchyAccess, UNO_QUERY);
     675       56169 :             if(xCont.is())
     676             :             {
     677       56169 :                 aRet = xCont->getElementNames();
     678       56169 :                 lcl_normalizeLocalNames(aRet,eFormat,xCont);
     679       56169 :             }
     680             : 
     681             :         }
     682           0 :         CATCH_INFO("Exception from GetNodeNames: ");
     683             :     }
     684      112338 :     return aRet;
     685             : }
     686             : 
     687           8 : bool ConfigItem::ClearNodeSet(const OUString& rNode)
     688             : {
     689           8 :     ValueCounter_Impl aCounter(m_nInValueChange);
     690           8 :     bool bRet = false;
     691          16 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     692           8 :     if(xHierarchyAccess.is())
     693             :     {
     694             :         try
     695             :         {
     696           8 :             Reference<XNameContainer> xCont;
     697           8 :             if(!rNode.isEmpty())
     698             :             {
     699           8 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     700           8 :                 aNode >>= xCont;
     701             :             }
     702             :             else
     703           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     704           8 :             if(!xCont.is())
     705           0 :                 return false;
     706          16 :             Sequence< OUString > aNames = xCont->getElementNames();
     707           8 :             const OUString* pNames = aNames.getConstArray();
     708          16 :             Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     709          38 :             for(sal_Int32 i = 0; i < aNames.getLength(); i++)
     710             :             {
     711             :                 try
     712             :                 {
     713          30 :                     xCont->removeByName(pNames[i]);
     714             :                 }
     715           0 :                 CATCH_INFO("Exception from removeByName(): ")
     716             :             }
     717           8 :             xBatch->commitChanges();
     718          16 :             bRet = true;
     719             :         }
     720           0 :         CATCH_INFO("Exception from ClearNodeSet")
     721             :     }
     722          16 :     return bRet;
     723             : }
     724             : 
     725          50 : bool ConfigItem::ClearNodeElements(const OUString& rNode, Sequence< OUString >& rElements)
     726             : {
     727          50 :     ValueCounter_Impl aCounter(m_nInValueChange);
     728          50 :     bool bRet = false;
     729         100 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     730          50 :     if(xHierarchyAccess.is())
     731             :     {
     732          50 :         const OUString* pElements = rElements.getConstArray();
     733             :         try
     734             :         {
     735          50 :             Reference<XNameContainer> xCont;
     736          50 :             if(!rNode.isEmpty())
     737             :             {
     738          50 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     739          50 :                 aNode >>= xCont;
     740             :             }
     741             :             else
     742           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     743          50 :             if(!xCont.is())
     744           0 :                 return false;
     745             :             try
     746             :             {
     747          70 :                 for(sal_Int32 nElement = 0; nElement < rElements.getLength(); nElement++)
     748             :                 {
     749          50 :                     xCont->removeByName(pElements[nElement]);
     750             :                 }
     751          20 :                 Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     752          20 :                 xBatch->commitChanges();
     753             :             }
     754          30 :             CATCH_INFO("Exception from commitChanges(): ")
     755          50 :             bRet = true;
     756             :         }
     757           0 :         CATCH_INFO("Exception from GetNodeNames: ")
     758             :     }
     759         100 :     return bRet;
     760             : }
     761             : 
     762             : static inline
     763        6160 : OUString lcl_extractSetPropertyName( const OUString& rInPath, const OUString& rPrefix )
     764             : {
     765        6160 :     OUString const sSubPath = dropPrefixFromConfigurationPath( rInPath, rPrefix);
     766        6160 :     return extractFirstFromConfigurationPath( sSubPath );
     767             : }
     768             : 
     769             : static
     770         954 : Sequence< OUString > lcl_extractSetPropertyNames( const Sequence< PropertyValue >& rValues, const OUString& rPrefix )
     771             : {
     772         954 :     const PropertyValue* pProperties = rValues.getConstArray();
     773             : 
     774         954 :     Sequence< OUString > aSubNodeNames(rValues.getLength());
     775         954 :     OUString* pSubNodeNames = aSubNodeNames.getArray();
     776             : 
     777        1908 :     OUString sLastSubNode;
     778         954 :     sal_Int32 nSubIndex = 0;
     779             : 
     780        8532 :     for(sal_Int32 i = 0; i < rValues.getLength(); i++)
     781             :     {
     782        7578 :         OUString const sSubPath = dropPrefixFromConfigurationPath( pProperties[i].Name, rPrefix);
     783       15156 :         OUString const sSubNode = extractFirstFromConfigurationPath( sSubPath );
     784             : 
     785        7578 :         if(sLastSubNode != sSubNode)
     786             :         {
     787        6234 :             pSubNodeNames[nSubIndex++] = sSubNode;
     788             :         }
     789             : 
     790        7578 :         sLastSubNode = sSubNode;
     791        7578 :     }
     792         954 :     aSubNodeNames.realloc(nSubIndex);
     793             : 
     794        1908 :     return aSubNodeNames;
     795             : }
     796             : 
     797             : // Add or change properties
     798          74 : bool ConfigItem::SetSetProperties(
     799             :     const OUString& rNode, const Sequence< PropertyValue >& rValues)
     800             : {
     801          74 :     ValueCounter_Impl aCounter(m_nInValueChange);
     802          74 :     bool bRet = true;
     803         148 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     804          74 :     if(xHierarchyAccess.is())
     805             :     {
     806          74 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     807             :         try
     808             :         {
     809          74 :             Reference<XNameContainer> xCont;
     810          74 :             if(!rNode.isEmpty())
     811             :             {
     812          74 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     813          74 :                 aNode >>= xCont;
     814             :             }
     815             :             else
     816           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     817          74 :             if(!xCont.is())
     818           0 :                 return false;
     819             : 
     820         148 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
     821             : 
     822          74 :             if(xFac.is())
     823             :             {
     824          74 :                 const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode);
     825             : 
     826          74 :                 const sal_Int32 nSubNodeCount = aSubNodeNames.getLength();
     827             : 
     828         148 :                 for(sal_Int32 j = 0; j <nSubNodeCount; j++)
     829             :                 {
     830          74 :                     if(!xCont->hasByName(aSubNodeNames[j]))
     831             :                     {
     832          50 :                         Reference<XInterface> xInst = xFac->createInstance();
     833         100 :                         Any aVal; aVal <<= xInst;
     834         100 :                         xCont->insertByName(aSubNodeNames[j], aVal);
     835             :                     }
     836             :                     //set values
     837             :                 }
     838             :                 try
     839             :                 {
     840          74 :                     xBatch->commitChanges();
     841             :                 }
     842           0 :                 CATCH_INFO("Exception from commitChanges(): ")
     843             : 
     844          74 :                 const PropertyValue* pProperties = rValues.getConstArray();
     845             : 
     846         148 :                 Sequence< OUString > aSetNames(rValues.getLength());
     847          74 :                 OUString* pSetNames = aSetNames.getArray();
     848             : 
     849         148 :                 Sequence< Any> aSetValues(rValues.getLength());
     850          74 :                 Any* pSetValues = aSetValues.getArray();
     851             : 
     852          74 :                 bool bEmptyNode = rNode.isEmpty();
     853        1492 :                 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
     854             :                 {
     855        1418 :                     pSetNames[k] =  pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
     856        1418 :                     pSetValues[k] = pProperties[k].Value;
     857             :                 }
     858         148 :                 bRet = PutProperties(aSetNames, aSetValues);
     859             :             }
     860             :             else
     861             :             {
     862             :                 //if no factory is available then the node contains basic data elements
     863           0 :                 const PropertyValue* pValues = rValues.getConstArray();
     864           0 :                 for(int nValue = 0; nValue < rValues.getLength();nValue++)
     865             :                 {
     866             :                     try
     867             :                     {
     868           0 :                         OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode );
     869             : 
     870           0 :                         if(xCont->hasByName(sSubNode))
     871           0 :                             xCont->replaceByName(sSubNode, pValues[nValue].Value);
     872             :                         else
     873           0 :                             xCont->insertByName(sSubNode, pValues[nValue].Value);
     874             : 
     875             :                         OSL_ENSURE( xHierarchyAccess->hasByHierarchicalName(pValues[nValue].Name),
     876           0 :                             "Invalid config path" );
     877             :                     }
     878           0 :                     CATCH_INFO("Exception form insert/replaceByName(): ")
     879             :                 }
     880           0 :                 xBatch->commitChanges();
     881          74 :             }
     882             :         }
     883             : #ifdef DBG_UTIL
     884             :         catch (const Exception& rEx)
     885             :         {
     886             :             lcl_CFG_DBG_EXCEPTION("Exception from SetSetProperties: ", rEx);
     887             : #else
     888           0 :         catch (const Exception&)
     889             :         {
     890             : #endif
     891           0 :             bRet = false;
     892          74 :         }
     893             :     }
     894         148 :     return bRet;
     895             : }
     896             : 
     897         880 : bool ConfigItem::ReplaceSetProperties(
     898             :     const OUString& rNode, const Sequence< PropertyValue >& rValues)
     899             : {
     900         880 :     ValueCounter_Impl aCounter(m_nInValueChange);
     901         880 :     bool bRet = true;
     902        1760 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     903         880 :     if(xHierarchyAccess.is())
     904             :     {
     905         880 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     906             :         try
     907             :         {
     908         880 :             Reference<XNameContainer> xCont;
     909         880 :             if(!rNode.isEmpty())
     910             :             {
     911         880 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     912         880 :                 aNode >>= xCont;
     913             :             }
     914             :             else
     915           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     916         880 :             if(!xCont.is())
     917           0 :                 return false;
     918             : 
     919             :             // JB: Change: now the same name handling for sets of simple values
     920        1760 :             const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode);
     921         880 :             const OUString* pSubNodeNames = aSubNodeNames.getConstArray();
     922         880 :             const sal_Int32 nSubNodeCount = aSubNodeNames.getLength();
     923             : 
     924        1760 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
     925         880 :             const bool isSimpleValueSet = !xFac.is();
     926             : 
     927             :             //remove unknown members first
     928             :             {
     929         880 :                 const Sequence<OUString> aContainerSubNodes = xCont->getElementNames();
     930         880 :                 const OUString* pContainerSubNodes = aContainerSubNodes.getConstArray();
     931             : 
     932        1440 :                 for(sal_Int32 nContSub = 0; nContSub < aContainerSubNodes.getLength(); nContSub++)
     933             :                 {
     934         560 :                     bool bFound = false;
     935        6816 :                     for(sal_Int32 j = 0; j < nSubNodeCount; j++)
     936             :                     {
     937        6816 :                         if(pSubNodeNames[j] == pContainerSubNodes[nContSub])
     938             :                         {
     939         560 :                             bFound = true;
     940         560 :                             break;
     941             :                         }
     942             :                     }
     943         560 :                     if(!bFound)
     944             :                     try
     945             :                     {
     946           0 :                         xCont->removeByName(pContainerSubNodes[nContSub]);
     947             :                     }
     948           0 :                     catch (const Exception&)
     949             :                     {
     950           0 :                         if (isSimpleValueSet)
     951             :                         {
     952             :                             try
     953             :                             {
     954             :                                 // #i37322#: fallback action: replace with <void/>
     955           0 :                                 xCont->replaceByName(pContainerSubNodes[nContSub], Any());
     956             :                                 // fallback successful: continue looping
     957           0 :                                 continue;
     958             :                             }
     959           0 :                             catch (Exception &)
     960             :                             {} // propagate original exception, if fallback fails
     961             :                         }
     962           0 :                         throw;
     963             :                     }
     964             :                 }
     965         880 :                 try { xBatch->commitChanges(); }
     966         880 :                 CATCH_INFO("Exception from commitChanges(): ")
     967             :             }
     968             : 
     969         880 :             if(xFac.is()) // !isSimpleValueSet
     970             :             {
     971           0 :                 for(sal_Int32 j = 0; j < nSubNodeCount; j++)
     972             :                 {
     973           0 :                     if(!xCont->hasByName(pSubNodeNames[j]))
     974             :                     {
     975             :                         //create if not available
     976           0 :                         Reference<XInterface> xInst = xFac->createInstance();
     977           0 :                         Any aVal; aVal <<= xInst;
     978           0 :                         xCont->insertByName(pSubNodeNames[j], aVal);
     979             :                     }
     980             :                 }
     981           0 :                 try { xBatch->commitChanges(); }
     982           0 :                 CATCH_INFO("Exception from commitChanges(): ")
     983             : 
     984           0 :                 const PropertyValue* pProperties = rValues.getConstArray();
     985             : 
     986           0 :                 Sequence< OUString > aSetNames(rValues.getLength());
     987           0 :                 OUString* pSetNames = aSetNames.getArray();
     988             : 
     989           0 :                 Sequence< Any> aSetValues(rValues.getLength());
     990           0 :                 Any* pSetValues = aSetValues.getArray();
     991             : 
     992           0 :                 bool bEmptyNode = rNode.isEmpty();
     993           0 :                 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
     994             :                 {
     995           0 :                     pSetNames[k] =  pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
     996           0 :                     pSetValues[k] = pProperties[k].Value;
     997             :                 }
     998           0 :                 bRet = PutProperties(aSetNames, aSetValues);
     999             :             }
    1000             :             else
    1001             :             {
    1002         880 :                 const PropertyValue* pValues = rValues.getConstArray();
    1003             : 
    1004             :                 //if no factory is available then the node contains basic data elements
    1005        7040 :                 for(int nValue = 0; nValue < rValues.getLength();nValue++)
    1006             :                 {
    1007             :                     try
    1008             :                     {
    1009        6160 :                         OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode );
    1010             : 
    1011        6160 :                         if(xCont->hasByName(sSubNode))
    1012         560 :                             xCont->replaceByName(sSubNode, pValues[nValue].Value);
    1013             :                         else
    1014        5600 :                             xCont->insertByName(sSubNode, pValues[nValue].Value);
    1015             :                     }
    1016           0 :                     CATCH_INFO("Exception from insert/replaceByName(): ");
    1017             :                 }
    1018         880 :                 xBatch->commitChanges();
    1019         880 :             }
    1020             :         }
    1021             : #ifdef DBG_UTIL
    1022             :         catch (const Exception& rEx)
    1023             :         {
    1024             :             lcl_CFG_DBG_EXCEPTION("Exception from ReplaceSetProperties: ", rEx);
    1025             : #else
    1026           0 :         catch (const Exception&)
    1027             :         {
    1028             : #endif
    1029           0 :             bRet = false;
    1030         880 :         }
    1031             :     }
    1032        1760 :     return bRet;
    1033             : }
    1034             : 
    1035           0 : bool ConfigItem::AddNode(const OUString& rNode, const OUString& rNewNode)
    1036             : {
    1037           0 :     ValueCounter_Impl aCounter(m_nInValueChange);
    1038           0 :     bool bRet = true;
    1039           0 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
    1040           0 :     if(xHierarchyAccess.is())
    1041             :     {
    1042           0 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
    1043             :         try
    1044             :         {
    1045           0 :             Reference<XNameContainer> xCont;
    1046           0 :             if(!rNode.isEmpty())
    1047             :             {
    1048           0 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
    1049           0 :                 aNode >>= xCont;
    1050             :             }
    1051             :             else
    1052           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
    1053           0 :             if(!xCont.is())
    1054           0 :                 return false;
    1055             : 
    1056           0 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
    1057             : 
    1058           0 :             if(xFac.is())
    1059             :             {
    1060           0 :                 if(!xCont->hasByName(rNewNode))
    1061             :                 {
    1062           0 :                     Reference<XInterface> xInst = xFac->createInstance();
    1063           0 :                     Any aVal; aVal <<= xInst;
    1064           0 :                     xCont->insertByName(rNewNode, aVal);
    1065             :                 }
    1066             :                 try
    1067             :                 {
    1068           0 :                     xBatch->commitChanges();
    1069             :                 }
    1070           0 :                 CATCH_INFO("Exception from commitChanges(): ")
    1071             :             }
    1072             :             else
    1073             :             {
    1074             :                 //if no factory is available then the node contains basic data elements
    1075             :                 try
    1076             :                 {
    1077           0 :                     if(!xCont->hasByName(rNewNode))
    1078           0 :                         xCont->insertByName(rNewNode, Any());
    1079             :                 }
    1080           0 :                 CATCH_INFO("Exception from AddNode(): ")
    1081             :             }
    1082           0 :             xBatch->commitChanges();
    1083             :         }
    1084             : #ifdef DBG_UTIL
    1085             :         catch (const Exception& rEx)
    1086             :         {
    1087             :             lcl_CFG_DBG_EXCEPTION("Exception from AddNode(): ", rEx);
    1088             : #else
    1089           0 :         catch (const Exception&)
    1090             :         {
    1091             : #endif
    1092           0 :             bRet = false;
    1093           0 :         }
    1094             :     }
    1095           0 :     return bRet;
    1096             : }
    1097             : 
    1098             : 
    1099        4534 : void    ConfigItem::SetModified()
    1100             : {
    1101        4534 :     m_bIsModified = true;
    1102        4534 : }
    1103             : 
    1104         844 : void    ConfigItem::ClearModified()
    1105             : {
    1106         844 :     m_bIsModified = false;
    1107         844 : }
    1108             : 
    1109             : 
    1110             : 
    1111      272860 : Reference< XHierarchicalNameAccess> ConfigItem::GetTree()
    1112             : {
    1113      272860 :     Reference< XHierarchicalNameAccess> xRet;
    1114      272860 :     if(!m_xHierarchyAccess.is())
    1115        1602 :         xRet = ConfigManager::acquireTree(*this);
    1116             :     else
    1117      271258 :         xRet = m_xHierarchyAccess;
    1118      272860 :     return xRet;
    1119             : }
    1120             : 
    1121             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10