fix toolbar import
[ooovba.git] / package / source / xstor / owriteablestream.cxx
blob21f6e5499628b5b1c786e15e6c2ff1bacc14e55b
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 #ifndef _COMPHELPER_PROCESSFACTORY_HXX
47 #include <comphelper/processfactory.hxx>
48 #endif
50 #include <comphelper/storagehelper.hxx>
51 #include <comphelper/ofopxmlhelper.hxx>
53 #include "owriteablestream.hxx"
54 #include "oseekinstream.hxx"
55 #include "mutexholder.hxx"
56 #include "xstorage.hxx"
58 #include <rtl/digest.h>
59 #include <rtl/logfile.hxx>
62 using namespace ::com::sun::star;
64 //-----------------------------------------------
65 void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet,
66 const uno::Sequence< sal_Int8 >& aKey )
68 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
69 if ( !xPropertySet.is() )
70 throw uno::RuntimeException();
72 ::rtl::OUString aString_EncryptionKey = ::rtl::OUString::createFromAscii( "EncryptionKey" );
73 try {
74 xPropertySet->setPropertyValue( aString_EncryptionKey, uno::makeAny( aKey ) );
76 catch ( uno::Exception& )
78 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
79 throw io::IOException(); // TODO
83 //-----------------------------------------------
84 uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet )
86 OSL_ENSURE( xPropertySet.is(), "No property set is provided!\n" );
87 if ( !xPropertySet.is() )
88 throw uno::RuntimeException();
90 ::rtl::OUString aString_EncryptionKey = ::rtl::OUString::createFromAscii( "EncryptionKey" );
91 try {
92 return xPropertySet->getPropertyValue( aString_EncryptionKey );
94 catch ( uno::Exception& )
96 OSL_ENSURE( sal_False, "Can't get encryption related properties!\n" );
97 throw io::IOException(); // TODO
101 //-----------------------------------------------
102 sal_Bool SequencesEqual( uno::Sequence< sal_Int8 > aSequence1, uno::Sequence< sal_Int8 > aSequence2 )
104 if ( aSequence1.getLength() != aSequence2.getLength() )
105 return sal_False;
107 for ( sal_Int32 nInd = 0; nInd < aSequence1.getLength(); nInd++ )
108 if ( aSequence1[nInd] != aSequence2[nInd] )
109 return sal_False;
111 return sal_True;
114 //-----------------------------------------------
115 sal_Bool KillFile( const ::rtl::OUString& aURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory )
117 if ( !xFactory.is() )
118 return sal_False;
120 sal_Bool bRet = sal_False;
124 uno::Reference < ucb::XSimpleFileAccess > xAccess(
125 xFactory->createInstance (
126 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
127 uno::UNO_QUERY );
129 if ( xAccess.is() )
131 xAccess->kill( aURL );
132 bRet = sal_True;
135 catch( uno::Exception& )
139 return bRet;
142 const sal_Int32 n_ConstBufferSize = 32000;
144 //-----------------------------------------------
146 ::rtl::OUString GetNewTempFileURL( const uno::Reference< lang::XMultiServiceFactory > xFactory )
148 ::rtl::OUString aTempURL;
150 uno::Reference < beans::XPropertySet > xTempFile(
151 xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
152 uno::UNO_QUERY );
154 if ( !xTempFile.is() )
155 throw uno::RuntimeException(); // TODO
157 try {
158 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), uno::makeAny( sal_False ) );
159 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
160 aUrl >>= aTempURL;
162 catch ( uno::Exception& )
166 if ( !aTempURL.getLength() )
167 throw uno::RuntimeException(); // TODO: can not create tempfile
169 return aTempURL;
172 uno::Sequence< sal_Int8 > MakeKeyFromPass( ::rtl::OUString aPass, sal_Bool bUseUTF )
174 // MS_1252 encoding was used for SO60 document format password encoding,
175 // this encoding supports only a minor subset of nonascii characters,
176 // but for compatibility reasons it has to be used for old document formats
178 ::rtl::OString aByteStrPass;
179 if ( bUseUTF )
180 aByteStrPass = ::rtl::OUStringToOString( aPass, RTL_TEXTENCODING_UTF8 );
181 else
182 aByteStrPass = ::rtl::OUStringToOString( aPass, RTL_TEXTENCODING_MS_1252 );
184 sal_uInt8 pBuffer[RTL_DIGEST_LENGTH_SHA1];
185 rtlDigestError nError = rtl_digest_SHA1( aByteStrPass.getStr(),
186 aByteStrPass.getLength(),
187 pBuffer,
188 RTL_DIGEST_LENGTH_SHA1 );
190 if ( nError != rtl_Digest_E_None )
191 throw uno::RuntimeException();
193 return uno::Sequence< sal_Int8 >( (sal_Int8*)pBuffer, RTL_DIGEST_LENGTH_SHA1 );
197 // ================================================================
199 //-----------------------------------------------
200 OWriteStream_Impl::OWriteStream_Impl( OStorage_Impl* pParent,
201 const uno::Reference< packages::XDataSinkEncrSupport >& xPackageStream,
202 const uno::Reference< lang::XSingleServiceFactory >& xPackage,
203 const uno::Reference< lang::XMultiServiceFactory >& xFactory,
204 sal_Bool bForceEncrypted,
205 sal_Int16 nStorageType,
206 const uno::Reference< io::XInputStream >& xRelInfoStream )
207 : m_pAntiImpl( NULL )
208 , m_bHasDataToFlush( sal_False )
209 , m_bFlushed( sal_False )
210 , m_xPackageStream( xPackageStream )
211 , m_xFactory( xFactory )
212 , m_pParent( pParent )
213 , m_bForceEncrypted( bForceEncrypted )
214 , m_bUseCommonPass( !bForceEncrypted && nStorageType == PACKAGE_STORAGE )
215 , m_bHasCachedPassword( sal_False )
216 , m_xPackage( xPackage )
217 , m_bHasInsertedStreamOptimization( sal_False )
218 , m_nStorageType( nStorageType )
219 , m_xOrigRelInfoStream( xRelInfoStream )
220 , m_bOrigRelInfoBroken( sal_False )
221 , m_nRelInfoStatus( RELINFO_NO_INIT )
222 , m_nRelId( 1 )
224 OSL_ENSURE( xPackageStream.is(), "No package stream is provided!\n" );
225 OSL_ENSURE( xPackage.is(), "No package component is provided!\n" );
226 OSL_ENSURE( m_xFactory.is(), "No package stream is provided!\n" );
227 OSL_ENSURE( pParent, "No parent storage is provided!\n" );
228 OSL_ENSURE( m_nStorageType == OFOPXML_STORAGE || !m_xOrigRelInfoStream.is(), "The Relations info makes sence only for OFOPXML format!\n" );
231 //-----------------------------------------------
232 OWriteStream_Impl::~OWriteStream_Impl()
234 DisposeWrappers();
236 if ( m_aTempURL.getLength() )
238 KillFile( m_aTempURL, GetServiceFactory() );
239 m_aTempURL = ::rtl::OUString();
243 //-----------------------------------------------
244 void OWriteStream_Impl::InsertIntoPackageFolder( const ::rtl::OUString& aName,
245 const uno::Reference< container::XNameContainer >& xParentPackageFolder )
247 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
249 OSL_ENSURE( m_bFlushed, "This method must not be called for nonflushed streams!\n" );
250 if ( m_bFlushed )
252 OSL_ENSURE( m_xPackageStream.is(), "An inserted stream is incomplete!\n" );
253 uno::Reference< lang::XUnoTunnel > xTunnel( m_xPackageStream, uno::UNO_QUERY );
254 if ( !xTunnel.is() )
255 throw uno::RuntimeException(); // TODO
257 xParentPackageFolder->insertByName( aName, uno::makeAny( xTunnel ) );
259 m_bFlushed = sal_False;
260 m_bHasInsertedStreamOptimization = sal_False;
263 //-----------------------------------------------
264 sal_Bool OWriteStream_Impl::IsEncrypted()
266 if ( m_nStorageType != PACKAGE_STORAGE )
267 return sal_False;
269 if ( m_bForceEncrypted || m_bHasCachedPassword )
270 return sal_True;
272 if ( m_aTempURL.getLength() )
273 return sal_False;
275 GetStreamProperties();
277 // the following value can not be cached since it can change after root commit
278 sal_Bool bWasEncr = sal_False;
279 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
280 if ( xPropSet.is() )
282 uno::Any aValue = xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "WasEncrypted" ) );
283 if ( !( aValue >>= bWasEncr ) )
285 OSL_ENSURE( sal_False, "The property WasEncrypted has wrong type!\n" );
289 sal_Bool bToBeEncr = sal_False;
290 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
292 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
294 if ( !( m_aProps[nInd].Value >>= bToBeEncr ) )
296 OSL_ENSURE( sal_False, "The property has wrong type!\n" );
301 // since a new key set to the package stream it should not be removed except the case when
302 // the stream becomes nonencrypted
303 uno::Sequence< sal_Int8 > aKey;
304 if ( bToBeEncr )
305 GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey;
307 // If the properties must be investigated the stream is either
308 // was never changed or was changed, the parent was commited
309 // and the stream was closed.
310 // That means that if it is intended to use common storage key
311 // it is already has no encryption but is marked to be stored
312 // encrypted and the key is empty.
313 if ( !bWasEncr && bToBeEncr && !aKey.getLength() )
315 // the stream is intended to use common storage password
316 m_bUseCommonPass = sal_True;
317 return sal_False;
319 else
320 return bToBeEncr;
323 //-----------------------------------------------
324 void OWriteStream_Impl::SetDecrypted()
326 OSL_ENSURE( m_nStorageType == PACKAGE_STORAGE, "The encryption is supported only for package storages!\n" );
327 if ( m_nStorageType != PACKAGE_STORAGE )
328 throw uno::RuntimeException();
330 GetStreamProperties();
332 // let the stream be modified
333 GetFilledTempFile();
334 m_bHasDataToFlush = sal_True;
336 // remove encryption
337 m_bForceEncrypted = sal_False;
338 m_bHasCachedPassword = sal_False;
339 m_aPass = ::rtl::OUString();
341 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
343 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
344 m_aProps[nInd].Value <<= sal_False;
348 //-----------------------------------------------
349 void OWriteStream_Impl::SetEncryptedWithPass( const ::rtl::OUString& aPass )
351 OSL_ENSURE( m_nStorageType == PACKAGE_STORAGE, "The encryption is supported only for package storages!\n" );
352 if ( m_nStorageType != PACKAGE_STORAGE )
353 throw uno::RuntimeException();
355 GetStreamProperties();
357 // let the stream be modified
358 GetFilledTempFile();
359 m_bHasDataToFlush = sal_True;
361 // introduce encryption info
362 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
364 if ( m_aProps[nInd].Name.equalsAscii( "Encrypted" ) )
365 m_aProps[nInd].Value <<= sal_True;
368 m_bUseCommonPass = sal_False; // very important to set it to false
370 m_bHasCachedPassword = sal_True;
371 m_aPass = aPass;
374 //-----------------------------------------------
375 void OWriteStream_Impl::DisposeWrappers()
377 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
378 if ( m_pAntiImpl )
380 try {
381 m_pAntiImpl->dispose();
383 catch ( uno::RuntimeException& )
385 m_pAntiImpl = NULL;
387 m_pParent = NULL;
389 if ( !m_aInputStreamsList.empty() )
391 for ( InputStreamsList_Impl::iterator pStreamIter = m_aInputStreamsList.begin();
392 pStreamIter != m_aInputStreamsList.end(); pStreamIter++ )
394 if ( (*pStreamIter) )
396 (*pStreamIter)->InternalDispose();
397 (*pStreamIter) = NULL;
401 m_aInputStreamsList.clear();
405 //-----------------------------------------------
406 uno::Reference< lang::XMultiServiceFactory > OWriteStream_Impl::GetServiceFactory()
408 if ( m_xFactory.is() )
409 return m_xFactory;
411 return ::comphelper::getProcessServiceFactory();
414 //-----------------------------------------------
415 ::rtl::OUString OWriteStream_Impl::GetFilledTempFile()
417 if ( !m_aTempURL.getLength() )
419 m_aTempURL = GetNewTempFileURL( GetServiceFactory() );
421 try {
422 if ( m_aTempURL )
424 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
425 GetServiceFactory()->createInstance (
426 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
427 uno::UNO_QUERY );
429 if ( !xTempAccess.is() )
430 throw uno::RuntimeException(); // TODO:
433 // in case of new inserted package stream it is possible that input stream still was not set
434 uno::Reference< io::XInputStream > xOrigStream = m_xPackageStream->getDataStream();
435 if ( xOrigStream.is() )
437 uno::Reference< io::XOutputStream > xTempOutStream = xTempAccess->openFileWrite( m_aTempURL );
438 if ( xTempOutStream.is() )
440 // copy stream contents to the file
441 ::comphelper::OStorageHelper::CopyInputToOutput( xOrigStream, xTempOutStream );
442 xTempOutStream->closeOutput();
443 xTempOutStream = uno::Reference< io::XOutputStream >();
445 else
446 throw io::IOException(); // TODO:
450 catch( packages::WrongPasswordException& )
452 KillFile( m_aTempURL, GetServiceFactory() );
453 m_aTempURL = ::rtl::OUString();
455 throw;
457 catch( uno::Exception& )
459 KillFile( m_aTempURL, GetServiceFactory() );
460 m_aTempURL = ::rtl::OUString();
464 return m_aTempURL;
467 //-----------------------------------------------
468 uno::Reference< io::XStream > OWriteStream_Impl::GetTempFileAsStream()
470 uno::Reference< io::XStream > xTempStream;
472 if ( !m_aTempURL.getLength() )
473 m_aTempURL = GetFilledTempFile();
475 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
476 GetServiceFactory()->createInstance (
477 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
478 uno::UNO_QUERY );
480 if ( !xTempAccess.is() )
481 throw uno::RuntimeException(); // TODO:
485 xTempStream = xTempAccess->openFileReadWrite( m_aTempURL );
487 catch( uno::Exception& )
491 // the method must always return a stream
492 // in case the stream can not be open
493 // an exception should be thrown
494 if ( !xTempStream.is() )
495 throw io::IOException(); //TODO:
497 return xTempStream;
500 //-----------------------------------------------
501 uno::Reference< io::XInputStream > OWriteStream_Impl::GetTempFileAsInputStream()
503 uno::Reference< io::XInputStream > xInputStream;
505 if ( !m_aTempURL.getLength() )
506 m_aTempURL = GetFilledTempFile();
508 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
509 GetServiceFactory()->createInstance (
510 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
511 uno::UNO_QUERY );
513 if ( !xTempAccess.is() )
514 throw uno::RuntimeException(); // TODO:
518 xInputStream = xTempAccess->openFileRead( m_aTempURL );
520 catch( uno::Exception& )
524 // the method must always return a stream
525 // in case the stream can not be open
526 // an exception should be thrown
527 if ( !xInputStream.is() )
528 throw io::IOException(); // TODO:
530 return xInputStream;
533 //-----------------------------------------------
534 void OWriteStream_Impl::CopyTempFileToOutput( uno::Reference< io::XOutputStream > xOutStream )
536 OSL_ENSURE( xOutStream.is(), "The stream must be specified!\n" );
537 OSL_ENSURE( m_aTempURL.getLength(), "The temporary must exist!\n" );
539 uno::Reference < ucb::XSimpleFileAccess > xTempAccess(
540 GetServiceFactory()->createInstance (
541 ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
542 uno::UNO_QUERY );
544 if ( !xTempAccess.is() )
545 throw uno::RuntimeException(); // TODO:
547 uno::Reference< io::XInputStream > xTempInStream;
550 xTempInStream = xTempAccess->openFileRead( m_aTempURL );
552 catch( uno::Exception& )
556 if ( !xTempInStream.is() )
557 throw io::IOException(); //TODO:
559 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutStream );
562 // =================================================================================================
564 //-----------------------------------------------
565 void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputStream >& xInStream,
566 const uno::Sequence< beans::PropertyValue >& aProps )
568 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
570 // this call can be made only during parent storage commit
571 // the parent storage is responsible for the correct handling
572 // of deleted and renamed contents
574 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
576 if ( m_bHasDataToFlush )
577 throw io::IOException();
579 OSL_ENSURE( !m_aTempURL.getLength(), "The temporary must not exist!\n" );
581 // use new file as current persistent representation
582 // the new file will be removed after it's stream is closed
583 m_xPackageStream->setDataStream( xInStream );
585 // copy properties to the package stream
586 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
587 if ( !xPropertySet.is() )
588 throw uno::RuntimeException();
590 // The storage-package communication has a problem
591 // the storage caches properties, thus if the package changes one of them itself
592 // the storage does not know about it
594 // Depending from MediaType value the package can change the compressed property itself
595 // Thus if Compressed property is provided it must be set as the latest one
596 sal_Bool bCompressedIsSet = sal_False;
597 sal_Bool bCompressed = sal_False;
598 ::rtl::OUString aComprPropName( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) );
599 ::rtl::OUString aMedTypePropName( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) );
600 for ( sal_Int32 nInd = 0; nInd < aProps.getLength(); nInd++ )
602 if ( aProps[nInd].Name.equals( aComprPropName ) )
604 bCompressedIsSet = sal_True;
605 aProps[nInd].Value >>= bCompressed;
607 else if ( ( m_nStorageType == OFOPXML_STORAGE || m_nStorageType == PACKAGE_STORAGE )
608 && aProps[nInd].Name.equals( aMedTypePropName ) )
610 xPropertySet->setPropertyValue( aProps[nInd].Name, aProps[nInd].Value );
612 else if ( m_nStorageType == PACKAGE_STORAGE && aProps[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
613 aProps[nInd].Value >>= m_bUseCommonPass;
614 else
615 throw lang::IllegalArgumentException();
617 // if there are cached properties update them
618 if ( aProps[nInd].Name.equals( aMedTypePropName ) || aProps[nInd].Name.equals( aComprPropName ) )
619 for ( sal_Int32 nMemInd = 0; nMemInd < m_aProps.getLength(); nMemInd++ )
621 if ( aProps[nInd].Name.equals( m_aProps[nMemInd].Name ) )
622 m_aProps[nMemInd].Value = aProps[nInd].Value;
626 if ( bCompressedIsSet )
627 xPropertySet->setPropertyValue( aComprPropName, uno::makeAny( (sal_Bool)bCompressed ) );
629 if ( m_bUseCommonPass )
631 if ( m_nStorageType != PACKAGE_STORAGE )
632 throw uno::RuntimeException();
634 // set to be encrypted but do not use encryption key
635 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
636 uno::makeAny( uno::Sequence< sal_Int8 >() ) );
637 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
638 uno::makeAny( sal_True ) );
641 // the stream should be free soon, after package is stored
642 m_bHasDataToFlush = sal_False;
643 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
644 m_bHasInsertedStreamOptimization = sal_True;
647 //-----------------------------------------------
648 void OWriteStream_Impl::Commit()
650 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
652 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
654 if ( !m_bHasDataToFlush )
655 return;
657 uno::Reference< packages::XDataSinkEncrSupport > xNewPackageStream;
659 OSL_ENSURE( m_bHasInsertedStreamOptimization || m_aTempURL.getLength(), "The temporary must exist!\n" );
660 if ( m_aTempURL.getLength() )
662 uno::Reference < io::XOutputStream > xTempOut(
663 GetServiceFactory()->createInstance (
664 ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
665 uno::UNO_QUERY );
666 uno::Reference < io::XInputStream > xTempIn( xTempOut, uno::UNO_QUERY );
668 if ( !xTempOut.is() || !xTempIn.is() )
669 throw io::IOException();
671 // Copy temporary file to a new one
672 CopyTempFileToOutput( xTempOut );
673 xTempOut->closeOutput();
675 uno::Sequence< uno::Any > aSeq( 1 );
676 aSeq[0] <<= sal_False;
677 xNewPackageStream = uno::Reference< packages::XDataSinkEncrSupport >(
678 m_xPackage->createInstanceWithArguments( aSeq ),
679 uno::UNO_QUERY );
680 if ( !xNewPackageStream.is() )
681 throw uno::RuntimeException();
683 // use new file as current persistent representation
684 // the new file will be removed after it's stream is closed
685 xNewPackageStream->setDataStream( xTempIn );
687 else // if ( m_bHasInsertedStreamOptimization )
689 // if the optimization is used the stream can be accessed directly
690 xNewPackageStream = m_xPackageStream;
693 // copy properties to the package stream
694 uno::Reference< beans::XPropertySet > xPropertySet( xNewPackageStream, uno::UNO_QUERY );
695 if ( !xPropertySet.is() )
696 throw uno::RuntimeException();
698 for ( sal_Int32 nInd = 0; nInd < m_aProps.getLength(); nInd++ )
700 if ( m_aProps[nInd].Name.equalsAscii( "Size" ) )
702 if ( m_pAntiImpl && !m_bHasInsertedStreamOptimization && m_pAntiImpl->m_xSeekable.is() )
704 m_aProps[nInd].Value <<= ((sal_Int32)m_pAntiImpl->m_xSeekable->getLength());
705 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
708 else
709 xPropertySet->setPropertyValue( m_aProps[nInd].Name, m_aProps[nInd].Value );
712 if ( m_bUseCommonPass )
714 if ( m_nStorageType != PACKAGE_STORAGE )
715 throw uno::RuntimeException();
717 // set to be encrypted but do not use encryption key
718 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
719 uno::makeAny( uno::Sequence< sal_Int8 >() ) );
720 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ),
721 uno::makeAny( sal_True ) );
723 else if ( m_bHasCachedPassword )
725 if ( m_nStorageType != PACKAGE_STORAGE )
726 throw uno::RuntimeException();
728 xPropertySet->setPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ),
729 uno::makeAny( MakeKeyFromPass( m_aPass, sal_True ) ) );
732 // the stream should be free soon, after package is stored
733 m_xPackageStream = xNewPackageStream;
734 m_bHasDataToFlush = sal_False;
735 m_bFlushed = sal_True; // will allow to use transaction on stream level if will need it
738 //-----------------------------------------------
739 void OWriteStream_Impl::Revert()
741 // can be called only from parent storage
742 // means complete reload of the stream
744 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
746 if ( !m_bHasDataToFlush )
747 return; // nothing to do
749 OSL_ENSURE( m_aTempURL.getLength(), "The temporary must exist!\n" );
751 if ( m_aTempURL.getLength() )
753 KillFile( m_aTempURL, GetServiceFactory() );
754 m_aTempURL = ::rtl::OUString();
757 m_aProps.realloc( 0 );
759 m_bHasDataToFlush = sal_False;
761 m_bUseCommonPass = sal_True;
762 m_bHasCachedPassword = sal_False;
763 m_aPass = ::rtl::OUString();
765 if ( m_nStorageType == OFOPXML_STORAGE )
767 // currently the relations storage is changed only on commit
768 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
769 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
770 if ( m_xOrigRelInfoStream.is() )
772 // the original stream is still here, that means that it was not parsed
773 m_aOrigRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
774 m_nRelInfoStatus = RELINFO_NO_INIT;
776 else
778 // the original stream was aready parsed
779 if ( !m_bOrigRelInfoBroken )
780 m_nRelInfoStatus = RELINFO_READ;
781 else
782 m_nRelInfoStatus = RELINFO_BROKEN;
787 //-----------------------------------------------
788 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::GetStreamProperties()
790 if ( !m_aProps.getLength() )
791 m_aProps = ReadPackageStreamProperties();
793 return m_aProps;
796 //-----------------------------------------------
797 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::InsertOwnProps(
798 const uno::Sequence< beans::PropertyValue >& aProps,
799 sal_Bool bUseCommonPass )
801 uno::Sequence< beans::PropertyValue > aResult( aProps );
802 sal_Int32 nLen = aResult.getLength();
804 if ( m_nStorageType == PACKAGE_STORAGE )
806 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
807 if ( aResult[nInd].Name.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
809 aResult[nInd].Value <<= bUseCommonPass;
810 return aResult;
813 aResult.realloc( ++nLen );
814 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
815 aResult[nLen - 1].Value <<= bUseCommonPass;
817 else if ( m_nStorageType == OFOPXML_STORAGE )
819 ReadRelInfoIfNecessary();
821 uno::Any aValue;
822 if ( m_nRelInfoStatus == RELINFO_READ )
823 aValue <<= m_aOrigRelInfo;
824 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
825 aValue <<= m_aNewRelInfo;
826 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
827 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
828 uno::Reference< uno::XInterface >() );
830 for ( sal_Int32 nInd = 0; nInd < nLen; nInd++ )
831 if ( aResult[nInd].Name.equalsAscii( "RelationsInfo" ) )
833 aResult[nInd].Value = aValue;
834 return aResult;
837 aResult.realloc( ++nLen );
838 aResult[nLen - 1].Name = ::rtl::OUString::createFromAscii( "RelationsInfo" );
839 aResult[nLen - 1].Value = aValue;
842 return aResult;
845 //-----------------------------------------------
846 sal_Bool OWriteStream_Impl::IsTransacted()
848 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
849 return ( m_pAntiImpl && m_pAntiImpl->m_bTransacted );
852 void OWriteStream_Impl::ReadRelInfoIfNecessary()
854 if ( m_nStorageType != OFOPXML_STORAGE )
855 return;
857 if ( m_nRelInfoStatus == RELINFO_NO_INIT )
861 // Init from original stream
862 if ( m_xOrigRelInfoStream.is() )
863 m_aOrigRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
864 m_xOrigRelInfoStream,
865 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
866 m_xFactory );
868 // in case of success the stream must be thrown away, that means that the OrigRelInfo is initialized
869 // the reason for this is that the original stream might not be seekable ( at the same time the new
870 // provided stream must be seekable ), so it must be read only once
871 m_xOrigRelInfoStream = uno::Reference< io::XInputStream >();
872 m_nRelInfoStatus = RELINFO_READ;
874 catch( uno::Exception& )
876 m_nRelInfoStatus = RELINFO_BROKEN;
877 m_bOrigRelInfoBroken = sal_True;
880 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
882 // Init from the new stream
885 if ( m_xNewRelInfoStream.is() )
886 m_aNewRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
887 m_xNewRelInfoStream,
888 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/*.rels" ) ),
889 m_xFactory );
891 m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ;
893 catch( uno::Exception )
895 m_nRelInfoStatus = RELINFO_CHANGED_BROKEN;
900 //-----------------------------------------------
901 uno::Sequence< beans::PropertyValue > OWriteStream_Impl::ReadPackageStreamProperties()
903 sal_Int32 nPropNum = 0;
904 if ( m_nStorageType == ZIP_STORAGE )
905 nPropNum = 2;
906 else if ( m_nStorageType == OFOPXML_STORAGE )
907 nPropNum = 3;
908 else if ( m_nStorageType == PACKAGE_STORAGE )
909 nPropNum = 4;
910 uno::Sequence< beans::PropertyValue > aResult( nPropNum );
912 // The "Compressed" property must be set after "MediaType" property,
913 // since the setting of the last one can change the value of the first one
915 if ( m_nStorageType == OFOPXML_STORAGE || m_nStorageType == PACKAGE_STORAGE )
917 aResult[0].Name = ::rtl::OUString::createFromAscii("MediaType");
918 aResult[1].Name = ::rtl::OUString::createFromAscii("Compressed");
919 aResult[2].Name = ::rtl::OUString::createFromAscii("Size");
921 if ( m_nStorageType == PACKAGE_STORAGE )
922 aResult[3].Name = ::rtl::OUString::createFromAscii("Encrypted");
924 else
926 aResult[0].Name = ::rtl::OUString::createFromAscii("Compressed");
927 aResult[1].Name = ::rtl::OUString::createFromAscii("Size");
931 // TODO: may be also raw stream should be marked
933 uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY );
934 if ( xPropSet.is() )
936 for ( sal_Int32 nInd = 0; nInd < aResult.getLength(); nInd++ )
938 try {
939 aResult[nInd].Value = xPropSet->getPropertyValue( aResult[nInd].Name );
941 catch( uno::Exception& )
943 OSL_ENSURE( sal_False, "A property can't be retrieved!\n" );
947 else
949 OSL_ENSURE( sal_False, "Can not get properties from a package stream!\n" );
950 throw uno::RuntimeException();
953 return aResult;
956 //-----------------------------------------------
957 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream,
958 const ::rtl::OUString& aPass )
960 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
962 OSL_ENSURE( !m_bUseCommonPass, "The stream can not be encrypted!" );
964 if ( m_nStorageType != PACKAGE_STORAGE )
965 throw packages::NoEncryptionException();
967 if ( m_pAntiImpl )
969 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
971 else
973 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, aPass, sal_False );
974 if ( !xOwnStream.is() )
975 throw io::IOException(); // TODO
977 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
980 uno::Reference< embed::XEncryptionProtectedSource > xEncr( xDestStream, uno::UNO_QUERY );
981 if ( xEncr.is() )
982 xEncr->setEncryptionPassword( aPass );
985 //-----------------------------------------------
986 uno::Sequence< uno::Sequence< beans::StringPair > > OWriteStream_Impl::GetAllRelationshipsIfAny()
988 if ( m_nStorageType != OFOPXML_STORAGE )
989 return uno::Sequence< uno::Sequence< beans::StringPair > >();
991 ReadRelInfoIfNecessary();
993 if ( m_nRelInfoStatus == RELINFO_READ )
994 return m_aOrigRelInfo;
995 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED )
996 return m_aNewRelInfo;
997 else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
998 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong relinfo stream!" ) ),
999 uno::Reference< uno::XInterface >() );
1002 //-----------------------------------------------
1003 void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream )
1005 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1007 if ( m_pAntiImpl )
1009 m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream );
1011 else
1013 uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, sal_False );
1014 if ( !xOwnStream.is() )
1015 throw io::IOException(); // TODO
1017 OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
1021 //-----------------------------------------------
1022 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, const ::rtl::OUString& aPass, sal_Bool bHierarchyAccess )
1024 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1026 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1028 if ( m_pAntiImpl )
1029 throw io::IOException(); // TODO:
1031 if ( !IsEncrypted() )
1032 throw packages::NoEncryptionException();
1034 uno::Reference< io::XStream > xResultStream;
1036 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1037 if ( !xPropertySet.is() )
1038 throw uno::RuntimeException();
1040 if ( m_bHasCachedPassword )
1042 if ( !m_aPass.equals( aPass ) )
1043 throw packages::WrongPasswordException();
1045 // the correct key must be set already
1046 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1048 else
1050 SetEncryptionKeyProperty_Impl( xPropertySet, MakeKeyFromPass( aPass, sal_True ) );
1052 try {
1053 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1055 m_bUseCommonPass = sal_False; // very important to set it to false
1056 m_bHasCachedPassword = sal_True;
1057 m_aPass = aPass;
1059 catch( packages::WrongPasswordException& )
1061 // retry with different encoding
1062 SetEncryptionKeyProperty_Impl( xPropertySet, MakeKeyFromPass( aPass, sal_False ) );
1063 try {
1064 // the stream must be cashed to be resaved
1065 xResultStream = GetStream_Impl( nStreamMode | embed::ElementModes::SEEKABLE, bHierarchyAccess );
1067 m_bUseCommonPass = sal_False; // very important to set it to false
1068 m_bHasCachedPassword = sal_True;
1069 m_aPass = aPass;
1071 // the stream must be resaved with new password encryption
1072 if ( nStreamMode & embed::ElementModes::WRITE )
1074 GetFilledTempFile();
1075 m_bHasDataToFlush = sal_True;
1077 // TODO/LATER: should the notification be done?
1078 if ( m_pParent )
1079 m_pParent->m_bIsModified = sal_True;
1082 catch( packages::WrongPasswordException& )
1084 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1085 throw;
1087 catch ( uno::Exception& )
1089 OSL_ENSURE( sal_False, "Can't write encryption related properties!\n" );
1090 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1091 throw io::IOException(); // TODO:
1094 catch( uno::Exception& )
1096 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1098 throw;
1103 OSL_ENSURE( xResultStream.is(), "In case stream can not be retrieved an exception must be thrown!\n" );
1105 return xResultStream;
1108 //-----------------------------------------------
1109 uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1111 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1113 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1115 if ( m_pAntiImpl )
1116 throw io::IOException(); // TODO:
1118 uno::Reference< io::XStream > xResultStream;
1120 if ( IsEncrypted() )
1122 ::rtl::OUString aGlobalPass;
1125 aGlobalPass = GetCommonRootPass();
1127 catch( packages::NoEncryptionException& )
1129 throw packages::WrongPasswordException();
1132 xResultStream = GetStream( nStreamMode, aGlobalPass, bHierarchyAccess );
1134 else
1135 xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess );
1137 return xResultStream;
1140 //-----------------------------------------------
1141 uno::Reference< io::XStream > OWriteStream_Impl::GetStream_Impl( sal_Int32 nStreamMode, sal_Bool bHierarchyAccess )
1143 // private method, no mutex is used
1144 GetStreamProperties();
1146 // TODO/LATER: this info might be read later, on demand in future
1147 ReadRelInfoIfNecessary();
1149 if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::READ )
1151 uno::Reference< io::XInputStream > xInStream;
1152 if ( m_aTempURL.getLength() )
1153 xInStream = GetTempFileAsInputStream(); //TODO:
1154 else
1155 xInStream = m_xPackageStream->getDataStream();
1157 // The stream does not exist in the storage
1158 if ( !xInStream.is() )
1159 throw io::IOException();
1161 OInputCompStream* pStream = new OInputCompStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonPass ), m_nStorageType );
1162 uno::Reference< io::XStream > xCompStream(
1163 static_cast< ::cppu::OWeakObject* >( pStream ),
1164 uno::UNO_QUERY );
1165 OSL_ENSURE( xCompStream.is(),
1166 "OInputCompStream MUST provide XStream interfaces!\n" );
1168 m_aInputStreamsList.push_back( pStream );
1169 return xCompStream;
1171 else if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::SEEKABLEREAD )
1173 if ( !m_aTempURL.getLength() && !( m_xPackageStream->getDataStream().is() ) )
1175 // The stream does not exist in the storage
1176 throw io::IOException();
1179 uno::Reference< io::XInputStream > xInStream;
1181 xInStream = GetTempFileAsInputStream(); //TODO:
1183 if ( !xInStream.is() )
1184 throw io::IOException();
1186 OInputSeekStream* pStream = new OInputSeekStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonPass ), m_nStorageType );
1187 uno::Reference< io::XStream > xSeekStream(
1188 static_cast< ::cppu::OWeakObject* >( pStream ),
1189 uno::UNO_QUERY );
1190 OSL_ENSURE( xSeekStream.is(),
1191 "OInputSeekStream MUST provide XStream interfaces!\n" );
1193 m_aInputStreamsList.push_back( pStream );
1194 return xSeekStream;
1196 else if ( ( nStreamMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE )
1198 if ( !m_aInputStreamsList.empty() )
1199 throw io::IOException(); // TODO:
1201 uno::Reference< io::XStream > xStream;
1202 if ( ( nStreamMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
1204 if ( m_aTempURL.getLength() )
1205 KillFile( m_aTempURL, GetServiceFactory() );
1207 // open new empty temp file
1208 m_aTempURL = GetNewTempFileURL( GetServiceFactory() );
1210 m_bHasDataToFlush = sal_True;
1212 // this call is triggered by the parent and it will recognize the change of the state
1213 if ( m_pParent )
1214 m_pParent->m_bIsModified = sal_True;
1216 xStream = GetTempFileAsStream();
1218 else if ( !m_bHasInsertedStreamOptimization )
1220 if ( !m_aTempURL.getLength() && !( m_xPackageStream->getDataStream().is() ) )
1222 // The stream does not exist in the storage
1223 m_bHasDataToFlush = sal_True;
1225 // this call is triggered by the parent and it will recognize the change of the state
1226 if ( m_pParent )
1227 m_pParent->m_bIsModified = sal_True;
1228 xStream = GetTempFileAsStream();
1231 // if the stream exists the temporary file is created on demand
1232 // xStream = GetTempFileAsStream();
1235 if ( !xStream.is() )
1236 m_pAntiImpl = new OWriteStream( this, bHierarchyAccess );
1237 else
1238 m_pAntiImpl = new OWriteStream( this, xStream, bHierarchyAccess );
1240 uno::Reference< io::XStream > xWriteStream =
1241 uno::Reference< io::XStream >( static_cast< ::cppu::OWeakObject* >( m_pAntiImpl ),
1242 uno::UNO_QUERY );
1244 OSL_ENSURE( xWriteStream.is(), "OWriteStream MUST implement XStream && XComponent interfaces!\n" );
1246 return xWriteStream;
1249 throw lang::IllegalArgumentException(); // TODO
1252 //-----------------------------------------------
1253 uno::Reference< io::XInputStream > OWriteStream_Impl::GetPlainRawInStream()
1255 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1257 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1259 // this method is used only internally, this stream object should not go outside of this implementation
1260 // if ( m_pAntiImpl )
1261 // throw io::IOException(); // TODO:
1263 return m_xPackageStream->getPlainRawStream();
1266 //-----------------------------------------------
1267 uno::Reference< io::XInputStream > OWriteStream_Impl::GetRawInStream()
1269 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1271 OSL_ENSURE( m_xPackageStream.is(), "No package stream is set!\n" );
1273 if ( m_pAntiImpl )
1274 throw io::IOException(); // TODO:
1276 OSL_ENSURE( IsEncrypted(), "Impossible to get raw representation for nonencrypted stream!\n" );
1277 if ( !IsEncrypted() )
1278 throw packages::NoEncryptionException();
1280 return m_xPackageStream->getRawStream();
1283 //-----------------------------------------------
1284 ::rtl::OUString OWriteStream_Impl::GetCommonRootPass()
1285 throw ( packages::NoEncryptionException )
1287 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() ) ;
1289 if ( m_nStorageType != PACKAGE_STORAGE || !m_pParent )
1290 throw packages::NoEncryptionException();
1292 return m_pParent->GetCommonRootPass();
1295 //-----------------------------------------------
1296 void OWriteStream_Impl::InputStreamDisposed( OInputCompStream* pStream )
1298 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1299 m_aInputStreamsList.remove( pStream );
1302 //-----------------------------------------------
1303 void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( const uno::Reference< io::XInputStream >& xDataToCopy, const uno::Sequence< beans::PropertyValue >& aProps, sal_Bool, uno::Reference< io::XStream >& xTargetStream )
1305 uno::Reference < io::XStream > xTempFile;
1306 if ( !xTargetStream.is() )
1307 xTempFile = uno::Reference < io::XStream >(
1308 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ),
1309 uno::UNO_QUERY );
1310 else
1311 xTempFile = xTargetStream;
1313 uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY );
1314 if ( !xTempSeek.is() )
1315 throw uno::RuntimeException(); // TODO
1317 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
1318 if ( !xTempOut.is() )
1319 throw uno::RuntimeException();
1321 if ( xDataToCopy.is() )
1322 ::comphelper::OStorageHelper::CopyInputToOutput( xDataToCopy, xTempOut );
1324 xTempOut->closeOutput();
1325 xTempSeek->seek( 0 );
1327 uno::Reference< io::XInputStream > xInStream = xTempFile->getInputStream();
1328 if ( !xInStream.is() )
1329 throw io::IOException();
1331 // TODO: remember last state of m_bUseCommonPass
1332 if ( !xTargetStream.is() )
1333 xTargetStream = uno::Reference< io::XStream > (
1334 static_cast< ::cppu::OWeakObject* >(
1335 new OInputSeekStream( xInStream, InsertOwnProps( aProps, m_bUseCommonPass ), m_nStorageType ) ),
1336 uno::UNO_QUERY_THROW );
1339 //-----------------------------------------------
1340 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream )
1342 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1344 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1345 if ( !m_xPackageStream.is() )
1346 throw uno::RuntimeException();
1348 uno::Reference< io::XInputStream > xDataToCopy;
1349 if ( IsEncrypted() )
1351 // an encrypted stream must contain input stream
1352 ::rtl::OUString aGlobalPass;
1355 aGlobalPass = GetCommonRootPass();
1357 catch( packages::NoEncryptionException& )
1359 throw packages::WrongPasswordException();
1362 GetCopyOfLastCommit( xTargetStream, aGlobalPass );
1364 else
1366 xDataToCopy = m_xPackageStream->getDataStream();
1368 // in case of new inserted package stream it is possible that input stream still was not set
1369 GetStreamProperties();
1371 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonPass, xTargetStream );
1375 //-----------------------------------------------
1376 void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream, const ::rtl::OUString& aPass )
1378 ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
1380 OSL_ENSURE( m_xPackageStream.is(), "The source stream for copying is incomplete!\n" );
1381 if ( !m_xPackageStream.is() )
1382 throw uno::RuntimeException();
1384 if ( !IsEncrypted() )
1385 throw packages::NoEncryptionException();
1387 uno::Reference< io::XInputStream > xDataToCopy;
1389 if ( m_bHasCachedPassword )
1391 // TODO: introduce last commited cashed password information and use it here
1392 // that means "use common pass" also should be remembered on flash
1393 uno::Sequence< sal_Int8 > aNewKey = MakeKeyFromPass( aPass, sal_True );
1394 uno::Sequence< sal_Int8 > aOldKey = MakeKeyFromPass( aPass, sal_False );
1396 uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY );
1397 if ( !xProps.is() )
1398 throw uno::RuntimeException();
1400 sal_Bool bEncr = sal_False;
1401 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "Encrypted" ) ) >>= bEncr;
1402 if ( !bEncr )
1403 throw packages::NoEncryptionException();
1405 uno::Sequence< sal_Int8 > aEncrKey;
1406 xProps->getPropertyValue( ::rtl::OUString::createFromAscii( "EncryptionKey" ) ) >>= aEncrKey;
1407 if ( !SequencesEqual( aNewKey, aEncrKey ) && !SequencesEqual( aOldKey, aEncrKey ) )
1408 throw packages::WrongPasswordException();
1410 // the correct key must be set already
1411 xDataToCopy = m_xPackageStream->getDataStream();
1413 else
1415 uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY );
1416 SetEncryptionKeyProperty_Impl( xPropertySet, MakeKeyFromPass( aPass, sal_True ) );
1418 try {
1419 xDataToCopy = m_xPackageStream->getDataStream();
1421 if ( !xDataToCopy.is() )
1423 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" );
1424 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1427 catch( packages::WrongPasswordException& )
1429 SetEncryptionKeyProperty_Impl( xPropertySet, MakeKeyFromPass( aPass, sal_False ) );
1430 try {
1431 xDataToCopy = m_xPackageStream->getDataStream();
1433 if ( !xDataToCopy.is() )
1435 OSL_ENSURE( sal_False, "Encrypted ZipStream must already have input stream inside!\n" );
1436 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1437 throw;
1440 catch( uno::Exception& )
1442 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1443 throw;
1446 catch( uno::Exception& )
1448 OSL_ENSURE( sal_False, "Can't open encrypted stream!\n" );
1449 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1450 throw;
1453 SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< sal_Int8 >() );
1456 // in case of new inserted package stream it is possible that input stream still was not set
1457 GetStreamProperties();
1459 CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, m_bUseCommonPass, xTargetStream );
1462 //-----------------------------------------------
1463 void OWriteStream_Impl::CommitStreamRelInfo( const uno::Reference< embed::XStorage >& xRelStorage, const ::rtl::OUString& aOrigStreamName, const ::rtl::OUString& aNewStreamName )
1465 // at this point of time the old stream must be already cleaned
1466 OSL_ENSURE( m_nStorageType == OFOPXML_STORAGE, "The method should be used only with OFOPXML format!\n" );
1468 if ( m_nStorageType == OFOPXML_STORAGE )
1470 OSL_ENSURE( aOrigStreamName.getLength() && aNewStreamName.getLength() && xRelStorage.is(),
1471 "Wrong relation persistence information is provided!\n" );
1473 if ( !xRelStorage.is() || !aOrigStreamName.getLength() || !aNewStreamName.getLength() )
1474 throw uno::RuntimeException();
1476 if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN )
1477 throw io::IOException(); // TODO:
1479 ::rtl::OUString aOrigRelStreamName = aOrigStreamName;
1480 aOrigRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1482 ::rtl::OUString aNewRelStreamName = aNewStreamName;
1483 aNewRelStreamName += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".rels" ) );
1485 sal_Bool bRenamed = !aOrigRelStreamName.equals( aNewRelStreamName );
1486 if ( m_nRelInfoStatus == RELINFO_CHANGED
1487 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1488 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1490 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1491 xRelStorage->removeElement( aOrigRelStreamName );
1493 if ( m_nRelInfoStatus == RELINFO_CHANGED )
1495 if ( m_aNewRelInfo.getLength() )
1497 uno::Reference< io::XStream > xRelsStream =
1498 xRelStorage->openStreamElement( aNewRelStreamName,
1499 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1501 uno::Reference< io::XOutputStream > xOutStream = xRelsStream->getOutputStream();
1502 if ( !xOutStream.is() )
1503 throw uno::RuntimeException();
1505 ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence( xOutStream, m_aNewRelInfo, m_xFactory );
1507 // set the mediatype
1508 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1509 xPropSet->setPropertyValue(
1510 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1511 uno::makeAny( ::rtl::OUString(
1512 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1514 m_nRelInfoStatus = RELINFO_READ;
1517 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1518 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1520 uno::Reference< io::XStream > xRelsStream =
1521 xRelStorage->openStreamElement( aNewRelStreamName,
1522 embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE );
1524 uno::Reference< io::XOutputStream > xOutputStream = xRelsStream->getOutputStream();
1525 if ( !xOutputStream.is() )
1526 throw uno::RuntimeException();
1528 uno::Reference< io::XSeekable > xSeek( m_xNewRelInfoStream, uno::UNO_QUERY_THROW );
1529 xSeek->seek( 0 );
1530 ::comphelper::OStorageHelper::CopyInputToOutput( m_xNewRelInfoStream, xOutputStream );
1531 xSeek->seek( 0 );
1533 // set the mediatype
1534 uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW );
1535 xPropSet->setPropertyValue(
1536 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1537 uno::makeAny( ::rtl::OUString(
1538 RTL_CONSTASCII_USTRINGPARAM( "application/vnd.openxmlformats-package.relationships+xml" ) ) ) );
1540 if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
1541 m_nRelInfoStatus = RELINFO_NO_INIT;
1542 else
1544 // the information is already parsed and the stream is stored, no need in temporary stream any more
1545 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1546 m_nRelInfoStatus = RELINFO_READ;
1550 // the original stream makes no sence after this step
1551 m_xOrigRelInfoStream = m_xNewRelInfoStream;
1552 m_aOrigRelInfo = m_aNewRelInfo;
1553 m_bOrigRelInfoBroken = sal_False;
1554 m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1555 m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
1557 else
1559 // the stream is not changed but it might be renamed
1560 if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) )
1561 xRelStorage->renameElement( aOrigRelStreamName, aNewRelStreamName );
1566 //===============================================
1567 // OWriteStream implementation
1568 //===============================================
1570 //-----------------------------------------------
1571 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, sal_Bool bTransacted )
1572 : m_pImpl( pImpl )
1573 , m_bInStreamDisconnected( sal_False )
1574 , m_bInitOnDemand( sal_True )
1575 , m_bTransacted( bTransacted )
1577 OSL_ENSURE( pImpl, "No base implementation!\n" );
1578 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1580 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1581 throw uno::RuntimeException(); // just a disaster
1583 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1586 //-----------------------------------------------
1587 OWriteStream::OWriteStream( OWriteStream_Impl* pImpl, uno::Reference< io::XStream > xStream, sal_Bool bTransacted )
1588 : m_pImpl( pImpl )
1589 , m_bInStreamDisconnected( sal_False )
1590 , m_bInitOnDemand( sal_False )
1591 , m_bTransacted( bTransacted )
1593 OSL_ENSURE( pImpl && xStream.is(), "No base implementation!\n" );
1594 OSL_ENSURE( m_pImpl->m_rMutexRef.Is(), "No mutex!\n" );
1596 if ( !m_pImpl || !m_pImpl->m_rMutexRef.Is() )
1597 throw uno::RuntimeException(); // just a disaster
1599 m_pData = new WSInternalData_Impl( pImpl->m_rMutexRef, m_pImpl->m_nStorageType );
1601 if ( xStream.is() )
1603 m_xInStream = xStream->getInputStream();
1604 m_xOutStream = xStream->getOutputStream();
1605 m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
1606 OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!\n" );
1610 //-----------------------------------------------
1611 OWriteStream::~OWriteStream()
1614 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1615 if ( m_pImpl )
1617 m_refCount++;
1618 try {
1619 dispose();
1621 catch( uno::RuntimeException& )
1626 if ( m_pData && m_pData->m_pTypeCollection )
1627 delete m_pData->m_pTypeCollection;
1629 if ( m_pData )
1630 delete m_pData;
1633 //-----------------------------------------------
1634 void OWriteStream::CheckInitOnDemand()
1636 if ( !m_pImpl )
1637 throw lang::DisposedException();
1639 if ( m_bInitOnDemand )
1641 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" );
1642 uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream();
1643 if ( xStream.is() )
1645 m_xInStream = xStream->getInputStream();
1646 m_xOutStream = xStream->getOutputStream();
1647 m_xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
1648 OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!\n" );
1650 m_bInitOnDemand = sal_False;
1655 //-----------------------------------------------
1656 void OWriteStream::CopyToStreamInternally_Impl( const uno::Reference< io::XStream >& xDest )
1658 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1660 CheckInitOnDemand();
1662 if ( !m_xInStream.is() )
1663 throw uno::RuntimeException();
1665 if ( !m_xSeekable.is() )
1666 throw uno::RuntimeException();
1668 uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY );
1669 if ( !xDestProps.is() )
1670 throw uno::RuntimeException(); //TODO
1672 uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream();
1673 if ( !xDestOutStream.is() )
1674 throw io::IOException(); // TODO
1676 sal_Int64 nCurPos = m_xSeekable->getPosition();
1677 m_xSeekable->seek( 0 );
1679 uno::Exception eThrown;
1680 sal_Bool bThrown = sal_False;
1681 try {
1682 ::comphelper::OStorageHelper::CopyInputToOutput( m_xInStream, xDestOutStream );
1684 catch ( uno::Exception& e )
1686 eThrown = e;
1687 bThrown = sal_True;
1690 // position-related section below is critical
1691 // if it fails the stream will become invalid
1692 try {
1693 m_xSeekable->seek( nCurPos );
1695 catch ( uno::Exception& )
1697 // TODO: set the stoream in invalid state or dispose
1698 OSL_ENSURE( sal_False, "The stream become invalid during copiing!\n" );
1699 throw uno::RuntimeException();
1702 if ( bThrown )
1703 throw eThrown;
1705 // now the properties can be copied
1706 // the order of the properties setting is not important for StorageStream API
1707 ::rtl::OUString aPropName = ::rtl::OUString::createFromAscii( "Compressed" );
1708 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1709 if ( m_pData->m_nStorageType == PACKAGE_STORAGE || m_pData->m_nStorageType == OFOPXML_STORAGE )
1711 aPropName = ::rtl::OUString::createFromAscii( "MediaType" );
1712 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1714 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
1716 aPropName = ::rtl::OUString::createFromAscii( "UseCommonStoragePasswordEncryption" );
1717 xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) );
1722 //-----------------------------------------------
1723 void OWriteStream::ModifyParentUnlockMutex_Impl( ::osl::ResettableMutexGuard& aGuard )
1725 if ( m_pImpl->m_pParent )
1727 if ( m_pImpl->m_pParent->m_pAntiImpl )
1729 uno::Reference< util::XModifiable > xParentModif( (util::XModifiable*)(m_pImpl->m_pParent->m_pAntiImpl) );
1730 aGuard.clear();
1731 xParentModif->setModified( sal_True );
1733 else
1734 m_pImpl->m_pParent->m_bIsModified = sal_True;
1738 //-----------------------------------------------
1739 uno::Any SAL_CALL OWriteStream::queryInterface( const uno::Type& rType )
1740 throw( uno::RuntimeException )
1742 uno::Any aReturn;
1744 // common interfaces
1745 aReturn <<= ::cppu::queryInterface
1746 ( rType
1747 , static_cast<lang::XTypeProvider*> ( this )
1748 , static_cast<io::XInputStream*> ( this )
1749 , static_cast<io::XOutputStream*> ( this )
1750 , static_cast<io::XStream*> ( this )
1751 , static_cast<embed::XExtendedStorageStream*> ( this )
1752 , static_cast<io::XSeekable*> ( this )
1753 , static_cast<io::XTruncate*> ( this )
1754 , static_cast<lang::XComponent*> ( this )
1755 , static_cast<beans::XPropertySet*> ( this ) );
1757 if ( aReturn.hasValue() == sal_True )
1758 return aReturn ;
1760 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
1762 aReturn <<= ::cppu::queryInterface
1763 ( rType
1764 , static_cast<embed::XEncryptionProtectedSource*> ( this ) );
1766 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
1768 aReturn <<= ::cppu::queryInterface
1769 ( rType
1770 , static_cast<embed::XRelationshipAccess*> ( this ) );
1773 if ( aReturn.hasValue() == sal_True )
1774 return aReturn ;
1776 if ( m_bTransacted )
1778 aReturn <<= ::cppu::queryInterface
1779 ( rType
1780 , static_cast<embed::XTransactedObject*> ( this )
1781 , static_cast<embed::XTransactionBroadcaster*> ( this ) );
1783 if ( aReturn.hasValue() == sal_True )
1784 return aReturn ;
1787 return OWeakObject::queryInterface( rType );
1790 //-----------------------------------------------
1791 void SAL_CALL OWriteStream::acquire() throw()
1793 OWeakObject::acquire();
1796 //-----------------------------------------------
1797 void SAL_CALL OWriteStream::release() throw()
1799 OWeakObject::release();
1802 //-----------------------------------------------
1803 uno::Sequence< uno::Type > SAL_CALL OWriteStream::getTypes()
1804 throw( uno::RuntimeException )
1806 if ( m_pData->m_pTypeCollection == NULL )
1808 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1810 if ( m_pData->m_pTypeCollection == NULL )
1812 if ( m_bTransacted )
1814 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
1816 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1817 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1818 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1819 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1820 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1821 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1822 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1823 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1824 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
1825 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
1826 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
1827 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
1828 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1830 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
1832 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1833 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1834 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1835 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1836 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1837 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1838 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1839 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1840 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
1841 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
1842 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
1843 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
1844 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1846 else // if ( m_pData->m_nStorageType == ZIP_STORAGE )
1848 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1849 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1850 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1851 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1852 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1853 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1854 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1855 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1856 , ::getCppuType( ( const uno::Reference< embed::XExtendedStorageStream >* )NULL )
1857 , ::getCppuType( ( const uno::Reference< embed::XTransactedObject >* )NULL )
1858 , ::getCppuType( ( const uno::Reference< embed::XTransactionBroadcaster >* )NULL )
1859 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1862 else
1864 if ( m_pData->m_nStorageType == PACKAGE_STORAGE )
1866 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1867 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1868 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1869 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1870 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1871 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1872 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1873 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1874 , ::getCppuType( ( const uno::Reference< embed::XEncryptionProtectedSource >* )NULL )
1875 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1877 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE )
1879 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1880 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1881 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1882 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1883 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1884 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1885 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1886 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1887 , ::getCppuType( ( const uno::Reference< embed::XRelationshipAccess >* )NULL )
1888 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1890 else // if ( m_pData->m_nStorageType == ZIP_STORAGE )
1892 m_pData->m_pTypeCollection = new ::cppu::OTypeCollection
1893 ( ::getCppuType( ( const uno::Reference< lang::XTypeProvider >* )NULL )
1894 , ::getCppuType( ( const uno::Reference< io::XInputStream >* )NULL )
1895 , ::getCppuType( ( const uno::Reference< io::XOutputStream >* )NULL )
1896 , ::getCppuType( ( const uno::Reference< io::XStream >* )NULL )
1897 , ::getCppuType( ( const uno::Reference< io::XSeekable >* )NULL )
1898 , ::getCppuType( ( const uno::Reference< io::XTruncate >* )NULL )
1899 , ::getCppuType( ( const uno::Reference< lang::XComponent >* )NULL )
1900 , ::getCppuType( ( const uno::Reference< beans::XPropertySet >* )NULL ) );
1906 return m_pData->m_pTypeCollection->getTypes() ;
1909 //-----------------------------------------------
1910 uno::Sequence< sal_Int8 > SAL_CALL OWriteStream::getImplementationId()
1911 throw( uno::RuntimeException )
1913 static ::cppu::OImplementationId* pID = NULL ;
1915 if ( pID == NULL )
1917 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;
1919 if ( pID == NULL )
1921 static ::cppu::OImplementationId aID( sal_False ) ;
1922 pID = &aID ;
1926 return pID->getImplementationId() ;
1930 //-----------------------------------------------
1931 sal_Int32 SAL_CALL OWriteStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
1932 throw ( io::NotConnectedException,
1933 io::BufferSizeExceededException,
1934 io::IOException,
1935 uno::RuntimeException )
1937 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1939 CheckInitOnDemand();
1941 if ( !m_pImpl )
1942 throw lang::DisposedException();
1944 if ( !m_xInStream.is() )
1945 throw io::NotConnectedException();
1947 return m_xInStream->readBytes( aData, nBytesToRead );
1950 //-----------------------------------------------
1951 sal_Int32 SAL_CALL OWriteStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
1952 throw ( io::NotConnectedException,
1953 io::BufferSizeExceededException,
1954 io::IOException,
1955 uno::RuntimeException )
1957 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1959 CheckInitOnDemand();
1961 if ( !m_pImpl )
1962 throw lang::DisposedException();
1964 if ( !m_xInStream.is() )
1965 throw io::NotConnectedException();
1967 return m_xInStream->readSomeBytes( aData, nMaxBytesToRead );
1970 //-----------------------------------------------
1971 void SAL_CALL OWriteStream::skipBytes( sal_Int32 nBytesToSkip )
1972 throw ( io::NotConnectedException,
1973 io::BufferSizeExceededException,
1974 io::IOException,
1975 uno::RuntimeException )
1977 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1979 CheckInitOnDemand();
1981 if ( !m_pImpl )
1982 throw lang::DisposedException();
1984 if ( !m_xInStream.is() )
1985 throw io::NotConnectedException();
1987 m_xInStream->skipBytes( nBytesToSkip );
1990 //-----------------------------------------------
1991 sal_Int32 SAL_CALL OWriteStream::available( )
1992 throw ( io::NotConnectedException,
1993 io::IOException,
1994 uno::RuntimeException )
1996 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
1998 CheckInitOnDemand();
2000 if ( !m_pImpl )
2001 throw lang::DisposedException();
2003 if ( !m_xInStream.is() )
2004 throw io::NotConnectedException();
2006 return m_xInStream->available();
2010 //-----------------------------------------------
2011 void SAL_CALL OWriteStream::closeInput( )
2012 throw ( io::NotConnectedException,
2013 io::IOException,
2014 uno::RuntimeException )
2016 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2018 if ( !m_pImpl )
2019 throw lang::DisposedException();
2021 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2022 throw io::NotConnectedException();
2024 // the input part of the stream stays open for internal purposes ( to allow reading during copiing )
2025 // since it can not be reopened until output part is closed, it will be closed with output part.
2026 m_bInStreamDisconnected = sal_True;
2027 // m_xInStream->closeInput();
2028 // m_xInStream = uno::Reference< io::XInputStream >();
2030 if ( !m_xOutStream.is() )
2031 dispose();
2034 //-----------------------------------------------
2035 uno::Reference< io::XInputStream > SAL_CALL OWriteStream::getInputStream()
2036 throw ( uno::RuntimeException )
2038 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2040 if ( !m_pImpl )
2041 throw lang::DisposedException();
2043 if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) )
2044 return uno::Reference< io::XInputStream >();
2046 return uno::Reference< io::XInputStream >( static_cast< io::XInputStream* >( this ), uno::UNO_QUERY );
2049 //-----------------------------------------------
2050 uno::Reference< io::XOutputStream > SAL_CALL OWriteStream::getOutputStream()
2051 throw ( uno::RuntimeException )
2053 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2055 CheckInitOnDemand();
2057 if ( !m_pImpl )
2058 throw lang::DisposedException();
2060 if ( !m_xOutStream.is() )
2061 return uno::Reference< io::XOutputStream >();
2063 return uno::Reference< io::XOutputStream >( static_cast< io::XOutputStream* >( this ), uno::UNO_QUERY );
2066 //-----------------------------------------------
2067 void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData )
2068 throw ( io::NotConnectedException,
2069 io::BufferSizeExceededException,
2070 io::IOException,
2071 uno::RuntimeException )
2073 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2075 CheckInitOnDemand();
2077 if ( !m_pImpl )
2078 throw lang::DisposedException();
2080 if ( !m_xOutStream.is() )
2081 throw io::NotConnectedException();
2083 m_xOutStream->writeBytes( aData );
2084 m_pImpl->m_bHasDataToFlush = sal_True;
2086 ModifyParentUnlockMutex_Impl( aGuard );
2089 //-----------------------------------------------
2090 void SAL_CALL OWriteStream::flush()
2091 throw ( io::NotConnectedException,
2092 io::BufferSizeExceededException,
2093 io::IOException,
2094 uno::RuntimeException )
2096 // In case stream is flushed it's current version becomes visible
2097 // to the parent storage. Usually parent storage flushes the stream
2098 // during own commit but a user can explicitly flush the stream
2099 // so the changes will be available through cloning functionality.
2101 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2103 if ( !m_pImpl )
2104 throw lang::DisposedException();
2106 if ( !m_bInitOnDemand )
2108 if ( !m_xOutStream.is() )
2109 throw io::NotConnectedException();
2111 m_xOutStream->flush();
2112 m_pImpl->Commit();
2116 //-----------------------------------------------
2117 void OWriteStream::CloseOutput_Impl()
2119 // all the checks must be done in calling method
2121 m_xOutStream->closeOutput();
2122 m_xOutStream = uno::Reference< io::XOutputStream >();
2124 if ( !m_bInitOnDemand )
2126 // after the stream is disposed it can be commited
2127 // so transport correct size property
2128 if ( !m_xSeekable.is() )
2129 throw uno::RuntimeException();
2131 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
2133 if ( m_pImpl->m_aProps[nInd].Name.equalsAscii( "Size" ) )
2134 m_pImpl->m_aProps[nInd].Value <<= ((sal_Int32)m_xSeekable->getLength());
2139 //-----------------------------------------------
2140 void SAL_CALL OWriteStream::closeOutput()
2141 throw ( io::NotConnectedException,
2142 io::BufferSizeExceededException,
2143 io::IOException,
2144 uno::RuntimeException )
2146 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2148 CheckInitOnDemand();
2150 if ( !m_pImpl )
2151 throw lang::DisposedException();
2153 if ( !m_xOutStream.is() )
2154 throw io::NotConnectedException();
2156 CloseOutput_Impl();
2158 if ( m_bInStreamDisconnected || !m_xInStream.is() )
2159 dispose();
2162 //-----------------------------------------------
2163 void SAL_CALL OWriteStream::seek( sal_Int64 location )
2164 throw ( lang::IllegalArgumentException,
2165 io::IOException,
2166 uno::RuntimeException )
2168 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2170 CheckInitOnDemand();
2172 if ( !m_pImpl )
2173 throw lang::DisposedException();
2175 if ( !m_xSeekable.is() )
2176 throw uno::RuntimeException();
2178 m_xSeekable->seek( location );
2181 //-----------------------------------------------
2182 sal_Int64 SAL_CALL OWriteStream::getPosition()
2183 throw ( io::IOException,
2184 uno::RuntimeException)
2186 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2188 CheckInitOnDemand();
2190 if ( !m_pImpl )
2191 throw lang::DisposedException();
2193 if ( !m_xSeekable.is() )
2194 throw uno::RuntimeException();
2196 return m_xSeekable->getPosition();
2199 //-----------------------------------------------
2200 sal_Int64 SAL_CALL OWriteStream::getLength()
2201 throw ( io::IOException,
2202 uno::RuntimeException )
2204 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2206 CheckInitOnDemand();
2208 if ( !m_pImpl )
2209 throw lang::DisposedException();
2211 if ( !m_xSeekable.is() )
2212 throw uno::RuntimeException();
2214 return m_xSeekable->getLength();
2217 //-----------------------------------------------
2218 void SAL_CALL OWriteStream::truncate()
2219 throw ( io::IOException,
2220 uno::RuntimeException )
2222 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2224 CheckInitOnDemand();
2226 if ( !m_pImpl )
2227 throw lang::DisposedException();
2229 if ( !m_xOutStream.is() )
2230 throw uno::RuntimeException();
2232 uno::Reference< io::XTruncate > xTruncate( m_xOutStream, uno::UNO_QUERY );
2234 if ( !xTruncate.is() )
2236 OSL_ENSURE( sal_False, "The output stream must support XTruncate interface!\n" );
2237 throw uno::RuntimeException();
2240 xTruncate->truncate();
2242 m_pImpl->m_bHasDataToFlush = sal_True;
2244 ModifyParentUnlockMutex_Impl( aGuard );
2247 //-----------------------------------------------
2248 void SAL_CALL OWriteStream::dispose()
2249 throw ( uno::RuntimeException )
2251 // should be an internal method since it can be called only from parent storage
2253 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2255 if ( !m_pImpl )
2256 throw lang::DisposedException();
2258 if ( m_xOutStream.is() )
2259 CloseOutput_Impl();
2261 if ( m_xInStream.is() )
2263 m_xInStream->closeInput();
2264 m_xInStream = uno::Reference< io::XInputStream >();
2267 m_pImpl->m_pAntiImpl = NULL;
2269 if ( !m_bInitOnDemand )
2273 if ( !m_bTransacted )
2275 m_pImpl->Commit();
2277 else
2279 // throw away all the changes
2280 m_pImpl->Revert();
2283 catch( uno::Exception& )
2285 uno::Any aCaught( ::cppu::getCaughtException() );
2286 throw lang::WrappedTargetRuntimeException(
2287 ::rtl::OUString::createFromAscii( "Can not commit/revert the storage!\n" ),
2288 uno::Reference< uno::XInterface >( static_cast< OWeakObject* >( this ),
2289 uno::UNO_QUERY ),
2290 aCaught );
2294 m_pImpl = NULL;
2297 // the listener might try to get rid of parent storage, and the storage would delete this object;
2298 // for now the listener is just notified at the end of the method to workaround the problem
2299 // in future a more elegant way should be found
2301 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
2302 m_pData->m_aListenersContainer.disposeAndClear( aSource );
2305 //-----------------------------------------------
2306 void SAL_CALL OWriteStream::addEventListener(
2307 const uno::Reference< lang::XEventListener >& xListener )
2308 throw ( uno::RuntimeException )
2310 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2312 if ( !m_pImpl )
2313 throw lang::DisposedException();
2315 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2316 xListener );
2319 //-----------------------------------------------
2320 void SAL_CALL OWriteStream::removeEventListener(
2321 const uno::Reference< lang::XEventListener >& xListener )
2322 throw ( uno::RuntimeException )
2324 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2326 if ( !m_pImpl )
2327 throw lang::DisposedException();
2329 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0),
2330 xListener );
2333 //-----------------------------------------------
2334 void SAL_CALL OWriteStream::setEncryptionPassword( const ::rtl::OUString& aPass )
2335 throw ( uno::RuntimeException,
2336 io::IOException )
2338 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2340 CheckInitOnDemand();
2342 if ( !m_pImpl )
2343 throw lang::DisposedException();
2345 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2347 m_pImpl->SetEncryptedWithPass( aPass );
2349 ModifyParentUnlockMutex_Impl( aGuard );
2352 //-----------------------------------------------
2353 void SAL_CALL OWriteStream::removeEncryption()
2354 throw ( uno::RuntimeException,
2355 io::IOException )
2357 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2359 CheckInitOnDemand();
2361 if ( !m_pImpl )
2362 throw lang::DisposedException();
2364 OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!\n" );
2366 m_pImpl->SetDecrypted();
2368 ModifyParentUnlockMutex_Impl( aGuard );
2371 //-----------------------------------------------
2372 sal_Bool SAL_CALL OWriteStream::hasByID( const ::rtl::OUString& sID )
2373 throw ( io::IOException,
2374 uno::RuntimeException )
2376 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2378 if ( !m_pImpl )
2379 throw lang::DisposedException();
2381 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2382 throw uno::RuntimeException();
2386 getRelationshipByID( sID );
2387 return sal_True;
2389 catch( container::NoSuchElementException& )
2392 return sal_False;
2395 //-----------------------------------------------
2396 ::rtl::OUString SAL_CALL OWriteStream::getTargetByID( const ::rtl::OUString& sID )
2397 throw ( container::NoSuchElementException,
2398 io::IOException,
2399 uno::RuntimeException )
2401 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2403 if ( !m_pImpl )
2404 throw lang::DisposedException();
2406 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2407 throw uno::RuntimeException();
2409 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2410 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2411 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Target" ) ) )
2412 return aSeq[nInd].Second;
2414 return ::rtl::OUString();
2417 //-----------------------------------------------
2418 ::rtl::OUString SAL_CALL OWriteStream::getTypeByID( const ::rtl::OUString& sID )
2419 throw ( container::NoSuchElementException,
2420 io::IOException,
2421 uno::RuntimeException )
2423 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2425 if ( !m_pImpl )
2426 throw lang::DisposedException();
2428 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2429 throw uno::RuntimeException();
2431 uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
2432 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
2433 if ( aSeq[nInd].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2434 return aSeq[nInd].Second;
2436 return ::rtl::OUString();
2439 //-----------------------------------------------
2440 uno::Sequence< beans::StringPair > SAL_CALL OWriteStream::getRelationshipByID( const ::rtl::OUString& sID )
2441 throw ( container::NoSuchElementException,
2442 io::IOException,
2443 uno::RuntimeException )
2445 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2447 if ( !m_pImpl )
2448 throw lang::DisposedException();
2450 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2451 throw uno::RuntimeException();
2453 // TODO/LATER: in future the unification of the ID could be checked
2454 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2455 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2456 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2457 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2459 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2460 return aSeq[nInd1];
2461 break;
2464 throw container::NoSuchElementException();
2467 //-----------------------------------------------
2468 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getRelationshipsByType( const ::rtl::OUString& sType )
2469 throw ( io::IOException,
2470 uno::RuntimeException )
2472 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2474 if ( !m_pImpl )
2475 throw lang::DisposedException();
2477 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2478 throw uno::RuntimeException();
2480 uno::Sequence< uno::Sequence< beans::StringPair > > aResult;
2481 sal_Int32 nEntriesNum = 0;
2483 // TODO/LATER: in future the unification of the ID could be checked
2484 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2485 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2486 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2487 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Type" ) ) )
2489 if ( aSeq[nInd1][nInd2].Second.equals( sType ) )
2491 aResult.realloc( nEntriesNum );
2492 aResult[nEntriesNum-1] = aSeq[nInd1];
2494 break;
2497 return aResult;
2500 //-----------------------------------------------
2501 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getAllRelationships()
2502 throw (io::IOException, uno::RuntimeException)
2504 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2506 if ( !m_pImpl )
2507 throw lang::DisposedException();
2509 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2510 throw uno::RuntimeException();
2512 return m_pImpl->GetAllRelationshipsIfAny();
2515 //-----------------------------------------------
2516 void SAL_CALL OWriteStream::insertRelationshipByID( const ::rtl::OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, ::sal_Bool bReplace )
2517 throw ( container::ElementExistException,
2518 io::IOException,
2519 uno::RuntimeException )
2521 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2523 if ( !m_pImpl )
2524 throw lang::DisposedException();
2526 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2527 throw uno::RuntimeException();
2529 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
2531 sal_Int32 nIDInd = -1;
2533 // TODO/LATER: in future the unification of the ID could be checked
2534 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2535 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2536 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2537 if ( aSeq[nInd1][nInd2].First.equals( aIDTag ) )
2539 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2540 nIDInd = nInd1;
2542 break;
2545 if ( nIDInd == -1 || bReplace )
2547 if ( nIDInd == -1 )
2549 nIDInd = aSeq.getLength();
2550 aSeq.realloc( nIDInd + 1 );
2553 aSeq[nIDInd].realloc( aEntry.getLength() + 1 );
2555 aSeq[nIDInd][0].First = aIDTag;
2556 aSeq[nIDInd][0].Second = sID;
2557 sal_Int32 nIndTarget = 1;
2558 for ( sal_Int32 nIndOrig = 0;
2559 nIndOrig < aEntry.getLength();
2560 nIndOrig++ )
2562 if ( !aEntry[nIndOrig].First.equals( aIDTag ) )
2563 aSeq[nIDInd][nIndTarget++] = aEntry[nIndOrig];
2566 aSeq[nIDInd].realloc( nIndTarget );
2568 else
2569 throw container::ElementExistException(); // TODO
2572 m_pImpl->m_aNewRelInfo = aSeq;
2573 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2574 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2577 //-----------------------------------------------
2578 void SAL_CALL OWriteStream::removeRelationshipByID( const ::rtl::OUString& sID )
2579 throw ( container::NoSuchElementException,
2580 io::IOException,
2581 uno::RuntimeException )
2583 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2585 if ( !m_pImpl )
2586 throw lang::DisposedException();
2588 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2589 throw uno::RuntimeException();
2591 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2592 for ( sal_Int32 nInd1 = 0; nInd1 < aSeq.getLength(); nInd1++ )
2593 for ( sal_Int32 nInd2 = 0; nInd2 < aSeq[nInd1].getLength(); nInd2++ )
2594 if ( aSeq[nInd1][nInd2].First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Id" ) ) )
2596 if ( aSeq[nInd1][nInd2].Second.equals( sID ) )
2598 sal_Int32 nLength = aSeq.getLength();
2599 aSeq[nInd1] = aSeq[nLength-1];
2600 aSeq.realloc( nLength - 1 );
2602 m_pImpl->m_aNewRelInfo = aSeq;
2603 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2604 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2606 // TODO/LATER: in future the unification of the ID could be checked
2607 return;
2610 break;
2613 throw container::NoSuchElementException();
2616 //-----------------------------------------------
2617 void SAL_CALL OWriteStream::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, ::sal_Bool bReplace )
2618 throw ( container::ElementExistException,
2619 io::IOException,
2620 uno::RuntimeException )
2622 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2624 if ( !m_pImpl )
2625 throw lang::DisposedException();
2627 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2628 throw uno::RuntimeException();
2630 ::rtl::OUString aIDTag( RTL_CONSTASCII_USTRINGPARAM( "Id" ) );
2631 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
2632 uno::Sequence< uno::Sequence< beans::StringPair > > aResultSeq( aSeq.getLength() + aEntries.getLength() );
2633 sal_Int32 nResultInd = 0;
2635 for ( sal_Int32 nIndTarget1 = 0; nIndTarget1 < aSeq.getLength(); nIndTarget1++ )
2636 for ( sal_Int32 nIndTarget2 = 0; nIndTarget2 < aSeq[nIndTarget1].getLength(); nIndTarget2++ )
2637 if ( aSeq[nIndTarget1][nIndTarget2].First.equals( aIDTag ) )
2639 sal_Int32 nIndSourceSame = -1;
2641 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
2642 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
2644 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
2646 if ( aEntries[nIndSource1][nIndSource2].Second.equals( aSeq[nIndTarget1][nIndTarget2].Second ) )
2648 if ( !bReplace )
2649 throw container::ElementExistException();
2651 nIndSourceSame = nIndSource1;
2654 break;
2658 if ( nIndSourceSame == -1 )
2660 // no such element in the provided sequence
2661 aResultSeq[nResultInd++] = aSeq[nIndTarget1];
2664 break;
2667 for ( sal_Int32 nIndSource1 = 0; nIndSource1 < aEntries.getLength(); nIndSource1++ )
2669 aResultSeq[nResultInd].realloc( aEntries[nIndSource1].getLength() );
2670 sal_Bool bHasID = sal_False;
2671 sal_Int32 nResInd2 = 1;
2673 for ( sal_Int32 nIndSource2 = 0; nIndSource2 < aEntries[nIndSource1].getLength(); nIndSource2++ )
2674 if ( aEntries[nIndSource1][nIndSource2].First.equals( aIDTag ) )
2676 aResultSeq[nResultInd][0] = aEntries[nIndSource1][nIndSource2];
2677 bHasID = sal_True;
2679 else if ( nResInd2 < aResultSeq[nResultInd].getLength() )
2680 aResultSeq[nResultInd][nResInd2++] = aEntries[nIndSource1][nIndSource2];
2681 else
2682 throw io::IOException(); // TODO: illegal relation ( no ID )
2684 if ( !bHasID )
2685 throw io::IOException(); // TODO: illegal relations
2687 nResultInd++;
2690 aResultSeq.realloc( nResultInd );
2691 m_pImpl->m_aNewRelInfo = aResultSeq;
2692 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2693 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2696 //-----------------------------------------------
2697 void SAL_CALL OWriteStream::clearRelationships()
2698 throw ( io::IOException,
2699 uno::RuntimeException )
2701 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2703 if ( !m_pImpl )
2704 throw lang::DisposedException();
2706 if ( m_pData->m_nStorageType != OFOPXML_STORAGE )
2707 throw uno::RuntimeException();
2709 m_pImpl->m_aNewRelInfo.realloc( 0 );
2710 m_pImpl->m_xNewRelInfoStream = uno::Reference< io::XInputStream >();
2711 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
2714 //-----------------------------------------------
2715 uno::Reference< beans::XPropertySetInfo > SAL_CALL OWriteStream::getPropertySetInfo()
2716 throw ( uno::RuntimeException )
2718 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2720 //TODO:
2721 return uno::Reference< beans::XPropertySetInfo >();
2724 //-----------------------------------------------
2725 void SAL_CALL OWriteStream::setPropertyValue( const ::rtl::OUString& aPropertyName, const uno::Any& aValue )
2726 throw ( beans::UnknownPropertyException,
2727 beans::PropertyVetoException,
2728 lang::IllegalArgumentException,
2729 lang::WrappedTargetException,
2730 uno::RuntimeException )
2732 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2734 if ( !m_pImpl )
2735 throw lang::DisposedException();
2737 m_pImpl->GetStreamProperties();
2739 if ( ( m_pData->m_nStorageType == PACKAGE_STORAGE || m_pData->m_nStorageType == OFOPXML_STORAGE )
2740 && aPropertyName.equalsAscii( "MediaType" )
2741 || aPropertyName.equalsAscii( "Compressed" ) )
2743 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
2745 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
2746 m_pImpl->m_aProps[nInd].Value = aValue;
2749 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
2750 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
2752 sal_Bool bUseCommonPass = sal_False;
2753 if ( aValue >>= bUseCommonPass )
2755 if ( m_bInitOnDemand && m_pImpl->m_bHasInsertedStreamOptimization )
2757 // the data stream is provided to the packagestream directly
2758 m_pImpl->m_bUseCommonPass = bUseCommonPass;
2760 else if ( bUseCommonPass )
2762 if ( !m_pImpl->m_bUseCommonPass )
2764 m_pImpl->SetDecrypted();
2765 m_pImpl->m_bUseCommonPass = sal_True;
2768 else
2769 m_pImpl->m_bUseCommonPass = sal_False;
2771 else
2772 throw lang::IllegalArgumentException(); //TODO
2774 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE && aPropertyName.equalsAscii( "RelationsInfoStream" ) )
2776 uno::Reference< io::XInputStream > xInRelStream;
2777 if ( ( aValue >>= xInRelStream ) && xInRelStream.is() )
2779 uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY );
2780 if ( !xSeek.is() )
2782 // currently this is an internal property that is used for optimization
2783 // and the stream must support XSeekable interface
2784 // TODO/LATER: in future it can be changed if property is used from outside
2785 throw lang::IllegalArgumentException(); // TODO
2788 m_pImpl->m_xNewRelInfoStream = xInRelStream;
2789 m_pImpl->m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
2790 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM;
2792 else
2793 throw lang::IllegalArgumentException(); // TODO
2795 else if ( m_pData->m_nStorageType == OFOPXML_STORAGE && aPropertyName.equalsAscii( "RelationsInfo" ) )
2797 if ( aValue >>= m_pImpl->m_aNewRelInfo )
2800 else
2801 throw lang::IllegalArgumentException(); // TODO
2803 else if ( aPropertyName.equalsAscii( "Size" ) )
2804 throw beans::PropertyVetoException(); // TODO
2805 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
2806 && ( aPropertyName.equalsAscii( "IsEncrypted" ) || aPropertyName.equalsAscii( "Encrypted" ) ) )
2807 throw beans::PropertyVetoException(); // TODO
2808 else
2809 throw beans::UnknownPropertyException(); // TODO
2811 m_pImpl->m_bHasDataToFlush = sal_True;
2812 ModifyParentUnlockMutex_Impl( aGuard );
2816 //-----------------------------------------------
2817 uno::Any SAL_CALL OWriteStream::getPropertyValue( const ::rtl::OUString& aProp )
2818 throw ( beans::UnknownPropertyException,
2819 lang::WrappedTargetException,
2820 uno::RuntimeException )
2822 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2824 if ( !m_pImpl )
2825 throw lang::DisposedException();
2827 if ( aProp.equalsAscii( "RelId" ) )
2829 return uno::makeAny( m_pImpl->GetNewRelId() );
2832 ::rtl::OUString aPropertyName;
2833 if ( aProp.equalsAscii( "IsEncrypted" ) )
2834 aPropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) );
2835 else
2836 aPropertyName = aProp;
2838 if ( ( m_pData->m_nStorageType == PACKAGE_STORAGE || m_pData->m_nStorageType == OFOPXML_STORAGE )
2839 && aPropertyName.equalsAscii( "MediaType" )
2840 || m_pData->m_nStorageType == PACKAGE_STORAGE && aPropertyName.equalsAscii( "Encrypted" )
2841 || aPropertyName.equalsAscii( "Compressed" ) )
2843 m_pImpl->GetStreamProperties();
2845 for ( sal_Int32 nInd = 0; nInd < m_pImpl->m_aProps.getLength(); nInd++ )
2847 if ( aPropertyName.equals( m_pImpl->m_aProps[nInd].Name ) )
2848 return m_pImpl->m_aProps[nInd].Value;
2851 else if ( m_pData->m_nStorageType == PACKAGE_STORAGE
2852 && aPropertyName.equalsAscii( "UseCommonStoragePasswordEncryption" ) )
2853 return uno::makeAny( m_pImpl->m_bUseCommonPass );
2854 else if ( aPropertyName.equalsAscii( "Size" ) )
2856 CheckInitOnDemand();
2858 if ( !m_xSeekable.is() )
2859 throw uno::RuntimeException();
2861 return uno::makeAny( (sal_Int32)m_xSeekable->getLength() );
2864 throw beans::UnknownPropertyException(); // TODO
2868 //-----------------------------------------------
2869 void SAL_CALL OWriteStream::addPropertyChangeListener(
2870 const ::rtl::OUString& /*aPropertyName*/,
2871 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
2872 throw ( beans::UnknownPropertyException,
2873 lang::WrappedTargetException,
2874 uno::RuntimeException )
2876 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2878 if ( !m_pImpl )
2879 throw lang::DisposedException();
2881 //TODO:
2885 //-----------------------------------------------
2886 void SAL_CALL OWriteStream::removePropertyChangeListener(
2887 const ::rtl::OUString& /*aPropertyName*/,
2888 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
2889 throw ( beans::UnknownPropertyException,
2890 lang::WrappedTargetException,
2891 uno::RuntimeException )
2893 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2895 if ( !m_pImpl )
2896 throw lang::DisposedException();
2898 //TODO:
2902 //-----------------------------------------------
2903 void SAL_CALL OWriteStream::addVetoableChangeListener(
2904 const ::rtl::OUString& /*PropertyName*/,
2905 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
2906 throw ( beans::UnknownPropertyException,
2907 lang::WrappedTargetException,
2908 uno::RuntimeException )
2910 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2912 if ( !m_pImpl )
2913 throw lang::DisposedException();
2915 //TODO:
2919 //-----------------------------------------------
2920 void SAL_CALL OWriteStream::removeVetoableChangeListener(
2921 const ::rtl::OUString& /*PropertyName*/,
2922 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
2923 throw ( beans::UnknownPropertyException,
2924 lang::WrappedTargetException,
2925 uno::RuntimeException )
2927 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
2929 if ( !m_pImpl )
2930 throw lang::DisposedException();
2932 //TODO:
2935 //____________________________________________________________________________________________________
2936 // XTransactedObject
2937 //____________________________________________________________________________________________________
2939 //-----------------------------------------------
2940 void OWriteStream::BroadcastTransaction( sal_Int8 nMessage )
2942 1 - preCommit
2943 2 - commited
2944 3 - preRevert
2945 4 - reverted
2948 // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
2949 if ( !m_pImpl )
2950 throw lang::DisposedException();
2952 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
2954 ::cppu::OInterfaceContainerHelper* pContainer =
2955 m_pData->m_aListenersContainer.getContainer(
2956 ::getCppuType( ( const uno::Reference< embed::XTransactionListener >*) NULL ) );
2957 if ( pContainer )
2959 ::cppu::OInterfaceIteratorHelper pIterator( *pContainer );
2960 while ( pIterator.hasMoreElements( ) )
2962 OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!\n" );
2964 switch( nMessage )
2966 case STOR_MESS_PRECOMMIT:
2967 ( ( embed::XTransactionListener* )pIterator.next( ) )->preCommit( aSource );
2968 break;
2969 case STOR_MESS_COMMITED:
2970 ( ( embed::XTransactionListener* )pIterator.next( ) )->commited( aSource );
2971 break;
2972 case STOR_MESS_PREREVERT:
2973 ( ( embed::XTransactionListener* )pIterator.next( ) )->preRevert( aSource );
2974 break;
2975 case STOR_MESS_REVERTED:
2976 ( ( embed::XTransactionListener* )pIterator.next( ) )->reverted( aSource );
2977 break;
2982 //-----------------------------------------------
2983 void SAL_CALL OWriteStream::commit()
2984 throw ( io::IOException,
2985 embed::StorageWrappedTargetException,
2986 uno::RuntimeException )
2988 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::commit" );
2990 if ( !m_pImpl )
2991 throw lang::DisposedException();
2993 if ( !m_bTransacted )
2994 throw uno::RuntimeException();
2996 try {
2997 BroadcastTransaction( STOR_MESS_PRECOMMIT );
2999 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3001 if ( !m_pImpl )
3002 throw lang::DisposedException();
3004 m_pImpl->Commit();
3006 // when the storage is commited the parent is modified
3007 ModifyParentUnlockMutex_Impl( aGuard );
3009 catch( io::IOException& )
3011 throw;
3013 catch( embed::StorageWrappedTargetException& )
3015 throw;
3017 catch( uno::RuntimeException& )
3019 throw;
3021 catch( uno::Exception& )
3023 uno::Any aCaught( ::cppu::getCaughtException() );
3024 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on commit!" ),
3025 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3026 aCaught );
3029 BroadcastTransaction( STOR_MESS_COMMITED );
3032 //-----------------------------------------------
3033 void SAL_CALL OWriteStream::revert()
3034 throw ( io::IOException,
3035 embed::StorageWrappedTargetException,
3036 uno::RuntimeException )
3038 RTL_LOGFILE_CONTEXT( aLog, "package (mv76033) OWriteStream::revert" );
3040 // the method removes all the changes done after last commit
3042 if ( !m_pImpl )
3043 throw lang::DisposedException();
3045 if ( !m_bTransacted )
3046 throw uno::RuntimeException();
3048 BroadcastTransaction( STOR_MESS_PREREVERT );
3050 ::osl::ResettableMutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3052 if ( !m_pImpl )
3053 throw lang::DisposedException();
3055 try {
3056 m_pImpl->Revert();
3058 catch( io::IOException& )
3060 throw;
3062 catch( embed::StorageWrappedTargetException& )
3064 throw;
3066 catch( uno::RuntimeException& )
3068 throw;
3070 catch( uno::Exception& )
3072 uno::Any aCaught( ::cppu::getCaughtException() );
3073 throw embed::StorageWrappedTargetException( ::rtl::OUString::createFromAscii( "Problems on revert!" ),
3074 uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ),
3075 aCaught );
3078 aGuard.clear();
3080 BroadcastTransaction( STOR_MESS_REVERTED );
3083 //____________________________________________________________________________________________________
3084 // XTransactionBroadcaster
3085 //____________________________________________________________________________________________________
3087 //-----------------------------------------------
3088 void SAL_CALL OWriteStream::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3089 throw ( uno::RuntimeException )
3091 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3093 if ( !m_pImpl )
3094 throw lang::DisposedException();
3096 if ( !m_bTransacted )
3097 throw uno::RuntimeException();
3099 m_pData->m_aListenersContainer.addInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3100 aListener );
3103 //-----------------------------------------------
3104 void SAL_CALL OWriteStream::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3105 throw ( uno::RuntimeException )
3107 ::osl::MutexGuard aGuard( m_pData->m_rSharedMutexRef->GetMutex() );
3109 if ( !m_pImpl )
3110 throw lang::DisposedException();
3112 if ( !m_bTransacted )
3113 throw uno::RuntimeException();
3115 m_pData->m_aListenersContainer.removeInterface( ::getCppuType((const uno::Reference< embed::XTransactionListener >*)0),
3116 aListener );