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