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