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