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