25#include <osl/thread.hxx>
26#include <osl/diagnose.h>
30#include <com/sun/star/lang/XUnoTunnel.hpp>
31#include <com/sun/star/task/XInteractionAbort.hpp>
32#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
33#include <com/sun/star/ucb/CommandFailedException.hpp>
34#include <com/sun/star/ucb/ContentCreationException.hpp>
35#include <com/sun/star/ucb/CommandAbortedException.hpp>
36#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
37#include <com/sun/star/ucb/InteractiveIOException.hpp>
38#include <com/sun/star/ucb/XContentIdentifier.hpp>
39#include <com/sun/star/ucb/XContent.hpp>
40#include <com/sun/star/io/IOException.hpp>
41#include <com/sun/star/io/XActiveDataStreamer.hpp>
42#include <com/sun/star/io/TempFile.hpp>
43#include <com/sun/star/ucb/XCommandProcessor.hpp>
44#include <com/sun/star/task/XInteractionHandler.hpp>
45#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
46#include <com/sun/star/ucb/PostCommandArgument2.hpp>
47#include <com/sun/star/ucb/OpenMode.hpp>
48#include <com/sun/star/beans/PropertyValue.hpp>
49#include <com/sun/star/beans/XPropertiesChangeNotifier.hpp>
50#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
51#include <com/sun/star/io/XActiveDataSink.hpp>
52#include <com/sun/star/io/XActiveDataControl.hpp>
53#include <com/sun/star/io/XSeekable.hpp>
56#include <com/sun/star/io/XTruncate.hpp>
57#include <com/sun/star/lang/IllegalArgumentException.hpp>
81class UcbDataSink_Impl :
public ::cppu::WeakImplHelper< XActiveDataControl, XActiveDataSink >
86 explicit UcbDataSink_Impl( UcbLockBytes* pLockBytes )
91 virtual void SAL_CALL
addListener (
const Reference<XStreamListener> &)
override {}
92 virtual void SAL_CALL
removeListener (
const Reference<XStreamListener> &)
override {}
93 virtual void SAL_CALL
start()
override {}
94 virtual void SAL_CALL terminate()
override
98 virtual void SAL_CALL setInputStream (
const Reference<XInputStream> &rxInputStream)
override
100 virtual Reference<XInputStream> SAL_CALL getInputStream()
override
107class UcbStreamer_Impl :
public ::cppu::WeakImplHelper< XActiveDataStreamer, XActiveDataControl >
113 explicit UcbStreamer_Impl( UcbLockBytes* pLockBytes )
118 virtual void SAL_CALL
addListener (
const Reference<XStreamListener> &)
override {}
119 virtual void SAL_CALL
removeListener (
const Reference<XStreamListener> &)
override {}
120 virtual void SAL_CALL
start()
override {}
121 virtual void SAL_CALL terminate()
override
125 virtual void SAL_CALL setStream(
const Reference< XStream >& aStream )
override
127 virtual Reference< XStream > SAL_CALL getStream()
override
134class UcbTaskEnvironment :
public ::cppu::WeakImplHelper< XCommandEnvironment >
140 UcbTaskEnvironment(
const Reference< XInteractionHandler>& rxInteractionHandler,
141 const Reference< XProgressHandler>& rxProgressHandler )
146 virtual Reference<XInteractionHandler> SAL_CALL getInteractionHandler()
override
149 virtual Reference<XProgressHandler> SAL_CALL getProgressHandler()
override
156class UcbPropertiesChangeListener_Impl :
public ::cppu::WeakImplHelper< XPropertiesChangeListener >
165 virtual void SAL_CALL disposing (
const EventObject &)
override {}
166 virtual void SAL_CALL propertiesChange (
const Sequence<PropertyChangeEvent> &rEvent)
override;
171void SAL_CALL UcbPropertiesChangeListener_Impl::propertiesChange (
const Sequence<PropertyChangeEvent> &rEvent)
173 for (
const auto& rPropChangeEvent : rEvent)
175 if (rPropChangeEvent.PropertyName ==
"DocumentHeader")
196 Reference < XContent >
const & xContent,
197 Reference < XInteractionHandler >
const & xInteract,
201 enum class ResultType {
222 ConditionRes(osl::Mutex& aMutex,Moderator& aModerator)
229 bool applies()
const override {
230 return m_aModerator.m_aResultType != ResultType::NORESULT;
243 Result getResult(
const sal_uInt32 milliSec);
255 ConditionRep(osl::Mutex& aMutex,Moderator& aModerator)
262 bool applies()
const override {
270 void setReply(ReplyType);
272 void handle(
const Reference<XInteractionRequest >& Request );
274 void setStream(
const Reference< XStream >& aStream);
275 void setInputStream(
const Reference<XInputStream> &rxInputStream);
278 virtual void SAL_CALL
run()
override;
279 virtual void SAL_CALL onTerminated()
override;
284 friend class ConditionRes;
291 friend class ConditionRep;
300class ModeratorsActiveDataStreamer
301 :
public ::cppu::WeakImplHelper<XActiveDataStreamer>
305 explicit ModeratorsActiveDataStreamer(Moderator &theModerator);
308 virtual void SAL_CALL
310 const Reference< XStream >& aStream
313 virtual Reference<XStream> SAL_CALL getStream ()
override
326class ModeratorsActiveDataSink
327 :
public ::cppu::WeakImplHelper<XActiveDataSink>
331 explicit ModeratorsActiveDataSink(Moderator &theModerator);
334 virtual void SAL_CALL
336 const Reference<XInputStream> &rxInputStream
339 virtual Reference<XInputStream> SAL_CALL getInputStream()
override
353ModeratorsActiveDataSink::ModeratorsActiveDataSink(Moderator &theModerator)
360ModeratorsActiveDataSink::setInputStream (
361 const Reference<XInputStream> &rxInputStream
369ModeratorsActiveDataStreamer::ModeratorsActiveDataStreamer(
370 Moderator &theModerator
378ModeratorsActiveDataStreamer::setStream (
379 const Reference<XStream> &rxStream
389class ModeratorsInteractionHandler
390 :
public ::cppu::WeakImplHelper<XInteractionHandler>
394 explicit ModeratorsInteractionHandler(Moderator &theModerator);
396 virtual void SAL_CALL
397 handle(
const Reference<XInteractionRequest >& Request )
override;
406ModeratorsInteractionHandler::ModeratorsInteractionHandler(
407 Moderator &aModerator)
413ModeratorsInteractionHandler::handle(
414 const Reference<XInteractionRequest >& Request
422 Reference < XContent >
const & xContent,
423 Reference < XInteractionHandler >
const & xInteract,
434 new UcbTaskEnvironment(
435 xInteract.is() ? new ModeratorsInteractionHandler(*this) : nullptr,
442 Reference<XInterface> *pxSink =
nullptr;
444 PostCommandArgument2 aPostArg;
445 OpenCommandArgument2 aOpenArg;
448 if(
m_aArg.Argument >>= aPostArg) {
449 pxSink = &aPostArg.Sink;
452 else if(
m_aArg.Argument >>= aOpenArg) {
453 pxSink = &aOpenArg.Sink;
458 throw ContentCreationException();
460 Reference < XActiveDataSink > xActiveSink(*pxSink,UNO_QUERY);
462 pxSink->set(getXWeak(
new ModeratorsActiveDataSink(*
this)));
464 Reference<XActiveDataStreamer> xStreamer( *pxSink, UNO_QUERY );
465 if ( xStreamer.is() )
466 pxSink->set(getXWeak(
new ModeratorsActiveDataStreamer(*
this)));
469 m_aArg.Argument <<= aPostArg;
471 m_aArg.Argument <<= aOpenArg;
474Moderator::Result Moderator::getResult(
const sal_uInt32 milliSec)
488 ret.type = ResultType::TIMEDOUT;
494void Moderator::setReply(ReplyType aReplyType )
500void Moderator::handle(
const Reference<XInteractionRequest >& Request )
502 ReplyType aReplyType;
519 if(aReplyType == EXIT) {
520 const Sequence<Reference<XInteractionContinuation> >
aSeq(
521 Request->getContinuations());
522 for(
const auto& rContinuation : aSeq) {
523 Reference<XInteractionAbort> aRef(rContinuation,UNO_QUERY);
533 }
while(aReplyType != REQUESTHANDLED);
536void Moderator::setStream(
const Reference< XStream >& aStream)
543 ReplyType aReplyType;
549 if(aReplyType == EXIT)
553void Moderator::setInputStream(
const Reference<XInputStream> &rxInputStream)
560 ReplyType aReplyType;
566 if(aReplyType == EXIT)
570void SAL_CALL Moderator::run()
572 osl_setThreadName(
"utl::Moderator");
574 ResultType aResultType;
576 IOErrorCode nIOErrorCode = IOErrorCode_ABORT;
581 aResultType = ResultType::RESULT;
583 catch (
const CommandAbortedException&)
585 aResultType = ResultType::COMMANDABORTED;
587 catch (
const CommandFailedException&)
589 aResultType = ResultType::COMMANDFAILED;
591 catch (
const InteractiveIOException& r)
593 nIOErrorCode = r.Code;
594 aResultType = ResultType::INTERACTIVEIO;
596 catch (
const UnsupportedDataSinkException &)
598 aResultType = ResultType::UNSUPPORTED;
600 catch (
const Exception&)
602 aResultType = ResultType::GENERAL;
613void SAL_CALL Moderator::onTerminated()
627 const Reference < XContent >& xContent,
629 const Reference < XInterface >& xSink,
630 const Reference < XInteractionHandler >& xInteract );
634 Reference < XContent >
const & xContent,
636 const Reference < XInterface >& xSink,
637 Reference < XInteractionHandler >
const & xInteract )
644 Reference<XContentIdentifier> xContId(
645 xContent.is() ? xContent->getIdentifier() :
nullptr );
649 aScheme = xContId->getContentProviderScheme();
652 if( ! aScheme.equalsIgnoreAsciiCase(
"http") &&
653 ! aScheme.equalsIgnoreAsciiCase(
"https") &&
654 ! aScheme.equalsIgnoreAsciiCase(
"vnd.sun.star.webdav") &&
655 ! aScheme.equalsIgnoreAsciiCase(
"vnd.sun.star.webdavs") &&
656 ! aScheme.equalsIgnoreAsciiCase(
"ftp"))
658 xLockBytes,xContent,rArg,
xSink,xInteract);
660 if ( !aScheme.equalsIgnoreAsciiCase(
"http" ) &&
661 !aScheme.equalsIgnoreAsciiCase(
"https" ) )
662 xLockBytes->SetStreamValid();
664 Reference< XPropertiesChangeListener > xListener;
665 Reference< XPropertiesChangeNotifier > xProps(xContent,UNO_QUERY);
668 new UcbPropertiesChangeListener_Impl(xLockBytes);
669 xProps->addPropertiesChangeListener(
674 bool bException(
false);
675 bool bAborted(
false);
676 bool bResultAchieved(
false);
678 Moderator* pMod =
nullptr;
681 pMod =
new Moderator(xContent,xInteract,rArg);
687 catch (
const ContentCreationException&)
689 bResultAchieved = bException =
true;
693 sal_uInt32 nTimeout(5000);
694 while(!bResultAchieved) {
697 Moderator::Result res = pMod->getResult(nTimeout);
700 case Moderator::ResultType::STREAM:
702 Reference<XStream>
result;
703 if(res.result >>=
result) {
704 Reference < XActiveDataStreamer > xStreamer(
709 xStreamer->setStream(
result);
711 pMod->setReply(Moderator::REQUESTHANDLED);
714 case Moderator::ResultType::INPUTSTREAM:
716 Reference<XInputStream>
result;
718 Reference < XActiveDataSink > xActiveSink(
723 xActiveSink->setInputStream(
result);
724 pMod->setReply(Moderator::REQUESTHANDLED);
727 case Moderator::ResultType::TIMEDOUT:
729 Reference<XInteractionRetry> xRet;
731 InteractiveNetworkConnectException aExcep;
734 xContId->getContentIdentifier() :
736 aExcep.Server =
aURL.GetHost();
737 aExcep.Classification = InteractionClassification_ERROR;
738 aExcep.Message =
"server not responding after five seconds";
747 Sequence<Reference<XInteractionContinuation> >
aSeq { retryP, abortP };
749 xIR->setContinuations(
aSeq);
750 xInteract->handle(xIR);
752 = xIR->getSelection();
754 Reference<XInterface> xInt(ref);
755 xRet.set(xInt,UNO_QUERY);
766 case Moderator::ResultType::INTERACTIONREQUEST:
768 Reference<XInteractionRequest> Request;
769 res.result >>= Request;
770 xInteract->handle(Request);
771 pMod->setReply(Moderator::REQUESTHANDLED);
774 case Moderator::ResultType::RESULT:
776 bResultAchieved =
true;
779 case Moderator::ResultType::COMMANDABORTED:
785 case Moderator::ResultType::COMMANDFAILED:
791 case Moderator::ResultType::INTERACTIVEIO:
794 if ( res.ioErrorCode == IOErrorCode_ACCESS_DENIED ||
795 res.ioErrorCode == IOErrorCode_LOCKING_VIOLATION )
797 else if ( res.ioErrorCode == IOErrorCode_NOT_EXISTING )
799 else if ( res.ioErrorCode == IOErrorCode_CANT_READ )
805 case Moderator::ResultType::UNSUPPORTED:
819 bResultAchieved |= bException;
820 bResultAchieved |= bAborted;
821 if(nTimeout == 5000) nTimeout *= 2;
824 if(pMod) pMod->setReply(Moderator::EXIT);
826 if ( bAborted || bException )
828 Reference < XActiveDataSink > xActiveSink(
xSink, UNO_QUERY );
829 if ( xActiveSink.is() )
830 xActiveSink->setInputStream( Reference < XInputStream >() );
832 Reference < XActiveDataStreamer > xStreamer(
xSink, UNO_QUERY );
833 if ( xStreamer.is() )
834 xStreamer->setStream( Reference < XStream >() );
837 Reference < XActiveDataControl > xControl(
xSink, UNO_QUERY );
839 xControl->terminate();
842 xProps->removePropertiesChangeListener(
846 return ( bAborted || bException );
854 const Reference < XContent >& xContent,
856 const Reference < XInterface >& xSink,
857 const Reference < XInteractionHandler >& xInteract )
860 xContent,
new UcbTaskEnvironment( xInteract,
nullptr ),
862 Reference < XContentIdentifier > xIdent = xContent->getIdentifier();
863 OUString aScheme = xIdent->getContentProviderScheme();
867 if ( !aScheme.equalsIgnoreAsciiCase(
"http") )
868 xLockBytes->SetStreamValid();
870 Reference< XPropertiesChangeListener > xListener =
new UcbPropertiesChangeListener_Impl( xLockBytes );
871 Reference< XPropertiesChangeNotifier > xProps ( xContent, UNO_QUERY );
875 bool bException =
false;
876 bool bAborted =
false;
882 catch (
const CommandAbortedException&)
887 catch (
const CommandFailedException&)
892 catch (
const InteractiveIOException& r)
895 if ( r.Code == IOErrorCode_ACCESS_DENIED || r.Code == IOErrorCode_LOCKING_VIOLATION )
897 else if ( r.Code == IOErrorCode_NOT_EXISTING )
899 else if ( r.Code == IOErrorCode_CANT_READ )
904 catch (
const UnsupportedDataSinkException&)
915 if ( bAborted || bException )
917 Reference < XActiveDataSink > xActiveSink(
xSink, UNO_QUERY );
918 if ( xActiveSink.is() )
919 xActiveSink->setInputStream( Reference < XInputStream >() );
921 Reference < XActiveDataStreamer > xStreamer(
xSink, UNO_QUERY );
922 if ( xStreamer.is() )
923 xStreamer->setStream( Reference < XStream >() );
926 Reference < XActiveDataControl > xControl(
xSink, UNO_QUERY );
928 xControl->terminate();
933 return ( bAborted || bException );
936UcbLockBytes::UcbLockBytes()
939 , m_bDontClose( false )
940 , m_bStreamValid (false)
981 std::unique_lock aGuard(
m_aMutex );
988 std::unique_lock aGuard(
m_aMutex );
1004 std::unique_lock aGuard(
m_aMutex );
1024 Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1060 OSL_FAIL(
"No InputStream, but no error set!" );
1066 void *pBuffer, std::size_t nCount, std::size_t *pRead)
const
1087 if ( !xSeekable.is() )
1092 xSeekable->seek(
nPos );
1098 catch (
const css::lang::IllegalArgumentException&)
1113 sal_uInt64 nLen = xSeekable->getLength();
1118 comphelper::ByteReader* pByteReader =
dynamic_cast< comphelper::ByteReader*
>(
xStream.get());
1121 nSize = pByteReader->readSomeBytes(
static_cast<sal_Int8*
>(pBuffer), sal_Int32(
nCount) );
1125 Sequence<sal_Int8>
aData;
1127 memcpy (pBuffer,
aData.getConstArray(), nSize);
1136 *pRead =
static_cast<std::size_t
>(nSize);
1142 std::size_t nCount, std::size_t *pWritten)
1152 if ( !xOutputStream.is() || !xSeekable.is() )
1157 xSeekable->seek(
nPos );
1168 xOutputStream->writeBytes(
aData );
1183 if ( !xOutputStream.is() )
1188 xOutputStream->flush();
1202 std::size_t nSize = aStat.
nSize;
1204 if ( nSize > nNewSize )
1213 SAL_INFO(
"unotools.ucbhelper",
"Not truncable!");
1217 if ( nSize < nNewSize )
1219 std::size_t nDiff = nNewSize-nSize,
nCount=0;
1220 std::unique_ptr<sal_uInt8[]> pBuffer(
new sal_uInt8[ nDiff ]);
1221 memset(pBuffer.get(), 0, nDiff);
1251 else if( !xSeekable.is() )
1268 if( !xInputStream.is() )
1272 xLockBytes->setDontClose();
1273 xLockBytes->setInputStream( xInputStream );
1274 xLockBytes->terminate();
1284 xLockBytes->setDontClose();
1285 xLockBytes->setStream( xStream );
1286 xLockBytes->terminate();
1291 StreamMode eOpenMode,
const Reference < XInteractionHandler >& xInteractionHandler )
1293 if( !xContent.is() )
1297 xLockBytes->SetSynchronMode();
1298 Reference< XActiveDataControl >
xSink;
1299 if ( eOpenMode & StreamMode::WRITE )
1300 xSink =
new UcbStreamer_Impl(xLockBytes.get());
1302 xSink =
new UcbDataSink_Impl(xLockBytes.get());
1304 if ( rProps.hasElements() )
1306 Reference < XCommandProcessor >
xProcessor( xContent, UNO_QUERY );
1308 aCommand.Name =
"setPropertyValues";
1311 xProcessor->execute( aCommand, 0, Reference < XCommandEnvironment >() );
1314 OpenCommandArgument2 aArgument;
1315 aArgument.Sink =
xSink;
1316 aArgument.Mode = OpenMode::DOCUMENT;
1326 xInteractionHandler );
1328 if ( xLockBytes->GetError() == ERRCODE_NONE && ( bError || !xLockBytes->getInputStream().is() ) )
1330 OSL_FAIL(
"No InputStream, but no error set!" );
1331 xLockBytes->SetError( ERRCODE_IO_GENERAL );
::rtl::Reference< IEventProcessor > xProcessor
void SetSynchronMode(bool bTheSync=true)
bool IsSynchronMode() const
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
ErrCode const & GetError() const
css::uno::Reference< css::io::XOutputStream > getOutputStream() const
osl::Condition m_aTerminated
css::uno::Reference< css::io::XSeekable > m_xSeekable
virtual ~UcbLockBytes() override
virtual ErrCode ReadAt(sal_uInt64 nPos, void *pBuffer, std::size_t nCount, std::size_t *pRead) const override
css::uno::Reference< css::io::XOutputStream > m_xOutputStream
virtual ErrCode Flush() const override
css::uno::Reference< css::io::XInputStream > getInputStream()
void SetError(ErrCode nError)
void setStream(const css::uno::Reference< css::io::XStream > &rxStream)
static UcbLockBytesRef CreateInputLockBytes(const css::uno::Reference< css::io::XInputStream > &xContent)
virtual ErrCode Stat(SvLockBytesStat *pStat) const override
bool setInputStreamImpl(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< css::io::XInputStream > &rxInputStream, bool bSetXSeekable=true)
virtual ErrCode SetSize(sal_uInt64) override
static UcbLockBytesRef CreateLockBytes(const css::uno::Reference< css::ucb::XContent > &xContent, const css::uno::Sequence< css::beans::PropertyValue > &rProps, StreamMode eMode, const css::uno::Reference< css::task::XInteractionHandler > &xInter)
css::uno::Reference< css::io::XSeekable > getSeekable() const
virtual ErrCode WriteAt(sal_uInt64, const void *, std::size_t, std::size_t *pWritten) override
osl::Condition m_aInitialized
bool setInputStream(const css::uno::Reference< css::io::XInputStream > &rxInputStream, bool bSetXSeekable=true)
css::uno::Reference< css::io::XInputStream > m_xInputStream
#define DBG_ASSERT(sCon, aError)
#define ERRCODE_IO_ACCESSDENIED
#define ERRCODE_IO_CANTTELL
#define ERRCODE_IO_CANTREAD
#define ERRCODE_IO_GENERAL
#define ERRCODE_IO_PENDING
#define ERRCODE_IO_CANTSEEK
#define ERRCODE_IO_CANTWRITE
#define ERRCODE_IO_NOTEXISTS
#define ERRCODE_IO_NOTSUPPORTED
#define ERRCODE_IO_INVALIDACCESS
#define ERRCODE_IO_INVALIDPARAMETER
tools::SvRef< SvBaseLink > xSink
Sequence< sal_Int8 > aSeq
#define SAL_INFO(area, stream)
std::unique_ptr< sal_Int32[]> pData
def run(arg=None, arg2=-1)
constexpr OUStringLiteral aData
void addListener(const InterfaceRef &xObject, const css::uno::Reference< css::lang::XEventListener > &xListener)
void removeListener(const InterfaceRef &xObject, const css::uno::Reference< css::lang::XEventListener > &xListener)
Reference< XComponentContext > getProcessComponentContext()
tools::SvRef< UcbLockBytes > UcbLockBytesRef
static bool UCBOpenContentSync(const UcbLockBytesRef &xLockBytes, Reference< XContent > const &xContent, const Command &rArg, const Reference< XInterface > &xSink, Reference< XInteractionHandler > const &xInteract)
static bool UCBOpenContentSync_(const UcbLockBytesRef &xLockBytes, const Reference< XContent > &xContent, const Command &rArg, const Reference< XInterface > &xSink, const Reference< XInteractionHandler > &xInteract)
Function for opening UCB contents synchronously, but with handled timeout;.
::ucbhelper::Content m_aContent
IOErrorCode m_nIOErrorCode
UcbLockBytesRef m_xLockBytes
Reference< XInteractionHandler > m_xInteractionHandler
Reference< XStream > m_xStream
Reference< XProgressHandler > m_xProgressHandler