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