LCOV - code coverage report
Current view: top level - unotools/source/ucbhelper - ucblockbytes.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 228 678 33.6 %
Date: 2014-04-11 Functions: 39 101 38.6 %
Legend: Lines: hit not hit

          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         584 : class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink >
      72             : {
      73             :     UcbLockBytesRef         m_xLockBytes;
      74             : 
      75             : public:
      76         292 :                             UcbDataSink_Impl( UcbLockBytes* pLockBytes )
      77         292 :                                 : m_xLockBytes( pLockBytes )
      78         292 :                             {}
      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         292 :     virtual void SAL_CALL   terminate (void) throw(RuntimeException, std::exception) SAL_OVERRIDE
      85         292 :                             { m_xLockBytes->terminate_Impl(); }
      86             : 
      87             :     // XActiveDataSink.
      88         451 :     virtual void SAL_CALL   setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException, std::exception) SAL_OVERRIDE
      89         451 :                             { 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       36296 : class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl >
      98             : {
      99             :     Reference < XStream >   m_xStream;
     100             :     UcbLockBytesRef         m_xLockBytes;
     101             : 
     102             : public:
     103       18148 :                             UcbStreamer_Impl( UcbLockBytes* pLockBytes )
     104       18148 :                                 : m_xLockBytes( pLockBytes )
     105       18148 :                             {}
     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       18148 :     virtual void SAL_CALL   terminate (void) throw(RuntimeException, std::exception) SAL_OVERRIDE
     112       18148 :                             { m_xLockBytes->terminate_Impl(); }
     113             : 
     114             :     // XActiveDataStreamer
     115       18158 :     virtual void SAL_CALL   setStream( const Reference< XStream >& aStream ) throw(RuntimeException, std::exception) SAL_OVERRIDE
     116       18158 :                             { 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       36880 : class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler >
     125             : {
     126             :     Link                    m_aProgress;
     127             : 
     128             : public:
     129       18440 :                             ProgressHandler_Impl( const Link& rLink )
     130       18440 :                                 : m_aProgress( rLink )
     131       18440 :                             {}
     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       36880 : class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment >
     143             : {
     144             :     Reference< XInteractionHandler >                m_xInteractionHandler;
     145             :     Reference< XProgressHandler >                   m_xProgressHandler;
     146             : 
     147             : public:
     148       18440 :                             UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
     149             :                                                 const Reference< XProgressHandler>& rxProgressHandler )
     150             :                                 : m_xInteractionHandler( rxInteractionHandler )
     151       18440 :                                 , m_xProgressHandler( rxProgressHandler )
     152       18440 :                             {}
     153             : 
     154         206 :     virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException, std::exception) SAL_OVERRIDE
     155         206 :     { 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       36880 : class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener >
     165             : {
     166             : public:
     167             :     UcbLockBytesRef         m_xLockBytes;
     168             : 
     169       18440 :                             UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
     170       18440 :                                 : m_xLockBytes( rRef )
     171       18440 :                             {}
     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       18440 : 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       18440 :         xContent.is() ? xContent->getIdentifier() : 0 );
     861             : 
     862       36880 :     OUString aScheme;
     863       18440 :     if(xContId.is())
     864       18440 :         aScheme = xContId->getContentProviderScheme();
     865             : 
     866             :     // now determine whether we use a timeout or not;
     867       55320 :     if( ! aScheme.equalsIgnoreAsciiCase("http")                &&
     868       36880 :         ! aScheme.equalsIgnoreAsciiCase("https")               &&
     869       55320 :         ! aScheme.equalsIgnoreAsciiCase("vnd.sun.star.webdav") &&
     870       18440 :         ! aScheme.equalsIgnoreAsciiCase("ftp"))
     871             :         return _UCBOpenContentSync(
     872       18440 :             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       18440 :     return ( bAborted || bException );
    1089             : }
    1090             : 
    1091             : /**
    1092             :     Function for opening UCB contents synchronously
    1093             :  */
    1094       18440 : 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       18440 :         xContent, new UcbTaskEnvironment( xInteract, xProgress ),
    1105       36880 :         comphelper::getProcessComponentContext() );
    1106       36880 :     Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
    1107       36880 :     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       18440 :     if ( aScheme.compareToAscii("http") != 0 )
    1112       18440 :         xLockBytes->SetStreamValid_Impl();
    1113             : 
    1114       36880 :     Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes );
    1115       36880 :     Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
    1116       18440 :     if ( xProps.is() )
    1117       18440 :         xProps->addPropertiesChangeListener( Sequence< OUString >(), xListener );
    1118             : 
    1119       36880 :     Any aResult;
    1120       18440 :     bool bException = false;
    1121       18440 :     bool bAborted = false;
    1122             : 
    1123             :     try
    1124             :     {
    1125       18440 :         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         412 :     catch (const InteractiveIOException& r)
    1138             :     {
    1139         206 :         bException = true;
    1140         206 :         if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
    1141           0 :             xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
    1142         206 :         else if ( r.Code == IOErrorCode_NOT_EXISTING )
    1143         206 :             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       18440 :     if ( bAborted || bException )
    1161             :     {
    1162         206 :         if( xHandler.Is() )
    1163           0 :             xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
    1164             : 
    1165         206 :         Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
    1166         206 :         if ( xActiveSink.is() )
    1167         196 :             xActiveSink->setInputStream( Reference < XInputStream >() );
    1168             : 
    1169         412 :         Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
    1170         206 :         if ( xStreamer.is() )
    1171         216 :             xStreamer->setStream( Reference < XStream >() );
    1172             :     }
    1173             : 
    1174       36880 :     Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
    1175       18440 :     if ( xControl.is() )
    1176       18440 :         xControl->terminate();
    1177             : 
    1178       18440 :     if ( xProps.is() )
    1179       18440 :         xProps->removePropertiesChangeListener( Sequence< OUString >(), xListener );
    1180             : 
    1181       36880 :     return ( bAborted || bException );
    1182             : }
    1183             : 
    1184       30139 : 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       30139 :     , m_bStreamValid  (false)
    1193             : {
    1194       30139 :     SetSynchronMode( true );
    1195       30139 : }
    1196             : 
    1197      120348 : UcbLockBytes::~UcbLockBytes()
    1198             : {
    1199       30087 :     if ( !m_bDontClose )
    1200             :     {
    1201         202 :         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       30087 :     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       90261 : }
    1230             : 
    1231       18234 : Reference < XInputStream > UcbLockBytes::getInputStream()
    1232             : {
    1233       18234 :     osl::MutexGuard aGuard( m_aMutex );
    1234       18234 :     m_bDontClose = true;
    1235       18234 :     return m_xInputStream;
    1236             : }
    1237             : 
    1238       20159 : bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream )
    1239             : {
    1240       20159 :     osl::MutexGuard aGuard( m_aMutex );
    1241       20159 :     if ( aStream.is() )
    1242             :     {
    1243       20139 :         m_xOutputStream = aStream->getOutputStream();
    1244       20139 :         setInputStream_Impl( aStream->getInputStream(), false );
    1245       20139 :         m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY );
    1246             :     }
    1247             :     else
    1248             :     {
    1249          20 :         m_xOutputStream.clear();
    1250          20 :         setInputStream_Impl( Reference < XInputStream >() );
    1251             :     }
    1252             : 
    1253       20159 :     return m_xInputStream.is();
    1254             : }
    1255             : 
    1256       30308 : bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, bool bSetXSeekable )
    1257             : {
    1258       30308 :     bool bRet = false;
    1259             : 
    1260             :     try
    1261             :     {
    1262       30308 :         osl::MutexGuard aGuard( m_aMutex );
    1263             : 
    1264       30308 :         if ( !m_bDontClose && m_xInputStream.is() )
    1265           0 :             m_xInputStream->closeInput();
    1266             : 
    1267       30308 :         m_xInputStream = rxInputStream;
    1268             : 
    1269       30308 :         if( bSetXSeekable )
    1270             :         {
    1271       10169 :             m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY );
    1272       10169 :             if( !m_xSeekable.is() && rxInputStream.is() )
    1273             :             {
    1274         562 :                 Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
    1275        1124 :                 Reference< XOutputStream > rxTempOut = Reference < XOutputStream > ( TempFile::create(xContext), UNO_QUERY_THROW );
    1276             : 
    1277         562 :                 ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut );
    1278         562 :                 m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY );
    1279        1124 :                 m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY );
    1280             :             }
    1281             :         }
    1282             : 
    1283       30308 :         bRet = m_xInputStream.is();
    1284             :     }
    1285           0 :     catch (const Exception&)
    1286             :     {
    1287             :     }
    1288             : 
    1289       30308 :     if ( m_bStreamValid && m_xInputStream.is() )
    1290       18234 :         m_aInitialized.set();
    1291             : 
    1292       30308 :     return bRet;
    1293             : }
    1294             : 
    1295       18440 : void UcbLockBytes::SetStreamValid_Impl()
    1296             : {
    1297       18440 :     m_bStreamValid = true;
    1298       18440 :     if ( m_xInputStream.is() )
    1299           0 :         m_aInitialized.set();
    1300       18440 : }
    1301             : 
    1302       30139 : void UcbLockBytes::terminate_Impl()
    1303             : {
    1304       30139 :     m_bTerminated = true;
    1305       30139 :     m_aInitialized.set();
    1306       30139 :     m_aTerminated.set();
    1307             : 
    1308       30139 :     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       30139 :     if ( m_xHandler.Is() )
    1315           0 :         m_xHandler->Handle( UcbLockBytesHandler::DONE, this );
    1316       30139 : }
    1317             : 
    1318       48656 : void UcbLockBytes::SetSynchronMode (bool bSynchron)
    1319             : {
    1320       48656 :     SvLockBytes::SetSynchronMode (bSynchron);
    1321       48656 : }
    1322             : 
    1323       73665 : ErrCode UcbLockBytes::ReadAt(sal_uInt64 const nPos,
    1324             :         void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const
    1325             : {
    1326       73665 :     if ( IsSynchronMode() )
    1327             :     {
    1328       73665 :         UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
    1329       73665 :         pThis->m_aInitialized.wait();
    1330             :     }
    1331             : 
    1332       73665 :     Reference <XInputStream> xStream = getInputStream_Impl();
    1333       73665 :     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       73665 :     if ( pRead )
    1342       73665 :         *pRead = 0;
    1343             : 
    1344      147330 :     Reference <XSeekable> xSeekable = getSeekable_Impl();
    1345       73665 :     if ( !xSeekable.is() )
    1346           0 :         return ERRCODE_IO_CANTREAD;
    1347             : 
    1348             :     try
    1349             :     {
    1350       73665 :         xSeekable->seek( nPos );
    1351             :     }
    1352           0 :     catch (const IOException&)
    1353             :     {
    1354           0 :         return ERRCODE_IO_CANTSEEK;
    1355             :     }
    1356           2 :     catch (const com::sun::star::lang::IllegalArgumentException&)
    1357             :     {
    1358           1 :         return ERRCODE_IO_CANTSEEK;
    1359             :     }
    1360             : 
    1361      147328 :     Sequence<sal_Int8> aData;
    1362             :     sal_Int32          nSize;
    1363             : 
    1364       73664 :     if(nCount > 0x7FFFFFFF)
    1365             :     {
    1366           0 :         nCount = 0x7FFFFFFF;
    1367             :     }
    1368             :     try
    1369             :     {
    1370       73664 :         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       73664 :         nSize = xStream->readBytes( aData, sal_Int32(nCount) );
    1378             :     }
    1379           0 :     catch (const IOException&)
    1380             :     {
    1381           0 :         return ERRCODE_IO_CANTREAD;
    1382             :     }
    1383             : 
    1384       73664 :     memcpy (pBuffer, aData.getConstArray(), nSize);
    1385       73664 :     if (pRead)
    1386       73664 :         *pRead = sal_uLong(nSize);
    1387             : 
    1388      147329 :     return ERRCODE_NONE;
    1389             : }
    1390             : 
    1391       26365 : ErrCode UcbLockBytes::WriteAt(sal_uInt64 const nPos, const void *pBuffer,
    1392             :         sal_uLong nCount, sal_uLong *pWritten)
    1393             : {
    1394       26365 :     if ( pWritten )
    1395       26365 :         *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       26365 :     Reference <XSeekable> xSeekable = getSeekable_Impl();
    1401       52730 :     Reference <XOutputStream> xOutputStream = getOutputStream_Impl();
    1402       26365 :     if ( !xOutputStream.is() || !xSeekable.is() )
    1403           8 :         return ERRCODE_IO_CANTWRITE;
    1404             : 
    1405             :     try
    1406             :     {
    1407       26357 :         xSeekable->seek( nPos );
    1408             :     }
    1409           0 :     catch (const IOException&)
    1410             :     {
    1411           0 :         return ERRCODE_IO_CANTSEEK;
    1412             :     }
    1413             : 
    1414       26357 :     sal_Int8* pData = (sal_Int8*) pBuffer;
    1415       52714 :     Sequence<sal_Int8> aData( pData, nCount );
    1416             :     try
    1417             :     {
    1418       26357 :         xOutputStream->writeBytes( aData );
    1419       26357 :         if ( pWritten )
    1420       26357 :             *pWritten = nCount;
    1421             :     }
    1422           0 :     catch (const Exception&)
    1423             :     {
    1424           0 :         return ERRCODE_IO_CANTWRITE;
    1425             :     }
    1426             : 
    1427       52722 :     return ERRCODE_NONE;
    1428             : }
    1429             : 
    1430       32517 : ErrCode UcbLockBytes::Flush() const
    1431             : {
    1432       32517 :     Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
    1433       32517 :     if ( !xOutputStream.is() )
    1434        9790 :         return ERRCODE_IO_CANTWRITE;
    1435             : 
    1436             :     try
    1437             :     {
    1438       22727 :         xOutputStream->flush();
    1439             :     }
    1440           2 :     catch (const Exception&)
    1441             :     {
    1442           1 :         return ERRCODE_IO_CANTWRITE;
    1443             :     }
    1444             : 
    1445       22726 :     return ERRCODE_NONE;
    1446             : }
    1447             : 
    1448        3295 : ErrCode UcbLockBytes::SetSize (sal_uInt64 const nNewSize)
    1449             : {
    1450        3295 :     SvLockBytesStat aStat;
    1451        3295 :     Stat( &aStat, (SvLockBytesStatFlag) 0 );
    1452        3295 :     sal_uLong nSize = aStat.nSize;
    1453             : 
    1454        3295 :     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        3295 :     if ( nSize < nNewSize )
    1468             :     {
    1469        3295 :         sal_uLong nDiff = nNewSize-nSize, nCount=0;
    1470        3295 :         sal_uInt8* pBuffer = new sal_uInt8[ nDiff ];
    1471        3295 :         memset(pBuffer, 0, nDiff); // initialize for enhanced security
    1472        3295 :         WriteAt( nSize, pBuffer, nDiff, &nCount );
    1473        3295 :         delete[] pBuffer;
    1474        3295 :         if ( nCount != nDiff )
    1475           0 :             return ERRCODE_IO_CANTWRITE;
    1476             :     }
    1477             : 
    1478        3295 :     return ERRCODE_NONE;
    1479             : }
    1480             : 
    1481       46329 : ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const
    1482             : {
    1483       46329 :     if ( IsSynchronMode() )
    1484             :     {
    1485       46329 :         UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
    1486       46329 :         pThis->m_aInitialized.wait();
    1487             :     }
    1488             : 
    1489       46329 :     if (!pStat)
    1490           0 :         return ERRCODE_IO_INVALIDPARAMETER;
    1491             : 
    1492       46329 :     Reference <XInputStream> xStream = getInputStream_Impl();
    1493       92658 :     Reference <XSeekable> xSeekable = getSeekable_Impl();
    1494             : 
    1495       46329 :     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       46329 :     else if( !xSeekable.is() )
    1503           0 :         return ERRCODE_IO_CANTTELL;
    1504             : 
    1505             :     try
    1506             :     {
    1507       46329 :         pStat->nSize = sal_uLong(xSeekable->getLength());
    1508             :     }
    1509           0 :     catch (const IOException&)
    1510             :     {
    1511           0 :         return ERRCODE_IO_CANTTELL;
    1512             :     }
    1513             : 
    1514       92658 :     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        9698 : UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream )
    1526             : {
    1527        9698 :     if( !xInputStream.is() )
    1528           0 :         return NULL;
    1529             : 
    1530        9698 :     UcbLockBytesRef xLockBytes = new UcbLockBytes();
    1531        9698 :     xLockBytes->setDontClose_Impl();
    1532        9698 :     xLockBytes->setInputStream_Impl( xInputStream );
    1533        9698 :     xLockBytes->terminate_Impl();
    1534        9698 :     return xLockBytes;
    1535             : }
    1536             : 
    1537        2001 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream )
    1538             : {
    1539        2001 :     if( !xStream.is() )
    1540           0 :         return NULL;
    1541             : 
    1542        2001 :     UcbLockBytesRef xLockBytes = new UcbLockBytes();
    1543        2001 :     xLockBytes->setDontClose_Impl();
    1544        2001 :     xLockBytes->setStream_Impl( xStream );
    1545        2001 :     xLockBytes->terminate_Impl();
    1546        2001 :     return xLockBytes;
    1547             : }
    1548             : 
    1549       18440 : UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps,
    1550             :         StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
    1551             : {
    1552       18440 :     if( !xContent.is() )
    1553           0 :         return NULL;
    1554             : 
    1555       18440 :     UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
    1556       18440 :     xLockBytes->SetSynchronMode( !pHandler );
    1557       36880 :     Reference< XActiveDataControl > xSink;
    1558       18440 :     if ( eOpenMode & STREAM_WRITE )
    1559       18148 :         xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes );
    1560             :     else
    1561         292 :         xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
    1562             : 
    1563       18440 :     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       36880 :     OpenCommandArgument2 aArgument;
    1574       18440 :     aArgument.Sink = xSink;
    1575       18440 :     aArgument.Mode = OpenMode::DOCUMENT;
    1576             : 
    1577       36880 :     Command aCommand;
    1578       18440 :     aCommand.Name = "open";
    1579       18440 :     aCommand.Argument <<= aArgument;
    1580             : 
    1581       36880 :     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       18440 :                                       pHandler );
    1590             : 
    1591       18440 :     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       36880 :     return xLockBytes;
    1598             : }
    1599             : 
    1600             : }
    1601             : 
    1602             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10