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