xref: /trunk/main/comphelper/source/streaming/seekableinput.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
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 //---------------------------------------------------------------------------
readSomeBytes(uno::Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)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 //---------------------------------------------------------------------------
skipBytes(sal_Int32 nBytesToSkip)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 //---------------------------------------------------------------------------
available()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 //---------------------------------------------------------------------------
closeInput()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 //---------------------------------------------------------------------------
seek(sal_Int64 location)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 //---------------------------------------------------------------------------
getPosition()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 //---------------------------------------------------------------------------
getLength()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