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