1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_comphelper.hxx" 26 #include <com/sun/star/io/XOutputStream.hpp> 27 28 29 #include <comphelper/seekableinput.hxx> 30 31 using namespace ::com::sun::star; 32 33 namespace comphelper 34 { 35 36 const sal_Int32 nConstBufferSize = 32000; 37 38 //--------------------------------------------------------------------------- 39 void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xIn, 40 const uno::Reference< io::XOutputStream >& xOut ) 41 { 42 sal_Int32 nRead; 43 uno::Sequence< sal_Int8 > aSequence( nConstBufferSize ); 44 45 do 46 { 47 nRead = xIn->readBytes( aSequence, nConstBufferSize ); 48 if ( nRead < nConstBufferSize ) 49 { 50 uno::Sequence< sal_Int8 > aTempBuf( aSequence.getConstArray(), nRead ); 51 xOut->writeBytes( aTempBuf ); 52 } 53 else 54 xOut->writeBytes( aSequence ); 55 } 56 while ( nRead == nConstBufferSize ); 57 } 58 59 //--------------------------------------------------------------------------- 60 OSeekableInputWrapper::OSeekableInputWrapper( 61 const uno::Reference< io::XInputStream >& xInStream, 62 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 63 : m_xFactory( xFactory ) 64 , m_xOriginalStream( xInStream ) 65 { 66 if ( !m_xFactory.is() ) 67 throw uno::RuntimeException(); 68 } 69 70 //--------------------------------------------------------------------------- 71 OSeekableInputWrapper::~OSeekableInputWrapper() 72 { 73 } 74 75 //--------------------------------------------------------------------------- 76 uno::Reference< io::XInputStream > OSeekableInputWrapper::CheckSeekableCanWrap( 77 const uno::Reference< io::XInputStream >& xInStream, 78 const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 79 { 80 // check that the stream is seekable and just wrap it if it is not 81 uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY ); 82 if ( xSeek.is() ) 83 return xInStream; 84 85 uno::Reference< io::XInputStream > xNewStream( 86 static_cast< io::XInputStream* >( 87 new OSeekableInputWrapper( xInStream, xFactory ) ) ); 88 return xNewStream; 89 } 90 91 //--------------------------------------------------------------------------- 92 void OSeekableInputWrapper::PrepareCopy_Impl() 93 { 94 if ( !m_xCopyInput.is() ) 95 { 96 if ( !m_xFactory.is() ) 97 throw uno::RuntimeException(); 98 99 uno::Reference< io::XOutputStream > xTempOut( 100 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 101 uno::UNO_QUERY ); 102 103 if ( xTempOut.is() ) 104 { 105 copyInputToOutput_Impl( m_xOriginalStream, xTempOut ); 106 xTempOut->closeOutput(); 107 108 uno::Reference< io::XSeekable > xTempSeek( xTempOut, uno::UNO_QUERY ); 109 if ( xTempSeek.is() ) 110 { 111 xTempSeek->seek( 0 ); 112 m_xCopyInput = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY ); 113 if ( m_xCopyInput.is() ) 114 m_xCopySeek = xTempSeek; 115 } 116 } 117 } 118 119 if ( !m_xCopyInput.is() ) 120 throw io::IOException(); 121 } 122 123 // XInputStream 124 //--------------------------------------------------------------------------- 125 sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 126 throw ( io::NotConnectedException, 127 io::BufferSizeExceededException, 128 io::IOException, 129 uno::RuntimeException ) 130 { 131 ::osl::MutexGuard aGuard( m_aMutex ); 132 133 if ( !m_xOriginalStream.is() ) 134 throw io::NotConnectedException(); 135 136 PrepareCopy_Impl(); 137 138 return m_xCopyInput->readBytes( aData, nBytesToRead ); 139 } 140 141 //--------------------------------------------------------------------------- 142 sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 143 throw ( io::NotConnectedException, 144 io::BufferSizeExceededException, 145 io::IOException, 146 uno::RuntimeException ) 147 { 148 ::osl::MutexGuard aGuard( m_aMutex ); 149 150 if ( !m_xOriginalStream.is() ) 151 throw io::NotConnectedException(); 152 153 PrepareCopy_Impl(); 154 155 return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); 156 } 157 158 //--------------------------------------------------------------------------- 159 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) 160 throw ( io::NotConnectedException, 161 io::BufferSizeExceededException, 162 io::IOException, 163 uno::RuntimeException ) 164 { 165 ::osl::MutexGuard aGuard( m_aMutex ); 166 167 if ( !m_xOriginalStream.is() ) 168 throw io::NotConnectedException(); 169 170 PrepareCopy_Impl(); 171 172 m_xCopyInput->skipBytes( nBytesToSkip ); 173 } 174 175 //--------------------------------------------------------------------------- 176 sal_Int32 SAL_CALL OSeekableInputWrapper::available() 177 throw ( io::NotConnectedException, 178 io::IOException, 179 uno::RuntimeException ) 180 { 181 ::osl::MutexGuard aGuard( m_aMutex ); 182 183 if ( !m_xOriginalStream.is() ) 184 throw io::NotConnectedException(); 185 186 PrepareCopy_Impl(); 187 188 return m_xCopyInput->available(); 189 } 190 191 //--------------------------------------------------------------------------- 192 void SAL_CALL OSeekableInputWrapper::closeInput() 193 throw ( io::NotConnectedException, 194 io::IOException, 195 uno::RuntimeException ) 196 { 197 ::osl::MutexGuard aGuard( m_aMutex ); 198 199 if ( !m_xOriginalStream.is() ) 200 throw io::NotConnectedException(); 201 202 m_xOriginalStream->closeInput(); 203 m_xOriginalStream = uno::Reference< io::XInputStream >(); 204 205 if ( m_xCopyInput.is() ) 206 { 207 m_xCopyInput->closeInput(); 208 m_xCopyInput = uno::Reference< io::XInputStream >(); 209 } 210 211 m_xCopySeek = uno::Reference< io::XSeekable >(); 212 } 213 214 215 // XSeekable 216 //--------------------------------------------------------------------------- 217 void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) 218 throw ( lang::IllegalArgumentException, 219 io::IOException, 220 uno::RuntimeException ) 221 { 222 ::osl::MutexGuard aGuard( m_aMutex ); 223 224 if ( !m_xOriginalStream.is() ) 225 throw io::NotConnectedException(); 226 227 PrepareCopy_Impl(); 228 229 m_xCopySeek->seek( location ); 230 } 231 232 //--------------------------------------------------------------------------- 233 sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() 234 throw ( io::IOException, 235 uno::RuntimeException ) 236 { 237 ::osl::MutexGuard aGuard( m_aMutex ); 238 239 if ( !m_xOriginalStream.is() ) 240 throw io::NotConnectedException(); 241 242 PrepareCopy_Impl(); 243 244 return m_xCopySeek->getPosition(); 245 } 246 247 //--------------------------------------------------------------------------- 248 sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() 249 throw ( io::IOException, 250 uno::RuntimeException ) 251 { 252 ::osl::MutexGuard aGuard( m_aMutex ); 253 254 if ( !m_xOriginalStream.is() ) 255 throw io::NotConnectedException(); 256 257 PrepareCopy_Impl(); 258 259 return m_xCopySeek->getLength(); 260 } 261 262 } // namespace comphelper 263 264