| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_ucb.hxx" |
| #include "gvfs_stream.hxx" |
| #include <rtl/memory.h> |
| #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> |
| |
| #include <libgnomevfs/gnome-vfs-ops.h> |
| |
| using namespace cppu; |
| using namespace rtl; |
| using namespace com::sun::star::io; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::ucb; |
| using namespace gvfs; |
| |
| Stream::Stream( GnomeVFSHandle *handle, |
| const GnomeVFSFileInfo *aInfo ) : |
| m_eof (sal_False), |
| m_bInputStreamCalled( sal_False ), |
| m_bOutputStreamCalled( sal_False ) |
| { |
| m_handle = handle; |
| gnome_vfs_file_info_copy (&m_info, aInfo); |
| } |
| |
| Stream::~Stream( void ) |
| { |
| if (m_handle) { |
| gnome_vfs_close (m_handle); |
| m_handle = NULL; |
| } |
| } |
| |
| Any Stream::queryInterface( const Type &type ) |
| throw( RuntimeException ) |
| { |
| Any aRet = ::cppu::queryInterface |
| ( type, |
| static_cast< XStream * >( this ), |
| static_cast< XInputStream * >( this ), |
| static_cast< XOutputStream * >( this ), |
| static_cast< XSeekable * >( this ), |
| static_cast< XTruncate * >( this ) ); |
| |
| return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // XStream |
| // ------------------------------------------------------------------- |
| |
| com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL |
| Stream::getInputStream( ) |
| throw( com::sun::star::uno::RuntimeException ) |
| { |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| m_bInputStreamCalled = true; |
| } |
| return Reference< XInputStream >( this ); |
| } |
| |
| com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL |
| Stream::getOutputStream( ) |
| throw( com::sun::star::uno::RuntimeException ) |
| { |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| m_bOutputStreamCalled = true; |
| } |
| return Reference< XOutputStream >( this ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // XInputStream |
| // ------------------------------------------------------------------- |
| |
| sal_Int32 SAL_CALL Stream::readBytes( |
| Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) |
| throw( NotConnectedException, |
| BufferSizeExceededException, |
| IOException, |
| RuntimeException ) |
| { |
| GnomeVFSResult result; |
| GnomeVFSFileSize nBytesRead = 0; |
| |
| if( ! m_handle ) |
| throw IOException(); |
| |
| if( m_eof ) { |
| aData.realloc( 0 ); |
| return 0; |
| } |
| |
| try { |
| aData.realloc( nBytesToRead ); |
| } catch ( const Exception &e ) { |
| throw BufferSizeExceededException(); |
| } |
| |
| do { |
| result = gnome_vfs_read( m_handle, aData.getArray(), |
| nBytesToRead, &nBytesRead ); |
| } while( result == GNOME_VFS_ERROR_INTERRUPTED ); |
| |
| if (result != GNOME_VFS_OK && |
| result != GNOME_VFS_ERROR_EOF) |
| throwOnError( result ); |
| |
| if (result == GNOME_VFS_ERROR_EOF) |
| m_eof = sal_True; |
| |
| aData.realloc( sal::static_int_cast<sal_uInt32>(nBytesRead) ); |
| |
| return sal::static_int_cast<sal_Int32>(nBytesRead); |
| } |
| |
| sal_Int32 SAL_CALL Stream::readSomeBytes( |
| Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) |
| throw( NotConnectedException, |
| BufferSizeExceededException, |
| IOException, |
| RuntimeException ) |
| { |
| // Again - having 2 methods here just sucks; cf. filinpstr.cxx |
| // This can never be an effective non-blocking API - so why bother ? |
| return readBytes( aData, nMaxBytesToRead ); |
| } |
| |
| void SAL_CALL Stream::skipBytes( sal_Int32 nBytesToSkip ) |
| throw( NotConnectedException, |
| BufferSizeExceededException, |
| IOException, |
| RuntimeException ) |
| { |
| GnomeVFSResult result; |
| |
| if( ! m_handle ) |
| throw IOException(); |
| |
| result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_CURRENT, nBytesToSkip ); |
| |
| if ( result == GNOME_VFS_ERROR_BAD_PARAMETERS || |
| result == GNOME_VFS_ERROR_NOT_SUPPORTED ) |
| g_warning ("FIXME: just read them in ..."); |
| |
| throwOnError( result ); |
| } |
| |
| sal_Int32 SAL_CALL Stream::available( ) |
| throw( NotConnectedException, |
| IOException, |
| RuntimeException ) |
| { |
| return 0; // cf. filinpstr.cxx |
| } |
| |
| void SAL_CALL Stream::closeInput( void ) |
| throw( NotConnectedException, |
| IOException, |
| RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| m_bInputStreamCalled = false; |
| |
| if( ! m_bOutputStreamCalled ) |
| closeStream(); |
| } |
| |
| // ------------------------------------------------------------------- |
| // XSeekable |
| // ------------------------------------------------------------------- |
| |
| void SAL_CALL Stream::seek( sal_Int64 location ) |
| throw( ::com::sun::star::lang::IllegalArgumentException, |
| IOException, |
| RuntimeException ) |
| { |
| GnomeVFSResult result; |
| |
| if( ! m_handle ) |
| throw IOException(); |
| |
| if ( location < 0 ) |
| throw ::com::sun::star::lang::IllegalArgumentException(); |
| |
| m_eof = sal_False; |
| result = gnome_vfs_seek( m_handle, GNOME_VFS_SEEK_START, location ); |
| |
| if (result == GNOME_VFS_ERROR_EOF) |
| throw ::com::sun::star::lang::IllegalArgumentException(); |
| |
| throwOnError( result ); |
| } |
| |
| sal_Int64 SAL_CALL Stream::getPosition() |
| throw( IOException, |
| RuntimeException ) |
| { |
| GnomeVFSFileSize nBytesIn = 0; |
| |
| if( ! m_handle ) |
| throw IOException(); |
| |
| throwOnError( gnome_vfs_tell( m_handle, &nBytesIn ) ); |
| |
| return nBytesIn; |
| } |
| |
| sal_Int64 SAL_CALL Stream::getLength() |
| throw( IOException, RuntimeException ) |
| { |
| // FIXME: so this sucks; it may be stale but ... |
| if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) |
| return m_info.size; |
| else { |
| g_warning ("FIXME: No valid length"); |
| return 0; |
| } |
| } |
| |
| // ------------------------------------------------------------------- |
| // XTruncate |
| // ------------------------------------------------------------------- |
| |
| void SAL_CALL Stream::truncate( void ) |
| throw( com::sun::star::io::IOException, |
| com::sun::star::uno::RuntimeException ) |
| { |
| if( ! m_handle ) |
| throw IOException(); |
| |
| throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) ); |
| } |
| |
| // ------------------------------------------------------------------- |
| // XOutputStream |
| // ------------------------------------------------------------------- |
| |
| void SAL_CALL Stream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData ) |
| throw( com::sun::star::io::NotConnectedException, |
| com::sun::star::io::BufferSizeExceededException, |
| com::sun::star::io::IOException, |
| com::sun::star::uno::RuntimeException) |
| { |
| GnomeVFSResult result = GNOME_VFS_OK; |
| GnomeVFSFileSize toWrite = aData.getLength(); |
| const sal_Int8 *p = aData.getConstArray(); |
| |
| if( ! m_handle ) |
| throw IOException(); |
| |
| while( toWrite > 0) { |
| GnomeVFSFileSize bytesWritten = 0; |
| |
| result = gnome_vfs_write( m_handle, p, toWrite, &bytesWritten ); |
| if( result == GNOME_VFS_ERROR_INTERRUPTED ) |
| continue; |
| throwOnError( result ); |
| g_assert( bytesWritten <= toWrite ); |
| toWrite -= bytesWritten; |
| p += bytesWritten; |
| } |
| } |
| |
| void SAL_CALL Stream::flush( void ) |
| throw( NotConnectedException, BufferSizeExceededException, |
| IOException, RuntimeException ) |
| { |
| } |
| |
| void SAL_CALL Stream::closeOutput( void ) |
| throw( com::sun::star::io::NotConnectedException, |
| com::sun::star::io::IOException, |
| com::sun::star::uno::RuntimeException ) |
| { |
| osl::MutexGuard aGuard( m_aMutex ); |
| m_bOutputStreamCalled = false; |
| |
| if( ! m_bInputStreamCalled ) |
| closeStream(); |
| } |
| |
| // ------------------------------------------------------------------- |
| // Misc. |
| // ------------------------------------------------------------------- |
| |
| void Stream::closeStream( void ) |
| throw( ::com::sun::star::io::NotConnectedException, |
| ::com::sun::star::io::IOException, |
| ::com::sun::star::uno::RuntimeException ) |
| { |
| if (m_handle) { |
| gnome_vfs_close (m_handle); |
| m_handle = NULL; |
| } else |
| throw IOException(); |
| } |
| |
| void Stream::throwOnError( GnomeVFSResult result ) |
| throw( NotConnectedException, |
| BufferSizeExceededException, |
| IOException, |
| RuntimeException ) |
| { |
| if( result != GNOME_VFS_OK ) { |
| ::rtl::OUString aMsg = ::rtl::OUString::createFromAscii |
| ( gnome_vfs_result_to_string( result ) ); |
| |
| g_warning( "Input Stream exceptional result '%s' (%d)", |
| gnome_vfs_result_to_string( result ), result ); |
| |
| throw IOException( aMsg, static_cast< cppu::OWeakObject * >( this ) ); |
| } |
| } |