1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_unotools.hxx" 30 31 #include <unotools/ucblockbytes.hxx> 32 #include <comphelper/processfactory.hxx> 33 #include <salhelper/condition.hxx> 34 #ifndef _OSL_THREAD_HXX_ 35 #include <osl/thread.hxx> 36 #endif 37 #include <tools/urlobj.hxx> 38 #include <ucbhelper/interactionrequest.hxx> 39 #include <com/sun/star/task/XInteractionAbort.hpp> 40 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> 41 #include <com/sun/star/ucb/CommandFailedException.hpp> 42 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> 43 #ifndef _COM_SUN_STAR_UCB_INTERACTIVEIODEXCEPTION_HPP_ 44 #include <com/sun/star/ucb/InteractiveIOException.hpp> 45 #endif 46 #include <com/sun/star/io/XActiveDataStreamer.hpp> 47 #include <com/sun/star/ucb/DocumentHeaderField.hpp> 48 #include <com/sun/star/ucb/XCommandInfo.hpp> 49 #include <com/sun/star/ucb/XCommandProcessor.hpp> 50 #include <com/sun/star/task/XInteractionHandler.hpp> 51 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 52 #include <com/sun/star/ucb/PostCommandArgument2.hpp> 53 #include <com/sun/star/ucb/OpenMode.hpp> 54 #include <com/sun/star/beans/Property.hpp> 55 #include <com/sun/star/beans/PropertyValue.hpp> 56 #include <com/sun/star/beans/XPropertiesChangeNotifier.hpp> 57 #include <com/sun/star/beans/XPropertiesChangeListener.hpp> 58 #include <com/sun/star/sdbc/XRow.hpp> 59 #include <com/sun/star/io/XActiveDataSink.hpp> 60 #include <com/sun/star/io/XActiveDataControl.hpp> 61 #include <com/sun/star/io/XSeekable.hpp> 62 #include <cppuhelper/implbase1.hxx> 63 #include <cppuhelper/implbase2.hxx> 64 #include <tools/inetmsg.hxx> 65 #include <com/sun/star/io/XTruncate.hpp> 66 #include <com/sun/star/lang/IllegalArgumentException.hpp> 67 68 #include <comphelper/storagehelper.hxx> 69 70 #include <ucbhelper/contentbroker.hxx> 71 #include <ucbhelper/content.hxx> 72 73 using namespace ::com::sun::star::uno; 74 using namespace ::com::sun::star::io; 75 using namespace ::com::sun::star::uno; 76 using namespace ::com::sun::star::ucb; 77 using namespace ::com::sun::star::task; 78 using namespace ::com::sun::star::lang; 79 using namespace ::com::sun::star::beans; 80 81 82 namespace utl 83 { 84 85 /** 86 Helper class for getting a XInputStream when opening a content 87 */ 88 class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink > 89 { 90 UcbLockBytesRef m_xLockBytes; 91 92 public: 93 UcbDataSink_Impl( UcbLockBytes* pLockBytes ) 94 : m_xLockBytes( pLockBytes ) 95 {} 96 97 SvLockBytes* getLockBytes (void) 98 { return m_xLockBytes; } 99 100 // XActiveDataControl. 101 virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} 102 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} 103 virtual void SAL_CALL start (void) throw(RuntimeException) {} 104 virtual void SAL_CALL terminate (void) throw(RuntimeException) 105 { m_xLockBytes->terminate_Impl(); } 106 107 // XActiveDataSink. 108 virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException) 109 { m_xLockBytes->setInputStream_Impl (rxInputStream); } 110 virtual Reference<XInputStream> SAL_CALL getInputStream (void) throw(RuntimeException) 111 { return m_xLockBytes->getInputStream_Impl(); } 112 }; 113 114 /** 115 Helper class for getting a XStream when opening a content 116 */ 117 class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl > 118 { 119 Reference < XStream > m_xStream; 120 UcbLockBytesRef m_xLockBytes; 121 122 public: 123 124 UcbStreamer_Impl( UcbLockBytes* pLockBytes ) 125 : m_xLockBytes( pLockBytes ) 126 {} 127 128 // XActiveDataControl. 129 virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} 130 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {} 131 virtual void SAL_CALL start (void) throw(RuntimeException) {} 132 virtual void SAL_CALL terminate (void) throw(RuntimeException) 133 { m_xLockBytes->terminate_Impl(); } 134 135 // XActiveDataStreamer 136 virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException) 137 { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); } 138 virtual Reference< XStream > SAL_CALL getStream() throw(RuntimeException) 139 { return m_xStream; } 140 }; 141 142 /** 143 Helper class for progress handling while executing UCB commands 144 */ 145 class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler > 146 { 147 Link m_aProgress; 148 149 public: 150 ProgressHandler_Impl( const Link& rLink ) 151 : m_aProgress( rLink ) 152 {} 153 // XProgressHandler 154 virtual void SAL_CALL push(const Any & /*rStatus*/) throw (RuntimeException) {} 155 virtual void SAL_CALL pop() throw (RuntimeException) {} 156 virtual void SAL_CALL update(const Any & /*rStatus*/) throw (RuntimeException) 157 { if ( m_aProgress.IsSet() ) m_aProgress.Call( 0 ); } 158 }; 159 160 /** 161 Helper class for managing interactions and progress when executing UCB commands 162 */ 163 class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment > 164 { 165 Reference< XInteractionHandler > m_xInteractionHandler; 166 Reference< XProgressHandler > m_xProgressHandler; 167 168 public: 169 UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler, 170 const Reference< XProgressHandler>& rxProgressHandler ) 171 : m_xInteractionHandler( rxInteractionHandler ) 172 , m_xProgressHandler( rxProgressHandler ) 173 {} 174 175 176 virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException) 177 { return m_xInteractionHandler; } 178 179 virtual Reference<XProgressHandler> SAL_CALL getProgressHandler() throw (RuntimeException) 180 { return m_xProgressHandler; } 181 }; 182 183 184 /** 185 Helper class for property change notifies when executing UCB commands 186 */ 187 class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener > 188 { 189 public: 190 UcbLockBytesRef m_xLockBytes; 191 192 UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef ) 193 : m_xLockBytes( rRef ) 194 {} 195 196 virtual void SAL_CALL disposing ( const EventObject &/*rEvent*/) throw(RuntimeException) {} 197 virtual void SAL_CALL propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException); 198 }; 199 200 void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException) 201 { 202 sal_Int32 i, n = rEvent.getLength(); 203 for (i = 0; i < n; i++) 204 { 205 PropertyChangeEvent evt (rEvent[i]); 206 if (evt.PropertyName == ::rtl::OUString::createFromAscii ("DocumentHeader")) 207 { 208 Sequence<DocumentHeaderField> aHead; 209 if (evt.NewValue >>= aHead) 210 { 211 sal_Int32 k, m = aHead.getLength(); 212 for (k = 0; k < m; k++) 213 { 214 String aName( aHead[k].Name ); 215 String aValue( aHead[k].Value ); 216 217 if (aName.CompareIgnoreCaseToAscii("Expires") == COMPARE_EQUAL) 218 { 219 DateTime aExpires (0, 0); 220 if (INetRFC822Message::ParseDateField (aValue, aExpires)) 221 { 222 aExpires.ConvertToLocalTime(); 223 m_xLockBytes->SetExpireDate_Impl( aExpires ); 224 } 225 } 226 } 227 } 228 229 m_xLockBytes->SetStreamValid_Impl(); 230 } 231 else if (evt.PropertyName == rtl::OUString::createFromAscii ("PresentationURL")) 232 { 233 ::rtl::OUString aUrl; 234 if (evt.NewValue >>= aUrl) 235 { 236 ::rtl::OUString aBad (::rtl::OUString::createFromAscii ("private:")); 237 if (!(aUrl.compareTo (aBad, aBad.getLength()) == 0)) 238 { 239 // URL changed (Redirection). 240 m_xLockBytes->SetRealURL_Impl( aUrl ); 241 } 242 } 243 } 244 else if (evt.PropertyName == ::rtl::OUString::createFromAscii ("MediaType")) 245 { 246 ::rtl::OUString aContentType; 247 if (evt.NewValue >>= aContentType) 248 m_xLockBytes->SetContentType_Impl( aContentType ); 249 } 250 } 251 } 252 253 254 255 class Moderator 256 : public osl::Thread 257 { 258 // usage restriction: 259 // It might be possible, that the call to the interactionhandler and/or 260 // progresshandler is done asynchrounsly, while the 'execute' simply 261 // returns. This would imply that these class must be refcounted !!! 262 263 public: 264 265 Moderator( 266 Reference < XContent >& xContent, 267 Reference < XInteractionHandler >& xInteract, 268 Reference < XProgressHandler >& xProgress, 269 const Command& rArg 270 ) 271 throw( 272 ContentCreationException, 273 RuntimeException 274 ); 275 276 ~Moderator(); 277 278 279 enum ResultType { 280 NORESULT, 281 282 INTERACTIONREQUEST, // reply expected 283 284 PROGRESSPUSH, 285 PROGRESSUPDATE, 286 PROGRESSPOP, 287 288 INPUTSTREAM, 289 STREAM, 290 291 RESULT, 292 TIMEDOUT, 293 COMMANDABORTED, 294 COMMANDFAILED, 295 INTERACTIVEIO, 296 UNSUPPORTED, 297 GENERAL 298 }; 299 300 301 class ConditionRes 302 : public salhelper::Condition 303 { 304 public: 305 306 ConditionRes(osl::Mutex& aMutex,Moderator& aModerator) 307 : salhelper::Condition(aMutex), 308 m_aModerator(aModerator) 309 { 310 } 311 312 protected: 313 314 bool applies() const { 315 return m_aModerator.m_aResultType != NORESULT; 316 } 317 318 private: 319 320 Moderator& m_aModerator; 321 }; 322 323 324 struct Result { 325 ResultType type; 326 Any result; 327 sal_Int32 ioErrorCode; 328 }; 329 330 331 Result getResult(const sal_uInt32 milliSec); 332 333 334 enum ReplyType { 335 NOREPLY, 336 EXIT, 337 RETRY, 338 REQUESTHANDLED 339 }; 340 341 342 class ConditionRep 343 : public salhelper::Condition 344 { 345 public: 346 347 ConditionRep(osl::Mutex& aMutex,Moderator& aModerator) 348 : salhelper::Condition(aMutex), 349 m_aModerator(aModerator) 350 { 351 } 352 353 protected: 354 355 bool applies() const { 356 return m_aModerator.m_aReplyType != NOREPLY; 357 } 358 359 private: 360 361 Moderator& m_aModerator; 362 }; 363 364 void setReply(ReplyType); 365 366 367 void handle( const Reference<XInteractionRequest >& Request ); 368 369 void push( const Any& Status ); 370 371 void update( const Any& Status ); 372 373 void pop( ); 374 375 void setStream(const Reference< XStream >& aStream); 376 377 void setInputStream(const Reference<XInputStream> &rxInputStream); 378 379 380 protected: 381 382 virtual void SAL_CALL run(); 383 384 virtual void SAL_CALL onTerminated(); 385 386 private: 387 388 osl::Mutex m_aMutex; 389 390 friend class ConditionRes; 391 392 ConditionRes m_aRes; 393 ResultType m_aResultType; 394 sal_Int32 m_nIOErrorCode; 395 Any m_aResult; 396 397 friend class ConditionRep; 398 399 ConditionRep m_aRep; 400 ReplyType m_aReplyType; 401 402 Command m_aArg; 403 ::ucbhelper::Content m_aContent; 404 }; 405 406 407 class ModeratorsActiveDataStreamer 408 : public ::cppu::WeakImplHelper1<XActiveDataStreamer> 409 { 410 public: 411 412 ModeratorsActiveDataStreamer(Moderator &theModerator); 413 414 ~ModeratorsActiveDataStreamer(); 415 416 // XActiveDataStreamer 417 virtual void SAL_CALL 418 setStream( 419 const Reference< XStream >& aStream 420 ) 421 throw( 422 RuntimeException 423 ); 424 425 virtual Reference<XStream> SAL_CALL 426 getStream ( 427 void 428 ) throw( 429 RuntimeException 430 ) 431 { 432 osl::MutexGuard aGuard(m_aMutex); 433 return m_xStream; 434 } 435 436 437 private: 438 439 Moderator& m_aModerator; 440 441 osl::Mutex m_aMutex; 442 Reference<XStream> m_xStream; 443 }; 444 445 446 447 class ModeratorsActiveDataSink 448 : public ::cppu::WeakImplHelper1<XActiveDataSink> 449 { 450 public: 451 452 ModeratorsActiveDataSink(Moderator &theModerator); 453 454 ~ModeratorsActiveDataSink(); 455 456 // XActiveDataSink. 457 virtual void SAL_CALL 458 setInputStream ( 459 const Reference<XInputStream> &rxInputStream 460 ) 461 throw( 462 RuntimeException 463 ); 464 465 virtual Reference<XInputStream> SAL_CALL 466 getInputStream ( 467 void 468 ) throw( 469 RuntimeException 470 ) 471 { 472 osl::MutexGuard aGuard(m_aMutex); 473 return m_xStream; 474 } 475 476 477 private: 478 479 Moderator& m_aModerator; 480 osl::Mutex m_aMutex; 481 Reference<XInputStream> m_xStream; 482 }; 483 484 485 486 ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator) 487 : m_aModerator(theModerator) 488 { 489 } 490 491 492 ModeratorsActiveDataSink::~ModeratorsActiveDataSink() 493 { 494 } 495 496 // XActiveDataSink. 497 void SAL_CALL 498 ModeratorsActiveDataSink::setInputStream ( 499 const Reference<XInputStream> &rxInputStream 500 ) 501 throw( 502 RuntimeException 503 ) 504 { 505 m_aModerator.setInputStream(rxInputStream); 506 osl::MutexGuard aGuard(m_aMutex); 507 m_xStream = rxInputStream; 508 } 509 510 511 ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer( 512 Moderator &theModerator 513 ) 514 : m_aModerator(theModerator) 515 { 516 } 517 518 519 ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer() 520 { 521 } 522 523 // XActiveDataStreamer. 524 void SAL_CALL 525 ModeratorsActiveDataStreamer::setStream ( 526 const Reference<XStream> &rxStream 527 ) 528 throw( 529 RuntimeException 530 ) 531 { 532 m_aModerator.setStream(rxStream); 533 osl::MutexGuard aGuard(m_aMutex); 534 m_xStream = rxStream; 535 } 536 537 538 539 class ModeratorsInteractionHandler 540 : public ::cppu::WeakImplHelper1<XInteractionHandler> 541 { 542 public: 543 544 ModeratorsInteractionHandler(Moderator &theModerator); 545 546 ~ModeratorsInteractionHandler(); 547 548 virtual void SAL_CALL 549 handle( const Reference<XInteractionRequest >& Request ) 550 throw (RuntimeException); 551 552 private: 553 554 Moderator& m_aModerator; 555 }; 556 557 558 class ModeratorsProgressHandler 559 : public ::cppu::WeakImplHelper1<XProgressHandler> 560 { 561 public: 562 563 ModeratorsProgressHandler(Moderator &theModerator); 564 565 ~ModeratorsProgressHandler(); 566 567 virtual void SAL_CALL push( const Any& Status ) 568 throw ( 569 RuntimeException); 570 571 virtual void SAL_CALL update( const Any& Status ) 572 throw (RuntimeException); 573 574 virtual void SAL_CALL pop( ) 575 throw (RuntimeException); 576 577 578 private: 579 580 Moderator& m_aModerator; 581 }; 582 583 584 ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator) 585 : m_aModerator(theModerator) 586 { 587 } 588 589 ModeratorsProgressHandler::~ModeratorsProgressHandler() 590 { 591 } 592 593 594 void SAL_CALL ModeratorsProgressHandler::push( const Any& Status ) 595 throw ( 596 RuntimeException) 597 { 598 m_aModerator.push(Status); 599 } 600 601 602 void SAL_CALL ModeratorsProgressHandler::update( const Any& Status ) 603 throw (RuntimeException) 604 { 605 m_aModerator.update(Status); 606 } 607 608 609 void SAL_CALL ModeratorsProgressHandler::pop( ) 610 throw (RuntimeException) 611 { 612 m_aModerator.pop(); 613 } 614 615 616 617 618 ModeratorsInteractionHandler::ModeratorsInteractionHandler( 619 Moderator &aModerator) 620 : m_aModerator(aModerator) 621 { 622 } 623 624 625 ModeratorsInteractionHandler::~ModeratorsInteractionHandler() 626 { 627 } 628 629 630 void SAL_CALL 631 ModeratorsInteractionHandler::handle( 632 const Reference<XInteractionRequest >& Request 633 ) 634 throw ( 635 RuntimeException 636 ) 637 { 638 // wakes up the mainthread 639 m_aModerator.handle(Request); 640 } 641 642 643 644 645 Moderator::Moderator( 646 Reference < XContent >& xContent, 647 Reference < XInteractionHandler >& xInteract, 648 Reference < XProgressHandler >& xProgress, 649 const Command& rArg 650 ) 651 throw( 652 ::com::sun::star::ucb::ContentCreationException, 653 ::com::sun::star::uno::RuntimeException 654 ) 655 : m_aMutex(), 656 657 m_aRes(m_aMutex,*this), 658 m_aResultType(NORESULT), 659 m_nIOErrorCode(0), 660 m_aResult(), 661 662 m_aRep(m_aMutex,*this), 663 m_aReplyType(NOREPLY), 664 665 m_aArg(rArg), 666 m_aContent( 667 xContent, 668 new UcbTaskEnvironment( 669 xInteract.is() ? new ModeratorsInteractionHandler(*this) : 0, 670 xProgress.is() ? new ModeratorsProgressHandler(*this) : 0 671 )) 672 { 673 // now exchange the whole data sink stuff 674 // with a thread safe version 675 676 Reference<XInterface> *pxSink = NULL; 677 678 PostCommandArgument2 aPostArg; 679 OpenCommandArgument2 aOpenArg; 680 681 int dec(2); 682 if(m_aArg.Argument >>= aPostArg) { 683 pxSink = &aPostArg.Sink; 684 dec = 0; 685 } 686 else if(m_aArg.Argument >>= aOpenArg) { 687 pxSink = &aOpenArg.Sink; 688 dec = 1; 689 } 690 691 if(dec ==2) 692 throw ContentCreationException(); 693 694 Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY); 695 if(xActiveSink.is()) 696 *pxSink = Reference<XInterface>( 697 (cppu::OWeakObject*)new ModeratorsActiveDataSink(*this)); 698 699 Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY ); 700 if ( xStreamer.is() ) 701 *pxSink = Reference<XInterface>( 702 (cppu::OWeakObject*)new ModeratorsActiveDataStreamer(*this)); 703 704 if(dec == 0) 705 m_aArg.Argument <<= aPostArg; 706 else if(dec == 1) 707 m_aArg.Argument <<= aOpenArg; 708 } 709 710 711 Moderator::~Moderator() 712 { 713 } 714 715 716 Moderator::Result Moderator::getResult(const sal_uInt32 milliSec) 717 { 718 Result ret; 719 try { 720 salhelper::ConditionWaiter aWaiter(m_aRes,milliSec); 721 ret.type = m_aResultType; 722 ret.result = m_aResult; 723 ret.ioErrorCode = m_nIOErrorCode; 724 725 // reset 726 m_aResultType = NORESULT; 727 } 728 catch(const salhelper::ConditionWaiter::timedout&) 729 { 730 ret.type = TIMEDOUT; 731 } 732 733 return ret; 734 } 735 736 737 void Moderator::setReply(ReplyType aReplyType ) 738 { 739 salhelper::ConditionModifier aMod(m_aRep); 740 m_aReplyType = aReplyType; 741 } 742 743 744 void Moderator::handle( const Reference<XInteractionRequest >& Request ) 745 { 746 ReplyType aReplyType; 747 748 do { 749 { 750 salhelper::ConditionModifier aMod(m_aRes); 751 m_aResultType = INTERACTIONREQUEST; 752 m_aResult <<= Request; 753 } 754 755 { 756 salhelper::ConditionWaiter aWait(m_aRep); 757 aReplyType = m_aReplyType; 758 759 // reset 760 m_aReplyType = NOREPLY; 761 } 762 763 if(aReplyType == EXIT) { 764 Sequence<Reference<XInteractionContinuation> > aSeq( 765 Request->getContinuations()); 766 for(sal_Int32 i = 0; i < aSeq.getLength(); ++i) { 767 Reference<XInteractionAbort> aRef(aSeq[i],UNO_QUERY); 768 if(aRef.is()) { 769 aRef->select(); 770 } 771 } 772 773 // resignal the exitcondition 774 setReply(EXIT); 775 break; 776 } 777 } while(aReplyType != REQUESTHANDLED); 778 } 779 780 781 782 void Moderator::push( const Any& Status ) 783 { 784 { 785 salhelper::ConditionModifier aMod(m_aRes); 786 m_aResultType = PROGRESSPUSH; 787 m_aResult = Status; 788 } 789 ReplyType aReplyType; 790 { 791 salhelper::ConditionWaiter aWait(m_aRep); 792 aReplyType = m_aReplyType; 793 m_aReplyType = NOREPLY; 794 } 795 if(aReplyType == EXIT) 796 setReply(EXIT); 797 } 798 799 800 void Moderator::update( const Any& Status ) 801 { 802 { 803 salhelper::ConditionModifier aMod(m_aRes); 804 m_aResultType = PROGRESSUPDATE; 805 m_aResult = Status; 806 } 807 ReplyType aReplyType; 808 { 809 salhelper::ConditionWaiter aWait(m_aRep); 810 aReplyType = m_aReplyType; 811 m_aReplyType = NOREPLY; 812 } 813 if(aReplyType == EXIT) 814 setReply(EXIT); 815 } 816 817 818 void Moderator::pop( ) 819 { 820 { 821 salhelper::ConditionModifier aMod(m_aRes); 822 m_aResultType = PROGRESSPOP; 823 } 824 ReplyType aReplyType; 825 { 826 salhelper::ConditionWaiter aWait(m_aRep); 827 aReplyType = m_aReplyType; 828 m_aReplyType = NOREPLY; 829 } 830 if(aReplyType == EXIT) 831 setReply(EXIT); 832 } 833 834 835 void Moderator::setStream(const Reference< XStream >& aStream) 836 { 837 { 838 salhelper::ConditionModifier aMod(m_aRes); 839 m_aResultType = STREAM; 840 m_aResult <<= aStream; 841 } 842 ReplyType aReplyType; 843 { 844 salhelper::ConditionWaiter aWait(m_aRep); 845 aReplyType = m_aReplyType; 846 m_aReplyType = NOREPLY; 847 } 848 if(aReplyType == EXIT) 849 setReply(EXIT); 850 } 851 852 853 void Moderator::setInputStream(const Reference<XInputStream> &rxInputStream) 854 { 855 { 856 salhelper::ConditionModifier aMod(m_aRes); 857 m_aResultType = INPUTSTREAM; 858 m_aResult <<= rxInputStream; 859 } 860 ReplyType aReplyType; 861 { 862 salhelper::ConditionWaiter aWait(m_aRep); 863 aReplyType = m_aReplyType; 864 m_aReplyType = NOREPLY; 865 } 866 if(aReplyType == EXIT) 867 setReply(EXIT); 868 } 869 870 871 872 void SAL_CALL Moderator::run() 873 { 874 ResultType aResultType; 875 Any aResult; 876 sal_Int32 nIOErrorCode = 0; 877 878 try 879 { 880 aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument); 881 aResultType = RESULT; 882 } 883 catch ( CommandAbortedException ) 884 { 885 aResultType = COMMANDABORTED; 886 } 887 catch ( CommandFailedException ) 888 { 889 aResultType = COMMANDFAILED; 890 } 891 catch ( InteractiveIOException& r ) 892 { 893 nIOErrorCode = r.Code; 894 aResultType = INTERACTIVEIO; 895 } 896 catch ( UnsupportedDataSinkException& ) 897 { 898 aResultType = UNSUPPORTED; 899 } 900 catch ( Exception ) 901 { 902 aResultType = GENERAL; 903 } 904 905 { 906 salhelper::ConditionModifier aMod(m_aRes); 907 m_aResultType = aResultType; 908 m_aResult = aResult; 909 m_nIOErrorCode = nIOErrorCode; 910 } 911 } 912 913 914 915 void SAL_CALL Moderator::onTerminated() 916 { 917 { 918 salhelper::ConditionWaiter aWaiter(m_aRep); 919 } 920 delete this; 921 } 922 923 924 /** 925 Function for opening UCB contents synchronously, 926 but with handled timeout; 927 */ 928 929 static sal_Bool _UCBOpenContentSync( 930 UcbLockBytesRef xLockBytes, 931 Reference < XContent > xContent, 932 const Command& rArg, 933 Reference < XInterface > xSink, 934 Reference < XInteractionHandler > xInteract, 935 Reference < XProgressHandler > xProgress, 936 UcbLockBytesHandlerRef xHandler ); 937 938 939 static sal_Bool UCBOpenContentSync( 940 UcbLockBytesRef xLockBytes, 941 Reference < XContent > xContent, 942 const Command& rArg, 943 Reference < XInterface > xSink, 944 Reference < XInteractionHandler > xInteract, 945 Reference < XProgressHandler > xProgress, 946 UcbLockBytesHandlerRef xHandler ) 947 { 948 // http protocol must be handled in a special way: 949 // during the opening process the input stream may change 950 // only the last inputstream after notifying the document 951 // headers is valid 952 953 Reference<XContentIdentifier> xContId( 954 xContent.is() ? xContent->getIdentifier() : 0 ); 955 956 rtl::OUString aScheme; 957 if(xContId.is()) 958 aScheme = xContId->getContentProviderScheme(); 959 960 // now determine wether we use a timeout or not; 961 if( ! aScheme.equalsIgnoreAsciiCaseAscii("http") && 962 ! aScheme.equalsIgnoreAsciiCaseAscii("https") && 963 ! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") && 964 ! aScheme.equalsIgnoreAsciiCaseAscii("ftp")) 965 return _UCBOpenContentSync( 966 xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler); 967 968 if ( (aScheme.compareToAscii( "http" ) != COMPARE_EQUAL) || 969 (aScheme.compareToAscii( "https" ) != COMPARE_EQUAL) ) 970 xLockBytes->SetStreamValid_Impl(); 971 972 Reference< XPropertiesChangeListener > xListener; 973 Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY); 974 if(xProps.is()) { 975 xListener = 976 new UcbPropertiesChangeListener_Impl(xLockBytes); 977 xProps->addPropertiesChangeListener( 978 Sequence< ::rtl::OUString >(), 979 xListener); 980 } 981 982 Any aResult; 983 bool bException(false); 984 bool bAborted(false); 985 bool bResultAchieved(false); 986 987 Moderator* pMod = 0; 988 try { 989 pMod = new Moderator(xContent,xInteract,xProgress,rArg); 990 pMod->create(); 991 } catch(const ContentCreationException&) { 992 bResultAchieved = bException = true; 993 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 994 } 995 996 sal_uInt32 nTimeout(5000); // initially 5000 milliSec 997 while(!bResultAchieved) { 998 999 Moderator::Result res; 1000 // try to get the result for with timeout 1001 res = pMod->getResult(nTimeout); 1002 1003 switch(res.type) { 1004 case Moderator::PROGRESSPUSH: 1005 { 1006 if(xProgress.is()) 1007 xProgress->push(res.result); 1008 pMod->setReply(Moderator::REQUESTHANDLED); 1009 break; 1010 } 1011 case Moderator::PROGRESSUPDATE: 1012 { 1013 if(xProgress.is()) 1014 xProgress->update(res.result); 1015 pMod->setReply(Moderator::REQUESTHANDLED); 1016 break; 1017 } 1018 case Moderator::PROGRESSPOP: 1019 { 1020 if(xProgress.is()) 1021 xProgress->pop(); 1022 pMod->setReply(Moderator::REQUESTHANDLED); 1023 break; 1024 } 1025 case Moderator::STREAM: 1026 { 1027 Reference<XStream> result; 1028 if(res.result >>= result) { 1029 Reference < XActiveDataStreamer > xStreamer( 1030 xSink, UNO_QUERY 1031 ); 1032 1033 if(xStreamer.is()) 1034 xStreamer->setStream(result); 1035 } 1036 pMod->setReply(Moderator::REQUESTHANDLED); 1037 break; 1038 } 1039 case Moderator::INPUTSTREAM: 1040 { 1041 Reference<XInputStream> result; 1042 res.result >>= result; 1043 Reference < XActiveDataSink > xActiveSink( 1044 xSink, UNO_QUERY 1045 ); 1046 1047 if(xActiveSink.is()) 1048 xActiveSink->setInputStream(result); 1049 pMod->setReply(Moderator::REQUESTHANDLED); 1050 break; 1051 } 1052 case Moderator::TIMEDOUT: 1053 { 1054 Reference<XInteractionRetry> xRet; 1055 if(xInteract.is()) { 1056 InteractiveNetworkConnectException aExcep; 1057 INetURLObject aURL( 1058 xContId.is() ? 1059 xContId->getContentIdentifier() : 1060 rtl::OUString() ); 1061 aExcep.Server = aURL.GetHost(); 1062 aExcep.Classification = InteractionClassification_ERROR; 1063 aExcep.Message = 1064 rtl::OUString( 1065 RTL_CONSTASCII_USTRINGPARAM( 1066 "server not responding after five seconds")); 1067 Any request; 1068 request <<= aExcep; 1069 ucbhelper::InteractionRequest *ir = 1070 new ucbhelper::InteractionRequest(request); 1071 Reference<XInteractionRequest> xIR(ir); 1072 Sequence<Reference<XInteractionContinuation> > aSeq(2); 1073 ucbhelper::InteractionRetry *retryP = 1074 new ucbhelper::InteractionRetry(ir); 1075 aSeq[0] = retryP; 1076 ucbhelper::InteractionAbort *abortP = 1077 new ucbhelper::InteractionAbort(ir); 1078 aSeq[1] = abortP; 1079 1080 ir->setContinuations(aSeq); 1081 xInteract->handle(xIR); 1082 rtl::Reference< ucbhelper::InteractionContinuation > ref 1083 = ir->getSelection(); 1084 if(ref.is()) { 1085 Reference<XInterface> xInt(ref.get()); 1086 xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY); 1087 } 1088 } 1089 1090 if(!xRet.is()) { 1091 bAborted = true; 1092 xLockBytes->SetError(ERRCODE_ABORT); 1093 } 1094 1095 break; 1096 } 1097 case Moderator::INTERACTIONREQUEST: 1098 { 1099 Reference<XInteractionRequest> Request; 1100 res.result >>= Request; 1101 xInteract->handle(Request); 1102 pMod->setReply(Moderator::REQUESTHANDLED); 1103 break; 1104 } 1105 case Moderator::RESULT: 1106 { 1107 bResultAchieved = true; 1108 aResult = res.result; 1109 break; 1110 } 1111 case Moderator::COMMANDABORTED: 1112 { 1113 bAborted = true; 1114 xLockBytes->SetError( ERRCODE_ABORT ); 1115 break; 1116 } 1117 case Moderator::COMMANDFAILED: 1118 { 1119 bAborted = true; 1120 xLockBytes->SetError( ERRCODE_ABORT ); 1121 break; 1122 } 1123 case Moderator::INTERACTIVEIO: 1124 { 1125 bException = true; 1126 if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED || 1127 res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION ) 1128 xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED ); 1129 else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING ) 1130 xLockBytes->SetError( ERRCODE_IO_NOTEXISTS ); 1131 else if ( res.ioErrorCode == IOErrorCode_CANT_READ ) 1132 xLockBytes->SetError( ERRCODE_IO_CANTREAD ); 1133 else 1134 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1135 break; 1136 } 1137 case Moderator::UNSUPPORTED: 1138 { 1139 bException = true; 1140 xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED ); 1141 break; 1142 } 1143 default: 1144 { 1145 bException = true; 1146 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1147 break; 1148 } 1149 } 1150 1151 bResultAchieved |= bException; 1152 bResultAchieved |= bAborted; 1153 if(nTimeout == 5000) nTimeout *= 2; 1154 } 1155 1156 if(pMod) pMod->setReply(Moderator::EXIT); 1157 1158 if ( bAborted || bException ) 1159 { 1160 if( xHandler.Is() ) 1161 xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes ); 1162 1163 Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY ); 1164 if ( xActiveSink.is() ) 1165 xActiveSink->setInputStream( Reference < XInputStream >() ); 1166 1167 Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY ); 1168 if ( xStreamer.is() ) 1169 xStreamer->setStream( Reference < XStream >() ); 1170 } 1171 1172 Reference < XActiveDataControl > xControl( xSink, UNO_QUERY ); 1173 if ( xControl.is() ) 1174 xControl->terminate(); 1175 1176 if ( xProps.is() ) 1177 xProps->removePropertiesChangeListener( 1178 Sequence< ::rtl::OUString >(), 1179 xListener ); 1180 1181 return ( bAborted || bException ); 1182 } 1183 1184 /** 1185 Function for opening UCB contents synchronously 1186 */ 1187 static sal_Bool _UCBOpenContentSync( 1188 UcbLockBytesRef xLockBytes, 1189 Reference < XContent > xContent, 1190 const Command& rArg, 1191 Reference < XInterface > xSink, 1192 Reference < XInteractionHandler > xInteract, 1193 Reference < XProgressHandler > xProgress, 1194 UcbLockBytesHandlerRef xHandler ) 1195 { 1196 ::ucbhelper::Content aContent( xContent, new UcbTaskEnvironment( xInteract, xProgress ) ); 1197 Reference < XContentIdentifier > xIdent = xContent->getIdentifier(); 1198 ::rtl::OUString aScheme = xIdent->getContentProviderScheme(); 1199 1200 // http protocol must be handled in a special way: during the opening process the input stream may change 1201 // only the last inputstream after notifying the document headers is valid 1202 if ( aScheme.compareToAscii("http") != COMPARE_EQUAL ) 1203 xLockBytes->SetStreamValid_Impl(); 1204 1205 Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes ); 1206 Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY ); 1207 if ( xProps.is() ) 1208 xProps->addPropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener ); 1209 1210 Any aResult; 1211 bool bException = false; 1212 bool bAborted = false; 1213 1214 try 1215 { 1216 aResult = aContent.executeCommand( rArg.Name, rArg.Argument ); 1217 } 1218 catch ( CommandAbortedException ) 1219 { 1220 bAborted = true; 1221 xLockBytes->SetError( ERRCODE_ABORT ); 1222 } 1223 catch ( CommandFailedException ) 1224 { 1225 bAborted = true; 1226 xLockBytes->SetError( ERRCODE_ABORT ); 1227 } 1228 catch ( InteractiveIOException& r ) 1229 { 1230 bException = true; 1231 if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION ) 1232 xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED ); 1233 else if ( r.Code == IOErrorCode_NOT_EXISTING ) 1234 xLockBytes->SetError( ERRCODE_IO_NOTEXISTS ); 1235 else if ( r.Code == IOErrorCode_CANT_READ ) 1236 xLockBytes->SetError( ERRCODE_IO_CANTREAD ); 1237 else 1238 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1239 } 1240 catch ( UnsupportedDataSinkException& ) 1241 { 1242 bException = true; 1243 xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED ); 1244 } 1245 catch ( Exception ) 1246 { 1247 bException = true; 1248 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1249 } 1250 1251 if ( bAborted || bException ) 1252 { 1253 if( xHandler.Is() ) 1254 xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes ); 1255 1256 Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY ); 1257 if ( xActiveSink.is() ) 1258 xActiveSink->setInputStream( Reference < XInputStream >() ); 1259 1260 Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY ); 1261 if ( xStreamer.is() ) 1262 xStreamer->setStream( Reference < XStream >() ); 1263 } 1264 1265 Reference < XActiveDataControl > xControl( xSink, UNO_QUERY ); 1266 if ( xControl.is() ) 1267 xControl->terminate(); 1268 1269 1270 if ( xProps.is() ) 1271 xProps->removePropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener ); 1272 1273 return ( bAborted || bException ); 1274 } 1275 1276 1277 //---------------------------------------------------------------------------- 1278 UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler ) 1279 : m_xInputStream (NULL) 1280 , m_pCommandThread( NULL ) 1281 , m_xHandler( pHandler ) 1282 , m_nError( ERRCODE_NONE ) 1283 , m_bTerminated (sal_False) 1284 , m_bDontClose( sal_False ) 1285 , m_bStreamValid (sal_False) 1286 { 1287 SetSynchronMode( sal_True ); 1288 } 1289 1290 //---------------------------------------------------------------------------- 1291 UcbLockBytes::~UcbLockBytes() 1292 { 1293 if ( !m_bDontClose ) 1294 { 1295 if ( m_xInputStream.is() ) 1296 { 1297 try 1298 { 1299 m_xInputStream->closeInput(); 1300 } 1301 catch ( RuntimeException const & ) 1302 {} 1303 catch ( IOException const & ) 1304 {} 1305 } 1306 } 1307 1308 if ( !m_xInputStream.is() && m_xOutputStream.is() ) 1309 { 1310 try 1311 { 1312 m_xOutputStream->closeOutput(); 1313 } 1314 catch ( RuntimeException const & ) 1315 {} 1316 catch ( IOException const & ) 1317 {} 1318 } 1319 } 1320 1321 Reference < XInputStream > UcbLockBytes::getInputStream() 1322 { 1323 vos::OClearableGuard aGuard( m_aMutex ); 1324 m_bDontClose = sal_True; 1325 return m_xInputStream; 1326 } 1327 1328 Reference < XStream > UcbLockBytes::getStream() 1329 { 1330 vos::OClearableGuard aGuard( m_aMutex ); 1331 Reference < XStream > xStream( m_xSeekable, UNO_QUERY ); 1332 if ( xStream.is() ) 1333 m_bDontClose = sal_True; 1334 return xStream; 1335 } 1336 1337 //---------------------------------------------------------------------------- 1338 1339 sal_Bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream ) 1340 { 1341 vos::OClearableGuard aGuard( m_aMutex ); 1342 if ( aStream.is() ) 1343 { 1344 m_xOutputStream = aStream->getOutputStream(); 1345 setInputStream_Impl( aStream->getInputStream(), sal_False ); 1346 m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY ); 1347 } 1348 else 1349 { 1350 m_xOutputStream = Reference < XOutputStream >(); 1351 setInputStream_Impl( Reference < XInputStream >() ); 1352 } 1353 1354 return m_xInputStream.is(); 1355 } 1356 1357 sal_Bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, sal_Bool bSetXSeekable ) 1358 { 1359 sal_Bool bRet = sal_False; 1360 1361 try 1362 { 1363 vos::OClearableGuard aGuard( m_aMutex ); 1364 1365 if ( !m_bDontClose && m_xInputStream.is() ) 1366 m_xInputStream->closeInput(); 1367 1368 m_xInputStream = rxInputStream; 1369 1370 if( bSetXSeekable ) 1371 { 1372 m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY ); 1373 if( !m_xSeekable.is() && rxInputStream.is() ) 1374 { 1375 Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 1376 Reference< XOutputStream > rxTempOut = Reference < XOutputStream > ( 1377 xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 1378 UNO_QUERY ); 1379 1380 if( rxTempOut.is() ) 1381 { 1382 ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut ); 1383 m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY ); 1384 m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY ); 1385 } 1386 } 1387 } 1388 1389 bRet = m_xInputStream.is(); 1390 // aGuard.clear(); 1391 } 1392 catch( Exception& ) 1393 {} 1394 1395 if ( m_bStreamValid && m_xInputStream.is() ) 1396 m_aInitialized.set(); 1397 1398 return bRet; 1399 } 1400 1401 void UcbLockBytes::SetStreamValid_Impl() 1402 { 1403 m_bStreamValid = sal_True; 1404 if ( m_xInputStream.is() ) 1405 m_aInitialized.set(); 1406 } 1407 1408 //---------------------------------------------------------------------------- 1409 void UcbLockBytes::terminate_Impl() 1410 { 1411 m_bTerminated = sal_True; 1412 m_aInitialized.set(); 1413 m_aTerminated.set(); 1414 1415 if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() ) 1416 { 1417 DBG_ERROR("No InputStream, but no error set!" ); 1418 SetError( ERRCODE_IO_NOTEXISTS ); 1419 } 1420 1421 if ( m_xHandler.Is() ) 1422 m_xHandler->Handle( UcbLockBytesHandler::DONE, this ); 1423 } 1424 1425 //---------------------------------------------------------------------------- 1426 void UcbLockBytes::SetSynchronMode (sal_Bool bSynchron) 1427 { 1428 SvLockBytes::SetSynchronMode (bSynchron); 1429 } 1430 1431 //---------------------------------------------------------------------------- 1432 ErrCode UcbLockBytes::ReadAt ( sal_uLong nPos, void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const 1433 { 1434 if ( IsSynchronMode() ) 1435 { 1436 UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this ); 1437 pThis->m_aInitialized.wait(); 1438 } 1439 1440 Reference <XInputStream> xStream = getInputStream_Impl(); 1441 if ( !xStream.is() ) 1442 { 1443 if ( m_bTerminated ) 1444 return ERRCODE_IO_CANTREAD; 1445 else 1446 return ERRCODE_IO_PENDING; 1447 } 1448 1449 if ( pRead ) 1450 *pRead = 0; 1451 1452 Reference <XSeekable> xSeekable = getSeekable_Impl(); 1453 if ( !xSeekable.is() ) 1454 return ERRCODE_IO_CANTREAD; 1455 1456 try 1457 { 1458 xSeekable->seek( nPos ); 1459 } 1460 catch ( IOException ) 1461 { 1462 return ERRCODE_IO_CANTSEEK; 1463 } 1464 catch (com::sun::star::lang::IllegalArgumentException) 1465 { 1466 return ERRCODE_IO_CANTSEEK; 1467 } 1468 1469 Sequence<sal_Int8> aData; 1470 sal_Int32 nSize; 1471 1472 nCount = VOS_MIN(nCount, 0x7FFFFFFF); 1473 try 1474 { 1475 if ( !m_bTerminated && !IsSynchronMode() ) 1476 { 1477 sal_uInt64 nLen = xSeekable->getLength(); 1478 if ( nPos + nCount > nLen ) 1479 return ERRCODE_IO_PENDING; 1480 } 1481 1482 nSize = xStream->readBytes( aData, sal_Int32(nCount) ); 1483 } 1484 catch (IOException) 1485 { 1486 return ERRCODE_IO_CANTREAD; 1487 } 1488 1489 rtl_copyMemory (pBuffer, aData.getConstArray(), nSize); 1490 if (pRead) 1491 *pRead = sal_uLong(nSize); 1492 1493 return ERRCODE_NONE; 1494 } 1495 1496 //---------------------------------------------------------------------------- 1497 ErrCode UcbLockBytes::WriteAt ( sal_uLong nPos, const void *pBuffer, sal_uLong nCount, sal_uLong *pWritten) 1498 { 1499 if ( pWritten ) 1500 *pWritten = 0; 1501 1502 DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" ); 1503 DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" ); 1504 1505 Reference <XSeekable> xSeekable = getSeekable_Impl(); 1506 Reference <XOutputStream> xOutputStream = getOutputStream_Impl(); 1507 if ( !xOutputStream.is() || !xSeekable.is() ) 1508 return ERRCODE_IO_CANTWRITE; 1509 1510 try 1511 { 1512 xSeekable->seek( nPos ); 1513 } 1514 catch ( IOException ) 1515 { 1516 return ERRCODE_IO_CANTSEEK; 1517 } 1518 1519 sal_Int8* pData = (sal_Int8*) pBuffer; 1520 Sequence<sal_Int8> aData( pData, nCount ); 1521 try 1522 { 1523 xOutputStream->writeBytes( aData ); 1524 if ( pWritten ) 1525 *pWritten = nCount; 1526 } 1527 catch ( Exception ) 1528 { 1529 return ERRCODE_IO_CANTWRITE; 1530 } 1531 1532 return ERRCODE_NONE; 1533 } 1534 1535 //---------------------------------------------------------------------------- 1536 ErrCode UcbLockBytes::Flush() const 1537 { 1538 Reference <XOutputStream > xOutputStream = getOutputStream_Impl(); 1539 if ( !xOutputStream.is() ) 1540 return ERRCODE_IO_CANTWRITE; 1541 1542 try 1543 { 1544 xOutputStream->flush(); 1545 } 1546 catch( Exception ) 1547 { 1548 return ERRCODE_IO_CANTWRITE; 1549 } 1550 1551 return ERRCODE_NONE; 1552 } 1553 1554 //---------------------------------------------------------------------------- 1555 ErrCode UcbLockBytes::SetSize (sal_uLong nNewSize) 1556 { 1557 SvLockBytesStat aStat; 1558 Stat( &aStat, (SvLockBytesStatFlag) 0 ); 1559 sal_uLong nSize = aStat.nSize; 1560 1561 if ( nSize > nNewSize ) 1562 { 1563 Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY ); 1564 if ( xTrunc.is() ) 1565 { 1566 xTrunc->truncate(); 1567 nSize = 0; 1568 } 1569 else { 1570 DBG_WARNING("Not truncatable!"); 1571 } 1572 } 1573 1574 if ( nSize < nNewSize ) 1575 { 1576 sal_uLong nDiff = nNewSize-nSize, nCount=0; 1577 sal_uInt8* pBuffer = new sal_uInt8[ nDiff ]; 1578 memset(pBuffer, 0, nDiff); // initialize for enhanced security 1579 WriteAt( nSize, pBuffer, nDiff, &nCount ); 1580 delete[] pBuffer; 1581 if ( nCount != nDiff ) 1582 return ERRCODE_IO_CANTWRITE; 1583 } 1584 1585 return ERRCODE_NONE; 1586 } 1587 1588 //---------------------------------------------------------------------------- 1589 ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const 1590 { 1591 if ( IsSynchronMode() ) 1592 { 1593 UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this ); 1594 pThis->m_aInitialized.wait(); 1595 } 1596 1597 if (!pStat) 1598 return ERRCODE_IO_INVALIDPARAMETER; 1599 1600 Reference <XInputStream> xStream = getInputStream_Impl(); 1601 Reference <XSeekable> xSeekable = getSeekable_Impl(); 1602 1603 if ( !xStream.is() ) 1604 { 1605 if ( m_bTerminated ) 1606 return ERRCODE_IO_INVALIDACCESS; 1607 else 1608 return ERRCODE_IO_PENDING; 1609 } 1610 else if( !xSeekable.is() ) 1611 return ERRCODE_IO_CANTTELL; 1612 1613 try 1614 { 1615 pStat->nSize = sal_uLong(xSeekable->getLength()); 1616 } 1617 catch (IOException) 1618 { 1619 return ERRCODE_IO_CANTTELL; 1620 } 1621 1622 return ERRCODE_NONE; 1623 } 1624 1625 //---------------------------------------------------------------------------- 1626 void UcbLockBytes::Cancel() 1627 { 1628 // is alive only for compatibility reasons 1629 OSL_ENSURE( m_bTerminated, "UcbLockBytes is not thread safe so it can be used only syncronously!\n" ); 1630 } 1631 1632 //---------------------------------------------------------------------------- 1633 IMPL_LINK( UcbLockBytes, DataAvailHdl, void*, EMPTYARG ) 1634 { 1635 if ( hasInputStream_Impl() && m_xHandler.Is() ) 1636 m_xHandler->Handle( UcbLockBytesHandler::DATA_AVAILABLE, this ); 1637 1638 return 0; 1639 } 1640 1641 UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream ) 1642 { 1643 if( !xInputStream.is() ) 1644 return NULL;; 1645 1646 UcbLockBytesRef xLockBytes = new UcbLockBytes(); 1647 xLockBytes->setDontClose_Impl(); 1648 xLockBytes->setInputStream_Impl( xInputStream ); 1649 xLockBytes->terminate_Impl(); 1650 return xLockBytes; 1651 } 1652 1653 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream ) 1654 { 1655 if( !xStream.is() ) 1656 return NULL;; 1657 1658 UcbLockBytesRef xLockBytes = new UcbLockBytes(); 1659 xLockBytes->setDontClose_Impl(); 1660 xLockBytes->setStream_Impl( xStream ); 1661 xLockBytes->terminate_Impl(); 1662 return xLockBytes; 1663 } 1664 1665 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const ::rtl::OUString& rReferer, const ::rtl::OUString& rMediaType, 1666 const Reference < XInputStream >& xPostData, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler ) 1667 { 1668 if( !xContent.is() ) 1669 return NULL;; 1670 1671 UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler ); 1672 xLockBytes->SetSynchronMode( !pHandler ); 1673 Reference< XActiveDataControl > xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes ); 1674 1675 PostCommandArgument2 aArgument; 1676 aArgument.Source = xPostData; 1677 aArgument.Sink = xSink; 1678 aArgument.MediaType = rMediaType; 1679 aArgument.Referer = rReferer; 1680 1681 Command aCommand; 1682 aCommand.Name = ::rtl::OUString::createFromAscii ("post"); 1683 aCommand.Argument <<= aArgument; 1684 1685 Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) ); 1686 1687 sal_Bool bError = UCBOpenContentSync( xLockBytes, 1688 xContent, 1689 aCommand, 1690 xSink, 1691 xInteractionHandler, 1692 xProgressHdl, 1693 pHandler ); 1694 1695 if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) ) 1696 { 1697 DBG_ERROR("No InputStream, but no error set!" ); 1698 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1699 } 1700 1701 return xLockBytes; 1702 } 1703 1704 UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps, 1705 StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler ) 1706 { 1707 if( !xContent.is() ) 1708 return NULL;; 1709 1710 UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler ); 1711 xLockBytes->SetSynchronMode( !pHandler ); 1712 Reference< XActiveDataControl > xSink; 1713 if ( eOpenMode & STREAM_WRITE ) 1714 xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes ); 1715 else 1716 xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes ); 1717 1718 if ( rProps.getLength() ) 1719 { 1720 Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY ); 1721 Command aCommand; 1722 aCommand.Name = ::rtl::OUString::createFromAscii("setPropertyValues"); 1723 aCommand.Handle = -1; /* unknown */ 1724 aCommand.Argument <<= rProps; 1725 xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() ); 1726 } 1727 1728 OpenCommandArgument2 aArgument; 1729 aArgument.Sink = xSink; 1730 aArgument.Mode = OpenMode::DOCUMENT; 1731 1732 Command aCommand; 1733 aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("open") ); 1734 aCommand.Argument <<= aArgument; 1735 1736 Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) ); 1737 1738 sal_Bool bError = UCBOpenContentSync( xLockBytes, 1739 xContent, 1740 aCommand, 1741 xSink, 1742 xInteractionHandler, 1743 xProgressHdl, 1744 pHandler ); 1745 1746 if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) ) 1747 { 1748 DBG_ERROR("No InputStream, but no error set!" ); 1749 xLockBytes->SetError( ERRCODE_IO_GENERAL ); 1750 } 1751 1752 return xLockBytes; 1753 } 1754 1755 } 1756