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 0 : class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink >
72 : {
73 : UcbLockBytesRef m_xLockBytes;
74 :
75 : public:
76 0 : UcbDataSink_Impl( UcbLockBytes* pLockBytes )
77 0 : : m_xLockBytes( pLockBytes )
78 0 : {}
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 0 : virtual void SAL_CALL terminate (void) throw(RuntimeException, std::exception) SAL_OVERRIDE
85 0 : { m_xLockBytes->terminate_Impl(); }
86 :
87 : // XActiveDataSink.
88 0 : virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException, std::exception) SAL_OVERRIDE
89 0 : { 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 0 : class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl >
98 : {
99 : Reference < XStream > m_xStream;
100 : UcbLockBytesRef m_xLockBytes;
101 :
102 : public:
103 0 : UcbStreamer_Impl( UcbLockBytes* pLockBytes )
104 0 : : m_xLockBytes( pLockBytes )
105 0 : {}
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 0 : virtual void SAL_CALL terminate (void) throw(RuntimeException, std::exception) SAL_OVERRIDE
112 0 : { m_xLockBytes->terminate_Impl(); }
113 :
114 : // XActiveDataStreamer
115 0 : virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException, std::exception) SAL_OVERRIDE
116 0 : { 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 0 : class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler >
125 : {
126 : Link m_aProgress;
127 :
128 : public:
129 0 : ProgressHandler_Impl( const Link& rLink )
130 0 : : m_aProgress( rLink )
131 0 : {}
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 0 : class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment >
143 : {
144 : Reference< XInteractionHandler > m_xInteractionHandler;
145 : Reference< XProgressHandler > m_xProgressHandler;
146 :
147 : public:
148 0 : UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
149 : const Reference< XProgressHandler>& rxProgressHandler )
150 : : m_xInteractionHandler( rxInteractionHandler )
151 0 : , m_xProgressHandler( rxProgressHandler )
152 0 : {}
153 :
154 0 : virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException, std::exception) SAL_OVERRIDE
155 0 : { 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 0 : class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener >
165 : {
166 : public:
167 : UcbLockBytesRef m_xLockBytes;
168 :
169 0 : UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
170 0 : : m_xLockBytes( rRef )
171 0 : {}
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 : ResultType aResultType;
786 0 : Any aResult;
787 0 : sal_Int32 nIOErrorCode = 0;
788 :
789 : try
790 : {
791 0 : aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument);
792 0 : aResultType = RESULT;
793 : }
794 0 : catch (const CommandAbortedException&)
795 : {
796 0 : aResultType = COMMANDABORTED;
797 : }
798 0 : catch (const CommandFailedException&)
799 : {
800 0 : aResultType = COMMANDFAILED;
801 : }
802 0 : catch (const InteractiveIOException& r)
803 : {
804 0 : nIOErrorCode = r.Code;
805 0 : aResultType = INTERACTIVEIO;
806 : }
807 0 : catch (const UnsupportedDataSinkException &)
808 : {
809 0 : aResultType = UNSUPPORTED;
810 : }
811 0 : catch (const Exception&)
812 : {
813 0 : aResultType = GENERAL;
814 : }
815 :
816 : {
817 0 : salhelper::ConditionModifier aMod(m_aRes);
818 0 : m_aResultType = aResultType;
819 0 : m_aResult = aResult;
820 0 : m_nIOErrorCode = nIOErrorCode;
821 0 : }
822 0 : }
823 :
824 0 : void SAL_CALL Moderator::onTerminated()
825 : {
826 : {
827 0 : salhelper::ConditionWaiter aWaiter(m_aRep);
828 : }
829 0 : delete this;
830 0 : }
831 :
832 : /**
833 : Function for opening UCB contents synchronously,
834 : but with handled timeout;
835 : */
836 : static bool _UCBOpenContentSync(
837 : UcbLockBytesRef xLockBytes,
838 : Reference < XContent > xContent,
839 : const Command& rArg,
840 : Reference < XInterface > xSink,
841 : Reference < XInteractionHandler > xInteract,
842 : Reference < XProgressHandler > xProgress,
843 : UcbLockBytesHandlerRef xHandler );
844 :
845 0 : static bool UCBOpenContentSync(
846 : UcbLockBytesRef xLockBytes,
847 : Reference < XContent > xContent,
848 : const Command& rArg,
849 : Reference < XInterface > xSink,
850 : Reference < XInteractionHandler > xInteract,
851 : Reference < XProgressHandler > xProgress,
852 : UcbLockBytesHandlerRef xHandler )
853 : {
854 : // http protocol must be handled in a special way:
855 : // during the opening process the input stream may change
856 : // only the last inputstream after notifying the document
857 : // headers is valid
858 :
859 : Reference<XContentIdentifier> xContId(
860 0 : xContent.is() ? xContent->getIdentifier() : 0 );
861 :
862 0 : OUString aScheme;
863 0 : if(xContId.is())
864 0 : aScheme = xContId->getContentProviderScheme();
865 :
866 : // now determine whether we use a timeout or not;
867 0 : if( ! aScheme.equalsIgnoreAsciiCase("http") &&
868 0 : ! aScheme.equalsIgnoreAsciiCase("https") &&
869 0 : ! aScheme.equalsIgnoreAsciiCase("vnd.sun.star.webdav") &&
870 0 : ! aScheme.equalsIgnoreAsciiCase("ftp"))
871 : return _UCBOpenContentSync(
872 0 : xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler);
873 :
874 0 : if ( (aScheme.compareToAscii( "http" ) != 0) ||
875 0 : (aScheme.compareToAscii( "https" ) != 0) )
876 0 : xLockBytes->SetStreamValid_Impl();
877 :
878 0 : Reference< XPropertiesChangeListener > xListener;
879 0 : Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY);
880 0 : if(xProps.is()) {
881 0 : xListener =
882 0 : new UcbPropertiesChangeListener_Impl(xLockBytes);
883 0 : xProps->addPropertiesChangeListener(
884 : Sequence< OUString >(),
885 0 : xListener);
886 : }
887 :
888 0 : Any aResult;
889 0 : bool bException(false);
890 0 : bool bAborted(false);
891 0 : bool bResultAchieved(false);
892 :
893 0 : Moderator* pMod = 0;
894 : try
895 : {
896 0 : pMod = new Moderator(xContent,xInteract,xProgress,rArg);
897 0 : pMod->create();
898 : }
899 0 : catch (const ContentCreationException&)
900 : {
901 0 : bResultAchieved = bException = true;
902 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
903 : }
904 :
905 0 : sal_uInt32 nTimeout(5000); // initially 5000 milliSec
906 0 : while(!bResultAchieved) {
907 :
908 0 : Moderator::Result res;
909 : // try to get the result for with timeout
910 0 : res = pMod->getResult(nTimeout);
911 :
912 0 : switch(res.type) {
913 : case Moderator::PROGRESSPUSH:
914 : {
915 0 : if(xProgress.is())
916 0 : xProgress->push(res.result);
917 0 : pMod->setReply(Moderator::REQUESTHANDLED);
918 0 : break;
919 : }
920 : case Moderator::PROGRESSUPDATE:
921 : {
922 0 : if(xProgress.is())
923 0 : xProgress->update(res.result);
924 0 : pMod->setReply(Moderator::REQUESTHANDLED);
925 0 : break;
926 : }
927 : case Moderator::PROGRESSPOP:
928 : {
929 0 : if(xProgress.is())
930 0 : xProgress->pop();
931 0 : pMod->setReply(Moderator::REQUESTHANDLED);
932 0 : break;
933 : }
934 : case Moderator::STREAM:
935 : {
936 0 : Reference<XStream> result;
937 0 : if(res.result >>= result) {
938 : Reference < XActiveDataStreamer > xStreamer(
939 : xSink, UNO_QUERY
940 0 : );
941 :
942 0 : if(xStreamer.is())
943 0 : xStreamer->setStream(result);
944 : }
945 0 : pMod->setReply(Moderator::REQUESTHANDLED);
946 0 : break;
947 : }
948 : case Moderator::INPUTSTREAM:
949 : {
950 0 : Reference<XInputStream> result;
951 0 : res.result >>= result;
952 : Reference < XActiveDataSink > xActiveSink(
953 : xSink, UNO_QUERY
954 0 : );
955 :
956 0 : if(xActiveSink.is())
957 0 : xActiveSink->setInputStream(result);
958 0 : pMod->setReply(Moderator::REQUESTHANDLED);
959 0 : break;
960 : }
961 : case Moderator::TIMEDOUT:
962 : {
963 0 : Reference<XInteractionRetry> xRet;
964 0 : if(xInteract.is()) {
965 0 : InteractiveNetworkConnectException aExcep;
966 : INetURLObject aURL(
967 0 : xContId.is() ?
968 0 : xContId->getContentIdentifier() :
969 0 : OUString() );
970 0 : aExcep.Server = aURL.GetHost();
971 0 : aExcep.Classification = InteractionClassification_ERROR;
972 0 : aExcep.Message =
973 0 : OUString( "server not responding after five seconds");
974 0 : Any request;
975 0 : request <<= aExcep;
976 : ucbhelper::InteractionRequest *ir =
977 0 : new ucbhelper::InteractionRequest(request);
978 0 : Reference<XInteractionRequest> xIR(ir);
979 0 : Sequence<Reference<XInteractionContinuation> > aSeq(2);
980 : ucbhelper::InteractionRetry *retryP =
981 0 : new ucbhelper::InteractionRetry(ir);
982 0 : aSeq[0] = retryP;
983 : ucbhelper::InteractionAbort *abortP =
984 0 : new ucbhelper::InteractionAbort(ir);
985 0 : aSeq[1] = abortP;
986 :
987 0 : ir->setContinuations(aSeq);
988 0 : xInteract->handle(xIR);
989 : rtl::Reference< ucbhelper::InteractionContinuation > ref
990 0 : = ir->getSelection();
991 0 : if(ref.is()) {
992 0 : Reference<XInterface> xInt(ref.get());
993 0 : xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY);
994 0 : }
995 : }
996 :
997 0 : if(!xRet.is()) {
998 0 : bAborted = true;
999 0 : xLockBytes->SetError(ERRCODE_ABORT);
1000 : }
1001 :
1002 0 : break;
1003 : }
1004 : case Moderator::INTERACTIONREQUEST:
1005 : {
1006 0 : Reference<XInteractionRequest> Request;
1007 0 : res.result >>= Request;
1008 0 : xInteract->handle(Request);
1009 0 : pMod->setReply(Moderator::REQUESTHANDLED);
1010 0 : break;
1011 : }
1012 : case Moderator::RESULT:
1013 : {
1014 0 : bResultAchieved = true;
1015 0 : aResult = res.result;
1016 0 : break;
1017 : }
1018 : case Moderator::COMMANDABORTED:
1019 : {
1020 0 : bAborted = true;
1021 0 : xLockBytes->SetError( ERRCODE_ABORT );
1022 0 : break;
1023 : }
1024 : case Moderator::COMMANDFAILED:
1025 : {
1026 0 : bAborted = true;
1027 0 : xLockBytes->SetError( ERRCODE_ABORT );
1028 0 : break;
1029 : }
1030 : case Moderator::INTERACTIVEIO:
1031 : {
1032 0 : bException = true;
1033 0 : if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED ||
1034 0 : res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION )
1035 0 : xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
1036 0 : else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING )
1037 0 : xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
1038 0 : else if ( res.ioErrorCode == IOErrorCode_CANT_READ )
1039 0 : xLockBytes->SetError( ERRCODE_IO_CANTREAD );
1040 : else
1041 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1042 0 : break;
1043 : }
1044 : case Moderator::UNSUPPORTED:
1045 : {
1046 0 : bException = true;
1047 0 : xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
1048 0 : break;
1049 : }
1050 : default:
1051 : {
1052 0 : bException = true;
1053 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1054 0 : break;
1055 : }
1056 : }
1057 :
1058 0 : bResultAchieved |= bException;
1059 0 : bResultAchieved |= bAborted;
1060 0 : if(nTimeout == 5000) nTimeout *= 2;
1061 0 : }
1062 :
1063 0 : if(pMod) pMod->setReply(Moderator::EXIT);
1064 :
1065 0 : if ( bAborted || bException )
1066 : {
1067 0 : if( xHandler.Is() )
1068 0 : xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
1069 :
1070 0 : Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
1071 0 : if ( xActiveSink.is() )
1072 0 : xActiveSink->setInputStream( Reference < XInputStream >() );
1073 :
1074 0 : Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
1075 0 : if ( xStreamer.is() )
1076 0 : xStreamer->setStream( Reference < XStream >() );
1077 : }
1078 :
1079 0 : Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
1080 0 : if ( xControl.is() )
1081 0 : xControl->terminate();
1082 :
1083 0 : if ( xProps.is() )
1084 0 : xProps->removePropertiesChangeListener(
1085 : Sequence< OUString >(),
1086 0 : xListener );
1087 :
1088 0 : return ( bAborted || bException );
1089 : }
1090 :
1091 : /**
1092 : Function for opening UCB contents synchronously
1093 : */
1094 0 : static bool _UCBOpenContentSync(
1095 : UcbLockBytesRef xLockBytes,
1096 : Reference < XContent > xContent,
1097 : const Command& rArg,
1098 : Reference < XInterface > xSink,
1099 : Reference < XInteractionHandler > xInteract,
1100 : Reference < XProgressHandler > xProgress,
1101 : UcbLockBytesHandlerRef xHandler )
1102 : {
1103 : ::ucbhelper::Content aContent(
1104 0 : xContent, new UcbTaskEnvironment( xInteract, xProgress ),
1105 0 : comphelper::getProcessComponentContext() );
1106 0 : Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
1107 0 : OUString aScheme = xIdent->getContentProviderScheme();
1108 :
1109 : // http protocol must be handled in a special way: during the opening process the input stream may change
1110 : // only the last inputstream after notifying the document headers is valid
1111 0 : if ( aScheme.compareToAscii("http") != 0 )
1112 0 : xLockBytes->SetStreamValid_Impl();
1113 :
1114 0 : Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes );
1115 0 : Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
1116 0 : if ( xProps.is() )
1117 0 : xProps->addPropertiesChangeListener( Sequence< OUString >(), xListener );
1118 :
1119 0 : Any aResult;
1120 0 : bool bException = false;
1121 0 : bool bAborted = false;
1122 :
1123 : try
1124 : {
1125 0 : aResult = aContent.executeCommand( rArg.Name, rArg.Argument );
1126 : }
1127 0 : catch (const CommandAbortedException&)
1128 : {
1129 0 : bAborted = true;
1130 0 : xLockBytes->SetError( ERRCODE_ABORT );
1131 : }
1132 0 : catch (const CommandFailedException&)
1133 : {
1134 0 : bAborted = true;
1135 0 : xLockBytes->SetError( ERRCODE_ABORT );
1136 : }
1137 0 : catch (const InteractiveIOException& r)
1138 : {
1139 0 : bException = true;
1140 0 : if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
1141 0 : xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
1142 0 : else if ( r.Code == IOErrorCode_NOT_EXISTING )
1143 0 : xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
1144 0 : else if ( r.Code == IOErrorCode_CANT_READ )
1145 0 : xLockBytes->SetError( ERRCODE_IO_CANTREAD );
1146 : else
1147 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1148 : }
1149 0 : catch (const UnsupportedDataSinkException&)
1150 : {
1151 0 : bException = true;
1152 0 : xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
1153 : }
1154 0 : catch (const Exception&)
1155 : {
1156 0 : bException = true;
1157 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1158 : }
1159 :
1160 0 : if ( bAborted || bException )
1161 : {
1162 0 : if( xHandler.Is() )
1163 0 : xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
1164 :
1165 0 : Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
1166 0 : if ( xActiveSink.is() )
1167 0 : xActiveSink->setInputStream( Reference < XInputStream >() );
1168 :
1169 0 : Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
1170 0 : if ( xStreamer.is() )
1171 0 : xStreamer->setStream( Reference < XStream >() );
1172 : }
1173 :
1174 0 : Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
1175 0 : if ( xControl.is() )
1176 0 : xControl->terminate();
1177 :
1178 0 : if ( xProps.is() )
1179 0 : xProps->removePropertiesChangeListener( Sequence< OUString >(), xListener );
1180 :
1181 0 : return ( bAborted || bException );
1182 : }
1183 :
1184 0 : UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler )
1185 : : m_aExpireDate( DateTime::EMPTY )
1186 : , m_xInputStream (NULL)
1187 : , m_pCommandThread( NULL )
1188 : , m_xHandler( pHandler )
1189 : , m_nError( ERRCODE_NONE )
1190 : , m_bTerminated (false)
1191 : , m_bDontClose( false )
1192 0 : , m_bStreamValid (false)
1193 : {
1194 0 : SetSynchronMode( true );
1195 0 : }
1196 :
1197 0 : UcbLockBytes::~UcbLockBytes()
1198 : {
1199 0 : if ( !m_bDontClose )
1200 : {
1201 0 : if ( m_xInputStream.is() )
1202 : {
1203 : try
1204 : {
1205 0 : m_xInputStream->closeInput();
1206 : }
1207 0 : catch (const RuntimeException&)
1208 : {
1209 : }
1210 0 : catch (const IOException&)
1211 : {
1212 : }
1213 : }
1214 : }
1215 :
1216 0 : if ( !m_xInputStream.is() && m_xOutputStream.is() )
1217 : {
1218 : try
1219 : {
1220 0 : m_xOutputStream->closeOutput();
1221 : }
1222 0 : catch (const RuntimeException&)
1223 : {
1224 : }
1225 0 : catch (const IOException&)
1226 : {
1227 : }
1228 : }
1229 0 : }
1230 :
1231 0 : Reference < XInputStream > UcbLockBytes::getInputStream()
1232 : {
1233 0 : osl::MutexGuard aGuard( m_aMutex );
1234 0 : m_bDontClose = true;
1235 0 : return m_xInputStream;
1236 : }
1237 :
1238 0 : bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream )
1239 : {
1240 0 : osl::MutexGuard aGuard( m_aMutex );
1241 0 : if ( aStream.is() )
1242 : {
1243 0 : m_xOutputStream = aStream->getOutputStream();
1244 0 : setInputStream_Impl( aStream->getInputStream(), false );
1245 0 : m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY );
1246 : }
1247 : else
1248 : {
1249 0 : m_xOutputStream.clear();
1250 0 : setInputStream_Impl( Reference < XInputStream >() );
1251 : }
1252 :
1253 0 : return m_xInputStream.is();
1254 : }
1255 :
1256 0 : bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, bool bSetXSeekable )
1257 : {
1258 0 : bool bRet = false;
1259 :
1260 : try
1261 : {
1262 0 : osl::MutexGuard aGuard( m_aMutex );
1263 :
1264 0 : if ( !m_bDontClose && m_xInputStream.is() )
1265 0 : m_xInputStream->closeInput();
1266 :
1267 0 : m_xInputStream = rxInputStream;
1268 :
1269 0 : if( bSetXSeekable )
1270 : {
1271 0 : m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY );
1272 0 : if( !m_xSeekable.is() && rxInputStream.is() )
1273 : {
1274 0 : Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1275 0 : Reference< XOutputStream > rxTempOut = Reference < XOutputStream > ( TempFile::create(xContext), UNO_QUERY_THROW );
1276 :
1277 0 : ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut );
1278 0 : m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY );
1279 0 : m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY );
1280 : }
1281 : }
1282 :
1283 0 : bRet = m_xInputStream.is();
1284 : }
1285 0 : catch (const Exception&)
1286 : {
1287 : }
1288 :
1289 0 : if ( m_bStreamValid && m_xInputStream.is() )
1290 0 : m_aInitialized.set();
1291 :
1292 0 : return bRet;
1293 : }
1294 :
1295 0 : void UcbLockBytes::SetStreamValid_Impl()
1296 : {
1297 0 : m_bStreamValid = true;
1298 0 : if ( m_xInputStream.is() )
1299 0 : m_aInitialized.set();
1300 0 : }
1301 :
1302 0 : void UcbLockBytes::terminate_Impl()
1303 : {
1304 0 : m_bTerminated = true;
1305 0 : m_aInitialized.set();
1306 0 : m_aTerminated.set();
1307 :
1308 0 : if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() )
1309 : {
1310 : OSL_FAIL("No InputStream, but no error set!" );
1311 0 : SetError( ERRCODE_IO_NOTEXISTS );
1312 : }
1313 :
1314 0 : if ( m_xHandler.Is() )
1315 0 : m_xHandler->Handle( UcbLockBytesHandler::DONE, this );
1316 0 : }
1317 :
1318 0 : void UcbLockBytes::SetSynchronMode (bool bSynchron)
1319 : {
1320 0 : SvLockBytes::SetSynchronMode (bSynchron);
1321 0 : }
1322 :
1323 0 : ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos,
1324 : void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const
1325 : {
1326 0 : if ( IsSynchronMode() )
1327 : {
1328 0 : UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1329 0 : pThis->m_aInitialized.wait();
1330 : }
1331 :
1332 0 : Reference <XInputStream> xStream = getInputStream_Impl();
1333 0 : if ( !xStream.is() )
1334 : {
1335 0 : if ( m_bTerminated )
1336 0 : return ERRCODE_IO_CANTREAD;
1337 : else
1338 0 : return ERRCODE_IO_PENDING;
1339 : }
1340 :
1341 0 : if ( pRead )
1342 0 : *pRead = 0;
1343 :
1344 0 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1345 0 : if ( !xSeekable.is() )
1346 0 : return ERRCODE_IO_CANTREAD;
1347 :
1348 : try
1349 : {
1350 0 : xSeekable->seek( nPos );
1351 : }
1352 0 : catch (const IOException&)
1353 : {
1354 0 : return ERRCODE_IO_CANTSEEK;
1355 : }
1356 0 : catch (const com::sun::star::lang::IllegalArgumentException&)
1357 : {
1358 0 : return ERRCODE_IO_CANTSEEK;
1359 : }
1360 :
1361 0 : Sequence<sal_Int8> aData;
1362 : sal_Int32 nSize;
1363 :
1364 0 : if(nCount > 0x7FFFFFFF)
1365 : {
1366 0 : nCount = 0x7FFFFFFF;
1367 : }
1368 : try
1369 : {
1370 0 : if ( !m_bTerminated && !IsSynchronMode() )
1371 : {
1372 0 : sal_uInt64 nLen = xSeekable->getLength();
1373 0 : if ( nPos + nCount > nLen )
1374 0 : return ERRCODE_IO_PENDING;
1375 : }
1376 :
1377 0 : nSize = xStream->readBytes( aData, sal_Int32(nCount) );
1378 : }
1379 0 : catch (const IOException&)
1380 : {
1381 0 : return ERRCODE_IO_CANTREAD;
1382 : }
1383 :
1384 0 : memcpy (pBuffer, aData.getConstArray(), nSize);
1385 0 : if (pRead)
1386 0 : *pRead = sal_uLong(nSize);
1387 :
1388 0 : return ERRCODE_NONE;
1389 : }
1390 :
1391 0 : ErrCode UcbLockBytes::WriteAt(sal_uInt64 const nPos, const void *pBuffer,
1392 : sal_uLong nCount, sal_uLong *pWritten)
1393 : {
1394 0 : if ( pWritten )
1395 0 : *pWritten = 0;
1396 :
1397 : DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" );
1398 : DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" );
1399 :
1400 0 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1401 0 : Reference <XOutputStream> xOutputStream = getOutputStream_Impl();
1402 0 : if ( !xOutputStream.is() || !xSeekable.is() )
1403 0 : return ERRCODE_IO_CANTWRITE;
1404 :
1405 : try
1406 : {
1407 0 : xSeekable->seek( nPos );
1408 : }
1409 0 : catch (const IOException&)
1410 : {
1411 0 : return ERRCODE_IO_CANTSEEK;
1412 : }
1413 :
1414 0 : sal_Int8* pData = (sal_Int8*) pBuffer;
1415 0 : Sequence<sal_Int8> aData( pData, nCount );
1416 : try
1417 : {
1418 0 : xOutputStream->writeBytes( aData );
1419 0 : if ( pWritten )
1420 0 : *pWritten = nCount;
1421 : }
1422 0 : catch (const Exception&)
1423 : {
1424 0 : return ERRCODE_IO_CANTWRITE;
1425 : }
1426 :
1427 0 : return ERRCODE_NONE;
1428 : }
1429 :
1430 0 : ErrCode UcbLockBytes::Flush() const
1431 : {
1432 0 : Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
1433 0 : if ( !xOutputStream.is() )
1434 0 : return ERRCODE_IO_CANTWRITE;
1435 :
1436 : try
1437 : {
1438 0 : xOutputStream->flush();
1439 : }
1440 0 : catch (const Exception&)
1441 : {
1442 0 : return ERRCODE_IO_CANTWRITE;
1443 : }
1444 :
1445 0 : return ERRCODE_NONE;
1446 : }
1447 :
1448 0 : ErrCode UcbLockBytes::SetSize (sal_uInt64 const nNewSize)
1449 : {
1450 0 : SvLockBytesStat aStat;
1451 0 : Stat( &aStat, (SvLockBytesStatFlag) 0 );
1452 0 : sal_uLong nSize = aStat.nSize;
1453 :
1454 0 : if ( nSize > nNewSize )
1455 : {
1456 0 : Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY );
1457 0 : if ( xTrunc.is() )
1458 : {
1459 0 : xTrunc->truncate();
1460 0 : nSize = 0;
1461 : }
1462 : else {
1463 : DBG_WARNING("Not truncatable!");
1464 0 : }
1465 : }
1466 :
1467 0 : if ( nSize < nNewSize )
1468 : {
1469 0 : sal_uLong nDiff = nNewSize-nSize, nCount=0;
1470 0 : sal_uInt8* pBuffer = new sal_uInt8[ nDiff ];
1471 0 : memset(pBuffer, 0, nDiff); // initialize for enhanced security
1472 0 : WriteAt( nSize, pBuffer, nDiff, &nCount );
1473 0 : delete[] pBuffer;
1474 0 : if ( nCount != nDiff )
1475 0 : return ERRCODE_IO_CANTWRITE;
1476 : }
1477 :
1478 0 : return ERRCODE_NONE;
1479 : }
1480 :
1481 0 : ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const
1482 : {
1483 0 : if ( IsSynchronMode() )
1484 : {
1485 0 : UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
1486 0 : pThis->m_aInitialized.wait();
1487 : }
1488 :
1489 0 : if (!pStat)
1490 0 : return ERRCODE_IO_INVALIDPARAMETER;
1491 :
1492 0 : Reference <XInputStream> xStream = getInputStream_Impl();
1493 0 : Reference <XSeekable> xSeekable = getSeekable_Impl();
1494 :
1495 0 : if ( !xStream.is() )
1496 : {
1497 0 : if ( m_bTerminated )
1498 0 : return ERRCODE_IO_INVALIDACCESS;
1499 : else
1500 0 : return ERRCODE_IO_PENDING;
1501 : }
1502 0 : else if( !xSeekable.is() )
1503 0 : return ERRCODE_IO_CANTTELL;
1504 :
1505 : try
1506 : {
1507 0 : pStat->nSize = sal_uLong(xSeekable->getLength());
1508 : }
1509 0 : catch (const IOException&)
1510 : {
1511 0 : return ERRCODE_IO_CANTTELL;
1512 : }
1513 :
1514 0 : return ERRCODE_NONE;
1515 : }
1516 :
1517 0 : IMPL_LINK_NOARG(UcbLockBytes, DataAvailHdl)
1518 : {
1519 0 : if ( hasInputStream_Impl() && m_xHandler.Is() )
1520 0 : m_xHandler->Handle( UcbLockBytesHandler::DATA_AVAILABLE, this );
1521 :
1522 0 : return 0;
1523 : }
1524 :
1525 0 : UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream )
1526 : {
1527 0 : if( !xInputStream.is() )
1528 0 : return NULL;
1529 :
1530 0 : UcbLockBytesRef xLockBytes = new UcbLockBytes();
1531 0 : xLockBytes->setDontClose_Impl();
1532 0 : xLockBytes->setInputStream_Impl( xInputStream );
1533 0 : xLockBytes->terminate_Impl();
1534 0 : return xLockBytes;
1535 : }
1536 :
1537 0 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream )
1538 : {
1539 0 : if( !xStream.is() )
1540 0 : return NULL;
1541 :
1542 0 : UcbLockBytesRef xLockBytes = new UcbLockBytes();
1543 0 : xLockBytes->setDontClose_Impl();
1544 0 : xLockBytes->setStream_Impl( xStream );
1545 0 : xLockBytes->terminate_Impl();
1546 0 : return xLockBytes;
1547 : }
1548 :
1549 0 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps,
1550 : StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
1551 : {
1552 0 : if( !xContent.is() )
1553 0 : return NULL;
1554 :
1555 0 : UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
1556 0 : xLockBytes->SetSynchronMode( !pHandler );
1557 0 : Reference< XActiveDataControl > xSink;
1558 0 : if ( eOpenMode & STREAM_WRITE )
1559 0 : xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes );
1560 : else
1561 0 : xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
1562 :
1563 0 : if ( rProps.getLength() )
1564 : {
1565 0 : Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY );
1566 0 : Command aCommand;
1567 0 : aCommand.Name = "setPropertyValues";
1568 0 : aCommand.Handle = -1; /* unknown */
1569 0 : aCommand.Argument <<= rProps;
1570 0 : xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() );
1571 : }
1572 :
1573 0 : OpenCommandArgument2 aArgument;
1574 0 : aArgument.Sink = xSink;
1575 0 : aArgument.Mode = OpenMode::DOCUMENT;
1576 :
1577 0 : Command aCommand;
1578 0 : aCommand.Name = "open";
1579 0 : aCommand.Argument <<= aArgument;
1580 :
1581 0 : Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) );
1582 :
1583 : bool bError = UCBOpenContentSync( xLockBytes,
1584 : xContent,
1585 : aCommand,
1586 : xSink,
1587 : xInteractionHandler,
1588 : xProgressHdl,
1589 0 : pHandler );
1590 :
1591 0 : if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
1592 : {
1593 : OSL_FAIL("No InputStream, but no error set!" );
1594 0 : xLockBytes->SetError( ERRCODE_IO_GENERAL );
1595 : }
1596 :
1597 0 : return xLockBytes;
1598 : }
1599 :
1600 : }
1601 :
1602 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|