LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/unotools/source/config - configitem.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 333 535 62.2 %
Date: 2013-07-09 Functions: 36 42 85.7 %
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> // helper for implementations
      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             :             ~ConfigChangeListener_Impl();
      87             : 
      88             :         //XChangesListener
      89             :         virtual void SAL_CALL changesOccurred( const ChangesEvent& Event ) throw(RuntimeException);
      90             : 
      91             :         //XEventListener
      92             :         virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException);
      93             :     };
      94             : 
      95             : struct ConfigItem_Impl
      96             : {
      97             :     utl::ConfigManager*         pManager;
      98             :        sal_Int16                    nMode;
      99             :     sal_Bool                    bIsModified;
     100             :     sal_Bool                    bEnableInternalNotification;
     101             : 
     102             :     sal_Int16                   nInValueChange;
     103       10400 :     ConfigItem_Impl() :
     104             :         pManager(0),
     105             :         nMode(0),
     106             :         bIsModified(sal_False),
     107             :         bEnableInternalNotification(sal_False),
     108       10400 :         nInValueChange(0)
     109       10400 :     {}
     110             : };
     111             : }
     112             : 
     113             : class ValueCounter_Impl
     114             : {
     115             :     sal_Int16& rCnt;
     116             : public:
     117        1576 :     ValueCounter_Impl(sal_Int16& rCounter):
     118        1576 :         rCnt(rCounter)
     119        1576 :             {rCnt++;}
     120        1576 :     ~ValueCounter_Impl()
     121             :             {
     122             :                 OSL_ENSURE(rCnt>0, "RefCount < 0 ??");
     123        1576 :                 rCnt--;
     124        1576 :             }
     125             : };
     126             : 
     127             : namespace
     128             : {
     129             :     // helper to achieve exception - safe handling of an Item under construction
     130             :     template <class TYP>
     131             :     class AutoDeleter // : Noncopyable
     132             :     {
     133             :         TYP* m_pItem;
     134             :     public:
     135       10400 :         AutoDeleter(TYP * pItem)
     136       10400 :         : m_pItem(pItem)
     137             :         {
     138       10400 :         }
     139             : 
     140       10400 :         ~AutoDeleter()
     141             :         {
     142       10400 :             delete m_pItem;
     143       10400 :         }
     144             : 
     145       10400 :         void keep() { m_pItem = 0; }
     146             :     };
     147             : }
     148             : 
     149        5704 : ConfigChangeListener_Impl::ConfigChangeListener_Impl(
     150             :              ConfigItem& rItem, const Sequence< OUString >& rNames) :
     151             :     pParent(&rItem),
     152        5704 :     aPropertyNames(rNames)
     153             : {
     154        5704 : }
     155             : 
     156       10218 : ConfigChangeListener_Impl::~ConfigChangeListener_Impl()
     157             : {
     158       10218 : }
     159             : 
     160       13102 : static sal_Bool lcl_Find(
     161             :         const OUString& rTemp,
     162             :         const OUString* pCheckPropertyNames,
     163             :         sal_Int32 nLength)
     164             : {
     165             :     //return true if the path is completely correct or if it is longer
     166             :     //i.e ...Print/Content/Graphic and .../Print
     167       98288 :     for(sal_Int32 nIndex = 0; nIndex < nLength; nIndex++)
     168       94482 :         if( isPrefixOfConfigurationPath(rTemp, pCheckPropertyNames[nIndex]) )
     169        9296 :             return sal_True;
     170        3806 :     return sal_False;
     171             : }
     172             : //-----------------------------------------------------------------------------
     173       10607 : void ConfigChangeListener_Impl::changesOccurred( const ChangesEvent& rEvent ) throw(RuntimeException)
     174             : {
     175       10607 :     const ElementChange* pElementChanges = rEvent.Changes.getConstArray();
     176             : 
     177       10607 :     Sequence<OUString>  aChangedNames(rEvent.Changes.getLength());
     178       10607 :     OUString* pNames = aChangedNames.getArray();
     179             : 
     180       10607 :     const OUString* pCheckPropertyNames = aPropertyNames.getConstArray();
     181             : 
     182       10607 :     sal_Int32 nNotify = 0;
     183       23709 :     for(int i = 0; i < aChangedNames.getLength(); i++)
     184             :     {
     185       13102 :         OUString sTemp;
     186       13102 :         pElementChanges[i].Accessor >>= sTemp;
     187       13102 :         if(lcl_Find(sTemp, pCheckPropertyNames, aPropertyNames.getLength()))
     188        9296 :             pNames[nNotify++] = sTemp;
     189       13102 :     }
     190       10607 :     if( nNotify )
     191             :     {
     192        8187 :         if ( ::tools::SolarMutex::Acquire() )
     193             :         {
     194        8187 :             aChangedNames.realloc(nNotify);
     195        8187 :             pParent->CallNotify(aChangedNames);
     196        8187 :             ::tools::SolarMutex::Release();
     197             :         }
     198       10607 :     }
     199       10607 : }
     200             : 
     201             : 
     202           0 : void ConfigChangeListener_Impl::disposing( const EventObject& /*rSource*/ ) throw(RuntimeException)
     203             : {
     204           0 :     pParent->RemoveChangesListener();
     205           0 : }
     206             : 
     207       10400 : ConfigItem::ConfigItem(const OUString &rSubTree, sal_Int16 nSetMode ) :
     208             :     sSubTree(rSubTree),
     209       10400 :     pImpl(new ConfigItem_Impl)
     210             : {
     211       10400 :     AutoDeleter<ConfigItem_Impl> aNewImpl(pImpl);
     212             : 
     213       10400 :     pImpl->pManager = &ConfigManager::getConfigManager();
     214       10400 :     pImpl->nMode = nSetMode;
     215       10400 :     if(0 != (nSetMode&CONFIG_MODE_RELEASE_TREE))
     216         498 :         pImpl->pManager->addConfigItem(*this);
     217             :     else
     218        9902 :         m_xHierarchyAccess = pImpl->pManager->addConfigItem(*this);
     219             : 
     220       10400 :     aNewImpl.keep();
     221       10400 : }
     222             : 
     223         262 : sal_Bool ConfigItem::IsValidConfigMgr() const
     224             : {
     225         262 :     return pImpl->pManager != 0;
     226             : }
     227             : 
     228       19044 : ConfigItem::~ConfigItem()
     229             : {
     230        9522 :     if(pImpl->pManager)
     231             :     {
     232        9522 :         RemoveChangesListener();
     233        9522 :         pImpl->pManager->removeConfigItem(*this);
     234             :     }
     235        9522 :     delete pImpl;
     236        9522 : }
     237             : 
     238        8187 : void ConfigItem::CallNotify( const com::sun::star::uno::Sequence<OUString>& rPropertyNames )
     239             : {
     240             :     // the call is forwarded to the virtual Notify() method
     241             :     // it is pure virtual, so all classes deriving from ConfigItem have to decide how they
     242             :     // want to notify listeners
     243        8187 :     if(!IsInValueChange() || pImpl->bEnableInternalNotification)
     244          70 :         Notify(rPropertyNames);
     245        8187 : }
     246             : 
     247           0 : void ConfigItem::impl_packLocalizedProperties(  const   Sequence< OUString >&   lInNames    ,
     248             :                                                 const   Sequence< Any >&        lInValues   ,
     249             :                                                         Sequence< Any >&        lOutValues  )
     250             : {
     251             :     // Safe impossible cases.
     252             :     // This method should be called for special ConfigItem-mode only!
     253             :     OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_packLocalizedProperties()\nWrong call of this method detected!\n" );
     254             : 
     255             :     sal_Int32                   nSourceCounter      ;   // used to step during input lists
     256             :     sal_Int32                   nSourceSize         ;   // marks end of loop over input lists
     257             :     sal_Int32                   nDestinationCounter ;   // actual position in output lists
     258             :     sal_Int32                   nPropertyCounter    ;   // counter of inner loop for Sequence< PropertyValue >
     259             :     sal_Int32                   nPropertiesSize     ;   // marks end of inner loop
     260           0 :     Sequence< OUString >        lPropertyNames      ;   // list of all locales for localized entry
     261           0 :     Sequence< PropertyValue >   lProperties         ;   // localized values of an configuration entry packed for return
     262           0 :     Reference< XInterface >     xLocalizedNode      ;   // if cfg entry is localized ... lInValues contains an XInterface!
     263             : 
     264             :     // Optimise follow algorithm ... A LITTLE BIT :-)
     265             :     // There exist two different possibilities:
     266             :     //  i ) There exist no localized entries ...                        =>  size of lOutValues will be the same like lInNames/lInValues!
     267             :     //  ii) There exist some (mostly one or two) localized entries ...  =>  size of lOutValues will be the same like lInNames/lInValues!
     268             :     //  ... Why? If a localized value exist - the any is filled with an XInterface object (is a SetNode-service).
     269             :     //      We read all his child nodes and pack it into Sequence< PropertyValue >.
     270             :     //      The result list we pack into the return any. We never change size of lists!
     271           0 :     nSourceSize = lInNames.getLength();
     272           0 :     lOutValues.realloc( nSourceSize );
     273             : 
     274             :     // Algorithm:
     275             :     // Copy all names and values from in to out lists.
     276             :     // Look for special localized entries ... You can detect it as "XInterface" packed into an Any.
     277             :     // Use this XInterface-object to read all localized values and pack it into Sequence< PropertValue >.
     278             :     // Add this list to out lists then.
     279             : 
     280           0 :     nDestinationCounter = 0;
     281           0 :     for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
     282             :     {
     283             :         // If item a special localized one ... convert and pack it ...
     284           0 :         if( lInValues[nSourceCounter].getValueTypeName() == "com.sun.star.uno.XInterface" )
     285             :         {
     286           0 :             lInValues[nSourceCounter] >>= xLocalizedNode;
     287           0 :             Reference< XNameContainer > xSetAccess( xLocalizedNode, UNO_QUERY );
     288           0 :             if( xSetAccess.is() == sal_True )
     289             :             {
     290           0 :                 lPropertyNames  =   xSetAccess->getElementNames()   ;
     291           0 :                 nPropertiesSize =   lPropertyNames.getLength()      ;
     292           0 :                 lProperties.realloc( nPropertiesSize )              ;
     293             : 
     294           0 :                 for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter )
     295             :                 {
     296             :                     #if OSL_DEBUG_LEVEL > 1
     297             :                     // Sometimes it's better to see what's going on :-)
     298             :                     OUString sPropName   = lInNames[nSourceCounter];
     299             :                     OUString sLocaleName = lPropertyNames[nPropertyCounter];
     300             :                     #endif
     301           0 :                     lProperties[nPropertyCounter].Name  =   lPropertyNames[nPropertyCounter]                            ;
     302           0 :                     OUString sLocaleValue;
     303           0 :                     xSetAccess->getByName( lPropertyNames[nPropertyCounter] ) >>= sLocaleValue  ;
     304           0 :                     lProperties[nPropertyCounter].Value <<= sLocaleValue;
     305           0 :                 }
     306             : 
     307           0 :                 lOutValues[nDestinationCounter] <<= lProperties;
     308           0 :             }
     309             :         }
     310             :         // ... or copy normal items to return lists directly.
     311             :         else
     312             :         {
     313           0 :             lOutValues[nDestinationCounter] = lInValues[nSourceCounter];
     314             :         }
     315           0 :         ++nDestinationCounter;
     316           0 :     }
     317           0 : }
     318             : 
     319           0 : void ConfigItem::impl_unpackLocalizedProperties(    const   Sequence< OUString >&   lInNames    ,
     320             :                                                     const   Sequence< Any >&        lInValues   ,
     321             :                                                             Sequence< OUString >&   lOutNames   ,
     322             :                                                             Sequence< Any >&        lOutValues  )
     323             : {
     324             :     // Safe impossible cases.
     325             :     // This method should be called for special ConfigItem-mode only!
     326             :     OSL_ENSURE( ((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES), "ConfigItem::impl_unpackLocalizedProperties()\nWrong call of this method detected!\n" );
     327             : 
     328             :     sal_Int32                   nSourceCounter      ;   // used to step during input lists
     329             :     sal_Int32                   nSourceSize         ;   // marks end of loop over input lists
     330             :     sal_Int32                   nDestinationCounter ;   // actual position in output lists
     331             :     sal_Int32                   nPropertyCounter    ;   // counter of inner loop for Sequence< PropertyValue >
     332             :     sal_Int32                   nPropertiesSize     ;   // marks end of inner loop
     333           0 :     OUString                    sNodeName           ;   // base name of node ( e.g. "UIName/" ) ... expand to locale ( e.g. "UIName/de" )
     334           0 :     Sequence< PropertyValue >   lProperties         ;   // localized values of an configuration entry getted from lInValues-Any
     335             : 
     336             :     // Optimise follow algorithm ... A LITTLE BIT :-)
     337             :     // There exist two different possibilities:
     338             :     //  i ) There exist no localized entries ...                        =>  size of lOutNames/lOutValues will be the same like lInNames/lInValues!
     339             :     //  ii) There exist some (mostly one or two) localized entries ...  =>  size of lOutNames/lOutValues will be some bytes greater then lInNames/lInValues.
     340             :     //  =>  I think we should make it fast for i). ii) is a special case and mustn't be SOOOO... fast.
     341             :     //      We should reserve same space for output list like input ones first.
     342             :     //      Follow algorithm looks for these borders and change it for ii) only!
     343             :     //      It will be faster then a "realloc()" call in every loop ...
     344           0 :     nSourceSize = lInNames.getLength();
     345             : 
     346           0 :     lOutNames.realloc   ( nSourceSize );
     347           0 :     lOutValues.realloc  ( nSourceSize );
     348             : 
     349             :     // Algorithm:
     350             :     // Copy all names and values from const to return lists.
     351             :     // Look for special localized entries ... You can detect it as Sequence< PropertyValue > packed into an Any.
     352             :     // Split it ... insert PropertyValue.Name to lOutNames and PropertyValue.Value to lOutValues.
     353             : 
     354           0 :     nDestinationCounter = 0;
     355           0 :     for( nSourceCounter=0; nSourceCounter<nSourceSize; ++nSourceCounter )
     356             :     {
     357             :         // If item a special localized one ... split it and insert his parts to output lists ...
     358           0 :         if( lInValues[nSourceCounter].getValueType() == ::getCppuType( (const Sequence< PropertyValue >*)NULL ) )
     359             :         {
     360           0 :             lInValues[nSourceCounter] >>= lProperties;
     361           0 :             nPropertiesSize = lProperties.getLength();
     362             : 
     363           0 :             sNodeName = lInNames[nSourceCounter] + "/";
     364             : 
     365           0 :             if( (nDestinationCounter+nPropertiesSize) > lOutNames.getLength() )
     366             :             {
     367           0 :                 lOutNames.realloc   ( nDestinationCounter+nPropertiesSize );
     368           0 :                 lOutValues.realloc  ( nDestinationCounter+nPropertiesSize );
     369             :             }
     370             : 
     371           0 :             for( nPropertyCounter=0; nPropertyCounter<nPropertiesSize; ++nPropertyCounter )
     372             :             {
     373           0 :                  lOutNames [nDestinationCounter] = sNodeName + lProperties[nPropertyCounter].Name   ;
     374           0 :                 lOutValues[nDestinationCounter] = lProperties[nPropertyCounter].Value               ;
     375           0 :                 ++nDestinationCounter;
     376             :             }
     377             :         }
     378             :         // ... or copy normal items to return lists directly.
     379             :         else
     380             :         {
     381           0 :             if( (nDestinationCounter+1) > lOutNames.getLength() )
     382             :             {
     383           0 :                 lOutNames.realloc   ( nDestinationCounter+1 );
     384           0 :                 lOutValues.realloc  ( nDestinationCounter+1 );
     385             :             }
     386             : 
     387           0 :             lOutNames [nDestinationCounter] = lInNames [nSourceCounter];
     388           0 :             lOutValues[nDestinationCounter] = lInValues[nSourceCounter];
     389           0 :             ++nDestinationCounter;
     390             :         }
     391           0 :     }
     392           0 : }
     393             : 
     394         668 : Sequence< sal_Bool > ConfigItem::GetReadOnlyStates(const com::sun::star::uno::Sequence< OUString >& rNames)
     395             : {
     396             :     sal_Int32 i;
     397             : 
     398             :     // size of return list is fix!
     399             :     // Every item must match to length of incoming name list.
     400         668 :     sal_Int32 nCount = rNames.getLength();
     401         668 :     Sequence< sal_Bool > lStates(nCount);
     402             : 
     403             :     // We must be shure to return a valid information everytime!
     404             :     // Set default to non readonly ... similar to the configuration handling of this property.
     405        8523 :     for ( i=0; i<nCount; ++i)
     406        7855 :         lStates[i] = sal_False;
     407             : 
     408             :     // no access - no information ...
     409        1336 :     Reference< XHierarchicalNameAccess > xHierarchyAccess = GetTree();
     410         668 :     if (!xHierarchyAccess.is())
     411           0 :         return lStates;
     412             : 
     413        8523 :     for (i=0; i<nCount; ++i)
     414             :     {
     415             :         try
     416             :         {
     417        7855 :             OUString sName = rNames[i];
     418       15710 :             OUString sPath;
     419       15710 :             OUString sProperty;
     420             : 
     421        7855 :             ::utl::splitLastFromConfigurationPath(sName,sPath,sProperty);
     422        7855 :             if (sPath.isEmpty() && sProperty.isEmpty())
     423             :             {
     424             :                 OSL_FAIL("ConfigItem::IsReadonly()\nsplitt failed\n");
     425           0 :                 continue;
     426             :             }
     427             : 
     428       15710 :             Reference< XInterface >       xNode;
     429       15710 :             Reference< XPropertySet >     xSet ;
     430       15710 :             Reference< XPropertySetInfo > xInfo;
     431        7855 :             if (!sPath.isEmpty())
     432             :             {
     433        3045 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(sPath);
     434        3045 :                 if (!(aNode >>= xNode) || !xNode.is())
     435             :                 {
     436             :                     OSL_FAIL("ConfigItem::IsReadonly()\nno set available\n");
     437           0 :                     continue;
     438        3045 :                 }
     439             :             }
     440             :             else
     441             :             {
     442        4810 :                 xNode = xHierarchyAccess;
     443             :             }
     444             : 
     445        7855 :         xSet = Reference< XPropertySet >(xNode, UNO_QUERY);
     446        7855 :             if (xSet.is())
     447             :         {
     448        7855 :             xInfo = xSet->getPropertySetInfo();
     449             :                 OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\ngetPropertySetInfo failed ...\n");
     450             :         }
     451             :             else
     452             :         {
     453           0 :                xInfo = Reference< XPropertySetInfo >(xNode, UNO_QUERY);
     454             :                 OSL_ENSURE(xInfo.is(), "ConfigItem::IsReadonly()\nUNO_QUERY failed ...\n");
     455             :         }
     456             : 
     457        7855 :             if (!xInfo.is())
     458             :             {
     459             :                 OSL_FAIL("ConfigItem::IsReadonly()\nno prop info available\n");
     460           0 :                 continue;
     461             :             }
     462             : 
     463       15710 :             Property aProp = xInfo->getPropertyByName(sProperty);
     464       15710 :             lStates[i] = ((aProp.Attributes & PropertyAttribute::READONLY) == PropertyAttribute::READONLY);
     465             :         }
     466           0 :         catch (const Exception&)
     467             :         {
     468             :         }
     469             :     }
     470             : 
     471         668 :     return lStates;
     472             : }
     473             : 
     474       32883 : Sequence< Any > ConfigItem::GetProperties(const Sequence< OUString >& rNames)
     475             : {
     476       32883 :     Sequence< Any > aRet(rNames.getLength());
     477       32883 :     const OUString* pNames = rNames.getConstArray();
     478       32883 :     Any* pRet = aRet.getArray();
     479       65766 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     480       32883 :     if(xHierarchyAccess.is())
     481             :     {
     482      243859 :         for(int i = 0; i < rNames.getLength(); i++)
     483             :         {
     484             :             try
     485             :             {
     486      210976 :                 pRet[i] = xHierarchyAccess->getByHierarchicalName(pNames[i]);
     487             :             }
     488        2000 :             catch (const Exception& rEx)
     489             :             {
     490             : #if OSL_DEBUG_LEVEL > 0
     491             :                 OString sMsg("XHierarchicalNameAccess: ");
     492             :                 sMsg += OString(rEx.Message.getStr(),
     493             :                     rEx.Message.getLength(),
     494             :                      RTL_TEXTENCODING_ASCII_US);
     495             :                 sMsg += OString("\n/org.openoffice.");
     496             :                 sMsg += OString(sSubTree.getStr(),
     497             :                     sSubTree.getLength(),
     498             :                      RTL_TEXTENCODING_ASCII_US);
     499             :                 sMsg += OString("/");
     500             :                 sMsg += OString(pNames[i].getStr(),
     501             :                     pNames[i].getLength(),
     502             :                      RTL_TEXTENCODING_ASCII_US);
     503             :                 OSL_FAIL(sMsg.getStr());
     504             : #else
     505             :                 (void) rEx; // avoid warning
     506             : #endif
     507             :             }
     508             :         }
     509             : 
     510             :         // In special mode "ALL_LOCALES" we must convert localized values to Sequence< PropertyValue >.
     511       32883 :         if((pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES)
     512             :         {
     513           0 :             Sequence< Any > lValues;
     514           0 :             impl_packLocalizedProperties( rNames, aRet, lValues );
     515           0 :             aRet = lValues;
     516             :         }
     517             :     }
     518       65766 :     return aRet;
     519             : }
     520             : 
     521        1182 : sal_Bool ConfigItem::PutProperties( const Sequence< OUString >& rNames,
     522             :                                                 const Sequence< Any>& rValues)
     523             : {
     524        1182 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
     525        2364 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     526        2364 :     Reference<XNameReplace> xTopNodeReplace(xHierarchyAccess, UNO_QUERY);
     527        1182 :     sal_Bool bRet = xHierarchyAccess.is() && xTopNodeReplace.is();
     528        1182 :     if(bRet)
     529             :     {
     530        1182 :         Sequence< OUString >    lNames          ;
     531        2364 :         Sequence< Any >         lValues         ;
     532        1182 :         const OUString*         pNames  = NULL  ;
     533        1182 :         const Any*              pValues = NULL  ;
     534             :         sal_Int32               nNameCount      ;
     535        1182 :         if(( pImpl->nMode & CONFIG_MODE_ALL_LOCALES ) == CONFIG_MODE_ALL_LOCALES )
     536             :         {
     537             :             // If ConfigItem works in "ALL_LOCALES"-mode ... we must support a Sequence< PropertyValue >
     538             :             // as value of an localized configuration entry!
     539             :             // How we can do that?
     540             :             // We must split all PropertyValues to "Sequence< OUString >" AND "Sequence< Any >"!
     541           0 :             impl_unpackLocalizedProperties( rNames, rValues, lNames, lValues );
     542           0 :             pNames      = lNames.getConstArray  ();
     543           0 :             pValues     = lValues.getConstArray ();
     544           0 :             nNameCount  = lNames.getLength      ();
     545             :         }
     546             :         else
     547             :         {
     548             :             // This is the normal mode ...
     549             :             // Use given input lists directly.
     550        1182 :             pNames      = rNames.getConstArray  ();
     551        1182 :             pValues     = rValues.getConstArray ();
     552        1182 :             nNameCount  = rNames.getLength      ();
     553             :         }
     554       10024 :         for(int i = 0; i < nNameCount; i++)
     555             :         {
     556             :             try
     557             :             {
     558       17684 :                 OUString sNode, sProperty;
     559        8842 :                 if (splitLastFromConfigurationPath(pNames[i],sNode, sProperty))
     560             :                 {
     561        1191 :                     Any aNode = xHierarchyAccess->getByHierarchicalName(sNode);
     562             : 
     563        2382 :                     Reference<XNameAccess> xNodeAcc;
     564        1191 :                     aNode >>= xNodeAcc;
     565        2382 :                     Reference<XNameReplace>   xNodeReplace(xNodeAcc, UNO_QUERY);
     566        2382 :                     Reference<XNameContainer> xNodeCont   (xNodeAcc, UNO_QUERY);
     567             : 
     568        1191 :                     sal_Bool bExist = (xNodeAcc.is() && xNodeAcc->hasByName(sProperty));
     569        1191 :                     if (bExist && xNodeReplace.is())
     570        1191 :                         xNodeReplace->replaceByName(sProperty, pValues[i]);
     571             :                     else
     572           0 :                         if (!bExist && xNodeCont.is())
     573           0 :                             xNodeCont->insertByName(sProperty, pValues[i]);
     574             :                         else
     575        1191 :                             bRet = sal_False;
     576             :                 }
     577             :                 else //direct value
     578             :                 {
     579        7651 :                     xTopNodeReplace->replaceByName(sProperty, pValues[i]);
     580        8842 :                 }
     581             :             }
     582           0 :             CATCH_INFO("Exception from PutProperties: ");
     583             :         }
     584             :         try
     585             :         {
     586        1182 :             Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     587        1182 :             xBatch->commitChanges();
     588             :         }
     589        1182 :         CATCH_INFO("Exception from commitChanges(): ")
     590             :     }
     591             : 
     592        2364 :     return bRet;
     593             : }
     594             : 
     595        1052 : void ConfigItem::DisableNotification()
     596             : {
     597             :     OSL_ENSURE( xChangeLstnr.is(), "ConfigItem::DisableNotification: notifications not enabled currently!" );
     598        1052 :     RemoveChangesListener();
     599        1052 : }
     600             : 
     601        5704 : sal_Bool    ConfigItem::EnableNotification(const Sequence< OUString >& rNames,
     602             :                 sal_Bool bEnableInternalNotification )
     603             : 
     604             : {
     605             :     OSL_ENSURE(0 == (pImpl->nMode&CONFIG_MODE_RELEASE_TREE), "notification in CONFIG_MODE_RELEASE_TREE mode not possible");
     606        5704 :     pImpl->bEnableInternalNotification = bEnableInternalNotification;
     607        5704 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     608       11408 :     Reference<XChangesNotifier> xChgNot(xHierarchyAccess, UNO_QUERY);
     609        5704 :     if(!xChgNot.is())
     610           0 :         return sal_False;
     611             : 
     612             :     OSL_ENSURE(!xChangeLstnr.is(), "EnableNotification already called");
     613        5704 :     if(xChangeLstnr.is())
     614           0 :         xChgNot->removeChangesListener( xChangeLstnr );
     615        5704 :     sal_Bool bRet = sal_True;
     616             : 
     617             :     try
     618             :     {
     619        5704 :         xChangeLstnr = new ConfigChangeListener_Impl(*this, rNames);
     620        5704 :         xChgNot->addChangesListener( xChangeLstnr );
     621             :     }
     622           0 :     catch (const RuntimeException&)
     623             :     {
     624           0 :         bRet = sal_False;
     625             :     }
     626       11408 :     return bRet;
     627             : }
     628             : 
     629       10574 : void ConfigItem::RemoveChangesListener()
     630             : {
     631       10574 :     Reference<XChangesNotifier> xChgNot(m_xHierarchyAccess, UNO_QUERY);
     632       10574 :     if(xChgNot.is() && xChangeLstnr.is())
     633             :     {
     634             :         try
     635             :         {
     636        5109 :             xChgNot->removeChangesListener( xChangeLstnr );
     637        5109 :             xChangeLstnr = 0;
     638             :         }
     639           0 :         catch (const Exception&)
     640             :         {
     641             :         }
     642       10574 :     }
     643       10574 : }
     644             : 
     645       12362 : static void lcl_normalizeLocalNames(Sequence< OUString >& _rNames, ConfigNameFormat _eFormat, Reference<XInterface> const& _xParentNode)
     646             : {
     647       12362 :     switch (_eFormat)
     648             :     {
     649             :     case CONFIG_NAME_LOCAL_NAME:
     650             :         // unaltered - this is our input format
     651       11872 :         break;
     652             : 
     653             :     case CONFIG_NAME_FULL_PATH:
     654             :         {
     655           0 :             Reference<XHierarchicalName> xFormatter(_xParentNode, UNO_QUERY);
     656           0 :             if (xFormatter.is())
     657             :             {
     658           0 :                 OUString * pNames = _rNames.getArray();
     659           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     660             :                 {
     661             :                     try
     662             :                     {
     663           0 :                         pNames[i] = xFormatter->composeHierarchicalName(pNames[i]);
     664             :                     }
     665           0 :                     CATCH_INFO("Exception from composeHierarchicalName(): ")
     666             :                 }
     667           0 :                 break;
     668           0 :             }
     669             :         }
     670             :         OSL_FAIL("Cannot create absolute paths: missing interface");
     671             :         // make local paths instaed
     672             : 
     673             :     case CONFIG_NAME_LOCAL_PATH:
     674             :         {
     675         490 :             Reference<XTemplateContainer> xTypeContainer(_xParentNode, UNO_QUERY);
     676         490 :             if (xTypeContainer.is())
     677             :             {
     678           0 :                 OUString sTypeName = xTypeContainer->getElementTemplateName();
     679           0 :                 sTypeName = sTypeName.copy(sTypeName.lastIndexOf('/')+1);
     680             : 
     681           0 :                 OUString * pNames = _rNames.getArray();
     682           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     683             :                 {
     684           0 :                     pNames[i] = wrapConfigurationElementName(pNames[i],sTypeName);
     685           0 :                 }
     686             :             }
     687             :             else
     688             :             {
     689         490 :                 Reference<XServiceInfo> xSVI(_xParentNode, UNO_QUERY);
     690         490 :                 if (xSVI.is() && xSVI->supportsService("com.sun.star.configuration.SetAccess"))
     691             :                 {
     692         490 :                     OUString * pNames = _rNames.getArray();
     693        1742 :                     for(int i = 0; i<_rNames.getLength(); ++i)
     694             :                     {
     695        1252 :                         pNames[i] = wrapConfigurationElementName(pNames[i]);
     696             :                     }
     697         490 :                 }
     698         490 :             }
     699             :         }
     700         490 :         break;
     701             : 
     702             :     case CONFIG_NAME_PLAINTEXT_NAME:
     703             :         {
     704           0 :             Reference<XStringEscape> xEscaper(_xParentNode, UNO_QUERY);
     705           0 :             if (xEscaper.is())
     706             :             {
     707           0 :                 OUString * pNames = _rNames.getArray();
     708           0 :                 for(int i = 0; i<_rNames.getLength(); ++i)
     709             :                 try
     710             :                 {
     711           0 :                     pNames[i] = xEscaper->unescapeString(pNames[i]);
     712             :                 }
     713           0 :                 CATCH_INFO("Exception from unescapeString(): ")
     714           0 :             }
     715             :         }
     716           0 :         break;
     717             : 
     718             :     }
     719       12362 : }
     720             : 
     721       11872 : Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode)
     722             : {
     723       11872 :     ConfigNameFormat const eDefaultFormat = CONFIG_NAME_LOCAL_NAME; // CONFIG_NAME_DEFAULT;
     724             : 
     725       11872 :     return GetNodeNames(rNode, eDefaultFormat);
     726             : }
     727             : 
     728       12362 : Sequence< OUString > ConfigItem::GetNodeNames(const OUString& rNode, ConfigNameFormat eFormat)
     729             : {
     730       12362 :     Sequence< OUString > aRet;
     731       24724 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     732       12362 :     if(xHierarchyAccess.is())
     733             :     {
     734             :         try
     735             :         {
     736       12362 :             Reference<XNameAccess> xCont;
     737       12362 :             if(!rNode.isEmpty())
     738             :             {
     739       12163 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     740       12163 :                 aNode >>= xCont;
     741             :             }
     742             :             else
     743         199 :                 xCont = Reference<XNameAccess> (xHierarchyAccess, UNO_QUERY);
     744       12362 :             if(xCont.is())
     745             :             {
     746       12362 :                 aRet = xCont->getElementNames();
     747       12362 :                 lcl_normalizeLocalNames(aRet,eFormat,xCont);
     748       12362 :             }
     749             : 
     750             :         }
     751           0 :         CATCH_INFO("Exception from GetNodeNames: ");
     752             :     }
     753       24724 :     return aRet;
     754             : }
     755             : 
     756           4 : sal_Bool ConfigItem::ClearNodeSet(const OUString& rNode)
     757             : {
     758           4 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
     759           4 :     sal_Bool bRet = sal_False;
     760           8 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     761           4 :     if(xHierarchyAccess.is())
     762             :     {
     763             :         try
     764             :         {
     765           4 :             Reference<XNameContainer> xCont;
     766           4 :             if(!rNode.isEmpty())
     767             :             {
     768           4 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     769           4 :                 aNode >>= xCont;
     770             :             }
     771             :             else
     772           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     773           4 :             if(!xCont.is())
     774           0 :                 return sal_False;
     775           8 :             Sequence< OUString > aNames = xCont->getElementNames();
     776           4 :             const OUString* pNames = aNames.getConstArray();
     777           8 :             Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     778          19 :             for(sal_Int32 i = 0; i < aNames.getLength(); i++)
     779             :             {
     780             :                 try
     781             :                 {
     782          15 :                     xCont->removeByName(pNames[i]);
     783             :                 }
     784           0 :                 CATCH_INFO("Exception from removeByName(): ")
     785             :             }
     786           4 :             xBatch->commitChanges();
     787           8 :             bRet = sal_True;
     788             :         }
     789           0 :         CATCH_INFO("Exception from ClearNodeSet")
     790             :     }
     791           8 :     return bRet;
     792             : }
     793             : 
     794          25 : sal_Bool ConfigItem::ClearNodeElements(const OUString& rNode, Sequence< OUString >& rElements)
     795             : {
     796          25 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
     797          25 :     sal_Bool bRet = sal_False;
     798          50 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     799          25 :     if(xHierarchyAccess.is())
     800             :     {
     801          25 :         const OUString* pElements = rElements.getConstArray();
     802             :         try
     803             :         {
     804          25 :             Reference<XNameContainer> xCont;
     805          25 :             if(!rNode.isEmpty())
     806             :             {
     807          25 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     808          25 :                 aNode >>= xCont;
     809             :             }
     810             :             else
     811           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     812          25 :             if(!xCont.is())
     813           0 :                 return sal_False;
     814             :             try
     815             :             {
     816          35 :                 for(sal_Int32 nElement = 0; nElement < rElements.getLength(); nElement++)
     817             :                 {
     818          25 :                     xCont->removeByName(pElements[nElement]);
     819             :                 }
     820          10 :                 Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     821          10 :                 xBatch->commitChanges();
     822             :             }
     823          15 :             CATCH_INFO("Exception from commitChanges(): ")
     824          25 :             bRet = sal_True;
     825             :         }
     826           0 :         CATCH_INFO("Exception from GetNodeNames: ")
     827             :     }
     828          50 :     return bRet;
     829             : }
     830             : //----------------------------------------------------------------------------
     831             : static inline
     832         966 : OUString lcl_extractSetPropertyName( const OUString& rInPath, const OUString& rPrefix )
     833             : {
     834         966 :     OUString const sSubPath = dropPrefixFromConfigurationPath( rInPath, rPrefix);
     835         966 :     return extractFirstFromConfigurationPath( sSubPath );
     836             : }
     837             : //----------------------------------------------------------------------------
     838             : static
     839         365 : Sequence< OUString > lcl_extractSetPropertyNames( const Sequence< PropertyValue >& rValues, const OUString& rPrefix )
     840             : {
     841         365 :     const PropertyValue* pProperties = rValues.getConstArray();
     842             : 
     843         365 :     Sequence< OUString > aSubNodeNames(rValues.getLength());
     844         365 :     OUString* pSubNodeNames = aSubNodeNames.getArray();
     845             : 
     846         730 :     OUString sLastSubNode;
     847         365 :     sal_Int32 nSubIndex = 0;
     848             : 
     849        2040 :     for(sal_Int32 i = 0; i < rValues.getLength(); i++)
     850             :     {
     851        1675 :         OUString const sSubPath = dropPrefixFromConfigurationPath( pProperties[i].Name, rPrefix);
     852        3350 :         OUString const sSubNode = extractFirstFromConfigurationPath( sSubPath );
     853             : 
     854        1675 :         if(sLastSubNode != sSubNode)
     855             :         {
     856        1003 :             pSubNodeNames[nSubIndex++] = sSubNode;
     857             :         }
     858             : 
     859        1675 :         sLastSubNode = sSubNode;
     860        1675 :     }
     861         365 :     aSubNodeNames.realloc(nSubIndex);
     862             : 
     863         730 :     return aSubNodeNames;
     864             : }
     865             : 
     866             : // Add or change properties
     867          37 : sal_Bool ConfigItem::SetSetProperties(
     868             :     const OUString& rNode, Sequence< PropertyValue > rValues)
     869             : {
     870          37 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
     871          37 :     sal_Bool bRet = sal_True;
     872          74 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     873          37 :     if(xHierarchyAccess.is())
     874             :     {
     875          37 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     876             :         try
     877             :         {
     878          37 :             Reference<XNameContainer> xCont;
     879          37 :             if(!rNode.isEmpty())
     880             :             {
     881          37 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     882          37 :                 aNode >>= xCont;
     883             :             }
     884             :             else
     885           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     886          37 :             if(!xCont.is())
     887           0 :                 return sal_False;
     888             : 
     889          74 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
     890             : 
     891          37 :             if(xFac.is())
     892             :             {
     893          37 :                 const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode);
     894             : 
     895          37 :                 const sal_Int32 nSubNodeCount = aSubNodeNames.getLength();
     896             : 
     897          74 :                 for(sal_Int32 j = 0; j <nSubNodeCount ; j++)
     898             :                 {
     899          37 :                     if(!xCont->hasByName(aSubNodeNames[j]))
     900             :                     {
     901          25 :                         Reference<XInterface> xInst = xFac->createInstance();
     902          50 :                         Any aVal; aVal <<= xInst;
     903          50 :                         xCont->insertByName(aSubNodeNames[j], aVal);
     904             :                     }
     905             :                     //set values
     906             :                 }
     907             :                 try
     908             :                 {
     909          37 :                     xBatch->commitChanges();
     910             :                 }
     911           0 :                 CATCH_INFO("Exception from commitChanges(): ")
     912             : 
     913          37 :                 const PropertyValue* pProperties = rValues.getConstArray();
     914             : 
     915          74 :                 Sequence< OUString > aSetNames(rValues.getLength());
     916          37 :                 OUString* pSetNames = aSetNames.getArray();
     917             : 
     918          74 :                 Sequence< Any> aSetValues(rValues.getLength());
     919          37 :                 Any* pSetValues = aSetValues.getArray();
     920             : 
     921          37 :                 sal_Bool bEmptyNode = rNode.isEmpty();
     922         746 :                 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
     923             :                 {
     924         709 :                     pSetNames[k] =  pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
     925         709 :                     pSetValues[k] = pProperties[k].Value;
     926             :                 }
     927          74 :                 bRet = PutProperties(aSetNames, aSetValues);
     928             :             }
     929             :             else
     930             :             {
     931             :                 //if no factory is available then the node contains basic data elements
     932           0 :                 const PropertyValue* pValues = rValues.getConstArray();
     933           0 :                 for(int nValue = 0; nValue < rValues.getLength();nValue++)
     934             :                 {
     935             :                     try
     936             :                     {
     937           0 :                         OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode );
     938             : 
     939           0 :                         if(xCont->hasByName(sSubNode))
     940           0 :                             xCont->replaceByName(sSubNode, pValues[nValue].Value);
     941             :                         else
     942           0 :                             xCont->insertByName(sSubNode, pValues[nValue].Value);
     943             : 
     944             :                         OSL_ENSURE( xHierarchyAccess->hasByHierarchicalName(pValues[nValue].Name),
     945           0 :                             "Invalid config path" );
     946             :                     }
     947           0 :                     CATCH_INFO("Exception form insert/replaceByName(): ")
     948             :                 }
     949           0 :                 xBatch->commitChanges();
     950          37 :             }
     951             :         }
     952             : #ifdef DBG_UTIL
     953             :         catch (const Exception& rEx)
     954             :         {
     955             :             lcl_CFG_DBG_EXCEPTION("Exception from SetSetProperties: ", rEx);
     956             : #else
     957           0 :         catch (const Exception&)
     958             :         {
     959             : #endif
     960           0 :             bRet = sal_False;
     961          37 :         }
     962             :     }
     963          74 :     return bRet;
     964             : }
     965             : 
     966         328 : sal_Bool ConfigItem::ReplaceSetProperties(
     967             :     const OUString& rNode, Sequence< PropertyValue > rValues)
     968             : {
     969         328 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
     970         328 :     sal_Bool bRet = sal_True;
     971         656 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
     972         328 :     if(xHierarchyAccess.is())
     973             :     {
     974         328 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
     975             :         try
     976             :         {
     977         328 :             Reference<XNameContainer> xCont;
     978         328 :             if(!rNode.isEmpty())
     979             :             {
     980         328 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
     981         328 :                 aNode >>= xCont;
     982             :             }
     983             :             else
     984           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
     985         328 :             if(!xCont.is())
     986           0 :                 return sal_False;
     987             : 
     988             :             // JB: Change: now the same name handling for sets of simple values
     989         656 :             const Sequence< OUString > aSubNodeNames = lcl_extractSetPropertyNames(rValues, rNode);
     990         328 :             const OUString* pSubNodeNames = aSubNodeNames.getConstArray();
     991         328 :             const sal_Int32 nSubNodeCount = aSubNodeNames.getLength();
     992             : 
     993         656 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
     994         328 :             const bool isSimpleValueSet = !xFac.is();
     995             : 
     996             :             //remove unknown members first
     997             :             {
     998         328 :                 const Sequence<OUString> aContainerSubNodes = xCont->getElementNames();
     999         328 :                 const OUString* pContainerSubNodes = aContainerSubNodes.getConstArray();
    1000             : 
    1001         664 :                 for(sal_Int32 nContSub = 0; nContSub < aContainerSubNodes.getLength(); nContSub++)
    1002             :                 {
    1003         336 :                     sal_Bool bFound = sal_False;
    1004        3376 :                     for(sal_Int32 j = 0; j < nSubNodeCount; j++)
    1005             :                     {
    1006        3376 :                         if(pSubNodeNames[j] == pContainerSubNodes[nContSub])
    1007             :                         {
    1008         336 :                             bFound = sal_True;
    1009         336 :                             break;
    1010             :                         }
    1011             :                     }
    1012         336 :                     if(!bFound)
    1013             :                     try
    1014             :                     {
    1015           0 :                         xCont->removeByName(pContainerSubNodes[nContSub]);
    1016             :                     }
    1017           0 :                     catch (const Exception&)
    1018             :                     {
    1019           0 :                         if (isSimpleValueSet)
    1020             :                         {
    1021             :                             try
    1022             :                             {
    1023             :                                 // #i37322#: fallback action: replace with <void/>
    1024           0 :                                 xCont->replaceByName(pContainerSubNodes[nContSub], Any());
    1025             :                                 // fallback successful: continue looping
    1026           0 :                                 continue;
    1027             :                             }
    1028           0 :                             catch (Exception &)
    1029             :                             {} // propagate original exception, if fallback fails
    1030             :                         }
    1031           0 :                         throw;
    1032             :                     }
    1033             :                 }
    1034         328 :                 try { xBatch->commitChanges(); }
    1035         328 :                 CATCH_INFO("Exception from commitChanges(): ")
    1036             :             }
    1037             : 
    1038         328 :             if(xFac.is()) // !isSimpleValueSet
    1039             :             {
    1040           0 :                 for(sal_Int32 j = 0; j < nSubNodeCount; j++)
    1041             :                 {
    1042           0 :                     if(!xCont->hasByName(pSubNodeNames[j]))
    1043             :                     {
    1044             :                         //create if not available
    1045           0 :                         Reference<XInterface> xInst = xFac->createInstance();
    1046           0 :                         Any aVal; aVal <<= xInst;
    1047           0 :                         xCont->insertByName(pSubNodeNames[j], aVal);
    1048             :                     }
    1049             :                 }
    1050           0 :                 try { xBatch->commitChanges(); }
    1051           0 :                 CATCH_INFO("Exception from commitChanges(): ")
    1052             : 
    1053           0 :                 const PropertyValue* pProperties = rValues.getConstArray();
    1054             : 
    1055           0 :                 Sequence< OUString > aSetNames(rValues.getLength());
    1056           0 :                 OUString* pSetNames = aSetNames.getArray();
    1057             : 
    1058           0 :                 Sequence< Any> aSetValues(rValues.getLength());
    1059           0 :                 Any* pSetValues = aSetValues.getArray();
    1060             : 
    1061           0 :                 sal_Bool bEmptyNode = rNode.isEmpty();
    1062           0 :                 for(sal_Int32 k = 0; k < rValues.getLength(); k++)
    1063             :                 {
    1064           0 :                     pSetNames[k] =  pProperties[k].Name.copy( bEmptyNode ? 1 : 0);
    1065           0 :                     pSetValues[k] = pProperties[k].Value;
    1066             :                 }
    1067           0 :                 bRet = PutProperties(aSetNames, aSetValues);
    1068             :             }
    1069             :             else
    1070             :             {
    1071         328 :                 const PropertyValue* pValues = rValues.getConstArray();
    1072             : 
    1073             :                 //if no factory is available then the node contains basic data elements
    1074        1294 :                 for(int nValue = 0; nValue < rValues.getLength();nValue++)
    1075             :                 {
    1076             :                     try
    1077             :                     {
    1078         966 :                         OUString sSubNode = lcl_extractSetPropertyName( pValues[nValue].Name, rNode );
    1079             : 
    1080         966 :                         if(xCont->hasByName(sSubNode))
    1081         336 :                             xCont->replaceByName(sSubNode, pValues[nValue].Value);
    1082             :                         else
    1083         630 :                             xCont->insertByName(sSubNode, pValues[nValue].Value);
    1084             :                     }
    1085           0 :                     CATCH_INFO("Exception from insert/replaceByName(): ");
    1086             :                 }
    1087         328 :                 xBatch->commitChanges();
    1088         328 :             }
    1089             :         }
    1090             : #ifdef DBG_UTIL
    1091             :         catch (const Exception& rEx)
    1092             :         {
    1093             :             lcl_CFG_DBG_EXCEPTION("Exception from ReplaceSetProperties: ", rEx);
    1094             : #else
    1095           0 :         catch (const Exception&)
    1096             :         {
    1097             : #endif
    1098           0 :             bRet = sal_False;
    1099         328 :         }
    1100             :     }
    1101         656 :     return bRet;
    1102             : }
    1103             : 
    1104           0 : sal_Bool ConfigItem::getUniqueSetElementName( const OUString& _rSetNode, OUString& _rName)
    1105             : {
    1106           0 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
    1107           0 :     sal_Bool bRet = sal_False;
    1108           0 :     if(xHierarchyAccess.is())
    1109             :     {
    1110             :         try
    1111             :         {
    1112           0 :             Reference< XNameAccess > xSetNode;
    1113           0 :             xHierarchyAccess->getByHierarchicalName(_rSetNode) >>= xSetNode;
    1114           0 :             if (xSetNode.is())
    1115             :             {
    1116           0 :                 const sal_uInt32 nPrime = 65521;                            // a prime number
    1117           0 :                 const sal_uInt32 nPrimeLess2 = nPrime - 2;
    1118           0 :                 sal_uInt32 nEngendering     = (rand() % nPrimeLess2) + 2;   // the engendering of the field
    1119             : 
    1120             :                 // the element which will loop through the field
    1121           0 :                 sal_uInt32 nFieldElement = nEngendering;
    1122             : 
    1123           0 :                 for (; 1 != nFieldElement; nFieldElement = (nFieldElement * nEngendering) % nPrime)
    1124             :                 {
    1125           0 :                     OUString sThisRoundTrial = _rName;
    1126           0 :                     sThisRoundTrial += OUString::valueOf((sal_Int32)nFieldElement);
    1127             : 
    1128           0 :                     if (!xSetNode->hasByName(sThisRoundTrial))
    1129             :                     {
    1130           0 :                         _rName = sThisRoundTrial;
    1131           0 :                         bRet =  sal_True;
    1132           0 :                         break;
    1133             :                     }
    1134           0 :                 }
    1135           0 :             }
    1136             :         }
    1137           0 :         CATCH_INFO("Exception from getUniqueSetElementName(): ")
    1138             :     }
    1139           0 :     return bRet;
    1140             : }
    1141             : 
    1142           0 : sal_Bool ConfigItem::AddNode(const OUString& rNode, const OUString& rNewNode)
    1143             : {
    1144           0 :     ValueCounter_Impl aCounter(pImpl->nInValueChange);
    1145           0 :     sal_Bool bRet = sal_True;
    1146           0 :     Reference<XHierarchicalNameAccess> xHierarchyAccess = GetTree();
    1147           0 :     if(xHierarchyAccess.is())
    1148             :     {
    1149           0 :         Reference<XChangesBatch> xBatch(xHierarchyAccess, UNO_QUERY);
    1150             :         try
    1151             :         {
    1152           0 :             Reference<XNameContainer> xCont;
    1153           0 :             if(!rNode.isEmpty())
    1154             :             {
    1155           0 :                 Any aNode = xHierarchyAccess->getByHierarchicalName(rNode);
    1156           0 :                 aNode >>= xCont;
    1157             :             }
    1158             :             else
    1159           0 :                 xCont = Reference<XNameContainer> (xHierarchyAccess, UNO_QUERY);
    1160           0 :             if(!xCont.is())
    1161           0 :                 return sal_False;
    1162             : 
    1163           0 :             Reference<XSingleServiceFactory> xFac(xCont, UNO_QUERY);
    1164             : 
    1165           0 :             if(xFac.is())
    1166             :             {
    1167           0 :                 if(!xCont->hasByName(rNewNode))
    1168             :                 {
    1169           0 :                     Reference<XInterface> xInst = xFac->createInstance();
    1170           0 :                     Any aVal; aVal <<= xInst;
    1171           0 :                     xCont->insertByName(rNewNode, aVal);
    1172             :                 }
    1173             :                 try
    1174             :                 {
    1175           0 :                     xBatch->commitChanges();
    1176             :                 }
    1177           0 :                 CATCH_INFO("Exception from commitChanges(): ")
    1178             :             }
    1179             :             else
    1180             :             {
    1181             :                 //if no factory is available then the node contains basic data elements
    1182             :                 try
    1183             :                 {
    1184           0 :                     if(!xCont->hasByName(rNewNode))
    1185           0 :                         xCont->insertByName(rNewNode, Any());
    1186             :                 }
    1187           0 :                 CATCH_INFO("Exception from AddNode(): ")
    1188             :             }
    1189           0 :             xBatch->commitChanges();
    1190             :         }
    1191             : #ifdef DBG_UTIL
    1192             :         catch (const Exception& rEx)
    1193             :         {
    1194             :             lcl_CFG_DBG_EXCEPTION("Exception from AddNode(): ", rEx);
    1195             : #else
    1196           0 :         catch (const Exception&)
    1197             :         {
    1198             : #endif
    1199           0 :             bRet = sal_False;
    1200           0 :         }
    1201             :     }
    1202           0 :     return bRet;
    1203             : }
    1204             : 
    1205       10921 : sal_Int16   ConfigItem::GetMode() const
    1206             : {
    1207       10921 :     return pImpl->nMode;
    1208             : }
    1209             : 
    1210        1900 : void    ConfigItem::SetModified()
    1211             : {
    1212        1900 :     pImpl->bIsModified = sal_True;
    1213        1900 : }
    1214             : 
    1215         291 : void    ConfigItem::ClearModified()
    1216             : {
    1217         291 :     pImpl->bIsModified = sal_False;
    1218         291 : }
    1219             : 
    1220       35579 : sal_Bool ConfigItem::IsModified() const
    1221             : {
    1222       35579 :     return pImpl->bIsModified;
    1223             : }
    1224             : 
    1225        8187 : sal_Bool ConfigItem::IsInValueChange() const
    1226             : {
    1227        8187 :     return pImpl->nInValueChange > 0;
    1228             : }
    1229             : 
    1230       53193 : Reference< XHierarchicalNameAccess> ConfigItem::GetTree()
    1231             : {
    1232       53193 :     Reference< XHierarchicalNameAccess> xRet;
    1233       53193 :     if(!m_xHierarchyAccess.is())
    1234         521 :         xRet = ConfigManager::acquireTree(*this);
    1235             :     else
    1236       52672 :         xRet = m_xHierarchyAccess;
    1237       53193 :     return xRet;
    1238             : }
    1239             : 
    1240             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10