xref: /AOO41X/main/comphelper/source/streaming/seekableinput.cxx (revision dde7d3faf6dcd9cbeb7b48ba6d0cea5ffcc883d0)
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 //---------------------------------------------------------------------------
copyInputToOutput_Impl(const uno::Reference<io::XInputStream> & xIn,const uno::Reference<io::XOutputStream> & xOut)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 //---------------------------------------------------------------------------
OSeekableInputWrapper(const uno::Reference<io::XInputStream> & xInStream,const uno::Reference<lang::XMultiServiceFactory> & xFactory)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 //---------------------------------------------------------------------------
~OSeekableInputWrapper()71 OSeekableInputWrapper::~OSeekableInputWrapper()
72 {
73 }
74 
75 //---------------------------------------------------------------------------
CheckSeekableCanWrap(const uno::Reference<io::XInputStream> & xInStream,const uno::Reference<lang::XMultiServiceFactory> & xFactory)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 //---------------------------------------------------------------------------
PrepareCopy_Impl()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 //---------------------------------------------------------------------------
readBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)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 //---------------------------------------------------------------------------
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)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 //---------------------------------------------------------------------------
skipBytes(sal_Int32 nBytesToSkip)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 //---------------------------------------------------------------------------
available()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 //---------------------------------------------------------------------------
closeInput()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 //---------------------------------------------------------------------------
seek(sal_Int64 location)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 //---------------------------------------------------------------------------
getPosition()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 //---------------------------------------------------------------------------
getLength()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