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:
UcbDataSink_Impl(UcbLockBytes * pLockBytes)89 UcbDataSink_Impl( UcbLockBytes* pLockBytes )
90 : m_xLockBytes( pLockBytes )
91 {}
92
getLockBytes(void)93 SvLockBytes* getLockBytes (void)
94 { return m_xLockBytes; }
95
96 // XActiveDataControl.
addListener(const Reference<XStreamListener> &)97 virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
removeListener(const Reference<XStreamListener> &)98 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
start(void)99 virtual void SAL_CALL start (void) throw(RuntimeException) {}
terminate(void)100 virtual void SAL_CALL terminate (void) throw(RuntimeException)
101 { m_xLockBytes->terminate_Impl(); }
102
103 // XActiveDataSink.
setInputStream(const Reference<XInputStream> & rxInputStream)104 virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException)
105 { m_xLockBytes->setInputStream_Impl (rxInputStream); }
getInputStream(void)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
UcbStreamer_Impl(UcbLockBytes * pLockBytes)120 UcbStreamer_Impl( UcbLockBytes* pLockBytes )
121 : m_xLockBytes( pLockBytes )
122 {}
123
124 // XActiveDataControl.
addListener(const Reference<XStreamListener> &)125 virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
removeListener(const Reference<XStreamListener> &)126 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
start(void)127 virtual void SAL_CALL start (void) throw(RuntimeException) {}
terminate(void)128 virtual void SAL_CALL terminate (void) throw(RuntimeException)
129 { m_xLockBytes->terminate_Impl(); }
130
131 // XActiveDataStreamer
setStream(const Reference<XStream> & aStream)132 virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException)
133 { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); }
getStream()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:
ProgressHandler_Impl(const Link & rLink)146 ProgressHandler_Impl( const Link& rLink )
147 : m_aProgress( rLink )
148 {}
149 // XProgressHandler
push(const Any &)150 virtual void SAL_CALL push(const Any & /*rStatus*/) throw (RuntimeException) {}
pop()151 virtual void SAL_CALL pop() throw (RuntimeException) {}
update(const Any &)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:
UcbTaskEnvironment(const Reference<XInteractionHandler> & rxInteractionHandler,const Reference<XProgressHandler> & rxProgressHandler)165 UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
166 const Reference< XProgressHandler>& rxProgressHandler )
167 : m_xInteractionHandler( rxInteractionHandler )
168 , m_xProgressHandler( rxProgressHandler )
169 {}
170
171
getInteractionHandler()172 virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException)
173 { return m_xInteractionHandler; }
174
getProgressHandler()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
UcbPropertiesChangeListener_Impl(UcbLockBytesRef rRef)188 UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
189 : m_xLockBytes( rRef )
190 {}
191
disposing(const EventObject &)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
propertiesChange(const Sequence<PropertyChangeEvent> & rEvent)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
ConditionRes(osl::Mutex & aMutex,Moderator & aModerator)302 ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
303 : salhelper::Condition(aMutex),
304 m_aModerator(aModerator)
305 {
306 }
307
308 protected:
309
applies() const310 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
ConditionRep(osl::Mutex & aMutex,Moderator & aModerator)343 ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
344 : salhelper::Condition(aMutex),
345 m_aModerator(aModerator)
346 {
347 }
348
349 protected:
350
applies() const351 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
getStream(void)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
getInputStream(void)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
ModeratorsActiveDataSink(Moderator & theModerator)482 ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
483 : m_aModerator(theModerator)
484 {
485 }
486
487
~ModeratorsActiveDataSink()488 ModeratorsActiveDataSink::~ModeratorsActiveDataSink()
489 {
490 }
491
492 // XActiveDataSink.
493 void SAL_CALL
setInputStream(const Reference<XInputStream> & rxInputStream)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
ModeratorsActiveDataStreamer(Moderator & theModerator)507 ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
508 Moderator &theModerator
509 )
510 : m_aModerator(theModerator)
511 {
512 }
513
514
~ModeratorsActiveDataStreamer()515 ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer()
516 {
517 }
518
519 // XActiveDataStreamer.
520 void SAL_CALL
setStream(const Reference<XStream> & rxStream)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
ModeratorsProgressHandler(Moderator & theModerator)580 ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator)
581 : m_aModerator(theModerator)
582 {
583 }
584
~ModeratorsProgressHandler()585 ModeratorsProgressHandler::~ModeratorsProgressHandler()
586 {
587 }
588
589
push(const Any & Status)590 void SAL_CALL ModeratorsProgressHandler::push( const Any& Status )
591 throw (
592 RuntimeException)
593 {
594 m_aModerator.push(Status);
595 }
596
597
update(const Any & Status)598 void SAL_CALL ModeratorsProgressHandler::update( const Any& Status )
599 throw (RuntimeException)
600 {
601 m_aModerator.update(Status);
602 }
603
604
pop()605 void SAL_CALL ModeratorsProgressHandler::pop( )
606 throw (RuntimeException)
607 {
608 m_aModerator.pop();
609 }
610
611
612
613
ModeratorsInteractionHandler(Moderator & aModerator)614 ModeratorsInteractionHandler::ModeratorsInteractionHandler(
615 Moderator &aModerator)
616 : m_aModerator(aModerator)
617 {
618 }
619
620
~ModeratorsInteractionHandler()621 ModeratorsInteractionHandler::~ModeratorsInteractionHandler()
622 {
623 }
624
625
626 void SAL_CALL
handle(const Reference<XInteractionRequest> & Request)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
Moderator(Reference<XContent> & xContent,Reference<XInteractionHandler> & xInteract,Reference<XProgressHandler> & xProgress,const Command & rArg)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
~Moderator()707 Moderator::~Moderator()
708 {
709 }
710
711
getResult(const sal_uInt32 milliSec)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
setReply(ReplyType aReplyType)733 void Moderator::setReply(ReplyType aReplyType )
734 {
735 salhelper::ConditionModifier aMod(m_aRep);
736 m_aReplyType = aReplyType;
737 }
738
739
handle(const Reference<XInteractionRequest> & Request)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
push(const Any & Status)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
update(const Any & Status)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
pop()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
setStream(const Reference<XStream> & aStream)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
setInputStream(const Reference<XInputStream> & rxInputStream)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
run()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
onTerminated()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
UCBOpenContentSync(UcbLockBytesRef xLockBytes,Reference<XContent> xContent,const Command & rArg,Reference<XInterface> xSink,Reference<XInteractionHandler> xInteract,Reference<XProgressHandler> xProgress,UcbLockBytesHandlerRef xHandler)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 */
_UCBOpenContentSync(UcbLockBytesRef xLockBytes,Reference<XContent> xContent,const Command & rArg,Reference<XInterface> xSink,Reference<XInteractionHandler> xInteract,Reference<XProgressHandler> xProgress,UcbLockBytesHandlerRef xHandler)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 //----------------------------------------------------------------------------
UcbLockBytes(UcbLockBytesHandler * pHandler)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 //----------------------------------------------------------------------------
~UcbLockBytes()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
getInputStream()1317 Reference < XInputStream > UcbLockBytes::getInputStream()
1318 {
1319 vos::OClearableGuard aGuard( m_aMutex );
1320 m_bDontClose = sal_True;
1321 return m_xInputStream;
1322 }
1323
getStream()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
setStream_Impl(const Reference<XStream> & aStream)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
setInputStream_Impl(const Reference<XInputStream> & rxInputStream,sal_Bool bSetXSeekable)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
SetStreamValid_Impl()1397 void UcbLockBytes::SetStreamValid_Impl()
1398 {
1399 m_bStreamValid = sal_True;
1400 if ( m_xInputStream.is() )
1401 m_aInitialized.set();
1402 }
1403
1404 //----------------------------------------------------------------------------
terminate_Impl()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 //----------------------------------------------------------------------------
SetSynchronMode(sal_Bool bSynchron)1422 void UcbLockBytes::SetSynchronMode (sal_Bool bSynchron)
1423 {
1424 SvLockBytes::SetSynchronMode (bSynchron);
1425 }
1426
1427 //----------------------------------------------------------------------------
ReadAt(sal_uLong nPos,void * pBuffer,sal_uLong nCount,sal_uLong * pRead) const1428 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 //----------------------------------------------------------------------------
WriteAt(sal_uLong nPos,const void * pBuffer,sal_uLong nCount,sal_uLong * pWritten)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 //----------------------------------------------------------------------------
Flush() const1532 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 //----------------------------------------------------------------------------
SetSize(sal_uLong nNewSize)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 //----------------------------------------------------------------------------
Stat(SvLockBytesStat * pStat,SvLockBytesStatFlag) const1585 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 //----------------------------------------------------------------------------
Cancel()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 //----------------------------------------------------------------------------
IMPL_LINK(UcbLockBytes,DataAvailHdl,void *,EMPTYARG)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
CreateInputLockBytes(const Reference<XInputStream> & xInputStream)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
CreateLockBytes(const Reference<XStream> & xStream)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
CreateLockBytes(const Reference<XContent> & xContent,const::rtl::OUString & rReferer,const::rtl::OUString & rMediaType,const Reference<XInputStream> & xPostData,const Reference<XInteractionHandler> & xInteractionHandler,UcbLockBytesHandler * pHandler)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
CreateLockBytes(const Reference<XContent> & xContent,const Sequence<PropertyValue> & rProps,StreamMode eOpenMode,const Reference<XInteractionHandler> & xInteractionHandler,UcbLockBytesHandler * pHandler)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