summaryrefslogtreecommitdiff
path: root/unotools/source/ucbhelper/ucblockbytes.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'unotools/source/ucbhelper/ucblockbytes.cxx')
-rw-r--r--unotools/source/ucbhelper/ucblockbytes.cxx1755
1 files changed, 1755 insertions, 0 deletions
diff --git a/unotools/source/ucbhelper/ucblockbytes.cxx b/unotools/source/ucbhelper/ucblockbytes.cxx
new file mode 100644
index 000000000000..71640c6e5b08
--- /dev/null
+++ b/unotools/source/ucbhelper/ucblockbytes.cxx
@@ -0,0 +1,1755 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_unotools.hxx"
+
+#include <unotools/ucblockbytes.hxx>
+#include <comphelper/processfactory.hxx>
+#include <salhelper/condition.hxx>
+#ifndef _OSL_THREAD_HXX_
+#include <osl/thread.hxx>
+#endif
+#include <tools/urlobj.hxx>
+#include <ucbhelper/interactionrequest.hxx>
+#include <com/sun/star/task/XInteractionAbort.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/CommandFailedException.hpp>
+#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+#ifndef _COM_SUN_STAR_UCB_INTERACTIVEIODEXCEPTION_HPP_
+#include <com/sun/star/ucb/InteractiveIOException.hpp>
+#endif
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#include <com/sun/star/ucb/DocumentHeaderField.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/PostCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XActiveDataControl.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <tools/inetmsg.hxx>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <comphelper/storagehelper.hxx>
+
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/content.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+
+namespace utl
+{
+
+/**
+ Helper class for getting a XInputStream when opening a content
+ */
+class UcbDataSink_Impl : public ::cppu::WeakImplHelper2< XActiveDataControl, XActiveDataSink >
+{
+ UcbLockBytesRef m_xLockBytes;
+
+public:
+ UcbDataSink_Impl( UcbLockBytes* pLockBytes )
+ : m_xLockBytes( pLockBytes )
+ {}
+
+ SvLockBytes* getLockBytes (void)
+ { return m_xLockBytes; }
+
+ // XActiveDataControl.
+ virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
+ virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
+ virtual void SAL_CALL start (void) throw(RuntimeException) {}
+ virtual void SAL_CALL terminate (void) throw(RuntimeException)
+ { m_xLockBytes->terminate_Impl(); }
+
+ // XActiveDataSink.
+ virtual void SAL_CALL setInputStream ( const Reference<XInputStream> &rxInputStream) throw(RuntimeException)
+ { m_xLockBytes->setInputStream_Impl (rxInputStream); }
+ virtual Reference<XInputStream> SAL_CALL getInputStream (void) throw(RuntimeException)
+ { return m_xLockBytes->getInputStream_Impl(); }
+};
+
+/**
+ Helper class for getting a XStream when opening a content
+ */
+class UcbStreamer_Impl : public ::cppu::WeakImplHelper2< XActiveDataStreamer, XActiveDataControl >
+{
+ Reference < XStream > m_xStream;
+ UcbLockBytesRef m_xLockBytes;
+
+public:
+
+ UcbStreamer_Impl( UcbLockBytes* pLockBytes )
+ : m_xLockBytes( pLockBytes )
+ {}
+
+ // XActiveDataControl.
+ virtual void SAL_CALL addListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
+ virtual void SAL_CALL removeListener ( const Reference<XStreamListener> &/*rxListener*/) throw(RuntimeException) {}
+ virtual void SAL_CALL start (void) throw(RuntimeException) {}
+ virtual void SAL_CALL terminate (void) throw(RuntimeException)
+ { m_xLockBytes->terminate_Impl(); }
+
+ // XActiveDataStreamer
+ virtual void SAL_CALL setStream( const Reference< XStream >& aStream ) throw(RuntimeException)
+ { m_xStream = aStream; m_xLockBytes->setStream_Impl( aStream ); }
+ virtual Reference< XStream > SAL_CALL getStream() throw(RuntimeException)
+ { return m_xStream; }
+};
+
+/**
+ Helper class for progress handling while executing UCB commands
+ */
+class ProgressHandler_Impl: public ::cppu::WeakImplHelper1< XProgressHandler >
+{
+ Link m_aProgress;
+
+public:
+ ProgressHandler_Impl( const Link& rLink )
+ : m_aProgress( rLink )
+ {}
+ // XProgressHandler
+ virtual void SAL_CALL push(const Any & /*rStatus*/) throw (RuntimeException) {}
+ virtual void SAL_CALL pop() throw (RuntimeException) {}
+ virtual void SAL_CALL update(const Any & /*rStatus*/) throw (RuntimeException)
+ { if ( m_aProgress.IsSet() ) m_aProgress.Call( 0 ); }
+};
+
+/**
+ Helper class for managing interactions and progress when executing UCB commands
+ */
+class UcbTaskEnvironment : public ::cppu::WeakImplHelper1< XCommandEnvironment >
+{
+ Reference< XInteractionHandler > m_xInteractionHandler;
+ Reference< XProgressHandler > m_xProgressHandler;
+
+public:
+ UcbTaskEnvironment( const Reference< XInteractionHandler>& rxInteractionHandler,
+ const Reference< XProgressHandler>& rxProgressHandler )
+ : m_xInteractionHandler( rxInteractionHandler )
+ , m_xProgressHandler( rxProgressHandler )
+ {}
+
+
+ virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler() throw (RuntimeException)
+ { return m_xInteractionHandler; }
+
+ virtual Reference<XProgressHandler> SAL_CALL getProgressHandler() throw (RuntimeException)
+ { return m_xProgressHandler; }
+};
+
+
+/**
+ Helper class for property change notifies when executing UCB commands
+*/
+class UcbPropertiesChangeListener_Impl : public ::cppu::WeakImplHelper1< XPropertiesChangeListener >
+{
+public:
+ UcbLockBytesRef m_xLockBytes;
+
+ UcbPropertiesChangeListener_Impl( UcbLockBytesRef rRef )
+ : m_xLockBytes( rRef )
+ {}
+
+ virtual void SAL_CALL disposing ( const EventObject &/*rEvent*/) throw(RuntimeException) {}
+ virtual void SAL_CALL propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException);
+};
+
+void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange ( const Sequence<PropertyChangeEvent> &rEvent) throw(RuntimeException)
+{
+ sal_Int32 i, n = rEvent.getLength();
+ for (i = 0; i < n; i++)
+ {
+ PropertyChangeEvent evt (rEvent[i]);
+ if (evt.PropertyName == ::rtl::OUString::createFromAscii ("DocumentHeader"))
+ {
+ Sequence<DocumentHeaderField> aHead;
+ if (evt.NewValue >>= aHead)
+ {
+ sal_Int32 k, m = aHead.getLength();
+ for (k = 0; k < m; k++)
+ {
+ String aName( aHead[k].Name );
+ String aValue( aHead[k].Value );
+
+ if (aName.CompareIgnoreCaseToAscii("Expires") == COMPARE_EQUAL)
+ {
+ DateTime aExpires (0, 0);
+ if (INetRFC822Message::ParseDateField (aValue, aExpires))
+ {
+ aExpires.ConvertToLocalTime();
+ m_xLockBytes->SetExpireDate_Impl( aExpires );
+ }
+ }
+ }
+ }
+
+ m_xLockBytes->SetStreamValid_Impl();
+ }
+ else if (evt.PropertyName == rtl::OUString::createFromAscii ("PresentationURL"))
+ {
+ ::rtl::OUString aUrl;
+ if (evt.NewValue >>= aUrl)
+ {
+ ::rtl::OUString aBad (::rtl::OUString::createFromAscii ("private:"));
+ if (!(aUrl.compareTo (aBad, aBad.getLength()) == 0))
+ {
+ // URL changed (Redirection).
+ m_xLockBytes->SetRealURL_Impl( aUrl );
+ }
+ }
+ }
+ else if (evt.PropertyName == ::rtl::OUString::createFromAscii ("MediaType"))
+ {
+ ::rtl::OUString aContentType;
+ if (evt.NewValue >>= aContentType)
+ m_xLockBytes->SetContentType_Impl( aContentType );
+ }
+ }
+}
+
+
+
+class Moderator
+ : public osl::Thread
+{
+ // usage restriction:
+ // It might be possible, that the call to the interactionhandler and/or
+ // progresshandler is done asynchrounsly, while the 'execute' simply
+ // returns. This would imply that these class must be refcounted !!!
+
+public:
+
+ Moderator(
+ Reference < XContent >& xContent,
+ Reference < XInteractionHandler >& xInteract,
+ Reference < XProgressHandler >& xProgress,
+ const Command& rArg
+ )
+ throw(
+ ContentCreationException,
+ RuntimeException
+ );
+
+ ~Moderator();
+
+
+ enum ResultType {
+ NORESULT,
+
+ INTERACTIONREQUEST, // reply expected
+
+ PROGRESSPUSH,
+ PROGRESSUPDATE,
+ PROGRESSPOP,
+
+ INPUTSTREAM,
+ STREAM,
+
+ RESULT,
+ TIMEDOUT,
+ COMMANDABORTED,
+ COMMANDFAILED,
+ INTERACTIVEIO,
+ UNSUPPORTED,
+ GENERAL
+ };
+
+
+ class ConditionRes
+ : public salhelper::Condition
+ {
+ public:
+
+ ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
+ : salhelper::Condition(aMutex),
+ m_aModerator(aModerator)
+ {
+ }
+
+ protected:
+
+ bool applies() const {
+ return m_aModerator.m_aResultType != NORESULT;
+ }
+
+ private:
+
+ Moderator& m_aModerator;
+ };
+
+
+ struct Result {
+ ResultType type;
+ Any result;
+ sal_Int32 ioErrorCode;
+ };
+
+
+ Result getResult(const sal_uInt32 milliSec);
+
+
+ enum ReplyType {
+ NOREPLY,
+ EXIT,
+ RETRY,
+ REQUESTHANDLED
+ };
+
+
+ class ConditionRep
+ : public salhelper::Condition
+ {
+ public:
+
+ ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
+ : salhelper::Condition(aMutex),
+ m_aModerator(aModerator)
+ {
+ }
+
+ protected:
+
+ bool applies() const {
+ return m_aModerator.m_aReplyType != NOREPLY;
+ }
+
+ private:
+
+ Moderator& m_aModerator;
+ };
+
+ void setReply(ReplyType);
+
+
+ void handle( const Reference<XInteractionRequest >& Request );
+
+ void push( const Any& Status );
+
+ void update( const Any& Status );
+
+ void pop( );
+
+ void setStream(const Reference< XStream >& aStream);
+
+ void setInputStream(const Reference<XInputStream> &rxInputStream);
+
+
+protected:
+
+ virtual void SAL_CALL run();
+
+ virtual void SAL_CALL onTerminated();
+
+private:
+
+ osl::Mutex m_aMutex;
+
+ friend class ConditionRes;
+
+ ConditionRes m_aRes;
+ ResultType m_aResultType;
+ sal_Int32 m_nIOErrorCode;
+ Any m_aResult;
+
+ friend class ConditionRep;
+
+ ConditionRep m_aRep;
+ ReplyType m_aReplyType;
+
+ Command m_aArg;
+ ::ucbhelper::Content m_aContent;
+};
+
+
+class ModeratorsActiveDataStreamer
+ : public ::cppu::WeakImplHelper1<XActiveDataStreamer>
+{
+public:
+
+ ModeratorsActiveDataStreamer(Moderator &theModerator);
+
+ ~ModeratorsActiveDataStreamer();
+
+ // XActiveDataStreamer
+ virtual void SAL_CALL
+ setStream(
+ const Reference< XStream >& aStream
+ )
+ throw(
+ RuntimeException
+ );
+
+ virtual Reference<XStream> SAL_CALL
+ getStream (
+ void
+ ) throw(
+ RuntimeException
+ )
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xStream;
+ }
+
+
+private:
+
+ Moderator& m_aModerator;
+
+ osl::Mutex m_aMutex;
+ Reference<XStream> m_xStream;
+};
+
+
+
+class ModeratorsActiveDataSink
+ : public ::cppu::WeakImplHelper1<XActiveDataSink>
+{
+public:
+
+ ModeratorsActiveDataSink(Moderator &theModerator);
+
+ ~ModeratorsActiveDataSink();
+
+ // XActiveDataSink.
+ virtual void SAL_CALL
+ setInputStream (
+ const Reference<XInputStream> &rxInputStream
+ )
+ throw(
+ RuntimeException
+ );
+
+ virtual Reference<XInputStream> SAL_CALL
+ getInputStream (
+ void
+ ) throw(
+ RuntimeException
+ )
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ return m_xStream;
+ }
+
+
+private:
+
+ Moderator& m_aModerator;
+ osl::Mutex m_aMutex;
+ Reference<XInputStream> m_xStream;
+};
+
+
+
+ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
+ : m_aModerator(theModerator)
+{
+}
+
+
+ModeratorsActiveDataSink::~ModeratorsActiveDataSink()
+{
+}
+
+// XActiveDataSink.
+void SAL_CALL
+ModeratorsActiveDataSink::setInputStream (
+ const Reference<XInputStream> &rxInputStream
+)
+ throw(
+ RuntimeException
+ )
+{
+ m_aModerator.setInputStream(rxInputStream);
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xStream = rxInputStream;
+}
+
+
+ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
+ Moderator &theModerator
+)
+ : m_aModerator(theModerator)
+{
+}
+
+
+ModeratorsActiveDataStreamer::~ModeratorsActiveDataStreamer()
+{
+}
+
+// XActiveDataStreamer.
+void SAL_CALL
+ModeratorsActiveDataStreamer::setStream (
+ const Reference<XStream> &rxStream
+)
+ throw(
+ RuntimeException
+ )
+{
+ m_aModerator.setStream(rxStream);
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xStream = rxStream;
+}
+
+
+
+class ModeratorsInteractionHandler
+ : public ::cppu::WeakImplHelper1<XInteractionHandler>
+{
+public:
+
+ ModeratorsInteractionHandler(Moderator &theModerator);
+
+ ~ModeratorsInteractionHandler();
+
+ virtual void SAL_CALL
+ handle( const Reference<XInteractionRequest >& Request )
+ throw (RuntimeException);
+
+private:
+
+ Moderator& m_aModerator;
+};
+
+
+class ModeratorsProgressHandler
+ : public ::cppu::WeakImplHelper1<XProgressHandler>
+{
+public:
+
+ ModeratorsProgressHandler(Moderator &theModerator);
+
+ ~ModeratorsProgressHandler();
+
+ virtual void SAL_CALL push( const Any& Status )
+ throw (
+ RuntimeException);
+
+ virtual void SAL_CALL update( const Any& Status )
+ throw (RuntimeException);
+
+ virtual void SAL_CALL pop( )
+ throw (RuntimeException);
+
+
+private:
+
+ Moderator& m_aModerator;
+};
+
+
+ModeratorsProgressHandler::ModeratorsProgressHandler(Moderator &theModerator)
+ : m_aModerator(theModerator)
+{
+}
+
+ModeratorsProgressHandler::~ModeratorsProgressHandler()
+{
+}
+
+
+void SAL_CALL ModeratorsProgressHandler::push( const Any& Status )
+ throw (
+ RuntimeException)
+{
+ m_aModerator.push(Status);
+}
+
+
+void SAL_CALL ModeratorsProgressHandler::update( const Any& Status )
+ throw (RuntimeException)
+{
+ m_aModerator.update(Status);
+}
+
+
+void SAL_CALL ModeratorsProgressHandler::pop( )
+ throw (RuntimeException)
+{
+ m_aModerator.pop();
+}
+
+
+
+
+ModeratorsInteractionHandler::ModeratorsInteractionHandler(
+ Moderator &aModerator)
+ : m_aModerator(aModerator)
+{
+}
+
+
+ModeratorsInteractionHandler::~ModeratorsInteractionHandler()
+{
+}
+
+
+void SAL_CALL
+ModeratorsInteractionHandler::handle(
+ const Reference<XInteractionRequest >& Request
+)
+ throw (
+ RuntimeException
+ )
+{
+ // wakes up the mainthread
+ m_aModerator.handle(Request);
+}
+
+
+
+
+Moderator::Moderator(
+ Reference < XContent >& xContent,
+ Reference < XInteractionHandler >& xInteract,
+ Reference < XProgressHandler >& xProgress,
+ const Command& rArg
+)
+ throw(
+ ::com::sun::star::ucb::ContentCreationException,
+ ::com::sun::star::uno::RuntimeException
+ )
+ : m_aMutex(),
+
+ m_aRes(m_aMutex,*this),
+ m_aResultType(NORESULT),
+ m_nIOErrorCode(0),
+ m_aResult(),
+
+ m_aRep(m_aMutex,*this),
+ m_aReplyType(NOREPLY),
+
+ m_aArg(rArg),
+ m_aContent(
+ xContent,
+ new UcbTaskEnvironment(
+ xInteract.is() ? new ModeratorsInteractionHandler(*this) : 0,
+ xProgress.is() ? new ModeratorsProgressHandler(*this) : 0
+ ))
+{
+ // now exchange the whole data sink stuff
+ // with a thread safe version
+
+ Reference<XInterface> *pxSink = NULL;
+
+ PostCommandArgument2 aPostArg;
+ OpenCommandArgument2 aOpenArg;
+
+ int dec(2);
+ if(m_aArg.Argument >>= aPostArg) {
+ pxSink = &aPostArg.Sink;
+ dec = 0;
+ }
+ else if(m_aArg.Argument >>= aOpenArg) {
+ pxSink = &aOpenArg.Sink;
+ dec = 1;
+ }
+
+ if(dec ==2)
+ throw ContentCreationException();
+
+ Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY);
+ if(xActiveSink.is())
+ *pxSink = Reference<XInterface>(
+ (cppu::OWeakObject*)new ModeratorsActiveDataSink(*this));
+
+ Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY );
+ if ( xStreamer.is() )
+ *pxSink = Reference<XInterface>(
+ (cppu::OWeakObject*)new ModeratorsActiveDataStreamer(*this));
+
+ if(dec == 0)
+ m_aArg.Argument <<= aPostArg;
+ else if(dec == 1)
+ m_aArg.Argument <<= aOpenArg;
+}
+
+
+Moderator::~Moderator()
+{
+}
+
+
+Moderator::Result Moderator::getResult(const sal_uInt32 milliSec)
+{
+ Result ret;
+ try {
+ salhelper::ConditionWaiter aWaiter(m_aRes,milliSec);
+ ret.type = m_aResultType;
+ ret.result = m_aResult;
+ ret.ioErrorCode = m_nIOErrorCode;
+
+ // reset
+ m_aResultType = NORESULT;
+ }
+ catch(const salhelper::ConditionWaiter::timedout&)
+ {
+ ret.type = TIMEDOUT;
+ }
+
+ return ret;
+}
+
+
+void Moderator::setReply(ReplyType aReplyType )
+{
+ salhelper::ConditionModifier aMod(m_aRep);
+ m_aReplyType = aReplyType;
+}
+
+
+void Moderator::handle( const Reference<XInteractionRequest >& Request )
+{
+ ReplyType aReplyType;
+
+ do {
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = INTERACTIONREQUEST;
+ m_aResult <<= Request;
+ }
+
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+
+ // reset
+ m_aReplyType = NOREPLY;
+ }
+
+ if(aReplyType == EXIT) {
+ Sequence<Reference<XInteractionContinuation> > aSeq(
+ Request->getContinuations());
+ for(sal_Int32 i = 0; i < aSeq.getLength(); ++i) {
+ Reference<XInteractionAbort> aRef(aSeq[i],UNO_QUERY);
+ if(aRef.is()) {
+ aRef->select();
+ }
+ }
+
+ // resignal the exitcondition
+ setReply(EXIT);
+ break;
+ }
+ } while(aReplyType != REQUESTHANDLED);
+}
+
+
+
+void Moderator::push( const Any& Status )
+{
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = PROGRESSPUSH;
+ m_aResult = Status;
+ }
+ ReplyType aReplyType;
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+ m_aReplyType = NOREPLY;
+ }
+ if(aReplyType == EXIT)
+ setReply(EXIT);
+}
+
+
+void Moderator::update( const Any& Status )
+{
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = PROGRESSUPDATE;
+ m_aResult = Status;
+ }
+ ReplyType aReplyType;
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+ m_aReplyType = NOREPLY;
+ }
+ if(aReplyType == EXIT)
+ setReply(EXIT);
+}
+
+
+void Moderator::pop( )
+{
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = PROGRESSPOP;
+ }
+ ReplyType aReplyType;
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+ m_aReplyType = NOREPLY;
+ }
+ if(aReplyType == EXIT)
+ setReply(EXIT);
+}
+
+
+void Moderator::setStream(const Reference< XStream >& aStream)
+{
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = STREAM;
+ m_aResult <<= aStream;
+ }
+ ReplyType aReplyType;
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+ m_aReplyType = NOREPLY;
+ }
+ if(aReplyType == EXIT)
+ setReply(EXIT);
+}
+
+
+void Moderator::setInputStream(const Reference<XInputStream> &rxInputStream)
+{
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = INPUTSTREAM;
+ m_aResult <<= rxInputStream;
+ }
+ ReplyType aReplyType;
+ {
+ salhelper::ConditionWaiter aWait(m_aRep);
+ aReplyType = m_aReplyType;
+ m_aReplyType = NOREPLY;
+ }
+ if(aReplyType == EXIT)
+ setReply(EXIT);
+}
+
+
+
+void SAL_CALL Moderator::run()
+{
+ ResultType aResultType;
+ Any aResult;
+ sal_Int32 nIOErrorCode = 0;
+
+ try
+ {
+ aResult = m_aContent.executeCommand(m_aArg.Name,m_aArg.Argument);
+ aResultType = RESULT;
+ }
+ catch ( CommandAbortedException )
+ {
+ aResultType = COMMANDABORTED;
+ }
+ catch ( CommandFailedException )
+ {
+ aResultType = COMMANDFAILED;
+ }
+ catch ( InteractiveIOException& r )
+ {
+ nIOErrorCode = r.Code;
+ aResultType = INTERACTIVEIO;
+ }
+ catch ( UnsupportedDataSinkException& )
+ {
+ aResultType = UNSUPPORTED;
+ }
+ catch ( Exception )
+ {
+ aResultType = GENERAL;
+ }
+
+ {
+ salhelper::ConditionModifier aMod(m_aRes);
+ m_aResultType = aResultType;
+ m_aResult = aResult;
+ m_nIOErrorCode = nIOErrorCode;
+ }
+}
+
+
+
+void SAL_CALL Moderator::onTerminated()
+{
+ {
+ salhelper::ConditionWaiter aWaiter(m_aRep);
+ }
+ delete this;
+}
+
+
+/**
+ Function for opening UCB contents synchronously,
+ but with handled timeout;
+*/
+
+static sal_Bool _UCBOpenContentSync(
+ UcbLockBytesRef xLockBytes,
+ Reference < XContent > xContent,
+ const Command& rArg,
+ Reference < XInterface > xSink,
+ Reference < XInteractionHandler > xInteract,
+ Reference < XProgressHandler > xProgress,
+ UcbLockBytesHandlerRef xHandler );
+
+
+static sal_Bool UCBOpenContentSync(
+ UcbLockBytesRef xLockBytes,
+ Reference < XContent > xContent,
+ const Command& rArg,
+ Reference < XInterface > xSink,
+ Reference < XInteractionHandler > xInteract,
+ Reference < XProgressHandler > xProgress,
+ UcbLockBytesHandlerRef xHandler )
+{
+ // http protocol must be handled in a special way:
+ // during the opening process the input stream may change
+ // only the last inputstream after notifying the document
+ // headers is valid
+
+ Reference<XContentIdentifier> xContId(
+ xContent.is() ? xContent->getIdentifier() : 0 );
+
+ rtl::OUString aScheme;
+ if(xContId.is())
+ aScheme = xContId->getContentProviderScheme();
+
+ // now determine wether we use a timeout or not;
+ if( ! aScheme.equalsIgnoreAsciiCaseAscii("http") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("https") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("ftp"))
+ return _UCBOpenContentSync(
+ xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler);
+
+ if ( (aScheme.compareToAscii( "http" ) != COMPARE_EQUAL) ||
+ (aScheme.compareToAscii( "https" ) != COMPARE_EQUAL) )
+ xLockBytes->SetStreamValid_Impl();
+
+ Reference< XPropertiesChangeListener > xListener;
+ Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY);
+ if(xProps.is()) {
+ xListener =
+ new UcbPropertiesChangeListener_Impl(xLockBytes);
+ xProps->addPropertiesChangeListener(
+ Sequence< ::rtl::OUString >(),
+ xListener);
+ }
+
+ Any aResult;
+ bool bException(false);
+ bool bAborted(false);
+ bool bResultAchieved(false);
+
+ Moderator* pMod = 0;
+ try {
+ pMod = new Moderator(xContent,xInteract,xProgress,rArg);
+ pMod->create();
+ } catch(const ContentCreationException&) {
+ bResultAchieved = bException = true;
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ }
+
+ sal_uInt32 nTimeout(5000); // initially 5000 milliSec
+ while(!bResultAchieved) {
+
+ Moderator::Result res;
+ // try to get the result for with timeout
+ res = pMod->getResult(nTimeout);
+
+ switch(res.type) {
+ case Moderator::PROGRESSPUSH:
+ {
+ if(xProgress.is())
+ xProgress->push(res.result);
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::PROGRESSUPDATE:
+ {
+ if(xProgress.is())
+ xProgress->update(res.result);
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::PROGRESSPOP:
+ {
+ if(xProgress.is())
+ xProgress->pop();
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::STREAM:
+ {
+ Reference<XStream> result;
+ if(res.result >>= result) {
+ Reference < XActiveDataStreamer > xStreamer(
+ xSink, UNO_QUERY
+ );
+
+ if(xStreamer.is())
+ xStreamer->setStream(result);
+ }
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::INPUTSTREAM:
+ {
+ Reference<XInputStream> result;
+ res.result >>= result;
+ Reference < XActiveDataSink > xActiveSink(
+ xSink, UNO_QUERY
+ );
+
+ if(xActiveSink.is())
+ xActiveSink->setInputStream(result);
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::TIMEDOUT:
+ {
+ Reference<XInteractionRetry> xRet;
+ if(xInteract.is()) {
+ InteractiveNetworkConnectException aExcep;
+ INetURLObject aURL(
+ xContId.is() ?
+ xContId->getContentIdentifier() :
+ rtl::OUString() );
+ aExcep.Server = aURL.GetHost();
+ aExcep.Classification = InteractionClassification_ERROR;
+ aExcep.Message =
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "server not responding after five seconds"));
+ Any request;
+ request <<= aExcep;
+ ucbhelper::InteractionRequest *ir =
+ new ucbhelper::InteractionRequest(request);
+ Reference<XInteractionRequest> xIR(ir);
+ Sequence<Reference<XInteractionContinuation> > aSeq(2);
+ ucbhelper::InteractionRetry *retryP =
+ new ucbhelper::InteractionRetry(ir);
+ aSeq[0] = retryP;
+ ucbhelper::InteractionAbort *abortP =
+ new ucbhelper::InteractionAbort(ir);
+ aSeq[1] = abortP;
+
+ ir->setContinuations(aSeq);
+ xInteract->handle(xIR);
+ rtl::Reference< ucbhelper::InteractionContinuation > ref
+ = ir->getSelection();
+ if(ref.is()) {
+ Reference<XInterface> xInt(ref.get());
+ xRet = Reference<XInteractionRetry>(xInt,UNO_QUERY);
+ }
+ }
+
+ if(!xRet.is()) {
+ bAborted = true;
+ xLockBytes->SetError(ERRCODE_ABORT);
+ }
+
+ break;
+ }
+ case Moderator::INTERACTIONREQUEST:
+ {
+ Reference<XInteractionRequest> Request;
+ res.result >>= Request;
+ xInteract->handle(Request);
+ pMod->setReply(Moderator::REQUESTHANDLED);
+ break;
+ }
+ case Moderator::RESULT:
+ {
+ bResultAchieved = true;
+ aResult = res.result;
+ break;
+ }
+ case Moderator::COMMANDABORTED:
+ {
+ bAborted = true;
+ xLockBytes->SetError( ERRCODE_ABORT );
+ break;
+ }
+ case Moderator::COMMANDFAILED:
+ {
+ bAborted = true;
+ xLockBytes->SetError( ERRCODE_ABORT );
+ break;
+ }
+ case Moderator::INTERACTIVEIO:
+ {
+ bException = true;
+ if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED ||
+ res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION )
+ xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
+ else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING )
+ xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
+ else if ( res.ioErrorCode == IOErrorCode_CANT_READ )
+ xLockBytes->SetError( ERRCODE_IO_CANTREAD );
+ else
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ break;
+ }
+ case Moderator::UNSUPPORTED:
+ {
+ bException = true;
+ xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
+ break;
+ }
+ default:
+ {
+ bException = true;
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ break;
+ }
+ }
+
+ bResultAchieved |= bException;
+ bResultAchieved |= bAborted;
+ if(nTimeout == 5000) nTimeout *= 2;
+ }
+
+ if(pMod) pMod->setReply(Moderator::EXIT);
+
+ if ( bAborted || bException )
+ {
+ if( xHandler.Is() )
+ xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
+
+ Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
+ if ( xActiveSink.is() )
+ xActiveSink->setInputStream( Reference < XInputStream >() );
+
+ Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
+ if ( xStreamer.is() )
+ xStreamer->setStream( Reference < XStream >() );
+ }
+
+ Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
+ if ( xControl.is() )
+ xControl->terminate();
+
+ if ( xProps.is() )
+ xProps->removePropertiesChangeListener(
+ Sequence< ::rtl::OUString >(),
+ xListener );
+
+ return ( bAborted || bException );
+}
+
+/**
+ Function for opening UCB contents synchronously
+ */
+static sal_Bool _UCBOpenContentSync(
+ UcbLockBytesRef xLockBytes,
+ Reference < XContent > xContent,
+ const Command& rArg,
+ Reference < XInterface > xSink,
+ Reference < XInteractionHandler > xInteract,
+ Reference < XProgressHandler > xProgress,
+ UcbLockBytesHandlerRef xHandler )
+{
+ ::ucbhelper::Content aContent( xContent, new UcbTaskEnvironment( xInteract, xProgress ) );
+ Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
+ ::rtl::OUString aScheme = xIdent->getContentProviderScheme();
+
+ // http protocol must be handled in a special way: during the opening process the input stream may change
+ // only the last inputstream after notifying the document headers is valid
+ if ( aScheme.compareToAscii("http") != COMPARE_EQUAL )
+ xLockBytes->SetStreamValid_Impl();
+
+ Reference< XPropertiesChangeListener > xListener = new UcbPropertiesChangeListener_Impl( xLockBytes );
+ Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
+ if ( xProps.is() )
+ xProps->addPropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener );
+
+ Any aResult;
+ bool bException = false;
+ bool bAborted = false;
+
+ try
+ {
+ aResult = aContent.executeCommand( rArg.Name, rArg.Argument );
+ }
+ catch ( CommandAbortedException )
+ {
+ bAborted = true;
+ xLockBytes->SetError( ERRCODE_ABORT );
+ }
+ catch ( CommandFailedException )
+ {
+ bAborted = true;
+ xLockBytes->SetError( ERRCODE_ABORT );
+ }
+ catch ( InteractiveIOException& r )
+ {
+ bException = true;
+ if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
+ xLockBytes->SetError( ERRCODE_IO_ACCESSDENIED );
+ else if ( r.Code == IOErrorCode_NOT_EXISTING )
+ xLockBytes->SetError( ERRCODE_IO_NOTEXISTS );
+ else if ( r.Code == IOErrorCode_CANT_READ )
+ xLockBytes->SetError( ERRCODE_IO_CANTREAD );
+ else
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ }
+ catch ( UnsupportedDataSinkException& )
+ {
+ bException = true;
+ xLockBytes->SetError( ERRCODE_IO_NOTSUPPORTED );
+ }
+ catch ( Exception )
+ {
+ bException = true;
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ }
+
+ if ( bAborted || bException )
+ {
+ if( xHandler.Is() )
+ xHandler->Handle( UcbLockBytesHandler::CANCEL, xLockBytes );
+
+ Reference < XActiveDataSink > xActiveSink( xSink, UNO_QUERY );
+ if ( xActiveSink.is() )
+ xActiveSink->setInputStream( Reference < XInputStream >() );
+
+ Reference < XActiveDataStreamer > xStreamer( xSink, UNO_QUERY );
+ if ( xStreamer.is() )
+ xStreamer->setStream( Reference < XStream >() );
+ }
+
+ Reference < XActiveDataControl > xControl( xSink, UNO_QUERY );
+ if ( xControl.is() )
+ xControl->terminate();
+
+
+ if ( xProps.is() )
+ xProps->removePropertiesChangeListener( Sequence< ::rtl::OUString >(), xListener );
+
+ return ( bAborted || bException );
+}
+
+
+//----------------------------------------------------------------------------
+UcbLockBytes::UcbLockBytes( UcbLockBytesHandler* pHandler )
+ : m_xInputStream (NULL)
+ , m_pCommandThread( NULL )
+ , m_xHandler( pHandler )
+ , m_nError( ERRCODE_NONE )
+ , m_bTerminated (sal_False)
+ , m_bDontClose( sal_False )
+ , m_bStreamValid (sal_False)
+{
+ SetSynchronMode( sal_True );
+}
+
+//----------------------------------------------------------------------------
+UcbLockBytes::~UcbLockBytes()
+{
+ if ( !m_bDontClose )
+ {
+ if ( m_xInputStream.is() )
+ {
+ try
+ {
+ m_xInputStream->closeInput();
+ }
+ catch ( RuntimeException const & )
+ {}
+ catch ( IOException const & )
+ {}
+ }
+ }
+
+ if ( !m_xInputStream.is() && m_xOutputStream.is() )
+ {
+ try
+ {
+ m_xOutputStream->closeOutput();
+ }
+ catch ( RuntimeException const & )
+ {}
+ catch ( IOException const & )
+ {}
+ }
+}
+
+Reference < XInputStream > UcbLockBytes::getInputStream()
+{
+ vos::OClearableGuard aGuard( m_aMutex );
+ m_bDontClose = sal_True;
+ return m_xInputStream;
+}
+
+Reference < XStream > UcbLockBytes::getStream()
+{
+ vos::OClearableGuard aGuard( m_aMutex );
+ Reference < XStream > xStream( m_xSeekable, UNO_QUERY );
+ if ( xStream.is() )
+ m_bDontClose = sal_True;
+ return xStream;
+}
+
+//----------------------------------------------------------------------------
+
+sal_Bool UcbLockBytes::setStream_Impl( const Reference<XStream>& aStream )
+{
+ vos::OClearableGuard aGuard( m_aMutex );
+ if ( aStream.is() )
+ {
+ m_xOutputStream = aStream->getOutputStream();
+ setInputStream_Impl( aStream->getInputStream(), sal_False );
+ m_xSeekable = Reference < XSeekable > ( aStream, UNO_QUERY );
+ }
+ else
+ {
+ m_xOutputStream = Reference < XOutputStream >();
+ setInputStream_Impl( Reference < XInputStream >() );
+ }
+
+ return m_xInputStream.is();
+}
+
+sal_Bool UcbLockBytes::setInputStream_Impl( const Reference<XInputStream> &rxInputStream, sal_Bool bSetXSeekable )
+{
+ sal_Bool bRet = sal_False;
+
+ try
+ {
+ vos::OClearableGuard aGuard( m_aMutex );
+
+ if ( !m_bDontClose && m_xInputStream.is() )
+ m_xInputStream->closeInput();
+
+ m_xInputStream = rxInputStream;
+
+ if( bSetXSeekable )
+ {
+ m_xSeekable = Reference < XSeekable > ( rxInputStream, UNO_QUERY );
+ if( !m_xSeekable.is() && rxInputStream.is() )
+ {
+ Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+ Reference< XOutputStream > rxTempOut = Reference < XOutputStream > (
+ xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
+ UNO_QUERY );
+
+ if( rxTempOut.is() )
+ {
+ ::comphelper::OStorageHelper::CopyInputToOutput( rxInputStream, rxTempOut );
+ m_xInputStream = Reference< XInputStream >( rxTempOut, UNO_QUERY );
+ m_xSeekable = Reference < XSeekable > ( rxTempOut, UNO_QUERY );
+ }
+ }
+ }
+
+ bRet = m_xInputStream.is();
+ // aGuard.clear();
+ }
+ catch( Exception& )
+ {}
+
+ if ( m_bStreamValid && m_xInputStream.is() )
+ m_aInitialized.set();
+
+ return bRet;
+}
+
+void UcbLockBytes::SetStreamValid_Impl()
+{
+ m_bStreamValid = sal_True;
+ if ( m_xInputStream.is() )
+ m_aInitialized.set();
+}
+
+//----------------------------------------------------------------------------
+void UcbLockBytes::terminate_Impl()
+{
+ m_bTerminated = sal_True;
+ m_aInitialized.set();
+ m_aTerminated.set();
+
+ if ( GetError() == ERRCODE_NONE && !m_xInputStream.is() )
+ {
+ DBG_ERROR("No InputStream, but no error set!" );
+ SetError( ERRCODE_IO_NOTEXISTS );
+ }
+
+ if ( m_xHandler.Is() )
+ m_xHandler->Handle( UcbLockBytesHandler::DONE, this );
+}
+
+//----------------------------------------------------------------------------
+void UcbLockBytes::SetSynchronMode (sal_Bool bSynchron)
+{
+ SvLockBytes::SetSynchronMode (bSynchron);
+}
+
+//----------------------------------------------------------------------------
+ErrCode UcbLockBytes::ReadAt ( sal_uLong nPos, void *pBuffer, sal_uLong nCount, sal_uLong *pRead) const
+{
+ if ( IsSynchronMode() )
+ {
+ UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
+ pThis->m_aInitialized.wait();
+ }
+
+ Reference <XInputStream> xStream = getInputStream_Impl();
+ if ( !xStream.is() )
+ {
+ if ( m_bTerminated )
+ return ERRCODE_IO_CANTREAD;
+ else
+ return ERRCODE_IO_PENDING;
+ }
+
+ if ( pRead )
+ *pRead = 0;
+
+ Reference <XSeekable> xSeekable = getSeekable_Impl();
+ if ( !xSeekable.is() )
+ return ERRCODE_IO_CANTREAD;
+
+ try
+ {
+ xSeekable->seek( nPos );
+ }
+ catch ( IOException )
+ {
+ return ERRCODE_IO_CANTSEEK;
+ }
+ catch (com::sun::star::lang::IllegalArgumentException)
+ {
+ return ERRCODE_IO_CANTSEEK;
+ }
+
+ Sequence<sal_Int8> aData;
+ sal_Int32 nSize;
+
+ nCount = VOS_MIN(nCount, 0x7FFFFFFF);
+ try
+ {
+ if ( !m_bTerminated && !IsSynchronMode() )
+ {
+ sal_uInt64 nLen = xSeekable->getLength();
+ if ( nPos + nCount > nLen )
+ return ERRCODE_IO_PENDING;
+ }
+
+ nSize = xStream->readBytes( aData, sal_Int32(nCount) );
+ }
+ catch (IOException)
+ {
+ return ERRCODE_IO_CANTREAD;
+ }
+
+ rtl_copyMemory (pBuffer, aData.getConstArray(), nSize);
+ if (pRead)
+ *pRead = sal_uLong(nSize);
+
+ return ERRCODE_NONE;
+}
+
+//----------------------------------------------------------------------------
+ErrCode UcbLockBytes::WriteAt ( sal_uLong nPos, const void *pBuffer, sal_uLong nCount, sal_uLong *pWritten)
+{
+ if ( pWritten )
+ *pWritten = 0;
+
+ DBG_ASSERT( IsSynchronMode(), "Writing is only possible in SynchronMode!" );
+ DBG_ASSERT( m_aInitialized.check(), "Writing bevor stream is ready!" );
+
+ Reference <XSeekable> xSeekable = getSeekable_Impl();
+ Reference <XOutputStream> xOutputStream = getOutputStream_Impl();
+ if ( !xOutputStream.is() || !xSeekable.is() )
+ return ERRCODE_IO_CANTWRITE;
+
+ try
+ {
+ xSeekable->seek( nPos );
+ }
+ catch ( IOException )
+ {
+ return ERRCODE_IO_CANTSEEK;
+ }
+
+ sal_Int8* pData = (sal_Int8*) pBuffer;
+ Sequence<sal_Int8> aData( pData, nCount );
+ try
+ {
+ xOutputStream->writeBytes( aData );
+ if ( pWritten )
+ *pWritten = nCount;
+ }
+ catch ( Exception )
+ {
+ return ERRCODE_IO_CANTWRITE;
+ }
+
+ return ERRCODE_NONE;
+}
+
+//----------------------------------------------------------------------------
+ErrCode UcbLockBytes::Flush() const
+{
+ Reference <XOutputStream > xOutputStream = getOutputStream_Impl();
+ if ( !xOutputStream.is() )
+ return ERRCODE_IO_CANTWRITE;
+
+ try
+ {
+ xOutputStream->flush();
+ }
+ catch( Exception )
+ {
+ return ERRCODE_IO_CANTWRITE;
+ }
+
+ return ERRCODE_NONE;
+}
+
+//----------------------------------------------------------------------------
+ErrCode UcbLockBytes::SetSize (sal_uLong nNewSize)
+{
+ SvLockBytesStat aStat;
+ Stat( &aStat, (SvLockBytesStatFlag) 0 );
+ sal_uLong nSize = aStat.nSize;
+
+ if ( nSize > nNewSize )
+ {
+ Reference < XTruncate > xTrunc( getOutputStream_Impl(), UNO_QUERY );
+ if ( xTrunc.is() )
+ {
+ xTrunc->truncate();
+ nSize = 0;
+ }
+ else {
+ DBG_WARNING("Not truncatable!");
+ }
+ }
+
+ if ( nSize < nNewSize )
+ {
+ sal_uLong nDiff = nNewSize-nSize, nCount=0;
+ sal_uInt8* pBuffer = new sal_uInt8[ nDiff ];
+ memset(pBuffer, 0, nDiff); // initialize for enhanced security
+ WriteAt( nSize, pBuffer, nDiff, &nCount );
+ delete[] pBuffer;
+ if ( nCount != nDiff )
+ return ERRCODE_IO_CANTWRITE;
+ }
+
+ return ERRCODE_NONE;
+}
+
+//----------------------------------------------------------------------------
+ErrCode UcbLockBytes::Stat( SvLockBytesStat *pStat, SvLockBytesStatFlag) const
+{
+ if ( IsSynchronMode() )
+ {
+ UcbLockBytes* pThis = const_cast < UcbLockBytes* >( this );
+ pThis->m_aInitialized.wait();
+ }
+
+ if (!pStat)
+ return ERRCODE_IO_INVALIDPARAMETER;
+
+ Reference <XInputStream> xStream = getInputStream_Impl();
+ Reference <XSeekable> xSeekable = getSeekable_Impl();
+
+ if ( !xStream.is() )
+ {
+ if ( m_bTerminated )
+ return ERRCODE_IO_INVALIDACCESS;
+ else
+ return ERRCODE_IO_PENDING;
+ }
+ else if( !xSeekable.is() )
+ return ERRCODE_IO_CANTTELL;
+
+ try
+ {
+ pStat->nSize = sal_uLong(xSeekable->getLength());
+ }
+ catch (IOException)
+ {
+ return ERRCODE_IO_CANTTELL;
+ }
+
+ return ERRCODE_NONE;
+}
+
+//----------------------------------------------------------------------------
+void UcbLockBytes::Cancel()
+{
+ // is alive only for compatibility reasons
+ OSL_ENSURE( m_bTerminated, "UcbLockBytes is not thread safe so it can be used only syncronously!\n" );
+}
+
+//----------------------------------------------------------------------------
+IMPL_LINK( UcbLockBytes, DataAvailHdl, void*, EMPTYARG )
+{
+ if ( hasInputStream_Impl() && m_xHandler.Is() )
+ m_xHandler->Handle( UcbLockBytesHandler::DATA_AVAILABLE, this );
+
+ return 0;
+}
+
+UcbLockBytesRef UcbLockBytes::CreateInputLockBytes( const Reference< XInputStream >& xInputStream )
+{
+ if( !xInputStream.is() )
+ return NULL;;
+
+ UcbLockBytesRef xLockBytes = new UcbLockBytes();
+ xLockBytes->setDontClose_Impl();
+ xLockBytes->setInputStream_Impl( xInputStream );
+ xLockBytes->terminate_Impl();
+ return xLockBytes;
+}
+
+UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference< XStream >& xStream )
+{
+ if( !xStream.is() )
+ return NULL;;
+
+ UcbLockBytesRef xLockBytes = new UcbLockBytes();
+ xLockBytes->setDontClose_Impl();
+ xLockBytes->setStream_Impl( xStream );
+ xLockBytes->terminate_Impl();
+ return xLockBytes;
+}
+
+UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const ::rtl::OUString& rReferer, const ::rtl::OUString& rMediaType,
+ const Reference < XInputStream >& xPostData, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
+{
+ if( !xContent.is() )
+ return NULL;;
+
+ UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
+ xLockBytes->SetSynchronMode( !pHandler );
+ Reference< XActiveDataControl > xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
+
+ PostCommandArgument2 aArgument;
+ aArgument.Source = xPostData;
+ aArgument.Sink = xSink;
+ aArgument.MediaType = rMediaType;
+ aArgument.Referer = rReferer;
+
+ Command aCommand;
+ aCommand.Name = ::rtl::OUString::createFromAscii ("post");
+ aCommand.Argument <<= aArgument;
+
+ Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) );
+
+ sal_Bool bError = UCBOpenContentSync( xLockBytes,
+ xContent,
+ aCommand,
+ xSink,
+ xInteractionHandler,
+ xProgressHdl,
+ pHandler );
+
+ if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
+ {
+ DBG_ERROR("No InputStream, but no error set!" );
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ }
+
+ return xLockBytes;
+}
+
+UcbLockBytesRef UcbLockBytes::CreateLockBytes( const Reference < XContent >& xContent, const Sequence < PropertyValue >& rProps,
+ StreamMode eOpenMode, const Reference < XInteractionHandler >& xInteractionHandler, UcbLockBytesHandler* pHandler )
+{
+ if( !xContent.is() )
+ return NULL;;
+
+ UcbLockBytesRef xLockBytes = new UcbLockBytes( pHandler );
+ xLockBytes->SetSynchronMode( !pHandler );
+ Reference< XActiveDataControl > xSink;
+ if ( eOpenMode & STREAM_WRITE )
+ xSink = (XActiveDataControl*) new UcbStreamer_Impl( xLockBytes );
+ else
+ xSink = (XActiveDataControl*) new UcbDataSink_Impl( xLockBytes );
+
+ if ( rProps.getLength() )
+ {
+ Reference < XCommandProcessor > xProcessor( xContent, UNO_QUERY );
+ Command aCommand;
+ aCommand.Name = ::rtl::OUString::createFromAscii("setPropertyValues");
+ aCommand.Handle = -1; /* unknown */
+ aCommand.Argument <<= rProps;
+ xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() );
+ }
+
+ OpenCommandArgument2 aArgument;
+ aArgument.Sink = xSink;
+ aArgument.Mode = OpenMode::DOCUMENT;
+
+ Command aCommand;
+ aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("open") );
+ aCommand.Argument <<= aArgument;
+
+ Reference< XProgressHandler > xProgressHdl = new ProgressHandler_Impl( LINK( &xLockBytes, UcbLockBytes, DataAvailHdl ) );
+
+ sal_Bool bError = UCBOpenContentSync( xLockBytes,
+ xContent,
+ aCommand,
+ xSink,
+ xInteractionHandler,
+ xProgressHdl,
+ pHandler );
+
+ if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
+ {
+ DBG_ERROR("No InputStream, but no error set!" );
+ xLockBytes->SetError( ERRCODE_IO_GENERAL );
+ }
+
+ return xLockBytes;
+}
+
+}