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