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