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