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_ucb.hxx" 30 31 /************************************************************************** 32 TODO 33 ************************************************************************** 34 35 - HierarchyEntry::move 36 --> Rewrite to use XNamed ( once this is supported by config db api ). 37 38 *************************************************************************/ 39 #include "hierarchydata.hxx" 40 41 #include <vector> 42 #include <osl/diagnose.h> 43 #include <rtl/ustrbuf.hxx> 44 #include <com/sun/star/beans/PropertyValue.hpp> 45 #include <com/sun/star/container/XHierarchicalNameAccess.hpp> 46 #include <com/sun/star/container/XNameContainer.hpp> 47 #include <com/sun/star/container/XNameReplace.hpp> 48 #include <com/sun/star/util/XChangesBatch.hpp> 49 #ifndef _COM_SUN_STAR_UTIL_XOFFICEINSTALLTIONDIRECTORIES_HPP_ 50 #include <com/sun/star/util/XOfficeInstallationDirectories.hpp> 51 #endif 52 #include "hierarchyprovider.hxx" 53 #include "hierarchyuri.hxx" 54 55 using namespace com::sun::star; 56 57 namespace hierarchy_ucp 58 { 59 60 //========================================================================= 61 struct HierarchyEntry::iterator_Impl 62 { 63 HierarchyEntryData entry; 64 uno::Reference< container::XHierarchicalNameAccess > dir; 65 uno::Reference< util::XOfficeInstallationDirectories > officeDirs; 66 uno::Sequence< rtl::OUString> names; 67 sal_Int32 pos; 68 iterator_Impl() 69 : officeDirs( 0 ), pos( -1 /* before first */ ) {}; 70 }; 71 72 //========================================================================= 73 void makeXMLName( const rtl::OUString & rIn, rtl::OUStringBuffer & rBuffer ) 74 { 75 sal_Int32 nCount = rIn.getLength(); 76 for ( sal_Int32 n = 0; n < nCount; ++n ) 77 { 78 const sal_Unicode c = rIn.getStr()[ n ]; 79 switch ( c ) 80 { 81 case '&': 82 rBuffer.appendAscii( "&" ); 83 break; 84 85 case '"': 86 rBuffer.appendAscii( """ ); 87 break; 88 89 case '\'': 90 rBuffer.appendAscii( "'" ); 91 break; 92 93 case '<': 94 rBuffer.appendAscii( "<" ); 95 break; 96 97 case '>': 98 rBuffer.appendAscii( ">" ); 99 break; 100 101 default: 102 rBuffer.append( c ); 103 break; 104 } 105 } 106 } 107 108 //========================================================================= 109 //========================================================================= 110 // 111 // HierarchyEntry Implementation. 112 // 113 //========================================================================= 114 //========================================================================= 115 116 #define READ_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadAccess" 117 #define READWRITE_SERVICE_NAME "com.sun.star.ucb.HierarchyDataReadWriteAccess" 118 119 // describe path of cfg entry 120 #define CFGPROPERTY_NODEPATH "nodepath" 121 122 //========================================================================= 123 HierarchyEntry::HierarchyEntry( 124 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 125 HierarchyContentProvider* pProvider, 126 const rtl::OUString& rURL ) 127 : m_xSMgr( rSMgr ), 128 m_xOfficeInstDirs( pProvider->getOfficeInstallationDirectories() ), 129 m_bTriedToGetRootReadAccess( sal_False ) 130 { 131 HierarchyUri aUri( rURL ); 132 m_aServiceSpecifier = aUri.getService(); 133 134 if ( pProvider ) 135 { 136 m_xConfigProvider 137 = pProvider->getConfigProvider( m_aServiceSpecifier ); 138 m_xRootReadAccess 139 = pProvider->getRootConfigReadNameAccess( m_aServiceSpecifier ); 140 } 141 142 // Note: do not init m_aPath in init list. createPathFromHierarchyURL 143 // needs m_xSMgr and m_aMutex. 144 m_aPath = createPathFromHierarchyURL( aUri ); 145 146 // Extract language independent name from URL. 147 sal_Int32 nPos = rURL.lastIndexOf( '/' ); 148 if ( nPos > HIERARCHY_URL_SCHEME_LENGTH ) 149 m_aName = rURL.copy( nPos + 1 ); 150 else 151 OSL_ENSURE( sal_False, "HierarchyEntry - Invalid URL!" ); 152 } 153 154 //========================================================================= 155 sal_Bool HierarchyEntry::hasData() 156 { 157 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 158 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess 159 = getRootReadAccess(); 160 161 OSL_ENSURE( xRootReadAccess.is(), "HierarchyEntry::hasData - No root!" ); 162 163 if ( xRootReadAccess.is() ) 164 return xRootReadAccess->hasByHierarchicalName( m_aPath ); 165 166 return sal_False; 167 } 168 169 //========================================================================= 170 sal_Bool HierarchyEntry::getData( HierarchyEntryData& rData ) 171 { 172 try 173 { 174 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 175 176 uno::Reference< container::XHierarchicalNameAccess > xRootReadAccess 177 = getRootReadAccess(); 178 179 OSL_ENSURE( xRootReadAccess.is(), 180 "HierarchyEntry::getData - No root!" ); 181 182 if ( xRootReadAccess.is() ) 183 { 184 rtl::OUString aTitlePath = m_aPath; 185 aTitlePath += rtl::OUString::createFromAscii( "/Title" ); 186 187 // Note: Avoid NoSuchElementExceptions, because exceptions are 188 // relatively 'expensive'. Checking for availability of 189 // title value is sufficient here, because if it is 190 // there, the other values will be available too. 191 if ( !xRootReadAccess->hasByHierarchicalName( aTitlePath ) ) 192 return sal_False; 193 194 rtl::OUString aValue; 195 196 // Get Title value. 197 if ( !( xRootReadAccess->getByHierarchicalName( aTitlePath ) 198 >>= aValue ) ) 199 { 200 OSL_ENSURE( sal_False, 201 "HierarchyEntry::getData - " 202 "Got no Title value!" ); 203 return sal_False; 204 } 205 206 rData.setTitle( aValue ); 207 208 // Get TargetURL value. 209 rtl::OUString aTargetURLPath = m_aPath; 210 aTargetURLPath += rtl::OUString::createFromAscii( "/TargetURL" ); 211 if ( !( xRootReadAccess->getByHierarchicalName( aTargetURLPath ) 212 >>= aValue ) ) 213 { 214 OSL_ENSURE( sal_False, 215 "HierarchyEntry::getData - " 216 "Got no TargetURL value!" ); 217 return sal_False; 218 } 219 220 // TargetURL property may contain a reference to the Office 221 // installation directory. To ensure a reloctable office 222 // installation, the path to the office installtion directory must 223 // never be stored directly. A placeholder is used instead. Replace 224 // it by actual installation directory. 225 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) 226 aValue = m_xOfficeInstDirs->makeAbsoluteURL( aValue ); 227 rData.setTargetURL( aValue ); 228 229 rtl::OUString aTypePath = m_aPath; 230 aTypePath += rtl::OUString::createFromAscii( "/Type" ); 231 if ( xRootReadAccess->hasByHierarchicalName( aTypePath ) ) 232 { 233 // Might not be present since it was introduced long after 234 // Title and TargetURL (#82433#)... So not getting it is 235 // not an error. 236 237 // Get Type value. 238 sal_Int32 nType = 0; 239 if ( xRootReadAccess->getByHierarchicalName( aTypePath ) 240 >>= nType ) 241 { 242 if ( nType == 0 ) 243 { 244 rData.setType( HierarchyEntryData::LINK ); 245 } 246 else if ( nType == 1 ) 247 { 248 rData.setType( HierarchyEntryData::FOLDER ); 249 } 250 else 251 { 252 OSL_ENSURE( sal_False, 253 "HierarchyEntry::getData - " 254 "Unknown Type value!" ); 255 return sal_False; 256 } 257 } 258 } 259 260 rData.setName( m_aName ); 261 return sal_True; 262 } 263 } 264 catch ( uno::RuntimeException const & ) 265 { 266 throw; 267 } 268 catch ( container::NoSuchElementException const & ) 269 { 270 // getByHierarchicalName 271 272 OSL_ENSURE( sal_False, 273 "HierarchyEntry::getData - caught NoSuchElementException!" ); 274 } 275 return sal_False; 276 } 277 278 //========================================================================= 279 sal_Bool HierarchyEntry::setData( 280 const HierarchyEntryData& rData, sal_Bool bCreate ) 281 { 282 try 283 { 284 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 285 286 if ( !m_xConfigProvider.is() ) 287 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( 288 m_xSMgr->createInstance( m_aServiceSpecifier ), 289 uno::UNO_QUERY ); 290 291 if ( m_xConfigProvider.is() ) 292 { 293 // Create parent's key. It must exist! 294 295 rtl::OUString aParentPath; 296 sal_Bool bRoot = sal_True; 297 298 sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); 299 if ( nPos != -1 ) 300 { 301 // Skip "/Children" segment of the path, too. 302 nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); 303 304 OSL_ENSURE( nPos != -1, 305 "HierarchyEntry::setData - Wrong path!" ); 306 307 aParentPath += m_aPath.copy( 0, nPos ); 308 bRoot = sal_False; 309 } 310 311 uno::Sequence< uno::Any > aArguments( 1 ); 312 beans::PropertyValue aProperty; 313 314 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 315 CFGPROPERTY_NODEPATH ) ); 316 aProperty.Value <<= aParentPath; 317 aArguments[ 0 ] <<= aProperty; 318 319 uno::Reference< util::XChangesBatch > xBatch( 320 m_xConfigProvider->createInstanceWithArguments( 321 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 322 READWRITE_SERVICE_NAME ) ), 323 aArguments ), 324 uno::UNO_QUERY ); 325 326 OSL_ENSURE( xBatch.is(), 327 "HierarchyEntry::setData - No batch!" ); 328 329 uno::Reference< container::XNameAccess > xParentNameAccess( 330 xBatch, uno::UNO_QUERY ); 331 332 OSL_ENSURE( xParentNameAccess.is(), 333 "HierarchyEntry::setData - No name access!" ); 334 335 if ( xBatch.is() && xParentNameAccess.is() ) 336 { 337 // Try to create own key. It must not exist! 338 339 sal_Bool bExists = sal_True; 340 uno::Any aMyKey; 341 342 try 343 { 344 uno::Reference< container::XNameAccess > xNameAccess; 345 346 if ( bRoot ) 347 { 348 xNameAccess = xParentNameAccess; 349 } 350 else 351 { 352 xParentNameAccess->getByName( 353 rtl::OUString::createFromAscii( "Children" ) ) 354 >>= xNameAccess; 355 } 356 357 if ( xNameAccess->hasByName( m_aName ) ) 358 aMyKey = xNameAccess->getByName( m_aName ); 359 else 360 bExists = sal_False; 361 } 362 catch ( container::NoSuchElementException const & ) 363 { 364 bExists = sal_False; 365 } 366 367 uno::Reference< container::XNameReplace > xNameReplace; 368 uno::Reference< container::XNameContainer > xContainer; 369 370 if ( bExists ) 371 { 372 // Key exists. Replace values. 373 374 aMyKey >>= xNameReplace; 375 376 OSL_ENSURE( xNameReplace.is(), 377 "HierarchyEntry::setData - No name replace!" ); 378 } 379 else 380 { 381 if ( !bCreate ) 382 return sal_True; 383 384 // Key does not exist. Create / fill / insert it. 385 386 uno::Reference< lang::XSingleServiceFactory > xFac; 387 388 if ( bRoot ) 389 { 390 // Special handling for children of root, 391 // which is not an entry. It's only a set 392 // of entries. 393 xFac = uno::Reference< lang::XSingleServiceFactory >( 394 xParentNameAccess, uno::UNO_QUERY ); 395 } 396 else 397 { 398 // Append new entry to parents child list, 399 // which is a set of entries. 400 xParentNameAccess->getByName( 401 rtl::OUString::createFromAscii( 402 "Children" ) ) >>= xFac; 403 } 404 405 OSL_ENSURE( xFac.is(), 406 "HierarchyEntry::setData - No factory!" ); 407 408 if ( xFac.is() ) 409 { 410 xNameReplace 411 = uno::Reference< container::XNameReplace >( 412 xFac->createInstance(), uno::UNO_QUERY ); 413 414 OSL_ENSURE( xNameReplace.is(), 415 "HierarchyEntry::setData - No name replace!" ); 416 417 if ( xNameReplace.is() ) 418 { 419 xContainer 420 = uno::Reference< container::XNameContainer >( 421 xFac, uno::UNO_QUERY ); 422 423 OSL_ENSURE( xContainer.is(), 424 "HierarchyEntry::setData - No container!" ); 425 } 426 } 427 } 428 429 if ( xNameReplace.is() ) 430 { 431 // Set Title value. 432 xNameReplace->replaceByName( 433 rtl::OUString::createFromAscii( "Title" ), 434 uno::makeAny( rData.getTitle() ) ); 435 436 // Set TargetURL value. 437 438 // TargetURL property may contain a reference to the Office 439 // installation directory. To ensure a reloctable office 440 // installation, the path to the office installtion 441 // directory must never be stored directly. Use a 442 // placeholder instead. 443 rtl::OUString aValue( rData.getTargetURL() ); 444 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) 445 aValue 446 = m_xOfficeInstDirs->makeRelocatableURL( aValue ); 447 448 xNameReplace->replaceByName( 449 rtl::OUString::createFromAscii( "TargetURL" ), 450 uno::makeAny( aValue ) ); 451 452 // Set Type value. 453 sal_Int32 nType 454 = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; 455 xNameReplace->replaceByName( 456 rtl::OUString::createFromAscii( "Type" ), 457 uno::makeAny( nType ) ); 458 459 if ( xContainer.is() ) 460 xContainer->insertByName( 461 m_aName, uno::makeAny( xNameReplace ) ); 462 463 // Commit changes. 464 xBatch->commitChanges(); 465 return sal_True; 466 } 467 } 468 } 469 } 470 catch ( uno::RuntimeException const & ) 471 { 472 throw; 473 } 474 catch ( lang::IllegalArgumentException const & ) 475 { 476 // replaceByName, insertByName 477 478 OSL_ENSURE( 479 sal_False, 480 "HierarchyEntry::setData - caught IllegalArgumentException!" ); 481 } 482 catch ( container::NoSuchElementException const & ) 483 { 484 // replaceByName, getByName 485 486 OSL_ENSURE( 487 sal_False, 488 "HierarchyEntry::setData - caught NoSuchElementException!" ); 489 } 490 catch ( container::ElementExistException const & ) 491 { 492 // insertByName 493 494 OSL_ENSURE( 495 sal_False, 496 "HierarchyEntry::setData - caught ElementExistException!" ); 497 } 498 catch ( lang::WrappedTargetException const & ) 499 { 500 // replaceByName, insertByName, getByName, commitChanges 501 502 OSL_ENSURE( 503 sal_False, 504 "HierarchyEntry::setData - caught WrappedTargetException!" ); 505 } 506 catch ( uno::Exception const & ) 507 { 508 // createInstance, createInstanceWithArguments 509 510 OSL_ENSURE( 511 sal_False, 512 "HierarchyEntry::setData - caught Exception!" ); 513 } 514 515 return sal_False; 516 } 517 518 //========================================================================= 519 sal_Bool HierarchyEntry::move( 520 const rtl::OUString& rNewURL, const HierarchyEntryData& rData ) 521 { 522 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 523 524 rtl::OUString aNewPath = createPathFromHierarchyURL( rNewURL ); 525 526 if ( aNewPath == m_aPath ) 527 return sal_True; 528 529 #if 0 530 // In the "near future"... ( not yet implemented in config db ) 531 532 - get update access for m_aPath 533 - update access -> XNamed 534 - xNamed::setName( newName ) 535 - updateaccess commit 536 #else 537 538 sal_Bool bOldRoot = sal_True; 539 uno::Reference< util::XChangesBatch > xOldParentBatch; 540 541 rtl::OUString aNewKey; 542 sal_Int32 nURLPos = rNewURL.lastIndexOf( '/' ); 543 if ( nURLPos > HIERARCHY_URL_SCHEME_LENGTH ) 544 aNewKey = rNewURL.copy( nURLPos + 1 ); 545 else 546 { 547 OSL_ENSURE( sal_False, "HierarchyEntry::move - Invalid URL!" ); 548 return sal_False; 549 } 550 551 sal_Bool bNewRoot = sal_True; 552 uno::Reference< util::XChangesBatch > xNewParentBatch; 553 554 sal_Bool bDifferentParents = sal_True; 555 556 try 557 { 558 if ( !m_xConfigProvider.is() ) 559 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( 560 m_xSMgr->createInstance( m_aServiceSpecifier ), 561 uno::UNO_QUERY ); 562 563 if ( !m_xConfigProvider.is() ) 564 return sal_False; 565 566 rtl::OUString aOldParentPath; 567 sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); 568 if ( nPos != -1 ) 569 { 570 // Skip "/Children" segment of the path, too. 571 nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); 572 573 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); 574 575 aOldParentPath += m_aPath.copy( 0, nPos ); 576 bOldRoot = sal_False; 577 } 578 579 rtl::OUString aNewParentPath; 580 nPos = aNewPath.lastIndexOf( '/' ); 581 if ( nPos != -1 ) 582 { 583 // Skip "/Children" segment of the path, too. 584 nPos = aNewPath.lastIndexOf( '/', nPos - 1 ); 585 586 OSL_ENSURE( nPos != -1, "HierarchyEntry::move - Wrong path!" ); 587 588 aNewParentPath += aNewPath.copy( 0, nPos ); 589 bNewRoot = sal_False; 590 } 591 592 uno::Sequence< uno::Any > aArguments( 1 ); 593 beans::PropertyValue aProperty; 594 595 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 596 CFGPROPERTY_NODEPATH ) ); 597 aProperty.Value <<= aOldParentPath; 598 aArguments[ 0 ] <<= aProperty; 599 600 xOldParentBatch = uno::Reference< util::XChangesBatch >( 601 m_xConfigProvider->createInstanceWithArguments( 602 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 603 READWRITE_SERVICE_NAME ) ), 604 aArguments ), 605 uno::UNO_QUERY ); 606 607 OSL_ENSURE( xOldParentBatch.is(), "HierarchyEntry::move - No batch!" ); 608 609 if ( !xOldParentBatch.is() ) 610 return sal_False; 611 612 if ( aOldParentPath == aNewParentPath ) 613 { 614 bDifferentParents = sal_False; 615 xNewParentBatch = xOldParentBatch; 616 } 617 else 618 { 619 bDifferentParents = sal_True; 620 621 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 622 CFGPROPERTY_NODEPATH ) ); 623 aProperty.Value <<= aNewParentPath; 624 aArguments[ 0 ] <<= aProperty; 625 626 xNewParentBatch = uno::Reference< util::XChangesBatch >( 627 m_xConfigProvider->createInstanceWithArguments( 628 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 629 READWRITE_SERVICE_NAME ) ), 630 aArguments ), 631 uno::UNO_QUERY ); 632 633 OSL_ENSURE( 634 xNewParentBatch.is(), "HierarchyEntry::move - No batch!" ); 635 636 if ( !xNewParentBatch.is() ) 637 return sal_False; 638 } 639 } 640 catch ( uno::RuntimeException const & ) 641 { 642 throw; 643 } 644 catch ( uno::Exception const & ) 645 { 646 // createInstance, createInstanceWithArguments 647 648 OSL_ENSURE( sal_False, "HierarchyEntry::move - caught Exception!" ); 649 return sal_False; 650 } 651 652 ////////////////////////////////////////////////////////////////////// 653 // (1) Get entry... 654 ////////////////////////////////////////////////////////////////////// 655 656 uno::Any aEntry; 657 uno::Reference< container::XNameAccess > xOldParentNameAccess; 658 uno::Reference< container::XNameContainer > xOldNameContainer; 659 660 try 661 { 662 xOldParentNameAccess 663 = uno::Reference< container::XNameAccess >( 664 xOldParentBatch, uno::UNO_QUERY ); 665 666 OSL_ENSURE( xOldParentNameAccess.is(), 667 "HierarchyEntry::move - No name access!" ); 668 669 if ( !xOldParentNameAccess.is() ) 670 return sal_False; 671 672 if ( bOldRoot ) 673 { 674 xOldNameContainer = uno::Reference< container::XNameContainer >( 675 xOldParentNameAccess, uno::UNO_QUERY ); 676 } 677 else 678 { 679 xOldParentNameAccess->getByName( 680 rtl::OUString::createFromAscii( "Children" ) ) 681 >>= xOldNameContainer; 682 } 683 684 aEntry = xOldNameContainer->getByName( m_aName ); 685 } 686 catch ( container::NoSuchElementException const & ) 687 { 688 // getByName 689 690 OSL_ENSURE( sal_False, 691 "HierarchyEntry::move - caught NoSuchElementException!" ); 692 return sal_False; 693 } 694 catch ( lang::WrappedTargetException const & ) 695 { 696 // getByName 697 698 OSL_ENSURE( sal_False, 699 "HierarchyEntry::move - caught WrappedTargetException!" ); 700 return sal_False; 701 } 702 703 ////////////////////////////////////////////////////////////////////// 704 // (2) Remove entry... Note: Insert BEFORE remove does not work! 705 ////////////////////////////////////////////////////////////////////// 706 707 try 708 { 709 xOldNameContainer->removeByName( m_aName ); 710 xOldParentBatch->commitChanges(); 711 } 712 catch ( container::NoSuchElementException const & ) 713 { 714 // getByName, removeByName 715 716 OSL_ENSURE( sal_False, 717 "HierarchyEntry::move - caught NoSuchElementException!" ); 718 return sal_False; 719 } 720 721 ////////////////////////////////////////////////////////////////////// 722 // (3) Insert entry at new parent... 723 ////////////////////////////////////////////////////////////////////// 724 725 try 726 { 727 uno::Reference< container::XNameReplace > xNewNameReplace; 728 aEntry >>= xNewNameReplace; 729 730 OSL_ENSURE( xNewNameReplace.is(), 731 "HierarchyEntry::move - No name replace!" ); 732 733 if ( !xNewNameReplace.is() ) 734 return sal_False; 735 736 uno::Reference< container::XNameAccess > xNewParentNameAccess; 737 if ( bDifferentParents ) 738 xNewParentNameAccess 739 = uno::Reference< container::XNameAccess >( 740 xNewParentBatch, uno::UNO_QUERY ); 741 else 742 xNewParentNameAccess = xOldParentNameAccess; 743 744 OSL_ENSURE( xNewParentNameAccess.is(), 745 "HierarchyEntry::move - No name access!" ); 746 747 if ( !xNewParentNameAccess.is() ) 748 return sal_False; 749 750 uno::Reference< container::XNameContainer > xNewNameContainer; 751 if ( bDifferentParents ) 752 { 753 if ( bNewRoot ) 754 { 755 xNewNameContainer 756 = uno::Reference< container::XNameContainer >( 757 xNewParentNameAccess, uno::UNO_QUERY ); 758 } 759 else 760 { 761 xNewParentNameAccess->getByName( 762 rtl::OUString::createFromAscii( "Children" ) ) 763 >>= xNewNameContainer; 764 } 765 } 766 else 767 xNewNameContainer = xOldNameContainer; 768 769 if ( !xNewNameContainer.is() ) 770 return sal_False; 771 772 xNewNameReplace->replaceByName( 773 rtl::OUString::createFromAscii( "Title" ), 774 uno::makeAny( rData.getTitle() ) ); 775 776 // TargetURL property may contain a reference to the Office 777 // installation directory. To ensure a reloctable office 778 // installation, the path to the office installtion 779 // directory must never be stored directly. Use a placeholder 780 // instead. 781 rtl::OUString aValue( rData.getTargetURL() ); 782 if ( m_xOfficeInstDirs.is() && ( aValue.getLength() > 0 ) ) 783 aValue = m_xOfficeInstDirs->makeRelocatableURL( aValue ); 784 xNewNameReplace->replaceByName( 785 rtl::OUString::createFromAscii( "TargetURL" ), 786 uno::makeAny( aValue ) ); 787 sal_Int32 nType = rData.getType() == HierarchyEntryData::LINK ? 0 : 1; 788 xNewNameReplace->replaceByName( 789 rtl::OUString::createFromAscii( "Type" ), 790 uno::makeAny( nType ) ); 791 792 xNewNameContainer->insertByName( aNewKey, aEntry ); 793 xNewParentBatch->commitChanges(); 794 } 795 catch ( container::NoSuchElementException const & ) 796 { 797 // replaceByName, insertByName, getByName 798 799 OSL_ENSURE( sal_False, 800 "HierarchyEntry::move - caught NoSuchElementException!" ); 801 return sal_False; 802 } 803 catch ( lang::IllegalArgumentException const & ) 804 { 805 // replaceByName, insertByName 806 807 OSL_ENSURE( 808 sal_False, 809 "HierarchyEntry::move - caught IllegalArgumentException!" ); 810 return sal_False; 811 } 812 catch ( container::ElementExistException const & ) 813 { 814 // insertByName 815 816 OSL_ENSURE( sal_False, 817 "HierarchyEntry::move - caught ElementExistException!" ); 818 return sal_False; 819 } 820 catch ( lang::WrappedTargetException const & ) 821 { 822 // replaceByName, insertByName, getByName 823 824 OSL_ENSURE( sal_False, 825 "HierarchyEntry::move - caught WrappedTargetException!" ); 826 return sal_False; 827 } 828 829 #if 0 830 ////////////////////////////////////////////////////////////////////// 831 // (4) Commit changes... 832 ////////////////////////////////////////////////////////////////////// 833 834 try 835 { 836 xNewParentBatch->commitChanges(); 837 838 if ( bDifferentParents ) 839 xOldParentBatch->commitChanges(); 840 } 841 catch ( lang::WrappedTargetException const & ) 842 { 843 // commitChanges 844 845 OSL_ENSURE( sal_False, 846 "HierarchyEntry::move - caught WrappedTargetException!" ); 847 return sal_False; 848 } 849 #endif 850 851 return sal_True; 852 #endif 853 } 854 855 //========================================================================= 856 sal_Bool HierarchyEntry::remove() 857 { 858 try 859 { 860 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 861 862 if ( !m_xConfigProvider.is() ) 863 m_xConfigProvider = uno::Reference< lang::XMultiServiceFactory >( 864 m_xSMgr->createInstance( m_aServiceSpecifier ), 865 uno::UNO_QUERY ); 866 867 if ( m_xConfigProvider.is() ) 868 { 869 // Create parent's key. It must exist! 870 871 rtl::OUString aParentPath; 872 sal_Bool bRoot = sal_True; 873 874 sal_Int32 nPos = m_aPath.lastIndexOf( '/' ); 875 if ( nPos != -1 ) 876 { 877 // Skip "/Children" segment of the path, too. 878 nPos = m_aPath.lastIndexOf( '/', nPos - 1 ); 879 880 OSL_ENSURE( nPos != -1, 881 "HierarchyEntry::remove - Wrong path!" ); 882 883 aParentPath += m_aPath.copy( 0, nPos ); 884 bRoot = sal_False; 885 } 886 887 uno::Sequence< uno::Any > aArguments( 1 ); 888 beans::PropertyValue aProperty; 889 890 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 891 CFGPROPERTY_NODEPATH ) ); 892 aProperty.Value <<= aParentPath; 893 aArguments[ 0 ] <<= aProperty; 894 895 uno::Reference< util::XChangesBatch > xBatch( 896 m_xConfigProvider->createInstanceWithArguments( 897 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 898 READWRITE_SERVICE_NAME ) ), 899 aArguments ), 900 uno::UNO_QUERY ); 901 902 OSL_ENSURE( xBatch.is(), 903 "HierarchyEntry::remove - No batch!" ); 904 905 uno::Reference< container::XNameAccess > xParentNameAccess( 906 xBatch, uno::UNO_QUERY ); 907 908 OSL_ENSURE( xParentNameAccess.is(), 909 "HierarchyEntry::remove - No name access!" ); 910 911 if ( xBatch.is() && xParentNameAccess.is() ) 912 { 913 uno::Reference< container::XNameContainer > xContainer; 914 915 if ( bRoot ) 916 { 917 // Special handling for children of root, 918 // which is not an entry. It's only a set 919 // of entries. 920 xContainer = uno::Reference< container::XNameContainer >( 921 xParentNameAccess, uno::UNO_QUERY ); 922 } 923 else 924 { 925 // Append new entry to parents child list, 926 // which is a set of entries. 927 xParentNameAccess->getByName( 928 rtl::OUString::createFromAscii( "Children" ) ) 929 >>= xContainer; 930 } 931 932 OSL_ENSURE( xContainer.is(), 933 "HierarchyEntry::remove - No container!" ); 934 935 if ( xContainer.is() ) 936 { 937 xContainer->removeByName( m_aName ); 938 xBatch->commitChanges(); 939 return sal_True; 940 } 941 } 942 } 943 } 944 catch ( uno::RuntimeException const & ) 945 { 946 throw; 947 } 948 catch ( container::NoSuchElementException const & ) 949 { 950 // getByName, removeByName 951 952 OSL_ENSURE( 953 sal_False, 954 "HierarchyEntry::remove - caught NoSuchElementException!" ); 955 } 956 catch ( lang::WrappedTargetException const & ) 957 { 958 // getByName, commitChanges 959 960 OSL_ENSURE( 961 sal_False, 962 "HierarchyEntry::remove - caught WrappedTargetException!" ); 963 } 964 catch ( uno::Exception const & ) 965 { 966 // createInstance, createInstanceWithArguments 967 968 OSL_ENSURE( sal_False, 969 "HierarchyEntry::remove - caught Exception!" ); 970 } 971 972 return sal_False; 973 } 974 975 //========================================================================= 976 sal_Bool HierarchyEntry::first( iterator& it ) 977 { 978 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 979 980 if ( it.m_pImpl->pos == -1 ) 981 { 982 // Init... 983 984 try 985 { 986 uno::Reference< container::XHierarchicalNameAccess > 987 xRootHierNameAccess = getRootReadAccess(); 988 989 if ( xRootHierNameAccess.is() ) 990 { 991 uno::Reference< container::XNameAccess > xNameAccess; 992 993 if ( m_aPath.getLength() > 0 ) 994 { 995 rtl::OUString aPath = m_aPath; 996 aPath += rtl::OUString::createFromAscii( "/Children" ); 997 998 xRootHierNameAccess->getByHierarchicalName( aPath ) 999 >>= xNameAccess; 1000 } 1001 else 1002 xNameAccess 1003 = uno::Reference< container::XNameAccess >( 1004 xRootHierNameAccess, uno::UNO_QUERY ); 1005 1006 OSL_ENSURE( xNameAccess.is(), 1007 "HierarchyEntry::first - No name access!" ); 1008 1009 if ( xNameAccess.is() ) 1010 it.m_pImpl->names = xNameAccess->getElementNames(); 1011 1012 uno::Reference< container::XHierarchicalNameAccess > 1013 xHierNameAccess( xNameAccess, uno::UNO_QUERY ); 1014 1015 OSL_ENSURE( xHierNameAccess.is(), 1016 "HierarchyEntry::first - No hier. name access!" ); 1017 1018 it.m_pImpl->dir = xHierNameAccess; 1019 1020 it.m_pImpl->officeDirs = m_xOfficeInstDirs; 1021 } 1022 } 1023 catch ( uno::RuntimeException const & ) 1024 { 1025 throw; 1026 } 1027 catch ( container::NoSuchElementException const& ) 1028 { 1029 // getByHierarchicalName 1030 1031 OSL_ENSURE( 1032 sal_False, 1033 "HierarchyEntry::first - caught NoSuchElementException!" ); 1034 } 1035 catch ( uno::Exception const & ) 1036 { 1037 OSL_ENSURE( sal_False, 1038 "HierarchyEntry::first - caught Exception!" ); 1039 } 1040 } 1041 1042 if ( it.m_pImpl->names.getLength() == 0 ) 1043 return sal_False; 1044 1045 it.m_pImpl->pos = 0; 1046 return sal_True; 1047 } 1048 1049 //========================================================================= 1050 sal_Bool HierarchyEntry::next( iterator& it ) 1051 { 1052 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1053 1054 if ( it.m_pImpl->pos == -1 ) 1055 return first( it ); 1056 1057 ++(it.m_pImpl->pos); 1058 1059 return ( it.m_pImpl->pos < it.m_pImpl->names.getLength() ); 1060 } 1061 1062 //========================================================================= 1063 rtl::OUString HierarchyEntry::createPathFromHierarchyURL( 1064 const HierarchyUri& rURI ) 1065 { 1066 // Transform path.... 1067 // folder/subfolder/subsubfolder 1068 // --> ['folder']/Children/['subfolder']/Children/['subsubfolder'] 1069 1070 const rtl::OUString aPath = rURI.getPath().copy( 1 ); // skip leading slash. 1071 sal_Int32 nLen = aPath.getLength(); 1072 1073 if ( nLen ) 1074 { 1075 rtl::OUStringBuffer aNewPath; 1076 aNewPath.appendAscii( "['" ); 1077 1078 sal_Int32 nStart = 0; 1079 sal_Int32 nEnd = aPath.indexOf( '/' ); 1080 1081 do 1082 { 1083 if ( nEnd == -1 ) 1084 nEnd = nLen; 1085 1086 rtl::OUString aToken = aPath.copy( nStart, nEnd - nStart ); 1087 makeXMLName( aToken, aNewPath ); 1088 1089 if ( nEnd != nLen ) 1090 { 1091 aNewPath.appendAscii( "']/Children/['" ); 1092 nStart = nEnd + 1; 1093 nEnd = aPath.indexOf( '/', nStart ); 1094 } 1095 else 1096 aNewPath.appendAscii( "']" ); 1097 } 1098 while ( nEnd != nLen ); 1099 1100 return aNewPath.makeStringAndClear(); 1101 } 1102 1103 return aPath; 1104 } 1105 1106 //========================================================================= 1107 uno::Reference< container::XHierarchicalNameAccess > 1108 HierarchyEntry::getRootReadAccess() 1109 { 1110 if ( !m_xRootReadAccess.is() ) 1111 { 1112 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1113 if ( !m_xRootReadAccess.is() ) 1114 { 1115 if ( m_bTriedToGetRootReadAccess ) // #82494# 1116 { 1117 OSL_ENSURE( sal_False, 1118 "HierarchyEntry::getRootReadAccess - " 1119 "Unable to read any config data! -> #82494#" ); 1120 return uno::Reference< container::XHierarchicalNameAccess >(); 1121 } 1122 1123 try 1124 { 1125 if ( !m_xConfigProvider.is() ) 1126 m_xConfigProvider 1127 = uno::Reference< lang::XMultiServiceFactory >( 1128 m_xSMgr->createInstance( m_aServiceSpecifier ), 1129 uno::UNO_QUERY ); 1130 1131 if ( m_xConfigProvider.is() ) 1132 { 1133 // Create Root object. 1134 1135 uno::Sequence< uno::Any > aArguments( 1 ); 1136 beans::PropertyValue aProperty; 1137 aProperty.Name = rtl::OUString( 1138 RTL_CONSTASCII_USTRINGPARAM( CFGPROPERTY_NODEPATH ) ); 1139 aProperty.Value <<= rtl::OUString(); // root path 1140 aArguments[ 0 ] <<= aProperty; 1141 1142 m_bTriedToGetRootReadAccess = sal_True; 1143 1144 m_xRootReadAccess 1145 = uno::Reference< container::XHierarchicalNameAccess >( 1146 m_xConfigProvider->createInstanceWithArguments( 1147 rtl::OUString( 1148 RTL_CONSTASCII_USTRINGPARAM( 1149 READ_SERVICE_NAME ) ), 1150 aArguments ), 1151 uno::UNO_QUERY ); 1152 } 1153 } 1154 catch ( uno::RuntimeException const & ) 1155 { 1156 throw; 1157 } 1158 catch ( uno::Exception const & ) 1159 { 1160 // createInstance, createInstanceWithArguments 1161 1162 OSL_ENSURE( sal_False, 1163 "HierarchyEntry::getRootReadAccess - " 1164 "caught Exception!" ); 1165 } 1166 } 1167 } 1168 return m_xRootReadAccess; 1169 } 1170 1171 //========================================================================= 1172 //========================================================================= 1173 // 1174 // HierarchyEntry::iterator Implementation. 1175 // 1176 //========================================================================= 1177 //========================================================================= 1178 1179 HierarchyEntry::iterator::iterator() 1180 { 1181 m_pImpl = new iterator_Impl; 1182 } 1183 1184 //========================================================================= 1185 HierarchyEntry::iterator::~iterator() 1186 { 1187 delete m_pImpl; 1188 } 1189 1190 //========================================================================= 1191 const HierarchyEntryData& HierarchyEntry::iterator::operator*() const 1192 { 1193 if ( ( m_pImpl->pos != -1 ) 1194 && ( m_pImpl->dir.is() ) 1195 && ( m_pImpl->pos < m_pImpl->names.getLength() ) ) 1196 { 1197 try 1198 { 1199 rtl::OUStringBuffer aKey; 1200 aKey.appendAscii( "['" ); 1201 makeXMLName( m_pImpl->names.getConstArray()[ m_pImpl->pos ], aKey ); 1202 aKey.appendAscii( "']" ); 1203 1204 rtl::OUString aTitle = aKey.makeStringAndClear(); 1205 rtl::OUString aTargetURL = aTitle; 1206 rtl::OUString aType = aTitle; 1207 1208 aTitle += rtl::OUString::createFromAscii( "/Title" ); 1209 aTargetURL += rtl::OUString::createFromAscii( "/TargetURL" ); 1210 aType += rtl::OUString::createFromAscii( "/Type" ); 1211 1212 rtl::OUString aValue; 1213 m_pImpl->dir->getByHierarchicalName( aTitle ) >>= aValue; 1214 m_pImpl->entry.setTitle( aValue ); 1215 1216 m_pImpl->dir->getByHierarchicalName( aTargetURL ) >>= aValue; 1217 1218 // TargetURL property may contain a reference to the Office 1219 // installation directory. To ensure a reloctable office 1220 // installation, the path to the office installtion directory must 1221 // never be stored directly. A placeholder is used instead. Replace 1222 // it by actual installation directory. 1223 if ( m_pImpl->officeDirs.is() && ( aValue.getLength() > 0 ) ) 1224 aValue = m_pImpl->officeDirs->makeAbsoluteURL( aValue ); 1225 m_pImpl->entry.setTargetURL( aValue ); 1226 1227 if ( m_pImpl->dir->hasByHierarchicalName( aType ) ) 1228 { 1229 // Might not be present since it was introduced long 1230 // after Title and TargetURL (#82433#)... So not getting 1231 // it is not an error. 1232 1233 // Get Type value. 1234 sal_Int32 nType = 0; 1235 if ( m_pImpl->dir->getByHierarchicalName( aType ) >>= nType ) 1236 { 1237 if ( nType == 0 ) 1238 { 1239 m_pImpl->entry.setType( HierarchyEntryData::LINK ); 1240 } 1241 else if ( nType == 1 ) 1242 { 1243 m_pImpl->entry.setType( HierarchyEntryData::FOLDER ); 1244 } 1245 else 1246 { 1247 OSL_ENSURE( sal_False, 1248 "HierarchyEntry::getData - " 1249 "Unknown Type value!" ); 1250 } 1251 } 1252 } 1253 1254 m_pImpl->entry.setName( 1255 m_pImpl->names.getConstArray()[ m_pImpl->pos ] ); 1256 } 1257 catch ( container::NoSuchElementException const & ) 1258 { 1259 m_pImpl->entry = HierarchyEntryData(); 1260 } 1261 } 1262 1263 return m_pImpl->entry; 1264 } 1265 1266 } // namespace hierarchy_ucp 1267