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_package.hxx" 26 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 27 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 28 #include <com/sun/star/lang/DisposedException.hpp> 29 #include <com/sun/star/lang/XUnoTunnel.hpp> 30 #include <com/sun/star/lang/XTypeProvider.hpp> 31 #include <com/sun/star/io/XInputStream.hpp> 32 #include <com/sun/star/io/IOException.hpp> 33 #include <com/sun/star/embed/ElementModes.hpp> 34 #include <com/sun/star/embed/StorageFormats.hpp> 35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> 36 #include <cppuhelper/typeprovider.hxx> 37 #include <cppuhelper/exc_hlp.hxx> 38 #include <osl/diagnose.h> 39 40 #include <comphelper/processfactory.hxx> 41 #include <comphelper/componentcontext.hxx> 42 #include <comphelper/storagehelper.hxx> 43 #include <comphelper/ofopxmlhelper.hxx> 44 45 #include <rtl/digest.h> 46 #include <rtl/logfile.hxx> 47 #include <rtl/instance.hxx> 48 49 #include <PackageConstants.hxx> 50 #include <mutexholder.hxx> 51 52 #include "selfterminatefilestream.hxx" 53 #include "owriteablestream.hxx" 54 #include "oseekinstream.hxx" 55 #include "xstorage.hxx" 56 57 // since the copying uses 32000 blocks usually, it makes sense to have a smaller size 58 #define MAX_STORCACHE_SIZE 30000 59 60 61 using namespace ::com::sun::star; 62 63 namespace package 64 { 65 //----------------------------------------------- 66 bool PackageEncryptionDatasEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 ) 67 { 68 bool bResult = ( aHash1.size() && aHash1.size() == aHash2.size() ); 69 for ( ::comphelper::SequenceAsHashMap::const_iterator aIter = aHash1.begin(); 70 bResult && aIter != aHash1.end(); 71 aIter++ ) 72 { 73 uno::Sequence< sal_Int8 > aKey1; 74 bResult = ( ( aIter->second >>= aKey1 ) && aKey1.getLength() ); 75 if ( bResult ) 76 { 77 uno::Sequence< sal_Int8 > aKey2 = aHash2.getUnpackedValueOrDefault( aIter->first, uno::Sequence< sal_Int8 >() ); 78 bResult = ( aKey1.getLength() == aKey2.getLength() ); 79 for ( sal_Int32 nInd = 0; bResult && nInd < aKey1.getLength(); nInd++ ) 80 bResult = ( aKey1[nInd] == aKey2[nInd] ); 81 } 82 } 83 84 return bResult; 85 } 86 87 //----------------------------------------------- 88 void StaticAddLog( const ::rtl::OUString& aMessage ) 89 { 90 try 91 { 92 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); 93 if ( aContext.is() ) 94 { 95 uno::Reference< logging::XSimpleLogRing > xLogRing( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW ); 96 xLogRing->logString( aMessage ); 97 } 98 } 99 catch( uno::Exception& ) 100 { 101 // No log 102 } 103 } 104 } // namespace package 105 106 // ================================================================ 107 namespace 108 { 109 //----------------------------------------------- 110 void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet, 111 const uno::Sequence< beans::NamedValue >& aKey ) 112 { 113 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" ); 114 if ( !xPropertySet.is() ) 115 throw uno::RuntimeException(); 116 117 try { 118 xPropertySet->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ), uno::makeAny( aKey ) ); 119 } 120 catch ( uno::Exception& aException ) 121 { 122 ::package::StaticAddLog( aException.Message ); 123 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't set encryption" ) ) ); 124 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" ); 125 throw io::IOException(); // TODO 126 } 127 } 128 129 //----------------------------------------------- 130 uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet ) 131 { 132 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" ); 133 if ( !xPropertySet.is() ) 134 throw uno::RuntimeException(); 135 136 try { 137 return xPropertySet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ); 138 } 139 catch ( uno::Exception& aException ) 140 { 141 ::package::StaticAddLog( aException.Message ); 142 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't get encryption property" ) ) ); 143 144 OSL_ENSURE( sal_False, "Can't get encryption related properties!\n" ); 145 throw io::IOException(); // TODO 146 } 147 } 148 149 //----------------------------------------------- 150 bool SequencesEqual( const uno::Sequence< sal_Int8 >& aSequence1, const uno::Sequence< sal_Int8 >& aSequence2 ) 151 { 152 if ( aSequence1.getLength() != aSequence2.getLength() ) 153 return false; 154 155 for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ ) 156 if ( aSequence1[nInd] != aSequence2[nInd] ) 157 return false; 158 159 return true; 160 } 161 162 //----------------------------------------------- 163 bool SequencesEqual( const uno::Sequence< beans::NamedValue >& aSequence1, const uno::Sequence< beans::NamedValue >& aSequence2 ) 164 { 165 if ( aSequence1.getLength() != aSequence2.getLength() ) 166 return false; 167 168 for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ ) 169 { 170 bool bHasMember = false; 171 uno::Sequence< sal_Int8 > aMember1; 172 sal_Int32 nMember1 = 0; 173 if ( ( aSequence1[nInd].Value >>= aMember1 ) ) 174 { 175 for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ ) 176 { 177 if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) ) 178 { 179 bHasMember = true; 180 181 uno::Sequence< sal_Int8 > aMember2; 182 if ( !( aSequence2[nInd2].Value >>= aMember2 ) || !SequencesEqual( aMember1, aMember2 ) ) 183 return false; 184 } 185 } 186 } 187 else if ( ( aSequence1[nInd].Value >>= nMember1 ) ) 188 { 189 for ( sal_Int32 nInd2 = 0; nInd2 < aSequence2.getLength(); nInd2++ ) 190 { 191 if ( aSequence1[nInd].Name.equals( aSequence2[nInd2].Name ) ) 192 { 193 bHasMember = true; 194 195 sal_Int32 nMember2 = 0; 196 if ( !( aSequence2[nInd2].Value >>= nMember2 ) || nMember1 != nMember2 ) 197 return false; 198 } 199 } 200 } 201 else 202 return false; 203 204 if ( !bHasMember ) 205 return false; 206 } 207 208 return true; 209 } 210 211 //----------------------------------------------- 212 sal_Bool KillFile( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 213 { 214 if ( !xFactory.is() ) 215 return sal_False; 216 217 sal_Bool bRet = sal_False; 218 219 try 220 { 221 uno::Reference < ucb::XSimpleFileAccess > xAccess( 222 xFactory->createInstance ( 223 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 224 uno::UNO_QUERY ); 225 226 if ( xAccess.is() ) 227 { 228 xAccess->kill( aURL ); 229 bRet = sal_True; 230 } 231 } 232 catch( uno::Exception& aException ) 233 { 234 ::package::StaticAddLog( aException.Message ); 235 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 236 } 237 238 return bRet; 239 } 240 241 const sal_Int32 n_ConstBufferSize = 32000; 242 243 //----------------------------------------------- 244 ::rtl::OUString GetNewTempFileURL( const uno::Reference< lang::XMultiServiceFactory > xFactory ) 245 { 246 ::rtl::OUString aTempURL; 247 248 uno::Reference < beans::XPropertySet > xTempFile( 249 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 250 uno::UNO_QUERY ); 251 252 if ( !xTempFile.is() ) 253 throw uno::RuntimeException(); // TODO 254 255 try { 256 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) ); 257 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); 258 aUrl >>= aTempURL; 259 } 260 catch ( uno::Exception& aException ) 261 { 262 ::package::StaticAddLog( aException.Message ); 263 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 264 } 265 266 if ( !aTempURL.getLength() ) 267 throw uno::RuntimeException(); // TODO: can not create tempfile 268 269 return aTempURL; 270 } 271 272 //----------------------------------------------- 273 uno::Reference< io::XStream > CreateMemoryStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 274 { 275 if ( !xFactory.is() ) 276 throw uno::RuntimeException(); 277 278 return uno::Reference< io::XStream >( xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.comp.MemoryStream" ) ), uno::UNO_QUERY_THROW ); 279 } 280 281 } // anonymous namespace 282 // ================================================================ 283 284 //----------------------------------------------- 285 OWriteStream_Impl::OWriteStream_Impl( OStorage_Impl* pParent, 286 const uno::Reference< packages::XDataSinkEncrSupport >& xPackageStream, 287 const uno::Reference< lang::XSingleServiceFactory >& xPackage, 288 const uno::Reference< lang::XMultiServiceFactory >& xFactory, 289 sal_Bool bForceEncrypted, 290 sal_Int32 nStorageType, 291 sal_Bool bDefaultCompress, 292 const uno::Reference< io::XInputStream >& xRelInfoStream ) 293 : m_pAntiImpl( NULL ) 294 , m_bHasDataToFlush( sal_False ) 295 , m_bFlushed( sal_False ) 296 , m_xPackageStream( xPackageStream ) 297 , m_xFactory( xFactory ) 298 , m_pParent( pParent ) 299 , m_bForceEncrypted( bForceEncrypted ) 300 , m_bUseCommonEncryption( !bForceEncrypted && nStorageType == embed::StorageFormats::PACKAGE ) 301 , m_bHasCachedEncryptionData( sal_False ) 302 , m_bCompressedSetExplicit( !bDefaultCompress ) 303 , m_xPackage( xPackage ) 304 , m_bHasInsertedStreamOptimization( sal_False ) 305 , m_nStorageType( nStorageType ) 306 , m_xOrigRelInfoStream( xRelInfoStream ) 307 , m_bOrigRelInfoBroken( sal_False ) 308 , m_nRelInfoStatus( RELINFO_NO_INIT ) 309 , m_nRelId( 1 ) 310 { 311 OSL_ENSURE( xPackageStream.is(), "No package stream is provided!\n" ); 312 OSL_ENSURE( xPackage.is(), "No package component is provided!\n" ); 313 OSL_ENSURE( m_xFactory.is(), "No package stream is provided!\n" ); 314 OSL_ENSURE( pParent, "No parent storage is provided!\n" ); 315 OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML || !m_xOrigRelInfoStream.is(), "The Relations info makes sence only for OFOPXML format!\n" ); 316 } 317 318 //----------------------------------------------- 319 OWriteStream_Impl::~OWriteStream_Impl() 320 { 321 DisposeWrappers(); 322 323 if ( m_aTempURL.getLength() ) 324 { 325 KillFile( m_aTempURL, GetServiceFactory() ); 326 m_aTempURL = ::rtl::OUString(); 327 } 328 329 CleanCacheStream(); 330 } 331 332 //----------------------------------------------- 333 void OWriteStream_Impl::CleanCacheStream() 334 { 335 if ( m_xCacheStream.is() ) 336 { 337 try 338 { 339 uno::Reference< io::XInputStream > xInputCache = m_xCacheStream->getInputStream(); 340 if ( xInputCache.is() ) 341 xInputCache->closeInput(); 342 } 343 catch( uno::Exception& ) 344 {} 345 346 try 347 { 348 uno::Reference< io::XOutputStream > xOutputCache = m_xCacheStream->getOutputStream(); 349 if ( xOutputCache.is() ) 350 xOutputCache->closeOutput(); 351 } 352 catch( uno::Exception& ) 353 {} 354 355 m_xCacheStream = uno::Reference< io::XStream >(); 356 m_xCacheSeek = uno::Reference< io::XSeekable >(); 357 } 358 } 359 360 //----------------------------------------------- 361 void OWriteStream_Impl::AddLog( const ::rtl::OUString& aMessage ) 362 { 363 if ( !m_xLogRing.is() ) 364 { 365 try 366 { 367 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); 368 if ( aContext.is() ) 369 m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW ); 370 } 371 catch( uno::Exception& ) 372 { 373 // No log 374 } 375 } 376 377 if ( m_xLogRing.is() ) 378 m_xLogRing->logString( aMessage ); 379 } 380 381 382 //----------------------------------------------- 383 void OWriteStream_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName, 384 const uno::Reference< container::XNameContainer >& xParentPackageFolder ) 385 { 386 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ); 387 388 OSL_ENSURE( m_bFlushed, "This method must not be called for nonflushed streams!\n" ); 389 if ( m_bFlushed ) 390 { 391 OSL_ENSURE( m_xPackageStream.is(), "An inserted stream is incomplete!\n" ); 392 uno::Reference< lang::XUnoTunnel > xTunnel( m_xPackageStream, uno::UNO_QUERY ); 393 if ( !xTunnel.is() ) 394 throw uno::RuntimeException(); // TODO 395 396 xParentPackageFolder->insertByName( aName, uno::makeAny( xTunnel ) ); 397 398 m_bFlushed = sal_False; 399 m_bHasInsertedStreamOptimization = sal_False; 400 } 401 } 402 //----------------------------------------------- 403 sal_Bool OWriteStream_Impl::IsEncrypted() 404 { 405 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 406 return sal_False; 407 408 if ( m_bForceEncrypted || m_bHasCachedEncryptionData ) 409 return sal_True; 410 411 if ( m_aTempURL.getLength() || m_xCacheStream.is() ) 412 return sal_False; 413 414 GetStreamProperties(); 415 416 // the following value can not be cached since it can change after root commit 417 sal_Bool bWasEncr = sal_False; 418 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY ); 419 if ( xPropSet.is() ) 420 { 421 uno::Any aValue = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "WasEncrypted" ) ); 422 if ( !( aValue >>= bWasEncr ) ) 423 { 424 OSL_ENSURE( sal_False, "The property WasEncrypted has wrong type!\n" ); 425 } 426 } 427 428 sal_Bool bToBeEncr = sal_False; 429 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ ) 430 { 431 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) ) 432 { 433 if ( !( m_aProps[nInd].Value >>= bToBeEncr ) ) 434 { 435 OSL_ENSURE( sal_False, "The property has wrong type!\n" ); 436 } 437 } 438 } 439 440 // since a new key set to the package stream it should not be removed except the case when 441 // the stream becomes nonencrypted 442 uno::Sequence< beans::NamedValue > aKey; 443 if ( bToBeEncr ) 444 GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey; 445 446 // If the properties must be investigated the stream is either 447 // was never changed or was changed, the parent was commited 448 // and the stream was closed. 449 // That means that if it is intended to use common storage key 450 // it is already has no encryption but is marked to be stored 451 // encrypted and the key is empty. 452 if ( !bWasEncr && bToBeEncr && !aKey.getLength() ) 453 { 454 // the stream is intended to use common storage password 455 m_bUseCommonEncryption = sal_True; 456 return sal_False; 457 } 458 else 459 return bToBeEncr; 460 } 461 462 //----------------------------------------------- 463 void OWriteStream_Impl::SetDecrypted() 464 { 465 OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE, "The encryption is supported only for package storages!\n" ); 466 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 467 throw uno::RuntimeException(); 468 469 GetStreamProperties(); 470 471 // let the stream be modified 472 FillTempGetFileName(); 473 m_bHasDataToFlush = sal_True; 474 475 // remove encryption 476 m_bForceEncrypted = sal_False; 477 m_bHasCachedEncryptionData = sal_False; 478 m_aEncryptionData.clear(); 479 480 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ ) 481 { 482 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) ) 483 m_aProps[nInd].Value <<= sal_False; 484 } 485 } 486 487 //----------------------------------------------- 488 void OWriteStream_Impl::SetEncrypted( const ::comphelper::SequenceAsHashMap& aEncryptionData ) 489 { 490 OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE, "The encryption is supported only for package storages!\n" ); 491 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 492 throw uno::RuntimeException(); 493 494 if ( !aEncryptionData.size() ) 495 throw uno::RuntimeException(); 496 497 GetStreamProperties(); 498 499 // let the stream be modified 500 FillTempGetFileName(); 501 m_bHasDataToFlush = sal_True; 502 503 // introduce encryption info 504 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ ) 505 { 506 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) ) 507 m_aProps[nInd].Value <<= sal_True; 508 } 509 510 m_bUseCommonEncryption = sal_False; // very important to set it to false 511 512 m_bHasCachedEncryptionData = sal_True; 513 m_aEncryptionData = aEncryptionData; 514 } 515 516 //----------------------------------------------- 517 void OWriteStream_Impl::DisposeWrappers() 518 { 519 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ); 520 if ( m_pAntiImpl ) 521 { 522 try { 523 m_pAntiImpl->dispose(); 524 } 525 catch ( uno::RuntimeException& aRuntimeException ) 526 { 527 AddLog( aRuntimeException.Message ); 528 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 529 } 530 531 m_pAntiImpl = NULL; 532 } 533 m_pParent = NULL; 534 535 if ( !m_aInputStreamsList.empty() ) 536 { 537 for ( InputStreamsList_Impl::iterator pStreamIter = m_aInputStreamsList.begin(); 538 pStreamIter != m_aInputStreamsList.end(); pStreamIter++ ) 539 { 540 if ( (*pStreamIter) ) 541 { 542 (*pStreamIter)->InternalDispose(); 543 (*pStreamIter) = NULL; 544 } 545 } 546 547 m_aInputStreamsList.clear(); 548 } 549 } 550 551 //----------------------------------------------- 552 uno::Reference< lang::XMultiServiceFactory > OWriteStream_Impl::GetServiceFactory() 553 { 554 if ( m_xFactory.is() ) 555 return m_xFactory; 556 557 return ::comphelper::getProcessServiceFactory(); 558 } 559 560 //----------------------------------------------- 561 ::rtl::OUString OWriteStream_Impl::GetFilledTempFileIfNo( const uno::Reference< io::XInputStream >& xStream ) 562 { 563 if ( !m_aTempURL.getLength() ) 564 { 565 ::rtl::OUString aTempURL = GetNewTempFileURL( GetServiceFactory() ); 566 567 try { 568 if ( aTempURL && xStream.is() ) 569 { 570 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 571 GetServiceFactory()->createInstance ( 572 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 573 uno::UNO_QUERY ); 574 575 if ( !xTempAccess.is() ) 576 throw uno::RuntimeException(); // TODO: 577 578 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aTempURL ); 579 if ( xTempOutStream.is() ) 580 { 581 // the current position of the original stream should be still OK, copy further 582 ::comphelper::OStorageHelper::CopyInputToOutput( xStream, xTempOutStream ); 583 xTempOutStream->closeOutput(); 584 xTempOutStream = uno::Reference< io::XOutputStream >(); 585 } 586 else 587 throw io::IOException(); // TODO: 588 } 589 } 590 catch( packages::WrongPasswordException& aWrongPasswordException ) 591 { 592 AddLog( aWrongPasswordException.Message ); 593 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 594 595 KillFile( aTempURL, GetServiceFactory() ); 596 throw; 597 } 598 catch( uno::Exception& aException ) 599 { 600 AddLog( aException.Message ); 601 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 602 603 KillFile( aTempURL, GetServiceFactory() ); 604 throw; 605 } 606 607 if ( aTempURL.getLength() ) 608 CleanCacheStream(); 609 610 m_aTempURL = aTempURL; 611 } 612 613 return m_aTempURL; 614 } 615 616 //----------------------------------------------- 617 ::rtl::OUString OWriteStream_Impl::FillTempGetFileName() 618 { 619 // should try to create cache first, if the amount of contents is too big, the temp file should be taken 620 if ( !m_xCacheStream.is() && !m_aTempURL.getLength() ) 621 { 622 uno::Reference< io::XInputStream > xOrigStream = m_xPackageStream->getDataStream(); 623 if ( !xOrigStream.is() ) 624 { 625 // in case of new inserted package stream it is possible that input stream still was not set 626 uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() ); 627 OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" ); 628 m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW ); 629 m_xCacheStream = xCacheStream; 630 } 631 else 632 { 633 sal_Int32 nRead = 0; 634 uno::Sequence< sal_Int8 > aData( MAX_STORCACHE_SIZE + 1 ); 635 nRead = xOrigStream->readBytes( aData, MAX_STORCACHE_SIZE + 1 ); 636 if ( aData.getLength() > nRead ) 637 aData.realloc( nRead ); 638 639 if ( nRead <= MAX_STORCACHE_SIZE ) 640 { 641 uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() ); 642 OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" ); 643 644 if ( nRead ) 645 { 646 uno::Reference< io::XOutputStream > xOutStream( xCacheStream->getOutputStream(), uno::UNO_SET_THROW ); 647 xOutStream->writeBytes( aData ); 648 } 649 m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW ); 650 m_xCacheStream = xCacheStream; 651 m_xCacheSeek->seek( 0 ); 652 } 653 else if ( !m_aTempURL.getLength() ) 654 { 655 m_aTempURL = GetNewTempFileURL( GetServiceFactory() ); 656 657 try { 658 if ( m_aTempURL.getLength() ) 659 { 660 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 661 GetServiceFactory()->createInstance ( 662 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 663 uno::UNO_QUERY ); 664 665 if ( !xTempAccess.is() ) 666 throw uno::RuntimeException(); // TODO: 667 668 669 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( m_aTempURL ); 670 if ( xTempOutStream.is() ) 671 { 672 // copy stream contents to the file 673 xTempOutStream->writeBytes( aData ); 674 675 // the current position of the original stream should be still OK, copy further 676 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigStream, xTempOutStream ); 677 xTempOutStream->closeOutput(); 678 xTempOutStream = uno::Reference< io::XOutputStream >(); 679 } 680 else 681 throw io::IOException(); // TODO: 682 } 683 } 684 catch( packages::WrongPasswordException& ) 685 { 686 KillFile( m_aTempURL, GetServiceFactory() ); 687 m_aTempURL = ::rtl::OUString(); 688 689 throw; 690 } 691 catch( uno::Exception& ) 692 { 693 KillFile( m_aTempURL, GetServiceFactory() ); 694 m_aTempURL = ::rtl::OUString(); 695 } 696 } 697 } 698 } 699 700 return m_aTempURL; 701 } 702 703 //----------------------------------------------- 704 uno::Reference< io::XStream > OWriteStream_Impl::GetTempFileAsStream() 705 { 706 uno::Reference< io::XStream > xTempStream; 707 708 if ( !m_xCacheStream.is() ) 709 { 710 if ( !m_aTempURL.getLength() ) 711 m_aTempURL = FillTempGetFileName(); 712 713 if ( m_aTempURL.getLength() ) 714 { 715 // the temporary file is not used if the cache is used 716 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 717 GetServiceFactory()->createInstance ( 718 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 719 uno::UNO_QUERY ); 720 721 if ( !xTempAccess.is() ) 722 throw uno::RuntimeException(); // TODO: 723 724 try 725 { 726 xTempStream = xTempAccess->openFileReadWrite( m_aTempURL ); 727 } 728 catch( uno::Exception& aException ) 729 { 730 AddLog( aException.Message ); 731 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 732 } 733 } 734 } 735 736 if ( m_xCacheStream.is() ) 737 xTempStream = m_xCacheStream; 738 739 // the method must always return a stream 740 // in case the stream can not be open 741 // an exception should be thrown 742 if ( !xTempStream.is() ) 743 throw io::IOException(); //TODO: 744 745 return xTempStream; 746 } 747 748 //----------------------------------------------- 749 uno::Reference< io::XInputStream > OWriteStream_Impl::GetTempFileAsInputStream() 750 { 751 uno::Reference< io::XInputStream > xInputStream; 752 753 if ( !m_xCacheStream.is() ) 754 { 755 if ( !m_aTempURL.getLength() ) 756 m_aTempURL = FillTempGetFileName(); 757 758 if ( m_aTempURL.getLength() ) 759 { 760 // the temporary file is not used if the cache is used 761 uno::Reference < ucb::XSimpleFileAccess > xTempAccess( 762 GetServiceFactory()->createInstance ( 763 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 764 uno::UNO_QUERY ); 765 766 if ( !xTempAccess.is() ) 767 throw uno::RuntimeException(); // TODO: 768 769 try 770 { 771 xInputStream = xTempAccess->openFileRead( m_aTempURL ); 772 } 773 catch( uno::Exception& aException ) 774 { 775 AddLog( aException.Message ); 776 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 777 } 778 } 779 } 780 781 if ( m_xCacheStream.is() ) 782 xInputStream = m_xCacheStream->getInputStream(); 783 784 // the method must always return a stream 785 // in case the stream can not be open 786 // an exception should be thrown 787 if ( !xInputStream.is() ) 788 throw io::IOException(); // TODO: 789 790 return xInputStream; 791 } 792 793 // ================================================================================================= 794 795 //----------------------------------------------- 796 void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputStream >& xInStream, 797 const uno::Sequence< beans::PropertyValue >& aProps ) 798 { 799 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 800 801 // this call can be made only during parent storage commit 802 // the parent storage is responsible for the correct handling 803 // of deleted and renamed contents 804 805 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 806 807 if ( m_bHasDataToFlush ) 808 throw io::IOException(); 809 810 OSL_ENSURE( !m_aTempURL.getLength() && !m_xCacheStream.is(), "The temporary must not exist!\n" ); 811 812 // use new file as current persistent representation 813 // the new file will be removed after it's stream is closed 814 m_xPackageStream->setDataStream( xInStream ); 815 816 // copy properties to the package stream 817 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY ); 818 if ( !xPropertySet.is() ) 819 throw uno::RuntimeException(); 820 821 // The storage-package communication has a problem 822 // the storage caches properties, thus if the package changes one of them itself 823 // the storage does not know about it 824 825 // Depending from MediaType value the package can change the compressed property itself 826 // Thus if Compressed property is provided it must be set as the latest one 827 sal_Bool bCompressedIsSet = sal_False; 828 sal_Bool bCompressed = sal_False; 829 ::rtl::OUString aComprPropName( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ); 830 ::rtl::OUString aMedTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 831 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ ) 832 { 833 if ( aProps[nInd].Name.equals( aComprPropName ) ) 834 { 835 bCompressedIsSet = sal_True; 836 aProps[nInd].Value >>= bCompressed; 837 } 838 else if ( ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE ) 839 && aProps[nInd].Name.equals( aMedTypePropName ) ) 840 { 841 xPropertySet->setPropertyValue( aProps[nInd].Name, aProps[nInd].Value ); 842 } 843 else if ( m_nStorageType == embed::StorageFormats::PACKAGE && aProps[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) ) 844 aProps[nInd].Value >>= m_bUseCommonEncryption; 845 else 846 throw lang::IllegalArgumentException(); 847 848 // if there are cached properties update them 849 if ( aProps[nInd].Name.equals( aMedTypePropName ) || aProps[nInd].Name.equals( aComprPropName ) ) 850 for ( sal_Int32 nMemInd = 0; nMemInd < m_aProps.getLength(); nMemInd++ ) 851 { 852 if ( aProps[nInd].Name.equals( m_aProps[nMemInd].Name ) ) 853 m_aProps[nMemInd].Value = aProps[nInd].Value; 854 } 855 } 856 857 if ( bCompressedIsSet ) 858 { 859 xPropertySet->setPropertyValue( aComprPropName, uno::makeAny( (sal_Bool)bCompressed ) ); 860 m_bCompressedSetExplicit = sal_True; 861 } 862 863 if ( m_bUseCommonEncryption ) 864 { 865 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 866 throw uno::RuntimeException(); 867 868 // set to be encrypted but do not use encryption key 869 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), 870 uno::makeAny( uno::Sequence< beans::NamedValue >() ) ); 871 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ), 872 uno::makeAny( sal_True ) ); 873 } 874 875 // the stream should be free soon, after package is stored 876 m_bHasDataToFlush = sal_False; 877 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it 878 m_bHasInsertedStreamOptimization = sal_True; 879 } 880 881 //----------------------------------------------- 882 void OWriteStream_Impl::Commit() 883 { 884 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 885 886 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 887 888 if ( !m_bHasDataToFlush ) 889 return; 890 891 uno::Reference< packages::XDataSinkEncrSupport > xNewPackageStream; 892 uno::Sequence< uno::Any > aSeq( 1 ); 893 aSeq[0] <<= sal_False; 894 895 if ( m_xCacheStream.is() ) 896 { 897 if ( m_pAntiImpl ) 898 m_pAntiImpl->DeInit(); 899 900 uno::Reference< io::XInputStream > xInStream( m_xCacheStream->getInputStream(), uno::UNO_SET_THROW ); 901 902 xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >( 903 m_xPackage->createInstanceWithArguments( aSeq ), 904 uno::UNO_QUERY_THROW ); 905 906 xNewPackageStream->setDataStream( xInStream ); 907 908 m_xCacheStream = uno::Reference< io::XStream >(); 909 m_xCacheSeek = uno::Reference< io::XSeekable >(); 910 911 } 912 else if ( m_aTempURL.getLength() ) 913 { 914 if ( m_pAntiImpl ) 915 m_pAntiImpl->DeInit(); 916 917 uno::Reference< io::XInputStream > xInStream; 918 try 919 { 920 xInStream.set( static_cast< io::XInputStream* >( new OSelfTerminateFileStream( GetServiceFactory(), m_aTempURL ) ), uno::UNO_QUERY ); 921 } 922 catch( uno::Exception& ) 923 { 924 } 925 926 if ( !xInStream.is() ) 927 throw io::IOException(); 928 929 xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >( 930 m_xPackage->createInstanceWithArguments( aSeq ), 931 uno::UNO_QUERY_THROW ); 932 933 // TODO/NEW: Let the temporary file be removed after commit 934 xNewPackageStream->setDataStream( xInStream ); 935 m_aTempURL = ::rtl::OUString(); 936 } 937 else // if ( m_bHasInsertedStreamOptimization ) 938 { 939 // if the optimization is used the stream can be accessed directly 940 xNewPackageStream = m_xPackageStream; 941 } 942 943 // copy properties to the package stream 944 uno::Reference< beans::XPropertySet > xPropertySet( xNewPackageStream, uno::UNO_QUERY ); 945 if ( !xPropertySet.is() ) 946 throw uno::RuntimeException(); 947 948 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ ) 949 { 950 if ( m_aProps[nInd].Name.equalsAscii( "Size" ) ) 951 { 952 if ( m_pAntiImpl && !m_bHasInsertedStreamOptimization && m_pAntiImpl->m_xSeekable.is() ) 953 { 954 m_aProps[nInd].Value <<= ((sal_Int32)m_pAntiImpl->m_xSeekable->getLength()); 955 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value ); 956 } 957 } 958 else 959 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value ); 960 } 961 962 if ( m_bUseCommonEncryption ) 963 { 964 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 965 throw uno::RuntimeException(); 966 967 // set to be encrypted but do not use encryption key 968 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), 969 uno::makeAny( uno::Sequence< beans::NamedValue >() ) ); 970 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ), 971 uno::makeAny( sal_True ) ); 972 } 973 else if ( m_bHasCachedEncryptionData ) 974 { 975 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 976 throw uno::RuntimeException(); 977 978 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ), 979 uno::makeAny( m_aEncryptionData.getAsConstNamedValueList() ) ); 980 } 981 982 // the stream should be free soon, after package is stored 983 m_xPackageStream = xNewPackageStream; 984 m_bHasDataToFlush = sal_False; 985 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it 986 } 987 988 //----------------------------------------------- 989 void OWriteStream_Impl::Revert() 990 { 991 // can be called only from parent storage 992 // means complete reload of the stream 993 994 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 995 996 if ( !m_bHasDataToFlush ) 997 return; // nothing to do 998 999 OSL_ENSURE( m_aTempURL.getLength() || m_xCacheStream.is(), "The temporary must exist!\n" ); 1000 1001 if ( m_xCacheStream.is() ) 1002 { 1003 m_xCacheStream = uno::Reference< io::XStream >(); 1004 m_xCacheSeek = uno::Reference< io::XSeekable >(); 1005 } 1006 1007 if ( m_aTempURL.getLength() ) 1008 { 1009 KillFile( m_aTempURL, GetServiceFactory() ); 1010 m_aTempURL = ::rtl::OUString(); 1011 } 1012 1013 m_aProps.realloc( 0 ); 1014 1015 m_bHasDataToFlush = sal_False; 1016 1017 m_bUseCommonEncryption = sal_True; 1018 m_bHasCachedEncryptionData = sal_False; 1019 m_aEncryptionData.clear(); 1020 1021 if ( m_nStorageType == embed::StorageFormats::OFOPXML ) 1022 { 1023 // currently the relations storage is changed only on commit 1024 m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 1025 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); 1026 if ( m_xOrigRelInfoStream.is() ) 1027 { 1028 // the original stream is still here, that means that it was not parsed 1029 m_aOrigRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); 1030 m_nRelInfoStatus = RELINFO_NO_INIT; 1031 } 1032 else 1033 { 1034 // the original stream was aready parsed 1035 if ( !m_bOrigRelInfoBroken ) 1036 m_nRelInfoStatus = RELINFO_READ; 1037 else 1038 m_nRelInfoStatus = RELINFO_BROKEN; 1039 } 1040 } 1041 } 1042 1043 //----------------------------------------------- 1044 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::GetStreamProperties() 1045 { 1046 if ( !m_aProps.getLength() ) 1047 m_aProps = ReadPackageStreamProperties(); 1048 1049 return m_aProps; 1050 } 1051 1052 //----------------------------------------------- 1053 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::InsertOwnProps( 1054 const uno::Sequence< beans::PropertyValue >& aProps, 1055 sal_Bool bUseCommonEncryption ) 1056 { 1057 uno::Sequence< beans::PropertyValue > aResult( aProps ); 1058 sal_Int32 nLen = aResult.getLength(); 1059 1060 if ( m_nStorageType == embed::StorageFormats::PACKAGE ) 1061 { 1062 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) 1063 if ( aResult[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) ) 1064 { 1065 aResult[nInd].Value <<= bUseCommonEncryption; 1066 return aResult; 1067 } 1068 1069 aResult.realloc( ++nLen ); 1070 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ); 1071 aResult[nLen - 1].Value <<= bUseCommonEncryption; 1072 } 1073 else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) 1074 { 1075 ReadRelInfoIfNecessary(); 1076 1077 uno::Any aValue; 1078 if ( m_nRelInfoStatus == RELINFO_READ ) 1079 aValue <<= m_aOrigRelInfo; 1080 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED ) 1081 aValue <<= m_aNewRelInfo; 1082 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN 1083 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ), 1084 uno::Reference< uno::XInterface >() ); 1085 1086 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ ) 1087 if ( aResult[nInd].Name.equalsAscii( "RelationsInfo" ) ) 1088 { 1089 aResult[nInd].Value = aValue; 1090 return aResult; 1091 } 1092 1093 aResult.realloc( ++nLen ); 1094 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "RelationsInfo" ); 1095 aResult[nLen - 1].Value = aValue; 1096 } 1097 1098 return aResult; 1099 } 1100 1101 //----------------------------------------------- 1102 sal_Bool OWriteStream_Impl::IsTransacted() 1103 { 1104 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1105 return ( m_pAntiImpl && m_pAntiImpl->m_bTransacted ); 1106 } 1107 1108 void OWriteStream_Impl::ReadRelInfoIfNecessary() 1109 { 1110 if ( m_nStorageType != embed::StorageFormats::OFOPXML ) 1111 return; 1112 1113 if ( m_nRelInfoStatus == RELINFO_NO_INIT ) 1114 { 1115 try 1116 { 1117 // Init from original stream 1118 if ( m_xOrigRelInfoStream.is() ) 1119 m_aOrigRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence( 1120 m_xOrigRelInfoStream, 1121 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ), 1122 m_xFactory ); 1123 1124 // in case of success the stream must be thrown away, that means that the OrigRelInfo is initialized 1125 // the reason for this is that the original stream might not be seekable ( at the same time the new 1126 // provided stream must be seekable ), so it must be read only once 1127 m_xOrigRelInfoStream = uno::Reference< io::XInputStream >(); 1128 m_nRelInfoStatus = RELINFO_READ; 1129 } 1130 catch( uno::Exception& aException ) 1131 { 1132 AddLog( aException.Message ); 1133 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 1134 1135 m_nRelInfoStatus = RELINFO_BROKEN; 1136 m_bOrigRelInfoBroken = sal_True; 1137 } 1138 } 1139 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) 1140 { 1141 // Init from the new stream 1142 try 1143 { 1144 if ( m_xNewRelInfoStream.is() ) 1145 m_aNewRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence( 1146 m_xNewRelInfoStream, 1147 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ), 1148 m_xFactory ); 1149 1150 m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ; 1151 } 1152 catch( uno::Exception ) 1153 { 1154 m_nRelInfoStatus = RELINFO_CHANGED_BROKEN; 1155 } 1156 } 1157 } 1158 1159 //----------------------------------------------- 1160 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::ReadPackageStreamProperties() 1161 { 1162 sal_Int32 nPropNum = 0; 1163 if ( m_nStorageType == embed::StorageFormats::ZIP ) 1164 nPropNum = 2; 1165 else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) 1166 nPropNum = 3; 1167 else if ( m_nStorageType == embed::StorageFormats::PACKAGE ) 1168 nPropNum = 4; 1169 uno::Sequence< beans::PropertyValue > aResult( nPropNum ); 1170 1171 // The "Compressed" property must be set after "MediaType" property, 1172 // since the setting of the last one can change the value of the first one 1173 1174 if ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE ) 1175 { 1176 aResult[0].Name = ::rtl::OUString::createFromAscii("MediaType"); 1177 aResult[1].Name = ::rtl::OUString::createFromAscii("Compressed"); 1178 aResult[2].Name = ::rtl::OUString::createFromAscii("Size"); 1179 1180 if ( m_nStorageType == embed::StorageFormats::PACKAGE ) 1181 aResult[3].Name = ::rtl::OUString::createFromAscii("Encrypted"); 1182 } 1183 else 1184 { 1185 aResult[0].Name = ::rtl::OUString::createFromAscii("Compressed"); 1186 aResult[1].Name = ::rtl::OUString::createFromAscii("Size"); 1187 1188 } 1189 1190 // TODO: may be also raw stream should be marked 1191 1192 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY ); 1193 if ( xPropSet.is() ) 1194 { 1195 for ( sal_Int32 nInd = 0; nInd < aResult.getLength(); nInd++ ) 1196 { 1197 try { 1198 aResult[nInd].Value = xPropSet->getPropertyValue( aResult[nInd].Name ); 1199 } 1200 catch( uno::Exception& aException ) 1201 { 1202 AddLog( aException.Message ); 1203 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 1204 1205 OSL_ENSURE( sal_False, "A property can't be retrieved!\n" ); 1206 } 1207 } 1208 } 1209 else 1210 { 1211 OSL_ENSURE( sal_False, "Can not get properties from a package stream!\n" ); 1212 throw uno::RuntimeException(); 1213 } 1214 1215 return aResult; 1216 } 1217 1218 //----------------------------------------------- 1219 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream, 1220 const ::comphelper::SequenceAsHashMap& aEncryptionData ) 1221 { 1222 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1223 1224 OSL_ENSURE( !m_bUseCommonEncryption, "The stream can not be encrypted!" ); 1225 1226 if ( m_nStorageType != embed::StorageFormats::PACKAGE ) 1227 throw packages::NoEncryptionException(); 1228 1229 if ( m_pAntiImpl ) 1230 { 1231 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream ); 1232 } 1233 else 1234 { 1235 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, aEncryptionData, sal_False ); 1236 if ( !xOwnStream.is() ) 1237 throw io::IOException(); // TODO 1238 1239 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() ); 1240 } 1241 1242 uno::Reference< embed::XEncryptionProtectedSource2 > xEncr( xDestStream, uno::UNO_QUERY ); 1243 if ( xEncr.is() ) 1244 xEncr->setEncryptionData( aEncryptionData.getAsConstNamedValueList() ); 1245 } 1246 1247 //----------------------------------------------- 1248 uno::Sequence< uno::Sequence< beans::StringPair > > OWriteStream_Impl::GetAllRelationshipsIfAny() 1249 { 1250 if ( m_nStorageType != embed::StorageFormats::OFOPXML ) 1251 return uno::Sequence< uno::Sequence< beans::StringPair > >(); 1252 1253 ReadRelInfoIfNecessary(); 1254 1255 if ( m_nRelInfoStatus == RELINFO_READ ) 1256 return m_aOrigRelInfo; 1257 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED ) 1258 return m_aNewRelInfo; 1259 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN 1260 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ), 1261 uno::Reference< uno::XInterface >() ); 1262 } 1263 1264 //----------------------------------------------- 1265 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream ) 1266 { 1267 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1268 1269 if ( m_pAntiImpl ) 1270 { 1271 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream ); 1272 } 1273 else 1274 { 1275 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, sal_False ); 1276 if ( !xOwnStream.is() ) 1277 throw io::IOException(); // TODO 1278 1279 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() ); 1280 } 1281 } 1282 1283 //----------------------------------------------- 1284 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData, sal_Bool bHierarchyAccess ) 1285 { 1286 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1287 1288 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 1289 1290 if ( m_pAntiImpl ) 1291 throw io::IOException(); // TODO: 1292 1293 if ( !IsEncrypted() ) 1294 throw packages::NoEncryptionException(); 1295 1296 uno::Reference< io::XStream > xResultStream; 1297 1298 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY ); 1299 if ( !xPropertySet.is() ) 1300 throw uno::RuntimeException(); 1301 1302 if ( m_bHasCachedEncryptionData ) 1303 { 1304 if ( !::package::PackageEncryptionDatasEqual( m_aEncryptionData, aEncryptionData ) ) 1305 throw packages::WrongPasswordException(); 1306 1307 // the correct key must be set already 1308 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); 1309 } 1310 else 1311 { 1312 SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); 1313 1314 try { 1315 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); 1316 1317 m_bUseCommonEncryption = sal_False; // very important to set it to false 1318 m_bHasCachedEncryptionData = sal_True; 1319 m_aEncryptionData = aEncryptionData; 1320 } 1321 catch( packages::WrongPasswordException& aWrongPasswordException ) 1322 { 1323 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); 1324 AddLog( aWrongPasswordException.Message ); 1325 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 1326 throw; 1327 } 1328 catch ( uno::Exception& aException ) 1329 { 1330 AddLog( aException.Message ); 1331 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 1332 1333 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" ); 1334 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); 1335 throw io::IOException(); // TODO: 1336 } 1337 } 1338 1339 OSL_ENSURE( xResultStream.is(), "In case stream can not be retrieved an exception must be thrown!\n" ); 1340 1341 return xResultStream; 1342 } 1343 1344 //----------------------------------------------- 1345 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess ) 1346 { 1347 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1348 1349 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 1350 1351 if ( m_pAntiImpl ) 1352 throw io::IOException(); // TODO: 1353 1354 uno::Reference< io::XStream > xResultStream; 1355 1356 if ( IsEncrypted() ) 1357 { 1358 ::comphelper::SequenceAsHashMap aGlobalEncryptionData; 1359 try 1360 { 1361 aGlobalEncryptionData = GetCommonRootEncryptionData(); 1362 } 1363 catch( packages::NoEncryptionException& aNoEncryptionException ) 1364 { 1365 AddLog( aNoEncryptionException.Message ); 1366 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 1367 1368 throw packages::WrongPasswordException(); 1369 } 1370 1371 xResultStream = GetStream( nStreamMode, aGlobalEncryptionData, bHierarchyAccess ); 1372 } 1373 else 1374 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); 1375 1376 return xResultStream; 1377 } 1378 1379 //----------------------------------------------- 1380 uno::Reference< io::XStream > OWriteStream_Impl::GetStream_Impl( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess ) 1381 { 1382 // private method, no mutex is used 1383 GetStreamProperties(); 1384 1385 // TODO/LATER: this info might be read later, on demand in future 1386 ReadRelInfoIfNecessary(); 1387 1388 if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::READ ) 1389 { 1390 uno::Reference< io::XInputStream > xInStream; 1391 if ( m_xCacheStream.is() || m_aTempURL.getLength() ) 1392 xInStream = GetTempFileAsInputStream(); //TODO: 1393 else 1394 xInStream = m_xPackageStream->getDataStream(); 1395 1396 // The stream does not exist in the storage 1397 if ( !xInStream.is() ) 1398 throw io::IOException(); 1399 1400 OInputCompStream* pStream = new OInputCompStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType ); 1401 uno::Reference< io::XStream > xCompStream( 1402 static_cast< ::cppu::OWeakObject* >( pStream ), 1403 uno::UNO_QUERY ); 1404 OSL_ENSURE( xCompStream.is(), 1405 "OInputCompStream MUST provide XStream interfaces!\n" ); 1406 1407 m_aInputStreamsList.push_back( pStream ); 1408 return xCompStream; 1409 } 1410 else if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::SEEKABLEREAD ) 1411 { 1412 if ( !m_xCacheStream.is() && !m_aTempURL.getLength() && !( m_xPackageStream->getDataStream().is() ) ) 1413 { 1414 // The stream does not exist in the storage 1415 throw io::IOException(); 1416 } 1417 1418 uno::Reference< io::XInputStream > xInStream; 1419 1420 xInStream = GetTempFileAsInputStream(); //TODO: 1421 1422 if ( !xInStream.is() ) 1423 throw io::IOException(); 1424 1425 OInputSeekStream* pStream = new OInputSeekStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType ); 1426 uno::Reference< io::XStream > xSeekStream( 1427 static_cast< ::cppu::OWeakObject* >( pStream ), 1428 uno::UNO_QUERY ); 1429 OSL_ENSURE( xSeekStream.is(), 1430 "OInputSeekStream MUST provide XStream interfaces!\n" ); 1431 1432 m_aInputStreamsList.push_back( pStream ); 1433 return xSeekStream; 1434 } 1435 else if ( ( nStreamMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE ) 1436 { 1437 if ( !m_aInputStreamsList.empty() ) 1438 throw io::IOException(); // TODO: 1439 1440 uno::Reference< io::XStream > xStream; 1441 if ( ( nStreamMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE ) 1442 { 1443 if ( m_aTempURL.getLength() ) 1444 { 1445 KillFile( m_aTempURL, GetServiceFactory() ); 1446 m_aTempURL = ::rtl::OUString(); 1447 } 1448 if ( m_xCacheStream.is() ) 1449 CleanCacheStream(); 1450 1451 m_bHasDataToFlush = sal_True; 1452 1453 // this call is triggered by the parent and it will recognize the change of the state 1454 if ( m_pParent ) 1455 m_pParent->m_bIsModified = sal_True; 1456 1457 xStream = CreateMemoryStream( GetServiceFactory() ); 1458 m_xCacheSeek.set( xStream, uno::UNO_QUERY_THROW ); 1459 m_xCacheStream = xStream; 1460 } 1461 else if ( !m_bHasInsertedStreamOptimization ) 1462 { 1463 if ( !m_aTempURL.getLength() && !m_xCacheStream.is() && !( m_xPackageStream->getDataStream().is() ) ) 1464 { 1465 // The stream does not exist in the storage 1466 m_bHasDataToFlush = sal_True; 1467 1468 // this call is triggered by the parent and it will recognize the change of the state 1469 if ( m_pParent ) 1470 m_pParent->m_bIsModified = sal_True; 1471 xStream = GetTempFileAsStream(); 1472 } 1473 1474 // if the stream exists the temporary file is created on demand 1475 // xStream = GetTempFileAsStream(); 1476 } 1477 1478 if ( !xStream.is() ) 1479 m_pAntiImpl = new OWriteStream( this, bHierarchyAccess ); 1480 else 1481 m_pAntiImpl = new OWriteStream( this, xStream, bHierarchyAccess ); 1482 1483 uno::Reference< io::XStream > xWriteStream = 1484 uno::Reference< io::XStream >( static_cast< ::cppu::OWeakObject* >( m_pAntiImpl ), 1485 uno::UNO_QUERY ); 1486 1487 OSL_ENSURE( xWriteStream.is(), "OWriteStream MUST implement XStream && XComponent interfaces!\n" ); 1488 1489 return xWriteStream; 1490 } 1491 1492 throw lang::IllegalArgumentException(); // TODO 1493 } 1494 1495 //----------------------------------------------- 1496 uno::Reference< io::XInputStream > OWriteStream_Impl::GetPlainRawInStream() 1497 { 1498 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1499 1500 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 1501 1502 // this method is used only internally, this stream object should not go outside of this implementation 1503 // if ( m_pAntiImpl ) 1504 // throw io::IOException(); // TODO: 1505 1506 return m_xPackageStream->getPlainRawStream(); 1507 } 1508 1509 //----------------------------------------------- 1510 uno::Reference< io::XInputStream > OWriteStream_Impl::GetRawInStream() 1511 { 1512 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1513 1514 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" ); 1515 1516 if ( m_pAntiImpl ) 1517 throw io::IOException(); // TODO: 1518 1519 OSL_ENSURE( IsEncrypted(), "Impossible to get raw representation for nonencrypted stream!\n" ); 1520 if ( !IsEncrypted() ) 1521 throw packages::NoEncryptionException(); 1522 1523 return m_xPackageStream->getRawStream(); 1524 } 1525 1526 //----------------------------------------------- 1527 ::comphelper::SequenceAsHashMap OWriteStream_Impl::GetCommonRootEncryptionData() 1528 throw ( packages::NoEncryptionException ) 1529 { 1530 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ; 1531 1532 if ( m_nStorageType != embed::StorageFormats::PACKAGE || !m_pParent ) 1533 throw packages::NoEncryptionException(); 1534 1535 return m_pParent->GetCommonRootEncryptionData(); 1536 } 1537 1538 //----------------------------------------------- 1539 void OWriteStream_Impl::InputStreamDisposed( OInputCompStream* pStream ) 1540 { 1541 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ); 1542 m_aInputStreamsList.remove( pStream ); 1543 } 1544 1545 //----------------------------------------------- 1546 void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( const uno::Reference< io::XInputStream >& xDataToCopy, const uno::Sequence< beans::PropertyValue >& aProps, sal_Bool, uno::Reference< io::XStream >& xTargetStream ) 1547 { 1548 uno::Reference < io::XStream > xTempFile; 1549 if ( !xTargetStream.is() ) 1550 xTempFile = uno::Reference < io::XStream >( 1551 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 1552 uno::UNO_QUERY ); 1553 else 1554 xTempFile = xTargetStream; 1555 1556 uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY ); 1557 if ( !xTempSeek.is() ) 1558 throw uno::RuntimeException(); // TODO 1559 1560 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream(); 1561 if ( !xTempOut.is() ) 1562 throw uno::RuntimeException(); 1563 1564 if ( xDataToCopy.is() ) 1565 ::comphelper::OStorageHelper::CopyInputToOutput( xDataToCopy, xTempOut ); 1566 1567 xTempOut->closeOutput(); 1568 xTempSeek->seek( 0 ); 1569 1570 uno::Reference< io::XInputStream > xInStream = xTempFile->getInputStream(); 1571 if ( !xInStream.is() ) 1572 throw io::IOException(); 1573 1574 // TODO: remember last state of m_bUseCommonEncryption 1575 if ( !xTargetStream.is() ) 1576 xTargetStream = uno::Reference< io::XStream > ( 1577 static_cast< ::cppu::OWeakObject* >( 1578 new OInputSeekStream( xInStream, InsertOwnProps( aProps, m_bUseCommonEncryption ), m_nStorageType ) ), 1579 uno::UNO_QUERY_THROW ); 1580 } 1581 1582 //----------------------------------------------- 1583 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream ) 1584 { 1585 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ); 1586 1587 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" ); 1588 if ( !m_xPackageStream.is() ) 1589 throw uno::RuntimeException(); 1590 1591 uno::Reference< io::XInputStream > xDataToCopy; 1592 if ( IsEncrypted() ) 1593 { 1594 // an encrypted stream must contain input stream 1595 ::comphelper::SequenceAsHashMap aGlobalEncryptionData; 1596 try 1597 { 1598 aGlobalEncryptionData = GetCommonRootEncryptionData(); 1599 } 1600 catch( packages::NoEncryptionException& aNoEncryptionException ) 1601 { 1602 AddLog( aNoEncryptionException.Message ); 1603 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) ); 1604 1605 throw packages::WrongPasswordException(); 1606 } 1607 1608 GetCopyOfLastCommit( xTargetStream, aGlobalEncryptionData ); 1609 } 1610 else 1611 { 1612 xDataToCopy = m_xPackageStream->getDataStream(); 1613 1614 // in case of new inserted package stream it is possible that input stream still was not set 1615 GetStreamProperties(); 1616 1617 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonEncryption, xTargetStream ); 1618 } 1619 } 1620 1621 //----------------------------------------------- 1622 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream, const ::comphelper::SequenceAsHashMap& aEncryptionData ) 1623 { 1624 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ); 1625 1626 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" ); 1627 if ( !m_xPackageStream.is() ) 1628 throw uno::RuntimeException(); 1629 1630 if ( !IsEncrypted() ) 1631 throw packages::NoEncryptionException(); 1632 1633 uno::Reference< io::XInputStream > xDataToCopy; 1634 1635 if ( m_bHasCachedEncryptionData ) 1636 { 1637 // TODO: introduce last commited cashed password information and use it here 1638 // that means "use common pass" also should be remembered on flash 1639 uno::Sequence< beans::NamedValue > aKey = aEncryptionData.getAsConstNamedValueList(); 1640 1641 uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY ); 1642 if ( !xProps.is() ) 1643 throw uno::RuntimeException(); 1644 1645 sal_Bool bEncr = sal_False; 1646 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ) ) >>= bEncr; 1647 if ( !bEncr ) 1648 throw packages::NoEncryptionException(); 1649 1650 uno::Sequence< beans::NamedValue > aPackKey; 1651 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) >>= aPackKey; 1652 if ( !SequencesEqual( aKey, aPackKey ) ) 1653 throw packages::WrongPasswordException(); 1654 1655 // the correct key must be set already 1656 xDataToCopy = m_xPackageStream->getDataStream(); 1657 } 1658 else 1659 { 1660 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY ); 1661 SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); 1662 1663 try { 1664 xDataToCopy = m_xPackageStream->getDataStream(); 1665 1666 if ( !xDataToCopy.is() ) 1667 { 1668 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" ); 1669 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); 1670 } 1671 } 1672 catch( uno::Exception& aException ) 1673 { 1674 OSL_ENSURE( sal_False, "Can't open encrypted stream!\n" ); 1675 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); 1676 AddLog( aException.Message ); 1677 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 1678 throw; 1679 } 1680 1681 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); 1682 } 1683 1684 // in case of new inserted package stream it is possible that input stream still was not set 1685 GetStreamProperties(); 1686 1687 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonEncryption, xTargetStream ); 1688 } 1689 1690 //----------------------------------------------- 1691 void OWriteStream_Impl::CommitStreamRelInfo( const uno::Reference< embed::XStorage >& xRelStorage, const ::rtl::OUString& aOrigStreamName, const ::rtl::OUString& aNewStreamName ) 1692 { 1693 // at this point of time the old stream must be already cleaned 1694 OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML, "The method should be used only with OFOPXML format!\n" ); 1695 1696 if ( m_nStorageType == embed::StorageFormats::OFOPXML ) 1697 { 1698 OSL_ENSURE( aOrigStreamName.getLength() && aNewStreamName.getLength() && xRelStorage.is(), 1699 "Wrong relation persistence information is provided!\n" ); 1700 1701 if ( !xRelStorage.is() || !aOrigStreamName.getLength() || !aNewStreamName.getLength() ) 1702 throw uno::RuntimeException(); 1703 1704 if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN ) 1705 throw io::IOException(); // TODO: 1706 1707 ::rtl::OUString aOrigRelStreamName = aOrigStreamName; 1708 aOrigRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) ); 1709 1710 ::rtl::OUString aNewRelStreamName = aNewStreamName; 1711 aNewRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) ); 1712 1713 sal_Bool bRenamed = !aOrigRelStreamName.equals( aNewRelStreamName ); 1714 if ( m_nRelInfoStatus == RELINFO_CHANGED 1715 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ 1716 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) 1717 { 1718 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) ) 1719 xRelStorage->removeElement( aOrigRelStreamName ); 1720 1721 if ( m_nRelInfoStatus == RELINFO_CHANGED ) 1722 { 1723 if ( m_aNewRelInfo.getLength() ) 1724 { 1725 uno::Reference< io::XStream > xRelsStream = 1726 xRelStorage->openStreamElement( aNewRelStreamName, 1727 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE ); 1728 1729 uno::Reference< io::XOutputStream > xOutStream = xRelsStream->getOutputStream(); 1730 if ( !xOutStream.is() ) 1731 throw uno::RuntimeException(); 1732 1733 ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence( xOutStream, m_aNewRelInfo, m_xFactory ); 1734 1735 // set the mediatype 1736 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW ); 1737 xPropSet->setPropertyValue( 1738 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), 1739 uno::makeAny( ::rtl::OUString( 1740 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) ); 1741 1742 m_nRelInfoStatus = RELINFO_READ; 1743 } 1744 } 1745 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ 1746 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) 1747 { 1748 uno::Reference< io::XStream > xRelsStream = 1749 xRelStorage->openStreamElement( aNewRelStreamName, 1750 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE ); 1751 1752 uno::Reference< io::XOutputStream > xOutputStream = xRelsStream->getOutputStream(); 1753 if ( !xOutputStream.is() ) 1754 throw uno::RuntimeException(); 1755 1756 uno::Reference< io::XSeekable > xSeek( m_xNewRelInfoStream, uno::UNO_QUERY_THROW ); 1757 xSeek->seek( 0 ); 1758 ::comphelper::OStorageHelper::CopyInputToOutput( m_xNewRelInfoStream, xOutputStream ); 1759 xSeek->seek( 0 ); 1760 1761 // set the mediatype 1762 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW ); 1763 xPropSet->setPropertyValue( 1764 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), 1765 uno::makeAny( ::rtl::OUString( 1766 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) ); 1767 1768 if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) 1769 m_nRelInfoStatus = RELINFO_NO_INIT; 1770 else 1771 { 1772 // the information is already parsed and the stream is stored, no need in temporary stream any more 1773 m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 1774 m_nRelInfoStatus = RELINFO_READ; 1775 } 1776 } 1777 1778 // the original stream makes no sence after this step 1779 m_xOrigRelInfoStream = m_xNewRelInfoStream; 1780 m_aOrigRelInfo = m_aNewRelInfo; 1781 m_bOrigRelInfoBroken = sal_False; 1782 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); 1783 m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 1784 } 1785 else 1786 { 1787 // the stream is not changed but it might be renamed 1788 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) ) 1789 xRelStorage->renameElement( aOrigRelStreamName, aNewRelStreamName ); 1790 } 1791 } 1792 } 1793 1794 //=============================================== 1795 // OWriteStream implementation 1796 //=============================================== 1797 1798 //----------------------------------------------- 1799 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, sal_Bool bTransacted ) 1800 : m_pImpl( pImpl ) 1801 , m_bInStreamDisconnected( sal_False ) 1802 , m_bInitOnDemand( sal_True ) 1803 , m_nInitPosition( 0 ) 1804 , m_bTransacted( bTransacted ) 1805 { 1806 OSL_ENSURE( pImpl, "No base implementation!\n" ); 1807 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" ); 1808 1809 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() ) 1810 throw uno::RuntimeException(); // just a disaster 1811 1812 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType ); 1813 } 1814 1815 //----------------------------------------------- 1816 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, uno::Reference< io::XStream > xStream, sal_Bool bTransacted ) 1817 : m_pImpl( pImpl ) 1818 , m_bInStreamDisconnected( sal_False ) 1819 , m_bInitOnDemand( sal_False ) 1820 , m_nInitPosition( 0 ) 1821 , m_bTransacted( bTransacted ) 1822 { 1823 OSL_ENSURE( pImpl && xStream.is(), "No base implementation!\n" ); 1824 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" ); 1825 1826 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() ) 1827 throw uno::RuntimeException(); // just a disaster 1828 1829 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType ); 1830 1831 if ( xStream.is() ) 1832 { 1833 m_xInStream = xStream->getInputStream(); 1834 m_xOutStream = xStream->getOutputStream(); 1835 m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY ); 1836 OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!\n" ); 1837 } 1838 } 1839 1840 //----------------------------------------------- 1841 OWriteStream::~OWriteStream() 1842 { 1843 { 1844 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 1845 if ( m_pImpl ) 1846 { 1847 m_refCount++; 1848 try { 1849 dispose(); 1850 } 1851 catch( uno::RuntimeException& aRuntimeException ) 1852 { 1853 m_pImpl->AddLog( aRuntimeException.Message ); 1854 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 1855 } 1856 } 1857 } 1858 1859 if ( m_pData && m_pData->m_pTypeCollection ) 1860 delete m_pData->m_pTypeCollection; 1861 1862 if ( m_pData ) 1863 delete m_pData; 1864 } 1865 1866 //----------------------------------------------- 1867 void OWriteStream::DeInit() 1868 { 1869 if ( !m_pImpl ) 1870 return; // do nothing 1871 1872 if ( m_xSeekable.is() ) 1873 m_nInitPosition = m_xSeekable->getPosition(); 1874 1875 m_xInStream = uno::Reference< io::XInputStream >(); 1876 m_xOutStream = uno::Reference< io::XOutputStream >(); 1877 m_xSeekable = uno::Reference< io::XSeekable >(); 1878 m_bInitOnDemand = sal_True; 1879 } 1880 1881 //----------------------------------------------- 1882 void OWriteStream::CheckInitOnDemand() 1883 { 1884 if ( !m_pImpl ) 1885 { 1886 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 1887 throw lang::DisposedException(); 1888 } 1889 1890 if ( m_bInitOnDemand ) 1891 { 1892 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" ); 1893 uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream(); 1894 if ( xStream.is() ) 1895 { 1896 m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW ); 1897 m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW ); 1898 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW ); 1899 m_xSeekable->seek( m_nInitPosition ); 1900 1901 m_nInitPosition = 0; 1902 m_bInitOnDemand = sal_False; 1903 } 1904 } 1905 } 1906 1907 //----------------------------------------------- 1908 void OWriteStream::CopyToStreamInternally_Impl( const uno::Reference< io::XStream >& xDest ) 1909 { 1910 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 1911 1912 CheckInitOnDemand(); 1913 1914 if ( !m_xInStream.is() ) 1915 throw uno::RuntimeException(); 1916 1917 if ( !m_xSeekable.is() ) 1918 throw uno::RuntimeException(); 1919 1920 uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY ); 1921 if ( !xDestProps.is() ) 1922 throw uno::RuntimeException(); //TODO 1923 1924 uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream(); 1925 if ( !xDestOutStream.is() ) 1926 throw io::IOException(); // TODO 1927 1928 sal_Int64 nCurPos = m_xSeekable->getPosition(); 1929 m_xSeekable->seek( 0 ); 1930 1931 uno::Exception eThrown; 1932 sal_Bool bThrown = sal_False; 1933 try { 1934 ::comphelper::OStorageHelper::CopyInputToOutput( m_xInStream, xDestOutStream ); 1935 } 1936 catch ( uno::Exception& e ) 1937 { 1938 eThrown = e; 1939 bThrown = sal_True; 1940 } 1941 1942 // position-related section below is critical 1943 // if it fails the stream will become invalid 1944 try { 1945 m_xSeekable->seek( nCurPos ); 1946 } 1947 catch ( uno::Exception& aException ) 1948 { 1949 m_pImpl->AddLog( aException.Message ); 1950 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) ); 1951 1952 // TODO: set the stoream in invalid state or dispose 1953 OSL_ENSURE( sal_False, "The stream become invalid during copiing!\n" ); 1954 throw uno::RuntimeException(); 1955 } 1956 1957 if ( bThrown ) 1958 throw eThrown; 1959 1960 // now the properties can be copied 1961 // the order of the properties setting is not important for StorageStream API 1962 ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "Compressed" ); 1963 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); 1964 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE || m_pData->m_nStorageType == embed::StorageFormats::OFOPXML ) 1965 { 1966 aPropName = ::rtl::OUString::createFromAscii( "MediaType" ); 1967 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); 1968 1969 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE ) 1970 { 1971 aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" ); 1972 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); 1973 } 1974 } 1975 } 1976 1977 //----------------------------------------------- 1978 void OWriteStream::ModifyParentUnlockMutex_Impl( ::osl::ResettableMutexGuard& aGuard ) 1979 { 1980 if ( m_pImpl->m_pParent ) 1981 { 1982 if ( m_pImpl->m_pParent->m_pAntiImpl ) 1983 { 1984 uno::Reference< util::XModifiable > xParentModif( (util::XModifiable*)(m_pImpl->m_pParent->m_pAntiImpl) ); 1985 aGuard.clear(); 1986 xParentModif->setModified( sal_True ); 1987 } 1988 else 1989 m_pImpl->m_pParent->m_bIsModified = sal_True; 1990 } 1991 } 1992 1993 //----------------------------------------------- 1994 uno::Any SAL_CALL OWriteStream::queryInterface( const uno::Type& rType ) 1995 throw( uno::RuntimeException ) 1996 { 1997 uno::Any aReturn; 1998 1999 // common interfaces 2000 aReturn <<= ::cppu::queryInterface 2001 ( rType 2002 , static_cast<lang::XTypeProvider*> ( this ) 2003 , static_cast<io::XInputStream*> ( this ) 2004 , static_cast<io::XOutputStream*> ( this ) 2005 , static_cast<io::XStream*> ( this ) 2006 , static_cast<embed::XExtendedStorageStream*> ( this ) 2007 , static_cast<io::XSeekable*> ( this ) 2008 , static_cast<io::XTruncate*> ( this ) 2009 , static_cast<lang::XComponent*> ( this ) 2010 , static_cast<beans::XPropertySet*> ( this ) ); 2011 2012 if ( aReturn.hasValue() == sal_True ) 2013 return aReturn ; 2014 2015 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE ) 2016 { 2017 aReturn <<= ::cppu::queryInterface 2018 ( rType 2019 , static_cast<embed::XEncryptionProtectedSource2*> ( this ) 2020 , static_cast<embed::XEncryptionProtectedSource*> ( this ) ); 2021 } 2022 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML ) 2023 { 2024 aReturn <<= ::cppu::queryInterface 2025 ( rType 2026 , static_cast<embed::XRelationshipAccess*> ( this ) ); 2027 } 2028 2029 if ( aReturn.hasValue() == sal_True ) 2030 return aReturn ; 2031 2032 if ( m_bTransacted ) 2033 { 2034 aReturn <<= ::cppu::queryInterface 2035 ( rType 2036 , static_cast<embed::XTransactedObject*> ( this ) 2037 , static_cast<embed::XTransactionBroadcaster*> ( this ) ); 2038 2039 if ( aReturn.hasValue() == sal_True ) 2040 return aReturn ; 2041 } 2042 2043 return OWeakObject::queryInterface( rType ); 2044 } 2045 2046 //----------------------------------------------- 2047 void SAL_CALL OWriteStream::acquire() throw() 2048 { 2049 OWeakObject::acquire(); 2050 } 2051 2052 //----------------------------------------------- 2053 void SAL_CALL OWriteStream::release() throw() 2054 { 2055 OWeakObject::release(); 2056 } 2057 2058 //----------------------------------------------- 2059 uno::Sequence< uno::Type > SAL_CALL OWriteStream::getTypes() 2060 throw( uno::RuntimeException ) 2061 { 2062 if ( m_pData->m_pTypeCollection == NULL ) 2063 { 2064 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2065 2066 if ( m_pData->m_pTypeCollection == NULL ) 2067 { 2068 if ( m_bTransacted ) 2069 { 2070 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE ) 2071 { 2072 ::cppu::OTypeCollection aTmpCollection 2073 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2074 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2075 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2076 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2077 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2078 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2079 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2080 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource2 >* )NULL ) 2081 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL ) 2082 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL ) 2083 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL ) 2084 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL ) ); 2085 2086 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2087 ( ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) 2088 , aTmpCollection.getTypes() ); 2089 } 2090 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML ) 2091 { 2092 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2093 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2094 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2095 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2096 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2097 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2098 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2099 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2100 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL ) 2101 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL ) 2102 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL ) 2103 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL ) 2104 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); 2105 } 2106 else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP ) 2107 { 2108 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2109 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2110 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2111 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2112 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2113 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2114 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2115 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2116 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL ) 2117 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL ) 2118 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL ) 2119 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); 2120 } 2121 } 2122 else 2123 { 2124 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE ) 2125 { 2126 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2127 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2128 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2129 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2130 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2131 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2132 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2133 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2134 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource2 >* )NULL ) 2135 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL ) 2136 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); 2137 } 2138 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML ) 2139 { 2140 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2141 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2142 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2143 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2144 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2145 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2146 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2147 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2148 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL ) 2149 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); 2150 } 2151 else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP ) 2152 { 2153 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection 2154 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL ) 2155 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL ) 2156 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL ) 2157 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL ) 2158 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL ) 2159 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL ) 2160 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL ) 2161 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) ); 2162 } 2163 } 2164 } 2165 } 2166 2167 return m_pData->m_pTypeCollection->getTypes() ; 2168 } 2169 2170 namespace { struct lcl_ImplId : public rtl::Static< ::cppu::OImplementationId, lcl_ImplId > {}; } 2171 2172 //----------------------------------------------- 2173 uno::Sequence< sal_Int8 > SAL_CALL OWriteStream::getImplementationId() 2174 throw( uno::RuntimeException ) 2175 { 2176 ::cppu::OImplementationId &rId = lcl_ImplId::get(); 2177 return rId.getImplementationId(); 2178 } 2179 2180 //----------------------------------------------- 2181 sal_Int32 SAL_CALL OWriteStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) 2182 throw ( io::NotConnectedException, 2183 io::BufferSizeExceededException, 2184 io::IOException, 2185 uno::RuntimeException ) 2186 { 2187 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2188 2189 CheckInitOnDemand(); 2190 2191 if ( !m_pImpl ) 2192 { 2193 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2194 throw lang::DisposedException(); 2195 } 2196 2197 if ( !m_xInStream.is() ) 2198 throw io::NotConnectedException(); 2199 2200 return m_xInStream->readBytes( aData, nBytesToRead ); 2201 } 2202 2203 //----------------------------------------------- 2204 sal_Int32 SAL_CALL OWriteStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) 2205 throw ( io::NotConnectedException, 2206 io::BufferSizeExceededException, 2207 io::IOException, 2208 uno::RuntimeException ) 2209 { 2210 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2211 2212 CheckInitOnDemand(); 2213 2214 if ( !m_pImpl ) 2215 { 2216 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2217 throw lang::DisposedException(); 2218 } 2219 2220 if ( !m_xInStream.is() ) 2221 throw io::NotConnectedException(); 2222 2223 return m_xInStream->readSomeBytes( aData, nMaxBytesToRead ); 2224 } 2225 2226 //----------------------------------------------- 2227 void SAL_CALL OWriteStream::skipBytes( sal_Int32 nBytesToSkip ) 2228 throw ( io::NotConnectedException, 2229 io::BufferSizeExceededException, 2230 io::IOException, 2231 uno::RuntimeException ) 2232 { 2233 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2234 2235 CheckInitOnDemand(); 2236 2237 if ( !m_pImpl ) 2238 { 2239 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2240 throw lang::DisposedException(); 2241 } 2242 2243 if ( !m_xInStream.is() ) 2244 throw io::NotConnectedException(); 2245 2246 m_xInStream->skipBytes( nBytesToSkip ); 2247 } 2248 2249 //----------------------------------------------- 2250 sal_Int32 SAL_CALL OWriteStream::available( ) 2251 throw ( io::NotConnectedException, 2252 io::IOException, 2253 uno::RuntimeException ) 2254 { 2255 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2256 2257 CheckInitOnDemand(); 2258 2259 if ( !m_pImpl ) 2260 { 2261 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2262 throw lang::DisposedException(); 2263 } 2264 2265 if ( !m_xInStream.is() ) 2266 throw io::NotConnectedException(); 2267 2268 return m_xInStream->available(); 2269 2270 } 2271 2272 //----------------------------------------------- 2273 void SAL_CALL OWriteStream::closeInput( ) 2274 throw ( io::NotConnectedException, 2275 io::IOException, 2276 uno::RuntimeException ) 2277 { 2278 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2279 2280 if ( !m_pImpl ) 2281 { 2282 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2283 throw lang::DisposedException(); 2284 } 2285 2286 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) ) 2287 throw io::NotConnectedException(); 2288 2289 // the input part of the stream stays open for internal purposes ( to allow reading during copiing ) 2290 // since it can not be reopened until output part is closed, it will be closed with output part. 2291 m_bInStreamDisconnected = sal_True; 2292 // m_xInStream->closeInput(); 2293 // m_xInStream = uno::Reference< io::XInputStream >(); 2294 2295 if ( !m_xOutStream.is() ) 2296 dispose(); 2297 } 2298 2299 //----------------------------------------------- 2300 uno::Reference< io::XInputStream > SAL_CALL OWriteStream::getInputStream() 2301 throw ( uno::RuntimeException ) 2302 { 2303 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2304 2305 if ( !m_pImpl ) 2306 { 2307 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2308 throw lang::DisposedException(); 2309 } 2310 2311 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) ) 2312 return uno::Reference< io::XInputStream >(); 2313 2314 return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ), uno::UNO_QUERY ); 2315 } 2316 2317 //----------------------------------------------- 2318 uno::Reference< io::XOutputStream > SAL_CALL OWriteStream::getOutputStream() 2319 throw ( uno::RuntimeException ) 2320 { 2321 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2322 2323 CheckInitOnDemand(); 2324 2325 if ( !m_pImpl ) 2326 { 2327 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2328 throw lang::DisposedException(); 2329 } 2330 2331 if ( !m_xOutStream.is() ) 2332 return uno::Reference< io::XOutputStream >(); 2333 2334 return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ), uno::UNO_QUERY ); 2335 } 2336 2337 //----------------------------------------------- 2338 void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) 2339 throw ( io::NotConnectedException, 2340 io::BufferSizeExceededException, 2341 io::IOException, 2342 uno::RuntimeException ) 2343 { 2344 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2345 2346 // the write method makes initialization itself, since it depends from the aData length 2347 // NO CheckInitOnDemand()! 2348 2349 if ( !m_pImpl ) 2350 { 2351 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2352 throw lang::DisposedException(); 2353 } 2354 2355 if ( !m_bInitOnDemand ) 2356 { 2357 if ( !m_xOutStream.is() || !m_xSeekable.is()) 2358 throw io::NotConnectedException(); 2359 2360 if ( m_pImpl->m_xCacheStream.is() ) 2361 { 2362 // check whether the cache should be turned off 2363 sal_Int64 nPos = m_xSeekable->getPosition(); 2364 if ( nPos + aData.getLength() > MAX_STORCACHE_SIZE ) 2365 { 2366 // disconnect the cache and copy the data to the temporary file 2367 m_xSeekable->seek( 0 ); 2368 2369 // it is enough to copy the cached stream, the cache should already contain everything 2370 if ( m_pImpl->GetFilledTempFileIfNo( m_xInStream ).getLength() ) 2371 { 2372 DeInit(); 2373 // the last position is known and it is differs from the current stream position 2374 m_nInitPosition = nPos; 2375 } 2376 } 2377 } 2378 } 2379 2380 if ( m_bInitOnDemand ) 2381 { 2382 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" ); 2383 uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream(); 2384 if ( xStream.is() ) 2385 { 2386 m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW ); 2387 m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW ); 2388 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW ); 2389 m_xSeekable->seek( m_nInitPosition ); 2390 2391 m_nInitPosition = 0; 2392 m_bInitOnDemand = sal_False; 2393 } 2394 } 2395 2396 2397 if ( !m_xOutStream.is() ) 2398 throw io::NotConnectedException(); 2399 2400 m_xOutStream->writeBytes( aData ); 2401 m_pImpl->m_bHasDataToFlush = sal_True; 2402 2403 ModifyParentUnlockMutex_Impl( aGuard ); 2404 } 2405 2406 //----------------------------------------------- 2407 void SAL_CALL OWriteStream::flush() 2408 throw ( io::NotConnectedException, 2409 io::BufferSizeExceededException, 2410 io::IOException, 2411 uno::RuntimeException ) 2412 { 2413 // In case stream is flushed it's current version becomes visible 2414 // to the parent storage. Usually parent storage flushes the stream 2415 // during own commit but a user can explicitly flush the stream 2416 // so the changes will be available through cloning functionality. 2417 2418 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2419 2420 if ( !m_pImpl ) 2421 { 2422 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2423 throw lang::DisposedException(); 2424 } 2425 2426 if ( !m_bInitOnDemand ) 2427 { 2428 if ( !m_xOutStream.is() ) 2429 throw io::NotConnectedException(); 2430 2431 m_xOutStream->flush(); 2432 m_pImpl->Commit(); 2433 } 2434 } 2435 2436 //----------------------------------------------- 2437 void OWriteStream::CloseOutput_Impl() 2438 { 2439 // all the checks must be done in calling method 2440 2441 m_xOutStream->closeOutput(); 2442 m_xOutStream = uno::Reference< io::XOutputStream >(); 2443 2444 if ( !m_bInitOnDemand ) 2445 { 2446 // after the stream is disposed it can be commited 2447 // so transport correct size property 2448 if ( !m_xSeekable.is() ) 2449 throw uno::RuntimeException(); 2450 2451 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ ) 2452 { 2453 if ( m_pImpl->m_aProps[nInd].Name.equalsAscii( "Size" ) ) 2454 m_pImpl->m_aProps[nInd].Value <<= ((sal_Int32)m_xSeekable->getLength()); 2455 } 2456 } 2457 } 2458 2459 //----------------------------------------------- 2460 void SAL_CALL OWriteStream::closeOutput() 2461 throw ( io::NotConnectedException, 2462 io::BufferSizeExceededException, 2463 io::IOException, 2464 uno::RuntimeException ) 2465 { 2466 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2467 2468 CheckInitOnDemand(); 2469 2470 if ( !m_pImpl ) 2471 { 2472 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2473 throw lang::DisposedException(); 2474 } 2475 2476 if ( !m_xOutStream.is() ) 2477 throw io::NotConnectedException(); 2478 2479 CloseOutput_Impl(); 2480 2481 if ( m_bInStreamDisconnected || !m_xInStream.is() ) 2482 dispose(); 2483 } 2484 2485 //----------------------------------------------- 2486 void SAL_CALL OWriteStream::seek( sal_Int64 location ) 2487 throw ( lang::IllegalArgumentException, 2488 io::IOException, 2489 uno::RuntimeException ) 2490 { 2491 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2492 2493 CheckInitOnDemand(); 2494 2495 if ( !m_pImpl ) 2496 { 2497 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2498 throw lang::DisposedException(); 2499 } 2500 2501 if ( !m_xSeekable.is() ) 2502 throw uno::RuntimeException(); 2503 2504 m_xSeekable->seek( location ); 2505 } 2506 2507 //----------------------------------------------- 2508 sal_Int64 SAL_CALL OWriteStream::getPosition() 2509 throw ( io::IOException, 2510 uno::RuntimeException) 2511 { 2512 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2513 2514 CheckInitOnDemand(); 2515 2516 if ( !m_pImpl ) 2517 { 2518 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2519 throw lang::DisposedException(); 2520 } 2521 2522 if ( !m_xSeekable.is() ) 2523 throw uno::RuntimeException(); 2524 2525 return m_xSeekable->getPosition(); 2526 } 2527 2528 //----------------------------------------------- 2529 sal_Int64 SAL_CALL OWriteStream::getLength() 2530 throw ( io::IOException, 2531 uno::RuntimeException ) 2532 { 2533 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2534 2535 CheckInitOnDemand(); 2536 2537 if ( !m_pImpl ) 2538 { 2539 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2540 throw lang::DisposedException(); 2541 } 2542 2543 if ( !m_xSeekable.is() ) 2544 throw uno::RuntimeException(); 2545 2546 return m_xSeekable->getLength(); 2547 } 2548 2549 //----------------------------------------------- 2550 void SAL_CALL OWriteStream::truncate() 2551 throw ( io::IOException, 2552 uno::RuntimeException ) 2553 { 2554 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2555 2556 CheckInitOnDemand(); 2557 2558 if ( !m_pImpl ) 2559 { 2560 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2561 throw lang::DisposedException(); 2562 } 2563 2564 if ( !m_xOutStream.is() ) 2565 throw uno::RuntimeException(); 2566 2567 uno::Reference< io::XTruncate > xTruncate( m_xOutStream, uno::UNO_QUERY ); 2568 2569 if ( !xTruncate.is() ) 2570 { 2571 OSL_ENSURE( sal_False, "The output stream must support XTruncate interface!\n" ); 2572 throw uno::RuntimeException(); 2573 } 2574 2575 xTruncate->truncate(); 2576 2577 m_pImpl->m_bHasDataToFlush = sal_True; 2578 2579 ModifyParentUnlockMutex_Impl( aGuard ); 2580 } 2581 2582 //----------------------------------------------- 2583 void SAL_CALL OWriteStream::dispose() 2584 throw ( uno::RuntimeException ) 2585 { 2586 // should be an internal method since it can be called only from parent storage 2587 { 2588 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2589 2590 if ( !m_pImpl ) 2591 { 2592 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2593 throw lang::DisposedException(); 2594 } 2595 2596 if ( m_xOutStream.is() ) 2597 CloseOutput_Impl(); 2598 2599 if ( m_xInStream.is() ) 2600 { 2601 m_xInStream->closeInput(); 2602 m_xInStream = uno::Reference< io::XInputStream >(); 2603 } 2604 2605 m_xSeekable = uno::Reference< io::XSeekable >(); 2606 2607 m_pImpl->m_pAntiImpl = NULL; 2608 2609 if ( !m_bInitOnDemand ) 2610 { 2611 try 2612 { 2613 if ( !m_bTransacted ) 2614 { 2615 m_pImpl->Commit(); 2616 } 2617 else 2618 { 2619 // throw away all the changes 2620 m_pImpl->Revert(); 2621 } 2622 } 2623 catch( uno::Exception& aException ) 2624 { 2625 m_pImpl->AddLog( aException.Message ); 2626 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 2627 2628 uno::Any aCaught( ::cppu::getCaughtException() ); 2629 throw lang::WrappedTargetRuntimeException( 2630 ::rtl::OUString::createFromAscii( "Can not commit/revert the storage!\n" ), 2631 uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( this ), 2632 uno::UNO_QUERY ), 2633 aCaught ); 2634 } 2635 } 2636 2637 m_pImpl = NULL; 2638 } 2639 2640 // the listener might try to get rid of parent storage, and the storage would delete this object; 2641 // for now the listener is just notified at the end of the method to workaround the problem 2642 // in future a more elegant way should be found 2643 2644 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); 2645 m_pData->m_aListenersContainer.disposeAndClear( aSource ); 2646 } 2647 2648 //----------------------------------------------- 2649 void SAL_CALL OWriteStream::addEventListener( 2650 const uno::Reference< lang::XEventListener >& xListener ) 2651 throw ( uno::RuntimeException ) 2652 { 2653 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2654 2655 if ( !m_pImpl ) 2656 { 2657 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2658 throw lang::DisposedException(); 2659 } 2660 2661 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), 2662 xListener ); 2663 } 2664 2665 //----------------------------------------------- 2666 void SAL_CALL OWriteStream::removeEventListener( 2667 const uno::Reference< lang::XEventListener >& xListener ) 2668 throw ( uno::RuntimeException ) 2669 { 2670 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2671 2672 if ( !m_pImpl ) 2673 { 2674 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2675 throw lang::DisposedException(); 2676 } 2677 2678 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), 2679 xListener ); 2680 } 2681 2682 //----------------------------------------------- 2683 void SAL_CALL OWriteStream::setEncryptionPassword( const ::rtl::OUString& aPass ) 2684 throw ( uno::RuntimeException, 2685 io::IOException ) 2686 { 2687 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2688 2689 CheckInitOnDemand(); 2690 2691 if ( !m_pImpl ) 2692 { 2693 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2694 throw lang::DisposedException(); 2695 } 2696 2697 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" ); 2698 2699 m_pImpl->SetEncrypted( ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) ); 2700 2701 ModifyParentUnlockMutex_Impl( aGuard ); 2702 } 2703 2704 //----------------------------------------------- 2705 void SAL_CALL OWriteStream::removeEncryption() 2706 throw ( uno::RuntimeException, 2707 io::IOException ) 2708 { 2709 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2710 2711 CheckInitOnDemand(); 2712 2713 if ( !m_pImpl ) 2714 { 2715 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2716 throw lang::DisposedException(); 2717 } 2718 2719 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" ); 2720 2721 m_pImpl->SetDecrypted(); 2722 2723 ModifyParentUnlockMutex_Impl( aGuard ); 2724 } 2725 2726 //----------------------------------------------- 2727 void SAL_CALL OWriteStream::setEncryptionData( const uno::Sequence< beans::NamedValue >& aEncryptionData ) 2728 throw (io::IOException, uno::RuntimeException) 2729 { 2730 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2731 2732 CheckInitOnDemand(); 2733 2734 if ( !m_pImpl ) 2735 { 2736 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2737 throw lang::DisposedException(); 2738 } 2739 2740 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" ); 2741 2742 m_pImpl->SetEncrypted( aEncryptionData ); 2743 2744 ModifyParentUnlockMutex_Impl( aGuard ); 2745 } 2746 2747 //----------------------------------------------- 2748 sal_Bool SAL_CALL OWriteStream::hasByID( const ::rtl::OUString& sID ) 2749 throw ( io::IOException, 2750 uno::RuntimeException ) 2751 { 2752 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2753 2754 if ( !m_pImpl ) 2755 { 2756 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2757 throw lang::DisposedException(); 2758 } 2759 2760 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2761 throw uno::RuntimeException(); 2762 2763 try 2764 { 2765 getRelationshipByID( sID ); 2766 return sal_True; 2767 } 2768 catch( container::NoSuchElementException& aNoSuchElementException ) 2769 { 2770 m_pImpl->AddLog( aNoSuchElementException.Message ); 2771 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) ); 2772 } 2773 2774 return sal_False; 2775 } 2776 2777 //----------------------------------------------- 2778 ::rtl::OUString SAL_CALL OWriteStream::getTargetByID( const ::rtl::OUString& sID ) 2779 throw ( container::NoSuchElementException, 2780 io::IOException, 2781 uno::RuntimeException ) 2782 { 2783 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2784 2785 if ( !m_pImpl ) 2786 { 2787 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2788 throw lang::DisposedException(); 2789 } 2790 2791 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2792 throw uno::RuntimeException(); 2793 2794 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID ); 2795 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 2796 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Target" ) ) ) 2797 return aSeq[nInd].Second; 2798 2799 return ::rtl::OUString(); 2800 } 2801 2802 //----------------------------------------------- 2803 ::rtl::OUString SAL_CALL OWriteStream::getTypeByID( const ::rtl::OUString& sID ) 2804 throw ( container::NoSuchElementException, 2805 io::IOException, 2806 uno::RuntimeException ) 2807 { 2808 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2809 2810 if ( !m_pImpl ) 2811 { 2812 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2813 throw lang::DisposedException(); 2814 } 2815 2816 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2817 throw uno::RuntimeException(); 2818 2819 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID ); 2820 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 2821 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) ) 2822 return aSeq[nInd].Second; 2823 2824 return ::rtl::OUString(); 2825 } 2826 2827 //----------------------------------------------- 2828 uno::Sequence< beans::StringPair > SAL_CALL OWriteStream::getRelationshipByID( const ::rtl::OUString& sID ) 2829 throw ( container::NoSuchElementException, 2830 io::IOException, 2831 uno::RuntimeException ) 2832 { 2833 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2834 2835 if ( !m_pImpl ) 2836 { 2837 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2838 throw lang::DisposedException(); 2839 } 2840 2841 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2842 throw uno::RuntimeException(); 2843 2844 // TODO/LATER: in future the unification of the ID could be checked 2845 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); 2846 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ ) 2847 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ ) 2848 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) ) 2849 { 2850 if ( aSeq[nInd1][nInd2].Second.equals( sID ) ) 2851 return aSeq[nInd1]; 2852 break; 2853 } 2854 2855 throw container::NoSuchElementException(); 2856 } 2857 2858 //----------------------------------------------- 2859 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getRelationshipsByType( const ::rtl::OUString& sType ) 2860 throw ( io::IOException, 2861 uno::RuntimeException ) 2862 { 2863 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2864 2865 if ( !m_pImpl ) 2866 { 2867 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2868 throw lang::DisposedException(); 2869 } 2870 2871 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2872 throw uno::RuntimeException(); 2873 2874 uno::Sequence< uno::Sequence< beans::StringPair > > aResult; 2875 sal_Int32 nEntriesNum = 0; 2876 2877 // TODO/LATER: in future the unification of the ID could be checked 2878 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); 2879 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ ) 2880 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ ) 2881 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) ) 2882 { 2883 if ( aSeq[nInd1][nInd2].Second.equals( sType ) ) 2884 { 2885 aResult.realloc( nEntriesNum ); 2886 aResult[nEntriesNum-1] = aSeq[nInd1]; 2887 } 2888 break; 2889 } 2890 2891 return aResult; 2892 } 2893 2894 //----------------------------------------------- 2895 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getAllRelationships() 2896 throw (io::IOException, uno::RuntimeException) 2897 { 2898 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2899 2900 if ( !m_pImpl ) 2901 { 2902 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2903 throw lang::DisposedException(); 2904 } 2905 2906 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2907 throw uno::RuntimeException(); 2908 2909 return m_pImpl->GetAllRelationshipsIfAny(); 2910 } 2911 2912 //----------------------------------------------- 2913 void SAL_CALL OWriteStream::insertRelationshipByID( const ::rtl::OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, ::sal_Bool bReplace ) 2914 throw ( container::ElementExistException, 2915 io::IOException, 2916 uno::RuntimeException ) 2917 { 2918 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2919 2920 if ( !m_pImpl ) 2921 { 2922 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2923 throw lang::DisposedException(); 2924 } 2925 2926 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2927 throw uno::RuntimeException(); 2928 2929 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ); 2930 2931 sal_Int32 nIDInd = -1; 2932 2933 // TODO/LATER: in future the unification of the ID could be checked 2934 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); 2935 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ ) 2936 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ ) 2937 if ( aSeq[nInd1][nInd2].First.equals( aIDTag ) ) 2938 { 2939 if ( aSeq[nInd1][nInd2].Second.equals( sID ) ) 2940 nIDInd = nInd1; 2941 2942 break; 2943 } 2944 2945 if ( nIDInd == -1 || bReplace ) 2946 { 2947 if ( nIDInd == -1 ) 2948 { 2949 nIDInd = aSeq.getLength(); 2950 aSeq.realloc( nIDInd + 1 ); 2951 } 2952 2953 aSeq[nIDInd].realloc( aEntry.getLength() + 1 ); 2954 2955 aSeq[nIDInd][0].First = aIDTag; 2956 aSeq[nIDInd][0].Second = sID; 2957 sal_Int32 nIndTarget = 1; 2958 for ( sal_Int32 nIndOrig = 0; 2959 nIndOrig < aEntry.getLength(); 2960 nIndOrig++ ) 2961 { 2962 if ( !aEntry[nIndOrig].First.equals( aIDTag ) ) 2963 aSeq[nIDInd][nIndTarget++] = aEntry[nIndOrig]; 2964 } 2965 2966 aSeq[nIDInd].realloc( nIndTarget ); 2967 } 2968 else 2969 throw container::ElementExistException(); // TODO 2970 2971 2972 m_pImpl->m_aNewRelInfo = aSeq; 2973 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 2974 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; 2975 } 2976 2977 //----------------------------------------------- 2978 void SAL_CALL OWriteStream::removeRelationshipByID( const ::rtl::OUString& sID ) 2979 throw ( container::NoSuchElementException, 2980 io::IOException, 2981 uno::RuntimeException ) 2982 { 2983 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 2984 2985 if ( !m_pImpl ) 2986 { 2987 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 2988 throw lang::DisposedException(); 2989 } 2990 2991 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 2992 throw uno::RuntimeException(); 2993 2994 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); 2995 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ ) 2996 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ ) 2997 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) ) 2998 { 2999 if ( aSeq[nInd1][nInd2].Second.equals( sID ) ) 3000 { 3001 sal_Int32 nLength = aSeq.getLength(); 3002 aSeq[nInd1] = aSeq[nLength-1]; 3003 aSeq.realloc( nLength - 1 ); 3004 3005 m_pImpl->m_aNewRelInfo = aSeq; 3006 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 3007 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; 3008 3009 // TODO/LATER: in future the unification of the ID could be checked 3010 return; 3011 } 3012 3013 break; 3014 } 3015 3016 throw container::NoSuchElementException(); 3017 } 3018 3019 //----------------------------------------------- 3020 void SAL_CALL OWriteStream::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, ::sal_Bool bReplace ) 3021 throw ( container::ElementExistException, 3022 io::IOException, 3023 uno::RuntimeException ) 3024 { 3025 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3026 3027 if ( !m_pImpl ) 3028 { 3029 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3030 throw lang::DisposedException(); 3031 } 3032 3033 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 3034 throw uno::RuntimeException(); 3035 3036 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ); 3037 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); 3038 uno::Sequence< uno::Sequence< beans::StringPair > > aResultSeq( aSeq.getLength() + aEntries.getLength() ); 3039 sal_Int32 nResultInd = 0; 3040 3041 for ( sal_Int32 nIndTarget1 = 0; nIndTarget1 < aSeq.getLength(); nIndTarget1++ ) 3042 for ( sal_Int32 nIndTarget2 = 0; nIndTarget2 < aSeq[nIndTarget1].getLength(); nIndTarget2++ ) 3043 if ( aSeq[nIndTarget1][nIndTarget2].First.equals( aIDTag ) ) 3044 { 3045 sal_Int32 nIndSourceSame = -1; 3046 3047 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ ) 3048 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ ) 3049 { 3050 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) ) 3051 { 3052 if ( aEntries[nIndSource1][nIndSource2].Second.equals( aSeq[nIndTarget1][nIndTarget2].Second ) ) 3053 { 3054 if ( !bReplace ) 3055 throw container::ElementExistException(); 3056 3057 nIndSourceSame = nIndSource1; 3058 } 3059 3060 break; 3061 } 3062 } 3063 3064 if ( nIndSourceSame == -1 ) 3065 { 3066 // no such element in the provided sequence 3067 aResultSeq[nResultInd++] = aSeq[nIndTarget1]; 3068 } 3069 3070 break; 3071 } 3072 3073 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ ) 3074 { 3075 aResultSeq[nResultInd].realloc( aEntries[nIndSource1].getLength() ); 3076 sal_Bool bHasID = sal_False; 3077 sal_Int32 nResInd2 = 1; 3078 3079 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ ) 3080 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) ) 3081 { 3082 aResultSeq[nResultInd][0] = aEntries[nIndSource1][nIndSource2]; 3083 bHasID = sal_True; 3084 } 3085 else if ( nResInd2 < aResultSeq[nResultInd].getLength() ) 3086 aResultSeq[nResultInd][nResInd2++] = aEntries[nIndSource1][nIndSource2]; 3087 else 3088 throw io::IOException(); // TODO: illegal relation ( no ID ) 3089 3090 if ( !bHasID ) 3091 throw io::IOException(); // TODO: illegal relations 3092 3093 nResultInd++; 3094 } 3095 3096 aResultSeq.realloc( nResultInd ); 3097 m_pImpl->m_aNewRelInfo = aResultSeq; 3098 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 3099 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; 3100 } 3101 3102 //----------------------------------------------- 3103 void SAL_CALL OWriteStream::clearRelationships() 3104 throw ( io::IOException, 3105 uno::RuntimeException ) 3106 { 3107 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3108 3109 if ( !m_pImpl ) 3110 { 3111 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3112 throw lang::DisposedException(); 3113 } 3114 3115 if ( m_pData->m_nStorageType != embed::StorageFormats::OFOPXML ) 3116 throw uno::RuntimeException(); 3117 3118 m_pImpl->m_aNewRelInfo.realloc( 0 ); 3119 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >(); 3120 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; 3121 } 3122 3123 //----------------------------------------------- 3124 uno::Reference< beans::XPropertySetInfo > SAL_CALL OWriteStream::getPropertySetInfo() 3125 throw ( uno::RuntimeException ) 3126 { 3127 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3128 3129 //TODO: 3130 return uno::Reference< beans::XPropertySetInfo >(); 3131 } 3132 3133 //----------------------------------------------- 3134 void SAL_CALL OWriteStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue ) 3135 throw ( beans::UnknownPropertyException, 3136 beans::PropertyVetoException, 3137 lang::IllegalArgumentException, 3138 lang::WrappedTargetException, 3139 uno::RuntimeException ) 3140 { 3141 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3142 3143 if ( !m_pImpl ) 3144 { 3145 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3146 throw lang::DisposedException(); 3147 } 3148 3149 m_pImpl->GetStreamProperties(); 3150 ::rtl::OUString aCompressedString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ); 3151 ::rtl::OUString aMediaTypeString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ); 3152 if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName.equals( aMediaTypeString ) ) 3153 { 3154 // if the "Compressed" property is not set explicitly, the MediaType can change the default value 3155 sal_Bool bCompressedValueFromType = sal_True; 3156 ::rtl::OUString aType; 3157 aValue >>= aType; 3158 3159 if ( !m_pImpl->m_bCompressedSetExplicit ) 3160 { 3161 if ( aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/jpeg" ) ) ) 3162 || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/png" ) ) ) 3163 || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/gif" ) ) ) ) 3164 bCompressedValueFromType = sal_False; 3165 } 3166 3167 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ ) 3168 { 3169 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) ) 3170 m_pImpl->m_aProps[nInd].Value = aValue; 3171 else if ( !m_pImpl->m_bCompressedSetExplicit && aCompressedString.equals( m_pImpl->m_aProps[nInd].Name ) ) 3172 m_pImpl->m_aProps[nInd].Value <<= bCompressedValueFromType; 3173 } 3174 } 3175 else if ( aPropertyName.equals( aCompressedString ) ) 3176 { 3177 // if the "Compressed" property is not set explicitly, the MediaType can change the default value 3178 m_pImpl->m_bCompressedSetExplicit = sal_True; 3179 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ ) 3180 { 3181 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) ) 3182 m_pImpl->m_aProps[nInd].Value = aValue; 3183 } 3184 } 3185 else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE 3186 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) ) 3187 { 3188 sal_Bool bUseCommonEncryption = sal_False; 3189 if ( aValue >>= bUseCommonEncryption ) 3190 { 3191 if ( m_bInitOnDemand && m_pImpl->m_bHasInsertedStreamOptimization ) 3192 { 3193 // the data stream is provided to the packagestream directly 3194 m_pImpl->m_bUseCommonEncryption = bUseCommonEncryption; 3195 } 3196 else if ( bUseCommonEncryption ) 3197 { 3198 if ( !m_pImpl->m_bUseCommonEncryption ) 3199 { 3200 m_pImpl->SetDecrypted(); 3201 m_pImpl->m_bUseCommonEncryption = sal_True; 3202 } 3203 } 3204 else 3205 m_pImpl->m_bUseCommonEncryption = sal_False; 3206 } 3207 else 3208 throw lang::IllegalArgumentException(); //TODO 3209 } 3210 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equals( aMediaTypeString ) ) 3211 { 3212 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ ) 3213 { 3214 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) ) 3215 m_pImpl->m_aProps[nInd].Value = aValue; 3216 } 3217 } 3218 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equalsAscii( "RelationsInfoStream" ) ) 3219 { 3220 uno::Reference< io::XInputStream > xInRelStream; 3221 if ( ( aValue >>= xInRelStream ) && xInRelStream.is() ) 3222 { 3223 uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY ); 3224 if ( !xSeek.is() ) 3225 { 3226 // currently this is an internal property that is used for optimization 3227 // and the stream must support XSeekable interface 3228 // TODO/LATER: in future it can be changed if property is used from outside 3229 throw lang::IllegalArgumentException(); // TODO 3230 } 3231 3232 m_pImpl->m_xNewRelInfoStream = xInRelStream; 3233 m_pImpl->m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); 3234 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM; 3235 } 3236 else 3237 throw lang::IllegalArgumentException(); // TODO 3238 } 3239 else if ( m_pData->m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName.equalsAscii( "RelationsInfo" ) ) 3240 { 3241 if ( aValue >>= m_pImpl->m_aNewRelInfo ) 3242 { 3243 } 3244 else 3245 throw lang::IllegalArgumentException(); // TODO 3246 } 3247 else if ( aPropertyName.equalsAscii( "Size" ) ) 3248 throw beans::PropertyVetoException(); // TODO 3249 else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE 3250 && ( aPropertyName.equalsAscii( "IsEncrypted" ) || aPropertyName.equalsAscii( "Encrypted" ) ) ) 3251 throw beans::PropertyVetoException(); // TODO 3252 else 3253 throw beans::UnknownPropertyException(); // TODO 3254 3255 m_pImpl->m_bHasDataToFlush = sal_True; 3256 ModifyParentUnlockMutex_Impl( aGuard ); 3257 } 3258 3259 3260 //----------------------------------------------- 3261 uno::Any SAL_CALL OWriteStream::getPropertyValue( const ::rtl::OUString& aProp ) 3262 throw ( beans::UnknownPropertyException, 3263 lang::WrappedTargetException, 3264 uno::RuntimeException ) 3265 { 3266 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3267 3268 if ( !m_pImpl ) 3269 { 3270 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3271 throw lang::DisposedException(); 3272 } 3273 3274 if ( aProp.equalsAscii( "RelId" ) ) 3275 { 3276 return uno::makeAny( m_pImpl->GetNewRelId() ); 3277 } 3278 3279 ::rtl::OUString aPropertyName; 3280 if ( aProp.equalsAscii( "IsEncrypted" ) ) 3281 aPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ); 3282 else 3283 aPropertyName = aProp; 3284 3285 if ( ( ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE || m_pData->m_nStorageType == embed::StorageFormats::OFOPXML ) 3286 && aPropertyName.equalsAscii( "MediaType" ) ) 3287 || ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName.equalsAscii( "Encrypted" ) ) 3288 || aPropertyName.equalsAscii( "Compressed" ) ) 3289 { 3290 m_pImpl->GetStreamProperties(); 3291 3292 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ ) 3293 { 3294 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) ) 3295 return m_pImpl->m_aProps[nInd].Value; 3296 } 3297 } 3298 else if ( m_pData->m_nStorageType == embed::StorageFormats::PACKAGE 3299 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) ) 3300 return uno::makeAny( m_pImpl->m_bUseCommonEncryption ); 3301 else if ( aPropertyName.equalsAscii( "Size" ) ) 3302 { 3303 CheckInitOnDemand(); 3304 3305 if ( !m_xSeekable.is() ) 3306 throw uno::RuntimeException(); 3307 3308 return uno::makeAny( (sal_Int32)m_xSeekable->getLength() ); 3309 } 3310 3311 throw beans::UnknownPropertyException(); // TODO 3312 } 3313 3314 3315 //----------------------------------------------- 3316 void SAL_CALL OWriteStream::addPropertyChangeListener( 3317 const ::rtl::OUString& /*aPropertyName*/, 3318 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ ) 3319 throw ( beans::UnknownPropertyException, 3320 lang::WrappedTargetException, 3321 uno::RuntimeException ) 3322 { 3323 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3324 3325 if ( !m_pImpl ) 3326 { 3327 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3328 throw lang::DisposedException(); 3329 } 3330 3331 //TODO: 3332 } 3333 3334 3335 //----------------------------------------------- 3336 void SAL_CALL OWriteStream::removePropertyChangeListener( 3337 const ::rtl::OUString& /*aPropertyName*/, 3338 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ ) 3339 throw ( beans::UnknownPropertyException, 3340 lang::WrappedTargetException, 3341 uno::RuntimeException ) 3342 { 3343 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3344 3345 if ( !m_pImpl ) 3346 { 3347 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3348 throw lang::DisposedException(); 3349 } 3350 3351 //TODO: 3352 } 3353 3354 3355 //----------------------------------------------- 3356 void SAL_CALL OWriteStream::addVetoableChangeListener( 3357 const ::rtl::OUString& /*PropertyName*/, 3358 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) 3359 throw ( beans::UnknownPropertyException, 3360 lang::WrappedTargetException, 3361 uno::RuntimeException ) 3362 { 3363 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3364 3365 if ( !m_pImpl ) 3366 { 3367 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3368 throw lang::DisposedException(); 3369 } 3370 3371 //TODO: 3372 } 3373 3374 3375 //----------------------------------------------- 3376 void SAL_CALL OWriteStream::removeVetoableChangeListener( 3377 const ::rtl::OUString& /*PropertyName*/, 3378 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) 3379 throw ( beans::UnknownPropertyException, 3380 lang::WrappedTargetException, 3381 uno::RuntimeException ) 3382 { 3383 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3384 3385 if ( !m_pImpl ) 3386 { 3387 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3388 throw lang::DisposedException(); 3389 } 3390 3391 //TODO: 3392 } 3393 3394 //____________________________________________________________________________________________________ 3395 // XTransactedObject 3396 //____________________________________________________________________________________________________ 3397 3398 //----------------------------------------------- 3399 void OWriteStream::BroadcastTransaction( sal_Int8 nMessage ) 3400 /* 3401 1 - preCommit 3402 2 - commited 3403 3 - preRevert 3404 4 - reverted 3405 */ 3406 { 3407 // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed 3408 if ( !m_pImpl ) 3409 { 3410 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3411 throw lang::DisposedException(); 3412 } 3413 3414 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); 3415 3416 ::cppu::OInterfaceContainerHelper* pContainer = 3417 m_pData->m_aListenersContainer.getContainer( 3418 ::getCppuType( ( const uno::Reference< embed::XTransactionListener >*) NULL ) ); 3419 if ( pContainer ) 3420 { 3421 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer ); 3422 while ( pIterator.hasMoreElements( ) ) 3423 { 3424 OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!\n" ); 3425 3426 switch( nMessage ) 3427 { 3428 case STOR_MESS_PRECOMMIT: 3429 ( ( embed::XTransactionListener* )pIterator.next( ) )->preCommit( aSource ); 3430 break; 3431 case STOR_MESS_COMMITED: 3432 ( ( embed::XTransactionListener* )pIterator.next( ) )->commited( aSource ); 3433 break; 3434 case STOR_MESS_PREREVERT: 3435 ( ( embed::XTransactionListener* )pIterator.next( ) )->preRevert( aSource ); 3436 break; 3437 case STOR_MESS_REVERTED: 3438 ( ( embed::XTransactionListener* )pIterator.next( ) )->reverted( aSource ); 3439 break; 3440 } 3441 } 3442 } 3443 } 3444 //----------------------------------------------- 3445 void SAL_CALL OWriteStream::commit() 3446 throw ( io::IOException, 3447 embed::StorageWrappedTargetException, 3448 uno::RuntimeException ) 3449 { 3450 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::commit" ); 3451 3452 if ( !m_pImpl ) 3453 { 3454 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3455 throw lang::DisposedException(); 3456 } 3457 3458 if ( !m_bTransacted ) 3459 throw uno::RuntimeException(); 3460 3461 try { 3462 BroadcastTransaction( STOR_MESS_PRECOMMIT ); 3463 3464 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3465 3466 if ( !m_pImpl ) 3467 { 3468 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3469 throw lang::DisposedException(); 3470 } 3471 3472 m_pImpl->Commit(); 3473 3474 // when the storage is commited the parent is modified 3475 ModifyParentUnlockMutex_Impl( aGuard ); 3476 } 3477 catch( io::IOException& aIOException ) 3478 { 3479 m_pImpl->AddLog( aIOException.Message ); 3480 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3481 throw; 3482 } 3483 catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException ) 3484 { 3485 m_pImpl->AddLog( aStorageWrappedTargetException.Message ); 3486 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3487 throw; 3488 } 3489 catch( uno::RuntimeException& aRuntimeException ) 3490 { 3491 m_pImpl->AddLog( aRuntimeException.Message ); 3492 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3493 throw; 3494 } 3495 catch( uno::Exception& aException ) 3496 { 3497 m_pImpl->AddLog( aException.Message ); 3498 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3499 3500 uno::Any aCaught( ::cppu::getCaughtException() ); 3501 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on commit!" ), 3502 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ), 3503 aCaught ); 3504 } 3505 3506 BroadcastTransaction( STOR_MESS_COMMITED ); 3507 } 3508 3509 //----------------------------------------------- 3510 void SAL_CALL OWriteStream::revert() 3511 throw ( io::IOException, 3512 embed::StorageWrappedTargetException, 3513 uno::RuntimeException ) 3514 { 3515 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::revert" ); 3516 3517 // the method removes all the changes done after last commit 3518 3519 if ( !m_pImpl ) 3520 { 3521 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3522 throw lang::DisposedException(); 3523 } 3524 3525 if ( !m_bTransacted ) 3526 throw uno::RuntimeException(); 3527 3528 BroadcastTransaction( STOR_MESS_PREREVERT ); 3529 3530 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3531 3532 if ( !m_pImpl ) 3533 { 3534 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3535 throw lang::DisposedException(); 3536 } 3537 3538 try { 3539 m_pImpl->Revert(); 3540 } 3541 catch( io::IOException& aIOException ) 3542 { 3543 m_pImpl->AddLog( aIOException.Message ); 3544 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3545 throw; 3546 } 3547 catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException ) 3548 { 3549 m_pImpl->AddLog( aStorageWrappedTargetException.Message ); 3550 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3551 throw; 3552 } 3553 catch( uno::RuntimeException& aRuntimeException ) 3554 { 3555 m_pImpl->AddLog( aRuntimeException.Message ); 3556 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3557 throw; 3558 } 3559 catch( uno::Exception& aException ) 3560 { 3561 m_pImpl->AddLog( aException.Message ); 3562 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) ); 3563 3564 uno::Any aCaught( ::cppu::getCaughtException() ); 3565 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on revert!" ), 3566 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ), 3567 aCaught ); 3568 } 3569 3570 aGuard.clear(); 3571 3572 BroadcastTransaction( STOR_MESS_REVERTED ); 3573 } 3574 3575 //____________________________________________________________________________________________________ 3576 // XTransactionBroadcaster 3577 //____________________________________________________________________________________________________ 3578 3579 //----------------------------------------------- 3580 void SAL_CALL OWriteStream::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener ) 3581 throw ( uno::RuntimeException ) 3582 { 3583 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3584 3585 if ( !m_pImpl ) 3586 { 3587 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3588 throw lang::DisposedException(); 3589 } 3590 3591 if ( !m_bTransacted ) 3592 throw uno::RuntimeException(); 3593 3594 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0), 3595 aListener ); 3596 } 3597 3598 //----------------------------------------------- 3599 void SAL_CALL OWriteStream::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener ) 3600 throw ( uno::RuntimeException ) 3601 { 3602 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() ); 3603 3604 if ( !m_pImpl ) 3605 { 3606 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) ); 3607 throw lang::DisposedException(); 3608 } 3609 3610 if ( !m_bTransacted ) 3611 throw uno::RuntimeException(); 3612 3613 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0), 3614 aListener ); 3615 } 3616 3617 3618