merge the formfield patch from ooo-build
[ooovba.git] / package / source / xstor / owriteablestream.cxx
blobd1b548777134fd8594bf5fe1ac036ca68a6f66a2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: owriteablestream.cxx,v $
10 * $Revision: 1.23 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_package.hxx"
33 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
34 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/lang/XUnoTunnel.hpp>
37 #include <com/sun/star/lang/XTypeProvider.hpp>
38 #include <com/sun/star/io/XInputStream.hpp>
39 #include <com/sun/star/io/IOException.hpp>
40 #include <com/sun/star/embed/ElementModes.hpp>
41 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
42 #include <cppuhelper/typeprovider.hxx>
43 #include <cppuhelper/exc_hlp.hxx>
44 #include <osl/diagnose.h>
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/componentcontext.hxx>
48 #include <comphelper/storagehelper.hxx>
49 #include <comphelper/ofopxmlhelper.hxx>
51 #include "owriteablestream.hxx"
52 #include "oseekinstream.hxx"
53 #include "mutexholder.hxx"
54 #include "xstorage.hxx"
56 #include <rtl/digest.h>
57 #include <rtl/logfile.hxx>
59 // since the copying uses 32000 blocks usually, it makes sense to have a smaller size
60 #define MAX_STORCACHE_SIZE 30000
63 using namespace ::com::sun::star;
65 namespace package
67 //-----------------------------------------------
68 uno::Sequence< sal_Int8 > MakeKeyFromPass( const ::rtl::OUString& aPass, sal_Bool bUseUTF )
70 // MS_1252 encoding was used for SO60 document format password encoding,
71 // this encoding supports only a minor subset of nonascii characters,
72 // but for compatibility reasons it has to be used for old document formats
74 ::rtl::OString aByteStrPass;
75 if ( bUseUTF )
76 aByteStrPass = ::rtl::OUStringToOString( aPass, RTL_TEXTENCODING_UTF8 );
77 else
78 aByteStrPass = ::rtl::OUStringToOString( aPass, RTL_TEXTENCODING_MS_1252 );
80 sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
81 rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
82 aByteStrPass.getLength(),
83 pBuffer,
84 RTL_DIGEST_LENGTH_SHA1 );
86 if ( nError != rtl_Digest_E_None )
87 throw uno::RuntimeException();
89 return uno::Sequence< sal_Int8 >( (sal_Int8*)pBuffer, RTL_DIGEST_LENGTH_SHA1 );
93 //-----------------------------------------------
94 void StaticAddLog( const ::rtl::OUString& aMessage )
96 try
98 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
99 if ( aContext.is() )
101 uno::Reference< logging::XSimpleLogRing > xLogRing( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW );
102 xLogRing->logString( aMessage );
105 catch( uno::Exception& )
107 // No log
110 } // namespace package
112 // ================================================================
113 namespace
115 //-----------------------------------------------
116 void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet,
117 const uno::Sequence< sal_Int8 >& aKey )
119 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
120 if ( !xPropertySet.is() )
121 throw uno::RuntimeException();
123 ::rtl::OUString aString_EncryptionKey = ::rtl::OUString::createFromAscii( "EncryptionKey" );
124 try {
125 xPropertySet->setPropertyValue( aString_EncryptionKey, uno::makeAny( aKey ) );
127 catch ( uno::Exception& aException )
129 ::package::StaticAddLog( aException.Message );
130 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't set encryption" ) ) );
131 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
132 throw io::IOException(); // TODO
136 //-----------------------------------------------
137 uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet )
139 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
140 if ( !xPropertySet.is() )
141 throw uno::RuntimeException();
143 ::rtl::OUString aString_EncryptionKey = ::rtl::OUString::createFromAscii( "EncryptionKey" );
144 try {
145 return xPropertySet->getPropertyValue( aString_EncryptionKey );
147 catch ( uno::Exception& aException )
149 ::package::StaticAddLog( aException.Message );
150 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can't get encryption property" ) ) );
152 OSL_ENSURE( sal_False, "Can't get encryption related properties!\n" );
153 throw io::IOException(); // TODO
157 //-----------------------------------------------
158 sal_Bool SequencesEqual( uno::Sequence< sal_Int8 > aSequence1, uno::Sequence< sal_Int8 > aSequence2 )
160 if ( aSequence1.getLength() != aSequence2.getLength() )
161 return sal_False;
163 for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ )
164 if ( aSequence1[nInd] != aSequence2[nInd] )
165 return sal_False;
167 return sal_True;
170 //-----------------------------------------------
171 sal_Bool KillFile( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
173 if ( !xFactory.is() )
174 return sal_False;
176 sal_Bool bRet = sal_False;
180 uno::Reference < ucb::XSimpleFileAccess > xAccess(
181 xFactory->createInstance (
182 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
183 uno::UNO_QUERY );
185 if ( xAccess.is() )
187 xAccess->kill( aURL );
188 bRet = sal_True;
191 catch( uno::Exception& aException )
193 ::package::StaticAddLog( aException.Message );
194 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
197 return bRet;
200 const sal_Int32 n_ConstBufferSize = 32000;
202 //-----------------------------------------------
203 ::rtl::OUString GetNewTempFileURL( const uno::Reference< lang::XMultiServiceFactory > xFactory )
205 ::rtl::OUString aTempURL;
207 uno::Reference < beans::XPropertySet > xTempFile(
208 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
209 uno::UNO_QUERY );
211 if ( !xTempFile.is() )
212 throw uno::RuntimeException(); // TODO
214 try {
215 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
216 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
217 aUrl >>= aTempURL;
219 catch ( uno::Exception& aException )
221 ::package::StaticAddLog( aException.Message );
222 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
225 if ( !aTempURL.getLength() )
226 throw uno::RuntimeException(); // TODO: can not create tempfile
228 return aTempURL;
231 //-----------------------------------------------
232 uno::Reference< io::XStream > CreateMemoryStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
234 if ( !xFactory.is() )
235 throw uno::RuntimeException();
237 return uno::Reference< io::XStream >( xFactory->createInstance ( ::rtl::OUString::createFromAscii( "com.sun.star.comp.MemoryStream" ) ), uno::UNO_QUERY_THROW );
240 } // anonymous namespace
241 // ================================================================
243 //-----------------------------------------------
244 OWriteStream_Impl::OWriteStream_Impl( OStorage_Impl* pParent,
245 const uno::Reference< packages::XDataSinkEncrSupport >& xPackageStream,
246 const uno::Reference< lang::XSingleServiceFactory >& xPackage,
247 const uno::Reference< lang::XMultiServiceFactory >& xFactory,
248 sal_Bool bForceEncrypted,
249 sal_Int16 nStorageType,
250 sal_Bool bDefaultCompress,
251 const uno::Reference< io::XInputStream >& xRelInfoStream )
252 : m_pAntiImpl( NULL )
253 , m_bHasDataToFlush( sal_False )
254 , m_bFlushed( sal_False )
255 , m_xPackageStream( xPackageStream )
256 , m_xFactory( xFactory )
257 , m_pParent( pParent )
258 , m_bForceEncrypted( bForceEncrypted )
259 , m_bUseCommonPass( !bForceEncrypted && nStorageType == PACKAGE_STORAGE )
260 , m_bHasCachedPassword( sal_False )
261 , m_bCompressedSetExplicit( !bDefaultCompress )
262 , m_xPackage( xPackage )
263 , m_bHasInsertedStreamOptimization( sal_False )
264 , m_nStorageType( nStorageType )
265 , m_xOrigRelInfoStream( xRelInfoStream )
266 , m_bOrigRelInfoBroken( sal_False )
267 , m_nRelInfoStatus( RELINFO_NO_INIT )
268 , m_nRelId( 1 )
270 OSL_ENSURE( xPackageStream.is(), "No package stream is provided!\n" );
271 OSL_ENSURE( xPackage.is(), "No package component is provided!\n" );
272 OSL_ENSURE( m_xFactory.is(), "No package stream is provided!\n" );
273 OSL_ENSURE( pParent, "No parent storage is provided!\n" );
274 OSL_ENSURE( m_nStorageType == OFOPXML_STORAGE || !m_xOrigRelInfoStream.is(), "The Relations info makes sence only for OFOPXML format!\n" );
277 //-----------------------------------------------
278 OWriteStream_Impl::~OWriteStream_Impl()
280 DisposeWrappers();
282 if ( m_aTempURL.getLength() )
284 KillFile( m_aTempURL, GetServiceFactory() );
285 m_aTempURL = ::rtl::OUString();
288 CleanCacheStream();
291 //-----------------------------------------------
292 void OWriteStream_Impl::CleanCacheStream()
294 if ( m_xCacheStream.is() )
298 uno::Reference< io::XInputStream > xInputCache = m_xCacheStream->getInputStream();
299 if ( xInputCache.is() )
300 xInputCache->closeInput();
302 catch( uno::Exception& )
307 uno::Reference< io::XOutputStream > xOutputCache = m_xCacheStream->getOutputStream();
308 if ( xOutputCache.is() )
309 xOutputCache->closeOutput();
311 catch( uno::Exception& )
314 m_xCacheStream = uno::Reference< io::XStream >();
315 m_xCacheSeek = uno::Reference< io::XSeekable >();
319 //-----------------------------------------------
320 void OWriteStream_Impl::AddLog( const ::rtl::OUString& aMessage )
322 if ( !m_xLogRing.is() )
326 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
327 if ( aContext.is() )
328 m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), uno::UNO_QUERY_THROW );
330 catch( uno::Exception& )
332 // No log
336 if ( m_xLogRing.is() )
337 m_xLogRing->logString( aMessage );
341 //-----------------------------------------------
342 void OWriteStream_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName,
343 const uno::Reference< container::XNameContainer >& xParentPackageFolder )
345 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
347 OSL_ENSURE( m_bFlushed, "This method must not be called for nonflushed streams!\n" );
348 if ( m_bFlushed )
350 OSL_ENSURE( m_xPackageStream.is(), "An inserted stream is incomplete!\n" );
351 uno::Reference< lang::XUnoTunnel > xTunnel( m_xPackageStream, uno::UNO_QUERY );
352 if ( !xTunnel.is() )
353 throw uno::RuntimeException(); // TODO
355 xParentPackageFolder->insertByName( aName, uno::makeAny( xTunnel ) );
357 m_bFlushed = sal_False;
358 m_bHasInsertedStreamOptimization = sal_False;
361 //-----------------------------------------------
362 sal_Bool OWriteStream_Impl::IsEncrypted()
364 if ( m_nStorageType != PACKAGE_STORAGE )
365 return sal_False;
367 if ( m_bForceEncrypted || m_bHasCachedPassword )
368 return sal_True;
370 if ( m_aTempURL.getLength() || m_xCacheStream.is() )
371 return sal_False;
373 GetStreamProperties();
375 // the following value can not be cached since it can change after root commit
376 sal_Bool bWasEncr = sal_False;
377 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
378 if ( xPropSet.is() )
380 uno::Any aValue = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "WasEncrypted" ) );
381 if ( !( aValue >>= bWasEncr ) )
383 OSL_ENSURE( sal_False, "The property WasEncrypted has wrong type!\n" );
387 sal_Bool bToBeEncr = sal_False;
388 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
390 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
392 if ( !( m_aProps[nInd].Value >>= bToBeEncr ) )
394 OSL_ENSURE( sal_False, "The property has wrong type!\n" );
399 // since a new key set to the package stream it should not be removed except the case when
400 // the stream becomes nonencrypted
401 uno::Sequence< sal_Int8 > aKey;
402 if ( bToBeEncr )
403 GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey;
405 // If the properties must be investigated the stream is either
406 // was never changed or was changed, the parent was commited
407 // and the stream was closed.
408 // That means that if it is intended to use common storage key
409 // it is already has no encryption but is marked to be stored
410 // encrypted and the key is empty.
411 if ( !bWasEncr && bToBeEncr && !aKey.getLength() )
413 // the stream is intended to use common storage password
414 m_bUseCommonPass = sal_True;
415 return sal_False;
417 else
418 return bToBeEncr;
421 //-----------------------------------------------
422 void OWriteStream_Impl::SetDecrypted()
424 OSL_ENSURE( m_nStorageType == PACKAGE_STORAGE, "The encryption is supported only for package storages!\n" );
425 if ( m_nStorageType != PACKAGE_STORAGE )
426 throw uno::RuntimeException();
428 GetStreamProperties();
430 // let the stream be modified
431 FillTempGetFileName();
432 m_bHasDataToFlush = sal_True;
434 // remove encryption
435 m_bForceEncrypted = sal_False;
436 m_bHasCachedPassword = sal_False;
437 m_aPass = ::rtl::OUString();
439 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
441 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
442 m_aProps[nInd].Value <<= sal_False;
446 //-----------------------------------------------
447 void OWriteStream_Impl::SetEncryptedWithPass( const ::rtl::OUString& aPass )
449 OSL_ENSURE( m_nStorageType == PACKAGE_STORAGE, "The encryption is supported only for package storages!\n" );
450 if ( m_nStorageType != PACKAGE_STORAGE )
451 throw uno::RuntimeException();
453 GetStreamProperties();
455 // let the stream be modified
456 FillTempGetFileName();
457 m_bHasDataToFlush = sal_True;
459 // introduce encryption info
460 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
462 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
463 m_aProps[nInd].Value <<= sal_True;
466 m_bUseCommonPass = sal_False; // very important to set it to false
468 m_bHasCachedPassword = sal_True;
469 m_aPass = aPass;
472 //-----------------------------------------------
473 void OWriteStream_Impl::DisposeWrappers()
475 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
476 if ( m_pAntiImpl )
478 try {
479 m_pAntiImpl->dispose();
481 catch ( uno::RuntimeException& aRuntimeException )
483 AddLog( aRuntimeException.Message );
484 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
487 m_pAntiImpl = NULL;
489 m_pParent = NULL;
491 if ( !m_aInputStreamsList.empty() )
493 for ( InputStreamsList_Impl::iterator pStreamIter = m_aInputStreamsList.begin();
494 pStreamIter != m_aInputStreamsList.end(); pStreamIter++ )
496 if ( (*pStreamIter) )
498 (*pStreamIter)->InternalDispose();
499 (*pStreamIter) = NULL;
503 m_aInputStreamsList.clear();
507 //-----------------------------------------------
508 uno::Reference< lang::XMultiServiceFactory > OWriteStream_Impl::GetServiceFactory()
510 if ( m_xFactory.is() )
511 return m_xFactory;
513 return ::comphelper::getProcessServiceFactory();
516 //-----------------------------------------------
517 ::rtl::OUString OWriteStream_Impl::GetFilledTempFileIfNo( const uno::Reference< io::XInputStream >& xStream )
519 if ( !m_aTempURL.getLength() )
521 ::rtl::OUString aTempURL = GetNewTempFileURL( GetServiceFactory() );
523 try {
524 if ( aTempURL && xStream.is() )
526 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
527 GetServiceFactory()->createInstance (
528 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
529 uno::UNO_QUERY );
531 if ( !xTempAccess.is() )
532 throw uno::RuntimeException(); // TODO:
534 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( aTempURL );
535 if ( xTempOutStream.is() )
537 // the current position of the original stream should be still OK, copy further
538 ::comphelper::OStorageHelper::CopyInputToOutput( xStream, xTempOutStream );
539 xTempOutStream->closeOutput();
540 xTempOutStream = uno::Reference< io::XOutputStream >();
542 else
543 throw io::IOException(); // TODO:
546 catch( packages::WrongPasswordException& aWrongPasswordException )
548 AddLog( aWrongPasswordException.Message );
549 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
551 KillFile( aTempURL, GetServiceFactory() );
552 throw;
554 catch( uno::Exception& aException )
556 AddLog( aException.Message );
557 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
559 KillFile( aTempURL, GetServiceFactory() );
560 throw;
563 if ( aTempURL.getLength() )
564 CleanCacheStream();
566 m_aTempURL = aTempURL;
569 return m_aTempURL;
572 //-----------------------------------------------
573 ::rtl::OUString OWriteStream_Impl::FillTempGetFileName()
575 // should try to create cache first, if the amount of contents is too big, the temp file should be taken
576 if ( !m_xCacheStream.is() && !m_aTempURL.getLength() )
578 uno::Reference< io::XInputStream > xOrigStream = m_xPackageStream->getDataStream();
579 if ( !xOrigStream.is() )
581 // in case of new inserted package stream it is possible that input stream still was not set
582 uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() );
583 OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" );
584 m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW );
585 m_xCacheStream = xCacheStream;
587 else
589 sal_Int32 nRead = 0;
590 uno::Sequence< sal_Int8 > aData( MAX_STORCACHE_SIZE + 1 );
591 nRead = xOrigStream->readBytes( aData, MAX_STORCACHE_SIZE + 1 );
592 if ( aData.getLength() > nRead )
593 aData.realloc( nRead );
595 if ( nRead && nRead <= MAX_STORCACHE_SIZE )
597 uno::Reference< io::XStream > xCacheStream = CreateMemoryStream( GetServiceFactory() );
598 OSL_ENSURE( xCacheStream.is(), "If the stream can not be created an exception must be thrown!\n" );
600 uno::Reference< io::XOutputStream > xOutStream( xCacheStream->getOutputStream(), uno::UNO_SET_THROW );
601 xOutStream->writeBytes( aData );
602 m_xCacheSeek.set( xCacheStream, uno::UNO_QUERY_THROW );
603 m_xCacheStream = xCacheStream;
604 m_xCacheSeek->seek( 0 );
606 else if ( nRead && !m_aTempURL.getLength() )
608 m_aTempURL = GetNewTempFileURL( GetServiceFactory() );
610 try {
611 if ( m_aTempURL.getLength() )
613 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
614 GetServiceFactory()->createInstance (
615 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
616 uno::UNO_QUERY );
618 if ( !xTempAccess.is() )
619 throw uno::RuntimeException(); // TODO:
622 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( m_aTempURL );
623 if ( xTempOutStream.is() )
625 // copy stream contents to the file
626 xTempOutStream->writeBytes( aData );
628 // the current position of the original stream should be still OK, copy further
629 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigStream, xTempOutStream );
630 xTempOutStream->closeOutput();
631 xTempOutStream = uno::Reference< io::XOutputStream >();
633 else
634 throw io::IOException(); // TODO:
637 catch( packages::WrongPasswordException& )
639 KillFile( m_aTempURL, GetServiceFactory() );
640 m_aTempURL = ::rtl::OUString();
642 throw;
644 catch( uno::Exception& )
646 KillFile( m_aTempURL, GetServiceFactory() );
647 m_aTempURL = ::rtl::OUString();
653 return m_aTempURL;
656 //-----------------------------------------------
657 uno::Reference< io::XStream > OWriteStream_Impl::GetTempFileAsStream()
659 uno::Reference< io::XStream > xTempStream;
661 if ( !m_xCacheStream.is() )
663 if ( !m_aTempURL.getLength() )
664 m_aTempURL = FillTempGetFileName();
666 if ( m_aTempURL.getLength() )
668 // the temporary file is not used if the cache is used
669 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
670 GetServiceFactory()->createInstance (
671 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
672 uno::UNO_QUERY );
674 if ( !xTempAccess.is() )
675 throw uno::RuntimeException(); // TODO:
679 xTempStream = xTempAccess->openFileReadWrite( m_aTempURL );
681 catch( uno::Exception& aException )
683 AddLog( aException.Message );
684 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
689 if ( m_xCacheStream.is() )
690 xTempStream = m_xCacheStream;
692 // the method must always return a stream
693 // in case the stream can not be open
694 // an exception should be thrown
695 if ( !xTempStream.is() )
696 throw io::IOException(); //TODO:
698 return xTempStream;
701 //-----------------------------------------------
702 uno::Reference< io::XInputStream > OWriteStream_Impl::GetTempFileAsInputStream()
704 uno::Reference< io::XInputStream > xInputStream;
706 if ( !m_xCacheStream.is() )
708 if ( !m_aTempURL.getLength() )
709 m_aTempURL = FillTempGetFileName();
711 if ( m_aTempURL.getLength() )
713 // the temporary file is not used if the cache is used
714 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
715 GetServiceFactory()->createInstance (
716 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
717 uno::UNO_QUERY );
719 if ( !xTempAccess.is() )
720 throw uno::RuntimeException(); // TODO:
724 xInputStream = xTempAccess->openFileRead( m_aTempURL );
726 catch( uno::Exception& aException )
728 AddLog( aException.Message );
729 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
734 if ( m_xCacheStream.is() )
735 xInputStream = m_xCacheStream->getInputStream();
737 // the method must always return a stream
738 // in case the stream can not be open
739 // an exception should be thrown
740 if ( !xInputStream.is() )
741 throw io::IOException(); // TODO:
743 return xInputStream;
746 // =================================================================================================
748 //-----------------------------------------------
749 void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputStream >& xInStream,
750 const uno::Sequence< beans::PropertyValue >& aProps )
752 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
754 // this call can be made only during parent storage commit
755 // the parent storage is responsible for the correct handling
756 // of deleted and renamed contents
758 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
760 if ( m_bHasDataToFlush )
761 throw io::IOException();
763 OSL_ENSURE( !m_aTempURL.getLength() && !m_xCacheStream.is(), "The temporary must not exist!\n" );
765 // use new file as current persistent representation
766 // the new file will be removed after it's stream is closed
767 m_xPackageStream->setDataStream( xInStream );
769 // copy properties to the package stream
770 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
771 if ( !xPropertySet.is() )
772 throw uno::RuntimeException();
774 // The storage-package communication has a problem
775 // the storage caches properties, thus if the package changes one of them itself
776 // the storage does not know about it
778 // Depending from MediaType value the package can change the compressed property itself
779 // Thus if Compressed property is provided it must be set as the latest one
780 sal_Bool bCompressedIsSet = sal_False;
781 sal_Bool bCompressed = sal_False;
782 ::rtl::OUString aComprPropName( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
783 ::rtl::OUString aMedTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
784 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
786 if ( aProps[nInd].Name.equals( aComprPropName ) )
788 bCompressedIsSet = sal_True;
789 aProps[nInd].Value >>= bCompressed;
791 else if ( ( m_nStorageType == OFOPXML_STORAGE || m_nStorageType == PACKAGE_STORAGE )
792 && aProps[nInd].Name.equals( aMedTypePropName ) )
794 xPropertySet->setPropertyValue( aProps[nInd].Name, aProps[nInd].Value );
796 else if ( m_nStorageType == PACKAGE_STORAGE && aProps[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
797 aProps[nInd].Value >>= m_bUseCommonPass;
798 else
799 throw lang::IllegalArgumentException();
801 // if there are cached properties update them
802 if ( aProps[nInd].Name.equals( aMedTypePropName ) || aProps[nInd].Name.equals( aComprPropName ) )
803 for ( sal_Int32 nMemInd = 0; nMemInd < m_aProps.getLength(); nMemInd++ )
805 if ( aProps[nInd].Name.equals( m_aProps[nMemInd].Name ) )
806 m_aProps[nMemInd].Value = aProps[nInd].Value;
810 if ( bCompressedIsSet )
812 xPropertySet->setPropertyValue( aComprPropName, uno::makeAny( (sal_Bool)bCompressed ) );
813 m_bCompressedSetExplicit = sal_True;
816 if ( m_bUseCommonPass )
818 if ( m_nStorageType != PACKAGE_STORAGE )
819 throw uno::RuntimeException();
821 // set to be encrypted but do not use encryption key
822 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
823 uno::makeAny( uno::Sequence< sal_Int8 >() ) );
824 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
825 uno::makeAny( sal_True ) );
828 // the stream should be free soon, after package is stored
829 m_bHasDataToFlush = sal_False;
830 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
831 m_bHasInsertedStreamOptimization = sal_True;
834 //-----------------------------------------------
835 void OWriteStream_Impl::Commit()
837 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
839 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
841 if ( !m_bHasDataToFlush )
842 return;
844 uno::Reference< packages::XDataSinkEncrSupport > xNewPackageStream;
845 uno::Sequence< uno::Any > aSeq( 1 );
846 aSeq[0] <<= sal_False;
848 if ( m_xCacheStream.is() )
850 uno::Reference< io::XInputStream > xInStream( m_xCacheStream->getInputStream(), uno::UNO_SET_THROW );
852 xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >(
853 m_xPackage->createInstanceWithArguments( aSeq ),
854 uno::UNO_QUERY_THROW );
856 xNewPackageStream->setDataStream( xInStream );
858 m_xCacheStream = uno::Reference< io::XStream >();
859 m_xCacheSeek = uno::Reference< io::XSeekable >();
861 if ( m_pAntiImpl )
862 m_pAntiImpl->DeInit();
864 else if ( m_aTempURL.getLength() )
866 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
867 GetServiceFactory()->createInstance (
868 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
869 uno::UNO_QUERY );
871 if ( !xTempAccess.is() )
872 throw uno::RuntimeException(); // TODO:
874 uno::Reference< io::XInputStream > xInStream;
877 xInStream = xTempAccess->openFileRead( m_aTempURL );
879 catch( uno::Exception& )
883 if ( !xInStream.is() )
884 throw io::IOException();
886 xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >(
887 m_xPackage->createInstanceWithArguments( aSeq ),
888 uno::UNO_QUERY_THROW );
890 // TODO/NEW: Let the temporary file be removed after commit
891 xNewPackageStream->setDataStream( xInStream );
892 m_aTempURL = ::rtl::OUString();
894 if ( m_pAntiImpl )
895 m_pAntiImpl->DeInit();
897 else // if ( m_bHasInsertedStreamOptimization )
899 // if the optimization is used the stream can be accessed directly
900 xNewPackageStream = m_xPackageStream;
903 // copy properties to the package stream
904 uno::Reference< beans::XPropertySet > xPropertySet( xNewPackageStream, uno::UNO_QUERY );
905 if ( !xPropertySet.is() )
906 throw uno::RuntimeException();
908 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
910 if ( m_aProps[nInd].Name.equalsAscii( "Size" ) )
912 if ( m_pAntiImpl && !m_bHasInsertedStreamOptimization && m_pAntiImpl->m_xSeekable.is() )
914 m_aProps[nInd].Value <<= ((sal_Int32)m_pAntiImpl->m_xSeekable->getLength());
915 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
918 else
919 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
922 if ( m_bUseCommonPass )
924 if ( m_nStorageType != PACKAGE_STORAGE )
925 throw uno::RuntimeException();
927 // set to be encrypted but do not use encryption key
928 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
929 uno::makeAny( uno::Sequence< sal_Int8 >() ) );
930 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
931 uno::makeAny( sal_True ) );
933 else if ( m_bHasCachedPassword )
935 if ( m_nStorageType != PACKAGE_STORAGE )
936 throw uno::RuntimeException();
938 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
939 uno::makeAny( ::package::MakeKeyFromPass( m_aPass, sal_True ) ) );
942 // the stream should be free soon, after package is stored
943 m_xPackageStream = xNewPackageStream;
944 m_bHasDataToFlush = sal_False;
945 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
948 //-----------------------------------------------
949 void OWriteStream_Impl::Revert()
951 // can be called only from parent storage
952 // means complete reload of the stream
954 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
956 if ( !m_bHasDataToFlush )
957 return; // nothing to do
959 OSL_ENSURE( m_aTempURL.getLength() || m_xCacheStream.is(), "The temporary must exist!\n" );
961 if ( m_xCacheStream.is() )
963 m_xCacheStream = uno::Reference< io::XStream >();
964 m_xCacheSeek = uno::Reference< io::XSeekable >();
967 if ( m_aTempURL.getLength() )
969 KillFile( m_aTempURL, GetServiceFactory() );
970 m_aTempURL = ::rtl::OUString();
973 m_aProps.realloc( 0 );
975 m_bHasDataToFlush = sal_False;
977 m_bUseCommonPass = sal_True;
978 m_bHasCachedPassword = sal_False;
979 m_aPass = ::rtl::OUString();
981 if ( m_nStorageType == OFOPXML_STORAGE )
983 // currently the relations storage is changed only on commit
984 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
985 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
986 if ( m_xOrigRelInfoStream.is() )
988 // the original stream is still here, that means that it was not parsed
989 m_aOrigRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
990 m_nRelInfoStatus = RELINFO_NO_INIT;
992 else
994 // the original stream was aready parsed
995 if ( !m_bOrigRelInfoBroken )
996 m_nRelInfoStatus = RELINFO_READ;
997 else
998 m_nRelInfoStatus = RELINFO_BROKEN;
1003 //-----------------------------------------------
1004 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::GetStreamProperties()
1006 if ( !m_aProps.getLength() )
1007 m_aProps = ReadPackageStreamProperties();
1009 return m_aProps;
1012 //-----------------------------------------------
1013 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::InsertOwnProps(
1014 const uno::Sequence< beans::PropertyValue >& aProps,
1015 sal_Bool bUseCommonPass )
1017 uno::Sequence< beans::PropertyValue > aResult( aProps );
1018 sal_Int32 nLen = aResult.getLength();
1020 if ( m_nStorageType == PACKAGE_STORAGE )
1022 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1023 if ( aResult[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
1025 aResult[nInd].Value <<= bUseCommonPass;
1026 return aResult;
1029 aResult.realloc( ++nLen );
1030 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1031 aResult[nLen - 1].Value <<= bUseCommonPass;
1033 else if ( m_nStorageType == OFOPXML_STORAGE )
1035 ReadRelInfoIfNecessary();
1037 uno::Any aValue;
1038 if ( m_nRelInfoStatus == RELINFO_READ )
1039 aValue <<= m_aOrigRelInfo;
1040 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
1041 aValue <<= m_aNewRelInfo;
1042 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
1043 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
1044 uno::Reference< uno::XInterface >() );
1046 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
1047 if ( aResult[nInd].Name.equalsAscii( "RelationsInfo" ) )
1049 aResult[nInd].Value = aValue;
1050 return aResult;
1053 aResult.realloc( ++nLen );
1054 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "RelationsInfo" );
1055 aResult[nLen - 1].Value = aValue;
1058 return aResult;
1061 //-----------------------------------------------
1062 sal_Bool OWriteStream_Impl::IsTransacted()
1064 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1065 return ( m_pAntiImpl && m_pAntiImpl->m_bTransacted );
1068 void OWriteStream_Impl::ReadRelInfoIfNecessary()
1070 if ( m_nStorageType != OFOPXML_STORAGE )
1071 return;
1073 if ( m_nRelInfoStatus == RELINFO_NO_INIT )
1077 // Init from original stream
1078 if ( m_xOrigRelInfoStream.is() )
1079 m_aOrigRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
1080 m_xOrigRelInfoStream,
1081 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
1082 m_xFactory );
1084 // in case of success the stream must be thrown away, that means that the OrigRelInfo is initialized
1085 // the reason for this is that the original stream might not be seekable ( at the same time the new
1086 // provided stream must be seekable ), so it must be read only once
1087 m_xOrigRelInfoStream = uno::Reference< io::XInputStream >();
1088 m_nRelInfoStatus = RELINFO_READ;
1090 catch( uno::Exception& aException )
1092 AddLog( aException.Message );
1093 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1095 m_nRelInfoStatus = RELINFO_BROKEN;
1096 m_bOrigRelInfoBroken = sal_True;
1099 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1101 // Init from the new stream
1104 if ( m_xNewRelInfoStream.is() )
1105 m_aNewRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
1106 m_xNewRelInfoStream,
1107 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
1108 m_xFactory );
1110 m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ;
1112 catch( uno::Exception )
1114 m_nRelInfoStatus = RELINFO_CHANGED_BROKEN;
1119 //-----------------------------------------------
1120 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::ReadPackageStreamProperties()
1122 sal_Int32 nPropNum = 0;
1123 if ( m_nStorageType == ZIP_STORAGE )
1124 nPropNum = 2;
1125 else if ( m_nStorageType == OFOPXML_STORAGE )
1126 nPropNum = 3;
1127 else if ( m_nStorageType == PACKAGE_STORAGE )
1128 nPropNum = 4;
1129 uno::Sequence< beans::PropertyValue > aResult( nPropNum );
1131 // The "Compressed" property must be set after "MediaType" property,
1132 // since the setting of the last one can change the value of the first one
1134 if ( m_nStorageType == OFOPXML_STORAGE || m_nStorageType == PACKAGE_STORAGE )
1136 aResult[0].Name = ::rtl::OUString::createFromAscii("MediaType");
1137 aResult[1].Name = ::rtl::OUString::createFromAscii("Compressed");
1138 aResult[2].Name = ::rtl::OUString::createFromAscii("Size");
1140 if ( m_nStorageType == PACKAGE_STORAGE )
1141 aResult[3].Name = ::rtl::OUString::createFromAscii("Encrypted");
1143 else
1145 aResult[0].Name = ::rtl::OUString::createFromAscii("Compressed");
1146 aResult[1].Name = ::rtl::OUString::createFromAscii("Size");
1150 // TODO: may be also raw stream should be marked
1152 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
1153 if ( xPropSet.is() )
1155 for ( sal_Int32 nInd = 0; nInd < aResult.getLength(); nInd++ )
1157 try {
1158 aResult[nInd].Value = xPropSet->getPropertyValue( aResult[nInd].Name );
1160 catch( uno::Exception& aException )
1162 AddLog( aException.Message );
1163 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1165 OSL_ENSURE( sal_False, "A property can't be retrieved!\n" );
1169 else
1171 OSL_ENSURE( sal_False, "Can not get properties from a package stream!\n" );
1172 throw uno::RuntimeException();
1175 return aResult;
1178 //-----------------------------------------------
1179 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream,
1180 const ::rtl::OUString& aPass )
1182 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1184 OSL_ENSURE( !m_bUseCommonPass, "The stream can not be encrypted!" );
1186 if ( m_nStorageType != PACKAGE_STORAGE )
1187 throw packages::NoEncryptionException();
1189 if ( m_pAntiImpl )
1191 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
1193 else
1195 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, aPass, sal_False );
1196 if ( !xOwnStream.is() )
1197 throw io::IOException(); // TODO
1199 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
1202 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xDestStream, uno::UNO_QUERY );
1203 if ( xEncr.is() )
1204 xEncr->setEncryptionPassword( aPass );
1207 //-----------------------------------------------
1208 uno::Sequence< uno::Sequence< beans::StringPair > > OWriteStream_Impl::GetAllRelationshipsIfAny()
1210 if ( m_nStorageType != OFOPXML_STORAGE )
1211 return uno::Sequence< uno::Sequence< beans::StringPair > >();
1213 ReadRelInfoIfNecessary();
1215 if ( m_nRelInfoStatus == RELINFO_READ )
1216 return m_aOrigRelInfo;
1217 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
1218 return m_aNewRelInfo;
1219 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
1220 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
1221 uno::Reference< uno::XInterface >() );
1224 //-----------------------------------------------
1225 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream )
1227 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1229 if ( m_pAntiImpl )
1231 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
1233 else
1235 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, sal_False );
1236 if ( !xOwnStream.is() )
1237 throw io::IOException(); // TODO
1239 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
1243 //-----------------------------------------------
1244 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, const ::rtl::OUString& aPass, sal_Bool bHierarchyAccess )
1246 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1248 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1250 if ( m_pAntiImpl )
1251 throw io::IOException(); // TODO:
1253 if ( !IsEncrypted() )
1254 throw packages::NoEncryptionException();
1256 uno::Reference< io::XStream > xResultStream;
1258 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1259 if ( !xPropertySet.is() )
1260 throw uno::RuntimeException();
1262 if ( m_bHasCachedPassword )
1264 if ( !m_aPass.equals( aPass ) )
1265 throw packages::WrongPasswordException();
1267 // the correct key must be set already
1268 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1270 else
1272 SetEncryptionKeyProperty_Impl( xPropertySet, ::package::MakeKeyFromPass( aPass, sal_True ) );
1274 try {
1275 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1277 m_bUseCommonPass = sal_False; // very important to set it to false
1278 m_bHasCachedPassword = sal_True;
1279 m_aPass = aPass;
1281 catch( packages::WrongPasswordException& )
1283 // retry with different encoding
1284 SetEncryptionKeyProperty_Impl( xPropertySet, ::package::MakeKeyFromPass( aPass, sal_False ) );
1285 try {
1286 // the stream must be cashed to be resaved
1287 xResultStream = GetStream_Impl( nStreamMode | embed::ElementModes::SEEKABLE, bHierarchyAccess );
1289 m_bUseCommonPass = sal_False; // very important to set it to false
1290 m_bHasCachedPassword = sal_True;
1291 m_aPass = aPass;
1293 // the stream must be resaved with new password encryption
1294 if ( nStreamMode & embed::ElementModes::WRITE )
1296 FillTempGetFileName();
1297 m_bHasDataToFlush = sal_True;
1299 // TODO/LATER: should the notification be done?
1300 if ( m_pParent )
1301 m_pParent->m_bIsModified = sal_True;
1304 catch( packages::WrongPasswordException& aWrongPasswordException )
1306 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1307 AddLog( aWrongPasswordException.Message );
1308 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1309 throw;
1311 catch ( uno::Exception& aException )
1313 AddLog( aException.Message );
1314 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1316 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
1317 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1318 throw io::IOException(); // TODO:
1321 catch( uno::Exception& aException )
1323 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1325 AddLog( aException.Message );
1326 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1327 throw;
1332 OSL_ENSURE( xResultStream.is(), "In case stream can not be retrieved an exception must be thrown!\n" );
1334 return xResultStream;
1337 //-----------------------------------------------
1338 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1340 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1342 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1344 if ( m_pAntiImpl )
1345 throw io::IOException(); // TODO:
1347 uno::Reference< io::XStream > xResultStream;
1349 if ( IsEncrypted() )
1351 ::rtl::OUString aGlobalPass;
1354 aGlobalPass = GetCommonRootPass();
1356 catch( packages::NoEncryptionException& aNoEncryptionException )
1358 AddLog( aNoEncryptionException.Message );
1359 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1361 throw packages::WrongPasswordException();
1364 xResultStream = GetStream( nStreamMode, aGlobalPass, bHierarchyAccess );
1366 else
1367 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1369 return xResultStream;
1372 //-----------------------------------------------
1373 uno::Reference< io::XStream > OWriteStream_Impl::GetStream_Impl( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1375 // private method, no mutex is used
1376 GetStreamProperties();
1378 // TODO/LATER: this info might be read later, on demand in future
1379 ReadRelInfoIfNecessary();
1381 if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::READ )
1383 uno::Reference< io::XInputStream > xInStream;
1384 if ( m_xCacheStream.is() || m_aTempURL.getLength() )
1385 xInStream = GetTempFileAsInputStream(); //TODO:
1386 else
1387 xInStream = m_xPackageStream->getDataStream();
1389 // The stream does not exist in the storage
1390 if ( !xInStream.is() )
1391 throw io::IOException();
1393 OInputCompStream* pStream = new OInputCompStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonPass ), m_nStorageType );
1394 uno::Reference< io::XStream > xCompStream(
1395 static_cast< ::cppu::OWeakObject* >( pStream ),
1396 uno::UNO_QUERY );
1397 OSL_ENSURE( xCompStream.is(),
1398 "OInputCompStream MUST provide XStream interfaces!\n" );
1400 m_aInputStreamsList.push_back( pStream );
1401 return xCompStream;
1403 else if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::SEEKABLEREAD )
1405 if ( !m_xCacheStream.is() && !m_aTempURL.getLength() && !( m_xPackageStream->getDataStream().is() ) )
1407 // The stream does not exist in the storage
1408 throw io::IOException();
1411 uno::Reference< io::XInputStream > xInStream;
1413 xInStream = GetTempFileAsInputStream(); //TODO:
1415 if ( !xInStream.is() )
1416 throw io::IOException();
1418 OInputSeekStream* pStream = new OInputSeekStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonPass ), m_nStorageType );
1419 uno::Reference< io::XStream > xSeekStream(
1420 static_cast< ::cppu::OWeakObject* >( pStream ),
1421 uno::UNO_QUERY );
1422 OSL_ENSURE( xSeekStream.is(),
1423 "OInputSeekStream MUST provide XStream interfaces!\n" );
1425 m_aInputStreamsList.push_back( pStream );
1426 return xSeekStream;
1428 else if ( ( nStreamMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE )
1430 if ( !m_aInputStreamsList.empty() )
1431 throw io::IOException(); // TODO:
1433 uno::Reference< io::XStream > xStream;
1434 if ( ( nStreamMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
1436 if ( m_aTempURL.getLength() )
1438 KillFile( m_aTempURL, GetServiceFactory() );
1439 m_aTempURL = ::rtl::OUString();
1441 if ( m_xCacheStream.is() )
1442 CleanCacheStream();
1444 m_bHasDataToFlush = sal_True;
1446 // this call is triggered by the parent and it will recognize the change of the state
1447 if ( m_pParent )
1448 m_pParent->m_bIsModified = sal_True;
1450 xStream = CreateMemoryStream( GetServiceFactory() );
1451 m_xCacheSeek.set( xStream, uno::UNO_QUERY_THROW );
1452 m_xCacheStream = xStream;
1454 else if ( !m_bHasInsertedStreamOptimization )
1456 if ( !m_aTempURL.getLength() && !m_xCacheStream.is() && !( m_xPackageStream->getDataStream().is() ) )
1458 // The stream does not exist in the storage
1459 m_bHasDataToFlush = sal_True;
1461 // this call is triggered by the parent and it will recognize the change of the state
1462 if ( m_pParent )
1463 m_pParent->m_bIsModified = sal_True;
1464 xStream = GetTempFileAsStream();
1467 // if the stream exists the temporary file is created on demand
1468 // xStream = GetTempFileAsStream();
1471 if ( !xStream.is() )
1472 m_pAntiImpl = new OWriteStream( this, bHierarchyAccess );
1473 else
1474 m_pAntiImpl = new OWriteStream( this, xStream, bHierarchyAccess );
1476 uno::Reference< io::XStream > xWriteStream =
1477 uno::Reference< io::XStream >( static_cast< ::cppu::OWeakObject* >( m_pAntiImpl ),
1478 uno::UNO_QUERY );
1480 OSL_ENSURE( xWriteStream.is(), "OWriteStream MUST implement XStream && XComponent interfaces!\n" );
1482 return xWriteStream;
1485 throw lang::IllegalArgumentException(); // TODO
1488 //-----------------------------------------------
1489 uno::Reference< io::XInputStream > OWriteStream_Impl::GetPlainRawInStream()
1491 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1493 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1495 // this method is used only internally, this stream object should not go outside of this implementation
1496 // if ( m_pAntiImpl )
1497 // throw io::IOException(); // TODO:
1499 return m_xPackageStream->getPlainRawStream();
1502 //-----------------------------------------------
1503 uno::Reference< io::XInputStream > OWriteStream_Impl::GetRawInStream()
1505 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1507 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1509 if ( m_pAntiImpl )
1510 throw io::IOException(); // TODO:
1512 OSL_ENSURE( IsEncrypted(), "Impossible to get raw representation for nonencrypted stream!\n" );
1513 if ( !IsEncrypted() )
1514 throw packages::NoEncryptionException();
1516 return m_xPackageStream->getRawStream();
1519 //-----------------------------------------------
1520 ::rtl::OUString OWriteStream_Impl::GetCommonRootPass()
1521 throw ( packages::NoEncryptionException )
1523 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1525 if ( m_nStorageType != PACKAGE_STORAGE || !m_pParent )
1526 throw packages::NoEncryptionException();
1528 return m_pParent->GetCommonRootPass();
1531 //-----------------------------------------------
1532 void OWriteStream_Impl::InputStreamDisposed( OInputCompStream* pStream )
1534 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1535 m_aInputStreamsList.remove( pStream );
1538 //-----------------------------------------------
1539 void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( const uno::Reference< io::XInputStream >& xDataToCopy, const uno::Sequence< beans::PropertyValue >& aProps, sal_Bool, uno::Reference< io::XStream >& xTargetStream )
1541 uno::Reference < io::XStream > xTempFile;
1542 if ( !xTargetStream.is() )
1543 xTempFile = uno::Reference < io::XStream >(
1544 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1545 uno::UNO_QUERY );
1546 else
1547 xTempFile = xTargetStream;
1549 uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY );
1550 if ( !xTempSeek.is() )
1551 throw uno::RuntimeException(); // TODO
1553 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
1554 if ( !xTempOut.is() )
1555 throw uno::RuntimeException();
1557 if ( xDataToCopy.is() )
1558 ::comphelper::OStorageHelper::CopyInputToOutput( xDataToCopy, xTempOut );
1560 xTempOut->closeOutput();
1561 xTempSeek->seek( 0 );
1563 uno::Reference< io::XInputStream > xInStream = xTempFile->getInputStream();
1564 if ( !xInStream.is() )
1565 throw io::IOException();
1567 // TODO: remember last state of m_bUseCommonPass
1568 if ( !xTargetStream.is() )
1569 xTargetStream = uno::Reference< io::XStream > (
1570 static_cast< ::cppu::OWeakObject* >(
1571 new OInputSeekStream( xInStream, InsertOwnProps( aProps, m_bUseCommonPass ), m_nStorageType ) ),
1572 uno::UNO_QUERY_THROW );
1575 //-----------------------------------------------
1576 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream )
1578 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1580 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1581 if ( !m_xPackageStream.is() )
1582 throw uno::RuntimeException();
1584 uno::Reference< io::XInputStream > xDataToCopy;
1585 if ( IsEncrypted() )
1587 // an encrypted stream must contain input stream
1588 ::rtl::OUString aGlobalPass;
1591 aGlobalPass = GetCommonRootPass();
1593 catch( packages::NoEncryptionException& aNoEncryptionException )
1595 AddLog( aNoEncryptionException.Message );
1596 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) );
1598 throw packages::WrongPasswordException();
1601 GetCopyOfLastCommit( xTargetStream, aGlobalPass );
1603 else
1605 xDataToCopy = m_xPackageStream->getDataStream();
1607 // in case of new inserted package stream it is possible that input stream still was not set
1608 GetStreamProperties();
1610 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonPass, xTargetStream );
1614 //-----------------------------------------------
1615 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream, const ::rtl::OUString& aPass )
1617 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1619 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1620 if ( !m_xPackageStream.is() )
1621 throw uno::RuntimeException();
1623 if ( !IsEncrypted() )
1624 throw packages::NoEncryptionException();
1626 uno::Reference< io::XInputStream > xDataToCopy;
1628 if ( m_bHasCachedPassword )
1630 // TODO: introduce last commited cashed password information and use it here
1631 // that means "use common pass" also should be remembered on flash
1632 uno::Sequence< sal_Int8 > aNewKey = ::package::MakeKeyFromPass( aPass, sal_True );
1633 uno::Sequence< sal_Int8 > aOldKey = ::package::MakeKeyFromPass( aPass, sal_False );
1635 uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY );
1636 if ( !xProps.is() )
1637 throw uno::RuntimeException();
1639 sal_Bool bEncr = sal_False;
1640 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ) ) >>= bEncr;
1641 if ( !bEncr )
1642 throw packages::NoEncryptionException();
1644 uno::Sequence< sal_Int8 > aEncrKey;
1645 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ) ) >>= aEncrKey;
1646 if ( !SequencesEqual( aNewKey, aEncrKey ) && !SequencesEqual( aOldKey, aEncrKey ) )
1647 throw packages::WrongPasswordException();
1649 // the correct key must be set already
1650 xDataToCopy = m_xPackageStream->getDataStream();
1652 else
1654 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1655 SetEncryptionKeyProperty_Impl( xPropertySet, ::package::MakeKeyFromPass( aPass, sal_True ) );
1657 try {
1658 xDataToCopy = m_xPackageStream->getDataStream();
1660 if ( !xDataToCopy.is() )
1662 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" );
1663 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1666 catch( packages::WrongPasswordException& aWrongPasswordException )
1668 SetEncryptionKeyProperty_Impl( xPropertySet, ::package::MakeKeyFromPass( aPass, sal_False ) );
1669 try {
1670 xDataToCopy = m_xPackageStream->getDataStream();
1672 if ( !xDataToCopy.is() )
1674 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" );
1675 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1676 AddLog( aWrongPasswordException.Message );
1677 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1678 throw;
1681 catch( uno::Exception& aException )
1683 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1684 AddLog( aException.Message );
1685 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1686 throw;
1689 catch( uno::Exception& aException )
1691 OSL_ENSURE( sal_False, "Can't open encrypted stream!\n" );
1692 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1693 AddLog( aException.Message );
1694 AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
1695 throw;
1698 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1701 // in case of new inserted package stream it is possible that input stream still was not set
1702 GetStreamProperties();
1704 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonPass, xTargetStream );
1707 //-----------------------------------------------
1708 void OWriteStream_Impl::CommitStreamRelInfo( const uno::Reference< embed::XStorage >& xRelStorage, const ::rtl::OUString& aOrigStreamName, const ::rtl::OUString& aNewStreamName )
1710 // at this point of time the old stream must be already cleaned
1711 OSL_ENSURE( m_nStorageType == OFOPXML_STORAGE, "The method should be used only with OFOPXML format!\n" );
1713 if ( m_nStorageType == OFOPXML_STORAGE )
1715 OSL_ENSURE( aOrigStreamName.getLength() && aNewStreamName.getLength() && xRelStorage.is(),
1716 "Wrong relation persistence information is provided!\n" );
1718 if ( !xRelStorage.is() || !aOrigStreamName.getLength() || !aNewStreamName.getLength() )
1719 throw uno::RuntimeException();
1721 if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN )
1722 throw io::IOException(); // TODO:
1724 ::rtl::OUString aOrigRelStreamName = aOrigStreamName;
1725 aOrigRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1727 ::rtl::OUString aNewRelStreamName = aNewStreamName;
1728 aNewRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1730 sal_Bool bRenamed = !aOrigRelStreamName.equals( aNewRelStreamName );
1731 if ( m_nRelInfoStatus == RELINFO_CHANGED
1732 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1733 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1735 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1736 xRelStorage->removeElement( aOrigRelStreamName );
1738 if ( m_nRelInfoStatus == RELINFO_CHANGED )
1740 if ( m_aNewRelInfo.getLength() )
1742 uno::Reference< io::XStream > xRelsStream =
1743 xRelStorage->openStreamElement( aNewRelStreamName,
1744 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1746 uno::Reference< io::XOutputStream > xOutStream = xRelsStream->getOutputStream();
1747 if ( !xOutStream.is() )
1748 throw uno::RuntimeException();
1750 ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence( xOutStream, m_aNewRelInfo, m_xFactory );
1752 // set the mediatype
1753 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1754 xPropSet->setPropertyValue(
1755 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1756 uno::makeAny( ::rtl::OUString(
1757 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1759 m_nRelInfoStatus = RELINFO_READ;
1762 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1763 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1765 uno::Reference< io::XStream > xRelsStream =
1766 xRelStorage->openStreamElement( aNewRelStreamName,
1767 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1769 uno::Reference< io::XOutputStream > xOutputStream = xRelsStream->getOutputStream();
1770 if ( !xOutputStream.is() )
1771 throw uno::RuntimeException();
1773 uno::Reference< io::XSeekable > xSeek( m_xNewRelInfoStream, uno::UNO_QUERY_THROW );
1774 xSeek->seek( 0 );
1775 ::comphelper::OStorageHelper::CopyInputToOutput( m_xNewRelInfoStream, xOutputStream );
1776 xSeek->seek( 0 );
1778 // set the mediatype
1779 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1780 xPropSet->setPropertyValue(
1781 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1782 uno::makeAny( ::rtl::OUString(
1783 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1785 if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1786 m_nRelInfoStatus = RELINFO_NO_INIT;
1787 else
1789 // the information is already parsed and the stream is stored, no need in temporary stream any more
1790 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1791 m_nRelInfoStatus = RELINFO_READ;
1795 // the original stream makes no sence after this step
1796 m_xOrigRelInfoStream = m_xNewRelInfoStream;
1797 m_aOrigRelInfo = m_aNewRelInfo;
1798 m_bOrigRelInfoBroken = sal_False;
1799 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1800 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1802 else
1804 // the stream is not changed but it might be renamed
1805 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1806 xRelStorage->renameElement( aOrigRelStreamName, aNewRelStreamName );
1811 //===============================================
1812 // OWriteStream implementation
1813 //===============================================
1815 //-----------------------------------------------
1816 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, sal_Bool bTransacted )
1817 : m_pImpl( pImpl )
1818 , m_bInStreamDisconnected( sal_False )
1819 , m_bInitOnDemand( sal_True )
1820 , m_nInitPosition( 0 )
1821 , m_bTransacted( bTransacted )
1823 OSL_ENSURE( pImpl, "No base implementation!\n" );
1824 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1826 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1827 throw uno::RuntimeException(); // just a disaster
1829 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1832 //-----------------------------------------------
1833 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, uno::Reference< io::XStream > xStream, sal_Bool bTransacted )
1834 : m_pImpl( pImpl )
1835 , m_bInStreamDisconnected( sal_False )
1836 , m_bInitOnDemand( sal_False )
1837 , m_nInitPosition( 0 )
1838 , m_bTransacted( bTransacted )
1840 OSL_ENSURE( pImpl && xStream.is(), "No base implementation!\n" );
1841 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1843 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1844 throw uno::RuntimeException(); // just a disaster
1846 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1848 if ( xStream.is() )
1850 m_xInStream = xStream->getInputStream();
1851 m_xOutStream = xStream->getOutputStream();
1852 m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
1853 OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!\n" );
1857 //-----------------------------------------------
1858 OWriteStream::~OWriteStream()
1861 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1862 if ( m_pImpl )
1864 m_refCount++;
1865 try {
1866 dispose();
1868 catch( uno::RuntimeException& aRuntimeException )
1870 m_pImpl->AddLog( aRuntimeException.Message );
1871 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1876 if ( m_pData && m_pData->m_pTypeCollection )
1877 delete m_pData->m_pTypeCollection;
1879 if ( m_pData )
1880 delete m_pData;
1883 //-----------------------------------------------
1884 void OWriteStream::DeInit()
1886 if ( !m_pImpl )
1887 return; // do nothing
1889 if ( m_xSeekable.is() )
1890 m_nInitPosition = m_xSeekable->getPosition();
1892 m_xInStream = uno::Reference< io::XInputStream >();
1893 m_xOutStream = uno::Reference< io::XOutputStream >();
1894 m_xSeekable = uno::Reference< io::XSeekable >();
1895 m_bInitOnDemand = sal_True;
1898 //-----------------------------------------------
1899 void OWriteStream::CheckInitOnDemand()
1901 if ( !m_pImpl )
1903 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
1904 throw lang::DisposedException();
1907 if ( m_bInitOnDemand )
1909 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
1910 uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
1911 if ( xStream.is() )
1913 m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
1914 m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
1915 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
1916 m_xSeekable->seek( m_nInitPosition );
1918 m_nInitPosition = 0;
1919 m_bInitOnDemand = sal_False;
1924 //-----------------------------------------------
1925 void OWriteStream::CopyToStreamInternally_Impl( const uno::Reference< io::XStream >& xDest )
1927 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1929 CheckInitOnDemand();
1931 if ( !m_xInStream.is() )
1932 throw uno::RuntimeException();
1934 if ( !m_xSeekable.is() )
1935 throw uno::RuntimeException();
1937 uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY );
1938 if ( !xDestProps.is() )
1939 throw uno::RuntimeException(); //TODO
1941 uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream();
1942 if ( !xDestOutStream.is() )
1943 throw io::IOException(); // TODO
1945 sal_Int64 nCurPos = m_xSeekable->getPosition();
1946 m_xSeekable->seek( 0 );
1948 uno::Exception eThrown;
1949 sal_Bool bThrown = sal_False;
1950 try {
1951 ::comphelper::OStorageHelper::CopyInputToOutput( m_xInStream, xDestOutStream );
1953 catch ( uno::Exception& e )
1955 eThrown = e;
1956 bThrown = sal_True;
1959 // position-related section below is critical
1960 // if it fails the stream will become invalid
1961 try {
1962 m_xSeekable->seek( nCurPos );
1964 catch ( uno::Exception& aException )
1966 m_pImpl->AddLog( aException.Message );
1967 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Quiet exception" ) ) );
1969 // TODO: set the stoream in invalid state or dispose
1970 OSL_ENSURE( sal_False, "The stream become invalid during copiing!\n" );
1971 throw uno::RuntimeException();
1974 if ( bThrown )
1975 throw eThrown;
1977 // now the properties can be copied
1978 // the order of the properties setting is not important for StorageStream API
1979 ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "Compressed" );
1980 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1981 if ( m_pData->m_nStorageType == PACKAGE_STORAGE || m_pData->m_nStorageType == OFOPXML_STORAGE )
1983 aPropName = ::rtl::OUString::createFromAscii( "MediaType" );
1984 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1986 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
1988 aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1989 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1994 //-----------------------------------------------
1995 void OWriteStream::ModifyParentUnlockMutex_Impl( ::osl::ResettableMutexGuard& aGuard )
1997 if ( m_pImpl->m_pParent )
1999 if ( m_pImpl->m_pParent->m_pAntiImpl )
2001 uno::Reference< util::XModifiable > xParentModif( (util::XModifiable*)(m_pImpl->m_pParent->m_pAntiImpl) );
2002 aGuard.clear();
2003 xParentModif->setModified( sal_True );
2005 else
2006 m_pImpl->m_pParent->m_bIsModified = sal_True;
2010 //-----------------------------------------------
2011 uno::Any SAL_CALL OWriteStream::queryInterface( const uno::Type& rType )
2012 throw( uno::RuntimeException )
2014 uno::Any aReturn;
2016 // common interfaces
2017 aReturn <<= ::cppu::queryInterface
2018 ( rType
2019 , static_cast<lang::XTypeProvider*> ( this )
2020 , static_cast<io::XInputStream*> ( this )
2021 , static_cast<io::XOutputStream*> ( this )
2022 , static_cast<io::XStream*> ( this )
2023 , static_cast<embed::XExtendedStorageStream*> ( this )
2024 , static_cast<io::XSeekable*> ( this )
2025 , static_cast<io::XTruncate*> ( this )
2026 , static_cast<lang::XComponent*> ( this )
2027 , static_cast<beans::XPropertySet*> ( this ) );
2029 if ( aReturn.hasValue() == sal_True )
2030 return aReturn ;
2032 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
2034 aReturn <<= ::cppu::queryInterface
2035 ( rType
2036 , static_cast<embed::XEncryptionProtectedSource*> ( this ) );
2038 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
2040 aReturn <<= ::cppu::queryInterface
2041 ( rType
2042 , static_cast<embed::XRelationshipAccess*> ( this ) );
2045 if ( aReturn.hasValue() == sal_True )
2046 return aReturn ;
2048 if ( m_bTransacted )
2050 aReturn <<= ::cppu::queryInterface
2051 ( rType
2052 , static_cast<embed::XTransactedObject*> ( this )
2053 , static_cast<embed::XTransactionBroadcaster*> ( this ) );
2055 if ( aReturn.hasValue() == sal_True )
2056 return aReturn ;
2059 return OWeakObject::queryInterface( rType );
2062 //-----------------------------------------------
2063 void SAL_CALL OWriteStream::acquire() throw()
2065 OWeakObject::acquire();
2068 //-----------------------------------------------
2069 void SAL_CALL OWriteStream::release() throw()
2071 OWeakObject::release();
2074 //-----------------------------------------------
2075 uno::Sequence< uno::Type > SAL_CALL OWriteStream::getTypes()
2076 throw( uno::RuntimeException )
2078 if ( m_pData->m_pTypeCollection == NULL )
2080 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2082 if ( m_pData->m_pTypeCollection == NULL )
2084 if ( m_bTransacted )
2086 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
2088 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2089 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2090 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2091 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2092 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2093 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2094 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2095 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2096 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
2097 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2098 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2099 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
2100 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2102 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
2104 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2105 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2106 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2107 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2108 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2109 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2110 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2111 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2112 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
2113 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2114 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2115 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
2116 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2118 else // if ( m_pData->m_nStorageType == ZIP_STORAGE )
2120 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2121 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2122 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2123 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2124 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2125 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2126 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2127 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2128 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
2129 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
2130 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
2131 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2134 else
2136 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
2138 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2139 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2140 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2141 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2142 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2143 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2144 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2145 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2146 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
2147 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2149 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
2151 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2152 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2153 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2154 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2155 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2156 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2157 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2158 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2159 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
2160 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2162 else // if ( m_pData->m_nStorageType == ZIP_STORAGE )
2164 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
2165 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
2166 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
2167 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
2168 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
2169 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
2170 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
2171 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
2172 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
2178 return m_pData->m_pTypeCollection->getTypes() ;
2181 //-----------------------------------------------
2182 uno::Sequence< sal_Int8 > SAL_CALL OWriteStream::getImplementationId()
2183 throw( uno::RuntimeException )
2185 static ::cppu::OImplementationId* pID = NULL ;
2187 if ( pID == NULL )
2189 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;
2191 if ( pID == NULL )
2193 static ::cppu::OImplementationId aID( sal_False ) ;
2194 pID = &aID ;
2198 return pID->getImplementationId() ;
2202 //-----------------------------------------------
2203 sal_Int32 SAL_CALL OWriteStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
2204 throw ( io::NotConnectedException,
2205 io::BufferSizeExceededException,
2206 io::IOException,
2207 uno::RuntimeException )
2209 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2211 CheckInitOnDemand();
2213 if ( !m_pImpl )
2215 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2216 throw lang::DisposedException();
2219 if ( !m_xInStream.is() )
2220 throw io::NotConnectedException();
2222 return m_xInStream->readBytes( aData, nBytesToRead );
2225 //-----------------------------------------------
2226 sal_Int32 SAL_CALL OWriteStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
2227 throw ( io::NotConnectedException,
2228 io::BufferSizeExceededException,
2229 io::IOException,
2230 uno::RuntimeException )
2232 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2234 CheckInitOnDemand();
2236 if ( !m_pImpl )
2238 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2239 throw lang::DisposedException();
2242 if ( !m_xInStream.is() )
2243 throw io::NotConnectedException();
2245 return m_xInStream->readSomeBytes( aData, nMaxBytesToRead );
2248 //-----------------------------------------------
2249 void SAL_CALL OWriteStream::skipBytes( sal_Int32 nBytesToSkip )
2250 throw ( io::NotConnectedException,
2251 io::BufferSizeExceededException,
2252 io::IOException,
2253 uno::RuntimeException )
2255 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2257 CheckInitOnDemand();
2259 if ( !m_pImpl )
2261 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2262 throw lang::DisposedException();
2265 if ( !m_xInStream.is() )
2266 throw io::NotConnectedException();
2268 m_xInStream->skipBytes( nBytesToSkip );
2271 //-----------------------------------------------
2272 sal_Int32 SAL_CALL OWriteStream::available( )
2273 throw ( io::NotConnectedException,
2274 io::IOException,
2275 uno::RuntimeException )
2277 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2279 CheckInitOnDemand();
2281 if ( !m_pImpl )
2283 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2284 throw lang::DisposedException();
2287 if ( !m_xInStream.is() )
2288 throw io::NotConnectedException();
2290 return m_xInStream->available();
2294 //-----------------------------------------------
2295 void SAL_CALL OWriteStream::closeInput( )
2296 throw ( io::NotConnectedException,
2297 io::IOException,
2298 uno::RuntimeException )
2300 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2302 if ( !m_pImpl )
2304 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2305 throw lang::DisposedException();
2308 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2309 throw io::NotConnectedException();
2311 // the input part of the stream stays open for internal purposes ( to allow reading during copiing )
2312 // since it can not be reopened until output part is closed, it will be closed with output part.
2313 m_bInStreamDisconnected = sal_True;
2314 // m_xInStream->closeInput();
2315 // m_xInStream = uno::Reference< io::XInputStream >();
2317 if ( !m_xOutStream.is() )
2318 dispose();
2321 //-----------------------------------------------
2322 uno::Reference< io::XInputStream > SAL_CALL OWriteStream::getInputStream()
2323 throw ( uno::RuntimeException )
2325 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2327 if ( !m_pImpl )
2329 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2330 throw lang::DisposedException();
2333 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2334 return uno::Reference< io::XInputStream >();
2336 return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ), uno::UNO_QUERY );
2339 //-----------------------------------------------
2340 uno::Reference< io::XOutputStream > SAL_CALL OWriteStream::getOutputStream()
2341 throw ( uno::RuntimeException )
2343 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2345 CheckInitOnDemand();
2347 if ( !m_pImpl )
2349 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2350 throw lang::DisposedException();
2353 if ( !m_xOutStream.is() )
2354 return uno::Reference< io::XOutputStream >();
2356 return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ), uno::UNO_QUERY );
2359 //-----------------------------------------------
2360 void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
2361 throw ( io::NotConnectedException,
2362 io::BufferSizeExceededException,
2363 io::IOException,
2364 uno::RuntimeException )
2366 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2368 // the write method makes initialization itself, since it depends from the aData length
2369 // NO CheckInitOnDemand()!
2371 if ( !m_pImpl )
2373 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2374 throw lang::DisposedException();
2377 if ( !m_bInitOnDemand )
2379 if ( !m_xOutStream.is() || !m_xSeekable.is())
2380 throw io::NotConnectedException();
2382 if ( m_pImpl->m_xCacheStream.is() )
2384 // check whether the cache should be turned off
2385 sal_Int64 nPos = m_xSeekable->getPosition();
2386 if ( nPos + aData.getLength() > MAX_STORCACHE_SIZE )
2388 // disconnect the cache and copy the data to the temporary file
2389 m_xSeekable->seek( 0 );
2391 // it is enough to copy the cached stream, the cache should already contain everything
2392 if ( m_pImpl->GetFilledTempFileIfNo( m_xInStream ).getLength() )
2394 DeInit();
2395 // the last position is known and it is differs from the current stream position
2396 m_nInitPosition = nPos;
2402 if ( m_bInitOnDemand )
2404 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
2405 uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
2406 if ( xStream.is() )
2408 m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
2409 m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
2410 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
2411 m_xSeekable->seek( m_nInitPosition );
2413 m_nInitPosition = 0;
2414 m_bInitOnDemand = sal_False;
2419 if ( !m_xOutStream.is() )
2420 throw io::NotConnectedException();
2422 m_xOutStream->writeBytes( aData );
2423 m_pImpl->m_bHasDataToFlush = sal_True;
2425 ModifyParentUnlockMutex_Impl( aGuard );
2428 //-----------------------------------------------
2429 void SAL_CALL OWriteStream::flush()
2430 throw ( io::NotConnectedException,
2431 io::BufferSizeExceededException,
2432 io::IOException,
2433 uno::RuntimeException )
2435 // In case stream is flushed it's current version becomes visible
2436 // to the parent storage. Usually parent storage flushes the stream
2437 // during own commit but a user can explicitly flush the stream
2438 // so the changes will be available through cloning functionality.
2440 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2442 if ( !m_pImpl )
2444 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2445 throw lang::DisposedException();
2448 if ( !m_bInitOnDemand )
2450 if ( !m_xOutStream.is() )
2451 throw io::NotConnectedException();
2453 m_xOutStream->flush();
2454 m_pImpl->Commit();
2458 //-----------------------------------------------
2459 void OWriteStream::CloseOutput_Impl()
2461 // all the checks must be done in calling method
2463 m_xOutStream->closeOutput();
2464 m_xOutStream = uno::Reference< io::XOutputStream >();
2466 if ( !m_bInitOnDemand )
2468 // after the stream is disposed it can be commited
2469 // so transport correct size property
2470 if ( !m_xSeekable.is() )
2471 throw uno::RuntimeException();
2473 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
2475 if ( m_pImpl->m_aProps[nInd].Name.equalsAscii( "Size" ) )
2476 m_pImpl->m_aProps[nInd].Value <<= ((sal_Int32)m_xSeekable->getLength());
2481 //-----------------------------------------------
2482 void SAL_CALL OWriteStream::closeOutput()
2483 throw ( io::NotConnectedException,
2484 io::BufferSizeExceededException,
2485 io::IOException,
2486 uno::RuntimeException )
2488 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2490 CheckInitOnDemand();
2492 if ( !m_pImpl )
2494 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2495 throw lang::DisposedException();
2498 if ( !m_xOutStream.is() )
2499 throw io::NotConnectedException();
2501 CloseOutput_Impl();
2503 if ( m_bInStreamDisconnected || !m_xInStream.is() )
2504 dispose();
2507 //-----------------------------------------------
2508 void SAL_CALL OWriteStream::seek( sal_Int64 location )
2509 throw ( lang::IllegalArgumentException,
2510 io::IOException,
2511 uno::RuntimeException )
2513 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2515 CheckInitOnDemand();
2517 if ( !m_pImpl )
2519 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2520 throw lang::DisposedException();
2523 if ( !m_xSeekable.is() )
2524 throw uno::RuntimeException();
2526 m_xSeekable->seek( location );
2529 //-----------------------------------------------
2530 sal_Int64 SAL_CALL OWriteStream::getPosition()
2531 throw ( io::IOException,
2532 uno::RuntimeException)
2534 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2536 CheckInitOnDemand();
2538 if ( !m_pImpl )
2540 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2541 throw lang::DisposedException();
2544 if ( !m_xSeekable.is() )
2545 throw uno::RuntimeException();
2547 return m_xSeekable->getPosition();
2550 //-----------------------------------------------
2551 sal_Int64 SAL_CALL OWriteStream::getLength()
2552 throw ( io::IOException,
2553 uno::RuntimeException )
2555 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2557 CheckInitOnDemand();
2559 if ( !m_pImpl )
2561 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2562 throw lang::DisposedException();
2565 if ( !m_xSeekable.is() )
2566 throw uno::RuntimeException();
2568 return m_xSeekable->getLength();
2571 //-----------------------------------------------
2572 void SAL_CALL OWriteStream::truncate()
2573 throw ( io::IOException,
2574 uno::RuntimeException )
2576 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2578 CheckInitOnDemand();
2580 if ( !m_pImpl )
2582 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2583 throw lang::DisposedException();
2586 if ( !m_xOutStream.is() )
2587 throw uno::RuntimeException();
2589 uno::Reference< io::XTruncate > xTruncate( m_xOutStream, uno::UNO_QUERY );
2591 if ( !xTruncate.is() )
2593 OSL_ENSURE( sal_False, "The output stream must support XTruncate interface!\n" );
2594 throw uno::RuntimeException();
2597 xTruncate->truncate();
2599 m_pImpl->m_bHasDataToFlush = sal_True;
2601 ModifyParentUnlockMutex_Impl( aGuard );
2604 //-----------------------------------------------
2605 void SAL_CALL OWriteStream::dispose()
2606 throw ( uno::RuntimeException )
2608 // should be an internal method since it can be called only from parent storage
2610 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2612 if ( !m_pImpl )
2614 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2615 throw lang::DisposedException();
2618 if ( m_xOutStream.is() )
2619 CloseOutput_Impl();
2621 if ( m_xInStream.is() )
2623 m_xInStream->closeInput();
2624 m_xInStream = uno::Reference< io::XInputStream >();
2627 m_pImpl->m_pAntiImpl = NULL;
2629 if ( !m_bInitOnDemand )
2633 if ( !m_bTransacted )
2635 m_pImpl->Commit();
2637 else
2639 // throw away all the changes
2640 m_pImpl->Revert();
2643 catch( uno::Exception& aException )
2645 m_pImpl->AddLog( aException.Message );
2646 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
2648 uno::Any aCaught( ::cppu::getCaughtException() );
2649 throw lang::WrappedTargetRuntimeException(
2650 ::rtl::OUString::createFromAscii( "Can not commit/revert the storage!\n" ),
2651 uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( this ),
2652 uno::UNO_QUERY ),
2653 aCaught );
2657 m_pImpl = NULL;
2660 // the listener might try to get rid of parent storage, and the storage would delete this object;
2661 // for now the listener is just notified at the end of the method to workaround the problem
2662 // in future a more elegant way should be found
2664 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
2665 m_pData->m_aListenersContainer.disposeAndClear( aSource );
2668 //-----------------------------------------------
2669 void SAL_CALL OWriteStream::addEventListener(
2670 const uno::Reference< lang::XEventListener >& xListener )
2671 throw ( uno::RuntimeException )
2673 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2675 if ( !m_pImpl )
2677 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2678 throw lang::DisposedException();
2681 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2682 xListener );
2685 //-----------------------------------------------
2686 void SAL_CALL OWriteStream::removeEventListener(
2687 const uno::Reference< lang::XEventListener >& xListener )
2688 throw ( uno::RuntimeException )
2690 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2692 if ( !m_pImpl )
2694 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2695 throw lang::DisposedException();
2698 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2699 xListener );
2702 //-----------------------------------------------
2703 void SAL_CALL OWriteStream::setEncryptionPassword( const ::rtl::OUString& aPass )
2704 throw ( uno::RuntimeException,
2705 io::IOException )
2707 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2709 CheckInitOnDemand();
2711 if ( !m_pImpl )
2713 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2714 throw lang::DisposedException();
2717 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2719 m_pImpl->SetEncryptedWithPass( aPass );
2721 ModifyParentUnlockMutex_Impl( aGuard );
2724 //-----------------------------------------------
2725 void SAL_CALL OWriteStream::removeEncryption()
2726 throw ( uno::RuntimeException,
2727 io::IOException )
2729 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2731 CheckInitOnDemand();
2733 if ( !m_pImpl )
2735 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2736 throw lang::DisposedException();
2739 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2741 m_pImpl->SetDecrypted();
2743 ModifyParentUnlockMutex_Impl( aGuard );
2746 //-----------------------------------------------
2747 sal_Bool SAL_CALL OWriteStream::hasByID( const ::rtl::OUString& sID )
2748 throw ( io::IOException,
2749 uno::RuntimeException )
2751 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2753 if ( !m_pImpl )
2755 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2756 throw lang::DisposedException();
2759 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2760 throw uno::RuntimeException();
2764 getRelationshipByID( sID );
2765 return sal_True;
2767 catch( container::NoSuchElementException& aNoSuchElementException )
2769 m_pImpl->AddLog( aNoSuchElementException.Message );
2770 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No Element" ) ) );
2773 return sal_False;
2776 //-----------------------------------------------
2777 ::rtl::OUString SAL_CALL OWriteStream::getTargetByID( const ::rtl::OUString& sID )
2778 throw ( container::NoSuchElementException,
2779 io::IOException,
2780 uno::RuntimeException )
2782 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2784 if ( !m_pImpl )
2786 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2787 throw lang::DisposedException();
2790 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2791 throw uno::RuntimeException();
2793 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2794 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2795 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Target" ) ) )
2796 return aSeq[nInd].Second;
2798 return ::rtl::OUString();
2801 //-----------------------------------------------
2802 ::rtl::OUString SAL_CALL OWriteStream::getTypeByID( const ::rtl::OUString& sID )
2803 throw ( container::NoSuchElementException,
2804 io::IOException,
2805 uno::RuntimeException )
2807 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2809 if ( !m_pImpl )
2811 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2812 throw lang::DisposedException();
2815 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2816 throw uno::RuntimeException();
2818 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2819 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2820 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2821 return aSeq[nInd].Second;
2823 return ::rtl::OUString();
2826 //-----------------------------------------------
2827 uno::Sequence< beans::StringPair > SAL_CALL OWriteStream::getRelationshipByID( const ::rtl::OUString& sID )
2828 throw ( container::NoSuchElementException,
2829 io::IOException,
2830 uno::RuntimeException )
2832 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2834 if ( !m_pImpl )
2836 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2837 throw lang::DisposedException();
2840 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2841 throw uno::RuntimeException();
2843 // TODO/LATER: in future the unification of the ID could be checked
2844 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2845 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2846 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2847 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2849 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2850 return aSeq[nInd1];
2851 break;
2854 throw container::NoSuchElementException();
2857 //-----------------------------------------------
2858 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getRelationshipsByType( const ::rtl::OUString& sType )
2859 throw ( io::IOException,
2860 uno::RuntimeException )
2862 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2864 if ( !m_pImpl )
2866 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2867 throw lang::DisposedException();
2870 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2871 throw uno::RuntimeException();
2873 uno::Sequence< uno::Sequence< beans::StringPair > > aResult;
2874 sal_Int32 nEntriesNum = 0;
2876 // TODO/LATER: in future the unification of the ID could be checked
2877 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2878 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2879 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2880 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2882 if ( aSeq[nInd1][nInd2].Second.equals( sType ) )
2884 aResult.realloc( nEntriesNum );
2885 aResult[nEntriesNum-1] = aSeq[nInd1];
2887 break;
2890 return aResult;
2893 //-----------------------------------------------
2894 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getAllRelationships()
2895 throw (io::IOException, uno::RuntimeException)
2897 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2899 if ( !m_pImpl )
2901 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2902 throw lang::DisposedException();
2905 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2906 throw uno::RuntimeException();
2908 return m_pImpl->GetAllRelationshipsIfAny();
2911 //-----------------------------------------------
2912 void SAL_CALL OWriteStream::insertRelationshipByID( const ::rtl::OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, ::sal_Bool bReplace )
2913 throw ( container::ElementExistException,
2914 io::IOException,
2915 uno::RuntimeException )
2917 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2919 if ( !m_pImpl )
2921 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2922 throw lang::DisposedException();
2925 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2926 throw uno::RuntimeException();
2928 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
2930 sal_Int32 nIDInd = -1;
2932 // TODO/LATER: in future the unification of the ID could be checked
2933 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2934 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2935 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2936 if ( aSeq[nInd1][nInd2].First.equals( aIDTag ) )
2938 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2939 nIDInd = nInd1;
2941 break;
2944 if ( nIDInd == -1 || bReplace )
2946 if ( nIDInd == -1 )
2948 nIDInd = aSeq.getLength();
2949 aSeq.realloc( nIDInd + 1 );
2952 aSeq[nIDInd].realloc( aEntry.getLength() + 1 );
2954 aSeq[nIDInd][0].First = aIDTag;
2955 aSeq[nIDInd][0].Second = sID;
2956 sal_Int32 nIndTarget = 1;
2957 for ( sal_Int32 nIndOrig = 0;
2958 nIndOrig < aEntry.getLength();
2959 nIndOrig++ )
2961 if ( !aEntry[nIndOrig].First.equals( aIDTag ) )
2962 aSeq[nIDInd][nIndTarget++] = aEntry[nIndOrig];
2965 aSeq[nIDInd].realloc( nIndTarget );
2967 else
2968 throw container::ElementExistException(); // TODO
2971 m_pImpl->m_aNewRelInfo = aSeq;
2972 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2973 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2976 //-----------------------------------------------
2977 void SAL_CALL OWriteStream::removeRelationshipByID( const ::rtl::OUString& sID )
2978 throw ( container::NoSuchElementException,
2979 io::IOException,
2980 uno::RuntimeException )
2982 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2984 if ( !m_pImpl )
2986 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
2987 throw lang::DisposedException();
2990 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2991 throw uno::RuntimeException();
2993 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2994 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2995 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2996 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2998 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
3000 sal_Int32 nLength = aSeq.getLength();
3001 aSeq[nInd1] = aSeq[nLength-1];
3002 aSeq.realloc( nLength - 1 );
3004 m_pImpl->m_aNewRelInfo = aSeq;
3005 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
3006 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
3008 // TODO/LATER: in future the unification of the ID could be checked
3009 return;
3012 break;
3015 throw container::NoSuchElementException();
3018 //-----------------------------------------------
3019 void SAL_CALL OWriteStream::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, ::sal_Bool bReplace )
3020 throw ( container::ElementExistException,
3021 io::IOException,
3022 uno::RuntimeException )
3024 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3026 if ( !m_pImpl )
3028 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3029 throw lang::DisposedException();
3032 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
3033 throw uno::RuntimeException();
3035 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
3036 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
3037 uno::Sequence< uno::Sequence< beans::StringPair > > aResultSeq( aSeq.getLength() + aEntries.getLength() );
3038 sal_Int32 nResultInd = 0;
3040 for ( sal_Int32 nIndTarget1 = 0; nIndTarget1 < aSeq.getLength(); nIndTarget1++ )
3041 for ( sal_Int32 nIndTarget2 = 0; nIndTarget2 < aSeq[nIndTarget1].getLength(); nIndTarget2++ )
3042 if ( aSeq[nIndTarget1][nIndTarget2].First.equals( aIDTag ) )
3044 sal_Int32 nIndSourceSame = -1;
3046 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
3047 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
3049 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
3051 if ( aEntries[nIndSource1][nIndSource2].Second.equals( aSeq[nIndTarget1][nIndTarget2].Second ) )
3053 if ( !bReplace )
3054 throw container::ElementExistException();
3056 nIndSourceSame = nIndSource1;
3059 break;
3063 if ( nIndSourceSame == -1 )
3065 // no such element in the provided sequence
3066 aResultSeq[nResultInd++] = aSeq[nIndTarget1];
3069 break;
3072 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
3074 aResultSeq[nResultInd].realloc( aEntries[nIndSource1].getLength() );
3075 sal_Bool bHasID = sal_False;
3076 sal_Int32 nResInd2 = 1;
3078 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
3079 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
3081 aResultSeq[nResultInd][0] = aEntries[nIndSource1][nIndSource2];
3082 bHasID = sal_True;
3084 else if ( nResInd2 < aResultSeq[nResultInd].getLength() )
3085 aResultSeq[nResultInd][nResInd2++] = aEntries[nIndSource1][nIndSource2];
3086 else
3087 throw io::IOException(); // TODO: illegal relation ( no ID )
3089 if ( !bHasID )
3090 throw io::IOException(); // TODO: illegal relations
3092 nResultInd++;
3095 aResultSeq.realloc( nResultInd );
3096 m_pImpl->m_aNewRelInfo = aResultSeq;
3097 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
3098 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
3101 //-----------------------------------------------
3102 void SAL_CALL OWriteStream::clearRelationships()
3103 throw ( io::IOException,
3104 uno::RuntimeException )
3106 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3108 if ( !m_pImpl )
3110 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3111 throw lang::DisposedException();
3114 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
3115 throw uno::RuntimeException();
3117 m_pImpl->m_aNewRelInfo.realloc( 0 );
3118 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
3119 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
3122 //-----------------------------------------------
3123 uno::Reference< beans::XPropertySetInfo > SAL_CALL OWriteStream::getPropertySetInfo()
3124 throw ( uno::RuntimeException )
3126 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3128 //TODO:
3129 return uno::Reference< beans::XPropertySetInfo >();
3132 //-----------------------------------------------
3133 void SAL_CALL OWriteStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
3134 throw ( beans::UnknownPropertyException,
3135 beans::PropertyVetoException,
3136 lang::IllegalArgumentException,
3137 lang::WrappedTargetException,
3138 uno::RuntimeException )
3140 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3142 if ( !m_pImpl )
3144 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3145 throw lang::DisposedException();
3148 m_pImpl->GetStreamProperties();
3149 ::rtl::OUString aCompressedString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
3150 ::rtl::OUString aMediaTypeString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
3151 if ( m_pData->m_nStorageType == PACKAGE_STORAGE && aPropertyName.equals( aMediaTypeString ) )
3153 // if the "Compressed" property is not set explicitly, the MediaType can change the default value
3154 sal_Bool bCompressedValueFromType = sal_True;
3155 ::rtl::OUString aType;
3156 aValue >>= aType;
3158 if ( !m_pImpl->m_bCompressedSetExplicit )
3160 if ( aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/jpeg" ) ) )
3161 || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/png" ) ) )
3162 || aType.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "image/gif" ) ) ) )
3163 bCompressedValueFromType = sal_False;
3166 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3168 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3169 m_pImpl->m_aProps[nInd].Value = aValue;
3170 else if ( !m_pImpl->m_bCompressedSetExplicit && aCompressedString.equals( m_pImpl->m_aProps[nInd].Name ) )
3171 m_pImpl->m_aProps[nInd].Value <<= bCompressedValueFromType;
3174 else if ( aPropertyName.equals( aCompressedString ) )
3176 // if the "Compressed" property is not set explicitly, the MediaType can change the default value
3177 m_pImpl->m_bCompressedSetExplicit = sal_True;
3178 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3180 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3181 m_pImpl->m_aProps[nInd].Value = aValue;
3184 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
3185 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
3187 sal_Bool bUseCommonPass = sal_False;
3188 if ( aValue >>= bUseCommonPass )
3190 if ( m_bInitOnDemand && m_pImpl->m_bHasInsertedStreamOptimization )
3192 // the data stream is provided to the packagestream directly
3193 m_pImpl->m_bUseCommonPass = bUseCommonPass;
3195 else if ( bUseCommonPass )
3197 if ( !m_pImpl->m_bUseCommonPass )
3199 m_pImpl->SetDecrypted();
3200 m_pImpl->m_bUseCommonPass = sal_True;
3203 else
3204 m_pImpl->m_bUseCommonPass = sal_False;
3206 else
3207 throw lang::IllegalArgumentException(); //TODO
3209 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE && aPropertyName.equals( aMediaTypeString ) )
3211 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3213 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3214 m_pImpl->m_aProps[nInd].Value = aValue;
3217 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE && aPropertyName.equalsAscii( "RelationsInfoStream" ) )
3219 uno::Reference< io::XInputStream > xInRelStream;
3220 if ( ( aValue >>= xInRelStream ) && xInRelStream.is() )
3222 uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY );
3223 if ( !xSeek.is() )
3225 // currently this is an internal property that is used for optimization
3226 // and the stream must support XSeekable interface
3227 // TODO/LATER: in future it can be changed if property is used from outside
3228 throw lang::IllegalArgumentException(); // TODO
3231 m_pImpl->m_xNewRelInfoStream = xInRelStream;
3232 m_pImpl->m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
3233 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM;
3235 else
3236 throw lang::IllegalArgumentException(); // TODO
3238 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE && aPropertyName.equalsAscii( "RelationsInfo" ) )
3240 if ( aValue >>= m_pImpl->m_aNewRelInfo )
3243 else
3244 throw lang::IllegalArgumentException(); // TODO
3246 else if ( aPropertyName.equalsAscii( "Size" ) )
3247 throw beans::PropertyVetoException(); // TODO
3248 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
3249 && ( aPropertyName.equalsAscii( "IsEncrypted" ) || aPropertyName.equalsAscii( "Encrypted" ) ) )
3250 throw beans::PropertyVetoException(); // TODO
3251 else
3252 throw beans::UnknownPropertyException(); // TODO
3254 m_pImpl->m_bHasDataToFlush = sal_True;
3255 ModifyParentUnlockMutex_Impl( aGuard );
3259 //-----------------------------------------------
3260 uno::Any SAL_CALL OWriteStream::getPropertyValue( const ::rtl::OUString& aProp )
3261 throw ( beans::UnknownPropertyException,
3262 lang::WrappedTargetException,
3263 uno::RuntimeException )
3265 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3267 if ( !m_pImpl )
3269 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3270 throw lang::DisposedException();
3273 if ( aProp.equalsAscii( "RelId" ) )
3275 return uno::makeAny( m_pImpl->GetNewRelId() );
3278 ::rtl::OUString aPropertyName;
3279 if ( aProp.equalsAscii( "IsEncrypted" ) )
3280 aPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) );
3281 else
3282 aPropertyName = aProp;
3284 if ( ( ( m_pData->m_nStorageType == PACKAGE_STORAGE || m_pData->m_nStorageType == OFOPXML_STORAGE )
3285 && aPropertyName.equalsAscii( "MediaType" ) )
3286 || m_pData->m_nStorageType == PACKAGE_STORAGE && aPropertyName.equalsAscii( "Encrypted" )
3287 || aPropertyName.equalsAscii( "Compressed" ) )
3289 m_pImpl->GetStreamProperties();
3291 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
3293 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
3294 return m_pImpl->m_aProps[nInd].Value;
3297 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
3298 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
3299 return uno::makeAny( m_pImpl->m_bUseCommonPass );
3300 else if ( aPropertyName.equalsAscii( "Size" ) )
3302 CheckInitOnDemand();
3304 if ( !m_xSeekable.is() )
3305 throw uno::RuntimeException();
3307 return uno::makeAny( (sal_Int32)m_xSeekable->getLength() );
3310 throw beans::UnknownPropertyException(); // TODO
3314 //-----------------------------------------------
3315 void SAL_CALL OWriteStream::addPropertyChangeListener(
3316 const ::rtl::OUString& /*aPropertyName*/,
3317 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
3318 throw ( beans::UnknownPropertyException,
3319 lang::WrappedTargetException,
3320 uno::RuntimeException )
3322 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3324 if ( !m_pImpl )
3326 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3327 throw lang::DisposedException();
3330 //TODO:
3334 //-----------------------------------------------
3335 void SAL_CALL OWriteStream::removePropertyChangeListener(
3336 const ::rtl::OUString& /*aPropertyName*/,
3337 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
3338 throw ( beans::UnknownPropertyException,
3339 lang::WrappedTargetException,
3340 uno::RuntimeException )
3342 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3344 if ( !m_pImpl )
3346 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3347 throw lang::DisposedException();
3350 //TODO:
3354 //-----------------------------------------------
3355 void SAL_CALL OWriteStream::addVetoableChangeListener(
3356 const ::rtl::OUString& /*PropertyName*/,
3357 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
3358 throw ( beans::UnknownPropertyException,
3359 lang::WrappedTargetException,
3360 uno::RuntimeException )
3362 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3364 if ( !m_pImpl )
3366 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3367 throw lang::DisposedException();
3370 //TODO:
3374 //-----------------------------------------------
3375 void SAL_CALL OWriteStream::removeVetoableChangeListener(
3376 const ::rtl::OUString& /*PropertyName*/,
3377 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
3378 throw ( beans::UnknownPropertyException,
3379 lang::WrappedTargetException,
3380 uno::RuntimeException )
3382 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3384 if ( !m_pImpl )
3386 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3387 throw lang::DisposedException();
3390 //TODO:
3393 //____________________________________________________________________________________________________
3394 // XTransactedObject
3395 //____________________________________________________________________________________________________
3397 //-----------------------------------------------
3398 void OWriteStream::BroadcastTransaction( sal_Int8 nMessage )
3400 1 - preCommit
3401 2 - commited
3402 3 - preRevert
3403 4 - reverted
3406 // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
3407 if ( !m_pImpl )
3409 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3410 throw lang::DisposedException();
3413 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
3415 ::cppu::OInterfaceContainerHelper* pContainer =
3416 m_pData->m_aListenersContainer.getContainer(
3417 ::getCppuType( ( const uno::Reference< embed::XTransactionListener >*) NULL ) );
3418 if ( pContainer )
3420 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
3421 while ( pIterator.hasMoreElements( ) )
3423 OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!\n" );
3425 switch( nMessage )
3427 case STOR_MESS_PRECOMMIT:
3428 ( ( embed::XTransactionListener* )pIterator.next( ) )->preCommit( aSource );
3429 break;
3430 case STOR_MESS_COMMITED:
3431 ( ( embed::XTransactionListener* )pIterator.next( ) )->commited( aSource );
3432 break;
3433 case STOR_MESS_PREREVERT:
3434 ( ( embed::XTransactionListener* )pIterator.next( ) )->preRevert( aSource );
3435 break;
3436 case STOR_MESS_REVERTED:
3437 ( ( embed::XTransactionListener* )pIterator.next( ) )->reverted( aSource );
3438 break;
3443 //-----------------------------------------------
3444 void SAL_CALL OWriteStream::commit()
3445 throw ( io::IOException,
3446 embed::StorageWrappedTargetException,
3447 uno::RuntimeException )
3449 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::commit" );
3451 if ( !m_pImpl )
3453 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3454 throw lang::DisposedException();
3457 if ( !m_bTransacted )
3458 throw uno::RuntimeException();
3460 try {
3461 BroadcastTransaction( STOR_MESS_PRECOMMIT );
3463 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3465 if ( !m_pImpl )
3467 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3468 throw lang::DisposedException();
3471 m_pImpl->Commit();
3473 // when the storage is commited the parent is modified
3474 ModifyParentUnlockMutex_Impl( aGuard );
3476 catch( io::IOException& aIOException )
3478 m_pImpl->AddLog( aIOException.Message );
3479 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3480 throw;
3482 catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException )
3484 m_pImpl->AddLog( aStorageWrappedTargetException.Message );
3485 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3486 throw;
3488 catch( uno::RuntimeException& aRuntimeException )
3490 m_pImpl->AddLog( aRuntimeException.Message );
3491 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3492 throw;
3494 catch( uno::Exception& aException )
3496 m_pImpl->AddLog( aException.Message );
3497 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3499 uno::Any aCaught( ::cppu::getCaughtException() );
3500 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on commit!" ),
3501 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3502 aCaught );
3505 BroadcastTransaction( STOR_MESS_COMMITED );
3508 //-----------------------------------------------
3509 void SAL_CALL OWriteStream::revert()
3510 throw ( io::IOException,
3511 embed::StorageWrappedTargetException,
3512 uno::RuntimeException )
3514 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::revert" );
3516 // the method removes all the changes done after last commit
3518 if ( !m_pImpl )
3520 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3521 throw lang::DisposedException();
3524 if ( !m_bTransacted )
3525 throw uno::RuntimeException();
3527 BroadcastTransaction( STOR_MESS_PREREVERT );
3529 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3531 if ( !m_pImpl )
3533 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3534 throw lang::DisposedException();
3537 try {
3538 m_pImpl->Revert();
3540 catch( io::IOException& aIOException )
3542 m_pImpl->AddLog( aIOException.Message );
3543 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3544 throw;
3546 catch( embed::StorageWrappedTargetException& aStorageWrappedTargetException )
3548 m_pImpl->AddLog( aStorageWrappedTargetException.Message );
3549 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3550 throw;
3552 catch( uno::RuntimeException& aRuntimeException )
3554 m_pImpl->AddLog( aRuntimeException.Message );
3555 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3556 throw;
3558 catch( uno::Exception& aException )
3560 m_pImpl->AddLog( aException.Message );
3561 m_pImpl->AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Rethrow" ) ) );
3563 uno::Any aCaught( ::cppu::getCaughtException() );
3564 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on revert!" ),
3565 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3566 aCaught );
3569 aGuard.clear();
3571 BroadcastTransaction( STOR_MESS_REVERTED );
3574 //____________________________________________________________________________________________________
3575 // XTransactionBroadcaster
3576 //____________________________________________________________________________________________________
3578 //-----------------------------------------------
3579 void SAL_CALL OWriteStream::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3580 throw ( uno::RuntimeException )
3582 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3584 if ( !m_pImpl )
3586 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3587 throw lang::DisposedException();
3590 if ( !m_bTransacted )
3591 throw uno::RuntimeException();
3593 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3594 aListener );
3597 //-----------------------------------------------
3598 void SAL_CALL OWriteStream::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3599 throw ( uno::RuntimeException )
3601 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3603 if ( !m_pImpl )
3605 ::package::StaticAddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Disposed!" ) ) );
3606 throw lang::DisposedException();
3609 if ( !m_bTransacted )
3610 throw uno::RuntimeException();
3612 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3613 aListener );