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 "com/sun/star/io/IOException.hpp" 31 #include "com/sun/star/uno/RuntimeException.hpp" 32 #include "osl/diagnose.h" 33 #include "filstr.hxx" 34 #include "shell.hxx" 35 #include "prov.hxx" 36 37 38 using namespace fileaccess; 39 using namespace com::sun::star; 40 using namespace com::sun::star::ucb; 41 42 43 44 /******************************************************************************/ 45 /* */ 46 /* XStream_impl implementation */ 47 /* */ 48 /******************************************************************************/ 49 50 51 uno::Any SAL_CALL 52 XStream_impl::queryInterface( 53 const uno::Type& rType ) 54 throw( uno::RuntimeException) 55 { 56 uno::Any aRet = cppu::queryInterface( rType, 57 SAL_STATIC_CAST( lang::XTypeProvider*,this ), 58 SAL_STATIC_CAST( io::XStream*,this ), 59 SAL_STATIC_CAST( io::XInputStream*,this ), 60 SAL_STATIC_CAST( io::XOutputStream*,this ), 61 SAL_STATIC_CAST( io::XSeekable*,this ), 62 SAL_STATIC_CAST( io::XTruncate*,this ), 63 SAL_STATIC_CAST( io::XAsyncOutputMonitor*,this ) ); 64 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 65 } 66 67 68 void SAL_CALL 69 XStream_impl::acquire( 70 void ) 71 throw() 72 { 73 OWeakObject::acquire(); 74 } 75 76 77 void SAL_CALL 78 XStream_impl::release( 79 void ) 80 throw() 81 { 82 OWeakObject::release(); 83 } 84 85 86 ////////////////////////////////////////////////////////////////////////////////////////// 87 // XTypeProvider 88 ////////////////////////////////////////////////////////////////////////////////////////// 89 90 91 XTYPEPROVIDER_IMPL_7( XStream_impl, 92 lang::XTypeProvider, 93 io::XStream, 94 io::XSeekable, 95 io::XInputStream, 96 io::XOutputStream, 97 io::XTruncate, 98 io::XAsyncOutputMonitor ) 99 100 101 102 XStream_impl::XStream_impl( shell* pMyShell,const rtl::OUString& aUncPath, sal_Bool bLock ) 103 : m_bInputStreamCalled( false ), 104 m_bOutputStreamCalled( false ), 105 m_pMyShell( pMyShell ), 106 m_xProvider( m_pMyShell->m_pProvider ), 107 m_bLock( bLock ), 108 m_aFile( aUncPath ), 109 m_nErrorCode( TASKHANDLER_NO_ERROR ), 110 m_nMinorErrorCode( TASKHANDLER_NO_ERROR ) 111 { 112 sal_uInt32 nFlags = ( OpenFlag_Read | OpenFlag_Write ); 113 if ( !bLock ) 114 nFlags |= OpenFlag_NoLock; 115 116 osl::FileBase::RC err = m_aFile.open( nFlags ); 117 if( err != osl::FileBase::E_None ) 118 { 119 m_nIsOpen = false; 120 m_aFile.close(); 121 122 m_nErrorCode = TASKHANDLING_OPEN_FOR_STREAM; 123 m_nMinorErrorCode = err; 124 } 125 else 126 m_nIsOpen = true; 127 } 128 129 130 XStream_impl::~XStream_impl() 131 { 132 try 133 { 134 closeStream(); 135 } 136 catch (io::IOException const &) 137 { 138 OSL_ENSURE(false, "unexpected situation"); 139 } 140 catch (uno::RuntimeException const &) 141 { 142 OSL_ENSURE(false, "unexpected situation"); 143 } 144 } 145 146 147 sal_Int32 SAL_CALL XStream_impl::CtorSuccess() 148 { 149 return m_nErrorCode; 150 } 151 152 153 154 sal_Int32 SAL_CALL XStream_impl::getMinorError() 155 { 156 return m_nMinorErrorCode; 157 } 158 159 160 161 uno::Reference< io::XInputStream > SAL_CALL 162 XStream_impl::getInputStream( ) 163 throw( uno::RuntimeException) 164 { 165 { 166 osl::MutexGuard aGuard( m_aMutex ); 167 m_bInputStreamCalled = true; 168 } 169 return uno::Reference< io::XInputStream >( this ); 170 } 171 172 173 uno::Reference< io::XOutputStream > SAL_CALL 174 XStream_impl::getOutputStream( ) 175 throw( uno::RuntimeException ) 176 { 177 { 178 osl::MutexGuard aGuard( m_aMutex ); 179 m_bOutputStreamCalled = true; 180 } 181 return uno::Reference< io::XOutputStream >( this ); 182 } 183 184 185 void SAL_CALL XStream_impl::truncate(void) 186 throw( io::IOException, uno::RuntimeException ) 187 { 188 if (osl::FileBase::E_None != m_aFile.setSize(0)) 189 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 190 191 if (osl::FileBase::E_None != m_aFile.setPos(Pos_Absolut,sal_uInt64(0))) 192 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 193 } 194 195 196 197 //=========================================================================== 198 // XStream_impl private non interface methods 199 //=========================================================================== 200 201 sal_Int32 SAL_CALL 202 XStream_impl::readBytes( 203 uno::Sequence< sal_Int8 >& aData, 204 sal_Int32 nBytesToRead ) 205 throw( io::NotConnectedException, 206 io::BufferSizeExceededException, 207 io::IOException, 208 uno::RuntimeException) 209 { 210 if( ! m_nIsOpen ) 211 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 212 213 sal_Int8 * buffer; 214 try 215 { 216 buffer = new sal_Int8[nBytesToRead]; 217 } 218 catch( std::bad_alloc ) 219 { 220 if( m_nIsOpen ) m_aFile.close(); 221 throw io::BufferSizeExceededException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 222 } 223 224 sal_uInt64 nrc(0); 225 if(m_aFile.read( (void* )buffer,sal_uInt64(nBytesToRead),nrc ) 226 != osl::FileBase::E_None) 227 { 228 delete[] buffer; 229 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 230 } 231 aData = uno::Sequence< sal_Int8 > ( buffer, (sal_uInt32)nrc ); 232 delete[] buffer; 233 return ( sal_Int32 ) nrc; 234 } 235 236 237 sal_Int32 SAL_CALL 238 XStream_impl::readSomeBytes( 239 uno::Sequence< sal_Int8 >& aData, 240 sal_Int32 nMaxBytesToRead ) 241 throw( io::NotConnectedException, 242 io::BufferSizeExceededException, 243 io::IOException, 244 uno::RuntimeException) 245 { 246 return readBytes( aData,nMaxBytesToRead ); 247 } 248 249 250 void SAL_CALL 251 XStream_impl::skipBytes( 252 sal_Int32 nBytesToSkip ) 253 throw( io::NotConnectedException, 254 io::BufferSizeExceededException, 255 io::IOException, 256 uno::RuntimeException ) 257 { 258 m_aFile.setPos( osl_Pos_Current, sal_uInt64( nBytesToSkip ) ); 259 } 260 261 262 sal_Int32 SAL_CALL 263 XStream_impl::available( 264 void ) 265 throw( io::NotConnectedException, 266 io::IOException, 267 uno::RuntimeException) 268 { 269 return 0; 270 } 271 272 273 void SAL_CALL 274 XStream_impl::writeBytes( const uno::Sequence< sal_Int8 >& aData ) 275 throw( io::NotConnectedException, 276 io::BufferSizeExceededException, 277 io::IOException, 278 uno::RuntimeException) 279 { 280 sal_uInt32 length = aData.getLength(); 281 if(length) 282 { 283 sal_uInt64 nWrittenBytes(0); 284 const sal_Int8* p = aData.getConstArray(); 285 if(osl::FileBase::E_None != m_aFile.write(((void*)(p)),sal_uInt64(length),nWrittenBytes) || 286 nWrittenBytes != length ) 287 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 288 } 289 } 290 291 292 void SAL_CALL 293 XStream_impl::closeStream( 294 void ) 295 throw( io::NotConnectedException, 296 io::IOException, 297 uno::RuntimeException ) 298 { 299 if( m_nIsOpen ) 300 { 301 osl::FileBase::RC err = m_aFile.close(); 302 303 if( err != osl::FileBase::E_None ) { 304 io::IOException ex; 305 ex.Message = rtl::OUString::createFromAscii( 306 "could not close file"); 307 throw ex; 308 } 309 310 m_nIsOpen = false; 311 } 312 } 313 314 void SAL_CALL 315 XStream_impl::closeInput( 316 void ) 317 throw( io::NotConnectedException, 318 io::IOException, 319 uno::RuntimeException ) 320 { 321 osl::MutexGuard aGuard( m_aMutex ); 322 m_bInputStreamCalled = false; 323 324 if( ! m_bOutputStreamCalled ) 325 closeStream(); 326 } 327 328 329 void SAL_CALL 330 XStream_impl::closeOutput( 331 void ) 332 throw( io::NotConnectedException, 333 io::IOException, 334 uno::RuntimeException ) 335 { 336 osl::MutexGuard aGuard( m_aMutex ); 337 m_bOutputStreamCalled = false; 338 339 if( ! m_bInputStreamCalled ) 340 closeStream(); 341 } 342 343 344 void SAL_CALL 345 XStream_impl::seek( 346 sal_Int64 location ) 347 throw( lang::IllegalArgumentException, 348 io::IOException, 349 uno::RuntimeException ) 350 { 351 if( location < 0 ) 352 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); 353 if( osl::FileBase::E_None != m_aFile.setPos( Pos_Absolut, sal_uInt64( location ) ) ) 354 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 355 } 356 357 358 sal_Int64 SAL_CALL 359 XStream_impl::getPosition( 360 void ) 361 throw( io::IOException, 362 uno::RuntimeException ) 363 { 364 sal_uInt64 uPos; 365 if( osl::FileBase::E_None != m_aFile.getPos( uPos ) ) 366 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 367 return sal_Int64( uPos ); 368 } 369 370 sal_Int64 SAL_CALL 371 XStream_impl::getLength( 372 void ) 373 throw( io::IOException, 374 uno::RuntimeException ) 375 { 376 sal_uInt64 uEndPos; 377 if ( m_aFile.getSize(uEndPos) != osl::FileBase::E_None ) 378 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 379 else 380 return sal_Int64( uEndPos ); 381 } 382 383 void SAL_CALL 384 XStream_impl::flush() 385 throw( io::NotConnectedException, 386 io::BufferSizeExceededException, 387 io::IOException, 388 uno::RuntimeException ) 389 {} 390 391 void XStream_impl::waitForCompletion() 392 throw (io::IOException, uno::RuntimeException) 393 { 394 // At least on UNIX, to reliably learn about any errors encountered by 395 // asynchronous NFS write operations, without closing the file directly 396 // afterwards, there appears to be no cheaper way than to call fsync: 397 if (m_nIsOpen && m_aFile.sync() != osl::FileBase::E_None) { 398 throw io::IOException( 399 rtl::OUString( 400 RTL_CONSTASCII_USTRINGPARAM( 401 "could not synchronize file to disc")), 402 static_cast< OWeakObject * >(this)); 403 } 404 } 405