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