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