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 *************************************************************************/ 36 37 #include "osl/diagnose.h" 38 #include "osl/doublecheckedlocking.h" 39 #include "rtl/ustrbuf.hxx" 40 41 #include "com/sun/star/beans/PropertyAttribute.hpp" 42 #include "com/sun/star/beans/PropertyValue.hpp" 43 #include "com/sun/star/beans/XPropertySet.hpp" 44 #include "com/sun/star/embed/ElementModes.hpp" 45 #include "com/sun/star/embed/XStorage.hpp" 46 #include "com/sun/star/embed/XTransactedObject.hpp" 47 #include "com/sun/star/io/XActiveDataSink.hpp" 48 #include "com/sun/star/io/XActiveDataStreamer.hpp" 49 #include "com/sun/star/lang/IllegalAccessException.hpp" 50 #include "com/sun/star/sdbc/XRow.hpp" 51 #include "com/sun/star/ucb/ContentAction.hpp" 52 #include "com/sun/star/ucb/ContentInfoAttribute.hpp" 53 #include "com/sun/star/ucb/InsertCommandArgument.hpp" 54 #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp" 55 #include "com/sun/star/ucb/MissingInputStreamException.hpp" 56 #include "com/sun/star/ucb/MissingPropertiesException.hpp" 57 #include "com/sun/star/ucb/NameClash.hpp" 58 #include "com/sun/star/ucb/NameClashException.hpp" 59 #include "com/sun/star/ucb/OpenCommandArgument2.hpp" 60 #include "com/sun/star/ucb/OpenMode.hpp" 61 #include "com/sun/star/ucb/TransferInfo.hpp" 62 #include "com/sun/star/ucb/UnsupportedCommandException.hpp" 63 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp" 64 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp" 65 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp" 66 #include "com/sun/star/ucb/XCommandInfo.hpp" 67 #include "com/sun/star/ucb/XPersistentPropertySet.hpp" 68 69 #include "ucbhelper/cancelcommandexecution.hxx" 70 #include "ucbhelper/contentidentifier.hxx" 71 #include "ucbhelper/propertyvalueset.hxx" 72 73 #include "tdoc_content.hxx" 74 #include "tdoc_resultset.hxx" 75 #include "tdoc_passwordrequest.hxx" 76 77 #include "../inc/urihelper.hxx" 78 79 using namespace com::sun::star; 80 using namespace tdoc_ucp; 81 82 //========================================================================= 83 static ContentType lcl_getContentType( const rtl::OUString & rType ) 84 { 85 if ( rType.equalsAsciiL( 86 RTL_CONSTASCII_STRINGPARAM( TDOC_ROOT_CONTENT_TYPE ) ) ) 87 return ROOT; 88 else if ( rType.equalsAsciiL( 89 RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE ) ) ) 90 return DOCUMENT; 91 else if ( rType.equalsAsciiL( 92 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) ) 93 return FOLDER; 94 else if ( rType.equalsAsciiL( 95 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) 96 return STREAM; 97 else 98 { 99 OSL_ENSURE( sal_False, 100 "Content::Content - unsupported content type string" ); 101 return STREAM; 102 } 103 } 104 105 //========================================================================= 106 //========================================================================= 107 // 108 // Content Implementation. 109 // 110 //========================================================================= 111 //========================================================================= 112 113 // static ( "virtual" ctor ) 114 Content* Content::create( 115 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 116 ContentProvider* pProvider, 117 const uno::Reference< ucb::XContentIdentifier >& Identifier ) 118 { 119 // Fail, if resource does not exist. 120 ContentProperties aProps; 121 if ( !Content::loadData( pProvider, 122 Uri( Identifier->getContentIdentifier() ), 123 aProps ) ) 124 return 0; 125 126 return new Content( rxSMgr, pProvider, Identifier, aProps ); 127 } 128 129 //========================================================================= 130 // static ( "virtual" ctor ) 131 Content* Content::create( 132 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 133 ContentProvider* pProvider, 134 const uno::Reference< ucb::XContentIdentifier >& Identifier, 135 const ucb::ContentInfo& Info ) 136 { 137 if ( !Info.Type.getLength() ) 138 return 0; 139 140 if ( !Info.Type.equalsAsciiL( 141 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) && 142 !Info.Type.equalsAsciiL( 143 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) 144 { 145 OSL_ENSURE( sal_False, "Content::create - unsupported content type!" ); 146 return 0; 147 } 148 149 #if 0 150 // Fail, if content does exist. 151 if ( Content::hasData( pProvider, 152 Uri( Identifier->getContentIdentifier() ) ) ) 153 return 0; 154 #endif 155 156 return new Content( rxSMgr, pProvider, Identifier, Info ); 157 } 158 159 //========================================================================= 160 Content::Content( 161 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr, 162 ContentProvider * pProvider, 163 const uno::Reference< ucb::XContentIdentifier > & Identifier, 164 const ContentProperties & rProps ) 165 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 166 m_aProps( rProps ), 167 m_eState( PERSISTENT ), 168 m_pProvider( pProvider ) 169 { 170 } 171 172 //========================================================================= 173 // ctor for a content just created via XContentCreator::createNewContent() 174 Content::Content( 175 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr, 176 ContentProvider* pProvider, 177 const uno::Reference< ucb::XContentIdentifier >& Identifier, 178 const ucb::ContentInfo& Info ) 179 : ContentImplHelper( rxSMgr, pProvider, Identifier ), 180 m_aProps( lcl_getContentType( Info.Type ), rtl::OUString() ), // no Title (yet) 181 m_eState( TRANSIENT ), 182 m_pProvider( pProvider ) 183 { 184 } 185 186 //========================================================================= 187 // virtual 188 Content::~Content() 189 { 190 } 191 192 //========================================================================= 193 // 194 // XInterface methods. 195 // 196 //========================================================================= 197 198 // virtual 199 void SAL_CALL Content::acquire() 200 throw( ) 201 { 202 ContentImplHelper::acquire(); 203 } 204 205 //========================================================================= 206 // virtual 207 void SAL_CALL Content::release() 208 throw( ) 209 { 210 ContentImplHelper::release(); 211 } 212 213 //========================================================================= 214 // virtual 215 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) 216 throw ( uno::RuntimeException ) 217 { 218 uno::Any aRet = ContentImplHelper::queryInterface( rType ); 219 220 if ( !aRet.hasValue() ) 221 { 222 aRet = cppu::queryInterface( 223 rType, static_cast< ucb::XContentCreator * >( this ) ); 224 if ( aRet.hasValue() ) 225 { 226 if ( !m_aProps.isContentCreator() ) 227 return uno::Any(); 228 } 229 } 230 231 return aRet; 232 } 233 234 //========================================================================= 235 // 236 // XTypeProvider methods. 237 // 238 //========================================================================= 239 240 XTYPEPROVIDER_COMMON_IMPL( Content ); 241 242 //========================================================================= 243 // virtual 244 uno::Sequence< uno::Type > SAL_CALL Content::getTypes() 245 throw( uno::RuntimeException ) 246 { 247 cppu::OTypeCollection * pCollection = 0; 248 249 if ( m_aProps.isContentCreator() ) 250 { 251 static cppu::OTypeCollection* pFolderTypes = 0; 252 253 pCollection = pFolderTypes; 254 if ( !pCollection ) 255 { 256 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 257 258 pCollection = pFolderTypes; 259 if ( !pCollection ) 260 { 261 static cppu::OTypeCollection aCollection( 262 CPPU_TYPE_REF( lang::XTypeProvider ), 263 CPPU_TYPE_REF( lang::XServiceInfo ), 264 CPPU_TYPE_REF( lang::XComponent ), 265 CPPU_TYPE_REF( ucb::XContent ), 266 CPPU_TYPE_REF( ucb::XCommandProcessor ), 267 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 268 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 269 CPPU_TYPE_REF( beans::XPropertyContainer ), 270 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 271 CPPU_TYPE_REF( container::XChild ), 272 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !! 273 pCollection = &aCollection; 274 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 275 pFolderTypes = pCollection; 276 } 277 } 278 else { 279 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 280 } 281 } 282 else 283 { 284 static cppu::OTypeCollection* pDocumentTypes = 0; 285 286 pCollection = pDocumentTypes; 287 if ( !pCollection ) 288 { 289 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 290 291 pCollection = pDocumentTypes; 292 if ( !pCollection ) 293 { 294 static cppu::OTypeCollection aCollection( 295 CPPU_TYPE_REF( lang::XTypeProvider ), 296 CPPU_TYPE_REF( lang::XServiceInfo ), 297 CPPU_TYPE_REF( lang::XComponent ), 298 CPPU_TYPE_REF( ucb::XContent ), 299 CPPU_TYPE_REF( ucb::XCommandProcessor ), 300 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ), 301 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ), 302 CPPU_TYPE_REF( beans::XPropertyContainer ), 303 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ), 304 CPPU_TYPE_REF( container::XChild ) ); 305 pCollection = &aCollection; 306 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 307 pDocumentTypes = pCollection; 308 } 309 } 310 else { 311 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 312 } 313 } 314 315 return (*pCollection).getTypes(); 316 } 317 318 //========================================================================= 319 // 320 // XServiceInfo methods. 321 // 322 //========================================================================= 323 324 // virtual 325 rtl::OUString SAL_CALL Content::getImplementationName() 326 throw( uno::RuntimeException ) 327 { 328 return rtl::OUString::createFromAscii( 329 "com.sun.star.comp.ucb.TransientDocumentsContent" ); 330 } 331 332 //========================================================================= 333 // virtual 334 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames() 335 throw( uno::RuntimeException ) 336 { 337 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 338 339 uno::Sequence< rtl::OUString > aSNS( 1 ); 340 341 if ( m_aProps.getType() == STREAM ) 342 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 343 TDOC_STREAM_CONTENT_SERVICE_NAME ); 344 else if ( m_aProps.getType() == FOLDER ) 345 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 346 TDOC_FOLDER_CONTENT_SERVICE_NAME ); 347 else if ( m_aProps.getType() == DOCUMENT ) 348 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 349 TDOC_DOCUMENT_CONTENT_SERVICE_NAME ); 350 else 351 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii( 352 TDOC_ROOT_CONTENT_SERVICE_NAME ); 353 354 return aSNS; 355 } 356 357 //========================================================================= 358 // 359 // XContent methods. 360 // 361 //========================================================================= 362 363 // virtual 364 rtl::OUString SAL_CALL Content::getContentType() 365 throw( uno::RuntimeException ) 366 { 367 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 368 return m_aProps.getContentType(); 369 } 370 371 //========================================================================= 372 // virtual 373 uno::Reference< ucb::XContentIdentifier > SAL_CALL 374 Content::getIdentifier() 375 throw( uno::RuntimeException ) 376 { 377 { 378 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 379 380 // Transient? 381 if ( m_eState == TRANSIENT ) 382 { 383 // Transient contents have no identifier. 384 return uno::Reference< ucb::XContentIdentifier >(); 385 } 386 } 387 return ContentImplHelper::getIdentifier(); 388 } 389 390 //========================================================================= 391 // 392 // XCommandProcessor methods. 393 // 394 //========================================================================= 395 396 // virtual 397 uno::Any SAL_CALL Content::execute( 398 const ucb::Command& aCommand, 399 sal_Int32 /*CommandId*/, 400 const uno::Reference< ucb::XCommandEnvironment >& Environment ) 401 throw( uno::Exception, 402 ucb::CommandAbortedException, 403 uno::RuntimeException ) 404 { 405 uno::Any aRet; 406 407 if ( aCommand.Name.equalsAsciiL( 408 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) 409 { 410 ////////////////////////////////////////////////////////////////// 411 // getPropertyValues 412 ////////////////////////////////////////////////////////////////// 413 414 uno::Sequence< beans::Property > Properties; 415 if ( !( aCommand.Argument >>= Properties ) ) 416 { 417 ucbhelper::cancelCommandExecution( 418 uno::makeAny( lang::IllegalArgumentException( 419 rtl::OUString::createFromAscii( 420 "Wrong argument type!" ), 421 static_cast< cppu::OWeakObject * >( this ), 422 -1 ) ), 423 Environment ); 424 // Unreachable 425 } 426 427 aRet <<= getPropertyValues( Properties ); 428 } 429 else if ( aCommand.Name.equalsAsciiL( 430 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) 431 { 432 ////////////////////////////////////////////////////////////////// 433 // setPropertyValues 434 ////////////////////////////////////////////////////////////////// 435 436 uno::Sequence< beans::PropertyValue > aProperties; 437 if ( !( aCommand.Argument >>= aProperties ) ) 438 { 439 ucbhelper::cancelCommandExecution( 440 uno::makeAny( lang::IllegalArgumentException( 441 rtl::OUString::createFromAscii( 442 "Wrong argument type!" ), 443 static_cast< cppu::OWeakObject * >( this ), 444 -1 ) ), 445 Environment ); 446 // Unreachable 447 } 448 449 if ( !aProperties.getLength() ) 450 { 451 ucbhelper::cancelCommandExecution( 452 uno::makeAny( lang::IllegalArgumentException( 453 rtl::OUString::createFromAscii( 454 "No properties!" ), 455 static_cast< cppu::OWeakObject * >( this ), 456 -1 ) ), 457 Environment ); 458 // Unreachable 459 } 460 461 aRet <<= setPropertyValues( aProperties, Environment ); 462 } 463 else if ( aCommand.Name.equalsAsciiL( 464 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) ) 465 { 466 ////////////////////////////////////////////////////////////////// 467 // getPropertySetInfo 468 ////////////////////////////////////////////////////////////////// 469 470 aRet <<= getPropertySetInfo( Environment ); 471 } 472 else if ( aCommand.Name.equalsAsciiL( 473 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) ) 474 { 475 ////////////////////////////////////////////////////////////////// 476 // getCommandInfo 477 ////////////////////////////////////////////////////////////////// 478 479 aRet <<= getCommandInfo( Environment ); 480 } 481 else if ( aCommand.Name.equalsAsciiL( 482 RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) 483 { 484 ////////////////////////////////////////////////////////////////// 485 // open 486 ////////////////////////////////////////////////////////////////// 487 488 ucb::OpenCommandArgument2 aOpenCommand; 489 if ( !( aCommand.Argument >>= aOpenCommand ) ) 490 { 491 ucbhelper::cancelCommandExecution( 492 uno::makeAny( lang::IllegalArgumentException( 493 rtl::OUString::createFromAscii( 494 "Wrong argument type!" ), 495 static_cast< cppu::OWeakObject * >( this ), 496 -1 ) ), 497 Environment ); 498 // Unreachable 499 } 500 501 aRet = open( aOpenCommand, Environment ); 502 } 503 else if ( aCommand.Name.equalsAsciiL( 504 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) 505 { 506 ////////////////////////////////////////////////////////////////// 507 // insert ( Supported by folders and streams only ) 508 ////////////////////////////////////////////////////////////////// 509 510 ContentType eType = m_aProps.getType(); 511 if ( ( eType != FOLDER ) && ( eType != STREAM ) ) 512 { 513 ucbhelper::cancelCommandExecution( 514 uno::makeAny( ucb::UnsupportedCommandException( 515 rtl::OUString( 516 RTL_CONSTASCII_USTRINGPARAM( 517 "insert command only supported by " 518 "folders and streams!" ) ), 519 static_cast< cppu::OWeakObject * >( this ) ) ), 520 Environment ); 521 // Unreachable 522 } 523 524 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 525 if ( eType == STREAM ) 526 { 527 Uri aUri( m_xIdentifier->getContentIdentifier() ); 528 Uri aParentUri( aUri.getParentUri() ); 529 if ( aParentUri.isDocument() ) 530 { 531 ucbhelper::cancelCommandExecution( 532 uno::makeAny( ucb::UnsupportedCommandException( 533 rtl::OUString( 534 RTL_CONSTASCII_USTRINGPARAM( 535 "insert command not supported by " 536 "streams that are direct children " 537 "of document root!" ) ), 538 static_cast< cppu::OWeakObject * >( 539 this ) ) ), 540 Environment ); 541 // Unreachable 542 } 543 } 544 #endif 545 ucb::InsertCommandArgument aArg; 546 if ( !( aCommand.Argument >>= aArg ) ) 547 { 548 ucbhelper::cancelCommandExecution( 549 uno::makeAny( lang::IllegalArgumentException( 550 rtl::OUString::createFromAscii( 551 "Wrong argument type!" ), 552 static_cast< cppu::OWeakObject * >( this ), 553 -1 ) ), 554 Environment ); 555 // Unreachable 556 } 557 558 sal_Int32 nNameClash = aArg.ReplaceExisting 559 ? ucb::NameClash::OVERWRITE 560 : ucb::NameClash::ERROR; 561 insert( aArg.Data, nNameClash, Environment ); 562 } 563 else if ( aCommand.Name.equalsAsciiL( 564 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) 565 { 566 ////////////////////////////////////////////////////////////////// 567 // delete ( Supported by folders and streams only ) 568 ////////////////////////////////////////////////////////////////// 569 570 { 571 osl::MutexGuard aGuard( m_aMutex ); 572 573 ContentType eType = m_aProps.getType(); 574 if ( ( eType != FOLDER ) && ( eType != STREAM ) ) 575 { 576 ucbhelper::cancelCommandExecution( 577 uno::makeAny( ucb::UnsupportedCommandException( 578 rtl::OUString( 579 RTL_CONSTASCII_USTRINGPARAM( 580 "delete command only supported by " 581 "folders and streams!" ) ), 582 static_cast< cppu::OWeakObject * >( 583 this ) ) ), 584 Environment ); 585 // Unreachable 586 } 587 } 588 589 sal_Bool bDeletePhysical = sal_False; 590 aCommand.Argument >>= bDeletePhysical; 591 destroy( bDeletePhysical, Environment ); 592 593 // Remove own and all children's persistent data. 594 if ( !removeData() ) 595 { 596 uno::Any aProps 597 = uno::makeAny( 598 beans::PropertyValue( 599 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 600 "Uri")), 601 -1, 602 uno::makeAny(m_xIdentifier-> 603 getContentIdentifier()), 604 beans::PropertyState_DIRECT_VALUE)); 605 ucbhelper::cancelCommandExecution( 606 ucb::IOErrorCode_CANT_WRITE, 607 uno::Sequence< uno::Any >(&aProps, 1), 608 Environment, 609 rtl::OUString::createFromAscii( 610 "Cannot remove persistent data!" ), 611 this ); 612 // Unreachable 613 } 614 615 // Remove own and all children's Additional Core Properties. 616 removeAdditionalPropertySet( sal_True ); 617 } 618 else if ( aCommand.Name.equalsAsciiL( 619 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) ) 620 { 621 ////////////////////////////////////////////////////////////////// 622 // transfer ( Supported by document and folders only ) 623 ////////////////////////////////////////////////////////////////// 624 625 { 626 osl::MutexGuard aGuard( m_aMutex ); 627 628 ContentType eType = m_aProps.getType(); 629 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) 630 { 631 ucbhelper::cancelCommandExecution( 632 uno::makeAny( ucb::UnsupportedCommandException( 633 rtl::OUString( 634 RTL_CONSTASCII_USTRINGPARAM( 635 "transfer command only supported " 636 "by folders and documents!" ) ), 637 static_cast< cppu::OWeakObject * >( 638 this ) ) ), 639 Environment ); 640 // Unreachable 641 } 642 } 643 644 ucb::TransferInfo aInfo; 645 if ( !( aCommand.Argument >>= aInfo ) ) 646 { 647 OSL_ENSURE( sal_False, "Wrong argument type!" ); 648 ucbhelper::cancelCommandExecution( 649 uno::makeAny( lang::IllegalArgumentException( 650 rtl::OUString::createFromAscii( 651 "Wrong argument type!" ), 652 static_cast< cppu::OWeakObject * >( this ), 653 -1 ) ), 654 Environment ); 655 // Unreachable 656 } 657 658 transfer( aInfo, Environment ); 659 } 660 else if ( aCommand.Name.equalsAsciiL( 661 RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) ) 662 { 663 ////////////////////////////////////////////////////////////////// 664 // createNewContent ( Supported by document and folders only ) 665 ////////////////////////////////////////////////////////////////// 666 667 { 668 osl::MutexGuard aGuard( m_aMutex ); 669 670 ContentType eType = m_aProps.getType(); 671 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) ) 672 { 673 ucbhelper::cancelCommandExecution( 674 uno::makeAny( ucb::UnsupportedCommandException( 675 rtl::OUString( 676 RTL_CONSTASCII_USTRINGPARAM( 677 "createNewContent command only " 678 "supported by folders and " 679 "documents!" ) ), 680 static_cast< cppu::OWeakObject * >( 681 this ) ) ), 682 Environment ); 683 // Unreachable 684 } 685 } 686 687 ucb::ContentInfo aInfo; 688 if ( !( aCommand.Argument >>= aInfo ) ) 689 { 690 OSL_ENSURE( sal_False, "Wrong argument type!" ); 691 ucbhelper::cancelCommandExecution( 692 uno::makeAny( lang::IllegalArgumentException( 693 rtl::OUString::createFromAscii( 694 "Wrong argument type!" ), 695 static_cast< cppu::OWeakObject * >( this ), 696 -1 ) ), 697 Environment ); 698 // Unreachable 699 } 700 701 aRet <<= createNewContent( aInfo ); 702 } 703 else 704 { 705 ////////////////////////////////////////////////////////////////// 706 // Unsupported command 707 ////////////////////////////////////////////////////////////////// 708 709 ucbhelper::cancelCommandExecution( 710 uno::makeAny( ucb::UnsupportedCommandException( 711 rtl::OUString(), 712 static_cast< cppu::OWeakObject * >( this ) ) ), 713 Environment ); 714 // Unreachable 715 } 716 717 return aRet; 718 } 719 720 //========================================================================= 721 // virtual 722 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) 723 throw( uno::RuntimeException ) 724 { 725 } 726 727 //========================================================================= 728 // 729 // XContentCreator methods. 730 // 731 //========================================================================= 732 733 // virtual 734 uno::Sequence< ucb::ContentInfo > SAL_CALL 735 Content::queryCreatableContentsInfo() 736 throw( uno::RuntimeException ) 737 { 738 return m_aProps.getCreatableContentsInfo(); 739 } 740 741 //========================================================================= 742 // virtual 743 uno::Reference< ucb::XContent > SAL_CALL 744 Content::createNewContent( const ucb::ContentInfo& Info ) 745 throw( uno::RuntimeException ) 746 { 747 if ( m_aProps.isContentCreator() ) 748 { 749 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 750 751 if ( !Info.Type.getLength() ) 752 return uno::Reference< ucb::XContent >(); 753 754 sal_Bool bCreateFolder = 755 Info.Type.equalsAsciiL( 756 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ); 757 758 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 759 // streams cannot be created as direct children of document root 760 if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) ) 761 { 762 OSL_ENSURE( sal_False, 763 "Content::createNewContent - streams cannot be " 764 "created as direct children of document root!" ); 765 return uno::Reference< ucb::XContent >(); 766 } 767 #endif 768 if ( !bCreateFolder && 769 !Info.Type.equalsAsciiL( 770 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) ) 771 { 772 OSL_ENSURE( sal_False, 773 "Content::createNewContent - unsupported type!" ); 774 return uno::Reference< ucb::XContent >(); 775 } 776 777 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 778 779 OSL_ENSURE( aURL.getLength() > 0, 780 "Content::createNewContent - empty identifier!" ); 781 782 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() ) 783 aURL += rtl::OUString::createFromAscii( "/" ); 784 785 if ( bCreateFolder ) 786 aURL += rtl::OUString::createFromAscii( "New_Folder" ); 787 else 788 aURL += rtl::OUString::createFromAscii( "New_Stream" ); 789 790 uno::Reference< ucb::XContentIdentifier > xId 791 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ); 792 793 return create( m_xSMgr, m_pProvider, xId, Info ); 794 } 795 else 796 { 797 OSL_ENSURE( sal_False, 798 "createNewContent called on non-contentcreator object!" ); 799 return uno::Reference< ucb::XContent >(); 800 } 801 } 802 803 //========================================================================= 804 // virtual 805 rtl::OUString Content::getParentURL() 806 { 807 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 808 Uri aUri( m_xIdentifier->getContentIdentifier() ); 809 return aUri.getParentUri(); 810 } 811 812 //========================================================================= 813 uno::Reference< ucb::XContentIdentifier > 814 Content::makeNewIdentifier( const rtl::OUString& rTitle ) 815 { 816 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 817 818 // Assemble new content identifier... 819 Uri aUri( m_xIdentifier->getContentIdentifier() ); 820 rtl::OUStringBuffer aNewURL = aUri.getParentUri(); 821 aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) ); 822 823 return 824 uno::Reference< ucb::XContentIdentifier >( 825 new ::ucbhelper::ContentIdentifier( 826 m_xSMgr, aNewURL.makeStringAndClear() ) ); 827 } 828 829 //========================================================================= 830 void Content::queryChildren( ContentRefList& rChildren ) 831 { 832 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 833 834 // Only folders (root, documents, folders) have children. 835 if ( !m_aProps.getIsFolder() ) 836 return; 837 838 // Obtain a list with a snapshot of all currently instanciated contents 839 // from provider and extract the contents which are direct children 840 // of this content. 841 842 ::ucbhelper::ContentRefList aAllContents; 843 m_xProvider->queryExistingContents( aAllContents ); 844 845 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 846 sal_Int32 nURLPos = aURL.lastIndexOf( '/' ); 847 848 if ( nURLPos != ( aURL.getLength() - 1 ) ) 849 { 850 // No trailing slash found. Append. 851 aURL += rtl::OUString::createFromAscii( "/" ); 852 } 853 854 sal_Int32 nLen = aURL.getLength(); 855 856 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin(); 857 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end(); 858 859 while ( it != end ) 860 { 861 ::ucbhelper::ContentImplHelperRef xChild = (*it); 862 rtl::OUString aChildURL 863 = xChild->getIdentifier()->getContentIdentifier(); 864 865 // Is aURL a prefix of aChildURL? 866 if ( ( aChildURL.getLength() > nLen ) && 867 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) 868 { 869 sal_Int32 nPos = nLen; 870 nPos = aChildURL.indexOf( '/', nPos ); 871 872 if ( ( nPos == -1 ) || 873 ( nPos == ( aChildURL.getLength() - 1 ) ) ) 874 { 875 // No further slashes / only a final slash. It's a child! 876 rChildren.push_back( 877 ContentRef( 878 static_cast< Content * >( xChild.get() ) ) ); 879 } 880 } 881 ++it; 882 } 883 } 884 885 //========================================================================= 886 sal_Bool Content::exchangeIdentity( 887 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 888 { 889 if ( !xNewId.is() ) 890 return sal_False; 891 892 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 893 894 uno::Reference< ucb::XContent > xThis = this; 895 896 // Already persistent? 897 if ( m_eState != PERSISTENT ) 898 { 899 OSL_ENSURE( sal_False, 900 "Content::exchangeIdentity - Not persistent!" ); 901 return sal_False; 902 } 903 904 // Only folders and streams can be renamed -> exchange identity. 905 ContentType eType = m_aProps.getType(); 906 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 907 { 908 OSL_ENSURE( sal_False, "Content::exchangeIdentity - " 909 "Not supported by root or document!" ); 910 return sal_False; 911 } 912 913 // Exchange own identitity. 914 915 // Fail, if a content with given id already exists. 916 if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) ) 917 { 918 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier(); 919 920 aGuard.clear(); 921 if ( exchange( xNewId ) ) 922 { 923 if ( eType == FOLDER ) 924 { 925 // Process instanciated children... 926 927 ContentRefList aChildren; 928 queryChildren( aChildren ); 929 930 ContentRefList::const_iterator it = aChildren.begin(); 931 ContentRefList::const_iterator end = aChildren.end(); 932 933 while ( it != end ) 934 { 935 ContentRef xChild = (*it); 936 937 // Create new content identifier for the child... 938 uno::Reference< ucb::XContentIdentifier > xOldChildId 939 = xChild->getIdentifier(); 940 rtl::OUString aOldChildURL 941 = xOldChildId->getContentIdentifier(); 942 rtl::OUString aNewChildURL 943 = aOldChildURL.replaceAt( 944 0, 945 aOldURL.getLength(), 946 xNewId->getContentIdentifier() ); 947 uno::Reference< ucb::XContentIdentifier > xNewChildId 948 = new ::ucbhelper::ContentIdentifier( 949 m_xSMgr, aNewChildURL ); 950 951 if ( !xChild->exchangeIdentity( xNewChildId ) ) 952 return sal_False; 953 954 ++it; 955 } 956 } 957 return sal_True; 958 } 959 } 960 961 OSL_ENSURE( sal_False, 962 "Content::exchangeIdentity - " 963 "Panic! Cannot exchange identity!" ); 964 return sal_False; 965 } 966 967 //========================================================================= 968 // static 969 uno::Reference< sdbc::XRow > Content::getPropertyValues( 970 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 971 const uno::Sequence< beans::Property >& rProperties, 972 ContentProvider* pProvider, 973 const rtl::OUString& rContentId ) 974 { 975 ContentProperties aData; 976 if ( loadData( pProvider, rContentId, aData ) ) 977 { 978 return getPropertyValues( 979 rSMgr, rProperties, aData, pProvider, rContentId ); 980 } 981 else 982 { 983 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 984 = new ::ucbhelper::PropertyValueSet( rSMgr ); 985 986 sal_Int32 nCount = rProperties.getLength(); 987 if ( nCount ) 988 { 989 const beans::Property* pProps = rProperties.getConstArray(); 990 for ( sal_Int32 n = 0; n < nCount; ++n ) 991 xRow->appendVoid( pProps[ n ] ); 992 } 993 994 return uno::Reference< sdbc::XRow >( xRow.get() ); 995 } 996 } 997 998 //========================================================================= 999 // static 1000 uno::Reference< sdbc::XRow > Content::getPropertyValues( 1001 const uno::Reference< lang::XMultiServiceFactory >& rSMgr, 1002 const uno::Sequence< beans::Property >& rProperties, 1003 const ContentProperties& rData, 1004 ContentProvider* pProvider, 1005 const rtl::OUString& rContentId ) 1006 { 1007 // Note: Empty sequence means "get values of all supported properties". 1008 1009 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow 1010 = new ::ucbhelper::PropertyValueSet( rSMgr ); 1011 1012 sal_Int32 nCount = rProperties.getLength(); 1013 if ( nCount ) 1014 { 1015 uno::Reference< beans::XPropertySet > xAdditionalPropSet; 1016 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1017 1018 const beans::Property* pProps = rProperties.getConstArray(); 1019 for ( sal_Int32 n = 0; n < nCount; ++n ) 1020 { 1021 const beans::Property& rProp = pProps[ n ]; 1022 1023 // Process Core properties. 1024 1025 if ( rProp.Name.equalsAsciiL( 1026 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1027 { 1028 xRow->appendString ( rProp, rData.getContentType() ); 1029 } 1030 else if ( rProp.Name.equalsAsciiL( 1031 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1032 { 1033 xRow->appendString ( rProp, rData.getTitle() ); 1034 } 1035 else if ( rProp.Name.equalsAsciiL( 1036 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1037 { 1038 xRow->appendBoolean( rProp, rData.getIsDocument() ); 1039 } 1040 else if ( rProp.Name.equalsAsciiL( 1041 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1042 { 1043 xRow->appendBoolean( rProp, rData.getIsFolder() ); 1044 } 1045 else if ( rProp.Name.equalsAsciiL( 1046 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1047 { 1048 xRow->appendObject( 1049 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) ); 1050 } 1051 else if ( rProp.Name.equalsAsciiL( 1052 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) ) 1053 { 1054 // Storage is only supported by folders. 1055 ContentType eType = rData.getType(); 1056 if ( eType == FOLDER ) 1057 xRow->appendObject( 1058 rProp, 1059 uno::makeAny( 1060 pProvider->queryStorageClone( rContentId ) ) ); 1061 else 1062 xRow->appendVoid( rProp ); 1063 } 1064 else if ( rProp.Name.equalsAsciiL( 1065 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) 1066 { 1067 // DocumentModel is only supported by documents. 1068 ContentType eType = rData.getType(); 1069 if ( eType == DOCUMENT ) 1070 xRow->appendObject( 1071 rProp, 1072 uno::makeAny( 1073 pProvider->queryDocumentModel( rContentId ) ) ); 1074 else 1075 xRow->appendVoid( rProp ); 1076 } 1077 else 1078 { 1079 // Not a Core Property! Maybe it's an Additional Core Property?! 1080 1081 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 1082 { 1083 xAdditionalPropSet 1084 = uno::Reference< beans::XPropertySet >( 1085 pProvider->getAdditionalPropertySet( rContentId, 1086 sal_False ), 1087 uno::UNO_QUERY ); 1088 bTriedToGetAdditonalPropSet = sal_True; 1089 } 1090 1091 if ( xAdditionalPropSet.is() ) 1092 { 1093 if ( !xRow->appendPropertySetValue( 1094 xAdditionalPropSet, 1095 rProp ) ) 1096 { 1097 // Append empty entry. 1098 xRow->appendVoid( rProp ); 1099 } 1100 } 1101 else 1102 { 1103 // Append empty entry. 1104 xRow->appendVoid( rProp ); 1105 } 1106 } 1107 } 1108 } 1109 else 1110 { 1111 // Append all Core Properties. 1112 xRow->appendString ( 1113 beans::Property( rtl::OUString::createFromAscii( "ContentType" ), 1114 -1, 1115 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1116 beans::PropertyAttribute::BOUND 1117 | beans::PropertyAttribute::READONLY ), 1118 rData.getContentType() ); 1119 1120 ContentType eType = rData.getType(); 1121 1122 xRow->appendString ( 1123 beans::Property( rtl::OUString::createFromAscii( "Title" ), 1124 -1, 1125 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 1126 // Title is read-only for root and documents. 1127 beans::PropertyAttribute::BOUND || 1128 ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 1129 ? beans::PropertyAttribute::READONLY 1130 : 0 ), 1131 rData.getTitle() ); 1132 xRow->appendBoolean( 1133 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ), 1134 -1, 1135 getCppuBooleanType(), 1136 beans::PropertyAttribute::BOUND 1137 | beans::PropertyAttribute::READONLY ), 1138 rData.getIsDocument() ); 1139 xRow->appendBoolean( 1140 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ), 1141 -1, 1142 getCppuBooleanType(), 1143 beans::PropertyAttribute::BOUND 1144 | beans::PropertyAttribute::READONLY ), 1145 rData.getIsFolder() ); 1146 xRow->appendObject( 1147 beans::Property( 1148 rtl::OUString::createFromAscii( "CreatableContentsInfo" ), 1149 -1, 1150 getCppuType( static_cast< 1151 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), 1152 beans::PropertyAttribute::BOUND 1153 | beans::PropertyAttribute::READONLY ), 1154 uno::makeAny( rData.getCreatableContentsInfo() ) ); 1155 1156 // Storage is only supported by folders. 1157 if ( eType == FOLDER ) 1158 xRow->appendObject( 1159 beans::Property( rtl::OUString::createFromAscii( "Storage" ), 1160 -1, 1161 getCppuType( 1162 static_cast< 1163 const uno::Reference< embed::XStorage > * >( 0 ) ), 1164 beans::PropertyAttribute::BOUND 1165 | beans::PropertyAttribute::READONLY ), 1166 uno::makeAny( pProvider->queryStorageClone( rContentId ) ) ); 1167 1168 // DocumentModel is only supported by documents. 1169 if ( eType == DOCUMENT ) 1170 xRow->appendObject( 1171 beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ), 1172 -1, 1173 getCppuType( 1174 static_cast< 1175 const uno::Reference< frame::XModel > * >( 0 ) ), 1176 beans::PropertyAttribute::BOUND 1177 | beans::PropertyAttribute::READONLY ), 1178 uno::makeAny( 1179 pProvider->queryDocumentModel( rContentId ) ) ); 1180 1181 // Append all Additional Core Properties. 1182 1183 uno::Reference< beans::XPropertySet > xSet( 1184 pProvider->getAdditionalPropertySet( rContentId, sal_False ), 1185 uno::UNO_QUERY ); 1186 xRow->appendPropertySet( xSet ); 1187 } 1188 1189 return uno::Reference< sdbc::XRow >( xRow.get() ); 1190 } 1191 1192 //========================================================================= 1193 uno::Reference< sdbc::XRow > Content::getPropertyValues( 1194 const uno::Sequence< beans::Property >& rProperties ) 1195 { 1196 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1197 return getPropertyValues( m_xSMgr, 1198 rProperties, 1199 m_aProps, 1200 m_pProvider, 1201 m_xIdentifier->getContentIdentifier() ); 1202 } 1203 1204 //========================================================================= 1205 uno::Sequence< uno::Any > Content::setPropertyValues( 1206 const uno::Sequence< beans::PropertyValue >& rValues, 1207 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 1208 throw( uno::Exception ) 1209 { 1210 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1211 1212 uno::Sequence< uno::Any > aRet( rValues.getLength() ); 1213 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() ); 1214 sal_Int32 nChanged = 0; 1215 1216 beans::PropertyChangeEvent aEvent; 1217 aEvent.Source = static_cast< cppu::OWeakObject * >( this ); 1218 aEvent.Further = sal_False; 1219 // aEvent.PropertyName = 1220 aEvent.PropertyHandle = -1; 1221 // aEvent.OldValue = 1222 // aEvent.NewValue = 1223 1224 const beans::PropertyValue* pValues = rValues.getConstArray(); 1225 sal_Int32 nCount = rValues.getLength(); 1226 1227 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet; 1228 sal_Bool bTriedToGetAdditonalPropSet = sal_False; 1229 1230 sal_Bool bExchange = sal_False; 1231 rtl::OUString aOldTitle; 1232 sal_Int32 nTitlePos = -1; 1233 1234 for ( sal_Int32 n = 0; n < nCount; ++n ) 1235 { 1236 const beans::PropertyValue& rValue = pValues[ n ]; 1237 1238 if ( rValue.Name.equalsAsciiL( 1239 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ) 1240 { 1241 // Read-only property! 1242 aRet[ n ] <<= lang::IllegalAccessException( 1243 rtl::OUString::createFromAscii( 1244 "Property is read-only!" ), 1245 static_cast< cppu::OWeakObject * >( this ) ); 1246 } 1247 else if ( rValue.Name.equalsAsciiL( 1248 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) 1249 { 1250 // Read-only property! 1251 aRet[ n ] <<= lang::IllegalAccessException( 1252 rtl::OUString::createFromAscii( 1253 "Property is read-only!" ), 1254 static_cast< cppu::OWeakObject * >( this ) ); 1255 } 1256 else if ( rValue.Name.equalsAsciiL( 1257 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) 1258 { 1259 // Read-only property! 1260 aRet[ n ] <<= lang::IllegalAccessException( 1261 rtl::OUString::createFromAscii( 1262 "Property is read-only!" ), 1263 static_cast< cppu::OWeakObject * >( this ) ); 1264 } 1265 else if ( rValue.Name.equalsAsciiL( 1266 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) 1267 { 1268 // Read-only property! 1269 aRet[ n ] <<= lang::IllegalAccessException( 1270 rtl::OUString::createFromAscii( 1271 "Property is read-only!" ), 1272 static_cast< cppu::OWeakObject * >( this ) ); 1273 } 1274 else if ( rValue.Name.equalsAsciiL( 1275 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) 1276 { 1277 // Title is read-only for root and documents. 1278 ContentType eType = m_aProps.getType(); 1279 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 1280 { 1281 aRet[ n ] <<= lang::IllegalAccessException( 1282 rtl::OUString::createFromAscii( 1283 "Property is read-only!" ), 1284 static_cast< cppu::OWeakObject * >( this ) ); 1285 } 1286 else 1287 { 1288 rtl::OUString aNewValue; 1289 if ( rValue.Value >>= aNewValue ) 1290 { 1291 // No empty titles! 1292 if ( aNewValue.getLength() > 0 ) 1293 { 1294 if ( aNewValue != m_aProps.getTitle() ) 1295 { 1296 // modified title -> modified URL -> exchange ! 1297 if ( m_eState == PERSISTENT ) 1298 bExchange = sal_True; 1299 1300 aOldTitle = m_aProps.getTitle(); 1301 m_aProps.setTitle( aNewValue ); 1302 1303 // property change event will be sent later... 1304 1305 // remember position within sequence of values 1306 // (for error handling). 1307 nTitlePos = n; 1308 } 1309 } 1310 else 1311 { 1312 aRet[ n ] <<= lang::IllegalArgumentException( 1313 rtl::OUString::createFromAscii( 1314 "Empty Title not allowed!" ), 1315 static_cast< cppu::OWeakObject * >( this ), 1316 -1 ); 1317 } 1318 } 1319 else 1320 { 1321 aRet[ n ] <<= beans::IllegalTypeException( 1322 rtl::OUString::createFromAscii( 1323 "Title Property value has wrong type!" ), 1324 static_cast< cppu::OWeakObject * >( this ) ); 1325 } 1326 } 1327 } 1328 else if ( rValue.Name.equalsAsciiL( 1329 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) ) 1330 { 1331 ContentType eType = m_aProps.getType(); 1332 if ( eType == FOLDER ) 1333 { 1334 aRet[ n ] <<= lang::IllegalAccessException( 1335 rtl::OUString::createFromAscii( 1336 "Property is read-only!" ), 1337 static_cast< cppu::OWeakObject * >( this ) ); 1338 } 1339 else 1340 { 1341 // Storage is only supported by folders. 1342 aRet[ n ] <<= beans::UnknownPropertyException( 1343 rtl::OUString::createFromAscii( 1344 "Storage property only supported by folders" ), 1345 static_cast< cppu::OWeakObject * >( this ) ); 1346 } 1347 } 1348 else if ( rValue.Name.equalsAsciiL( 1349 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) ) 1350 { 1351 ContentType eType = m_aProps.getType(); 1352 if ( eType == DOCUMENT ) 1353 { 1354 aRet[ n ] <<= lang::IllegalAccessException( 1355 rtl::OUString::createFromAscii( 1356 "Property is read-only!" ), 1357 static_cast< cppu::OWeakObject * >( this ) ); 1358 } 1359 else 1360 { 1361 // Storage is only supported by folders. 1362 aRet[ n ] <<= beans::UnknownPropertyException( 1363 rtl::OUString::createFromAscii( 1364 "DocumentModel property only supported by " 1365 "documents" ), 1366 static_cast< cppu::OWeakObject * >( this ) ); 1367 } 1368 } 1369 else 1370 { 1371 // Not a Core Property! Maybe it's an Additional Core Property?! 1372 1373 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() ) 1374 { 1375 xAdditionalPropSet = getAdditionalPropertySet( sal_False ); 1376 bTriedToGetAdditonalPropSet = sal_True; 1377 } 1378 1379 if ( xAdditionalPropSet.is() ) 1380 { 1381 try 1382 { 1383 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue( 1384 rValue.Name ); 1385 if ( aOldValue != rValue.Value ) 1386 { 1387 xAdditionalPropSet->setPropertyValue( 1388 rValue.Name, rValue.Value ); 1389 1390 aEvent.PropertyName = rValue.Name; 1391 aEvent.OldValue = aOldValue; 1392 aEvent.NewValue = rValue.Value; 1393 1394 aChanges.getArray()[ nChanged ] = aEvent; 1395 nChanged++; 1396 } 1397 } 1398 catch ( beans::UnknownPropertyException const & e ) 1399 { 1400 aRet[ n ] <<= e; 1401 } 1402 catch ( lang::WrappedTargetException const & e ) 1403 { 1404 aRet[ n ] <<= e; 1405 } 1406 catch ( beans::PropertyVetoException const & e ) 1407 { 1408 aRet[ n ] <<= e; 1409 } 1410 catch ( lang::IllegalArgumentException const & e ) 1411 { 1412 aRet[ n ] <<= e; 1413 } 1414 } 1415 else 1416 { 1417 aRet[ n ] <<= uno::Exception( 1418 rtl::OUString::createFromAscii( 1419 "No property set for storing the value!" ), 1420 static_cast< cppu::OWeakObject * >( this ) ); 1421 } 1422 } 1423 } 1424 1425 if ( bExchange ) 1426 { 1427 uno::Reference< ucb::XContentIdentifier > xOldId 1428 = m_xIdentifier; 1429 uno::Reference< ucb::XContentIdentifier > xNewId 1430 = makeNewIdentifier( m_aProps.getTitle() ); 1431 1432 aGuard.clear(); 1433 if ( exchangeIdentity( xNewId ) ) 1434 { 1435 // Adapt persistent data. 1436 renameData( xOldId, xNewId ); 1437 1438 // Adapt Additional Core Properties. 1439 renameAdditionalPropertySet( xOldId->getContentIdentifier(), 1440 xNewId->getContentIdentifier(), 1441 sal_True ); 1442 } 1443 else 1444 { 1445 // Roll-back. 1446 m_aProps.setTitle( aOldTitle ); 1447 aOldTitle = rtl::OUString(); 1448 1449 // Set error . 1450 aRet[ nTitlePos ] <<= uno::Exception( 1451 rtl::OUString::createFromAscii( "Exchange failed!" ), 1452 static_cast< cppu::OWeakObject * >( this ) ); 1453 } 1454 } 1455 1456 if ( aOldTitle.getLength() ) 1457 { 1458 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" ); 1459 aEvent.OldValue = uno::makeAny( aOldTitle ); 1460 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() ); 1461 1462 aChanges.getArray()[ nChanged ] = aEvent; 1463 nChanged++; 1464 } 1465 1466 if ( nChanged > 0 ) 1467 { 1468 // Save changes, if content was already made persistent. 1469 if ( !bExchange && ( m_eState == PERSISTENT ) ) 1470 { 1471 if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) ) 1472 { 1473 uno::Any aProps 1474 = uno::makeAny( 1475 beans::PropertyValue( 1476 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1477 "Uri")), 1478 -1, 1479 uno::makeAny(m_xIdentifier-> 1480 getContentIdentifier()), 1481 beans::PropertyState_DIRECT_VALUE)); 1482 ucbhelper::cancelCommandExecution( 1483 ucb::IOErrorCode_CANT_WRITE, 1484 uno::Sequence< uno::Any >(&aProps, 1), 1485 xEnv, 1486 rtl::OUString::createFromAscii( 1487 "Cannot store persistent data!" ), 1488 this ); 1489 // Unreachable 1490 } 1491 } 1492 1493 aChanges.realloc( nChanged ); 1494 1495 aGuard.clear(); 1496 notifyPropertiesChange( aChanges ); 1497 } 1498 1499 return aRet; 1500 } 1501 1502 //========================================================================= 1503 uno::Any Content::open( 1504 const ucb::OpenCommandArgument2& rArg, 1505 const uno::Reference< ucb::XCommandEnvironment >& xEnv ) 1506 throw( uno::Exception ) 1507 { 1508 if ( rArg.Mode == ucb::OpenMode::ALL || 1509 rArg.Mode == ucb::OpenMode::FOLDERS || 1510 rArg.Mode == ucb::OpenMode::DOCUMENTS ) 1511 { 1512 ////////////////////////////////////////////////////////////////// 1513 // open command for a folder content 1514 ////////////////////////////////////////////////////////////////// 1515 1516 uno::Reference< ucb::XDynamicResultSet > xSet 1517 = new DynamicResultSet( m_xSMgr, this, rArg ); 1518 return uno::makeAny( xSet ); 1519 } 1520 else 1521 { 1522 ////////////////////////////////////////////////////////////////// 1523 // open command for a document content 1524 ////////////////////////////////////////////////////////////////// 1525 1526 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) || 1527 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) 1528 { 1529 // Currently(?) unsupported. 1530 ucbhelper::cancelCommandExecution( 1531 uno::makeAny( ucb::UnsupportedOpenModeException( 1532 rtl::OUString(), 1533 static_cast< cppu::OWeakObject * >( this ), 1534 sal_Int16( rArg.Mode ) ) ), 1535 xEnv ); 1536 // Unreachable 1537 } 1538 1539 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1540 1541 rtl::OUString aURL = m_xIdentifier->getContentIdentifier(); 1542 1543 uno::Reference< io::XActiveDataStreamer > xDataStreamer( 1544 rArg.Sink, uno::UNO_QUERY ); 1545 if ( xDataStreamer.is() ) 1546 { 1547 // May throw CommandFailedException, DocumentPasswordRequest! 1548 uno::Reference< io::XStream > xStream = getStream( xEnv ); 1549 if ( !xStream.is() ) 1550 { 1551 // No interaction if we are not persistent! 1552 uno::Any aProps 1553 = uno::makeAny( 1554 beans::PropertyValue( 1555 rtl::OUString( 1556 RTL_CONSTASCII_USTRINGPARAM("Uri")), 1557 -1, 1558 uno::makeAny(m_xIdentifier-> 1559 getContentIdentifier()), 1560 beans::PropertyState_DIRECT_VALUE)); 1561 ucbhelper::cancelCommandExecution( 1562 ucb::IOErrorCode_CANT_READ, 1563 uno::Sequence< uno::Any >(&aProps, 1), 1564 m_eState == PERSISTENT 1565 ? xEnv 1566 : uno::Reference< ucb::XCommandEnvironment >(), 1567 rtl::OUString::createFromAscii( 1568 "Got no data stream!" ), 1569 this ); 1570 // Unreachable 1571 } 1572 1573 // Done. 1574 xDataStreamer->setStream( xStream ); 1575 } 1576 else 1577 { 1578 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY ); 1579 if ( xOut.is() ) 1580 { 1581 // PUSH: write data into xOut 1582 1583 // May throw CommandFailedException, DocumentPasswordRequest! 1584 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); 1585 if ( !xIn.is() ) 1586 { 1587 // No interaction if we are not persistent! 1588 uno::Any aProps 1589 = uno::makeAny( 1590 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_READ, 1599 uno::Sequence< uno::Any >(&aProps, 1), 1600 m_eState == PERSISTENT 1601 ? xEnv 1602 : uno::Reference< ucb::XCommandEnvironment >(), 1603 rtl::OUString::createFromAscii( "Got no data stream!" ), 1604 this ); 1605 // Unreachable 1606 } 1607 1608 try 1609 { 1610 uno::Sequence< sal_Int8 > aBuffer; 1611 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 ); 1612 1613 while ( nRead > 0 ) 1614 { 1615 aBuffer.realloc( nRead ); 1616 xOut->writeBytes( aBuffer ); 1617 aBuffer.realloc( 0 ); 1618 nRead = xIn->readSomeBytes( aBuffer, 65536 ); 1619 } 1620 1621 xOut->closeOutput(); 1622 } 1623 catch ( io::NotConnectedException const & ) 1624 { 1625 // closeOutput, readSomeBytes, writeBytes 1626 } 1627 catch ( io::BufferSizeExceededException const & ) 1628 { 1629 // closeOutput, readSomeBytes, writeBytes 1630 } 1631 catch ( io::IOException const & ) 1632 { 1633 // closeOutput, readSomeBytes, writeBytes 1634 } 1635 } 1636 else 1637 { 1638 uno::Reference< io::XActiveDataSink > xDataSink( 1639 rArg.Sink, uno::UNO_QUERY ); 1640 if ( xDataSink.is() ) 1641 { 1642 // PULL: wait for client read 1643 1644 // May throw CommandFailedException, DocumentPasswordRequest! 1645 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv ); 1646 if ( !xIn.is() ) 1647 { 1648 // No interaction if we are not persistent! 1649 uno::Any aProps 1650 = uno::makeAny( 1651 beans::PropertyValue( 1652 rtl::OUString( 1653 RTL_CONSTASCII_USTRINGPARAM("Uri")), 1654 -1, 1655 uno::makeAny(m_xIdentifier-> 1656 getContentIdentifier()), 1657 beans::PropertyState_DIRECT_VALUE)); 1658 ucbhelper::cancelCommandExecution( 1659 ucb::IOErrorCode_CANT_READ, 1660 uno::Sequence< uno::Any >(&aProps, 1), 1661 m_eState == PERSISTENT 1662 ? xEnv 1663 : uno::Reference< 1664 ucb::XCommandEnvironment >(), 1665 rtl::OUString::createFromAscii( 1666 "Got no data stream!" ), 1667 this ); 1668 // Unreachable 1669 } 1670 1671 // Done. 1672 xDataSink->setInputStream( xIn ); 1673 } 1674 else 1675 { 1676 ucbhelper::cancelCommandExecution( 1677 uno::makeAny( 1678 ucb::UnsupportedDataSinkException( 1679 rtl::OUString(), 1680 static_cast< cppu::OWeakObject * >( this ), 1681 rArg.Sink ) ), 1682 xEnv ); 1683 // Unreachable 1684 } 1685 } 1686 } 1687 } 1688 1689 return uno::Any(); 1690 } 1691 1692 //========================================================================= 1693 void Content::insert( const uno::Reference< io::XInputStream >& xData, 1694 sal_Int32 nNameClashResolve, 1695 const uno::Reference< 1696 ucb::XCommandEnvironment > & xEnv ) 1697 throw( uno::Exception ) 1698 { 1699 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1700 1701 ContentType eType = m_aProps.getType(); 1702 1703 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), 1704 "insert command only supported by streams and folders!" ); 1705 1706 Uri aUri( m_xIdentifier->getContentIdentifier() ); 1707 1708 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 1709 #if OSL_DEBUG_LEVEL > 0 1710 if ( eType == STREAM ) 1711 { 1712 Uri aParentUri( aUri.getParentUri() ); 1713 OSL_ENSURE( !aParentUri.isDocument(), 1714 "insert command not supported by streams that are direct " 1715 "children of document root!" ); 1716 } 1717 #endif 1718 #endif 1719 1720 // Check, if all required properties were set. 1721 if ( eType == FOLDER ) 1722 { 1723 // Required: Title 1724 1725 if ( m_aProps.getTitle().getLength() == 0 ) 1726 m_aProps.setTitle( aUri.getDecodedName() ); 1727 } 1728 else // stream 1729 { 1730 // Required: data 1731 1732 if ( !xData.is() ) 1733 { 1734 ucbhelper::cancelCommandExecution( 1735 uno::makeAny( ucb::MissingInputStreamException( 1736 rtl::OUString(), 1737 static_cast< cppu::OWeakObject * >( this ) ) ), 1738 xEnv ); 1739 // Unreachable 1740 } 1741 1742 // Required: Title 1743 1744 if ( m_aProps.getTitle().getLength() == 0 ) 1745 m_aProps.setTitle( aUri.getDecodedName() ); 1746 } 1747 1748 rtl::OUStringBuffer aNewURL = aUri.getParentUri(); 1749 aNewURL.append( m_aProps.getTitle() ); 1750 Uri aNewUri( aNewURL.makeStringAndClear() ); 1751 1752 // Handle possible name clash... 1753 switch ( nNameClashResolve ) 1754 { 1755 // fail. 1756 case ucb::NameClash::ERROR: 1757 if ( hasData( aNewUri ) ) 1758 { 1759 ucbhelper::cancelCommandExecution( 1760 uno::makeAny( ucb::NameClashException( 1761 rtl::OUString(), 1762 static_cast< cppu::OWeakObject * >( this ), 1763 task::InteractionClassification_ERROR, 1764 m_aProps.getTitle() ) ), 1765 xEnv ); 1766 // Unreachable 1767 } 1768 break; 1769 1770 // replace (possibly) existing object. 1771 case ucb::NameClash::OVERWRITE: 1772 break; 1773 1774 // "invent" a new valid title. 1775 case ucb::NameClash::RENAME: 1776 if ( hasData( aNewUri ) ) 1777 { 1778 sal_Int32 nTry = 0; 1779 1780 do 1781 { 1782 rtl::OUStringBuffer aNew = aNewUri.getUri(); 1783 aNew.appendAscii( "_" ); 1784 aNew.append( rtl::OUString::valueOf( ++nTry ) ); 1785 aNewUri.setUri( aNew.makeStringAndClear() ); 1786 } 1787 while ( hasData( aNewUri ) && ( nTry < 1000 ) ); 1788 1789 if ( nTry == 1000 ) 1790 { 1791 ucbhelper::cancelCommandExecution( 1792 uno::makeAny( 1793 ucb::UnsupportedNameClashException( 1794 rtl::OUString::createFromAscii( 1795 "Unable to resolve name clash!" ), 1796 static_cast< cppu::OWeakObject * >( this ), 1797 nNameClashResolve ) ), 1798 xEnv ); 1799 // Unreachable 1800 } 1801 else 1802 { 1803 rtl::OUStringBuffer aNewTitle = m_aProps.getTitle(); 1804 aNewTitle.appendAscii( "_" ); 1805 aNewTitle.append( rtl::OUString::valueOf( ++nTry ) ); 1806 m_aProps.setTitle( aNewTitle.makeStringAndClear() ); 1807 } 1808 } 1809 break; 1810 1811 case ucb::NameClash::KEEP: // deprecated 1812 case ucb::NameClash::ASK: 1813 default: 1814 if ( hasData( aNewUri ) ) 1815 { 1816 ucbhelper::cancelCommandExecution( 1817 uno::makeAny( 1818 ucb::UnsupportedNameClashException( 1819 rtl::OUString(), 1820 static_cast< cppu::OWeakObject * >( this ), 1821 nNameClashResolve ) ), 1822 xEnv ); 1823 // Unreachable 1824 } 1825 break; 1826 } 1827 1828 // Identifier changed? 1829 sal_Bool bNewId = ( aUri != aNewUri ); 1830 1831 if ( bNewId ) 1832 { 1833 m_xIdentifier 1834 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() ); 1835 } 1836 1837 if ( !storeData( xData, xEnv ) ) 1838 { 1839 uno::Any aProps 1840 = uno::makeAny(beans::PropertyValue( 1841 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1842 "Uri")), 1843 -1, 1844 uno::makeAny(m_xIdentifier-> 1845 getContentIdentifier()), 1846 beans::PropertyState_DIRECT_VALUE)); 1847 ucbhelper::cancelCommandExecution( 1848 ucb::IOErrorCode_CANT_WRITE, 1849 uno::Sequence< uno::Any >(&aProps, 1), 1850 xEnv, 1851 rtl::OUString::createFromAscii( "Cannot store persistent data!" ), 1852 this ); 1853 // Unreachable 1854 } 1855 1856 m_eState = PERSISTENT; 1857 1858 if ( bNewId ) 1859 { 1860 //loadData( m_pProvider, m_aUri, m_aProps ); 1861 1862 aGuard.clear(); 1863 inserted(); 1864 } 1865 } 1866 1867 //========================================================================= 1868 void Content::destroy( sal_Bool bDeletePhysical, 1869 const uno::Reference< 1870 ucb::XCommandEnvironment > & xEnv ) 1871 throw( uno::Exception ) 1872 { 1873 // @@@ take care about bDeletePhysical -> trashcan support 1874 1875 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1876 1877 ContentType eType = m_aProps.getType(); 1878 1879 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ), 1880 "delete command only supported by streams and folders!" ); 1881 1882 uno::Reference< ucb::XContent > xThis = this; 1883 1884 // Persistent? 1885 if ( m_eState != PERSISTENT ) 1886 { 1887 ucbhelper::cancelCommandExecution( 1888 uno::makeAny( ucb::UnsupportedCommandException( 1889 rtl::OUString::createFromAscii( 1890 "Not persistent!" ), 1891 static_cast< cppu::OWeakObject * >( this ) ) ), 1892 xEnv ); 1893 // Unreachable 1894 } 1895 1896 m_eState = DEAD; 1897 1898 aGuard.clear(); 1899 deleted(); 1900 1901 if ( eType == FOLDER ) 1902 { 1903 // Process instanciated children... 1904 1905 ContentRefList aChildren; 1906 queryChildren( aChildren ); 1907 1908 ContentRefList::const_iterator it = aChildren.begin(); 1909 ContentRefList::const_iterator end = aChildren.end(); 1910 1911 while ( it != end ) 1912 { 1913 (*it)->destroy( bDeletePhysical, xEnv ); 1914 ++it; 1915 } 1916 } 1917 } 1918 1919 //========================================================================= 1920 void Content::notifyDocumentClosed() 1921 { 1922 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1923 1924 m_eState = DEAD; 1925 1926 // @@@ anything else to reset or such? 1927 1928 // callback follows! 1929 aGuard.clear(); 1930 1931 // Propagate destruction to content event listeners 1932 // Remove this from provider's content list. 1933 deleted(); 1934 } 1935 1936 //========================================================================= 1937 uno::Reference< ucb::XContent > 1938 Content::queryChildContent( const rtl::OUString & rRelativeChildUri ) 1939 { 1940 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 1941 1942 const rtl::OUString aMyId = getIdentifier()->getContentIdentifier(); 1943 rtl::OUStringBuffer aBuf( aMyId ); 1944 if ( aMyId.getStr()[ aMyId.getLength() - 1 ] != sal_Unicode( '/' ) ) 1945 aBuf.appendAscii( "/" ); 1946 if ( rRelativeChildUri.getStr()[ 0 ] != sal_Unicode( '/' ) ) 1947 aBuf.append( rRelativeChildUri ); 1948 else 1949 aBuf.append( rRelativeChildUri.copy( 1 ) ); 1950 1951 uno::Reference< ucb::XContentIdentifier > xChildId 1952 = new ::ucbhelper::ContentIdentifier( 1953 m_xSMgr, aBuf.makeStringAndClear() ); 1954 1955 uno::Reference< ucb::XContent > xChild; 1956 try 1957 { 1958 xChild = m_pProvider->queryContent( xChildId ); 1959 } 1960 catch ( ucb::IllegalIdentifierException const & ) 1961 { 1962 // handled below. 1963 } 1964 1965 OSL_ENSURE( xChild.is(), 1966 "Content::queryChildContent - unable to create child content!" ); 1967 return xChild; 1968 } 1969 1970 //========================================================================= 1971 void Content::notifyChildRemoved( const rtl::OUString & rRelativeChildUri ) 1972 { 1973 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1974 1975 // Ugly! Need to create child content object, just to fill event properly. 1976 uno::Reference< ucb::XContent > xChild 1977 = queryChildContent( rRelativeChildUri ); 1978 1979 if ( xChild.is() ) 1980 { 1981 // callback follows! 1982 aGuard.clear(); 1983 1984 // Notify "REMOVED" event. 1985 ucb::ContentEvent aEvt( 1986 static_cast< cppu::OWeakObject * >( this ), 1987 ucb::ContentAction::REMOVED, 1988 xChild, 1989 getIdentifier() ); 1990 notifyContentEvent( aEvt ); 1991 } 1992 } 1993 1994 //========================================================================= 1995 void Content::notifyChildInserted( const rtl::OUString & rRelativeChildUri ) 1996 { 1997 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 1998 1999 // Ugly! Need to create child content object, just to fill event properly. 2000 uno::Reference< ucb::XContent > xChild 2001 = queryChildContent( rRelativeChildUri ); 2002 2003 if ( xChild.is() ) 2004 { 2005 // callback follows! 2006 aGuard.clear(); 2007 2008 // Notify "INSERTED" event. 2009 ucb::ContentEvent aEvt( 2010 static_cast< cppu::OWeakObject * >( this ), 2011 ucb::ContentAction::INSERTED, 2012 xChild, 2013 getIdentifier() ); 2014 notifyContentEvent( aEvt ); 2015 } 2016 } 2017 2018 //========================================================================= 2019 void Content::transfer( 2020 const ucb::TransferInfo& rInfo, 2021 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2022 throw( uno::Exception ) 2023 { 2024 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 2025 2026 // Persistent? 2027 if ( m_eState != PERSISTENT ) 2028 { 2029 ucbhelper::cancelCommandExecution( 2030 uno::makeAny( ucb::UnsupportedCommandException( 2031 rtl::OUString::createFromAscii( 2032 "Not persistent!" ), 2033 static_cast< cppu::OWeakObject * >( this ) ) ), 2034 xEnv ); 2035 // Unreachable 2036 } 2037 2038 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported. 2039 2040 if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) ) 2041 { 2042 // Invaild length (to short). 2043 ucbhelper::cancelCommandExecution( 2044 uno::makeAny( ucb::InteractiveBadTransferURLException( 2045 rtl::OUString(), 2046 static_cast< cppu::OWeakObject * >( this ) ) ), 2047 xEnv ); 2048 // Unreachable 2049 } 2050 2051 rtl::OUString aScheme 2052 = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 ) 2053 .toAsciiLowerCase(); 2054 if ( !aScheme.equalsAsciiL( 2055 RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ":/" ) ) ) 2056 { 2057 // Invalid scheme. 2058 ucbhelper::cancelCommandExecution( 2059 uno::makeAny( ucb::InteractiveBadTransferURLException( 2060 rtl::OUString(), 2061 static_cast< cppu::OWeakObject * >( this ) ) ), 2062 xEnv ); 2063 // Unreachable 2064 } 2065 2066 // Does source URI describe a tdoc folder or stream? 2067 Uri aSourceUri( rInfo.SourceURL ); 2068 if ( !aSourceUri.isValid() ) 2069 { 2070 ucbhelper::cancelCommandExecution( 2071 uno::makeAny( lang::IllegalArgumentException( 2072 rtl::OUString::createFromAscii( 2073 "Invalid source URI! Syntax!" ), 2074 static_cast< cppu::OWeakObject * >( this ), 2075 -1 ) ), 2076 xEnv ); 2077 // Unreachable 2078 } 2079 2080 if ( aSourceUri.isRoot() || aSourceUri.isDocument() ) 2081 { 2082 ucbhelper::cancelCommandExecution( 2083 uno::makeAny( lang::IllegalArgumentException( 2084 rtl::OUString::createFromAscii( 2085 "Invalid source URI! " 2086 "Must describe a folder or stream!" ), 2087 static_cast< cppu::OWeakObject * >( this ), 2088 -1 ) ), 2089 xEnv ); 2090 // Unreachable 2091 } 2092 2093 // Is source not a parent of me / not me? 2094 rtl::OUString aId = m_xIdentifier->getContentIdentifier(); 2095 sal_Int32 nPos = aId.lastIndexOf( '/' ); 2096 if ( nPos != ( aId.getLength() - 1 ) ) 2097 { 2098 // No trailing slash found. Append. 2099 aId += rtl::OUString::createFromAscii( "/" ); 2100 } 2101 2102 if ( rInfo.SourceURL.getLength() <= aId.getLength() ) 2103 { 2104 if ( aId.compareTo( 2105 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 ) 2106 { 2107 uno::Any aProps 2108 = uno::makeAny(beans::PropertyValue( 2109 rtl::OUString( 2110 RTL_CONSTASCII_USTRINGPARAM("Uri")), 2111 -1, 2112 uno::makeAny( rInfo.SourceURL ), 2113 beans::PropertyState_DIRECT_VALUE)); 2114 ucbhelper::cancelCommandExecution( 2115 ucb::IOErrorCode_RECURSIVE, 2116 uno::Sequence< uno::Any >(&aProps, 1), 2117 xEnv, 2118 rtl::OUString::createFromAscii( 2119 "Target is equal to or is a child of source!" ), 2120 this ); 2121 // Unreachable 2122 } 2123 } 2124 2125 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 2126 if ( m_aProps.getType() == DOCUMENT ) 2127 { 2128 bool bOK = false; 2129 2130 uno::Reference< embed::XStorage > xStorage 2131 = m_pProvider->queryStorage( 2132 aSourceUri.getParentUri(), READ_WRITE_NOCREATE ); 2133 if ( xStorage.is() ) 2134 { 2135 try 2136 { 2137 if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) ) 2138 { 2139 ucbhelper::cancelCommandExecution( 2140 uno::makeAny( lang::IllegalArgumentException( 2141 rtl::OUString::createFromAscii( 2142 "Invalid source URI! " 2143 "Streams cannot be created as " 2144 "children of document root!" ), 2145 static_cast< cppu::OWeakObject * >( 2146 this ), 2147 -1 ) ), 2148 xEnv ); 2149 // Unreachable 2150 } 2151 bOK = true; 2152 } 2153 catch ( container::NoSuchElementException const & ) 2154 { 2155 // handled below. 2156 } 2157 catch ( lang::IllegalArgumentException const & ) 2158 { 2159 // handled below. 2160 } 2161 catch ( embed::InvalidStorageException const & ) 2162 { 2163 // handled below. 2164 } 2165 } 2166 2167 if ( !bOK ) 2168 { 2169 ucbhelper::cancelCommandExecution( 2170 uno::makeAny( lang::IllegalArgumentException( 2171 rtl::OUString::createFromAscii( 2172 "Invalid source URI! " 2173 "Unabale to determine source type!" ), 2174 static_cast< cppu::OWeakObject * >( this ), 2175 -1 ) ), 2176 xEnv ); 2177 // Unreachable 2178 } 2179 } 2180 #endif 2181 2182 ///////////////////////////////////////////////////////////////////////// 2183 // Copy data. 2184 ///////////////////////////////////////////////////////////////////////// 2185 2186 rtl::OUString aNewName( rInfo.NewTitle.getLength() > 0 2187 ? rInfo.NewTitle 2188 : aSourceUri.getDecodedName() ); 2189 2190 if ( !copyData( aSourceUri, aNewName ) ) 2191 { 2192 uno::Any aProps 2193 = uno::makeAny( 2194 beans::PropertyValue( 2195 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2196 "Uri")), 2197 -1, 2198 uno::makeAny( rInfo.SourceURL ), 2199 beans::PropertyState_DIRECT_VALUE)); 2200 ucbhelper::cancelCommandExecution( 2201 ucb::IOErrorCode_CANT_WRITE, 2202 uno::Sequence< uno::Any >(&aProps, 1), 2203 xEnv, 2204 rtl::OUString( 2205 RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ), 2206 this ); 2207 // Unreachable 2208 } 2209 2210 ///////////////////////////////////////////////////////////////////////// 2211 // Copy own and all children's Additional Core Properties. 2212 ///////////////////////////////////////////////////////////////////////// 2213 2214 rtl::OUString aTargetUri = m_xIdentifier->getContentIdentifier(); 2215 if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() ) 2216 aTargetUri += rtl::OUString::createFromAscii( "/" ); 2217 2218 if ( rInfo.NewTitle.getLength() > 0 ) 2219 aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle ); 2220 else 2221 aTargetUri += aSourceUri.getName(); 2222 2223 if ( !copyAdditionalPropertySet( 2224 aSourceUri.getUri(), aTargetUri, sal_True ) ) 2225 { 2226 uno::Any aProps 2227 = uno::makeAny( 2228 beans::PropertyValue( 2229 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2230 "Uri")), 2231 -1, 2232 uno::makeAny( rInfo.SourceURL ), 2233 beans::PropertyState_DIRECT_VALUE)); 2234 ucbhelper::cancelCommandExecution( 2235 ucb::IOErrorCode_CANT_WRITE, 2236 uno::Sequence< uno::Any >(&aProps, 1), 2237 xEnv, 2238 rtl::OUString( 2239 RTL_CONSTASCII_USTRINGPARAM( 2240 "Cannot copy additional properties!" ) ), 2241 this ); 2242 // Unreachable 2243 } 2244 2245 ///////////////////////////////////////////////////////////////////////// 2246 // Propagate new content. 2247 ///////////////////////////////////////////////////////////////////////// 2248 2249 rtl::Reference< Content > xTarget; 2250 try 2251 { 2252 uno::Reference< ucb::XContentIdentifier > xTargetId 2253 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aTargetUri ); 2254 2255 // Note: The static cast is okay here, because its sure that 2256 // m_xProvider is always the WebDAVContentProvider. 2257 xTarget = static_cast< Content * >( 2258 m_pProvider->queryContent( xTargetId ).get() ); 2259 2260 } 2261 catch ( ucb::IllegalIdentifierException const & ) 2262 { 2263 // queryContent 2264 } 2265 2266 if ( !xTarget.is() ) 2267 { 2268 uno::Any aProps 2269 = uno::makeAny(beans::PropertyValue( 2270 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2271 "Uri")), 2272 -1, 2273 uno::makeAny( aTargetUri ), 2274 beans::PropertyState_DIRECT_VALUE)); 2275 ucbhelper::cancelCommandExecution( 2276 ucb::IOErrorCode_CANT_READ, 2277 uno::Sequence< uno::Any >(&aProps, 1), 2278 xEnv, 2279 rtl::OUString::createFromAscii( 2280 "Cannot instanciate target object!" ), 2281 this ); 2282 // Unreachable 2283 } 2284 2285 // Announce transfered content in its new folder. 2286 xTarget->inserted(); 2287 2288 ///////////////////////////////////////////////////////////////////////// 2289 // Remove source, if requested 2290 ///////////////////////////////////////////////////////////////////////// 2291 2292 if ( rInfo.MoveData ) 2293 { 2294 rtl::Reference< Content > xSource; 2295 try 2296 { 2297 uno::Reference< ucb::XContentIdentifier > 2298 xSourceId = new ::ucbhelper::ContentIdentifier( 2299 m_xSMgr, rInfo.SourceURL ); 2300 2301 // Note: The static cast is okay here, because its sure 2302 // that m_xProvider is always the ContentProvider. 2303 xSource = static_cast< Content * >( 2304 m_xProvider->queryContent( xSourceId ).get() ); 2305 } 2306 catch ( ucb::IllegalIdentifierException const & ) 2307 { 2308 // queryContent 2309 } 2310 2311 if ( !xSource.is() ) 2312 { 2313 uno::Any aProps 2314 = uno::makeAny(beans::PropertyValue( 2315 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2316 "Uri")), 2317 -1, 2318 uno::makeAny( rInfo.SourceURL ), 2319 beans::PropertyState_DIRECT_VALUE)); 2320 ucbhelper::cancelCommandExecution( 2321 ucb::IOErrorCode_CANT_READ, 2322 uno::Sequence< uno::Any >(&aProps, 1), 2323 xEnv, 2324 rtl::OUString::createFromAscii( 2325 "Cannot instanciate target object!" ), 2326 this ); 2327 // Unreachable 2328 } 2329 2330 // Propagate destruction (recursively). 2331 xSource->destroy( sal_True, xEnv ); 2332 2333 // Remove all persistent data of source and its children. 2334 if ( !xSource->removeData() ) 2335 { 2336 uno::Any aProps 2337 = uno::makeAny( 2338 beans::PropertyValue( 2339 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2340 "Uri")), 2341 -1, 2342 uno::makeAny( rInfo.SourceURL ), 2343 beans::PropertyState_DIRECT_VALUE)); 2344 ucbhelper::cancelCommandExecution( 2345 ucb::IOErrorCode_CANT_WRITE, 2346 uno::Sequence< uno::Any >(&aProps, 1), 2347 xEnv, 2348 rtl::OUString::createFromAscii( 2349 "Cannot remove persistent data of source object!" ), 2350 this ); 2351 // Unreachable 2352 } 2353 2354 // Remove own and all children's Additional Core Properties. 2355 if ( !xSource->removeAdditionalPropertySet( sal_True ) ) 2356 { 2357 uno::Any aProps 2358 = uno::makeAny( 2359 beans::PropertyValue( 2360 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2361 "Uri")), 2362 -1, 2363 uno::makeAny( rInfo.SourceURL ), 2364 beans::PropertyState_DIRECT_VALUE)); 2365 ucbhelper::cancelCommandExecution( 2366 ucb::IOErrorCode_CANT_WRITE, 2367 uno::Sequence< uno::Any >(&aProps, 1), 2368 xEnv, 2369 rtl::OUString::createFromAscii( 2370 "Cannot remove additional properties of source object!" ), 2371 this ); 2372 // Unreachable 2373 } 2374 2375 } // rInfo.MoveData 2376 } 2377 2378 //========================================================================= 2379 //static 2380 bool Content::hasData( ContentProvider* pProvider, const Uri & rUri ) 2381 { 2382 if ( rUri.isRoot() ) 2383 { 2384 return true; // root has no storage 2385 } 2386 else if ( rUri.isDocument() ) 2387 { 2388 uno::Reference< embed::XStorage > xStorage 2389 = pProvider->queryStorage( rUri.getUri(), READ ); 2390 return xStorage.is(); 2391 } 2392 else 2393 { 2394 // folder or stream 2395 2396 // Ask parent storage. In case that rUri describes a stream, 2397 // ContentProvider::queryStorage( rUri ) would return null. 2398 2399 uno::Reference< embed::XStorage > xStorage 2400 = pProvider->queryStorage( rUri.getParentUri(), READ ); 2401 2402 if ( !xStorage.is() ) 2403 return false; 2404 2405 uno::Reference< container::XNameAccess > xParentNA( 2406 xStorage, uno::UNO_QUERY ); 2407 2408 OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" ); 2409 2410 return xParentNA->hasByName( rUri.getDecodedName() ); 2411 } 2412 } 2413 2414 //========================================================================= 2415 //static 2416 bool Content::loadData( ContentProvider* pProvider, 2417 const Uri & rUri, 2418 ContentProperties& rProps ) 2419 { 2420 if ( rUri.isRoot() ) // root has no storage, but can always be created 2421 { 2422 rProps 2423 = ContentProperties( 2424 ROOT, pProvider->queryStorageTitle( rUri.getUri() ) ); 2425 } 2426 else if ( rUri.isDocument() ) // document must have storage 2427 { 2428 uno::Reference< embed::XStorage > xStorage 2429 = pProvider->queryStorage( rUri.getUri(), READ ); 2430 2431 if ( !xStorage.is() ) 2432 return false; 2433 2434 rProps 2435 = ContentProperties( 2436 DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) ); 2437 } 2438 else // stream or folder; stream has no storage; folder has storage 2439 { 2440 uno::Reference< embed::XStorage > xStorage 2441 = pProvider->queryStorage( rUri.getParentUri(), READ ); 2442 2443 if ( !xStorage.is() ) 2444 return false; 2445 2446 // Check whether exists at all, is stream or folder 2447 try 2448 { 2449 // return: true -> folder 2450 // return: false -> stream 2451 // NoSuchElementException -> neither folder nor stream 2452 bool bIsFolder 2453 = xStorage->isStorageElement( rUri.getDecodedName() ); 2454 2455 rProps 2456 = ContentProperties( 2457 bIsFolder ? FOLDER : STREAM, 2458 pProvider->queryStorageTitle( rUri.getUri() ) ); 2459 } 2460 catch ( container::NoSuchElementException const & ) 2461 { 2462 // there is no element with such name 2463 //OSL_ENSURE( false, "Caught NoSuchElementException!" ); 2464 return false; 2465 } 2466 catch ( lang::IllegalArgumentException const & ) 2467 { 2468 // an illegal argument is provided 2469 OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 2470 return false; 2471 } 2472 catch ( embed::InvalidStorageException const & ) 2473 { 2474 // this storage is in invalid state for any reason 2475 OSL_ENSURE( false, "Caught InvalidStorageException!" ); 2476 return false; 2477 } 2478 } 2479 return true; 2480 } 2481 2482 //========================================================================= 2483 bool Content::storeData( const uno::Reference< io::XInputStream >& xData, 2484 const uno::Reference< 2485 ucb::XCommandEnvironment >& xEnv ) 2486 throw ( ucb::CommandFailedException, 2487 task::DocumentPasswordRequest ) 2488 { 2489 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2490 2491 ContentType eType = m_aProps.getType(); 2492 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 2493 { 2494 OSL_ENSURE( false, "storeData not supported by root and documents!" ); 2495 return false; 2496 } 2497 2498 Uri aUri( m_xIdentifier->getContentIdentifier() ); 2499 2500 if ( eType == FOLDER ) 2501 { 2502 uno::Reference< embed::XStorage > xStorage 2503 = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE ); 2504 2505 if ( !xStorage.is() ) 2506 return false; 2507 2508 uno::Reference< beans::XPropertySet > xPropSet( 2509 xStorage, uno::UNO_QUERY ); 2510 OSL_ENSURE( xPropSet.is(), 2511 "Content::storeData - Got no XPropertySet interface!" ); 2512 if ( !xPropSet.is() ) 2513 return false; 2514 2515 try 2516 { 2517 // According to MBA, if no mediatype is set, folder and all 2518 // its contents will be lost on save of the document!!! 2519 xPropSet->setPropertyValue( 2520 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), 2521 uno::makeAny( 2522 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 2523 // @@@ better mediatype 2524 "application/binary" ) ) ) ); 2525 } 2526 catch ( beans::UnknownPropertyException const & ) 2527 { 2528 OSL_ENSURE( false, "Property MediaType not supported!" ); 2529 return false; 2530 } 2531 catch ( beans::PropertyVetoException const & ) 2532 { 2533 OSL_ENSURE( false, "Caught PropertyVetoException!" ); 2534 return false; 2535 } 2536 catch ( lang::IllegalArgumentException const & ) 2537 { 2538 OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 2539 return false; 2540 } 2541 catch ( lang::WrappedTargetException const & ) 2542 { 2543 OSL_ENSURE( false, "Caught WrappedTargetException!" ); 2544 return false; 2545 } 2546 2547 if ( !commitStorage( xStorage ) ) 2548 return false; 2549 } 2550 else if ( eType == STREAM ) 2551 { 2552 // stream 2553 2554 // Important: Parent storage and output stream must be kept alive until 2555 // changes have been committed! 2556 uno::Reference< embed::XStorage > xStorage 2557 = m_pProvider->queryStorage( 2558 aUri.getParentUri(), READ_WRITE_CREATE ); 2559 uno::Reference< io::XOutputStream > xOut; 2560 2561 if ( !xStorage.is() ) 2562 return false; 2563 2564 if ( xData.is() ) 2565 { 2566 // May throw CommandFailedException, DocumentPasswordRequest! 2567 xOut = getTruncatedOutputStream( xEnv ); 2568 2569 OSL_ENSURE( xOut.is(), "No target data stream!" ); 2570 2571 try 2572 { 2573 uno::Sequence< sal_Int8 > aBuffer; 2574 sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 ); 2575 2576 while ( nRead > 0 ) 2577 { 2578 aBuffer.realloc( nRead ); 2579 xOut->writeBytes( aBuffer ); 2580 aBuffer.realloc( 0 ); 2581 nRead = xData->readSomeBytes( aBuffer, 65536 ); 2582 } 2583 2584 closeOutputStream( xOut ); 2585 } 2586 catch ( io::NotConnectedException const & ) 2587 { 2588 // readSomeBytes, writeBytes 2589 OSL_ENSURE( false, "Caught NotConnectedException!" ); 2590 closeOutputStream( xOut ); 2591 return false; 2592 } 2593 catch ( io::BufferSizeExceededException const & ) 2594 { 2595 // readSomeBytes, writeBytes 2596 OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); 2597 closeOutputStream( xOut ); 2598 return false; 2599 } 2600 catch ( io::IOException const & ) 2601 { 2602 // readSomeBytes, writeBytes 2603 OSL_ENSURE( false, "Caught IOException!" ); 2604 closeOutputStream( xOut ); 2605 return false; 2606 } 2607 catch ( ... ) 2608 { 2609 closeOutputStream( xOut ); 2610 throw; 2611 } 2612 } 2613 2614 // Commit changes. 2615 if ( !commitStorage( xStorage ) ) 2616 return false; 2617 } 2618 else 2619 { 2620 OSL_ENSURE( false, "Unknown content type!" ); 2621 return false; 2622 } 2623 return true; 2624 } 2625 2626 //========================================================================= 2627 bool Content::renameData( 2628 const uno::Reference< ucb::XContentIdentifier >& xOldId, 2629 const uno::Reference< ucb::XContentIdentifier >& xNewId ) 2630 { 2631 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2632 2633 ContentType eType = m_aProps.getType(); 2634 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 2635 { 2636 OSL_ENSURE( false, "renameData not supported by root and documents!" ); 2637 return false; 2638 } 2639 2640 Uri aOldUri( xOldId->getContentIdentifier() ); 2641 uno::Reference< embed::XStorage > xStorage 2642 = m_pProvider->queryStorage( 2643 aOldUri.getParentUri(), READ_WRITE_NOCREATE ); 2644 2645 if ( !xStorage.is() ) 2646 return false; 2647 2648 try 2649 { 2650 Uri aNewUri( xNewId->getContentIdentifier() ); 2651 xStorage->renameElement( 2652 aOldUri.getDecodedName(), aNewUri.getDecodedName() ); 2653 } 2654 catch ( embed::InvalidStorageException const & ) 2655 { 2656 // this storage is in invalid state for eny reason 2657 OSL_ENSURE( false, "Caught InvalidStorageException!" ); 2658 return false; 2659 } 2660 catch ( lang::IllegalArgumentException const & ) 2661 { 2662 // an illegal argument is provided 2663 OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 2664 return false; 2665 } 2666 catch ( container::NoSuchElementException const & ) 2667 { 2668 // there is no element with old name in this storage 2669 OSL_ENSURE( false, "Caught NoSuchElementException!" ); 2670 return false; 2671 } 2672 catch ( container::ElementExistException const & ) 2673 { 2674 // an element with new name already exists in this storage 2675 OSL_ENSURE( false, "Caught ElementExistException!" ); 2676 return false; 2677 } 2678 catch ( io::IOException const & ) 2679 { 2680 // in case of io errors during renaming 2681 OSL_ENSURE( false, "Caught IOException!" ); 2682 return false; 2683 } 2684 catch ( embed::StorageWrappedTargetException const & ) 2685 { 2686 // wraps other exceptions 2687 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); 2688 return false; 2689 } 2690 2691 return commitStorage( xStorage ); 2692 } 2693 2694 //========================================================================= 2695 bool Content::removeData() 2696 { 2697 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2698 2699 ContentType eType = m_aProps.getType(); 2700 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) ) 2701 { 2702 OSL_ENSURE( false, "removeData not supported by root and documents!" ); 2703 return false; 2704 } 2705 2706 Uri aUri( m_xIdentifier->getContentIdentifier() ); 2707 uno::Reference< embed::XStorage > xStorage 2708 = m_pProvider->queryStorage( 2709 aUri.getParentUri(), READ_WRITE_NOCREATE ); 2710 2711 if ( !xStorage.is() ) 2712 return false; 2713 2714 try 2715 { 2716 xStorage->removeElement( aUri.getDecodedName() ); 2717 } 2718 catch ( embed::InvalidStorageException const & ) 2719 { 2720 // this storage is in invalid state for eny reason 2721 OSL_ENSURE( false, "Caught InvalidStorageException!" ); 2722 return false; 2723 } 2724 catch ( lang::IllegalArgumentException const & ) 2725 { 2726 // an illegal argument is provided 2727 OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 2728 return false; 2729 } 2730 catch ( container::NoSuchElementException const & ) 2731 { 2732 // there is no element with this name in this storage 2733 OSL_ENSURE( false, "Caught NoSuchElementException!" ); 2734 return false; 2735 } 2736 catch ( io::IOException const & ) 2737 { 2738 // in case of io errors during renaming 2739 OSL_ENSURE( false, "Caught IOException!" ); 2740 return false; 2741 } 2742 catch ( embed::StorageWrappedTargetException const & ) 2743 { 2744 // wraps other exceptions 2745 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); 2746 return false; 2747 } 2748 2749 return commitStorage( xStorage ); 2750 } 2751 2752 //========================================================================= 2753 bool Content::copyData( const Uri & rSourceUri, const rtl::OUString & rNewName ) 2754 { 2755 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2756 2757 ContentType eType = m_aProps.getType(); 2758 if ( ( eType == ROOT ) || ( eType == STREAM ) ) 2759 { 2760 OSL_ENSURE( false, "copyData not supported by root and streams!" ); 2761 return false; 2762 } 2763 2764 Uri aDestUri( m_xIdentifier->getContentIdentifier() ); 2765 uno::Reference< embed::XStorage > xDestStorage 2766 = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE ); 2767 2768 if ( !xDestStorage.is() ) 2769 return false; 2770 2771 uno::Reference< embed::XStorage > xSourceStorage 2772 = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ ); 2773 2774 if ( !xSourceStorage.is() ) 2775 return false; 2776 2777 try 2778 { 2779 xSourceStorage->copyElementTo( rSourceUri.getDecodedName(), 2780 xDestStorage, 2781 rNewName ); 2782 } 2783 catch ( embed::InvalidStorageException const & ) 2784 { 2785 // this storage is in invalid state for eny reason 2786 OSL_ENSURE( false, "Caught InvalidStorageException!" ); 2787 return false; 2788 } 2789 catch ( lang::IllegalArgumentException const & ) 2790 { 2791 // an illegal argument is provided 2792 OSL_ENSURE( false, "Caught IllegalArgumentException!" ); 2793 return false; 2794 } 2795 catch ( container::NoSuchElementException const & ) 2796 { 2797 // there is no element with this name in this storage 2798 OSL_ENSURE( false, "Caught NoSuchElementException!" ); 2799 return false; 2800 } 2801 catch ( container::ElementExistException const & ) 2802 { 2803 // there is no element with this name in this storage 2804 OSL_ENSURE( false, "Caught ElementExistException!" ); 2805 return false; 2806 } 2807 catch ( io::IOException const & ) 2808 { 2809 // in case of io errors during renaming 2810 OSL_ENSURE( false, "Caught IOException!" ); 2811 return false; 2812 } 2813 catch ( embed::StorageWrappedTargetException const & ) 2814 { 2815 // wraps other exceptions 2816 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" ); 2817 return false; 2818 } 2819 2820 return commitStorage( xDestStorage ); 2821 } 2822 2823 //========================================================================= 2824 // static 2825 bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage ) 2826 { 2827 // Commit changes 2828 uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY ); 2829 2830 OSL_ENSURE( xTO.is(), 2831 "Required interface css.embed.XTransactedObject missing!" ); 2832 try 2833 { 2834 xTO->commit(); 2835 } 2836 catch ( io::IOException const & ) 2837 { 2838 OSL_ENSURE( false, "Caught IOException!" ); 2839 return false; 2840 } 2841 catch ( lang::WrappedTargetException const & ) 2842 { 2843 OSL_ENSURE( false, "Caught WrappedTargetException!" ); 2844 return false; 2845 } 2846 2847 return true; 2848 } 2849 2850 //========================================================================= 2851 // static 2852 bool Content::closeOutputStream( 2853 const uno::Reference< io::XOutputStream > & xOut ) 2854 { 2855 if ( xOut.is() ) 2856 { 2857 try 2858 { 2859 xOut->closeOutput(); 2860 return true; 2861 } 2862 catch ( io::NotConnectedException const & ) 2863 { 2864 OSL_ENSURE( false, "Caught NotConnectedException!" ); 2865 } 2866 catch ( io::BufferSizeExceededException const & ) 2867 { 2868 OSL_ENSURE( false, "Caught BufferSizeExceededException!" ); 2869 } 2870 catch ( io::IOException const & ) 2871 { 2872 OSL_ENSURE( false, "Caught IOException!" ); 2873 } 2874 } 2875 return false; 2876 } 2877 2878 //========================================================================= 2879 static rtl::OUString obtainPassword( 2880 const rtl::OUString & rName, 2881 task::PasswordRequestMode eMode, 2882 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2883 throw ( ucb::CommandFailedException, 2884 task::DocumentPasswordRequest ) 2885 { 2886 rtl::Reference< DocumentPasswordRequest > xRequest 2887 = new DocumentPasswordRequest( eMode, rName ); 2888 2889 if ( xEnv.is() ) 2890 { 2891 uno::Reference< task::XInteractionHandler > xIH 2892 = xEnv->getInteractionHandler(); 2893 if ( xIH.is() ) 2894 { 2895 xIH->handle( xRequest.get() ); 2896 2897 rtl::Reference< ucbhelper::InteractionContinuation > xSelection 2898 = xRequest->getSelection(); 2899 2900 if ( xSelection.is() ) 2901 { 2902 // Handler handled the request. 2903 uno::Reference< task::XInteractionAbort > xAbort( 2904 xSelection.get(), uno::UNO_QUERY ); 2905 if ( xAbort.is() ) 2906 { 2907 throw ucb::CommandFailedException( 2908 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 2909 "Abort requested by Interaction Handler." ) ), 2910 uno::Reference< uno::XInterface >(), 2911 xRequest->getRequest() ); 2912 } 2913 2914 uno::Reference< task::XInteractionPassword > xPassword( 2915 xSelection.get(), uno::UNO_QUERY ); 2916 if ( xPassword.is() ) 2917 { 2918 return xPassword->getPassword(); 2919 } 2920 2921 // Unknown selection. Should never happen. 2922 throw ucb::CommandFailedException( 2923 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( 2924 "Interaction Handler selected unknown continuation!" ) ), 2925 uno::Reference< uno::XInterface >(), 2926 xRequest->getRequest() ); 2927 } 2928 } 2929 } 2930 2931 // No IH or IH did not handle exception. 2932 task::DocumentPasswordRequest aRequest; 2933 xRequest->getRequest() >>= aRequest; 2934 throw aRequest; 2935 } 2936 2937 //========================================================================= 2938 uno::Reference< io::XInputStream > Content::getInputStream( 2939 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2940 throw ( ucb::CommandFailedException, 2941 task::DocumentPasswordRequest ) 2942 { 2943 rtl::OUString aUri; 2944 rtl::OUString aPassword; 2945 bool bPasswordRequested = false; 2946 2947 { 2948 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2949 2950 OSL_ENSURE( m_aProps.getType() == STREAM, 2951 "Content::getInputStream - content is no stream!" ); 2952 2953 aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri(); 2954 } 2955 2956 for ( ;; ) 2957 { 2958 try 2959 { 2960 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 2961 return uno::Reference< io::XInputStream >( 2962 m_pProvider->queryInputStream( aUri, aPassword ) ); 2963 } 2964 catch ( packages::WrongPasswordException const & ) 2965 { 2966 // Obtain (new) password. 2967 aPassword 2968 = obtainPassword( aUri, /* @@@ find better title */ 2969 bPasswordRequested 2970 ? task::PasswordRequestMode_PASSWORD_REENTER 2971 : task::PasswordRequestMode_PASSWORD_ENTER, 2972 xEnv ); 2973 bPasswordRequested = true; 2974 } 2975 } 2976 } 2977 2978 //========================================================================= 2979 static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream( 2980 const rtl::OUString & rUri, 2981 ContentProvider * pProvider, 2982 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 2983 throw ( ucb::CommandFailedException, 2984 task::DocumentPasswordRequest ) 2985 { 2986 rtl::OUString aPassword; 2987 bool bPasswordRequested = false; 2988 for ( ;; ) 2989 { 2990 try 2991 { 2992 return uno::Reference< io::XOutputStream >( 2993 pProvider->queryOutputStream( 2994 rUri, aPassword, true /* truncate */ ) ); 2995 } 2996 catch ( packages::WrongPasswordException const & ) 2997 { 2998 // Obtain (new) password. 2999 aPassword 3000 = obtainPassword( rUri, /* @@@ find better title */ 3001 bPasswordRequested 3002 ? task::PasswordRequestMode_PASSWORD_REENTER 3003 : task::PasswordRequestMode_PASSWORD_ENTER, 3004 xEnv ); 3005 bPasswordRequested = true; 3006 } 3007 } 3008 } 3009 3010 //========================================================================= 3011 uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream( 3012 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 3013 throw ( ucb::CommandFailedException, 3014 task::DocumentPasswordRequest ) 3015 { 3016 OSL_ENSURE( m_aProps.getType() == STREAM, 3017 "Content::getTruncatedOutputStream - content is no stream!" ); 3018 3019 return lcl_getTruncatedOutputStream( 3020 Uri( m_xIdentifier->getContentIdentifier() ).getUri(), 3021 m_pProvider, 3022 xEnv ); 3023 } 3024 3025 //========================================================================= 3026 uno::Reference< io::XStream > Content::getStream( 3027 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 3028 throw ( ucb::CommandFailedException, 3029 task::DocumentPasswordRequest ) 3030 { 3031 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 3032 3033 OSL_ENSURE( m_aProps.getType() == STREAM, 3034 "Content::getStream - content is no stream!" ); 3035 3036 rtl::OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() ); 3037 rtl::OUString aPassword; 3038 bool bPasswordRequested = false; 3039 for ( ;; ) 3040 { 3041 try 3042 { 3043 return uno::Reference< io::XStream >( 3044 m_pProvider->queryStream( 3045 aUri, aPassword, false /* no truncate */ ) ); 3046 } 3047 catch ( packages::WrongPasswordException const & ) 3048 { 3049 // Obtain (new) password. 3050 aPassword 3051 = obtainPassword( aUri, /* @@@ find better title */ 3052 bPasswordRequested 3053 ? task::PasswordRequestMode_PASSWORD_REENTER 3054 : task::PasswordRequestMode_PASSWORD_ENTER, 3055 xEnv ); 3056 bPasswordRequested = true; 3057 } 3058 } 3059 } 3060 3061 //========================================================================= 3062 //========================================================================= 3063 // 3064 // ContentProperties Implementation. 3065 // 3066 //========================================================================= 3067 //========================================================================= 3068 3069 uno::Sequence< ucb::ContentInfo > 3070 ContentProperties::getCreatableContentsInfo() const 3071 { 3072 if ( isContentCreator() ) 3073 { 3074 uno::Sequence< beans::Property > aProps( 1 ); 3075 aProps.getArray()[ 0 ] = beans::Property( 3076 rtl::OUString::createFromAscii( "Title" ), 3077 -1, 3078 getCppuType( static_cast< const rtl::OUString * >( 0 ) ), 3079 beans::PropertyAttribute::BOUND ); 3080 3081 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 3082 if ( getType() == DOCUMENT ) 3083 { 3084 // streams cannot be created as direct children of document root 3085 uno::Sequence< ucb::ContentInfo > aSeq( 1 ); 3086 3087 // Folder. 3088 aSeq.getArray()[ 0 ].Type 3089 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); 3090 aSeq.getArray()[ 0 ].Attributes 3091 = ucb::ContentInfoAttribute::KIND_FOLDER; 3092 aSeq.getArray()[ 0 ].Properties = aProps; 3093 3094 return aSeq; 3095 } 3096 else 3097 { 3098 #endif 3099 uno::Sequence< ucb::ContentInfo > aSeq( 2 ); 3100 3101 // Folder. 3102 aSeq.getArray()[ 0 ].Type 3103 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE ); 3104 aSeq.getArray()[ 0 ].Attributes 3105 = ucb::ContentInfoAttribute::KIND_FOLDER; 3106 aSeq.getArray()[ 0 ].Properties = aProps; 3107 3108 // Stream. 3109 aSeq.getArray()[ 1 ].Type 3110 = rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE ); 3111 aSeq.getArray()[ 1 ].Attributes 3112 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM 3113 | ucb::ContentInfoAttribute::KIND_DOCUMENT; 3114 aSeq.getArray()[ 1 ].Properties = aProps; 3115 3116 return aSeq; 3117 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT 3118 } 3119 #endif 3120 } 3121 else 3122 { 3123 OSL_ENSURE( sal_False, 3124 "getCreatableContentsInfo called on non-contentcreator " 3125 "object!" ); 3126 3127 return uno::Sequence< ucb::ContentInfo >( 0 ); 3128 } 3129 } 3130 3131 //========================================================================= 3132 bool ContentProperties::isContentCreator() const 3133 { 3134 return ( getType() == FOLDER ) || ( getType() == DOCUMENT ); 3135 } 3136