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