xref: /aoo4110/main/ucb/source/ucp/gvfs/gvfs_stream.cxx (revision b1cdbd2c)
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_ucb.hxx"
26 #include "gvfs_stream.hxx"
27 #include <rtl/memory.h>
28 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
29 
30 #include <libgnomevfs/gnome-vfs-ops.h>
31 
32 using namespace cppu;
33 using namespace rtl;
34 using namespace com::sun::star::io;
35 using namespace com::sun::star::uno;
36 using namespace com::sun::star::ucb;
37 using namespace gvfs;
38 
Stream(GnomeVFSHandle * handle,const GnomeVFSFileInfo * aInfo)39 Stream::Stream( GnomeVFSHandle         *handle,
40         const GnomeVFSFileInfo *aInfo ) :
41     m_eof (sal_False),
42     m_bInputStreamCalled( sal_False ),
43     m_bOutputStreamCalled( sal_False )
44 {
45     m_handle = handle;
46     gnome_vfs_file_info_copy (&m_info, aInfo);
47 }
48 
~Stream(void)49 Stream::~Stream( void )
50 {
51     if (m_handle) {
52         gnome_vfs_close (m_handle);
53         m_handle = NULL;
54     }
55 }
56 
queryInterface(const Type & type)57 Any Stream::queryInterface( const Type &type )
58     throw( RuntimeException )
59 {
60     Any aRet = ::cppu::queryInterface
61         ( type,
62           static_cast< XStream * >( this ),
63           static_cast< XInputStream * >( this ),
64           static_cast< XOutputStream * >( this ),
65           static_cast< XSeekable * >( this ),
66           static_cast< XTruncate * >( this ) );
67 
68     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type );
69 }
70 
71 // -------------------------------------------------------------------
72 //                            XStream
73 // -------------------------------------------------------------------
74 
75 com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL
getInputStream()76 Stream::getInputStream(  )
77     throw( com::sun::star::uno::RuntimeException )
78 {
79     {
80         osl::MutexGuard aGuard( m_aMutex );
81         m_bInputStreamCalled = true;
82     }
83     return Reference< XInputStream >( this );
84 }
85 
86 com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL
getOutputStream()87 Stream::getOutputStream(  )
88     throw( com::sun::star::uno::RuntimeException )
89 {
90     {
91         osl::MutexGuard aGuard( m_aMutex );
92         m_bOutputStreamCalled = true;
93     }
94     return Reference< XOutputStream >( this );
95 }
96 
97 // -------------------------------------------------------------------
98 //                            XInputStream
99 // -------------------------------------------------------------------
100 
readBytes(Sequence<sal_Int8> & aData,sal_Int32 nBytesToRead)101 sal_Int32 SAL_CALL Stream::readBytes(
102     Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
103         throw( NotConnectedException,
104                BufferSizeExceededException,
105                IOException,
106                RuntimeException )
107 {
108     GnomeVFSResult   result;
109     GnomeVFSFileSize nBytesRead = 0;
110 
111     if( ! m_handle )
112         throw IOException();
113 
114     if( m_eof ) {
115         aData.realloc( 0 );
116         return 0;
117     }
118 
119     try {
120         aData.realloc( nBytesToRead );
121     } catch ( const Exception &e ) {
122         throw BufferSizeExceededException();
123     }
124 
125     do {
126         result = gnome_vfs_read( m_handle, aData.getArray(),
127                      nBytesToRead, &nBytesRead );
128     } while( result == GNOME_VFS_ERROR_INTERRUPTED );
129 
130     if (result != GNOME_VFS_OK &&
131         result != GNOME_VFS_ERROR_EOF)
132         throwOnError( result );
133 
134     if (result == GNOME_VFS_ERROR_EOF)
135         m_eof = sal_True;
136 
137     aData.realloc( sal::static_int_cast<sal_uInt32>(nBytesRead) );
138 
139     return sal::static_int_cast<sal_Int32>(nBytesRead);
140 }
141 
readSomeBytes(Sequence<sal_Int8> & aData,sal_Int32 nMaxBytesToRead)142 sal_Int32 SAL_CALL Stream::readSomeBytes(
143     Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
144             throw( NotConnectedException,
145                BufferSizeExceededException,
146                IOException,
147                RuntimeException )
148 {
149     // Again - having 2 methods here just sucks; cf. filinpstr.cxx
150     // This can never be an effective non-blocking API - so why bother ?
151     return readBytes( aData, nMaxBytesToRead );
152 }
153 
skipBytes(sal_Int32 nBytesToSkip)154 void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip )
155         throw( NotConnectedException,
156                BufferSizeExceededException,
157                IOException,
158                RuntimeException )
159 {
160     GnomeVFSResult result;
161 
162     if( ! m_handle )
163         throw IOException();
164 
165     result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_CURRENT, nBytesToSkip );
166 
167     if ( result == GNOME_VFS_ERROR_BAD_PARAMETERS ||
168          result == GNOME_VFS_ERROR_NOT_SUPPORTED )
169         g_warning ("FIXME: just read them in ...");
170 
171     throwOnError( result );
172 }
173 
available()174 sal_Int32 SAL_CALL Stream::available(  )
175         throw( NotConnectedException,
176                IOException,
177                RuntimeException )
178 {
179     return 0; // cf. filinpstr.cxx
180 }
181 
closeInput(void)182 void SAL_CALL Stream::closeInput( void )
183         throw( NotConnectedException,
184                    IOException,
185                    RuntimeException )
186 {
187     osl::MutexGuard aGuard( m_aMutex );
188     m_bInputStreamCalled = false;
189 
190     if( ! m_bOutputStreamCalled )
191         closeStream();
192 }
193 
194 // -------------------------------------------------------------------
195 //                            XSeekable
196 // -------------------------------------------------------------------
197 
seek(sal_Int64 location)198 void SAL_CALL Stream::seek( sal_Int64 location )
199         throw( ::com::sun::star::lang::IllegalArgumentException,
200                IOException,
201                RuntimeException )
202 {
203     GnomeVFSResult result;
204 
205     if( ! m_handle )
206         throw IOException();
207 
208     if ( location < 0 )
209         throw ::com::sun::star::lang::IllegalArgumentException();
210 
211     m_eof = sal_False;
212     result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_START, location );
213 
214     if (result == GNOME_VFS_ERROR_EOF)
215         throw ::com::sun::star::lang::IllegalArgumentException();
216 
217     throwOnError( result );
218 }
219 
getPosition()220 sal_Int64 SAL_CALL Stream::getPosition()
221         throw( IOException,
222                RuntimeException )
223 {
224     GnomeVFSFileSize nBytesIn = 0;
225 
226     if( ! m_handle )
227         throw IOException();
228 
229     throwOnError( gnome_vfs_tell( m_handle, &nBytesIn ) );
230 
231     return nBytesIn;
232 }
233 
getLength()234 sal_Int64 SAL_CALL Stream::getLength()
235     throw( IOException, RuntimeException )
236 {
237     // FIXME: so this sucks; it may be stale but ...
238     if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
239         return m_info.size;
240     else {
241         g_warning ("FIXME: No valid length");
242         return 0;
243     }
244 }
245 
246 // -------------------------------------------------------------------
247 //                            XTruncate
248 // -------------------------------------------------------------------
249 
truncate(void)250 void SAL_CALL Stream::truncate( void )
251     throw( com::sun::star::io::IOException,
252            com::sun::star::uno::RuntimeException )
253 {
254     if( ! m_handle )
255         throw IOException();
256 
257     throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) );
258 }
259 
260 // -------------------------------------------------------------------
261 //                            XOutputStream
262 // -------------------------------------------------------------------
263 
writeBytes(const com::sun::star::uno::Sequence<sal_Int8> & aData)264 void SAL_CALL Stream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
265     throw( com::sun::star::io::NotConnectedException,
266            com::sun::star::io::BufferSizeExceededException,
267            com::sun::star::io::IOException,
268            com::sun::star::uno::RuntimeException)
269 {
270     GnomeVFSResult   result = GNOME_VFS_OK;
271     GnomeVFSFileSize toWrite = aData.getLength();
272     const sal_Int8 *p = aData.getConstArray();
273 
274     if( ! m_handle )
275         throw IOException();
276 
277     while( toWrite > 0) {
278         GnomeVFSFileSize bytesWritten = 0;
279 
280         result = gnome_vfs_write( m_handle, p, toWrite, &bytesWritten );
281         if( result == GNOME_VFS_ERROR_INTERRUPTED )
282             continue;
283         throwOnError( result );
284         g_assert( bytesWritten <= toWrite );
285         toWrite -= bytesWritten;
286         p += bytesWritten;
287     }
288 }
289 
flush(void)290 void SAL_CALL Stream::flush( void )
291     throw( NotConnectedException, BufferSizeExceededException,
292            IOException, RuntimeException )
293 {
294 }
295 
closeOutput(void)296 void SAL_CALL Stream::closeOutput( void )
297     throw( com::sun::star::io::NotConnectedException,
298            com::sun::star::io::IOException,
299            com::sun::star::uno::RuntimeException )
300 {
301     osl::MutexGuard aGuard( m_aMutex );
302     m_bOutputStreamCalled = false;
303 
304     if( ! m_bInputStreamCalled )
305         closeStream();
306 }
307 
308 // -------------------------------------------------------------------
309 //                            Misc.
310 // -------------------------------------------------------------------
311 
closeStream(void)312 void Stream::closeStream( void )
313     throw( ::com::sun::star::io::NotConnectedException,
314            ::com::sun::star::io::IOException,
315            ::com::sun::star::uno::RuntimeException )
316 {
317     if (m_handle) {
318         gnome_vfs_close (m_handle);
319         m_handle = NULL;
320     } else
321         throw IOException();
322 }
323 
throwOnError(GnomeVFSResult result)324 void Stream::throwOnError( GnomeVFSResult result )
325     throw( NotConnectedException,
326            BufferSizeExceededException,
327            IOException,
328            RuntimeException )
329 {
330     if( result != GNOME_VFS_OK ) {
331         ::rtl::OUString aMsg = ::rtl::OUString::createFromAscii
332               ( gnome_vfs_result_to_string( result ) );
333 
334         g_warning( "Input Stream exceptional result '%s' (%d)",
335                gnome_vfs_result_to_string( result ), result );
336 
337         throw IOException( aMsg, static_cast< cppu::OWeakObject * >( this ) );
338     }
339 }
340