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 #include <osl/diagnose.h> 33 #include <cppuhelper/implbase1.hxx> 34 #include <cppuhelper/exc_hlp.hxx> 35 #include <rtl/ustring.h> 36 #include <rtl/ustring.hxx> 37 #include <com/sun/star/uno/XInterface.hpp> 38 #include <com/sun/star/beans/PropertyState.hpp> 39 #include <com/sun/star/beans/PropertyValue.hpp> 40 #include <com/sun/star/beans/XPropertySet.hpp> 41 #include <com/sun/star/container/XChild.hpp> 42 #include <com/sun/star/beans/XPropertySetInfo.hpp> 43 #include <com/sun/star/io/XActiveDataSink.hpp> 44 #include <com/sun/star/io/XOutputStream.hpp> 45 #include <com/sun/star/io/XSeekable.hpp> 46 #include <com/sun/star/sdbc/XRow.hpp> 47 #include <com/sun/star/task/XInteractionHandler.hpp> 48 #include <com/sun/star/ucb/CommandEnvironment.hpp> 49 #include <com/sun/star/ucb/CommandFailedException.hpp> 50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp> 51 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp> 52 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 53 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> 54 #include <com/sun/star/ucb/NameClash.hpp> 55 #include <com/sun/star/ucb/NameClashException.hpp> 56 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 57 #include <com/sun/star/ucb/OpenMode.hpp> 58 #include <com/sun/star/ucb/TransferInfo.hpp> 59 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> 60 #include <com/sun/star/ucb/XCommandInfo.hpp> 61 #include <com/sun/star/ucb/XContentAccess.hpp> 62 #include <com/sun/star/ucb/XContentCreator.hpp> 63 #include <com/sun/star/ucb/XDynamicResultSet.hpp> 64 #include <com/sun/star/uno/Any.hxx> 65 #include <com/sun/star/uno/Sequence.hxx> 66 #include <ucbhelper/cancelcommandexecution.hxx> 67 #include <ucbhelper/simplenameclashresolverequest.hxx> 68 #include "ucbcmds.hxx" 69 #include "ucb.hxx" 70 71 using namespace com::sun::star; 72 73 namespace 74 { 75 76 //========================================================================= 77 // 78 // struct TransferCommandContext. 79 // 80 //========================================================================= 81 82 struct TransferCommandContext 83 { 84 uno::Reference< lang::XMultiServiceFactory > xSMgr; 85 uno::Reference< ucb::XCommandProcessor > xProcessor; 86 uno::Reference< ucb::XCommandEnvironment > xEnv; 87 uno::Reference< ucb::XCommandEnvironment > xOrigEnv; 88 ucb::GlobalTransferCommandArgument aArg; 89 90 TransferCommandContext( 91 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr, 92 const uno::Reference< ucb::XCommandProcessor > & rxProcessor, 93 const uno::Reference< ucb::XCommandEnvironment > & rxEnv, 94 const uno::Reference< ucb::XCommandEnvironment > & rxOrigEnv, 95 const ucb::GlobalTransferCommandArgument & rArg ) 96 : xSMgr( rxSMgr ), xProcessor( rxProcessor ), xEnv( rxEnv ), 97 xOrigEnv( rxOrigEnv ), aArg( rArg ) {} 98 }; 99 100 //========================================================================= 101 // 102 // class InteractionHandlerProxy. 103 // 104 //========================================================================= 105 106 class InteractionHandlerProxy : 107 public cppu::WeakImplHelper1< task::XInteractionHandler > 108 { 109 uno::Reference< task::XInteractionHandler > m_xOrig; 110 111 public: 112 InteractionHandlerProxy( 113 const uno::Reference< task::XInteractionHandler > & xOrig ) 114 : m_xOrig( xOrig ) {} 115 116 // XInteractionHandler methods. 117 virtual void SAL_CALL handle( 118 const uno::Reference< task::XInteractionRequest >& Request ) 119 throw ( uno::RuntimeException ); 120 }; 121 122 //========================================================================= 123 // virtual 124 void SAL_CALL InteractionHandlerProxy::handle( 125 const uno::Reference< task::XInteractionRequest >& Request ) 126 throw ( uno::RuntimeException ) 127 { 128 if ( !m_xOrig.is() ) 129 return; 130 131 // Filter unwanted requests by just not handling them. 132 uno::Any aRequest = Request->getRequest(); 133 134 // "transfer" 135 ucb::InteractiveBadTransferURLException aBadTransferURLEx; 136 if ( aRequest >>= aBadTransferURLEx ) 137 { 138 return; 139 } 140 else 141 { 142 // "transfer" 143 ucb::UnsupportedNameClashException aUnsupportedNameClashEx; 144 if ( aRequest >>= aUnsupportedNameClashEx ) 145 { 146 if ( aUnsupportedNameClashEx.NameClash 147 != ucb::NameClash::ERROR ) 148 return; 149 } 150 else 151 { 152 // "insert" 153 ucb::NameClashException aNameClashEx; 154 if ( aRequest >>= aNameClashEx ) 155 { 156 return; 157 } 158 else 159 { 160 // "transfer" 161 ucb::UnsupportedCommandException aUnsupportedCommandEx; 162 if ( aRequest >>= aUnsupportedCommandEx ) 163 { 164 return; 165 } 166 } 167 } 168 } 169 170 // not filtered; let the original handler do the work. 171 m_xOrig->handle( Request ); 172 } 173 174 //========================================================================= 175 // 176 // class ActiveDataSink. 177 // 178 //========================================================================= 179 180 class ActiveDataSink : public cppu::WeakImplHelper1< io::XActiveDataSink > 181 { 182 uno::Reference< io::XInputStream > m_xStream; 183 184 public: 185 // XActiveDataSink methods. 186 virtual void SAL_CALL setInputStream( 187 const uno::Reference< io::XInputStream >& aStream ) 188 throw( uno::RuntimeException ); 189 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream() 190 throw( uno::RuntimeException ); 191 }; 192 193 //========================================================================= 194 // virtual 195 void SAL_CALL ActiveDataSink::setInputStream( 196 const uno::Reference< io::XInputStream >& aStream ) 197 throw( uno::RuntimeException ) 198 { 199 m_xStream = aStream; 200 } 201 202 //========================================================================= 203 // virtual 204 uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream() 205 throw( uno::RuntimeException ) 206 { 207 return m_xStream; 208 } 209 210 //========================================================================= 211 // 212 // class CommandProcessorInfo. 213 // 214 //========================================================================= 215 216 class CommandProcessorInfo : 217 public cppu::WeakImplHelper1< ucb::XCommandInfo > 218 { 219 uno::Sequence< ucb::CommandInfo > * m_pInfo; 220 221 public: 222 CommandProcessorInfo(); 223 virtual ~CommandProcessorInfo(); 224 225 // XCommandInfo methods 226 virtual uno::Sequence< ucb::CommandInfo > SAL_CALL getCommands() 227 throw( uno::RuntimeException ); 228 virtual ucb::CommandInfo SAL_CALL 229 getCommandInfoByName( const rtl::OUString& Name ) 230 throw( ucb::UnsupportedCommandException, uno::RuntimeException ); 231 virtual ucb::CommandInfo SAL_CALL 232 getCommandInfoByHandle( sal_Int32 Handle ) 233 throw( ucb::UnsupportedCommandException, uno::RuntimeException ); 234 virtual sal_Bool SAL_CALL hasCommandByName( const rtl::OUString& Name ) 235 throw( uno::RuntimeException ); 236 virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle ) 237 throw( uno::RuntimeException ); 238 }; 239 240 //========================================================================= 241 CommandProcessorInfo::CommandProcessorInfo() 242 { 243 m_pInfo = new uno::Sequence< ucb::CommandInfo >( 2 ); 244 245 (*m_pInfo)[ 0 ] 246 = ucb::CommandInfo( 247 rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME ), // Name 248 GETCOMMANDINFO_HANDLE, // Handle 249 getCppuVoidType() ); // ArgType 250 (*m_pInfo)[ 1 ] 251 = ucb::CommandInfo( 252 rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME ), // Name 253 GLOBALTRANSFER_HANDLE, // Handle 254 getCppuType( 255 static_cast< 256 ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType 257 } 258 259 //========================================================================= 260 // virtual 261 CommandProcessorInfo::~CommandProcessorInfo() 262 { 263 delete m_pInfo; 264 } 265 266 //========================================================================= 267 // virtual 268 uno::Sequence< ucb::CommandInfo > SAL_CALL 269 CommandProcessorInfo::getCommands() 270 throw( uno::RuntimeException ) 271 { 272 return uno::Sequence< ucb::CommandInfo >( *m_pInfo ); 273 } 274 275 //========================================================================= 276 // virtual 277 ucb::CommandInfo SAL_CALL 278 CommandProcessorInfo::getCommandInfoByName( const rtl::OUString& Name ) 279 throw( ucb::UnsupportedCommandException, uno::RuntimeException ) 280 { 281 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) 282 { 283 if ( (*m_pInfo)[ n ].Name == Name ) 284 return ucb::CommandInfo( (*m_pInfo)[ n ] ); 285 } 286 287 throw ucb::UnsupportedCommandException(); 288 } 289 290 //========================================================================= 291 // virtual 292 ucb::CommandInfo SAL_CALL 293 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle ) 294 throw( ucb::UnsupportedCommandException, uno::RuntimeException ) 295 { 296 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) 297 { 298 if ( (*m_pInfo)[ n ].Handle == Handle ) 299 return ucb::CommandInfo( (*m_pInfo)[ n ] ); 300 } 301 302 throw ucb::UnsupportedCommandException(); 303 } 304 305 //========================================================================= 306 // virtual 307 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName( 308 const rtl::OUString& Name ) 309 throw( uno::RuntimeException ) 310 { 311 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) 312 { 313 if ( (*m_pInfo)[ n ].Name == Name ) 314 return sal_True; 315 } 316 317 return sal_False; 318 } 319 320 //========================================================================= 321 // virtual 322 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle ) 323 throw( uno::RuntimeException ) 324 { 325 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n ) 326 { 327 if ( (*m_pInfo)[ n ].Handle == Handle ) 328 return sal_True; 329 } 330 331 return sal_False; 332 } 333 334 //========================================================================= 335 //========================================================================= 336 //========================================================================= 337 338 rtl::OUString createDesiredName( 339 const rtl::OUString & rSourceURL, const rtl::OUString & rNewTitle ) 340 { 341 rtl::OUString aName( rNewTitle ); 342 if ( aName.getLength() == 0 ) 343 { 344 // calculate name using source URL 345 346 // @@@ It's not guaranteed that slashes contained in the URL are 347 // actually path separators. This depends on the fact whether the 348 // URL is hierarchical. Only then the slashes are path separators. 349 // Therefore this algorithm is not guaranteed to work! But, ATM 350 // I don't know a better solution. It would have been better to 351 // have a member for the clashing name in 352 // UnsupportedNameClashException... 353 354 sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' ); 355 bool bTrailingSlash = false; 356 if ( nLastSlash == rSourceURL.getLength() - 1 ) 357 { 358 nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash ); 359 bTrailingSlash = true; 360 } 361 362 if ( nLastSlash != -1 ) 363 { 364 if ( bTrailingSlash ) 365 aName = rSourceURL.copy( 366 nLastSlash + 1, 367 rSourceURL.getLength() - nLastSlash - 2 ); 368 else 369 aName = rSourceURL.copy( nLastSlash + 1 ); 370 } 371 else 372 { 373 aName = rSourceURL; 374 } 375 376 // query, fragment present? 377 sal_Int32 nPos = aName.indexOf( '?' ); 378 if ( nPos == -1 ) 379 nPos = aName.indexOf( '#' ); 380 381 if ( nPos != -1 ) 382 aName = aName.copy( 0, nPos ); 383 } 384 return rtl::OUString( aName ); 385 } 386 387 rtl::OUString createDesiredName( 388 const ucb::GlobalTransferCommandArgument & rArg ) 389 { 390 return createDesiredName( rArg.SourceURL, rArg.NewTitle ); 391 } 392 393 rtl::OUString createDesiredName( 394 const ucb::TransferInfo & rArg ) 395 { 396 return createDesiredName( rArg.SourceURL, rArg.NewTitle ); 397 } 398 399 //========================================================================= 400 enum NameClashContinuation { NOT_HANDLED, ABORT, OVERWRITE, NEW_NAME, UNKNOWN }; 401 402 NameClashContinuation interactiveNameClashResolve( 403 const uno::Reference< ucb::XCommandEnvironment > & xEnv, 404 const rtl::OUString & rTargetURL, 405 const rtl::OUString & rClashingName, 406 /* [out] */ uno::Any & rException, 407 /* [out] */ rtl::OUString & rNewName ) 408 { 409 rtl::Reference< ucbhelper::SimpleNameClashResolveRequest > xRequest( 410 new ucbhelper::SimpleNameClashResolveRequest( 411 rTargetURL, // target folder URL 412 rClashingName, // clashing name 413 rtl::OUString(), // no proposal for new name 414 sal_True /* bSupportsOverwriteData */ ) ); 415 416 rException = xRequest->getRequest(); 417 if ( xEnv.is() ) 418 { 419 uno::Reference< task::XInteractionHandler > xIH 420 = xEnv->getInteractionHandler(); 421 if ( xIH.is() ) 422 { 423 424 xIH->handle( xRequest.get() ); 425 426 rtl::Reference< ucbhelper::InteractionContinuation > 427 xSelection( xRequest->getSelection() ); 428 429 if ( xSelection.is() ) 430 { 431 // Handler handled the request. 432 uno::Reference< task::XInteractionAbort > xAbort( 433 xSelection.get(), uno::UNO_QUERY ); 434 if ( xAbort.is() ) 435 { 436 // Abort. 437 return ABORT; 438 } 439 else 440 { 441 uno::Reference< 442 ucb::XInteractionReplaceExistingData > 443 xReplace( 444 xSelection.get(), uno::UNO_QUERY ); 445 if ( xReplace.is() ) 446 { 447 // Try again: Replace existing data. 448 return OVERWRITE; 449 } 450 else 451 { 452 uno::Reference< 453 ucb::XInteractionSupplyName > 454 xSupplyName( 455 xSelection.get(), uno::UNO_QUERY ); 456 if ( xSupplyName.is() ) 457 { 458 // Try again: Use new name. 459 rNewName = xRequest->getNewName(); 460 return NEW_NAME; 461 } 462 else 463 { 464 OSL_ENSURE( sal_False, 465 "Unknown interaction continuation!" ); 466 return UNKNOWN; 467 } 468 } 469 } 470 } 471 } 472 } 473 return NOT_HANDLED; 474 } 475 476 //========================================================================= 477 bool setTitle( 478 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessor, 479 const uno::Reference< ucb::XCommandEnvironment > & xEnv, 480 const rtl::OUString & rNewTitle ) 481 throw( uno::RuntimeException ) 482 { 483 try 484 { 485 uno::Sequence< beans::PropertyValue > aPropValues( 1 ); 486 aPropValues[ 0 ].Name 487 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ); 488 aPropValues[ 0 ].Handle = -1; 489 aPropValues[ 0 ].Value = uno::makeAny( rNewTitle ); 490 491 ucb::Command aSetPropsCommand( 492 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), 493 -1, 494 uno::makeAny( aPropValues ) ); 495 496 uno::Any aResult 497 = xCommandProcessor->execute( aSetPropsCommand, 0, xEnv ); 498 499 uno::Sequence< uno::Any > aErrors; 500 aResult >>= aErrors; 501 502 OSL_ENSURE( aErrors.getLength() == 1, 503 "getPropertyValues return value invalid!" ); 504 505 if ( aErrors[ 0 ].hasValue() ) 506 { 507 // error occured. 508 OSL_ENSURE( sal_False, "error setting Title property!" ); 509 return false; 510 } 511 } 512 catch ( uno::RuntimeException const & ) 513 { 514 throw; 515 } 516 catch ( uno::Exception const & ) 517 { 518 return false; 519 } 520 521 return true; 522 } 523 524 //========================================================================= 525 uno::Reference< ucb::XContent > createNew( 526 const TransferCommandContext & rContext, 527 const uno::Reference< ucb::XContent > & xTarget, 528 sal_Bool bSourceIsFolder, 529 sal_Bool bSourceIsDocument, 530 sal_Bool bSourceIsLink ) 531 throw( uno::Exception ) 532 { 533 ////////////////////////////////////////////////////////////////////// 534 // 535 // (1) Obtain creatable types from target. 536 // 537 ////////////////////////////////////////////////////////////////////// 538 539 // First, try it using "CreatabeleContentsInfo" property and 540 // "createNewContent" command -> the "new" way. 541 542 uno::Reference< ucb::XCommandProcessor > xCommandProcessorT( 543 xTarget, uno::UNO_QUERY ); 544 if ( !xCommandProcessorT.is() ) 545 { 546 uno::Any aProps 547 = uno::makeAny(beans::PropertyValue( 548 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 549 "Folder")), 550 -1, 551 uno::makeAny(rContext.aArg.TargetURL), 552 beans::PropertyState_DIRECT_VALUE)); 553 ucbhelper::cancelCommandExecution( 554 ucb::IOErrorCode_CANT_CREATE, 555 uno::Sequence< uno::Any >(&aProps, 1), 556 rContext.xOrigEnv, 557 rtl::OUString::createFromAscii( "Target is no XCommandProcessor!" ), 558 rContext.xProcessor ); 559 // Unreachable 560 } 561 562 uno::Sequence< beans::Property > aPropsToObtain( 1 ); 563 aPropsToObtain[ 0 ].Name 564 = rtl::OUString::createFromAscii( "CreatableContentsInfo" ); 565 aPropsToObtain[ 0 ].Handle 566 = -1; 567 568 ucb::Command aGetPropsCommand( 569 rtl::OUString::createFromAscii( "getPropertyValues" ), 570 -1, 571 uno::makeAny( aPropsToObtain ) ); 572 573 uno::Reference< sdbc::XRow > xRow; 574 xCommandProcessorT->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow; 575 576 uno::Sequence< ucb::ContentInfo > aTypesInfo; 577 bool bGotTypesInfo = false; 578 579 if ( xRow.is() ) 580 { 581 uno::Any aValue = xRow->getObject( 582 1, uno::Reference< container::XNameAccess >() ); 583 if ( aValue.hasValue() && ( aValue >>= aTypesInfo ) ) 584 { 585 bGotTypesInfo = true; 586 } 587 } 588 589 uno::Reference< ucb::XContentCreator > xCreator; 590 591 if ( !bGotTypesInfo ) 592 { 593 // Second, try it using XContentCreator interface -> the "old" way (not 594 // providing the chance to supply an XCommandEnvironment. 595 596 xCreator.set( xTarget, uno::UNO_QUERY ); 597 598 if ( !xCreator.is() ) 599 { 600 uno::Any aProps 601 = uno::makeAny(beans::PropertyValue( 602 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 603 "Folder")), 604 -1, 605 uno::makeAny(rContext.aArg.TargetURL), 606 beans::PropertyState_DIRECT_VALUE)); 607 ucbhelper::cancelCommandExecution( 608 ucb::IOErrorCode_CANT_CREATE, 609 uno::Sequence< uno::Any >(&aProps, 1), 610 rContext.xOrigEnv, 611 rtl::OUString::createFromAscii( "Target is no XContentCreator!" ), 612 rContext.xProcessor ); 613 // Unreachable 614 } 615 616 aTypesInfo = xCreator->queryCreatableContentsInfo(); 617 } 618 619 sal_Int32 nCount = aTypesInfo.getLength(); 620 if ( !nCount ) 621 { 622 uno::Any aProps 623 = uno::makeAny(beans::PropertyValue( 624 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Folder")), 625 -1, 626 uno::makeAny(rContext.aArg.TargetURL), 627 beans::PropertyState_DIRECT_VALUE)); 628 ucbhelper::cancelCommandExecution( 629 ucb::IOErrorCode_CANT_CREATE, 630 uno::Sequence< uno::Any >(&aProps, 1), 631 rContext.xOrigEnv, 632 rtl::OUString::createFromAscii( "No types creatable!" ), 633 rContext.xProcessor ); 634 // Unreachable 635 } 636 637 ////////////////////////////////////////////////////////////////////// 638 // 639 // (2) Try to find a matching target type for the source object. 640 // 641 ////////////////////////////////////////////////////////////////////// 642 643 uno::Reference< ucb::XContent > xNew; 644 for ( sal_Int32 n = 0; n < nCount; ++n ) 645 { 646 sal_Int32 nAttribs = aTypesInfo[ n ].Attributes; 647 sal_Bool bMatch = sal_False; 648 649 if ( rContext.aArg.Operation == ucb::TransferCommandOperation_LINK ) 650 { 651 // Create link 652 653 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK ) 654 { 655 // Match! 656 bMatch = sal_True; 657 } 658 } 659 else if ( ( rContext.aArg.Operation 660 == ucb::TransferCommandOperation_COPY ) || 661 ( rContext.aArg.Operation 662 == ucb::TransferCommandOperation_MOVE ) ) 663 { 664 // Copy / Move 665 666 // Is source a link? Create link in target folder then. 667 if ( bSourceIsLink ) 668 { 669 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK ) 670 { 671 // Match! 672 bMatch = sal_True; 673 } 674 } 675 else 676 { 677 // (not a and not b) or (a and b) 678 // not( a or b) or (a and b) 679 // 680 if ( ( !!bSourceIsFolder == 681 !!( nAttribs 682 & ucb::ContentInfoAttribute::KIND_FOLDER ) ) 683 && 684 ( !!bSourceIsDocument == 685 !!( nAttribs 686 & ucb::ContentInfoAttribute::KIND_DOCUMENT ) ) 687 ) 688 { 689 // Match! 690 bMatch = sal_True; 691 } 692 } 693 } 694 else 695 { 696 ucbhelper::cancelCommandExecution( 697 uno::makeAny( lang::IllegalArgumentException( 698 rtl::OUString::createFromAscii( 699 "Unknown transfer operation!" ), 700 rContext.xProcessor, 701 -1 ) ), 702 rContext.xOrigEnv ); 703 // Unreachable 704 } 705 706 if ( bMatch ) 707 { 708 ////////////////////////////////////////////////////////////// 709 // 710 // (3) Create a new, empty object of matched type. 711 // 712 ////////////////////////////////////////////////////////////// 713 714 if ( !xCreator.is() ) 715 { 716 // First, try it using "CreatabeleContentsInfo" property and 717 // "createNewContent" command -> the "new" way. 718 ucb::Command aCreateNewCommand( 719 rtl::OUString::createFromAscii( "createNewContent" ), 720 -1, 721 uno::makeAny( aTypesInfo[ n ] ) ); 722 723 xCommandProcessorT->execute( aCreateNewCommand, 0, rContext.xEnv ) 724 >>= xNew; 725 } 726 else 727 { 728 // Second, try it using XContentCreator interface -> the "old" 729 // way (not providing the chance to supply an XCommandEnvironment. 730 731 xNew = xCreator->createNewContent( aTypesInfo[ n ] ); 732 } 733 734 if ( !xNew.is() ) 735 { 736 uno::Any aProps 737 = uno::makeAny( 738 beans::PropertyValue( 739 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 740 "Folder")), 741 -1, 742 uno::makeAny(rContext.aArg.TargetURL), 743 beans::PropertyState_DIRECT_VALUE)); 744 ucbhelper::cancelCommandExecution( 745 ucb::IOErrorCode_CANT_CREATE, 746 uno::Sequence< uno::Any >(&aProps, 1), 747 rContext.xOrigEnv, 748 rtl::OUString::createFromAscii( 749 "createNewContent failed!" ), 750 rContext.xProcessor ); 751 // Unreachable 752 } 753 break; // escape from 'for' loop 754 } 755 } // for 756 757 return xNew; 758 } 759 760 //========================================================================= 761 void transferProperties( 762 const TransferCommandContext & rContext, 763 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS, 764 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorN ) 765 throw( uno::Exception ) 766 { 767 ucb::Command aGetPropertySetInfoCommand( 768 rtl::OUString::createFromAscii( "getPropertySetInfo" ), 769 -1, 770 uno::Any() ); 771 772 uno::Reference< beans::XPropertySetInfo > xInfo; 773 xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv ) 774 >>= xInfo; 775 776 if ( !xInfo.is() ) 777 { 778 uno::Any aProps 779 = uno::makeAny(beans::PropertyValue( 780 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 781 "Uri")), 782 -1, 783 uno::makeAny(rContext.aArg.SourceURL), 784 beans::PropertyState_DIRECT_VALUE)); 785 ucbhelper::cancelCommandExecution( 786 ucb::IOErrorCode_CANT_READ, 787 uno::Sequence< uno::Any >(&aProps, 1), 788 rContext.xOrigEnv, 789 rtl::OUString::createFromAscii( 790 "Unable to get propertyset info from source object!" ), 791 rContext.xProcessor ); 792 // Unreachable 793 } 794 795 uno::Sequence< beans::Property > aAllProps = xInfo->getProperties(); 796 797 ucb::Command aGetPropsCommand1( 798 rtl::OUString::createFromAscii( "getPropertyValues" ), 799 -1, 800 uno::makeAny( aAllProps ) ); 801 802 uno::Reference< sdbc::XRow > xRow1; 803 xCommandProcessorS->execute( 804 aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1; 805 806 if ( !xRow1.is() ) 807 { 808 uno::Any aProps 809 = uno::makeAny(beans::PropertyValue( 810 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 811 "Uri")), 812 -1, 813 uno::makeAny(rContext.aArg.SourceURL), 814 beans::PropertyState_DIRECT_VALUE)); 815 ucbhelper::cancelCommandExecution( 816 ucb::IOErrorCode_CANT_READ, 817 uno::Sequence< uno::Any >(&aProps, 1), 818 rContext.xOrigEnv, 819 rtl::OUString::createFromAscii( 820 "Unable to get properties from source object!" ), 821 rContext.xProcessor ); 822 // Unreachable 823 } 824 825 // Assemble data structure for setPropertyValues command. 826 827 // Note: Make room for additional Title and TargetURL too. -> + 2 828 uno::Sequence< beans::PropertyValue > aPropValues( 829 aAllProps.getLength() + 2 ); 830 831 sal_Bool bHasTitle = ( rContext.aArg.NewTitle.getLength() == 0 ); 832 sal_Bool bHasTargetURL = ( rContext.aArg.Operation 833 != ucb::TransferCommandOperation_LINK ); 834 835 sal_Int32 nWritePos = 0; 836 for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m ) 837 { 838 const beans::Property & rCurrProp = aAllProps[ m ]; 839 beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ]; 840 841 uno::Any aValue; 842 843 if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 ) 844 { 845 // Supply new title, if given. 846 if ( !bHasTitle ) 847 { 848 bHasTitle = sal_True; 849 aValue <<= rContext.aArg.NewTitle; 850 } 851 } 852 else if ( rCurrProp.Name.compareToAscii( "TargetURL" ) == 0 ) 853 { 854 // Supply source URL as link target for the new link to create. 855 if ( !bHasTargetURL ) 856 { 857 bHasTargetURL = sal_True; 858 aValue <<= rContext.aArg.SourceURL; 859 } 860 } 861 862 if ( !aValue.hasValue() ) 863 { 864 try 865 { 866 aValue = xRow1->getObject( 867 m + 1, uno::Reference< container::XNameAccess >() ); 868 } 869 catch ( sdbc::SQLException const & ) 870 { 871 // Argh! But try to bring things to an end. Perhaps the 872 // mad property is not really important... 873 } 874 } 875 876 if ( aValue.hasValue() ) 877 { 878 rCurrValue.Name = rCurrProp.Name; 879 rCurrValue.Handle = rCurrProp.Handle; 880 rCurrValue.Value = aValue; 881 // rCurrValue.State = 882 883 nWritePos++; 884 } 885 } 886 887 // Title needed, but not set yet? 888 if ( !bHasTitle && ( rContext.aArg.NewTitle.getLength() > 0 ) ) 889 { 890 aPropValues[ nWritePos ].Name 891 = rtl::OUString::createFromAscii( "Title" ); 892 aPropValues[ nWritePos ].Handle = -1; 893 aPropValues[ nWritePos ].Value <<= rContext.aArg.NewTitle; 894 895 nWritePos++; 896 } 897 898 // TargetURL needed, but not set yet? 899 if ( !bHasTargetURL && ( rContext.aArg.Operation 900 == ucb::TransferCommandOperation_LINK ) ) 901 { 902 aPropValues[ nWritePos ].Name 903 = rtl::OUString::createFromAscii( "TargetURL" ); 904 aPropValues[ nWritePos ].Handle = -1; 905 aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL; 906 907 nWritePos++; 908 } 909 910 aPropValues.realloc( nWritePos ); 911 912 // Set properties at new object. 913 914 ucb::Command aSetPropsCommand( 915 rtl::OUString::createFromAscii( "setPropertyValues" ), 916 -1, 917 uno::makeAny( aPropValues ) ); 918 919 xCommandProcessorN->execute( aSetPropsCommand, 0, rContext.xEnv ); 920 921 // @@@ What to do with source props that are not supported by the 922 // new object? addProperty ??? 923 } 924 925 //========================================================================= 926 uno::Reference< io::XInputStream > getInputStream( 927 const TransferCommandContext & rContext, 928 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS ) 929 throw( uno::Exception ) 930 { 931 uno::Reference< io::XInputStream > xInputStream; 932 933 ////////////////////////////////////////////////////////////////////// 934 // 935 // (1) Try to get data as XInputStream via XActiveDataSink. 936 // 937 ////////////////////////////////////////////////////////////////////// 938 939 try 940 { 941 uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink; 942 943 ucb::OpenCommandArgument2 aArg; 944 aArg.Mode = ucb::OpenMode::DOCUMENT; 945 aArg.Priority = 0; // unused 946 aArg.Sink = xSink; 947 aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused 948 949 ucb::Command aOpenCommand( 950 rtl::OUString::createFromAscii( "open" ), 951 -1, 952 uno::makeAny( aArg ) ); 953 954 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ); 955 xInputStream = xSink->getInputStream(); 956 } 957 catch ( uno::RuntimeException const & ) 958 { 959 throw; 960 } 961 catch ( uno::Exception const & ) 962 { 963 // will be handled below. 964 } 965 966 if ( !xInputStream.is() ) 967 { 968 ////////////////////////////////////////////////////////////////// 969 // 970 // (2) Try to get data via XOutputStream. 971 // 972 ////////////////////////////////////////////////////////////////// 973 974 try 975 { 976 uno::Reference< io::XOutputStream > xOutputStream( 977 rContext.xSMgr->createInstance( 978 rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ), 979 uno::UNO_QUERY ); 980 981 if ( xOutputStream.is() ) 982 { 983 ucb::OpenCommandArgument2 aArg; 984 aArg.Mode = ucb::OpenMode::DOCUMENT; 985 aArg.Priority = 0; // unused 986 aArg.Sink = xOutputStream; 987 aArg.Properties = uno::Sequence< beans::Property >( 0 ); 988 989 ucb::Command aOpenCommand( 990 rtl::OUString::createFromAscii( "open" ), 991 -1, 992 uno::makeAny( aArg ) ); 993 994 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ); 995 996 xInputStream = uno::Reference< io::XInputStream >( 997 xOutputStream, uno::UNO_QUERY ); 998 } 999 } 1000 catch ( uno::RuntimeException const & ) 1001 { 1002 throw; 1003 } 1004 catch ( uno::Exception const & ) 1005 { 1006 OSL_ENSURE( sal_False, "unable to get input stream from document!" ); 1007 } 1008 } 1009 1010 return xInputStream; 1011 } 1012 1013 //========================================================================= 1014 uno::Reference< sdbc::XResultSet > getResultSet( 1015 const TransferCommandContext & rContext, 1016 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS ) 1017 throw( uno::Exception ) 1018 { 1019 uno::Reference< sdbc::XResultSet > xResultSet; 1020 1021 uno::Sequence< beans::Property > aProps( 3 ); 1022 1023 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); 1024 aProps[ 0 ].Handle = -1; /* unknown */ 1025 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); 1026 aProps[ 1 ].Handle = -1; /* unknown */ 1027 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" ); 1028 aProps[ 2 ].Handle = -1; /* unknown */ 1029 1030 ucb::OpenCommandArgument2 aArg; 1031 aArg.Mode = ucb::OpenMode::ALL; 1032 aArg.Priority = 0; // unused 1033 aArg.Sink = 0; 1034 aArg.Properties = aProps; 1035 1036 ucb::Command aOpenCommand( rtl::OUString::createFromAscii( "open" ), 1037 -1, 1038 uno::makeAny( aArg ) ); 1039 try 1040 { 1041 uno::Reference< ucb::XDynamicResultSet > xSet; 1042 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet; 1043 1044 if ( xSet.is() ) 1045 xResultSet = xSet->getStaticResultSet(); 1046 } 1047 catch ( uno::RuntimeException const & ) 1048 { 1049 throw; 1050 } 1051 catch ( uno::Exception const & ) 1052 { 1053 OSL_ENSURE( sal_False, "unable to get result set from folder!" ); 1054 } 1055 1056 return xResultSet; 1057 } 1058 1059 //========================================================================= 1060 void handleNameClashRename( 1061 const TransferCommandContext & rContext, 1062 const uno::Reference< ucb::XContent > & xNew, 1063 const uno::Reference< 1064 ucb::XCommandProcessor > & xCommandProcessorN, 1065 const uno::Reference< 1066 ucb::XCommandProcessor > & xCommandProcessorS, 1067 /* [inout] */ uno::Reference< io::XInputStream > & xInputStream ) 1068 throw( uno::Exception ) 1069 { 1070 sal_Int32 nTry = 0; 1071 1072 // Obtain old title. 1073 uno::Sequence< beans::Property > aProps( 1 ); 1074 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" ); 1075 aProps[ 0 ].Handle = -1; 1076 1077 ucb::Command aGetPropsCommand( 1078 rtl::OUString::createFromAscii( "getPropertyValues" ), 1079 -1, 1080 uno::makeAny( aProps ) ); 1081 1082 uno::Reference< sdbc::XRow > xRow; 1083 xCommandProcessorN->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow; 1084 1085 if ( !xRow.is() ) 1086 { 1087 uno::Any aProps2 1088 = uno::makeAny( 1089 beans::PropertyValue( 1090 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), 1091 -1, 1092 uno::makeAny( 1093 xNew->getIdentifier()->getContentIdentifier() ), 1094 beans::PropertyState_DIRECT_VALUE ) ); 1095 ucbhelper::cancelCommandExecution( 1096 ucb::IOErrorCode_CANT_READ, 1097 uno::Sequence< uno::Any >( &aProps2, 1 ), 1098 rContext.xOrigEnv, 1099 rtl::OUString::createFromAscii( 1100 "Unable to get properties from new object!" ), 1101 rContext.xProcessor ); 1102 // Unreachable 1103 } 1104 1105 rtl::OUString aOldTitle = xRow->getString( 1 ); 1106 if ( !aOldTitle.getLength() ) 1107 { 1108 ucbhelper::cancelCommandExecution( 1109 uno::makeAny( beans::UnknownPropertyException( 1110 rtl::OUString::createFromAscii( 1111 "Unable to get property 'Title' " 1112 "from new object!" ), 1113 rContext.xProcessor ) ), 1114 rContext.xOrigEnv ); 1115 // Unreachable 1116 } 1117 1118 // Some pseudo-intelligence for not destroying file extensions. 1119 rtl::OUString aOldTitlePre; 1120 rtl::OUString aOldTitlePost; 1121 sal_Int32 nPos = aOldTitle.lastIndexOf( '.' ); 1122 if ( nPos != -1 ) 1123 { 1124 aOldTitlePre = aOldTitle.copy( 0, nPos ); 1125 aOldTitlePost = aOldTitle.copy( nPos ); 1126 } 1127 else 1128 aOldTitlePre = aOldTitle; 1129 1130 if ( nPos > 0 ) 1131 aOldTitlePre += rtl::OUString::createFromAscii( "_" ); 1132 1133 sal_Bool bContinue = sal_True; 1134 do 1135 { 1136 nTry++; 1137 1138 rtl::OUString aNewTitle = aOldTitlePre; 1139 aNewTitle += rtl::OUString::valueOf( nTry ); 1140 aNewTitle += aOldTitlePost; 1141 1142 // Set new title 1143 setTitle( xCommandProcessorN, rContext.xEnv, aNewTitle ); 1144 1145 // Retry inserting the content. 1146 try 1147 { 1148 // Previous try may have read from stream. Seek to begin (if 1149 // optional interface XSeekable is supported) or get a new stream. 1150 if ( xInputStream.is() ) 1151 { 1152 uno::Reference< io::XSeekable > xSeekable( 1153 xInputStream, uno::UNO_QUERY ); 1154 if ( xSeekable.is() ) 1155 { 1156 try 1157 { 1158 xSeekable->seek( 0 ); 1159 } 1160 catch ( lang::IllegalArgumentException const & ) 1161 { 1162 xInputStream.clear(); 1163 } 1164 catch ( io::IOException const & ) 1165 { 1166 xInputStream.clear(); 1167 } 1168 } 1169 else 1170 xInputStream.clear(); 1171 1172 if ( !xInputStream.is() ) 1173 { 1174 xInputStream 1175 = getInputStream( rContext, xCommandProcessorS ); 1176 if ( !xInputStream.is() ) 1177 { 1178 uno::Any aProps2 1179 = uno::makeAny( 1180 beans::PropertyValue( 1181 rtl::OUString( 1182 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ), 1183 -1, 1184 uno::makeAny( 1185 xNew->getIdentifier()-> 1186 getContentIdentifier() ), 1187 beans::PropertyState_DIRECT_VALUE ) ); 1188 ucbhelper::cancelCommandExecution( 1189 ucb::IOErrorCode_CANT_READ, 1190 uno::Sequence< uno::Any >( &aProps2, 1 ), 1191 rContext.xOrigEnv, 1192 rtl::OUString::createFromAscii( 1193 "Got no data stream from source!" ), 1194 rContext.xProcessor ); 1195 // Unreachable 1196 } 1197 } 1198 } 1199 1200 ucb::InsertCommandArgument aArg; 1201 aArg.Data = xInputStream; 1202 aArg.ReplaceExisting = sal_False; 1203 1204 ucb::Command aInsertCommand( 1205 rtl::OUString::createFromAscii( "insert" ), 1206 -1, 1207 uno::makeAny( aArg ) ); 1208 1209 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv ); 1210 1211 // Success! 1212 bContinue = sal_False; 1213 } 1214 catch ( uno::RuntimeException const & ) 1215 { 1216 throw; 1217 } 1218 catch ( uno::Exception const & ) 1219 { 1220 } 1221 } 1222 while ( bContinue && ( nTry < 50 ) ); 1223 1224 if ( nTry == 50 ) 1225 { 1226 ucbhelper::cancelCommandExecution( 1227 uno::makeAny( 1228 ucb::UnsupportedNameClashException( 1229 rtl::OUString::createFromAscii( 1230 "Unable to resolve name clash!" ), 1231 rContext.xProcessor, 1232 ucb::NameClash::RENAME ) ), 1233 rContext.xOrigEnv ); 1234 // Unreachable 1235 } 1236 } 1237 1238 //========================================================================= 1239 void globalTransfer_( 1240 const TransferCommandContext & rContext, 1241 const uno::Reference< ucb::XContent > & xSource, 1242 const uno::Reference< ucb::XContent > & xTarget, 1243 const uno::Reference< sdbc::XRow > & xSourceProps ) 1244 throw( uno::Exception ) 1245 { 1246 // IsFolder: property is required. 1247 sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 ); 1248 if ( !bSourceIsFolder && xSourceProps->wasNull() ) 1249 { 1250 ucbhelper::cancelCommandExecution( 1251 uno::makeAny( beans::UnknownPropertyException( 1252 rtl::OUString::createFromAscii( 1253 "Unable to get property 'IsFolder' " 1254 "from source object!" ), 1255 rContext.xProcessor ) ), 1256 rContext.xOrigEnv ); 1257 // Unreachable 1258 } 1259 1260 // IsDocument: property is required. 1261 sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 ); 1262 if ( !bSourceIsDocument && xSourceProps->wasNull() ) 1263 { 1264 ucbhelper::cancelCommandExecution( 1265 uno::makeAny( beans::UnknownPropertyException( 1266 rtl::OUString::createFromAscii( 1267 "Unable to get property 'IsDocument' " 1268 "from source object!" ), 1269 rContext.xProcessor ) ), 1270 rContext.xOrigEnv ); 1271 // Unreachable 1272 } 1273 1274 // TargetURL: property is optional. 1275 sal_Bool bSourceIsLink = ( xSourceProps->getString( 3 ).getLength() > 0 ); 1276 1277 ////////////////////////////////////////////////////////////////////// 1278 // 1279 // (1) Try to find a matching target type for the source object and 1280 // create a new, empty object of that type. 1281 // 1282 ////////////////////////////////////////////////////////////////////// 1283 1284 uno::Reference< ucb::XContent > xNew = createNew( rContext, 1285 xTarget, 1286 bSourceIsFolder, 1287 bSourceIsDocument, 1288 bSourceIsLink ); 1289 if ( !xNew.is() ) 1290 { 1291 uno::Any aProps 1292 = uno::makeAny(beans::PropertyValue( 1293 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1294 "Folder")), 1295 -1, 1296 uno::makeAny(rContext.aArg.TargetURL), 1297 beans::PropertyState_DIRECT_VALUE)); 1298 ucbhelper::cancelCommandExecution( 1299 ucb::IOErrorCode_CANT_CREATE, 1300 uno::Sequence< uno::Any >(&aProps, 1), 1301 rContext.xOrigEnv, 1302 rtl::OUString::createFromAscii( 1303 "No matching content type at target!" ), 1304 rContext.xProcessor ); 1305 // Unreachable 1306 } 1307 1308 ////////////////////////////////////////////////////////////////////// 1309 // 1310 // (2) Transfer property values from source to new object. 1311 // 1312 ////////////////////////////////////////////////////////////////////// 1313 1314 uno::Reference< ucb::XCommandProcessor > xCommandProcessorN( 1315 xNew, uno::UNO_QUERY ); 1316 if ( !xCommandProcessorN.is() ) 1317 { 1318 uno::Any aProps 1319 = uno::makeAny(beans::PropertyValue( 1320 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1321 "Uri")), 1322 -1, 1323 uno::makeAny( 1324 xNew->getIdentifier()-> 1325 getContentIdentifier()), 1326 beans::PropertyState_DIRECT_VALUE)); 1327 ucbhelper::cancelCommandExecution( 1328 ucb::IOErrorCode_CANT_WRITE, 1329 uno::Sequence< uno::Any >(&aProps, 1), 1330 rContext.xOrigEnv, 1331 rtl::OUString::createFromAscii( 1332 "New content is not a XCommandProcessor!" ), 1333 rContext.xProcessor ); 1334 // Unreachable 1335 } 1336 1337 // Obtain all properties from source. 1338 1339 uno::Reference< ucb::XCommandProcessor > xCommandProcessorS( 1340 xSource, uno::UNO_QUERY ); 1341 if ( !xCommandProcessorS.is() ) 1342 { 1343 uno::Any aProps 1344 = uno::makeAny(beans::PropertyValue( 1345 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1346 "Uri")), 1347 -1, 1348 uno::makeAny(rContext.aArg.SourceURL), 1349 beans::PropertyState_DIRECT_VALUE)); 1350 ucbhelper::cancelCommandExecution( 1351 ucb::IOErrorCode_CANT_READ, 1352 uno::Sequence< uno::Any >(&aProps, 1), 1353 rContext.xOrigEnv, 1354 rtl::OUString::createFromAscii( 1355 "Source content is not a XCommandProcessor!" ), 1356 rContext.xProcessor ); 1357 // Unreachable 1358 } 1359 1360 transferProperties( rContext, xCommandProcessorS, xCommandProcessorN ); 1361 1362 ////////////////////////////////////////////////////////////////////// 1363 // 1364 // (3) Try to obtain a data stream from source. 1365 // 1366 ////////////////////////////////////////////////////////////////////// 1367 1368 uno::Reference< io::XInputStream > xInputStream; 1369 1370 if ( bSourceIsDocument && ( rContext.aArg.Operation 1371 != ucb::TransferCommandOperation_LINK ) ) 1372 xInputStream = getInputStream( rContext, xCommandProcessorS ); 1373 1374 ////////////////////////////////////////////////////////////////////// 1375 // 1376 // (4) Try to obtain a resultset (children) from source. 1377 // 1378 ////////////////////////////////////////////////////////////////////// 1379 1380 uno::Reference< sdbc::XResultSet > xResultSet; 1381 1382 if ( bSourceIsFolder && ( rContext.aArg.Operation 1383 != ucb::TransferCommandOperation_LINK ) ) 1384 xResultSet = getResultSet( rContext, xCommandProcessorS ); 1385 1386 ////////////////////////////////////////////////////////////////////// 1387 // 1388 // (5) Insert (store) new content. 1389 // 1390 ////////////////////////////////////////////////////////////////////// 1391 1392 ucb::InsertCommandArgument aArg; 1393 aArg.Data = xInputStream; 1394 1395 switch ( rContext.aArg.NameClash ) 1396 { 1397 case ucb::NameClash::OVERWRITE: 1398 aArg.ReplaceExisting = sal_True; 1399 break; 1400 1401 case ucb::NameClash::ERROR: 1402 case ucb::NameClash::RENAME: 1403 case ucb::NameClash::KEEP: // deprecated 1404 case ucb::NameClash::ASK: 1405 aArg.ReplaceExisting = sal_False; 1406 break; 1407 1408 default: 1409 aArg.ReplaceExisting = sal_False; 1410 OSL_ENSURE( sal_False, "Unknown nameclash directive!" ); 1411 break; 1412 } 1413 1414 rtl::OUString aDesiredName = createDesiredName( rContext.aArg ); 1415 1416 bool bRetry; 1417 do 1418 { 1419 bRetry = false; 1420 1421 try 1422 { 1423 ucb::Command aInsertCommand( 1424 rtl::OUString::createFromAscii( "insert" ), 1425 -1, 1426 uno::makeAny( aArg ) ); 1427 1428 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv ); 1429 } 1430 catch ( ucb::UnsupportedNameClashException const & exc ) 1431 { 1432 OSL_ENSURE( !aArg.ReplaceExisting, 1433 "BUG: UnsupportedNameClashException not allowed here!" ); 1434 1435 if (exc.NameClash != ucb::NameClash::ERROR) { 1436 OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" ); 1437 } 1438 1439 // No chance to solve name clashes, because I'm not able to detect 1440 // whether there is one. 1441 throw ucb::UnsupportedNameClashException( 1442 rtl::OUString::createFromAscii( 1443 "Unable to resolve name clashes, no chance to detect " 1444 "that there is one!" ), 1445 rContext.xProcessor, 1446 rContext.aArg.NameClash ); 1447 } 1448 catch ( ucb::NameClashException const & ) 1449 { 1450 // The 'insert' command throws a NameClashException if the parameter 1451 // ReplaceExisting of the command's argument was set to false and 1452 // there exists a resource with a clashing name in the target folder 1453 // of the operation. 1454 1455 // 'insert' command has no direct support for name clashes other 1456 // than ERROR ( ReplaceExisting == false ) and OVERWRITE 1457 // ( ReplaceExisting == true ). So we have to implement the 1458 // other name clash handling directives on top of the content. 1459 1460 // @@@ 'insert' command should be extended that it accepts a 1461 // name clash handling directive, exactly like 'transfer' command. 1462 1463 switch ( rContext.aArg.NameClash ) 1464 { 1465 case ucb::NameClash::OVERWRITE: 1466 { 1467 ucbhelper::cancelCommandExecution( 1468 uno::makeAny( 1469 ucb::UnsupportedNameClashException( 1470 rtl::OUString::createFromAscii( 1471 "BUG: insert + replace == true MUST NOT " 1472 "throw NameClashException." ), 1473 rContext.xProcessor, 1474 rContext.aArg.NameClash ) ), 1475 rContext.xOrigEnv ); 1476 // Unreachable 1477 } 1478 1479 case ucb::NameClash::ERROR: 1480 throw; 1481 1482 case ucb::NameClash::RENAME: 1483 { 1484 // "invent" a new valid title. 1485 handleNameClashRename( rContext, 1486 xNew, 1487 xCommandProcessorN, 1488 xCommandProcessorS, 1489 xInputStream ); 1490 break; 1491 } 1492 1493 case ucb::NameClash::ASK: 1494 { 1495 uno::Any aExc; 1496 rtl::OUString aNewTitle; 1497 NameClashContinuation eCont 1498 = interactiveNameClashResolve( 1499 rContext.xOrigEnv, // always use original environment! 1500 rContext.aArg.TargetURL, // target folder URL 1501 aDesiredName, 1502 aExc, 1503 aNewTitle ); 1504 1505 switch ( eCont ) 1506 { 1507 case NOT_HANDLED: 1508 // Not handled. 1509 cppu::throwException( aExc ); 1510 // break; 1511 1512 case UNKNOWN: 1513 // Handled, but not clear, how... 1514 // fall-thru intended. 1515 1516 case ABORT: 1517 throw ucb::CommandFailedException( 1518 rtl::OUString( 1519 RTL_CONSTASCII_USTRINGPARAM( 1520 "abort requested via interaction " 1521 "handler" ) ), 1522 uno::Reference< uno::XInterface >(), 1523 aExc ); 1524 // break; 1525 1526 case OVERWRITE: 1527 OSL_ENSURE( aArg.ReplaceExisting == sal_False, 1528 "Hu? ReplaceExisting already true?" 1529 ); 1530 aArg.ReplaceExisting = sal_True; 1531 bRetry = true; 1532 break; 1533 1534 case NEW_NAME: 1535 { 1536 // set new name -> set "Title" property... 1537 if ( setTitle( xCommandProcessorN, 1538 rContext.xEnv, 1539 aNewTitle ) ) 1540 { 1541 // remember suggested title... 1542 aDesiredName = aNewTitle; 1543 1544 // ... and try again. 1545 bRetry = true; 1546 } 1547 else 1548 { 1549 // error setting title. Abort. 1550 throw ucb::CommandFailedException( 1551 rtl::OUString( 1552 RTL_CONSTASCII_USTRINGPARAM( 1553 "error setting Title property!" 1554 ) ), 1555 uno::Reference< uno::XInterface >(), 1556 aExc ); 1557 } 1558 break; 1559 } 1560 } 1561 1562 OSL_ENSURE( bRetry, "bRetry must be true here!!!" ); 1563 } 1564 break; 1565 1566 case ucb::NameClash::KEEP: // deprecated 1567 default: 1568 { 1569 ucbhelper::cancelCommandExecution( 1570 uno::makeAny( 1571 ucb::UnsupportedNameClashException( 1572 rtl::OUString( 1573 RTL_CONSTASCII_USTRINGPARAM( 1574 "default action, don't know how to " 1575 "handle name clash" ) ), 1576 rContext.xProcessor, 1577 rContext.aArg.NameClash ) ), 1578 rContext.xOrigEnv ); 1579 // Unreachable 1580 } 1581 } 1582 } 1583 } 1584 while ( bRetry ); 1585 1586 ////////////////////////////////////////////////////////////////////// 1587 // 1588 // (6) Process children of source. 1589 // 1590 ////////////////////////////////////////////////////////////////////// 1591 1592 if ( xResultSet.is() ) 1593 { 1594 try 1595 { 1596 // Iterate over children... 1597 1598 uno::Reference< sdbc::XRow > xChildRow( 1599 xResultSet, uno::UNO_QUERY ); 1600 1601 if ( !xChildRow.is() ) 1602 { 1603 uno::Any aProps 1604 = uno::makeAny( 1605 beans::PropertyValue( 1606 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1607 "Uri")), 1608 -1, 1609 uno::makeAny(rContext.aArg.SourceURL), 1610 beans::PropertyState_DIRECT_VALUE)); 1611 ucbhelper::cancelCommandExecution( 1612 ucb::IOErrorCode_CANT_READ, 1613 uno::Sequence< uno::Any >(&aProps, 1), 1614 rContext.xOrigEnv, 1615 rtl::OUString::createFromAscii( 1616 "Unable to get properties from children of source!" ), 1617 rContext.xProcessor ); 1618 // Unreachable 1619 } 1620 1621 uno::Reference< ucb::XContentAccess > xChildAccess( 1622 xResultSet, uno::UNO_QUERY ); 1623 1624 if ( !xChildAccess.is() ) 1625 { 1626 uno::Any aProps 1627 = uno::makeAny( 1628 beans::PropertyValue( 1629 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1630 "Uri")), 1631 -1, 1632 uno::makeAny(rContext.aArg.SourceURL), 1633 beans::PropertyState_DIRECT_VALUE)); 1634 ucbhelper::cancelCommandExecution( 1635 ucb::IOErrorCode_CANT_READ, 1636 uno::Sequence< uno::Any >(&aProps, 1), 1637 rContext.xOrigEnv, 1638 rtl::OUString::createFromAscii( 1639 "Unable to get children of source!" ), 1640 rContext.xProcessor ); 1641 // Unreachable 1642 } 1643 1644 if ( xResultSet->first() ) 1645 { 1646 ucb::GlobalTransferCommandArgument aTransArg( 1647 rContext.aArg.Operation, // Operation 1648 rtl::OUString(), // SourceURL; filled later 1649 xNew->getIdentifier() 1650 ->getContentIdentifier(), // TargetURL 1651 rtl::OUString(), // NewTitle; 1652 rContext.aArg.NameClash ); // NameClash 1653 1654 TransferCommandContext aSubCtx( 1655 rContext.xSMgr, 1656 rContext.xProcessor, 1657 rContext.xEnv, 1658 rContext.xOrigEnv, 1659 aTransArg ); 1660 do 1661 { 1662 uno::Reference< ucb::XContent > xChild 1663 = xChildAccess->queryContent(); 1664 if ( xChild.is() ) 1665 { 1666 // Recursion! 1667 1668 aSubCtx.aArg.SourceURL 1669 = xChild->getIdentifier()->getContentIdentifier(); 1670 1671 globalTransfer_( aSubCtx, 1672 xChild, 1673 xNew, 1674 xChildRow ); 1675 } 1676 } 1677 while ( xResultSet->next() ); 1678 } 1679 } 1680 catch ( sdbc::SQLException const & ) 1681 { 1682 } 1683 } 1684 1685 try { 1686 uno::Reference< ucb::XCommandProcessor > xcp( 1687 xTarget, uno::UNO_QUERY ); 1688 1689 uno::Any aAny; 1690 uno::Reference< ucb::XCommandInfo > xci; 1691 if(xcp.is()) 1692 aAny = 1693 xcp->execute( 1694 ucb::Command( 1695 rtl::OUString::createFromAscii("getCommandInfo"), 1696 -1, 1697 uno::Any()), 1698 0, 1699 rContext.xEnv ); 1700 1701 const rtl::OUString cmdName = 1702 rtl::OUString::createFromAscii("flush"); 1703 if((aAny >>= xci) && xci->hasCommandByName(cmdName)) 1704 xcp->execute( 1705 ucb::Command( 1706 cmdName, 1707 -1, 1708 uno::Any()) , 1709 0, 1710 rContext.xEnv ); 1711 } 1712 catch( uno::Exception const & ) 1713 { 1714 } 1715 } 1716 1717 } /* namescpace */ 1718 1719 //========================================================================= 1720 // 1721 // UniversalContentBroker implementation ( XCommandProcessor commands ). 1722 // 1723 //========================================================================= 1724 1725 uno::Reference< ucb::XCommandInfo > 1726 UniversalContentBroker::getCommandInfo() 1727 { 1728 return uno::Reference< ucb::XCommandInfo >( new CommandProcessorInfo() ); 1729 } 1730 1731 //========================================================================= 1732 void UniversalContentBroker::globalTransfer( 1733 const ucb::GlobalTransferCommandArgument & rArg, 1734 const uno::Reference< ucb::XCommandEnvironment > & xEnv ) 1735 throw( uno::Exception ) 1736 { 1737 // Use own command environment with own interaction handler intercepting 1738 // some interaction requests that shall not be handled by the user-supplied 1739 // interaction handler. 1740 uno::Reference< ucb::XCommandEnvironment > xLocalEnv; 1741 if (xEnv.is()) 1742 { 1743 uno::Reference< beans::XPropertySet > const xProps( 1744 m_xSMgr, uno::UNO_QUERY_THROW ); 1745 uno::Reference< uno::XComponentContext > xCtx; 1746 xCtx.set( xProps->getPropertyValue( 1747 rtl::OUString( 1748 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), 1749 uno::UNO_QUERY_THROW ); 1750 1751 xLocalEnv.set( ucb::CommandEnvironment::create( 1752 xCtx, 1753 new InteractionHandlerProxy( xEnv->getInteractionHandler() ), 1754 xEnv->getProgressHandler() ) ); 1755 } 1756 1757 ////////////////////////////////////////////////////////////////////// 1758 // 1759 // (1) Try to transfer the content using 'transfer' command. 1760 // 1761 ////////////////////////////////////////////////////////////////////// 1762 1763 uno::Reference< ucb::XContent > xTarget; 1764 uno::Reference< ucb::XContentIdentifier > xId 1765 = createContentIdentifier( rArg.TargetURL ); 1766 if ( xId.is() ) 1767 { 1768 try 1769 { 1770 xTarget = queryContent( xId ); 1771 } 1772 catch ( ucb::IllegalIdentifierException const & ) 1773 { 1774 } 1775 } 1776 1777 if ( !xTarget.is() ) 1778 { 1779 uno::Any aProps 1780 = uno::makeAny(beans::PropertyValue( 1781 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1782 "Uri")), 1783 -1, 1784 uno::makeAny(rArg.TargetURL), 1785 beans::PropertyState_DIRECT_VALUE)); 1786 ucbhelper::cancelCommandExecution( 1787 ucb::IOErrorCode_CANT_READ, 1788 uno::Sequence< uno::Any >(&aProps, 1), 1789 xEnv, 1790 rtl::OUString::createFromAscii( 1791 "Can't instanciate target object!" ), 1792 this ); 1793 // Unreachable 1794 } 1795 1796 if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) || 1797 ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) ) 1798 { 1799 uno::Reference< ucb::XCommandProcessor > xCommandProcessor( 1800 xTarget, uno::UNO_QUERY ); 1801 if ( !xCommandProcessor.is() ) 1802 { 1803 uno::Any aProps 1804 = uno::makeAny( 1805 beans::PropertyValue( 1806 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1807 "Uri")), 1808 -1, 1809 uno::makeAny(rArg.TargetURL), 1810 beans::PropertyState_DIRECT_VALUE)); 1811 ucbhelper::cancelCommandExecution( 1812 ucb::IOErrorCode_CANT_READ, 1813 uno::Sequence< uno::Any >(&aProps, 1), 1814 xEnv, 1815 rtl::OUString::createFromAscii( 1816 "Target content is not a XCommandProcessor!" ), 1817 this ); 1818 // Unreachable 1819 } 1820 1821 ucb::TransferInfo aTransferArg( 1822 ( rArg.Operation 1823 == ucb::TransferCommandOperation_MOVE ), // MoveData 1824 rArg.SourceURL, // SourceURL 1825 rArg.NewTitle, // NewTitle 1826 rArg.NameClash ); // NameClash 1827 1828 bool bRetry; 1829 do 1830 { 1831 bRetry = false; 1832 1833 try 1834 { 1835 ucb::Command aCommand( 1836 rtl::OUString::createFromAscii( "transfer" ), // Name 1837 -1, // Handle 1838 uno::makeAny( aTransferArg ) ); // Argument 1839 1840 xCommandProcessor->execute( aCommand, 0, xLocalEnv ); 1841 1842 // Command succeeded. We're done. 1843 return; 1844 } 1845 catch ( ucb::InteractiveBadTransferURLException const & ) 1846 { 1847 // Source URL is not supported by target. Try to transfer 1848 // the content "manually". 1849 } 1850 catch ( ucb::UnsupportedCommandException const & ) 1851 { 1852 // 'transfer' command is not supported by commandprocessor. 1853 // Try to transfer manually. 1854 } 1855 catch ( ucb::UnsupportedNameClashException const & exc ) 1856 { 1857 OSL_ENSURE( aTransferArg.NameClash == exc.NameClash, 1858 "nameclash mismatch!" ); 1859 if ( exc.NameClash == ucb::NameClash::ASK ) 1860 { 1861 // Try to detect a name clash by invoking "transfer" with 1862 // NameClash::ERROR. 1863 try 1864 { 1865 ucb::TransferInfo aTransferArg1( 1866 aTransferArg.MoveData, 1867 aTransferArg.SourceURL, 1868 aTransferArg.NewTitle, 1869 ucb::NameClash::ERROR ); 1870 1871 ucb::Command aCommand1( 1872 rtl::OUString::createFromAscii( "transfer" ), 1873 -1, 1874 uno::makeAny( aTransferArg1 ) ); 1875 1876 xCommandProcessor->execute( aCommand1, 0, xLocalEnv ); 1877 1878 // Command succeeded. We're done. 1879 return; 1880 } 1881 catch ( ucb::UnsupportedNameClashException const & ) 1882 { 1883 // No chance to solve name clashes, because I'm not 1884 // able to detect whether there is one. 1885 throw exc; // Not just 'throw;'! 1886 } 1887 catch ( ucb::NameClashException const & ) 1888 { 1889 // There's a clash. Use interaction handler to solve it. 1890 1891 uno::Any aExc; 1892 rtl::OUString aNewTitle; 1893 NameClashContinuation eCont 1894 = interactiveNameClashResolve( 1895 xEnv, // always use original environment! 1896 rArg.TargetURL, // target folder URL 1897 createDesiredName( 1898 aTransferArg ), // clashing name 1899 aExc, 1900 aNewTitle ); 1901 1902 switch ( eCont ) 1903 { 1904 case NOT_HANDLED: 1905 // Not handled. 1906 cppu::throwException( aExc ); 1907 // break; 1908 1909 case UNKNOWN: 1910 // Handled, but not clear, how... 1911 // fall-thru intended. 1912 1913 case ABORT: 1914 throw ucb::CommandFailedException( 1915 rtl::OUString( 1916 RTL_CONSTASCII_USTRINGPARAM( 1917 "abort requested via interaction " 1918 "handler" ) ), 1919 uno::Reference< uno::XInterface >(), 1920 aExc ); 1921 // break; 1922 1923 case OVERWRITE: 1924 aTransferArg.NameClash 1925 = ucb::NameClash::OVERWRITE; 1926 bRetry = true; 1927 break; 1928 1929 case NEW_NAME: 1930 aTransferArg.NewTitle = aNewTitle; 1931 bRetry = true; 1932 break; 1933 } 1934 1935 OSL_ENSURE( bRetry, "bRetry must be true here!!!" ); 1936 } 1937 } 1938 else 1939 { 1940 throw; 1941 } 1942 } 1943 } 1944 while ( bRetry ); 1945 } 1946 1947 ////////////////////////////////////////////////////////////////////// 1948 // 1949 // (2) Try to transfer the content "manually". 1950 // 1951 ////////////////////////////////////////////////////////////////////// 1952 1953 uno::Reference< ucb::XContent > xSource; 1954 try 1955 { 1956 uno::Reference< ucb::XContentIdentifier > xId2 1957 = createContentIdentifier( rArg.SourceURL ); 1958 if ( xId2.is() ) 1959 xSource = queryContent( xId2 ); 1960 } 1961 catch ( ucb::IllegalIdentifierException const & ) 1962 { 1963 // Error handling via "if ( !xSource.is() )" below. 1964 } 1965 1966 if ( !xSource.is() ) 1967 { 1968 uno::Any aProps 1969 = uno::makeAny(beans::PropertyValue( 1970 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1971 "Uri")), 1972 -1, 1973 uno::makeAny(rArg.SourceURL), 1974 beans::PropertyState_DIRECT_VALUE)); 1975 ucbhelper::cancelCommandExecution( 1976 ucb::IOErrorCode_CANT_READ, 1977 uno::Sequence< uno::Any >(&aProps, 1), 1978 xEnv, 1979 rtl::OUString::createFromAscii( 1980 "Can't instanciate source object!" ), 1981 this ); 1982 // Unreachable 1983 } 1984 1985 uno::Reference< ucb::XCommandProcessor > xCommandProcessor( 1986 xSource, uno::UNO_QUERY ); 1987 if ( !xCommandProcessor.is() ) 1988 { 1989 uno::Any aProps 1990 = uno::makeAny(beans::PropertyValue( 1991 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 1992 "Uri")), 1993 -1, 1994 uno::makeAny(rArg.SourceURL), 1995 beans::PropertyState_DIRECT_VALUE)); 1996 ucbhelper::cancelCommandExecution( 1997 ucb::IOErrorCode_CANT_READ, 1998 uno::Sequence< uno::Any >(&aProps, 1), 1999 xEnv, 2000 rtl::OUString::createFromAscii( 2001 "Source content is not a XCommandProcessor!" ), 2002 this ); 2003 // Unreachable 2004 } 2005 2006 // Obtain interesting property values from source... 2007 2008 uno::Sequence< beans::Property > aProps( 4 ); 2009 2010 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); 2011 aProps[ 0 ].Handle = -1; /* unknown */ 2012 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); 2013 aProps[ 1 ].Handle = -1; /* unknown */ 2014 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" ); 2015 aProps[ 2 ].Handle = -1; /* unknown */ 2016 aProps[ 3 ].Name = rtl::OUString::createFromAscii( "BaseURI" ); 2017 aProps[ 3 ].Handle = -1; /* unknown */ 2018 2019 ucb::Command aGetPropsCommand( 2020 rtl::OUString::createFromAscii( "getPropertyValues" ), 2021 -1, 2022 uno::makeAny( aProps ) ); 2023 2024 uno::Reference< sdbc::XRow > xRow; 2025 xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow; 2026 2027 if ( !xRow.is() ) 2028 { 2029 uno::Any aProps2 2030 = uno::makeAny(beans::PropertyValue( 2031 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 2032 "Uri")), 2033 -1, 2034 uno::makeAny(rArg.SourceURL), 2035 beans::PropertyState_DIRECT_VALUE)); 2036 ucbhelper::cancelCommandExecution( 2037 ucb::IOErrorCode_CANT_READ, 2038 uno::Sequence< uno::Any >(&aProps2, 1), 2039 xEnv, 2040 rtl::OUString::createFromAscii( 2041 "Unable to get properties from source object!" ), 2042 this ); 2043 // Unreachable 2044 } 2045 2046 TransferCommandContext aTransferCtx( 2047 m_xSMgr, this, xLocalEnv, xEnv, rArg ); 2048 2049 if ( rArg.NewTitle.getLength() == 0 ) 2050 { 2051 // BaseURI: property is optional. 2052 rtl::OUString aBaseURI( xRow->getString( 4 ) ); 2053 if ( aBaseURI.getLength() ) 2054 { 2055 aTransferCtx.aArg.NewTitle 2056 = createDesiredName( aBaseURI, rtl::OUString() ); 2057 } 2058 } 2059 2060 // Do it! 2061 globalTransfer_( aTransferCtx, xSource, xTarget, xRow ); 2062 2063 ////////////////////////////////////////////////////////////////////// 2064 // 2065 // (3) Delete source, if operation is MOVE. 2066 // 2067 ////////////////////////////////////////////////////////////////////// 2068 2069 if ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) 2070 { 2071 try 2072 { 2073 ucb::Command aCommand( 2074 rtl::OUString::createFromAscii( "delete" ), // Name 2075 -1, // Handle 2076 uno::makeAny( sal_Bool( sal_True ) ) ); // Argument 2077 2078 xCommandProcessor->execute( aCommand, 0, xLocalEnv ); 2079 } 2080 catch ( uno::Exception const & ) 2081 { 2082 OSL_ENSURE( sal_False, "Cannot delete source object!" ); 2083 throw; 2084 } 2085 } 2086 } 2087