xref: /trunk/main/comphelper/source/streaming/seekableinput.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <com/sun/star/io/XOutputStream.hpp>
31 
32 
33 #include <comphelper/seekableinput.hxx>
34 
35 using namespace ::com::sun::star;
36 
37 namespace comphelper
38 {
39 
40 const sal_Int32 nConstBufferSize = 32000;
41 
42 //---------------------------------------------------------------------------
43 void copyInputToOutput_Impl( const uno::Reference< io::XInputStream >& xIn,
44                             const uno::Reference< io::XOutputStream >& xOut )
45 {
46     sal_Int32 nRead;
47     uno::Sequence< sal_Int8 > aSequence( nConstBufferSize );
48 
49     do
50     {
51         nRead = xIn->readBytes( aSequence, nConstBufferSize );
52         if ( nRead < nConstBufferSize )
53         {
54             uno::Sequence< sal_Int8 > aTempBuf( aSequence.getConstArray(), nRead );
55             xOut->writeBytes( aTempBuf );
56         }
57         else
58             xOut->writeBytes( aSequence );
59     }
60     while ( nRead == nConstBufferSize );
61 }
62 
63 //---------------------------------------------------------------------------
64 OSeekableInputWrapper::OSeekableInputWrapper(
65             const uno::Reference< io::XInputStream >& xInStream,
66             const uno::Reference< lang::XMultiServiceFactory >& xFactory )
67 : m_xFactory( xFactory )
68 , m_xOriginalStream( xInStream )
69 {
70     if ( !m_xFactory.is() )
71         throw uno::RuntimeException();
72 }
73 
74 //---------------------------------------------------------------------------
75 OSeekableInputWrapper::~OSeekableInputWrapper()
76 {
77 }
78 
79 //---------------------------------------------------------------------------
80 uno::Reference< io::XInputStream > OSeekableInputWrapper::CheckSeekableCanWrap(
81                             const uno::Reference< io::XInputStream >& xInStream,
82                             const uno::Reference< lang::XMultiServiceFactory >& xFactory )
83 {
84     // check that the stream is seekable and just wrap it if it is not
85     uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
86     if ( xSeek.is() )
87         return xInStream;
88 
89     uno::Reference< io::XInputStream > xNewStream(
90             static_cast< io::XInputStream* >(
91                 new OSeekableInputWrapper( xInStream, xFactory ) ) );
92     return xNewStream;
93 }
94 
95 //---------------------------------------------------------------------------
96 void OSeekableInputWrapper::PrepareCopy_Impl()
97 {
98     if ( !m_xCopyInput.is() )
99     {
100         if ( !m_xFactory.is() )
101             throw uno::RuntimeException();
102 
103         uno::Reference< io::XOutputStream > xTempOut(
104                 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
105                 uno::UNO_QUERY );
106 
107         if ( xTempOut.is() )
108         {
109             copyInputToOutput_Impl( m_xOriginalStream, xTempOut );
110             xTempOut->closeOutput();
111 
112             uno::Reference< io::XSeekable > xTempSeek( xTempOut, uno::UNO_QUERY );
113             if ( xTempSeek.is() )
114             {
115                 xTempSeek->seek( 0 );
116                 m_xCopyInput = uno::Reference< io::XInputStream >( xTempOut, uno::UNO_QUERY );
117                 if ( m_xCopyInput.is() )
118                     m_xCopySeek = xTempSeek;
119             }
120         }
121     }
122 
123     if ( !m_xCopyInput.is() )
124         throw io::IOException();
125 }
126 
127 // XInputStream
128 //---------------------------------------------------------------------------
129 sal_Int32 SAL_CALL OSeekableInputWrapper::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
130     throw ( io::NotConnectedException,
131             io::BufferSizeExceededException,
132             io::IOException,
133             uno::RuntimeException )
134 {
135     ::osl::MutexGuard aGuard( m_aMutex );
136 
137     if ( !m_xOriginalStream.is() )
138         throw io::NotConnectedException();
139 
140     PrepareCopy_Impl();
141 
142     return m_xCopyInput->readBytes( aData, nBytesToRead );
143 }
144 
145 //---------------------------------------------------------------------------
146 sal_Int32 SAL_CALL OSeekableInputWrapper::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
147     throw ( io::NotConnectedException,
148             io::BufferSizeExceededException,
149             io::IOException,
150             uno::RuntimeException )
151 {
152     ::osl::MutexGuard aGuard( m_aMutex );
153 
154     if ( !m_xOriginalStream.is() )
155         throw io::NotConnectedException();
156 
157     PrepareCopy_Impl();
158 
159     return m_xCopyInput->readSomeBytes( aData, nMaxBytesToRead );
160 }
161 
162 //---------------------------------------------------------------------------
163 void SAL_CALL OSeekableInputWrapper::skipBytes( sal_Int32 nBytesToSkip )
164     throw ( io::NotConnectedException,
165             io::BufferSizeExceededException,
166             io::IOException,
167             uno::RuntimeException )
168 {
169     ::osl::MutexGuard aGuard( m_aMutex );
170 
171     if ( !m_xOriginalStream.is() )
172         throw io::NotConnectedException();
173 
174     PrepareCopy_Impl();
175 
176     m_xCopyInput->skipBytes( nBytesToSkip );
177 }
178 
179 //---------------------------------------------------------------------------
180 sal_Int32 SAL_CALL OSeekableInputWrapper::available()
181     throw ( io::NotConnectedException,
182             io::IOException,
183             uno::RuntimeException )
184 {
185     ::osl::MutexGuard aGuard( m_aMutex );
186 
187     if ( !m_xOriginalStream.is() )
188         throw io::NotConnectedException();
189 
190     PrepareCopy_Impl();
191 
192     return m_xCopyInput->available();
193 }
194 
195 //---------------------------------------------------------------------------
196 void SAL_CALL OSeekableInputWrapper::closeInput()
197     throw ( io::NotConnectedException,
198             io::IOException,
199             uno::RuntimeException )
200 {
201     ::osl::MutexGuard aGuard( m_aMutex );
202 
203     if ( !m_xOriginalStream.is() )
204         throw io::NotConnectedException();
205 
206     m_xOriginalStream->closeInput();
207     m_xOriginalStream = uno::Reference< io::XInputStream >();
208 
209     if ( m_xCopyInput.is() )
210     {
211         m_xCopyInput->closeInput();
212         m_xCopyInput = uno::Reference< io::XInputStream >();
213     }
214 
215     m_xCopySeek = uno::Reference< io::XSeekable >();
216 }
217 
218 
219 // XSeekable
220 //---------------------------------------------------------------------------
221 void SAL_CALL OSeekableInputWrapper::seek( sal_Int64 location )
222     throw ( lang::IllegalArgumentException,
223             io::IOException,
224             uno::RuntimeException )
225 {
226     ::osl::MutexGuard aGuard( m_aMutex );
227 
228     if ( !m_xOriginalStream.is() )
229         throw io::NotConnectedException();
230 
231     PrepareCopy_Impl();
232 
233     m_xCopySeek->seek( location );
234 }
235 
236 //---------------------------------------------------------------------------
237 sal_Int64 SAL_CALL OSeekableInputWrapper::getPosition()
238     throw ( io::IOException,
239             uno::RuntimeException )
240 {
241     ::osl::MutexGuard aGuard( m_aMutex );
242 
243     if ( !m_xOriginalStream.is() )
244         throw io::NotConnectedException();
245 
246     PrepareCopy_Impl();
247 
248     return m_xCopySeek->getPosition();
249 }
250 
251 //---------------------------------------------------------------------------
252 sal_Int64 SAL_CALL OSeekableInputWrapper::getLength()
253     throw ( io::IOException,
254             uno::RuntimeException )
255 {
256     ::osl::MutexGuard aGuard( m_aMutex );
257 
258     if ( !m_xOriginalStream.is() )
259         throw io::NotConnectedException();
260 
261     PrepareCopy_Impl();
262 
263     return m_xCopySeek->getLength();
264 }
265 
266 }   // namespace comphelper
267 
268