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