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

Generated by: LCOV version 1.10