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

Generated by: LCOV version 1.10