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