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