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