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 - optimize transfer command. "Move" should be implementable much more 36 efficient! 37 38 ************************************************************************** 39 40 - Root Folder vs. 'normal' Folder 41 - root doesn't support command 'delete' 42 - root doesn't support command 'insert' 43 - root needs not created via XContentCreator - queryContent with root 44 folder id ( HIERARCHY_ROOT_FOLDER_URL ) always returns a value != 0 45 - root has no parent. 46 47 *************************************************************************/ 48 #include <osl/diagnose.h> 49 50 #include "osl/doublecheckedlocking.h" 51 #include <rtl/ustring.h> 52 #include <rtl/ustring.hxx> 53 #include <com/sun/star/beans/PropertyAttribute.hpp> 54 #include <com/sun/star/beans/PropertyState.hpp> 55 #include <com/sun/star/beans/PropertyValue.hpp> 56 #include <com/sun/star/beans/XPropertyAccess.hpp> 57 #include <com/sun/star/lang/IllegalAccessException.hpp> 58 #include <com/sun/star/sdbc/XRow.hpp> 59 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 60 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 61 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> 62 #include <com/sun/star/ucb/MissingPropertiesException.hpp> 63 #include <com/sun/star/ucb/NameClash.hpp> 64 #include <com/sun/star/ucb/NameClashException.hpp> 65 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 66 #include <com/sun/star/ucb/TransferInfo.hpp> 67 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> 68 #include <com/sun/star/ucb/XCommandInfo.hpp> 69 #include <com/sun/star/ucb/XPersistentPropertySet.hpp> 70 #include <com/sun/star/uno/Any.hxx> 71 #include <com/sun/star/uno/Sequence.hxx> 72 #include <ucbhelper/contentidentifier.hxx> 73 #include <ucbhelper/propertyvalueset.hxx> 74 #include <ucbhelper/cancelcommandexecution.hxx> 75 #include "hierarchycontent.hxx" 76 #include "hierarchyprovider.hxx" 77 #include "dynamicresultset.hxx" 78 #include "hierarchyuri.hxx" 79 80 #include "../inc/urihelper.hxx" 81 82 using namespace com::sun::star; 83 using namespace hierarchy_ucp; 84 85 //========================================================================= 86 //========================================================================= 87 // 88 // HierarchyContent Implementation. 89 // 90 //========================================================================= 91 //========================================================================= 92 93 // static ( "virtual" ctor ) 94 HierarchyContent* HierarchyContent::create( 95 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 96 HierarchyContentProvider* pProvider, 97 const uno::Reference< ucb::XContentIdentifier >& Identifier ) 98 { 99 // Fail, if content does not exist. 100 HierarchyContentProperties aProps; 101 if ( !loadData( rxSMgr, pProvider, Identifier, aProps ) ) 102 return 0; 103 104 return new HierarchyContent( rxSMgr, pProvider, Identifier, aProps ); 105 } 106 107 //========================================================================= 108 // static ( "virtual" ctor ) 109 HierarchyContent* HierarchyContent::create( 110 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 111 HierarchyContentProvider* pProvider, 112 const uno::Reference< ucb::XContentIdentifier >& Identifier, 113 const ucb::ContentInfo& Info ) 114 { 115 if ( !Info.Type.getLength() ) 116 return 0; 117 118 if ( !Info.Type.equalsAsciiL( 119 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) && 120 !Info.Type.equalsAsciiL( 121 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) 122 return 0; 123 124 #if 0 125 // Fail, if content does exist. 126 if ( hasData( rxSMgr, pProvider, Identifier ) ) 127 return 0; 128 #endif 129 130 return new HierarchyContent( rxSMgr, pProvider, Identifier, Info ); 131 } 132 133 //========================================================================= 134 HierarchyContent::HierarchyContent( 135 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 136 HierarchyContentProvider* pProvider, 137 const uno::Reference< ucb::XContentIdentifier >& Identifier, 138 const HierarchyContentProperties& rProps ) 139 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 140 m_aProps( rProps ), 141 m_eState( PERSISTENT ), 142 m_pProvider( pProvider ), 143 m_bCheckedReadOnly( false ), 144 m_bIsReadOnly( true ) 145 { 146 setKind( Identifier ); 147 } 148 149 //========================================================================= 150 HierarchyContent::HierarchyContent( 151 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 152 HierarchyContentProvider* pProvider, 153 const uno::Reference< ucb::XContentIdentifier >& Identifier, 154 const ucb::ContentInfo& Info ) 155 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 156 m_aProps( Info.Type.equalsAsciiL( 157 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ) 158 ? HierarchyEntryData::FOLDER 159 : HierarchyEntryData::LINK ), 160 m_eState( TRANSIENT ), 161 m_pProvider( pProvider ), 162 m_bCheckedReadOnly( false ), 163 m_bIsReadOnly( true ) 164 { 165 setKind( Identifier ); 166 } 167 168 //========================================================================= 169 // virtual 170 HierarchyContent::~HierarchyContent() 171 { 172 } 173 174 //========================================================================= 175 // 176 // XInterface methods. 177 // 178 //========================================================================= 179 180 // virtual 181 void SAL_CALL HierarchyContent::acquire() 182 throw( ) 183 { 184 ContentImplHelper::acquire(); 185 } 186 187 //========================================================================= 188 // virtual 189 void SAL_CALL HierarchyContent::release() 190 throw( ) 191 { 192 ContentImplHelper::release(); 193 } 194 195 //========================================================================= 196 // virtual 197 uno::Any SAL_CALL HierarchyContent::queryInterface( const uno::Type & rType ) 198 throw ( uno::RuntimeException ) 199 { 200 uno::Any aRet = ContentImplHelper::queryInterface( rType ); 201 202 if ( !aRet.hasValue() ) 203 { 204 // Note: isReadOnly may be relative expensive. So avoid calling it 205 // unless it is really necessary. 206 aRet = cppu::queryInterface( 207 rType, static_cast< ucb::XContentCreator * >( this ) ); 208 if ( aRet.hasValue() ) 209 { 210 if ( !isFolder() || isReadOnly() ) 211 return uno::Any(); 212 } 213 } 214 215 return aRet; 216 } 217 218 //========================================================================= 219 // 220 // XTypeProvider methods. 221 // 222 //========================================================================= 223 224 XTYPEPROVIDER_COMMON_IMPL( HierarchyContent ); 225 226 //========================================================================= 227 // virtual 228 uno::Sequence< uno::Type > SAL_CALL HierarchyContent::getTypes() 229 throw( uno::RuntimeException ) 230 { 231 cppu::OTypeCollection * pCollection = 0; 232 233 if ( isFolder() && !isReadOnly() ) 234 { 235 static cppu::OTypeCollection* pFolderTypes = 0; 236 237 pCollection = pFolderTypes; 238 if ( !pCollection ) 239 { 240 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 241 242 pCollection = pFolderTypes; 243 if ( !pCollection ) 244 { 245 static cppu::OTypeCollection aCollection( 246 CPPU_TYPE_REF( lang::XTypeProvider ), 247 CPPU_TYPE_REF( lang::XServiceInfo ), 248 CPPU_TYPE_REF( lang::XComponent ), 249 CPPU_TYPE_REF( ucb::XContent ), 250 CPPU_TYPE_REF( ucb::XCommandProcessor ), 251 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 252 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 253 CPPU_TYPE_REF( beans::XPropertyContainer ), 254 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 255 CPPU_TYPE_REF( container::XChild ), 256 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! 257 pCollection = &aCollection; 258 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 259 pFolderTypes = pCollection; 260 } 261 } 262 else { 263 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 264 } 265 } 266 else 267 { 268 static cppu::OTypeCollection* pDocumentTypes = 0; 269 270 pCollection = pDocumentTypes; 271 if ( !pCollection ) 272 { 273 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 274 275 pCollection = pDocumentTypes; 276 if ( !pCollection ) 277 { 278 static cppu::OTypeCollection aCollection( 279 CPPU_TYPE_REF( lang::XTypeProvider ), 280 CPPU_TYPE_REF( lang::XServiceInfo ), 281 CPPU_TYPE_REF( lang::XComponent ), 282 CPPU_TYPE_REF( ucb::XContent ), 283 CPPU_TYPE_REF( ucb::XCommandProcessor ), 284 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 285 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 286 CPPU_TYPE_REF( beans::XPropertyContainer ), 287 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 288 CPPU_TYPE_REF( container::XChild ) ); 289 pCollection = &aCollection; 290 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 291 pDocumentTypes = pCollection; 292 } 293 } 294 else { 295 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 296 } 297 } 298 299 return (*pCollection).getTypes(); 300 } 301 302 //========================================================================= 303 // 304 // XServiceInfo methods. 305 // 306 //========================================================================= 307 308 // virtual 309 rtl::OUString SAL_CALL HierarchyContent::getImplementationName() 310 throw( uno::RuntimeException ) 311 { 312 return rtl::OUString::createFromAscii( 313 "com.sun.star.comp.ucb.HierarchyContent" ); 314 } 315 316 //========================================================================= 317 // virtual 318 uno::Sequence< rtl::OUString > SAL_CALL 319 HierarchyContent::getSupportedServiceNames() 320 throw( uno::RuntimeException ) 321 { 322 uno::Sequence< rtl::OUString > aSNS( 1 ); 323 324 if ( m_eKind == LINK ) 325 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 326 HIERARCHY_LINK_CONTENT_SERVICE_NAME ); 327 else if ( m_eKind == FOLDER ) 328 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 329 HIERARCHY_FOLDER_CONTENT_SERVICE_NAME ); 330 else 331 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 332 HIERARCHY_ROOT_FOLDER_CONTENT_SERVICE_NAME ); 333 334 return aSNS; 335 } 336 337 //========================================================================= 338 // 339 // XContent methods. 340 // 341 //========================================================================= 342 343 // virtual 344 rtl::OUString SAL_CALL HierarchyContent::getContentType() 345 throw( uno::RuntimeException ) 346 { 347 return m_aProps.getContentType(); 348 } 349 350 //========================================================================= 351 // virtual 352 uno::Reference< ucb::XContentIdentifier > SAL_CALL 353 HierarchyContent::getIdentifier() 354 throw( uno::RuntimeException ) 355 { 356 // Transient? 357 if ( m_eState == TRANSIENT ) 358 { 359 // Transient contents have no identifier. 360 return uno::Reference< ucb::XContentIdentifier >(); 361 } 362 363 return ContentImplHelper::getIdentifier(); 364 } 365 366 //========================================================================= 367 // 368 // XCommandProcessor methods. 369 // 370 //========================================================================= 371 372 // virtual 373 uno::Any SAL_CALL HierarchyContent::execute( 374 const ucb::Command& aCommand, 375 sal_Int32 /*CommandId*/, 376 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 377 throw( uno::Exception, 378 ucb::CommandAbortedException, 379 uno::RuntimeException ) 380 { 381 uno::Any aRet; 382 383 if ( aCommand.Name.equalsAsciiL( 384 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) 385 { 386 ////////////////////////////////////////////////////////////////// 387 // getPropertyValues 388 ////////////////////////////////////////////////////////////////// 389 390 uno::Sequence< beans::Property > Properties; 391 if ( !( aCommand.Argument >>= Properties ) ) 392 { 393 ucbhelper::cancelCommandExecution( 394 uno::makeAny( lang::IllegalArgumentException( 395 rtl::OUString::createFromAscii( 396 "Wrong argument type!" ), 397 static_cast< cppu::OWeakObject * >( this ), 398 -1 ) ), 399 Environment ); 400 // Unreachable 401 } 402 403 aRet <<= getPropertyValues( Properties ); 404 } 405 else if ( aCommand.Name.equalsAsciiL( 406 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) 407 { 408 ////////////////////////////////////////////////////////////////// 409 // setPropertyValues 410 ////////////////////////////////////////////////////////////////// 411 412 uno::Sequence< beans::PropertyValue > aProperties; 413 if ( !( aCommand.Argument >>= aProperties ) ) 414 { 415 ucbhelper::cancelCommandExecution( 416 uno::makeAny( lang::IllegalArgumentException( 417 rtl::OUString::createFromAscii( 418 "Wrong argument type!" ), 419 static_cast< cppu::OWeakObject * >( this ), 420 -1 ) ), 421 Environment ); 422 // Unreachable 423 } 424 425 if ( !aProperties.getLength() ) 426 { 427 ucbhelper::cancelCommandExecution( 428 uno::makeAny( lang::IllegalArgumentException( 429 rtl::OUString::createFromAscii( 430 "No properties!" ), 431 static_cast< cppu::OWeakObject * >( this ), 432 -1 ) ), 433 Environment ); 434 // Unreachable 435 } 436 437 aRet <<= setPropertyValues( aProperties, Environment ); 438 } 439 else if ( aCommand.Name.equalsAsciiL( 440 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) 441 { 442 ////////////////////////////////////////////////////////////////// 443 // getPropertySetInfo 444 ////////////////////////////////////////////////////////////////// 445 446 aRet <<= getPropertySetInfo( Environment ); 447 } 448 else if ( aCommand.Name.equalsAsciiL( 449 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) 450 { 451 ////////////////////////////////////////////////////////////////// 452 // getCommandInfo 453 ////////////////////////////////////////////////////////////////// 454 455 aRet <<= getCommandInfo( Environment ); 456 } 457 else if ( aCommand.Name.equalsAsciiL( 458 RTL_CONSTASCII_STRINGPARAM( "open" ) ) && isFolder() ) 459 { 460 ////////////////////////////////////////////////////////////////// 461 // open command for a folder content 462 ////////////////////////////////////////////////////////////////// 463 464 ucb::OpenCommandArgument2 aOpenCommand; 465 if ( !( aCommand.Argument >>= aOpenCommand ) ) 466 { 467 ucbhelper::cancelCommandExecution( 468 uno::makeAny( lang::IllegalArgumentException( 469 rtl::OUString::createFromAscii( 470 "Wrong argument type!" ), 471 static_cast< cppu::OWeakObject * >( this ), 472 -1 ) ), 473 Environment ); 474 // Unreachable 475 } 476 477 uno::Reference< ucb::XDynamicResultSet > xSet 478 = new DynamicResultSet( m_xSMgr, this, aOpenCommand ); 479 aRet <<= xSet; 480 } 481 else if ( aCommand.Name.equalsAsciiL( 482 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) && 483 ( m_eKind != ROOT ) && !isReadOnly() ) 484 { 485 ////////////////////////////////////////////////////////////////// 486 // insert 487 // ( Not available at root folder ) 488 ////////////////////////////////////////////////////////////////// 489 490 ucb::InsertCommandArgument aArg; 491 if ( !( aCommand.Argument >>= aArg ) ) 492 { 493 ucbhelper::cancelCommandExecution( 494 uno::makeAny( lang::IllegalArgumentException( 495 rtl::OUString::createFromAscii( 496 "Wrong argument type!" ), 497 static_cast< cppu::OWeakObject * >( this ), 498 -1 ) ), 499 Environment ); 500 // Unreachable 501 } 502 503 sal_Int32 nNameClash = aArg.ReplaceExisting 504 ? ucb::NameClash::OVERWRITE 505 : ucb::NameClash::ERROR; 506 insert( nNameClash, Environment ); 507 } 508 else if ( aCommand.Name.equalsAsciiL( 509 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) && 510 ( m_eKind != ROOT ) && !isReadOnly() ) 511 { 512 ////////////////////////////////////////////////////////////////// 513 // delete 514 // ( Not available at root folder ) 515 ////////////////////////////////////////////////////////////////// 516 517 sal_Bool bDeletePhysical = sal_False; 518 aCommand.Argument >>= bDeletePhysical; 519 destroy( bDeletePhysical, Environment ); 520 521 // Remove own and all children's persistent data. 522 if ( !removeData() ) 523 { 524 uno::Any aProps 525 = uno::makeAny( 526 beans::PropertyValue( 527 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 528 "Uri")), 529 -1, 530 uno::makeAny(m_xIdentifier-> 531 getContentIdentifier()), 532 beans::PropertyState_DIRECT_VALUE)); 533 ucbhelper::cancelCommandExecution( 534 ucb::IOErrorCode_CANT_WRITE, 535 uno::Sequence< uno::Any >(&aProps, 1), 536 Environment, 537 rtl::OUString::createFromAscii( 538 "Cannot remove persistent data!" ), 539 this ); 540 // Unreachable 541 } 542 543 // Remove own and all children's Additional Core Properties. 544 removeAdditionalPropertySet( sal_True ); 545 } 546 else if ( aCommand.Name.equalsAsciiL( 547 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) && 548 isFolder() && !isReadOnly() ) 549 { 550 ////////////////////////////////////////////////////////////////// 551 // transfer 552 // ( Not available at link objects ) 553 ////////////////////////////////////////////////////////////////// 554 555 ucb::TransferInfo aInfo; 556 if ( !( aCommand.Argument >>= aInfo ) ) 557 { 558 OSL_ENSURE( sal_False, "Wrong argument type!" ); 559 ucbhelper::cancelCommandExecution( 560 uno::makeAny( lang::IllegalArgumentException( 561 rtl::OUString::createFromAscii( 562 "Wrong argument type!" ), 563 static_cast< cppu::OWeakObject * >( this ), 564 -1 ) ), 565 Environment ); 566 // Unreachable 567 } 568 569 transfer( aInfo, Environment ); 570 } 571 else if ( aCommand.Name.equalsAsciiL( 572 RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && 573 isFolder() && !isReadOnly() ) 574 { 575 ////////////////////////////////////////////////////////////////// 576 // createNewContent 577 // ( Not available at link objects ) 578 ////////////////////////////////////////////////////////////////// 579 580 ucb::ContentInfo aInfo; 581 if ( !( aCommand.Argument >>= aInfo ) ) 582 { 583 OSL_ENSURE( sal_False, "Wrong argument type!" ); 584 ucbhelper::cancelCommandExecution( 585 uno::makeAny( lang::IllegalArgumentException( 586 rtl::OUString::createFromAscii( 587 "Wrong argument type!" ), 588 static_cast< cppu::OWeakObject * >( this ), 589 -1 ) ), 590 Environment ); 591 // Unreachable 592 } 593 594 aRet <<= createNewContent( aInfo ); 595 } 596 else 597 { 598 ////////////////////////////////////////////////////////////////// 599 // Unsupported command 600 ////////////////////////////////////////////////////////////////// 601 602 ucbhelper::cancelCommandExecution( 603 uno::makeAny( ucb::UnsupportedCommandException( 604 rtl::OUString(), 605 static_cast< cppu::OWeakObject * >( this ) ) ), 606 Environment ); 607 // Unreachable 608 } 609 610 return aRet; 611 } 612 613 //========================================================================= 614 // virtual 615 void SAL_CALL HierarchyContent::abort( sal_Int32 /*CommandId*/ ) 616 throw( uno::RuntimeException ) 617 { 618 // @@@ Generally, no action takes much time... 619 } 620 621 //========================================================================= 622 // 623 // XContentCreator methods. 624 // 625 //========================================================================= 626 627 // virtual 628 uno::Sequence< ucb::ContentInfo > SAL_CALL 629 HierarchyContent::queryCreatableContentsInfo() 630 throw( uno::RuntimeException ) 631 { 632 return m_aProps.getCreatableContentsInfo(); 633 } 634 635 //========================================================================= 636 // virtual 637 uno::Reference< ucb::XContent > SAL_CALL 638 HierarchyContent::createNewContent( const ucb::ContentInfo& Info ) 639 throw( uno::RuntimeException ) 640 { 641 if ( isFolder() ) 642 { 643 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 644 645 if ( !Info.Type.getLength() ) 646 return uno::Reference< ucb::XContent >(); 647 648 sal_Bool bCreateFolder = 649 Info.Type.equalsAsciiL( 650 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_FOLDER_CONTENT_TYPE ) ); 651 652 if ( !bCreateFolder && 653 !Info.Type.equalsAsciiL( 654 RTL_CONSTASCII_STRINGPARAM( HIERARCHY_LINK_CONTENT_TYPE ) ) ) 655 return uno::Reference< ucb::XContent >(); 656 657 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 658 659 OSL_ENSURE( aURL.getLength() > 0, 660 "HierarchyContent::createNewContent - empty identifier!" ); 661 662 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) 663 aURL += rtl::OUString::createFromAscii( "/" ); 664 665 if ( bCreateFolder ) 666 aURL += rtl::OUString::createFromAscii( "New_Folder" ); 667 else 668 aURL += rtl::OUString::createFromAscii( "New_Link" ); 669 670 uno::Reference< ucb::XContentIdentifier > xId 671 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); 672 673 return create( m_xSMgr, m_pProvider, xId, Info ); 674 } 675 else 676 { 677 OSL_ENSURE( sal_False, 678 "createNewContent called on non-folder object!" ); 679 return uno::Reference< ucb::XContent >(); 680 } 681 } 682 683 //========================================================================= 684 // virtual 685 rtl::OUString HierarchyContent::getParentURL() 686 { 687 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); 688 return aUri.getParentUri(); 689 } 690 691 //========================================================================= 692 //static 693 sal_Bool HierarchyContent::hasData( 694 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 695 HierarchyContentProvider* pProvider, 696 const uno::Reference< ucb::XContentIdentifier >& Identifier ) 697 { 698 rtl::OUString aURL = Identifier->getContentIdentifier(); 699 700 // Am I a root folder? 701 HierarchyUri aUri( aURL ); 702 if ( aUri.isRootFolder() ) 703 { 704 // hasData must always return 'true' for root folder 705 // even if no persistent data exist!!! 706 return sal_True; 707 } 708 709 return HierarchyEntry( rxSMgr, pProvider, aURL ).hasData(); 710 } 711 712 //========================================================================= 713 //static 714 sal_Bool HierarchyContent::loadData( 715 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 716 HierarchyContentProvider* pProvider, 717 const uno::Reference< ucb::XContentIdentifier >& Identifier, 718 HierarchyContentProperties& rProps ) 719 { 720 rtl::OUString aURL = Identifier->getContentIdentifier(); 721 722 // Am I a root folder? 723 HierarchyUri aUri( aURL ); 724 if ( aUri.isRootFolder() ) 725 { 726 rProps = HierarchyContentProperties( HierarchyEntryData::FOLDER ); 727 } 728 else 729 { 730 HierarchyEntry aEntry( rxSMgr, pProvider, aURL ); 731 HierarchyEntryData aData; 732 if ( !aEntry.getData( aData ) ) 733 return sal_False; 734 735 rProps = HierarchyContentProperties( aData ); 736 } 737 return sal_True; 738 } 739 740 //========================================================================= 741 sal_Bool HierarchyContent::storeData() 742 { 743 HierarchyEntry aEntry( 744 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); 745 return aEntry.setData( m_aProps.getHierarchyEntryData(), sal_True ); 746 } 747 748 //========================================================================= 749 sal_Bool HierarchyContent::renameData( 750 const uno::Reference< ucb::XContentIdentifier >& xOldId, 751 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 752 { 753 HierarchyEntry aEntry( 754 m_xSMgr, m_pProvider, xOldId->getContentIdentifier() ); 755 return aEntry.move( xNewId->getContentIdentifier(), 756 m_aProps.getHierarchyEntryData() ); 757 } 758 759 //========================================================================= 760 sal_Bool HierarchyContent::removeData() 761 { 762 HierarchyEntry aEntry( 763 m_xSMgr, m_pProvider, m_xIdentifier->getContentIdentifier() ); 764 return aEntry.remove(); 765 } 766 767 //========================================================================= 768 void HierarchyContent::setKind( 769 const uno::Reference< ucb::XContentIdentifier >& Identifier ) 770 { 771 if ( m_aProps.getIsFolder() ) 772 { 773 // Am I a root folder? 774 HierarchyUri aUri( Identifier->getContentIdentifier() ); 775 if ( aUri.isRootFolder() ) 776 m_eKind = ROOT; 777 else 778 m_eKind = FOLDER; 779 } 780 else 781 m_eKind = LINK; 782 } 783 784 //========================================================================= 785 bool HierarchyContent::isReadOnly() 786 { 787 if ( !m_bCheckedReadOnly ) 788 { 789 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 790 if ( !m_bCheckedReadOnly ) 791 { 792 m_bCheckedReadOnly = true; 793 m_bIsReadOnly = true; 794 795 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); 796 uno::Reference< lang::XMultiServiceFactory > xConfigProv 797 = m_pProvider->getConfigProvider( aUri.getService() ); 798 if ( xConfigProv.is() ) 799 { 800 uno::Sequence< rtl::OUString > aNames 801 = xConfigProv->getAvailableServiceNames(); 802 sal_Int32 nCount = aNames.getLength(); 803 for ( sal_Int32 n = 0; n < nCount; ++n ) 804 { 805 if ( aNames[ n ].equalsAsciiL( 806 RTL_CONSTASCII_STRINGPARAM( 807 "com.sun.star.ucb.HierarchyDataReadWriteAccess" 808 ) ) ) 809 { 810 m_bIsReadOnly = false; 811 break; 812 } 813 } 814 } 815 } 816 } 817 818 return m_bIsReadOnly; 819 } 820 821 //========================================================================= 822 uno::Reference< ucb::XContentIdentifier > 823 HierarchyContent::makeNewIdentifier( const rtl::OUString& rTitle ) 824 { 825 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 826 827 // Assemble new content identifier... 828 HierarchyUri aUri( m_xIdentifier->getContentIdentifier() ); 829 rtl::OUString aNewURL = aUri.getParentUri(); 830 aNewURL += rtl::OUString::createFromAscii( "/" ); 831 aNewURL += ::ucb_impl::urihelper::encodeSegment( rTitle ); 832 833 return uno::Reference< ucb::XContentIdentifier >( 834 new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL ) ); 835 } 836 837 //========================================================================= 838 void HierarchyContent::queryChildren( HierarchyContentRefList& rChildren ) 839 { 840 if ( ( m_eKind != FOLDER ) && ( m_eKind != ROOT ) ) 841 return; 842 843 // Obtain a list with a snapshot of all currently instanciated contents 844 // from provider and extract the contents which are direct children 845 // of this content. 846 847 ::ucbhelper::ContentRefList aAllContents; 848 m_xProvider->queryExistingContents( aAllContents ); 849 850 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 851 sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); 852 853 if ( nURLPos != ( aURL.getLength() - 1 ) ) 854 { 855 // No trailing slash found. Append. 856 aURL += rtl::OUString::createFromAscii( "/" ); 857 } 858 859 sal_Int32 nLen = aURL.getLength(); 860 861 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 862 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 863 864 while ( it != end ) 865 { 866 ::ucbhelper::ContentImplHelperRef xChild = (*it); 867 rtl::OUString aChildURL 868 = xChild->getIdentifier()->getContentIdentifier(); 869 870 // Is aURL a prefix of aChildURL? 871 if ( ( aChildURL.getLength() > nLen ) && 872 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 873 { 874 sal_Int32 nPos = nLen; 875 nPos = aChildURL.indexOf( '/', nPos ); 876 877 if ( ( nPos == -1 ) || 878 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 879 { 880 // No further slashes/ only a final slash. It's a child! 881 rChildren.push_back( 882 HierarchyContentRef( 883 static_cast< HierarchyContent * >( xChild.get() ) ) ); 884 } 885 } 886 ++it; 887 } 888 } 889 890 //========================================================================= 891 sal_Bool HierarchyContent::exchangeIdentity( 892 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 893 { 894 if ( !xNewId.is() ) 895 return sal_False; 896 897 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 898 899 uno::Reference< ucb::XContent > xThis = this; 900 901 // Already persistent? 902 if ( m_eState != PERSISTENT ) 903 { 904 OSL_ENSURE( sal_False, 905 "HierarchyContent::exchangeIdentity - Not persistent!" ); 906 return sal_False; 907 } 908 909 // Am I the root folder? 910 if ( m_eKind == ROOT ) 911 { 912 OSL_ENSURE( sal_False, "HierarchyContent::exchangeIdentity - " 913 "Not supported by root folder!" ); 914 return sal_False; 915 } 916 917 // Exchange own identitity. 918 919 // Fail, if a content with given id already exists. 920 if ( !hasData( xNewId ) ) 921 { 922 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); 923 924 aGuard.clear(); 925 if ( exchange( xNewId ) ) 926 { 927 if ( m_eKind == FOLDER ) 928 { 929 // Process instanciated children... 930 931 HierarchyContentRefList aChildren; 932 queryChildren( aChildren ); 933 934 HierarchyContentRefList::const_iterator it = aChildren.begin(); 935 HierarchyContentRefList::const_iterator end = aChildren.end(); 936 937 while ( it != end ) 938 { 939 HierarchyContentRef xChild = (*it); 940 941 // Create new content identifier for the child... 942 uno::Reference< ucb::XContentIdentifier > xOldChildId 943 = xChild->getIdentifier(); 944 rtl::OUString aOldChildURL 945 = xOldChildId->getContentIdentifier(); 946 rtl::OUString aNewChildURL 947 = aOldChildURL.replaceAt( 948 0, 949 aOldURL.getLength(), 950 xNewId->getContentIdentifier() ); 951 uno::Reference< ucb::XContentIdentifier > xNewChildId 952 = new ::ucbhelper::ContentIdentifier( 953 m_xSMgr, aNewChildURL ); 954 955 if ( !xChild->exchangeIdentity( xNewChildId ) ) 956 return sal_False; 957 958 ++it; 959 } 960 } 961 return sal_True; 962 } 963 } 964 965 OSL_ENSURE( sal_False, 966 "HierarchyContent::exchangeIdentity - " 967 "Panic! Cannot exchange identity!" ); 968 return sal_False; 969 } 970 971 //========================================================================= 972 // static 973 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( 974 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 975 const uno::Sequence< beans::Property >& rProperties, 976 const HierarchyContentProperties& rData, 977 HierarchyContentProvider* pProvider, 978 const rtl::OUString& rContentId ) 979 { 980 // Note: Empty sequence means "get values of all supported properties". 981 982 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 983 = new ::ucbhelper::PropertyValueSet( rSMgr ); 984 985 sal_Int32 nCount = rProperties.getLength(); 986 if ( nCount ) 987 { 988 uno::Reference< beans::XPropertySet > xAdditionalPropSet; 989 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 990 991 const beans::Property* pProps = rProperties.getConstArray(); 992 for ( sal_Int32 n = 0; n < nCount; ++n ) 993 { 994 const beans::Property& rProp = pProps[ n ]; 995 996 // Process Core properties. 997 998 if ( rProp.Name.equalsAsciiL( 999 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1000 { 1001 xRow->appendString ( rProp, rData.getContentType() ); 1002 } 1003 else if ( rProp.Name.equalsAsciiL( 1004 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1005 { 1006 xRow->appendString ( rProp, rData.getTitle() ); 1007 } 1008 else if ( rProp.Name.equalsAsciiL( 1009 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1010 { 1011 xRow->appendBoolean( rProp, rData.getIsDocument() ); 1012 } 1013 else if ( rProp.Name.equalsAsciiL( 1014 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1015 { 1016 xRow->appendBoolean( rProp, rData.getIsFolder() ); 1017 } 1018 else if ( rProp.Name.equalsAsciiL( 1019 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1020 { 1021 xRow->appendObject( 1022 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) ); 1023 } 1024 else if ( rProp.Name.equalsAsciiL( 1025 RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) 1026 { 1027 // TargetURL is only supported by links. 1028 1029 if ( rData.getIsDocument() ) 1030 xRow->appendString( rProp, rData.getTargetURL() ); 1031 else 1032 xRow->appendVoid( rProp ); 1033 } 1034 else 1035 { 1036 // Not a Core Property! Maybe it's an Additional Core Property?! 1037 1038 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 1039 { 1040 xAdditionalPropSet 1041 = uno::Reference< beans::XPropertySet >( 1042 pProvider->getAdditionalPropertySet( rContentId, 1043 sal_False ), 1044 uno::UNO_QUERY ); 1045 bTriedToGetAdditonalPropSet = sal_True; 1046 } 1047 1048 if ( xAdditionalPropSet.is() ) 1049 { 1050 if ( !xRow->appendPropertySetValue( 1051 xAdditionalPropSet, 1052 rProp ) ) 1053 { 1054 // Append empty entry. 1055 xRow->appendVoid( rProp ); 1056 } 1057 } 1058 else 1059 { 1060 // Append empty entry. 1061 xRow->appendVoid( rProp ); 1062 } 1063 } 1064 } 1065 } 1066 else 1067 { 1068 // Append all Core Properties. 1069 xRow->appendString ( 1070 beans::Property( rtl::OUString::createFromAscii( "ContentType" ), 1071 -1, 1072 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1073 beans::PropertyAttribute::BOUND 1074 | beans::PropertyAttribute::READONLY ), 1075 rData.getContentType() ); 1076 xRow->appendString ( 1077 beans::Property( rtl::OUString::createFromAscii( "Title" ), 1078 -1, 1079 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1080 // @@@ Might actually be read-only! 1081 beans::PropertyAttribute::BOUND ), 1082 rData.getTitle() ); 1083 xRow->appendBoolean( 1084 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), 1085 -1, 1086 getCppuBooleanType(), 1087 beans::PropertyAttribute::BOUND 1088 | beans::PropertyAttribute::READONLY ), 1089 rData.getIsDocument() ); 1090 xRow->appendBoolean( 1091 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), 1092 -1, 1093 getCppuBooleanType(), 1094 beans::PropertyAttribute::BOUND 1095 | beans::PropertyAttribute::READONLY ), 1096 rData.getIsFolder() ); 1097 1098 if ( rData.getIsDocument() ) 1099 xRow->appendString( 1100 beans::Property( rtl::OUString::createFromAscii( "TargetURL" ), 1101 -1, 1102 getCppuType( 1103 static_cast< const rtl::OUString * >( 0 ) ), 1104 // @@@ Might actually be read-only! 1105 beans::PropertyAttribute::BOUND ), 1106 rData.getTargetURL() ); 1107 xRow->appendObject( 1108 beans::Property( 1109 rtl::OUString::createFromAscii( "CreatableContentsInfo" ), 1110 -1, 1111 getCppuType( static_cast< 1112 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), 1113 beans::PropertyAttribute::BOUND 1114 | beans::PropertyAttribute::READONLY ), 1115 uno::makeAny( rData.getCreatableContentsInfo() ) ); 1116 1117 // Append all Additional Core Properties. 1118 1119 uno::Reference< beans::XPropertySet > xSet( 1120 pProvider->getAdditionalPropertySet( rContentId, sal_False ), 1121 uno::UNO_QUERY ); 1122 xRow->appendPropertySet( xSet ); 1123 } 1124 1125 return uno::Reference< sdbc::XRow >( xRow.get() ); 1126 } 1127 1128 //========================================================================= 1129 uno::Reference< sdbc::XRow > HierarchyContent::getPropertyValues( 1130 const uno::Sequence< beans::Property >& rProperties ) 1131 { 1132 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1133 return getPropertyValues( m_xSMgr, 1134 rProperties, 1135 m_aProps, 1136 m_pProvider, 1137 m_xIdentifier->getContentIdentifier() ); 1138 } 1139 1140 //========================================================================= 1141 uno::Sequence< uno::Any > HierarchyContent::setPropertyValues( 1142 const uno::Sequence< beans::PropertyValue >& rValues, 1143 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 1144 throw( uno::Exception ) 1145 { 1146 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1147 1148 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 1149 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 1150 sal_Int32 nChanged = 0; 1151 1152 beans::PropertyChangeEvent aEvent; 1153 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 1154 aEvent.Further = sal_False; 1155 // aEvent.PropertyName = 1156 aEvent.PropertyHandle = -1; 1157 // aEvent.OldValue = 1158 // aEvent.NewValue = 1159 1160 const beans::PropertyValue* pValues = rValues.getConstArray(); 1161 sal_Int32 nCount = rValues.getLength(); 1162 1163 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 1164 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1165 1166 sal_Bool bExchange = sal_False; 1167 rtl::OUString aOldTitle; 1168 rtl::OUString aOldName; 1169 sal_Int32 nTitlePos = -1; 1170 1171 for ( sal_Int32 n = 0; n < nCount; ++n ) 1172 { 1173 const beans::PropertyValue& rValue = pValues[ n ]; 1174 1175 if ( rValue.Name.equalsAsciiL( 1176 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1177 { 1178 // Read-only property! 1179 aRet[ n ] <<= lang::IllegalAccessException( 1180 rtl::OUString::createFromAscii( 1181 "Property is read-only!" ), 1182 static_cast< cppu::OWeakObject * >( this ) ); 1183 } 1184 else if ( rValue.Name.equalsAsciiL( 1185 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1186 { 1187 // Read-only property! 1188 aRet[ n ] <<= lang::IllegalAccessException( 1189 rtl::OUString::createFromAscii( 1190 "Property is read-only!" ), 1191 static_cast< cppu::OWeakObject * >( this ) ); 1192 } 1193 else if ( rValue.Name.equalsAsciiL( 1194 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1195 { 1196 // Read-only property! 1197 aRet[ n ] <<= lang::IllegalAccessException( 1198 rtl::OUString::createFromAscii( 1199 "Property is read-only!" ), 1200 static_cast< cppu::OWeakObject * >( this ) ); 1201 } 1202 else if ( rValue.Name.equalsAsciiL( 1203 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1204 { 1205 // Read-only property! 1206 aRet[ n ] <<= lang::IllegalAccessException( 1207 rtl::OUString::createFromAscii( 1208 "Property is read-only!" ), 1209 static_cast< cppu::OWeakObject * >( this ) ); 1210 } 1211 else if ( rValue.Name.equalsAsciiL( 1212 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1213 { 1214 if ( isReadOnly() ) 1215 { 1216 aRet[ n ] <<= lang::IllegalAccessException( 1217 rtl::OUString::createFromAscii( 1218 "Property is read-only!" ), 1219 static_cast< cppu::OWeakObject * >( this ) ); 1220 } 1221 else 1222 { 1223 rtl::OUString aNewValue; 1224 if ( rValue.Value >>= aNewValue ) 1225 { 1226 // No empty titles! 1227 if ( aNewValue.getLength() > 0 ) 1228 { 1229 if ( aNewValue != m_aProps.getTitle() ) 1230 { 1231 // modified title -> modified URL -> exchange ! 1232 if ( m_eState == PERSISTENT ) 1233 bExchange = sal_True; 1234 1235 aOldTitle = m_aProps.getTitle(); 1236 aOldName = m_aProps.getName(); 1237 1238 m_aProps.setTitle( aNewValue ); 1239 m_aProps.setName( 1240 ::ucb_impl::urihelper::encodeSegment( 1241 aNewValue ) ); 1242 1243 // property change event will be set later... 1244 1245 // remember position within sequence of values 1246 // (for error handling). 1247 nTitlePos = n; 1248 } 1249 } 1250 else 1251 { 1252 aRet[ n ] <<= lang::IllegalArgumentException( 1253 rtl::OUString::createFromAscii( 1254 "Empty title not allowed!" ), 1255 static_cast< cppu::OWeakObject * >( this ), 1256 -1 ); 1257 } 1258 } 1259 else 1260 { 1261 aRet[ n ] <<= beans::IllegalTypeException( 1262 rtl::OUString::createFromAscii( 1263 "Property value has wrong type!" ), 1264 static_cast< cppu::OWeakObject * >( this ) ); 1265 } 1266 } 1267 } 1268 else if ( rValue.Name.equalsAsciiL( 1269 RTL_CONSTASCII_STRINGPARAM( "TargetURL" ) ) ) 1270 { 1271 if ( isReadOnly() ) 1272 { 1273 aRet[ n ] <<= lang::IllegalAccessException( 1274 rtl::OUString::createFromAscii( 1275 "Property is read-only!" ), 1276 static_cast< cppu::OWeakObject * >( this ) ); 1277 } 1278 else 1279 { 1280 // TargetURL is only supported by links. 1281 1282 if ( m_eKind == LINK ) 1283 { 1284 rtl::OUString aNewValue; 1285 if ( rValue.Value >>= aNewValue ) 1286 { 1287 // No empty target URL's! 1288 if ( aNewValue.getLength() > 0 ) 1289 { 1290 if ( aNewValue != m_aProps.getTargetURL() ) 1291 { 1292 aEvent.PropertyName = rValue.Name; 1293 aEvent.OldValue 1294 = uno::makeAny( m_aProps.getTargetURL() ); 1295 aEvent.NewValue 1296 = uno::makeAny( aNewValue ); 1297 1298 aChanges.getArray()[ nChanged ] = aEvent; 1299 1300 m_aProps.setTargetURL( aNewValue ); 1301 nChanged++; 1302 } 1303 } 1304 else 1305 { 1306 aRet[ n ] <<= lang::IllegalArgumentException( 1307 rtl::OUString::createFromAscii( 1308 "Empty target URL not allowed!" ), 1309 static_cast< cppu::OWeakObject * >( this ), 1310 -1 ); 1311 } 1312 } 1313 else 1314 { 1315 aRet[ n ] <<= beans::IllegalTypeException( 1316 rtl::OUString::createFromAscii( 1317 "Property value has wrong type!" ), 1318 static_cast< cppu::OWeakObject * >( this ) ); 1319 } 1320 } 1321 else 1322 { 1323 aRet[ n ] <<= beans::UnknownPropertyException( 1324 rtl::OUString::createFromAscii( 1325 "TargetURL only supported by links!" ), 1326 static_cast< cppu::OWeakObject * >( this ) ); 1327 } 1328 } 1329 } 1330 else 1331 { 1332 // Not a Core Property! Maybe it's an Additional Core Property?! 1333 1334 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 1335 { 1336 xAdditionalPropSet = getAdditionalPropertySet( sal_False ); 1337 bTriedToGetAdditonalPropSet = sal_True; 1338 } 1339 1340 if ( xAdditionalPropSet.is() ) 1341 { 1342 try 1343 { 1344 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue( 1345 rValue.Name ); 1346 if ( aOldValue != rValue.Value ) 1347 { 1348 xAdditionalPropSet->setPropertyValue( 1349 rValue.Name, rValue.Value ); 1350 1351 aEvent.PropertyName = rValue.Name; 1352 aEvent.OldValue = aOldValue; 1353 aEvent.NewValue = rValue.Value; 1354 1355 aChanges.getArray()[ nChanged ] = aEvent; 1356 nChanged++; 1357 } 1358 } 1359 catch ( beans::UnknownPropertyException const & e ) 1360 { 1361 aRet[ n ] <<= e; 1362 } 1363 catch ( lang::WrappedTargetException const & e ) 1364 { 1365 aRet[ n ] <<= e; 1366 } 1367 catch ( beans::PropertyVetoException const & e ) 1368 { 1369 aRet[ n ] <<= e; 1370 } 1371 catch ( lang::IllegalArgumentException const & e ) 1372 { 1373 aRet[ n ] <<= e; 1374 } 1375 } 1376 else 1377 { 1378 aRet[ n ] <<= uno::Exception( 1379 rtl::OUString::createFromAscii( 1380 "No property set for storing the value!" ), 1381 static_cast< cppu::OWeakObject * >( this ) ); 1382 } 1383 } 1384 } 1385 1386 if ( bExchange ) 1387 { 1388 uno::Reference< ucb::XContentIdentifier > xOldId 1389 = m_xIdentifier; 1390 uno::Reference< ucb::XContentIdentifier > xNewId 1391 = makeNewIdentifier( m_aProps.getTitle() ); 1392 1393 aGuard.clear(); 1394 if ( exchangeIdentity( xNewId ) ) 1395 { 1396 // Adapt persistent data. 1397 renameData( xOldId, xNewId ); 1398 1399 // Adapt Additional Core Properties. 1400 renameAdditionalPropertySet( xOldId->getContentIdentifier(), 1401 xNewId->getContentIdentifier(), 1402 sal_True ); 1403 } 1404 else 1405 { 1406 // Roll-back. 1407 m_aProps.setTitle( aOldTitle ); 1408 m_aProps.setName ( aOldName ); 1409 1410 aOldTitle = aOldName = rtl::OUString(); 1411 1412 // Set error . 1413 aRet[ nTitlePos ] <<= uno::Exception( 1414 rtl::OUString::createFromAscii( "Exchange failed!" ), 1415 static_cast< cppu::OWeakObject * >( this ) ); 1416 } 1417 } 1418 1419 if ( aOldTitle.getLength() ) 1420 { 1421 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); 1422 aEvent.OldValue = uno::makeAny( aOldTitle ); 1423 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() ); 1424 1425 aChanges.getArray()[ nChanged ] = aEvent; 1426 nChanged++; 1427 } 1428 1429 if ( nChanged > 0 ) 1430 { 1431 // Save changes, if content was already made persistent. 1432 if ( !bExchange && ( m_eState == PERSISTENT ) ) 1433 { 1434 if ( !storeData() ) 1435 { 1436 uno::Any aProps 1437 = uno::makeAny( 1438 beans::PropertyValue( 1439 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1440 "Uri")), 1441 -1, 1442 uno::makeAny(m_xIdentifier-> 1443 getContentIdentifier()), 1444 beans::PropertyState_DIRECT_VALUE)); 1445 ucbhelper::cancelCommandExecution( 1446 ucb::IOErrorCode_CANT_WRITE, 1447 uno::Sequence< uno::Any >(&aProps, 1), 1448 xEnv, 1449 rtl::OUString::createFromAscii( 1450 "Cannot store persistent data!" ), 1451 this ); 1452 // Unreachable 1453 } 1454 } 1455 1456 aChanges.realloc( nChanged ); 1457 1458 aGuard.clear(); 1459 notifyPropertiesChange( aChanges ); 1460 } 1461 1462 return aRet; 1463 } 1464 1465 //========================================================================= 1466 void HierarchyContent::insert( sal_Int32 nNameClashResolve, 1467 const uno::Reference< 1468 ucb::XCommandEnvironment > & xEnv ) 1469 throw( uno::Exception ) 1470 { 1471 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1472 1473 // Am I the root folder? 1474 if ( m_eKind == ROOT ) 1475 { 1476 ucbhelper::cancelCommandExecution( 1477 uno::makeAny( ucb::UnsupportedCommandException( 1478 rtl::OUString::createFromAscii( 1479 "Not supported by root folder!" ), 1480 static_cast< cppu::OWeakObject * >( this ) ) ), 1481 xEnv ); 1482 // Unreachable 1483 } 1484 1485 // Check, if all required properties were set. 1486 if ( m_aProps.getTitle().getLength() == 0 ) 1487 { 1488 uno::Sequence< rtl::OUString > aProps( 1 ); 1489 aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" ); 1490 ucbhelper::cancelCommandExecution( 1491 uno::makeAny( ucb::MissingPropertiesException( 1492 rtl::OUString(), 1493 static_cast< cppu::OWeakObject * >( this ), 1494 aProps ) ), 1495 xEnv ); 1496 // Unreachable 1497 } 1498 1499 // Assemble new content identifier... 1500 1501 uno::Reference< ucb::XContentIdentifier > xId 1502 = makeNewIdentifier( m_aProps.getTitle() ); 1503 1504 // Handle possible name clash... 1505 1506 switch ( nNameClashResolve ) 1507 { 1508 // fail. 1509 case ucb::NameClash::ERROR: 1510 if ( hasData( xId ) ) 1511 { 1512 ucbhelper::cancelCommandExecution( 1513 uno::makeAny( 1514 ucb::NameClashException( 1515 rtl::OUString(), 1516 static_cast< cppu::OWeakObject * >( this ), 1517 task::InteractionClassification_ERROR, 1518 m_aProps.getTitle() ) ), 1519 xEnv ); 1520 // Unreachable 1521 } 1522 break; 1523 1524 // replace existing object. 1525 case ucb::NameClash::OVERWRITE: 1526 break; 1527 1528 // "invent" a new valid title. 1529 case ucb::NameClash::RENAME: 1530 if ( hasData( xId ) ) 1531 { 1532 sal_Int32 nTry = 0; 1533 1534 do 1535 { 1536 rtl::OUString aNewId = xId->getContentIdentifier(); 1537 aNewId += rtl::OUString::createFromAscii( "_" ); 1538 aNewId += rtl::OUString::valueOf( ++nTry ); 1539 xId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewId ); 1540 } 1541 while ( hasData( xId ) && ( nTry < 1000 ) ); 1542 1543 if ( nTry == 1000 ) 1544 { 1545 ucbhelper::cancelCommandExecution( 1546 uno::makeAny( 1547 ucb::UnsupportedNameClashException( 1548 rtl::OUString::createFromAscii( 1549 "Unable to resolve name clash!" ), 1550 static_cast< cppu::OWeakObject * >( this ), 1551 nNameClashResolve ) ), 1552 xEnv ); 1553 // Unreachable 1554 } 1555 else 1556 { 1557 rtl::OUString aNewTitle( m_aProps.getTitle() ); 1558 aNewTitle += rtl::OUString::createFromAscii( "_" ); 1559 aNewTitle += rtl::OUString::valueOf( nTry ); 1560 m_aProps.setTitle( aNewTitle ); 1561 } 1562 } 1563 break; 1564 1565 case ucb::NameClash::KEEP: // deprecated 1566 case ucb::NameClash::ASK: 1567 default: 1568 if ( hasData( xId ) ) 1569 { 1570 ucbhelper::cancelCommandExecution( 1571 uno::makeAny( 1572 ucb::UnsupportedNameClashException( 1573 rtl::OUString(), 1574 static_cast< cppu::OWeakObject * >( this ), 1575 nNameClashResolve ) ), 1576 xEnv ); 1577 // Unreachable 1578 } 1579 break; 1580 } 1581 1582 // Identifier changed? 1583 sal_Bool bNewId = ( xId->getContentIdentifier() 1584 != m_xIdentifier->getContentIdentifier() ); 1585 m_xIdentifier = xId; 1586 1587 if ( !storeData() ) 1588 { 1589 uno::Any aProps 1590 = uno::makeAny(beans::PropertyValue( 1591 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1592 "Uri")), 1593 -1, 1594 uno::makeAny(m_xIdentifier-> 1595 getContentIdentifier()), 1596 beans::PropertyState_DIRECT_VALUE)); 1597 ucbhelper::cancelCommandExecution( 1598 ucb::IOErrorCode_CANT_WRITE, 1599 uno::Sequence< uno::Any >(&aProps, 1), 1600 xEnv, 1601 rtl::OUString::createFromAscii( "Cannot store persistent data!" ), 1602 this ); 1603 // Unreachable 1604 } 1605 1606 m_eState = PERSISTENT; 1607 1608 if ( bNewId ) 1609 { 1610 aGuard.clear(); 1611 inserted(); 1612 } 1613 } 1614 1615 //========================================================================= 1616 void HierarchyContent::destroy( sal_Bool bDeletePhysical, 1617 const uno::Reference< 1618 ucb::XCommandEnvironment > & xEnv ) 1619 throw( uno::Exception ) 1620 { 1621 // @@@ take care about bDeletePhysical -> trashcan support 1622 1623 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1624 1625 uno::Reference< ucb::XContent > xThis = this; 1626 1627 // Persistent? 1628 if ( m_eState != PERSISTENT ) 1629 { 1630 ucbhelper::cancelCommandExecution( 1631 uno::makeAny( ucb::UnsupportedCommandException( 1632 rtl::OUString::createFromAscii( 1633 "Not persistent!" ), 1634 static_cast< cppu::OWeakObject * >( this ) ) ), 1635 xEnv ); 1636 // Unreachable 1637 } 1638 1639 // Am I the root folder? 1640 if ( m_eKind == ROOT ) 1641 { 1642 ucbhelper::cancelCommandExecution( 1643 uno::makeAny( ucb::UnsupportedCommandException( 1644 rtl::OUString::createFromAscii( 1645 "Not supported by root folder!" ), 1646 static_cast< cppu::OWeakObject * >( this ) ) ), 1647 xEnv ); 1648 // Unreachable 1649 } 1650 1651 m_eState = DEAD; 1652 1653 aGuard.clear(); 1654 deleted(); 1655 1656 if ( m_eKind == FOLDER ) 1657 { 1658 // Process instanciated children... 1659 1660 HierarchyContentRefList aChildren; 1661 queryChildren( aChildren ); 1662 1663 HierarchyContentRefList::const_iterator it = aChildren.begin(); 1664 HierarchyContentRefList::const_iterator end = aChildren.end(); 1665 1666 while ( it != end ) 1667 { 1668 (*it)->destroy( bDeletePhysical, xEnv ); 1669 ++it; 1670 } 1671 } 1672 } 1673 1674 //========================================================================= 1675 void HierarchyContent::transfer( 1676 const ucb::TransferInfo& rInfo, 1677 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 1678 throw( uno::Exception ) 1679 { 1680 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1681 1682 // Persistent? 1683 if ( m_eState != PERSISTENT ) 1684 { 1685 ucbhelper::cancelCommandExecution( 1686 uno::makeAny( ucb::UnsupportedCommandException( 1687 rtl::OUString::createFromAscii( 1688 "Not persistent!" ), 1689 static_cast< cppu::OWeakObject * >( this ) ) ), 1690 xEnv ); 1691 // Unreachable 1692 } 1693 1694 // Is source a hierarchy content? 1695 if ( ( rInfo.SourceURL.getLength() < HIERARCHY_URL_SCHEME_LENGTH + 2 ) || 1696 ( rInfo.SourceURL.compareToAscii( HIERARCHY_URL_SCHEME ":/", 1697 HIERARCHY_URL_SCHEME_LENGTH + 2 ) 1698 != 0 ) ) 1699 { 1700 ucbhelper::cancelCommandExecution( 1701 uno::makeAny( ucb::InteractiveBadTransferURLException( 1702 rtl::OUString(), 1703 static_cast< cppu::OWeakObject * >( this ) ) ), 1704 xEnv ); 1705 // Unreachable 1706 } 1707 1708 // Is source not a parent of me / not me? 1709 rtl::OUString aId = m_xIdentifier->getContentIdentifier(); 1710 sal_Int32 nPos = aId.lastIndexOf( '/' ); 1711 if ( nPos != ( aId.getLength() - 1 ) ) 1712 { 1713 // No trailing slash found. Append. 1714 aId += rtl::OUString::createFromAscii( "/" ); 1715 } 1716 1717 if ( rInfo.SourceURL.getLength() <= aId.getLength() ) 1718 { 1719 if ( aId.compareTo( 1720 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) 1721 { 1722 uno::Any aProps 1723 = uno::makeAny(beans::PropertyValue( 1724 rtl::OUString( 1725 RTL_CONSTASCII_USTRINGPARAM("Uri")), 1726 -1, 1727 uno::makeAny(rInfo.SourceURL), 1728 beans::PropertyState_DIRECT_VALUE)); 1729 ucbhelper::cancelCommandExecution( 1730 ucb::IOErrorCode_RECURSIVE, 1731 uno::Sequence< uno::Any >(&aProps, 1), 1732 xEnv, 1733 rtl::OUString::createFromAscii( 1734 "Target is equal to or is a child of source!" ), 1735 this ); 1736 // Unreachable 1737 } 1738 } 1739 1740 ////////////////////////////////////////////////////////////////////// 1741 // 0) Obtain content object for source. 1742 ////////////////////////////////////////////////////////////////////// 1743 1744 uno::Reference< ucb::XContentIdentifier > xId 1745 = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL ); 1746 1747 // Note: The static cast is okay here, because its sure that 1748 // m_xProvider is always the HierarchyContentProvider. 1749 rtl::Reference< HierarchyContent > xSource; 1750 1751 try 1752 { 1753 xSource = static_cast< HierarchyContent * >( 1754 m_xProvider->queryContent( xId ).get() ); 1755 } 1756 catch ( ucb::IllegalIdentifierException const & ) 1757 { 1758 // queryContent 1759 } 1760 1761 if ( !xSource.is() ) 1762 { 1763 uno::Any aProps 1764 = uno::makeAny(beans::PropertyValue( 1765 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1766 "Uri")), 1767 -1, 1768 uno::makeAny(xId->getContentIdentifier()), 1769 beans::PropertyState_DIRECT_VALUE)); 1770 ucbhelper::cancelCommandExecution( 1771 ucb::IOErrorCode_CANT_READ, 1772 uno::Sequence< uno::Any >(&aProps, 1), 1773 xEnv, 1774 rtl::OUString::createFromAscii( 1775 "Cannot instanciate source object!" ), 1776 this ); 1777 // Unreachable 1778 } 1779 1780 ////////////////////////////////////////////////////////////////////// 1781 // 1) Create new child content. 1782 ////////////////////////////////////////////////////////////////////// 1783 1784 rtl::OUString aType = xSource->isFolder() 1785 ? rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ) 1786 : rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); 1787 ucb::ContentInfo aContentInfo; 1788 aContentInfo.Type = aType; 1789 aContentInfo.Attributes = 0; 1790 1791 // Note: The static cast is okay here, because its sure that 1792 // createNewContent always creates a HierarchyContent. 1793 rtl::Reference< HierarchyContent > xTarget 1794 = static_cast< HierarchyContent * >( 1795 createNewContent( aContentInfo ).get() ); 1796 if ( !xTarget.is() ) 1797 { 1798 uno::Any aProps 1799 = uno::makeAny(beans::PropertyValue( 1800 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1801 "Folder")), 1802 -1, 1803 uno::makeAny(aId), 1804 beans::PropertyState_DIRECT_VALUE)); 1805 ucbhelper::cancelCommandExecution( 1806 ucb::IOErrorCode_CANT_CREATE, 1807 uno::Sequence< uno::Any >(&aProps, 1), 1808 xEnv, 1809 rtl::OUString::createFromAscii( 1810 "XContentCreator::createNewContent failed!" ), 1811 this ); 1812 // Unreachable 1813 } 1814 1815 ////////////////////////////////////////////////////////////////////// 1816 // 2) Copy data from source content to child content. 1817 ////////////////////////////////////////////////////////////////////// 1818 1819 uno::Sequence< beans::Property > aSourceProps 1820 = xSource->getPropertySetInfo( xEnv )->getProperties(); 1821 sal_Int32 nCount = aSourceProps.getLength(); 1822 1823 if ( nCount ) 1824 { 1825 sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 ); 1826 1827 // Get all source values. 1828 uno::Reference< sdbc::XRow > xRow 1829 = xSource->getPropertyValues( aSourceProps ); 1830 1831 uno::Sequence< beans::PropertyValue > aValues( nCount ); 1832 beans::PropertyValue* pValues = aValues.getArray(); 1833 1834 const beans::Property* pProps = aSourceProps.getConstArray(); 1835 for ( sal_Int32 n = 0; n < nCount; ++n ) 1836 { 1837 const beans::Property& rProp = pProps[ n ]; 1838 beans::PropertyValue& rValue = pValues[ n ]; 1839 1840 rValue.Name = rProp.Name; 1841 rValue.Handle = rProp.Handle; 1842 1843 if ( !bHadTitle && rProp.Name.equalsAsciiL( 1844 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1845 { 1846 // Set new title instead of original. 1847 bHadTitle = sal_True; 1848 rValue.Value <<= rInfo.NewTitle; 1849 } 1850 else 1851 rValue.Value = xRow->getObject( 1852 n + 1, 1853 uno::Reference< container::XNameAccess >() ); 1854 1855 rValue.State = beans::PropertyState_DIRECT_VALUE; 1856 1857 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE ) 1858 { 1859 // Add Additional Core Property. 1860 try 1861 { 1862 xTarget->addProperty( rProp.Name, 1863 rProp.Attributes, 1864 rValue.Value ); 1865 } 1866 catch ( beans::PropertyExistException const & ) 1867 { 1868 } 1869 catch ( beans::IllegalTypeException const & ) 1870 { 1871 } 1872 catch ( lang::IllegalArgumentException const & ) 1873 { 1874 } 1875 } 1876 } 1877 1878 // Set target values. 1879 xTarget->setPropertyValues( aValues, xEnv ); 1880 } 1881 1882 ////////////////////////////////////////////////////////////////////// 1883 // 3) Commit (insert) child. 1884 ////////////////////////////////////////////////////////////////////// 1885 1886 xTarget->insert( rInfo.NameClash, xEnv ); 1887 1888 ////////////////////////////////////////////////////////////////////// 1889 // 4) Transfer (copy) children of source. 1890 ////////////////////////////////////////////////////////////////////// 1891 1892 if ( xSource->isFolder() ) 1893 { 1894 HierarchyEntry aFolder( 1895 m_xSMgr, m_pProvider, xId->getContentIdentifier() ); 1896 HierarchyEntry::iterator it; 1897 1898 while ( aFolder.next( it ) ) 1899 { 1900 const HierarchyEntryData& rResult = *it; 1901 1902 rtl::OUString aChildId = xId->getContentIdentifier(); 1903 if ( ( aChildId.lastIndexOf( '/' ) + 1 ) != aChildId.getLength() ) 1904 aChildId += rtl::OUString::createFromAscii( "/" ); 1905 1906 aChildId += rResult.getName(); 1907 1908 ucb::TransferInfo aInfo; 1909 aInfo.MoveData = sal_False; 1910 aInfo.NewTitle = rtl::OUString(); 1911 aInfo.SourceURL = aChildId; 1912 aInfo.NameClash = rInfo.NameClash; 1913 1914 // Transfer child to target. 1915 xTarget->transfer( aInfo, xEnv ); 1916 } 1917 } 1918 1919 ////////////////////////////////////////////////////////////////////// 1920 // 5) Destroy source ( when moving only ) . 1921 ////////////////////////////////////////////////////////////////////// 1922 1923 if ( rInfo.MoveData ) 1924 { 1925 xSource->destroy( sal_True, xEnv ); 1926 1927 // Remove all persistent data of source and its children. 1928 if ( !xSource->removeData() ) 1929 { 1930 uno::Any aProps 1931 = uno::makeAny( 1932 beans::PropertyValue( 1933 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1934 "Uri")), 1935 -1, 1936 uno::makeAny( 1937 xSource->m_xIdentifier-> 1938 getContentIdentifier()), 1939 beans::PropertyState_DIRECT_VALUE)); 1940 ucbhelper::cancelCommandExecution( 1941 ucb::IOErrorCode_CANT_WRITE, 1942 uno::Sequence< uno::Any >(&aProps, 1), 1943 xEnv, 1944 rtl::OUString::createFromAscii( 1945 "Cannot remove persistent data of source object!" ), 1946 this ); 1947 // Unreachable 1948 } 1949 1950 // Remove own and all children's Additional Core Properties. 1951 xSource->removeAdditionalPropertySet( sal_True ); 1952 } 1953 } 1954 1955 //========================================================================= 1956 //========================================================================= 1957 // 1958 // HierarchyContentProperties Implementation. 1959 // 1960 //========================================================================= 1961 //========================================================================= 1962 1963 uno::Sequence< ucb::ContentInfo > 1964 HierarchyContentProperties::getCreatableContentsInfo() const 1965 { 1966 if ( getIsFolder() ) 1967 { 1968 uno::Sequence< ucb::ContentInfo > aSeq( 2 ); 1969 1970 // Folder. 1971 aSeq.getArray()[ 0 ].Type 1972 = rtl::OUString::createFromAscii( HIERARCHY_FOLDER_CONTENT_TYPE ); 1973 aSeq.getArray()[ 0 ].Attributes 1974 = ucb::ContentInfoAttribute::KIND_FOLDER; 1975 1976 uno::Sequence< beans::Property > aFolderProps( 1 ); 1977 aFolderProps.getArray()[ 0 ] = beans::Property( 1978 rtl::OUString::createFromAscii( "Title" ), 1979 -1, 1980 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1981 beans::PropertyAttribute::BOUND ); 1982 aSeq.getArray()[ 0 ].Properties = aFolderProps; 1983 1984 // Link. 1985 aSeq.getArray()[ 1 ].Type 1986 = rtl::OUString::createFromAscii( HIERARCHY_LINK_CONTENT_TYPE ); 1987 aSeq.getArray()[ 1 ].Attributes 1988 = ucb::ContentInfoAttribute::KIND_LINK; 1989 1990 uno::Sequence< beans::Property > aLinkProps( 2 ); 1991 aLinkProps.getArray()[ 0 ] = beans::Property( 1992 rtl::OUString::createFromAscii( "Title" ), 1993 -1, 1994 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1995 beans::PropertyAttribute::BOUND ); 1996 aLinkProps.getArray()[ 1 ] = beans::Property( 1997 rtl::OUString::createFromAscii( "TargetURL" ), 1998 -1, 1999 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 2000 beans::PropertyAttribute::BOUND ); 2001 aSeq.getArray()[ 1 ].Properties = aLinkProps; 2002 2003 return aSeq; 2004 } 2005 else 2006 { 2007 return uno::Sequence< ucb::ContentInfo >( 0 ); 2008 } 2009 } 2010