1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 #include <com/sun/star/io/XOutputStream.hpp> 31 32 33 #include <comphelper/seekableinput.hxx> 34 35 using namespace ::com::sun::star; 36 37 namespace comphelper 38 { 39 40 const sal_Int32 nConstBufferSize = 32000; 41 42 //--------------------------------------------------------------------------- 43 void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xIn, 44 const uno::Reference< io::XOutputStream >& xOut ) 45 { 46 sal_Int32 nRead; 47 uno::Sequence< sal_Int8 > aSequence( nConstBufferSize ); 48 49 do 50 { 51 nRead = xIn->readBytes( aSequence, nConstBufferSize ); 52 if ( nRead < nConstBufferSize ) 53 { 54 uno::Sequence< sal_Int8 > aTempBuf( aSequence.getConstArray(), nRead ); 55 xOut->writeBytes( aTempBuf ); 56 } 57 else 58 xOut->writeBytes( aSequence ); 59 } 60 while ( nRead == nConstBufferSize ); 61 } 62 63 //--------------------------------------------------------------------------- 64 OSeekableInputWrapper::OSeekableInputWrapper( 65 const uno::Reference< io::XInputStream >& xInStream, 66 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 67 : m_xFactory( xFactory ) 68 , m_xOriginalStream( xInStream ) 69 { 70 if ( !m_xFactory.is() ) 71 throw uno::RuntimeException(); 72 } 73 74 //--------------------------------------------------------------------------- 75 OSeekableInputWrapper::~OSeekableInputWrapper() 76 { 77 } 78 79 //--------------------------------------------------------------------------- 80 uno::Reference< io::XInputStream > OSeekableInputWrapper::CheckSeekableCanWrap( 81 const uno::Reference< io::XInputStream >& xInStream, 82 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 83 { 84 // check that the stream is seekable and just wrap it if it is not 85 uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY ); 86 if ( xSeek.is() ) 87 return xInStream; 88 89 uno::Reference< io::XInputStream > xNewStream( 90 static_cast< io::XInputStream* >( 91 new OSeekableInputWrapper( xInStream, xFactory ) ) ); 92 return xNewStream; 93 } 94 95 //--------------------------------------------------------------------------- 96 void OSeekableInputWrapper::PrepareCopy_Impl() 97 { 98 if ( !m_xCopyInput.is() ) 99 { 100 if ( !m_xFactory.is() ) 101 throw uno::RuntimeException(); 102 103 uno::Reference< io::XOutputStream > xTempOut( 104 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 105 uno::UNO_QUERY ); 106 107 if ( xTempOut.is() ) 108 { 109 copyInputToOutput_Impl( m_xOriginalStream, xTempOut ); 110 xTempOut->closeOutput(); 111 112 uno::Reference< io::XSeekable > xTempSeek( xTempOut, uno::UNO_QUERY ); 113 if ( xTempSeek.is() ) 114 { 115 xTempSeek->seek( 0 ); 116 m_xCopyInput = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY ); 117 if ( m_xCopyInput.is() ) 118 m_xCopySeek = xTempSeek; 119 } 120 } 121 } 122 123 if ( !m_xCopyInput.is() ) 124 throw io::IOException(); 125 } 126 127 // XInputStream 128 //--------------------------------------------------------------------------- 129 sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 130 throw ( io::NotConnectedException, 131 io::BufferSizeExceededException, 132 io::IOException, 133 uno::RuntimeException ) 134 { 135 ::osl::MutexGuard aGuard( m_aMutex ); 136 137 if ( !m_xOriginalStream.is() ) 138 throw io::NotConnectedException(); 139 140 PrepareCopy_Impl(); 141 142 return m_xCopyInput->readBytes( aData, nBytesToRead ); 143 } 144 145 //--------------------------------------------------------------------------- 146 sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 147 throw ( io::NotConnectedException, 148 io::BufferSizeExceededException, 149 io::IOException, 150 uno::RuntimeException ) 151 { 152 ::osl::MutexGuard aGuard( m_aMutex ); 153 154 if ( !m_xOriginalStream.is() ) 155 throw io::NotConnectedException(); 156 157 PrepareCopy_Impl(); 158 159 return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); 160 } 161 162 //--------------------------------------------------------------------------- 163 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) 164 throw ( io::NotConnectedException, 165 io::BufferSizeExceededException, 166 io::IOException, 167 uno::RuntimeException ) 168 { 169 ::osl::MutexGuard aGuard( m_aMutex ); 170 171 if ( !m_xOriginalStream.is() ) 172 throw io::NotConnectedException(); 173 174 PrepareCopy_Impl(); 175 176 m_xCopyInput->skipBytes( nBytesToSkip ); 177 } 178 179 //--------------------------------------------------------------------------- 180 sal_Int32 SAL_CALL OSeekableInputWrapper::available() 181 throw ( io::NotConnectedException, 182 io::IOException, 183 uno::RuntimeException ) 184 { 185 ::osl::MutexGuard aGuard( m_aMutex ); 186 187 if ( !m_xOriginalStream.is() ) 188 throw io::NotConnectedException(); 189 190 PrepareCopy_Impl(); 191 192 return m_xCopyInput->available(); 193 } 194 195 //--------------------------------------------------------------------------- 196 void SAL_CALL OSeekableInputWrapper::closeInput() 197 throw ( io::NotConnectedException, 198 io::IOException, 199 uno::RuntimeException ) 200 { 201 ::osl::MutexGuard aGuard( m_aMutex ); 202 203 if ( !m_xOriginalStream.is() ) 204 throw io::NotConnectedException(); 205 206 m_xOriginalStream->closeInput(); 207 m_xOriginalStream = uno::Reference< io::XInputStream >(); 208 209 if ( m_xCopyInput.is() ) 210 { 211 m_xCopyInput->closeInput(); 212 m_xCopyInput = uno::Reference< io::XInputStream >(); 213 } 214 215 m_xCopySeek = uno::Reference< io::XSeekable >(); 216 } 217 218 219 // XSeekable 220 //--------------------------------------------------------------------------- 221 void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) 222 throw ( lang::IllegalArgumentException, 223 io::IOException, 224 uno::RuntimeException ) 225 { 226 ::osl::MutexGuard aGuard( m_aMutex ); 227 228 if ( !m_xOriginalStream.is() ) 229 throw io::NotConnectedException(); 230 231 PrepareCopy_Impl(); 232 233 m_xCopySeek->seek( location ); 234 } 235 236 //--------------------------------------------------------------------------- 237 sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() 238 throw ( io::IOException, 239 uno::RuntimeException ) 240 { 241 ::osl::MutexGuard aGuard( m_aMutex ); 242 243 if ( !m_xOriginalStream.is() ) 244 throw io::NotConnectedException(); 245 246 PrepareCopy_Impl(); 247 248 return m_xCopySeek->getPosition(); 249 } 250 251 //--------------------------------------------------------------------------- 252 sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() 253 throw ( io::IOException, 254 uno::RuntimeException ) 255 { 256 ::osl::MutexGuard aGuard( m_aMutex ); 257 258 if ( !m_xOriginalStream.is() ) 259 throw io::NotConnectedException(); 260 261 PrepareCopy_Impl(); 262 263 return m_xCopySeek->getLength(); 264 } 265 266 } // namespace comphelper 267 268