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

Generated by: LCOV version 1.10