diff options
Diffstat (limited to 'comphelper/source/streaming')
-rw-r--r-- | comphelper/source/streaming/basicio.cxx | 174 | ||||
-rw-r--r-- | comphelper/source/streaming/makefile.mk | 54 | ||||
-rw-r--r-- | comphelper/source/streaming/memorystream.cxx | 247 | ||||
-rw-r--r-- | comphelper/source/streaming/oslfile2streamwrap.cxx | 198 | ||||
-rw-r--r-- | comphelper/source/streaming/otransactedfilestream.cxx | 824 | ||||
-rw-r--r-- | comphelper/source/streaming/seekableinput.cxx | 267 | ||||
-rw-r--r-- | comphelper/source/streaming/seqinputstreamserv.cxx | 251 | ||||
-rw-r--r-- | comphelper/source/streaming/seqoutputstreamserv.cxx | 172 | ||||
-rw-r--r-- | comphelper/source/streaming/seqstream.cxx | 243 | ||||
-rw-r--r-- | comphelper/source/streaming/streamsection.cxx | 122 |
10 files changed, 2552 insertions, 0 deletions
diff --git a/comphelper/source/streaming/basicio.cxx b/comphelper/source/streaming/basicio.cxx new file mode 100644 index 000000000000..eef5c6b844fa --- /dev/null +++ b/comphelper/source/streaming/basicio.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <comphelper/basicio.hxx> + +//......................................................................... +namespace comphelper +{ +//......................................................................... + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << ( + const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, + const starawt::FontDescriptor& _rFont) +{ + _rxOutStream->writeUTF( _rFont.Name ); + _rxOutStream->writeShort( _rFont.Height ); + _rxOutStream->writeShort( _rFont.Width ); + _rxOutStream->writeUTF( _rFont.StyleName ); + _rxOutStream->writeShort( _rFont.Family ); + _rxOutStream->writeShort( _rFont.CharSet ); + _rxOutStream->writeShort( _rFont.Pitch ); + _rxOutStream->writeDouble( _rFont.CharacterWidth ); + _rxOutStream->writeDouble( _rFont.Weight ); + _rxOutStream->writeShort( static_cast< sal_Int16 >(_rFont.Slant) ); + _rxOutStream->writeShort( _rFont.Underline ); + _rxOutStream->writeShort( _rFont.Strikeout ); + _rxOutStream->writeDouble( _rFont.Orientation ); + _rxOutStream->writeBoolean( _rFont.Kerning ); + _rxOutStream->writeBoolean( _rFont.WordLineMode ); + _rxOutStream->writeShort( _rFont.Type ); + return _rxOutStream; +} + +// FontDescriptor +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> ( + const staruno::Reference<stario::XObjectInputStream>& _rxInStream, + starawt::FontDescriptor& _rFont) +{ + // schreiben des Fontdescriptors + _rFont.Name = _rxInStream->readUTF(); + _rFont.Height = _rxInStream->readShort(); + _rFont.Width = _rxInStream->readShort(); + _rFont.StyleName = _rxInStream->readUTF(); + _rFont.Family = _rxInStream->readShort(); + _rFont.CharSet = _rxInStream->readShort(); + _rFont.Pitch = _rxInStream->readShort(); + _rFont.CharacterWidth = static_cast< float >(_rxInStream->readDouble()); + _rFont.Weight = static_cast< float >(_rxInStream->readDouble()); + _rFont.Slant = (starawt::FontSlant)_rxInStream->readShort(); + _rFont.Underline = _rxInStream->readShort(); + _rFont.Strikeout = _rxInStream->readShort(); + _rFont.Orientation = static_cast< float >(_rxInStream->readDouble()); + _rFont.Kerning = _rxInStream->readBoolean(); + _rFont.WordLineMode = _rxInStream->readBoolean(); + _rFont.Type = _rxInStream->readShort(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, sal_Bool& _rVal) +{ + _rVal = _rxInStream->readBoolean(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, sal_Bool _bVal) +{ + _rxOutStream->writeBoolean(_bVal); + return _rxOutStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, ::rtl::OUString& rStr) +{ + rStr = _rxInStream->readUTF(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, const ::rtl::OUString& rStr) +{ + _rxOutStream->writeUTF(rStr); + return _rxOutStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, sal_Int16& _rValue) +{ + _rValue = _rxInStream->readShort(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, sal_Int16 _nValue) +{ + _rxOutStream->writeShort(_nValue); + return _rxOutStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, sal_uInt16& _rValue) +{ + _rValue = _rxInStream->readShort(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, sal_uInt16 _nValue) +{ + _rxOutStream->writeShort(_nValue); + return _rxOutStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, sal_uInt32& _rValue) +{ + _rValue = _rxInStream->readLong(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, sal_uInt32 _nValue) +{ + _rxOutStream->writeLong(_nValue); + return _rxOutStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectInputStream>& operator >> (const staruno::Reference<stario::XObjectInputStream>& _rxInStream, sal_Int32& _rValue) +{ + _rValue = _rxInStream->readLong(); + return _rxInStream; +} + +//------------------------------------------------------------------------------ +const staruno::Reference<stario::XObjectOutputStream>& operator << (const staruno::Reference<stario::XObjectOutputStream>& _rxOutStream, sal_Int32 _nValue) +{ + _rxOutStream->writeLong(_nValue); + return _rxOutStream; +} + +//......................................................................... +} // namespace comphelper +//......................................................................... + diff --git a/comphelper/source/streaming/makefile.mk b/comphelper/source/streaming/makefile.mk new file mode 100644 index 000000000000..2a6ea38ca65e --- /dev/null +++ b/comphelper/source/streaming/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=comphelper +TARGET=streaming + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files ------------------------------------- + +SLOFILES= $(SLO)$/basicio.obj \ + $(SLO)$/oslfile2streamwrap.obj \ + $(SLO)$/seqstream.obj \ + $(SLO)$/seqinputstreamserv.obj \ + $(SLO)$/seqoutputstreamserv.obj \ + $(SLO)$/streamsection.obj \ + $(SLO)$/seekableinput.obj \ + $(SLO)$/otransactedfilestream.obj \ + $(SLO)$/memorystream.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk + diff --git a/comphelper/source/streaming/memorystream.cxx b/comphelper/source/streaming/memorystream.cxx new file mode 100644 index 000000000000..5298b7511f09 --- /dev/null +++ b/comphelper/source/streaming/memorystream.cxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * 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_comphelper.hxx" + +#include "comphelper_module.hxx" + +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XSeekableInputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase4.hxx> + +#include <string.h> +#include <vector> + +using ::rtl::OUString; +using ::cppu::OWeakObject; +using ::cppu::WeakImplHelper4; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::osl; + +namespace comphelper +{ + +class UNOMemoryStream : public WeakImplHelper4 < XStream, XSeekableInputStream, XOutputStream, XTruncate > +{ +public: + UNOMemoryStream(); + virtual ~UNOMemoryStream(); + + // XStream + virtual Reference< XInputStream > SAL_CALL getInputStream( ) throw (RuntimeException); + virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) throw (RuntimeException); + + // XInputStream + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual sal_Int32 SAL_CALL available() throw (NotConnectedException, IOException, RuntimeException); + virtual void SAL_CALL closeInput() throw (NotConnectedException, IOException, RuntimeException); + + // XSeekable + virtual void SAL_CALL seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException); + virtual sal_Int64 SAL_CALL getPosition() throw (IOException, RuntimeException); + virtual sal_Int64 SAL_CALL getLength() throw (IOException, RuntimeException); + + // XOutputStream + virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual void SAL_CALL flush() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual void SAL_CALL closeOutput() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + + // XTruncate + virtual void SAL_CALL truncate() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo - static versions (used for component registration) + static ::rtl::OUString SAL_CALL getImplementationName_static(); + static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(); + static Reference< XInterface > SAL_CALL Create( const Reference< ::com::sun::star::uno::XComponentContext >& ); + +private: + std::vector< sal_Int8 > maData; + sal_Int32 mnCursor; +}; + +UNOMemoryStream::UNOMemoryStream() +: mnCursor(0) +{ +} + +UNOMemoryStream::~UNOMemoryStream() +{ +} + +// XStream +Reference< XInputStream > SAL_CALL UNOMemoryStream::getInputStream( ) throw (RuntimeException) +{ + return this; +} + +Reference< XOutputStream > SAL_CALL UNOMemoryStream::getOutputStream( ) throw (RuntimeException) +{ + return this; +} + +// XInputStream +sal_Int32 SAL_CALL UNOMemoryStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + if( nBytesToRead < 0 ) + throw IOException(); + + nBytesToRead = std::min( nBytesToRead, available() ); + aData.realloc( nBytesToRead ); + + if( nBytesToRead ) + { + sal_Int8* pData = static_cast<sal_Int8*>(&(*maData.begin())); + sal_Int8* pCursor = &((pData)[mnCursor]); + memcpy( (void*)aData.getArray(), (void*)pCursor, nBytesToRead ); + + mnCursor += nBytesToRead; + } + + return nBytesToRead; +} + +sal_Int32 SAL_CALL UNOMemoryStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + return readBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL UNOMemoryStream::skipBytes( sal_Int32 nBytesToSkip ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + if( nBytesToSkip < 0 ) + throw IOException(); + + mnCursor += std::min( nBytesToSkip, available() ); +} + +sal_Int32 SAL_CALL UNOMemoryStream::available() throw (NotConnectedException, IOException, RuntimeException) +{ + return static_cast< sal_Int32 >( maData.size() ) - mnCursor; +} + +void SAL_CALL UNOMemoryStream::closeInput() throw (NotConnectedException, IOException, RuntimeException) +{ + mnCursor = 0; +} + +// XSeekable +void SAL_CALL UNOMemoryStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException) +{ + if( (location < 0) || (location > SAL_MAX_INT32) ) + throw IllegalArgumentException( OUString(RTL_CONSTASCII_USTRINGPARAM("this implementation does not support more than 2GB!")), Reference< XInterface >(static_cast<OWeakObject*>(this)), 0 ); + + // seek operation should be able to resize the stream + if ( location > static_cast< sal_Int64 >( maData.size() ) ) + maData.resize( static_cast< sal_Int32 >( location ) ); + + if ( location > static_cast< sal_Int64 >( maData.size() ) ) + maData.resize( static_cast< sal_Int32 >( location ) ); + + mnCursor = static_cast< sal_Int32 >( location ); +} + +sal_Int64 SAL_CALL UNOMemoryStream::getPosition() throw (IOException, RuntimeException) +{ + return static_cast< sal_Int64 >( mnCursor ); +} + +sal_Int64 SAL_CALL UNOMemoryStream::getLength() throw (IOException, RuntimeException) +{ + return static_cast< sal_Int64 >( maData.size() ); +} + +// XOutputStream +void SAL_CALL UNOMemoryStream::writeBytes( const Sequence< sal_Int8 >& aData ) throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + const sal_Int32 nBytesToWrite( aData.getLength() ); + if( nBytesToWrite ) + { + sal_Int64 nNewSize = static_cast< sal_Int64 >( mnCursor + nBytesToWrite ); + if( nNewSize > SAL_MAX_INT32 ) + { + OSL_ASSERT(false); + throw IOException( OUString(RTL_CONSTASCII_USTRINGPARAM("this implementation does not support more than 2GB!")), Reference< XInterface >(static_cast<OWeakObject*>(this)) ); + } + + if( static_cast< sal_Int32 >( nNewSize ) > static_cast< sal_Int32 >( maData.size() ) ) + maData.resize( static_cast< sal_Int32 >( nNewSize ) ); + + sal_Int8* pData = static_cast<sal_Int8*>(&(*maData.begin())); + sal_Int8* pCursor = &(pData[mnCursor]); + memcpy( (void*)pCursor, (void*)aData.getConstArray(), nBytesToWrite ); + + mnCursor += nBytesToWrite; + } +} + +void SAL_CALL UNOMemoryStream::flush() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ +} + +void SAL_CALL UNOMemoryStream::closeOutput() throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + mnCursor = 0; +} + +//XTruncate +void SAL_CALL UNOMemoryStream::truncate() throw (IOException, RuntimeException) +{ + maData.resize( 0 ); + mnCursor = 0; +} + +::rtl::OUString SAL_CALL UNOMemoryStream::getImplementationName_static() +{ + static const OUString sImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.MemoryStream" ) ); + return sImplName; +} + +Sequence< ::rtl::OUString > SAL_CALL UNOMemoryStream::getSupportedServiceNames_static() +{ + Sequence< OUString > aSeq(1); + aSeq[0] = getImplementationName_static(); + return aSeq; +} + +Reference< XInterface > SAL_CALL UNOMemoryStream::Create( + const Reference< XComponentContext >& ) +{ + return static_cast<OWeakObject*>(new UNOMemoryStream()); +} + +} // namespace comphelper + +void createRegistryInfo_UNOMemoryStream() +{ + static ::comphelper::module::OAutoRegistration< ::comphelper::UNOMemoryStream > aAutoRegistration; +} diff --git a/comphelper/source/streaming/oslfile2streamwrap.cxx b/comphelper/source/streaming/oslfile2streamwrap.cxx new file mode 100644 index 000000000000..9cf8eeaaf08a --- /dev/null +++ b/comphelper/source/streaming/oslfile2streamwrap.cxx @@ -0,0 +1,198 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <comphelper/oslfile2streamwrap.hxx> + +#include <algorithm> + +namespace comphelper +{ + using namespace osl; + +//------------------------------------------------------------------ +OSLInputStreamWrapper::OSLInputStreamWrapper( File& _rFile ) + :m_pFile(&_rFile) + ,m_bFileOwner(sal_False) +{ +} + +//------------------------------------------------------------------ +OSLInputStreamWrapper::OSLInputStreamWrapper( File* pStream, sal_Bool bOwner ) + :m_pFile( pStream ) + ,m_bFileOwner( bOwner ) +{ +} + +//------------------------------------------------------------------ +OSLInputStreamWrapper::~OSLInputStreamWrapper() +{ + if( m_bFileOwner ) + delete m_pFile; +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OSLInputStreamWrapper::readBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + if (!m_pFile) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + if (nBytesToRead < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + ::osl::MutexGuard aGuard( m_aMutex ); + + aData.realloc(nBytesToRead); + + sal_uInt64 nRead = 0; + FileBase::RC eError = m_pFile->read((void*)aData.getArray(), nBytesToRead, nRead); + if (eError != FileBase::E_None) + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + // Wenn gelesene Zeichen < MaxLength, staruno::Sequence anpassen + if (nRead < (sal_uInt32)nBytesToRead) + aData.realloc( sal::static_int_cast< sal_Int32 >(nRead) ); + + return sal::static_int_cast< sal_Int32 >(nRead); +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OSLInputStreamWrapper::readSomeBytes(staruno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + if (!m_pFile) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + if (nMaxBytesToRead < 0) + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + /* + if (m_pFile->IsEof()) + { + aData.realloc(0); + return 0; + } + else + */ + return readBytes(aData, nMaxBytesToRead); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSLInputStreamWrapper::skipBytes(sal_Int32 nBytesToSkip) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_pFile) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + sal_uInt64 nCurrentPos; + m_pFile->getPos(nCurrentPos); + + sal_uInt64 nNewPos = nCurrentPos + nBytesToSkip; + FileBase::RC eError = m_pFile->setPos(osl_Pos_Absolut, nNewPos); + if (eError != FileBase::E_None) + { + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + } + +#ifdef DBG_UTIL + m_pFile->getPos(nCurrentPos); +// volatile int dummy = 0; // to take a look at last changes ;-) +#endif +} + +//------------------------------------------------------------------------------ +sal_Int32 SAL_CALL OSLInputStreamWrapper::available() throw( stario::NotConnectedException, staruno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if (!m_pFile) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + sal_uInt64 nPos; + FileBase::RC eError = m_pFile->getPos(nPos); + if (eError != FileBase::E_None) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + sal_uInt64 nDummy = 0; + eError = m_pFile->setPos(Pos_End, nDummy); + if (eError != FileBase::E_None) + throw stario::NotConnectedException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + sal_uInt64 nAvailable; + eError = m_pFile->getPos(nAvailable); + if (eError != FileBase::E_None) + throw stario::NotConnectedException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + + nAvailable = nAvailable - nPos; + eError = m_pFile->setPos(Pos_Absolut, nPos); + if (eError != FileBase::E_None) + throw stario::NotConnectedException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + return sal::static_int_cast< sal_Int32 >( + std::max(nAvailable, sal::static_int_cast< sal_uInt64 >(SAL_MAX_INT32))); +} + +//------------------------------------------------------------------------------ +void SAL_CALL OSLInputStreamWrapper::closeInput() throw( stario::NotConnectedException, staruno::RuntimeException ) +{ + if (!m_pFile) + throw stario::NotConnectedException(::rtl::OUString(), static_cast<staruno::XWeak*>(this)); + + m_pFile->close(); + if (m_bFileOwner) + delete m_pFile; + + m_pFile = NULL; +} + +/*************************************************************************/ +// stario::XOutputStream +//------------------------------------------------------------------------------ +void SAL_CALL OSLOutputStreamWrapper::writeBytes(const staruno::Sequence< sal_Int8 >& aData) throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + sal_uInt64 nWritten; + FileBase::RC eError = rFile.write(aData.getConstArray(),aData.getLength(), nWritten); + if (eError != FileBase::E_None + || nWritten != sal::static_int_cast< sal_uInt32 >(aData.getLength())) + { + throw stario::BufferSizeExceededException(::rtl::OUString(),static_cast<staruno::XWeak*>(this)); + } +} + +//------------------------------------------------------------------ +void SAL_CALL OSLOutputStreamWrapper::flush() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ +} + +//------------------------------------------------------------------ +void SAL_CALL OSLOutputStreamWrapper::closeOutput() throw( stario::NotConnectedException, stario::BufferSizeExceededException, staruno::RuntimeException ) +{ + rFile.close(); +} + +} // namespace comphelper + + diff --git a/comphelper/source/streaming/otransactedfilestream.cxx b/comphelper/source/streaming/otransactedfilestream.cxx new file mode 100644 index 000000000000..03539a12305b --- /dev/null +++ b/comphelper/source/streaming/otransactedfilestream.cxx @@ -0,0 +1,824 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <osl/diagnose.h> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/io/XAsyncOutputMonitor.hpp> +#include <com/sun/star/embed/UseBackupException.hpp> + +#include <comphelper/otransactedfilestream.hxx> +#include <comphelper/storagehelper.hxx> +#include <cppuhelper/implbase1.hxx> + +using namespace ::com::sun::star; + +namespace comphelper +{ + +// ======================================================================== +class OTransactionHelper : public ::cppu::WeakImplHelper1 < embed::XTransactedObject > +{ + OTruncatedTransactedFileStream* m_pFileStream; + uno::Reference< io::XStream > m_xStreamHolder; + +public: + OTransactionHelper( OTruncatedTransactedFileStream* pStream ) + : m_pFileStream( pStream ) + { + m_xStreamHolder = static_cast< io::XStream* >( pStream ); + if ( !m_xStreamHolder.is() ) + throw uno::RuntimeException(); + } + + virtual void SAL_CALL commit( ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException); + virtual void SAL_CALL revert( ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException); +}; + +// ------------------------------------------------------------------------ +void SAL_CALL OTransactionHelper::commit( ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException) +{ + m_pFileStream->Commit_Impl(); +} + +// ------------------------------------------------------------------------ +void SAL_CALL OTransactionHelper::revert( ) throw (io::IOException, lang::WrappedTargetException, uno::RuntimeException) +{ + m_pFileStream->Revert_Impl(); +} + +// ======================================================================== +struct TTFileStreamData_Impl +{ + uno::Reference< ucb::XSimpleFileAccess > m_xFileAccess; + sal_Bool m_bDelete; + ::rtl::OUString m_aURL; + + // the streams below are not visible from outside so there is no need to remember position + + // original stream related members + uno::Reference< io::XStream > m_xOrigStream; + uno::Reference< io::XTruncate > m_xOrigTruncate; + uno::Reference< io::XSeekable > m_xOrigSeekable; + uno::Reference< io::XInputStream > m_xOrigInStream; + uno::Reference< io::XOutputStream > m_xOrigOutStream; + + // temporary stream related members + uno::Reference< io::XStream > m_xTempStream; + uno::Reference< io::XTruncate > m_xTempTruncate; + uno::Reference< io::XSeekable > m_xTempSeekable; + uno::Reference< io::XInputStream > m_xTempInStream; + uno::Reference< io::XOutputStream > m_xTempOutStream; + + sal_Bool m_bInOpen; + sal_Bool m_bOutOpen; + + sal_Bool m_bTransacted; + + + TTFileStreamData_Impl( + const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess, + sal_Bool bDelete, + const ::rtl::OUString& aURL, + const uno::Reference< io::XStream >& xOrigStream, + const uno::Reference< io::XTruncate >& xOrigTruncate, + const uno::Reference< io::XSeekable >& xOrigSeekable, + const uno::Reference< io::XInputStream >& xOrigInStream, + const uno::Reference< io::XOutputStream >& xOrigOutStream, + const uno::Reference< io::XStream >& xTempStream, + const uno::Reference< io::XTruncate >& xTempTruncate, + const uno::Reference< io::XSeekable >& xTempSeekable, + const uno::Reference< io::XInputStream >& xTempInStream, + const uno::Reference< io::XOutputStream >& xTempOutStream ) + : m_xFileAccess( xFileAccess ) + , m_bDelete( bDelete ) + , m_aURL( aURL ) + , m_xOrigStream( xOrigStream ) + , m_xOrigTruncate( xOrigTruncate ) + , m_xOrigSeekable( xOrigSeekable ) + , m_xOrigInStream( xOrigInStream ) + , m_xOrigOutStream( xOrigOutStream ) + , m_xTempStream( xTempStream ) + , m_xTempTruncate( xTempTruncate ) + , m_xTempSeekable( xTempSeekable ) + , m_xTempInStream( xTempInStream ) + , m_xTempOutStream( xTempOutStream ) + , m_bInOpen( sal_False ) + , m_bOutOpen( sal_False ) + , m_bTransacted( sal_True ) + {} + + void NoTransaction() + { + m_bDelete = sal_False; + m_bTransacted = sal_False; + m_xTempStream = uno::Reference< io::XStream >(); + m_xTempTruncate = uno::Reference< io::XTruncate >(); + m_xTempSeekable = uno::Reference< io::XSeekable >(); + m_xTempInStream = uno::Reference< io::XInputStream >(); + m_xTempOutStream = uno::Reference< io::XOutputStream >(); + } + + void FreeOriginal() + { + m_bDelete = sal_False; + m_bTransacted = sal_False; + + m_xOrigStream = m_xTempStream; + m_xTempStream = uno::Reference< io::XStream >(); + + m_xOrigTruncate = m_xTempTruncate; + m_xTempTruncate = uno::Reference< io::XTruncate >(); + + m_xOrigSeekable = m_xTempSeekable; + m_xTempSeekable = uno::Reference< io::XSeekable >(); + + m_xOrigInStream = m_xTempInStream; + m_xTempInStream = uno::Reference< io::XInputStream >(); + + m_xOrigOutStream = m_xTempOutStream; + m_xTempOutStream = uno::Reference< io::XOutputStream >(); + } +}; + +// ======================================================================== +// ------------------------------------------------------------------------ +OTruncatedTransactedFileStream::OTruncatedTransactedFileStream( + const ::rtl::OUString& aURL, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +: m_pStreamData( NULL ) +{ + uno::Reference< ucb::XSimpleFileAccess > xSimpleFileAccess( + xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.SimpleFileAccess" ) ) ), + uno::UNO_QUERY_THROW ); + + CommonInit_Impl( aURL, xSimpleFileAccess, xFactory, sal_False ); +} + +// ------------------------------------------------------------------------ +OTruncatedTransactedFileStream::OTruncatedTransactedFileStream( + const ::rtl::OUString& aURL, + const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +: m_pStreamData( NULL ) +{ + CommonInit_Impl( aURL, xFileAccess, xFactory, sal_False ); +} + +// ------------------------------------------------------------------------ +OTruncatedTransactedFileStream::OTruncatedTransactedFileStream( + const ::rtl::OUString& aURL, + const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess, + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + sal_Bool bDeleteIfNotCommited ) +: m_pStreamData( NULL ) +{ + CommonInit_Impl( aURL, xFileAccess, xFactory, sal_True ); + if ( m_pStreamData ) + m_pStreamData->m_bDelete = bDeleteIfNotCommited; +} + +// ------------------------------------------------------------------------ +OTruncatedTransactedFileStream::~OTruncatedTransactedFileStream() +{ + CloseAll_Impl(); +} + +// ------------------------------------------------------------------------ +void OTruncatedTransactedFileStream::CloseAll_Impl() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pStreamData ) + { + sal_Bool bDelete = m_pStreamData->m_bDelete; + ::rtl::OUString aURL = m_pStreamData->m_aURL; + uno::Reference< ucb::XSimpleFileAccess > xFileAccess = m_pStreamData->m_xFileAccess; + + delete m_pStreamData; + m_pStreamData = NULL; + + if ( bDelete && xFileAccess.is() && aURL.getLength() ) + { + // delete the file + try + { + xFileAccess->kill( aURL ); + } catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "Could not remove the file!" ); + } + } + } +} + +// ------------------------------------------------------------------------ +void OTruncatedTransactedFileStream::CommonInit_Impl( + const ::rtl::OUString& aURL, + const uno::Reference< ucb::XSimpleFileAccess >& xFileAccess, + const uno::Reference< lang::XMultiServiceFactory >& xFactory, + sal_Bool bDeleteOptionIsProvided ) +{ + sal_Bool bDelete = sal_False; + if ( !bDeleteOptionIsProvided ) + bDelete = !xFileAccess->exists( aURL ); + + uno::Reference< io::XStream > xOrigStream = xFileAccess->openFileReadWrite( aURL ); + uno::Reference< io::XTruncate > xOrigTruncate( xOrigStream, uno::UNO_QUERY_THROW ); + uno::Reference< io::XSeekable > xOrigSeekable( xOrigStream, uno::UNO_QUERY_THROW ); + uno::Reference< io::XInputStream > xOrigInStream = xOrigStream->getInputStream(); + uno::Reference< io::XOutputStream > xOrigOutStream = xOrigStream->getOutputStream(); + if ( !xOrigInStream.is() || !xOrigOutStream.is() ) + throw uno::RuntimeException(); + + // temporary stream related members + uno::Reference< io::XStream > xTempStream( xFactory->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ), + uno::UNO_QUERY_THROW ); + uno::Reference< io::XTruncate > xTempTruncate( xTempStream, uno::UNO_QUERY_THROW ); + uno::Reference< io::XSeekable > xTempSeekable( xTempStream, uno::UNO_QUERY_THROW ); + uno::Reference< io::XInputStream > xTempInStream = xTempStream->getInputStream(); + uno::Reference< io::XOutputStream > xTempOutStream = xTempStream->getOutputStream(); + if ( !xTempInStream.is() || !xTempOutStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData = new TTFileStreamData_Impl( xFileAccess, bDelete, aURL, + xOrigStream, xOrigTruncate, xOrigSeekable, xOrigInStream, xOrigOutStream, + xTempStream, xTempTruncate, xTempSeekable, xTempInStream, xTempOutStream ); +} + +// ------------------------------------------------------------------------ +void OTruncatedTransactedFileStream::Commit_Impl() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + sal_Int64 nPos = m_pStreamData->m_xTempSeekable->getPosition(); + m_pStreamData->m_xTempSeekable->seek( 0 ); + + // after the following step fails the information might be lost, throw an exception with URL of temporary file + try + { + m_pStreamData->m_xOrigTruncate->truncate(); + OStorageHelper::CopyInputToOutput( m_pStreamData->m_xTempInStream, m_pStreamData->m_xOrigOutStream ); + m_pStreamData->m_xOrigOutStream->flush(); + + // in case the stream is based on a file it will implement the following interface + // the call should be used to be sure that the contents are written to the file system + uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( m_pStreamData->m_xOrigOutStream, uno::UNO_QUERY ); + if ( asyncOutputMonitor.is() ) + asyncOutputMonitor->waitForCompletion(); + } + catch( uno::Exception& ) + { + ::rtl::OUString aTempURL; + try { + uno::Reference< beans::XPropertySet > xTempFile( m_pStreamData->m_xTempStream, uno::UNO_QUERY_THROW ); + uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); + aUrl >>= aTempURL; + xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), + uno::makeAny( sal_False ) ); + + m_pStreamData->m_xTempSeekable->seek( nPos ); + } + catch( uno::Exception& ) + { + OSL_ENSURE( sal_False, "These calls are pretty simple, they should not fail!\n" ); + } + + m_pStreamData->FreeOriginal(); + + ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( "Writing file failed!" ) ); + embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL ); + throw lang::WrappedTargetException( aErrTxt, + static_cast < OWeakObject * > ( this ), + uno::makeAny ( aException ) ); + } + + m_pStreamData->m_xOrigSeekable->seek( nPos ); + m_pStreamData->NoTransaction(); + } + else + throw io::NotConnectedException(); +} + +// ------------------------------------------------------------------------ +void OTruncatedTransactedFileStream::Revert_Impl() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + m_pStreamData->m_xTempTruncate->truncate(); + else + throw io::NotConnectedException(); +} + +// com::sun::star::io::XStream +// ------------------------------------------------------------------------ +uno::Reference< io::XInputStream > SAL_CALL OTruncatedTransactedFileStream::getInputStream( ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pStreamData ) + m_pStreamData->m_bInOpen = sal_True; + return static_cast< io::XInputStream* >( this ); +} + + +// ------------------------------------------------------------------------ +uno::Reference< io::XOutputStream > SAL_CALL OTruncatedTransactedFileStream::getOutputStream( ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pStreamData ) + m_pStreamData->m_bOutOpen = sal_True; + return static_cast< io::XOutputStream* >( this ); +} + + + +// com::sun::star::io::XInputStream +// ------------------------------------------------------------------------ +::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::readBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xTempInStream->readBytes( aData, nBytesToRead ); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xOrigInStream->readBytes( aData, nBytesToRead ); + } +} + + +// ------------------------------------------------------------------------ +::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::readSomeBytes( uno::Sequence< ::sal_Int8 >& aData, ::sal_Int32 nMaxBytesToRead ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xTempInStream->readSomeBytes( aData, nMaxBytesToRead ); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xOrigInStream->readSomeBytes( aData, nMaxBytesToRead ); + } +} + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::skipBytes( ::sal_Int32 nBytesToSkip ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempInStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xTempInStream->skipBytes( nBytesToSkip ); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigInStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xOrigInStream->skipBytes( nBytesToSkip ); + } +} + + +// ------------------------------------------------------------------------ +::sal_Int32 SAL_CALL OTruncatedTransactedFileStream::available( ) + throw (io::NotConnectedException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xTempInStream->available(); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigInStream.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xOrigInStream->available(); + } +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::closeInput() + throw (io::NotConnectedException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + m_pStreamData->m_bInOpen = sal_False; + if ( !m_pStreamData->m_bOutOpen ) + CloseAll_Impl(); +} + + + +// com::sun::star::io::XOutputStream +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::writeBytes( const uno::Sequence< ::sal_Int8 >& aData ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempOutStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xTempOutStream->writeBytes( aData ); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigOutStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xOrigOutStream->writeBytes( aData ); + } +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::flush( ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + { + OSL_ENSURE( sal_False, "flush() call on closed stream!\n" ); + return; + // in future throw exception, for now some code might call flush() on closed stream + // since file ucp implementation allows it + // throw io::NotConnectedException(); + } + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempOutStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xTempOutStream->flush(); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigOutStream.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xOrigOutStream->flush(); + } +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::closeOutput( ) + throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + m_pStreamData->m_bOutOpen = sal_False; + if ( !m_pStreamData->m_bInOpen ) + CloseAll_Impl(); +} + + + +// com::sun::star::io::XTruncate +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::truncate( ) + throw (io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempTruncate.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xTempTruncate->truncate(); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigTruncate.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xOrigTruncate->truncate(); + } +} + + + +// com::sun::star::io::XSeekable +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::seek( ::sal_Int64 location ) + throw (lang::IllegalArgumentException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempSeekable.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xTempSeekable->seek( location ); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigSeekable.is() ) + throw uno::RuntimeException(); + + m_pStreamData->m_xOrigSeekable->seek( location ); + } +} + + +// ------------------------------------------------------------------------ +::sal_Int64 SAL_CALL OTruncatedTransactedFileStream::getPosition( ) + throw (io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempSeekable.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xTempSeekable->getPosition(); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigSeekable.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xOrigSeekable->getPosition(); + } +} + + +// ------------------------------------------------------------------------ +::sal_Int64 SAL_CALL OTruncatedTransactedFileStream::getLength( ) + throw (io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + if ( m_pStreamData->m_bTransacted ) + { + // temporary stream data should be provided + if ( !m_pStreamData->m_xTempSeekable.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xTempSeekable->getLength(); + } + else + { + // the original stream data should be provided + if ( !m_pStreamData->m_xOrigSeekable.is() ) + throw uno::RuntimeException(); + + return m_pStreamData->m_xOrigSeekable->getLength(); + } +} + +// com::sun::star::beans::XPropertySetInfo +// ------------------------------------------------------------------------ +uno::Sequence< beans::Property > SAL_CALL OTruncatedTransactedFileStream::getProperties() + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< beans::Property > aProps( 1 ); + aProps[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + aProps[0].Type = getCppuType( static_cast< uno::Reference< beans::XPropertySet >* >( NULL ) ); + aProps[0].Attributes = beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::READONLY; + + return aProps; +} + + +// ------------------------------------------------------------------------ +beans::Property SAL_CALL OTruncatedTransactedFileStream::getPropertyByName( const ::rtl::OUString& aName ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + + if ( !aName.equals( aTransactionPropName ) ) + throw beans::UnknownPropertyException(); + + beans::Property aProp; + aProp.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + aProp.Type = getCppuType( static_cast< uno::Reference< beans::XPropertySet >* >( NULL ) ); + aProp.Attributes = beans::PropertyAttribute::TRANSIENT | beans::PropertyAttribute::READONLY; + + return aProp; +} + + +// ------------------------------------------------------------------------ +::sal_Bool SAL_CALL OTruncatedTransactedFileStream::hasPropertyByName( const ::rtl::OUString& Name ) + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + return ( Name.equals( aTransactionPropName ) ); +} + + + +// com::sun::star::beans::XPropertySet +// ------------------------------------------------------------------------ +uno::Reference< beans::XPropertySetInfo > SAL_CALL OTruncatedTransactedFileStream::getPropertySetInfo() + throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return static_cast< beans::XPropertySetInfo* >( this ); +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& ) + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + if ( aPropertyName.equals( aTransactionPropName ) ) + throw beans::PropertyVetoException(); + + throw beans::UnknownPropertyException(); +} + + +// ------------------------------------------------------------------------ +uno::Any SAL_CALL OTruncatedTransactedFileStream::getPropertyValue( const ::rtl::OUString& PropertyName ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pStreamData ) + throw io::NotConnectedException(); + + ::rtl::OUString aTransactionPropName( RTL_CONSTASCII_USTRINGPARAM( "TransactionSupport" ) ); + if ( PropertyName.equals( aTransactionPropName ) ) + { + uno::Reference< embed::XTransactedObject > xObj; + if ( m_pStreamData->m_bTransacted ) + xObj = static_cast< embed::XTransactedObject* >( new OTransactionHelper( this ) ); + + return uno::makeAny( xObj ); + } + + throw beans::UnknownPropertyException(); +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::addPropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + // not implemented +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::removePropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + // not implemented +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::addVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + // not implemented +} + + +// ------------------------------------------------------------------------ +void SAL_CALL OTruncatedTransactedFileStream::removeVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + // not implemented +} + + +} // namespace comphelper + diff --git a/comphelper/source/streaming/seekableinput.cxx b/comphelper/source/streaming/seekableinput.cxx new file mode 100644 index 000000000000..abaf46faf014 --- /dev/null +++ b/comphelper/source/streaming/seekableinput.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <com/sun/star/io/XOutputStream.hpp> + + +#include <comphelper/seekableinput.hxx> + +using namespace ::com::sun::star; + +namespace comphelper +{ + +const sal_Int32 nConstBufferSize = 32000; + +//--------------------------------------------------------------------------- +void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xIn, + const uno::Reference< io::XOutputStream >& xOut ) +{ + sal_Int32 nRead; + uno::Sequence< sal_Int8 > aSequence( nConstBufferSize ); + + do + { + nRead = xIn->readBytes( aSequence, nConstBufferSize ); + if ( nRead < nConstBufferSize ) + { + uno::Sequence< sal_Int8 > aTempBuf( aSequence.getConstArray(), nRead ); + xOut->writeBytes( aTempBuf ); + } + else + xOut->writeBytes( aSequence ); + } + while ( nRead == nConstBufferSize ); +} + +//--------------------------------------------------------------------------- +OSeekableInputWrapper::OSeekableInputWrapper( + const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +: m_xFactory( xFactory ) +, m_xOriginalStream( xInStream ) +{ + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); +} + +//--------------------------------------------------------------------------- +OSeekableInputWrapper::~OSeekableInputWrapper() +{ +} + +//--------------------------------------------------------------------------- +uno::Reference< io::XInputStream > OSeekableInputWrapper::CheckSeekableCanWrap( + const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< lang::XMultiServiceFactory >& xFactory ) +{ + // check that the stream is seekable and just wrap it if it is not + uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY ); + if ( xSeek.is() ) + return xInStream; + + uno::Reference< io::XInputStream > xNewStream( + static_cast< io::XInputStream* >( + new OSeekableInputWrapper( xInStream, xFactory ) ) ); + return xNewStream; +} + +//--------------------------------------------------------------------------- +void OSeekableInputWrapper::PrepareCopy_Impl() +{ + if ( !m_xCopyInput.is() ) + { + if ( !m_xFactory.is() ) + throw uno::RuntimeException(); + + uno::Reference< io::XOutputStream > xTempOut( + m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), + uno::UNO_QUERY ); + + if ( xTempOut.is() ) + { + copyInputToOutput_Impl( m_xOriginalStream, xTempOut ); + xTempOut->closeOutput(); + + uno::Reference< io::XSeekable > xTempSeek( xTempOut, uno::UNO_QUERY ); + if ( xTempSeek.is() ) + { + xTempSeek->seek( 0 ); + m_xCopyInput = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY ); + if ( m_xCopyInput.is() ) + m_xCopySeek = xTempSeek; + } + } + } + + if ( !m_xCopyInput.is() ) + throw io::IOException(); +} + +// XInputStream +//--------------------------------------------------------------------------- +sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->readBytes( aData, nBytesToRead ); +} + +//--------------------------------------------------------------------------- +sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); +} + +//--------------------------------------------------------------------------- +void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) + throw ( io::NotConnectedException, + io::BufferSizeExceededException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + m_xCopyInput->skipBytes( nBytesToSkip ); +} + +//--------------------------------------------------------------------------- +sal_Int32 SAL_CALL OSeekableInputWrapper::available() + throw ( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopyInput->available(); +} + +//--------------------------------------------------------------------------- +void SAL_CALL OSeekableInputWrapper::closeInput() + throw ( io::NotConnectedException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + m_xOriginalStream->closeInput(); + m_xOriginalStream = uno::Reference< io::XInputStream >(); + + if ( m_xCopyInput.is() ) + { + m_xCopyInput->closeInput(); + m_xCopyInput = uno::Reference< io::XInputStream >(); + } + + m_xCopySeek = uno::Reference< io::XSeekable >(); +} + + +// XSeekable +//--------------------------------------------------------------------------- +void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) + throw ( lang::IllegalArgumentException, + io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + m_xCopySeek->seek( location ); +} + +//--------------------------------------------------------------------------- +sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() + throw ( io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopySeek->getPosition(); +} + +//--------------------------------------------------------------------------- +sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() + throw ( io::IOException, + uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_xOriginalStream.is() ) + throw io::NotConnectedException(); + + PrepareCopy_Impl(); + + return m_xCopySeek->getLength(); +} + +} // namespace comphelper + diff --git a/comphelper/source/streaming/seqinputstreamserv.cxx b/comphelper/source/streaming/seqinputstreamserv.cxx new file mode 100644 index 000000000000..015387b9894d --- /dev/null +++ b/comphelper/source/streaming/seqinputstreamserv.cxx @@ -0,0 +1,251 @@ +/************************************************************************* + * + * 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_comphelper.hxx" + +#include "comphelper_module.hxx" + +#include <sal/config.h> +#include <osl/mutex.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include <cppuhelper/implbase3.hxx> +#include <comphelper/seqstream.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/io/XSeekableInputStream.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/DoubleInitializationException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + + +using namespace ::com::sun::star; + +namespace { + +class SequenceInputStreamService: + public ::cppu::WeakImplHelper3< + lang::XServiceInfo, + io::XSeekableInputStream, + lang::XInitialization> +{ +public: + explicit SequenceInputStreamService(); + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw ( uno::RuntimeException ); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString & ServiceName ) throw ( uno::RuntimeException ); + virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( uno::RuntimeException ); + + // XServiceInfo - static versions (used for component registration) + static ::rtl::OUString SAL_CALL getImplementationName_static(); + static uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(); + static uno::Reference< uno::XInterface > SAL_CALL Create( const uno::Reference< uno::XComponentContext >& ); + + // ::com::sun::star::io::XInputStream: + virtual ::sal_Int32 SAL_CALL readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ); + virtual ::sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ); + virtual void SAL_CALL skipBytes( ::sal_Int32 nBytesToSkip ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ); + virtual ::sal_Int32 SAL_CALL available() throw ( uno::RuntimeException, io::NotConnectedException, io::IOException ); + virtual void SAL_CALL closeInput() throw ( uno::RuntimeException, io::NotConnectedException, io::IOException ); + + // ::com::sun::star::io::XSeekable: + virtual void SAL_CALL seek( ::sal_Int64 location ) throw ( uno::RuntimeException, lang::IllegalArgumentException, io::IOException ); + virtual ::sal_Int64 SAL_CALL getPosition() throw ( uno::RuntimeException, io::IOException ); + virtual ::sal_Int64 SAL_CALL getLength() throw ( uno::RuntimeException, io::IOException ); + + // ::com::sun::star::lang::XInitialization: + virtual void SAL_CALL initialize( const uno::Sequence< ::com::sun::star::uno::Any > & aArguments ) throw ( uno::RuntimeException, uno::Exception ); + +private: + SequenceInputStreamService( SequenceInputStreamService & ); // not defined + void operator =( SequenceInputStreamService & ); // not defined + + virtual ~SequenceInputStreamService() {} + + + ::osl::Mutex m_aMutex; + sal_Bool m_bInitialized; + uno::Reference< io::XInputStream > m_xInputStream; + uno::Reference< io::XSeekable > m_xSeekable; +}; + +SequenceInputStreamService::SequenceInputStreamService() +: m_bInitialized( sal_False ) +{} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL SequenceInputStreamService::getImplementationName() throw ( uno::RuntimeException ) +{ + return getImplementationName_static(); +} + +::rtl::OUString SAL_CALL SequenceInputStreamService::getImplementationName_static() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.SequenceInputStreamService" ) ); +} + +::sal_Bool SAL_CALL SequenceInputStreamService::supportsService( ::rtl::OUString const & serviceName ) throw ( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > serviceNames = getSupportedServiceNames(); + for ( ::sal_Int32 i = 0; i < serviceNames.getLength(); ++i ) { + if ( serviceNames[i] == serviceName ) + return sal_True; + } + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL SequenceInputStreamService::getSupportedServiceNames() throw ( uno::RuntimeException ) +{ + return getSupportedServiceNames_static(); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL SequenceInputStreamService::getSupportedServiceNames_static() +{ + uno::Sequence< ::rtl::OUString > s( 1 ); + s[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.io.SequenceInputStream" ) ); + return s; +} + +uno::Reference< uno::XInterface > SAL_CALL SequenceInputStreamService::Create( + const uno::Reference< uno::XComponentContext >& ) +{ + return static_cast< ::cppu::OWeakObject * >( new SequenceInputStreamService() ); +} + +// ::com::sun::star::io::XInputStream: +::sal_Int32 SAL_CALL SequenceInputStreamService::readBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nBytesToRead ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->readBytes( aData, nBytesToRead ); +} + +::sal_Int32 SAL_CALL SequenceInputStreamService::readSomeBytes( uno::Sequence< ::sal_Int8 > & aData, ::sal_Int32 nMaxBytesToRead ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->readSomeBytes( aData, nMaxBytesToRead ); +} + +void SAL_CALL SequenceInputStreamService::skipBytes( ::sal_Int32 nBytesToSkip ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->skipBytes( nBytesToSkip ); +} + +::sal_Int32 SAL_CALL SequenceInputStreamService::available() throw ( uno::RuntimeException, io::NotConnectedException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + return m_xInputStream->available(); +} + +void SAL_CALL SequenceInputStreamService::closeInput() throw ( uno::RuntimeException, io::NotConnectedException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xInputStream.is() ) + throw io::NotConnectedException(); + + m_xInputStream->closeInput(); + m_xInputStream = uno::Reference< io::XInputStream >(); + m_xSeekable = uno::Reference< io::XSeekable >(); +} + +// ::com::sun::star::io::XSeekable: +void SAL_CALL SequenceInputStreamService::seek( ::sal_Int64 location ) throw ( uno::RuntimeException, lang::IllegalArgumentException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + m_xSeekable->seek( location ); +} + +::sal_Int64 SAL_CALL SequenceInputStreamService::getPosition() throw ( uno::RuntimeException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + return m_xSeekable->getPosition(); +} + +::sal_Int64 SAL_CALL SequenceInputStreamService::getLength() throw ( uno::RuntimeException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xSeekable.is() ) + throw io::NotConnectedException(); + + return m_xSeekable->getLength(); +} + +// ::com::sun::star::lang::XInitialization: +void SAL_CALL SequenceInputStreamService::initialize( const uno::Sequence< ::com::sun::star::uno::Any > & aArguments ) throw ( uno::RuntimeException, uno::Exception ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bInitialized ) + throw frame::DoubleInitializationException(); + + if ( aArguments.getLength() != 1 ) + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Wrong number of arguments!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); + + uno::Sequence< sal_Int8 > aSeq; + if ( aArguments[0] >>= aSeq ) + { + uno::Reference< io::XInputStream > xInputStream( + static_cast< ::cppu::OWeakObject* >( new ::comphelper::SequenceInputStream( aSeq ) ), + uno::UNO_QUERY_THROW ); + uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY_THROW ); + m_xInputStream = xInputStream; + m_xSeekable = xSeekable; + m_bInitialized = sal_True; + } + else + throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Unexpected type of argument!\n" ), + uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ), + 1 ); +} + +} // anonymous namespace + +void createRegistryInfo_SequenceInputStream() +{ + static ::comphelper::module::OAutoRegistration< SequenceInputStreamService > aAutoRegistration; +} diff --git a/comphelper/source/streaming/seqoutputstreamserv.cxx b/comphelper/source/streaming/seqoutputstreamserv.cxx new file mode 100644 index 000000000000..a51653e6e419 --- /dev/null +++ b/comphelper/source/streaming/seqoutputstreamserv.cxx @@ -0,0 +1,172 @@ +/************************************************************************* +* + * 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. + * +************************************************************************/ + +#include "precompiled_comphelper.hxx" + +#include "comphelper_module.hxx" + +#include <sal/config.h> +#include <osl/mutex.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include <cppuhelper/implbase2.hxx> +#include <comphelper/seqstream.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/io/XSequenceOutputStream.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +using namespace ::com::sun::star; + + +namespace { + +class SequenceOutputStreamService: +public ::cppu::WeakImplHelper2 < lang::XServiceInfo, io::XSequenceOutputStream > +{ +public: + explicit SequenceOutputStreamService(); + + // ::com::sun::star::lang::XServiceInfo: + virtual ::rtl::OUString SAL_CALL getImplementationName() throw ( uno::RuntimeException ); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString & ServiceName ) throw ( uno::RuntimeException ); + virtual uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( uno::RuntimeException ); + + // XServiceInfo - static versions (used for component registration) + static ::rtl::OUString SAL_CALL getImplementationName_static(); + static uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(); + static uno::Reference< uno::XInterface > SAL_CALL Create( const uno::Reference< uno::XComponentContext >& ); + + // ::com::sun::star::io::XOutputStream: + virtual void SAL_CALL writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) throw ( io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException ); + virtual void SAL_CALL flush() throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ); + virtual void SAL_CALL closeOutput() throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ); + + // ::com::sun::star::io::XSequenceOutputStream: + virtual uno::Sequence< ::sal_Int8 > SAL_CALL getWrittenBytes( ) throw ( io::NotConnectedException, io::IOException, uno::RuntimeException); + +private: + SequenceOutputStreamService( SequenceOutputStreamService & ); //not defined + void operator =( SequenceOutputStreamService & ); //not defined + + virtual ~SequenceOutputStreamService() {}; + + + ::osl::Mutex m_aMutex; + uno::Reference< io::XOutputStream > m_xOutputStream; + uno::Sequence< ::sal_Int8 > m_aSequence; +}; +SequenceOutputStreamService::SequenceOutputStreamService() +{ + m_xOutputStream.set( static_cast < ::cppu::OWeakObject* >( new ::comphelper::OSequenceOutputStream( m_aSequence ) ), uno::UNO_QUERY_THROW ); +} + +// com.sun.star.uno.XServiceInfo: +::rtl::OUString SAL_CALL SequenceOutputStreamService::getImplementationName() throw ( uno::RuntimeException ) +{ + return getImplementationName_static(); +} + +::rtl::OUString SAL_CALL SequenceOutputStreamService::getImplementationName_static() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.SequenceOutputStreamService" ) ); +} + +::sal_Bool SAL_CALL SequenceOutputStreamService::supportsService( ::rtl::OUString const & serviceName ) throw ( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > serviceNames = getSupportedServiceNames(); + for ( ::sal_Int32 i = 0; i < serviceNames.getLength(); ++i ) { + if ( serviceNames[i] == serviceName ) + return sal_True; + } + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL SequenceOutputStreamService::getSupportedServiceNames() throw ( uno::RuntimeException ) +{ + return getSupportedServiceNames_static(); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL SequenceOutputStreamService::getSupportedServiceNames_static() +{ + uno::Sequence< ::rtl::OUString > s( 1 ); + s[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.SequenceOutputStream" ) ); + return s; +} + +uno::Reference< uno::XInterface > SAL_CALL SequenceOutputStreamService::Create( + const uno::Reference< uno::XComponentContext >& ) +{ + return static_cast< ::cppu::OWeakObject * >( new SequenceOutputStreamService()); +} + +// ::com::sun::star::io::XOutputStream: +void SAL_CALL SequenceOutputStreamService::writeBytes( const uno::Sequence< ::sal_Int8 > & aData ) throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->writeBytes( aData ); + m_aSequence = aData; +} + +void SAL_CALL SequenceOutputStreamService::flush() throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->flush(); +}; + +void SAL_CALL SequenceOutputStreamService::closeOutput() throw ( uno::RuntimeException, io::NotConnectedException, io::BufferSizeExceededException, io::IOException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->closeOutput(); + m_xOutputStream = uno::Reference< io::XOutputStream >(); +} + +// ::com::sun::star::io::XSequenceOutputStream: +uno::Sequence< ::sal_Int8 > SAL_CALL SequenceOutputStreamService::getWrittenBytes() throw ( io::NotConnectedException, io::IOException, uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !m_xOutputStream.is() ) + throw io::NotConnectedException(); + + m_xOutputStream->flush(); + return m_aSequence; +} + +} // anonymous namespace + +void createRegistryInfo_SequenceOutputStream() +{ + static ::comphelper::module::OAutoRegistration< SequenceOutputStreamService > aAutoRegistration; +} diff --git a/comphelper/source/streaming/seqstream.cxx b/comphelper/source/streaming/seqstream.cxx new file mode 100644 index 000000000000..5c8a32b1f6e5 --- /dev/null +++ b/comphelper/source/streaming/seqstream.cxx @@ -0,0 +1,243 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <comphelper/seqstream.hxx> + +#include <memory.h> // for memcpy + +namespace comphelper +{ +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::osl; + +//--------------------------------------------------------------------------------------------- +// class SequenceInputStream +//--------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------ +SequenceInputStream::SequenceInputStream(const ByteSequence& rData) +: m_aData(rData) +, m_nPos(0) +{ +} + +// checks if closed, returns available size, not mutex-protected +//------------------------------------------------------------------ +inline sal_Int32 SequenceInputStream::avail() +{ + if (m_nPos == -1) + throw NotConnectedException(::rtl::OUString(), *this); + + return m_aData.getLength() - m_nPos; +} + +// com::sun::star::io::XInputStream +//------------------------------------------------------------------ +sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead ) + throw(NotConnectedException, BufferSizeExceededException, + IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nBytesToRead < 0) + throw BufferSizeExceededException(::rtl::OUString(),*this); + + if (nAvail < nBytesToRead) + nBytesToRead = nAvail; + + aData.realloc(nBytesToRead); + memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead); + m_nPos += nBytesToRead; + + return nBytesToRead; +} + +//------------------------------------------------------------------ +sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead ) + throw(NotConnectedException, BufferSizeExceededException, + IOException, RuntimeException) +{ + // all data is available at once + return readBytes(aData, nMaxBytesToRead); +} + +//------------------------------------------------------------------ +void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw(NotConnectedException, BufferSizeExceededException, + IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 nAvail = avail(); + + if (nBytesToSkip < 0) + throw BufferSizeExceededException(::rtl::OUString(),*this); + + if (nAvail < nBytesToSkip) + nBytesToSkip = nAvail; + + m_nPos += nBytesToSkip; +} + +//------------------------------------------------------------------ +sal_Int32 SAL_CALL SequenceInputStream::available( ) + throw(NotConnectedException, IOException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return avail(); +} + +//------------------------------------------------------------------ +void SAL_CALL SequenceInputStream::closeInput( ) + throw(NotConnectedException, IOException, RuntimeException) +{ + if (m_nPos == -1) + throw NotConnectedException(::rtl::OUString(), *this); + + m_nPos = -1; +} + +void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException) +{ + if ( location > m_aData.getLength() || location < 0 || location > SAL_MAX_INT32 ) + throw IllegalArgumentException(); + m_nPos = (sal_Int32) location; +} + +sal_Int64 SAL_CALL SequenceInputStream::getPosition() throw (IOException, RuntimeException) +{ + return m_nPos; +} + +sal_Int64 SAL_CALL SequenceInputStream::getLength( ) throw (IOException, RuntimeException) +{ + return m_aData.getLength(); +} + +//-------------------------------------------------------------------------- +OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize, sal_Int32 _nMaximumResize) + :m_rSequence(_rSeq) + ,m_nResizeFactor(_nResizeFactor) + ,m_nMinimumResize(_nMinimumResize) + ,m_nMaximumResize(_nMaximumResize) + ,m_nSize(0) // starting at position 0 + ,m_bConnected(sal_True) +{ + OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !"); + OSL_ENSURE((m_nMaximumResize < 0) || (m_nMaximumResize > m_nMinimumResize), + "OSequenceOutputStream::OSequenceOutputStream : these limits don't make any sense !"); + + if (m_nResizeFactor <= 1) + m_nResizeFactor = 1.3; + if ((m_nMaximumResize >= 0) && (m_nMaximumResize <= m_nMinimumResize)) + m_nMaximumResize = m_nMinimumResize * 2; + // this heuristic is as good as any other ... supply better parameters if you don't like it :) +} + +//-------------------------------------------------------------------------- +void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + // ensure the sequence has enoungh space left + if (m_nSize + _rData.getLength() > m_rSequence.getLength()) + { + sal_Int32 nCurrentLength = m_rSequence.getLength(); + sal_Int32 nNewLength = static_cast< sal_Int32 >( + nCurrentLength * m_nResizeFactor); + + if (m_nMinimumResize > nNewLength - nCurrentLength) + // we have a minimum so it's not too inefficient for small sequences and small write requests + nNewLength = nCurrentLength + m_nMinimumResize; + + if ((m_nMaximumResize > 0) && (nNewLength - nCurrentLength > m_nMaximumResize)) + // such a large step is not allowed + nNewLength = nCurrentLength + m_nMaximumResize; + + if (nNewLength < m_nSize + _rData.getLength()) + { // it's not enough .... the data would not fit + + // let's take the double amount of the length of the data to be written, as the next write + // request could be as large as this one + sal_Int32 nNewGrowth = _rData.getLength() * 2; + if ((m_nMaximumResize > 0) && (nNewGrowth > m_nMaximumResize)) + { // we came to the limit, again ... + nNewGrowth = m_nMaximumResize; + if (nNewGrowth + nCurrentLength < m_nSize + _rData.getLength()) + // but it would not fit if we respect the limit + nNewGrowth = m_nSize + _rData.getLength() - nCurrentLength; + } + nNewLength = nCurrentLength + nNewGrowth; + } + + // round it off to the next multiple of 4 ... + nNewLength = (nNewLength + 3) / 4 * 4; + + m_rSequence.realloc(nNewLength); + } + + OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(), + "ooops ... the realloc algorithm seems to be wrong :( !"); + + memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength()); + m_nSize += _rData.getLength(); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OSequenceOutputStream::flush( ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + // cut the sequence to the real size + m_rSequence.realloc(m_nSize); +} + +//-------------------------------------------------------------------------- +void SAL_CALL OSequenceOutputStream::closeOutput( ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + if (!m_bConnected) + throw NotConnectedException(); + + // cut the sequence to the real size + m_rSequence.realloc(m_nSize); + // and don't allow any further accesses + m_bConnected = sal_False; +} + +} // namespace comphelper diff --git a/comphelper/source/streaming/streamsection.cxx b/comphelper/source/streaming/streamsection.cxx new file mode 100644 index 000000000000..324299813986 --- /dev/null +++ b/comphelper/source/streaming/streamsection.cxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * 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_comphelper.hxx" +#include <comphelper/streamsection.hxx> +#include <osl/diagnose.h> + +namespace comphelper +{ + +//------------------------------------------------------------------------- +OStreamSection::OStreamSection(const staruno::Reference< stario::XDataInputStream >& _rxInput) + :m_xMarkStream(_rxInput, ::com::sun::star::uno::UNO_QUERY) + ,m_xInStream(_rxInput) + ,m_nBlockStart(-1) + ,m_nBlockLen(-1) +{ + OSL_ENSURE(m_xInStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !"); + if (m_xInStream.is() && m_xMarkStream.is()) + { + m_nBlockLen = _rxInput->readLong(); + m_nBlockStart = m_xMarkStream->createMark(); + } +} + +//------------------------------------------------------------------------- +OStreamSection::OStreamSection(const staruno::Reference< stario::XDataOutputStream >& _rxOutput, sal_Int32 _nPresumedLength) + :m_xMarkStream(_rxOutput, ::com::sun::star::uno::UNO_QUERY) + ,m_xOutStream(_rxOutput) + ,m_nBlockStart(-1) + ,m_nBlockLen(-1) +{ + OSL_ENSURE(m_xOutStream.is() && m_xMarkStream.is(), "OStreamSection::OStreamSection : invalid argument !"); + if (m_xOutStream.is() && m_xMarkStream.is()) + { + m_nBlockStart = m_xMarkStream->createMark(); + // a placeholder where we will write the overall length (within the destructor) + if (_nPresumedLength > 0) + m_nBlockLen = _nPresumedLength + sizeof(m_nBlockLen); + // as the caller did not consider - of course - the placeholder we are going to write + else + m_nBlockLen = 0; + m_xOutStream->writeLong(m_nBlockLen); + } +} + +//------------------------------------------------------------------------- +OStreamSection::~OStreamSection() +{ + try + { // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception + // handling routing + if (m_xInStream.is() && m_xMarkStream.is()) + { // we're working on an input stream + m_xMarkStream->jumpToMark(m_nBlockStart); + m_xInStream->skipBytes(m_nBlockLen); + m_xMarkStream->deleteMark(m_nBlockStart); + } + else if (m_xOutStream.is() && m_xMarkStream.is()) + { + sal_Int32 nRealBlockLength = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen); + if (m_nBlockLen && (m_nBlockLen == nRealBlockLength)) + // nothing to do : the estimation the caller gave us (in the ctor) was correct + m_xMarkStream->deleteMark(m_nBlockStart); + else + { // the estimation was wrong (or we didn't get one) + m_nBlockLen = nRealBlockLength; + m_xMarkStream->jumpToMark(m_nBlockStart); + m_xOutStream->writeLong(m_nBlockLen); + m_xMarkStream->jumpToFurthest(); + m_xMarkStream->deleteMark(m_nBlockStart); + } + } + } + catch(const staruno::Exception&) + { + } +} +// ----------------------------------------------------------------------------- +sal_Int32 OStreamSection::available() +{ + sal_Int32 nBytes = 0; + try + { // don't allow any exceptions to leave this block, this may be called during the stack unwinding of an exception + if (m_xInStream.is() && m_xMarkStream.is()) + nBytes = m_xMarkStream->offsetToMark(m_nBlockStart) - sizeof(m_nBlockLen); + } + catch(const staruno::Exception&) + { + } + return nBytes; +} +// ----------------------------------------------------------------------------- + +} // namespace comphelper + + |