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