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