1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_ucb.hxx" 30*cdf0e10cSrcweir #include "gvfs_stream.hxx" 31*cdf0e10cSrcweir #include <rtl/memory.h> 32*cdf0e10cSrcweir #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #include <libgnomevfs/gnome-vfs-ops.h> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir using namespace cppu; 37*cdf0e10cSrcweir using namespace rtl; 38*cdf0e10cSrcweir using namespace com::sun::star::io; 39*cdf0e10cSrcweir using namespace com::sun::star::uno; 40*cdf0e10cSrcweir using namespace com::sun::star::ucb; 41*cdf0e10cSrcweir using namespace gvfs; 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir Stream::Stream( GnomeVFSHandle *handle, 44*cdf0e10cSrcweir const GnomeVFSFileInfo *aInfo ) : 45*cdf0e10cSrcweir m_eof (sal_False), 46*cdf0e10cSrcweir m_bInputStreamCalled( sal_False ), 47*cdf0e10cSrcweir m_bOutputStreamCalled( sal_False ) 48*cdf0e10cSrcweir { 49*cdf0e10cSrcweir m_handle = handle; 50*cdf0e10cSrcweir gnome_vfs_file_info_copy (&m_info, aInfo); 51*cdf0e10cSrcweir } 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir Stream::~Stream( void ) 54*cdf0e10cSrcweir { 55*cdf0e10cSrcweir if (m_handle) { 56*cdf0e10cSrcweir gnome_vfs_close (m_handle); 57*cdf0e10cSrcweir m_handle = NULL; 58*cdf0e10cSrcweir } 59*cdf0e10cSrcweir } 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir Any Stream::queryInterface( const Type &type ) 62*cdf0e10cSrcweir throw( RuntimeException ) 63*cdf0e10cSrcweir { 64*cdf0e10cSrcweir Any aRet = ::cppu::queryInterface 65*cdf0e10cSrcweir ( type, 66*cdf0e10cSrcweir static_cast< XStream * >( this ), 67*cdf0e10cSrcweir static_cast< XInputStream * >( this ), 68*cdf0e10cSrcweir static_cast< XOutputStream * >( this ), 69*cdf0e10cSrcweir static_cast< XSeekable * >( this ), 70*cdf0e10cSrcweir static_cast< XTruncate * >( this ) ); 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir // ------------------------------------------------------------------- 76*cdf0e10cSrcweir // XStream 77*cdf0e10cSrcweir // ------------------------------------------------------------------- 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL 80*cdf0e10cSrcweir Stream::getInputStream( ) 81*cdf0e10cSrcweir throw( com::sun::star::uno::RuntimeException ) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMutex ); 85*cdf0e10cSrcweir m_bInputStreamCalled = true; 86*cdf0e10cSrcweir } 87*cdf0e10cSrcweir return Reference< XInputStream >( this ); 88*cdf0e10cSrcweir } 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL 91*cdf0e10cSrcweir Stream::getOutputStream( ) 92*cdf0e10cSrcweir throw( com::sun::star::uno::RuntimeException ) 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMutex ); 96*cdf0e10cSrcweir m_bOutputStreamCalled = true; 97*cdf0e10cSrcweir } 98*cdf0e10cSrcweir return Reference< XOutputStream >( this ); 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir // ------------------------------------------------------------------- 102*cdf0e10cSrcweir // XInputStream 103*cdf0e10cSrcweir // ------------------------------------------------------------------- 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir sal_Int32 SAL_CALL Stream::readBytes( 106*cdf0e10cSrcweir Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 107*cdf0e10cSrcweir throw( NotConnectedException, 108*cdf0e10cSrcweir BufferSizeExceededException, 109*cdf0e10cSrcweir IOException, 110*cdf0e10cSrcweir RuntimeException ) 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir GnomeVFSResult result; 113*cdf0e10cSrcweir GnomeVFSFileSize nBytesRead = 0; 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir if( ! m_handle ) 116*cdf0e10cSrcweir throw IOException(); 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir if( m_eof ) { 119*cdf0e10cSrcweir aData.realloc( 0 ); 120*cdf0e10cSrcweir return 0; 121*cdf0e10cSrcweir } 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir try { 124*cdf0e10cSrcweir aData.realloc( nBytesToRead ); 125*cdf0e10cSrcweir } catch ( const Exception &e ) { 126*cdf0e10cSrcweir throw BufferSizeExceededException(); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir do { 130*cdf0e10cSrcweir result = gnome_vfs_read( m_handle, aData.getArray(), 131*cdf0e10cSrcweir nBytesToRead, &nBytesRead ); 132*cdf0e10cSrcweir } while( result == GNOME_VFS_ERROR_INTERRUPTED ); 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir if (result != GNOME_VFS_OK && 135*cdf0e10cSrcweir result != GNOME_VFS_ERROR_EOF) 136*cdf0e10cSrcweir throwOnError( result ); 137*cdf0e10cSrcweir 138*cdf0e10cSrcweir if (result == GNOME_VFS_ERROR_EOF) 139*cdf0e10cSrcweir m_eof = sal_True; 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir aData.realloc( sal::static_int_cast<sal_uInt32>(nBytesRead) ); 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir return sal::static_int_cast<sal_Int32>(nBytesRead); 144*cdf0e10cSrcweir } 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir sal_Int32 SAL_CALL Stream::readSomeBytes( 147*cdf0e10cSrcweir Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 148*cdf0e10cSrcweir throw( NotConnectedException, 149*cdf0e10cSrcweir BufferSizeExceededException, 150*cdf0e10cSrcweir IOException, 151*cdf0e10cSrcweir RuntimeException ) 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir // Again - having 2 methods here just sucks; cf. filinpstr.cxx 154*cdf0e10cSrcweir // This can never be an effective non-blocking API - so why bother ? 155*cdf0e10cSrcweir return readBytes( aData, nMaxBytesToRead ); 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir 158*cdf0e10cSrcweir void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) 159*cdf0e10cSrcweir throw( NotConnectedException, 160*cdf0e10cSrcweir BufferSizeExceededException, 161*cdf0e10cSrcweir IOException, 162*cdf0e10cSrcweir RuntimeException ) 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir GnomeVFSResult result; 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir if( ! m_handle ) 167*cdf0e10cSrcweir throw IOException(); 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_CURRENT, nBytesToSkip ); 170*cdf0e10cSrcweir 171*cdf0e10cSrcweir if ( result == GNOME_VFS_ERROR_BAD_PARAMETERS || 172*cdf0e10cSrcweir result == GNOME_VFS_ERROR_NOT_SUPPORTED ) 173*cdf0e10cSrcweir g_warning ("FIXME: just read them in ..."); 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir throwOnError( result ); 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir sal_Int32 SAL_CALL Stream::available( ) 179*cdf0e10cSrcweir throw( NotConnectedException, 180*cdf0e10cSrcweir IOException, 181*cdf0e10cSrcweir RuntimeException ) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir return 0; // cf. filinpstr.cxx 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir void SAL_CALL Stream::closeInput( void ) 187*cdf0e10cSrcweir throw( NotConnectedException, 188*cdf0e10cSrcweir IOException, 189*cdf0e10cSrcweir RuntimeException ) 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMutex ); 192*cdf0e10cSrcweir m_bInputStreamCalled = false; 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir if( ! m_bOutputStreamCalled ) 195*cdf0e10cSrcweir closeStream(); 196*cdf0e10cSrcweir } 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir // ------------------------------------------------------------------- 199*cdf0e10cSrcweir // XSeekable 200*cdf0e10cSrcweir // ------------------------------------------------------------------- 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir void SAL_CALL Stream::seek( sal_Int64 location ) 203*cdf0e10cSrcweir throw( ::com::sun::star::lang::IllegalArgumentException, 204*cdf0e10cSrcweir IOException, 205*cdf0e10cSrcweir RuntimeException ) 206*cdf0e10cSrcweir { 207*cdf0e10cSrcweir GnomeVFSResult result; 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir if( ! m_handle ) 210*cdf0e10cSrcweir throw IOException(); 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir if ( location < 0 ) 213*cdf0e10cSrcweir throw ::com::sun::star::lang::IllegalArgumentException(); 214*cdf0e10cSrcweir 215*cdf0e10cSrcweir m_eof = sal_False; 216*cdf0e10cSrcweir result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_START, location ); 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir if (result == GNOME_VFS_ERROR_EOF) 219*cdf0e10cSrcweir throw ::com::sun::star::lang::IllegalArgumentException(); 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir throwOnError( result ); 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir sal_Int64 SAL_CALL Stream::getPosition() 225*cdf0e10cSrcweir throw( IOException, 226*cdf0e10cSrcweir RuntimeException ) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir GnomeVFSFileSize nBytesIn = 0; 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir if( ! m_handle ) 231*cdf0e10cSrcweir throw IOException(); 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir throwOnError( gnome_vfs_tell( m_handle, &nBytesIn ) ); 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir return nBytesIn; 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir sal_Int64 SAL_CALL Stream::getLength() 239*cdf0e10cSrcweir throw( IOException, RuntimeException ) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir // FIXME: so this sucks; it may be stale but ... 242*cdf0e10cSrcweir if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) 243*cdf0e10cSrcweir return m_info.size; 244*cdf0e10cSrcweir else { 245*cdf0e10cSrcweir g_warning ("FIXME: No valid length"); 246*cdf0e10cSrcweir return 0; 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir // ------------------------------------------------------------------- 251*cdf0e10cSrcweir // XTruncate 252*cdf0e10cSrcweir // ------------------------------------------------------------------- 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir void SAL_CALL Stream::truncate( void ) 255*cdf0e10cSrcweir throw( com::sun::star::io::IOException, 256*cdf0e10cSrcweir com::sun::star::uno::RuntimeException ) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir if( ! m_handle ) 259*cdf0e10cSrcweir throw IOException(); 260*cdf0e10cSrcweir 261*cdf0e10cSrcweir throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) ); 262*cdf0e10cSrcweir } 263*cdf0e10cSrcweir 264*cdf0e10cSrcweir // ------------------------------------------------------------------- 265*cdf0e10cSrcweir // XOutputStream 266*cdf0e10cSrcweir // ------------------------------------------------------------------- 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir void SAL_CALL Stream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) 269*cdf0e10cSrcweir throw( com::sun::star::io::NotConnectedException, 270*cdf0e10cSrcweir com::sun::star::io::BufferSizeExceededException, 271*cdf0e10cSrcweir com::sun::star::io::IOException, 272*cdf0e10cSrcweir com::sun::star::uno::RuntimeException) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir GnomeVFSResult result = GNOME_VFS_OK; 275*cdf0e10cSrcweir GnomeVFSFileSize toWrite = aData.getLength(); 276*cdf0e10cSrcweir const sal_Int8 *p = aData.getConstArray(); 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir if( ! m_handle ) 279*cdf0e10cSrcweir throw IOException(); 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir while( toWrite > 0) { 282*cdf0e10cSrcweir GnomeVFSFileSize bytesWritten = 0; 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir result = gnome_vfs_write( m_handle, p, toWrite, &bytesWritten ); 285*cdf0e10cSrcweir if( result == GNOME_VFS_ERROR_INTERRUPTED ) 286*cdf0e10cSrcweir continue; 287*cdf0e10cSrcweir throwOnError( result ); 288*cdf0e10cSrcweir g_assert( bytesWritten <= toWrite ); 289*cdf0e10cSrcweir toWrite -= bytesWritten; 290*cdf0e10cSrcweir p += bytesWritten; 291*cdf0e10cSrcweir } 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir void SAL_CALL Stream::flush( void ) 295*cdf0e10cSrcweir throw( NotConnectedException, BufferSizeExceededException, 296*cdf0e10cSrcweir IOException, RuntimeException ) 297*cdf0e10cSrcweir { 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir 300*cdf0e10cSrcweir void SAL_CALL Stream::closeOutput( void ) 301*cdf0e10cSrcweir throw( com::sun::star::io::NotConnectedException, 302*cdf0e10cSrcweir com::sun::star::io::IOException, 303*cdf0e10cSrcweir com::sun::star::uno::RuntimeException ) 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir osl::MutexGuard aGuard( m_aMutex ); 306*cdf0e10cSrcweir m_bOutputStreamCalled = false; 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir if( ! m_bInputStreamCalled ) 309*cdf0e10cSrcweir closeStream(); 310*cdf0e10cSrcweir } 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir // ------------------------------------------------------------------- 313*cdf0e10cSrcweir // Misc. 314*cdf0e10cSrcweir // ------------------------------------------------------------------- 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir void Stream::closeStream( void ) 317*cdf0e10cSrcweir throw( ::com::sun::star::io::NotConnectedException, 318*cdf0e10cSrcweir ::com::sun::star::io::IOException, 319*cdf0e10cSrcweir ::com::sun::star::uno::RuntimeException ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir if (m_handle) { 322*cdf0e10cSrcweir gnome_vfs_close (m_handle); 323*cdf0e10cSrcweir m_handle = NULL; 324*cdf0e10cSrcweir } else 325*cdf0e10cSrcweir throw IOException(); 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir void Stream::throwOnError( GnomeVFSResult result ) 329*cdf0e10cSrcweir throw( NotConnectedException, 330*cdf0e10cSrcweir BufferSizeExceededException, 331*cdf0e10cSrcweir IOException, 332*cdf0e10cSrcweir RuntimeException ) 333*cdf0e10cSrcweir { 334*cdf0e10cSrcweir if( result != GNOME_VFS_OK ) { 335*cdf0e10cSrcweir ::rtl::OUString aMsg = ::rtl::OUString::createFromAscii 336*cdf0e10cSrcweir ( gnome_vfs_result_to_string( result ) ); 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir g_warning( "Input Stream exceptional result '%s' (%d)", 339*cdf0e10cSrcweir gnome_vfs_result_to_string( result ), result ); 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir throw IOException( aMsg, static_cast< cppu::OWeakObject * >( this ) ); 342*cdf0e10cSrcweir } 343*cdf0e10cSrcweir } 344