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