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 { 127 ::osl::MutexGuard aGuard( m_aMutex ); 128 129 if ( !m_xOriginalStream.is() ) 130 throw io::NotConnectedException(); 131 132 PrepareCopy_Impl(); 133 134 return m_xCopyInput->readBytes( aData, nBytesToRead ); 135 } 136 137 //--------------------------------------------------------------------------- 138 sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 139 { 140 ::osl::MutexGuard aGuard( m_aMutex ); 141 142 if ( !m_xOriginalStream.is() ) 143 throw io::NotConnectedException(); 144 145 PrepareCopy_Impl(); 146 147 return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead ); 148 } 149 150 //--------------------------------------------------------------------------- 151 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip ) 152 { 153 ::osl::MutexGuard aGuard( m_aMutex ); 154 155 if ( !m_xOriginalStream.is() ) 156 throw io::NotConnectedException(); 157 158 PrepareCopy_Impl(); 159 160 m_xCopyInput->skipBytes( nBytesToSkip ); 161 } 162 163 //--------------------------------------------------------------------------- 164 sal_Int32 SAL_CALL OSeekableInputWrapper::available() 165 { 166 ::osl::MutexGuard aGuard( m_aMutex ); 167 168 if ( !m_xOriginalStream.is() ) 169 throw io::NotConnectedException(); 170 171 PrepareCopy_Impl(); 172 173 return m_xCopyInput->available(); 174 } 175 176 //--------------------------------------------------------------------------- 177 void SAL_CALL OSeekableInputWrapper::closeInput() 178 { 179 ::osl::MutexGuard aGuard( m_aMutex ); 180 181 if ( !m_xOriginalStream.is() ) 182 throw io::NotConnectedException(); 183 184 m_xOriginalStream->closeInput(); 185 m_xOriginalStream = uno::Reference< io::XInputStream >(); 186 187 if ( m_xCopyInput.is() ) 188 { 189 m_xCopyInput->closeInput(); 190 m_xCopyInput = uno::Reference< io::XInputStream >(); 191 } 192 193 m_xCopySeek = uno::Reference< io::XSeekable >(); 194 } 195 196 197 // XSeekable 198 //--------------------------------------------------------------------------- 199 void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location ) 200 { 201 ::osl::MutexGuard aGuard( m_aMutex ); 202 203 if ( !m_xOriginalStream.is() ) 204 throw io::NotConnectedException(); 205 206 PrepareCopy_Impl(); 207 208 m_xCopySeek->seek( location ); 209 } 210 211 //--------------------------------------------------------------------------- 212 sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition() 213 { 214 ::osl::MutexGuard aGuard( m_aMutex ); 215 216 if ( !m_xOriginalStream.is() ) 217 throw io::NotConnectedException(); 218 219 PrepareCopy_Impl(); 220 221 return m_xCopySeek->getPosition(); 222 } 223 224 //--------------------------------------------------------------------------- 225 sal_Int64 SAL_CALL OSeekableInputWrapper::getLength() 226 { 227 ::osl::MutexGuard aGuard( m_aMutex ); 228 229 if ( !m_xOriginalStream.is() ) 230 throw io::NotConnectedException(); 231 232 PrepareCopy_Impl(); 233 234 return m_xCopySeek->getLength(); 235 } 236 237 } // namespace comphelper 238