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