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