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*/) {}
removeListener(const Reference<XStreamListener> &)98 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) {}
start(void)99 virtual void SAL_CALL start (void) {}
terminate(void)100 virtual void SAL_CALL terminate (void)
101 { m_xLockBytes->terminate_Impl(); }
102
103 // XActiveDataSink.
setInputStream(const Reference<XInputStream> & rxInputStream)104 virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream)
105 { m_xLockBytes->setInputStream_Impl (rxInputStream); }
getInputStream(void)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
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*/) {}
removeListener(const Reference<XStreamListener> &)126 virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) {}
start(void)127 virtual void SAL_CALL start (void) {}
terminate(void)128 virtual void SAL_CALL terminate (void)
129 { m_xLockBytes->terminate_Impl(); }
130
131 // XActiveDataStreamer
setStream(const Reference<XStream> & aStream)132 virtual void SAL_CALL setStream( const Reference< XStream >& aStream )
133 { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); }
getStream()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:
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*/) {}
pop()151 virtual void SAL_CALL pop() {}
update(const Any &)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:
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()
173 { return m_xInteractionHandler; }
174
getProgressHandler()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
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*/) {}
193 virtual void SAL_CALL propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent);
194 };
195
propertiesChange(const Sequence<PropertyChangeEvent> & rEvent)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
ConditionRes(osl::Mutex & aMutex,Moderator & aModerator)298 ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
299 : salhelper::Condition(aMutex),
300 m_aModerator(aModerator)
301 {
302 }
303
304 protected:
305
applies() const306 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
ConditionRep(osl::Mutex & aMutex,Moderator & aModerator)339 ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
340 : salhelper::Condition(aMutex),
341 m_aModerator(aModerator)
342 {
343 }
344
345 protected:
346
applies() const347 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
getStream(void)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
getInputStream(void)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
ModeratorsActiveDataSink(Moderator & theModerator)468 ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
469 : m_aModerator(theModerator)
470 {
471 }
472
473
~ModeratorsActiveDataSink()474 ModeratorsActiveDataSink::~ModeratorsActiveDataSink()
475 {
476 }
477
478 // XActiveDataSink.
479 void SAL_CALL
setInputStream(const Reference<XInputStream> & rxInputStream)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
ModeratorsActiveDataStreamer(Moderator & theModerator)490 ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
491 Moderator &theModerator
492 )
493 : m_aModerator(theModerator)
494 {
495 }
496
497
~ModeratorsActiveDataStreamer()498 ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer()
499 {
500 }
501
502 // XActiveDataStreamer.
503 void SAL_CALL
setStream(const Reference<XStream> & rxStream)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
ModeratorsProgressHandler(Moderator & theModerator)555 ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator)
556 : m_aModerator(theModerator)
557 {
558 }
559
~ModeratorsProgressHandler()560 ModeratorsProgressHandler::~ModeratorsProgressHandler()
561 {
562 }
563
564
push(const Any & Status)565 void SAL_CALL ModeratorsProgressHandler::push( const Any& Status )
566 {
567 m_aModerator.push(Status);
568 }
569
570
update(const Any & Status)571 void SAL_CALL ModeratorsProgressHandler::update( const Any& Status )
572 {
573 m_aModerator.update(Status);
574 }
575
576
pop()577 void SAL_CALL ModeratorsProgressHandler::pop( )
578 {
579 m_aModerator.pop();
580 }
581
582
583
584
ModeratorsInteractionHandler(Moderator & aModerator)585 ModeratorsInteractionHandler::ModeratorsInteractionHandler(
586 Moderator &aModerator)
587 : m_aModerator(aModerator)
588 {
589 }
590
591
~ModeratorsInteractionHandler()592 ModeratorsInteractionHandler::~ModeratorsInteractionHandler()
593 {
594 }
595
596
597 void SAL_CALL
handle(const Reference<XInteractionRequest> & Request)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
Moderator(Reference<XContent> & xContent,Reference<XInteractionHandler> & xInteract,Reference<XProgressHandler> & xProgress,const Command & rArg)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
~Moderator()671 Moderator::~Moderator()
672 {
673 }
674
675
getResult(const sal_uInt32 milliSec)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
setReply(ReplyType aReplyType)697 void Moderator::setReply(ReplyType aReplyType )
698 {
699 salhelper::ConditionModifier aMod(m_aRep);
700 m_aReplyType = aReplyType;
701 }
702
703
handle(const Reference<XInteractionRequest> & Request)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
push(const Any & Status)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
update(const Any & Status)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
pop()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
setStream(const Reference<XStream> & aStream)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
setInputStream(const Reference<XInputStream> & rxInputStream)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
run()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
onTerminated()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
UCBOpenContentSync(UcbLockBytesRef xLockBytes,Reference<XContent> xContent,const Command & rArg,Reference<XInterface> xSink,Reference<XInteractionHandler> xInteract,Reference<XProgressHandler> xProgress,UcbLockBytesHandlerRef xHandler)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 */
_UCBOpenContentSync(UcbLockBytesRef xLockBytes,Reference<XContent> xContent,const Command & rArg,Reference<XInterface> xSink,Reference<XInteractionHandler> xInteract,Reference<XProgressHandler> xProgress,UcbLockBytesHandlerRef xHandler)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 //----------------------------------------------------------------------------
UcbLockBytes(UcbLockBytesHandler * pHandler)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 //----------------------------------------------------------------------------
~UcbLockBytes()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
getInputStream()1281 Reference < XInputStream > UcbLockBytes::getInputStream()
1282 {
1283 vos::OClearableGuard aGuard( m_aMutex );
1284 m_bDontClose = sal_True;
1285 return m_xInputStream;
1286 }
1287
getStream()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
setStream_Impl(const Reference<XStream> & aStream)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
setInputStream_Impl(const Reference<XInputStream> & rxInputStream,sal_Bool bSetXSeekable)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
SetStreamValid_Impl()1361 void UcbLockBytes::SetStreamValid_Impl()
1362 {
1363 m_bStreamValid = sal_True;
1364 if ( m_xInputStream.is() )
1365 m_aInitialized.set();
1366 }
1367
1368 //----------------------------------------------------------------------------
terminate_Impl()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 //----------------------------------------------------------------------------
SetSynchronMode(sal_Bool bSynchron)1386 void UcbLockBytes::SetSynchronMode (sal_Bool bSynchron)
1387 {
1388 SvLockBytes::SetSynchronMode (bSynchron);
1389 }
1390
1391 //----------------------------------------------------------------------------
ReadAt(sal_uLong nPos,void * pBuffer,sal_uLong nCount,sal_uLong * pRead) const1392 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 //----------------------------------------------------------------------------
WriteAt(sal_uLong nPos,const void * pBuffer,sal_uLong nCount,sal_uLong * pWritten)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 //----------------------------------------------------------------------------
Flush() const1496 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 //----------------------------------------------------------------------------
SetSize(sal_uLong nNewSize)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 //----------------------------------------------------------------------------
Stat(SvLockBytesStat * pStat,SvLockBytesStatFlag) const1549 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 //----------------------------------------------------------------------------
Cancel()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 //----------------------------------------------------------------------------
IMPL_LINK(UcbLockBytes,DataAvailHdl,void *,EMPTYARG)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
CreateInputLockBytes(const Reference<XInputStream> & xInputStream)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
CreateLockBytes(const Reference<XStream> & xStream)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
CreateLockBytes(const Reference<XContent> & xContent,const::rtl::OUString & rReferer,const::rtl::OUString & rMediaType,const Reference<XInputStream> & xPostData,const Reference<XInteractionHandler> & xInteractionHandler,UcbLockBytesHandler * pHandler)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
CreateLockBytes(const Reference<XContent> & xContent,const Sequence<PropertyValue> & rProps,StreamMode eOpenMode,const Reference<XInteractionHandler> & xInteractionHandler,UcbLockBytesHandler * pHandler)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