cid#1606940 Check of thread-shared field evades lock acquisition
[LibreOffice.git] / package / source / xstor / xstorage.cxx
blob2dbb2077fec45a11cfff4b044abcb4493e931de1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
24 #include <cassert>
25 #include <string_view>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <com/sun/star/embed/InvalidStorageException.hpp>
30 #include <com/sun/star/embed/UseBackupException.hpp>
31 #include <com/sun/star/embed/StorageFormats.hpp>
32 #include <com/sun/star/embed/StorageWrappedTargetException.hpp>
33 #include <com/sun/star/packages/NoEncryptionException.hpp>
34 #include <com/sun/star/packages/NoRawFormatException.hpp>
35 #include <com/sun/star/packages/WrongPasswordException.hpp>
36 #include <com/sun/star/io/TempFile.hpp>
37 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
38 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39 #include <com/sun/star/container/XEnumerationAccess.hpp>
40 #include <com/sun/star/container/XNamed.hpp>
41 #include <com/sun/star/util/XChangesBatch.hpp>
43 #include <com/sun/star/lang/XComponent.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
46 #include <com/sun/star/beans/NamedValue.hpp>
48 #include <PackageConstants.hxx>
50 #include <comphelper/sequence.hxx>
51 #include <cppuhelper/queryinterface.hxx>
52 #include <cppuhelper/exc_hlp.hxx>
54 #include <comphelper/servicehelper.hxx>
55 #include <comphelper/storagehelper.hxx>
56 #include <comphelper/ofopxmlhelper.hxx>
57 #include <utility>
58 #include <comphelper/diagnose_ex.hxx>
60 #include "xstorage.hxx"
61 #include "owriteablestream.hxx"
62 #include "switchpersistencestream.hxx"
64 using namespace ::com::sun::star;
66 #if OSL_DEBUG_LEVEL > 0
67 #define THROW_WHERE SAL_WHERE
68 #else
69 #define THROW_WHERE ""
70 #endif
72 // static
73 void OStorage_Impl::completeStorageStreamCopy_Impl(
74 const uno::Reference< io::XStream >& xSource,
75 const uno::Reference< io::XStream >& xDest,
76 sal_Int32 nStorageType,
77 const uno::Sequence< uno::Sequence< beans::StringPair > >& aRelInfo )
79 uno::Reference< beans::XPropertySet > xSourceProps( xSource, uno::UNO_QUERY_THROW );
80 uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY_THROW );
82 uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream();
83 if ( !xDestOutStream.is() )
84 throw io::IOException( THROW_WHERE );
86 uno::Reference< io::XInputStream > xSourceInStream = xSource->getInputStream();
87 if ( !xSourceInStream.is() )
88 throw io::IOException( THROW_WHERE );
90 // TODO: headers of encrypted streams should be copied also
91 ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInStream, xDestOutStream );
93 uno::Sequence<OUString> aPropNames { u"Compressed"_ustr, u"MediaType"_ustr,
94 u"UseCommonStoragePasswordEncryption"_ustr };
96 if ( nStorageType == embed::StorageFormats::OFOPXML )
98 // TODO/LATER: in future it might make sense to provide the stream if there is one
99 uno::Reference< embed::XRelationshipAccess > xRelAccess( xDest, uno::UNO_QUERY_THROW );
100 xRelAccess->clearRelationships();
101 xRelAccess->insertRelationships( aRelInfo, false );
103 aPropNames.realloc( 2 );
105 else if ( nStorageType != embed::StorageFormats::PACKAGE )
107 aPropNames.realloc( 1 );
110 for (const auto& rPropName : aPropNames)
111 xDestProps->setPropertyValue( rPropName, xSourceProps->getPropertyValue( rPropName ) );
114 static uno::Reference< io::XInputStream > GetSeekableTempCopy( const uno::Reference< io::XInputStream >& xInStream )
116 rtl::Reference < utl::TempFileFastService > xTempFile = new utl::TempFileFastService;
117 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
118 uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();
120 if ( !xTempOut.is() || !xTempIn.is() )
121 throw io::IOException( THROW_WHERE );
123 ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut );
124 xTempOut->closeOutput();
126 return xTempIn;
129 SotElement_Impl::SotElement_Impl(OUString aName, bool bStor, bool bNew)
130 : m_aOriginalName(std::move(aName))
131 , m_bIsRemoved(false)
132 , m_bIsInserted(bNew)
133 , m_bIsStorage(bStor)
137 // most of properties are holt by the storage but are not used
138 OStorage_Impl::OStorage_Impl( uno::Reference< io::XInputStream > const & xInputStream,
139 sal_Int32 nMode,
140 const uno::Sequence< beans::PropertyValue >& xProperties,
141 uno::Reference< uno::XComponentContext > const & xContext,
142 sal_Int32 nStorageType )
143 : m_xMutex( new comphelper::RefCountedMutex )
144 , m_pAntiImpl( nullptr )
145 , m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
146 , m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
147 , m_bBroadcastModified( false )
148 , m_bCommited( false )
149 , m_bIsRoot( true )
150 , m_bListCreated( false )
151 , m_nModifiedListenerCount( 0 )
152 , m_xContext( xContext )
153 , m_xProperties( xProperties )
154 , m_bHasCommonEncryptionData( false )
155 , m_pParent( nullptr )
156 , m_bControlMediaType( false )
157 , m_bMTFallbackUsed( false )
158 , m_bControlVersion( false )
159 , m_nStorageType( nStorageType )
160 , m_pRelStorElement( nullptr )
161 , m_nRelInfoStatus( RELINFO_NO_INIT )
163 // all the checks done below by assertion statements must be done by factory
164 SAL_WARN_IF( !xInputStream.is(), "package.xstor", "No input stream is provided!" );
165 assert(xContext.is());
167 m_pSwitchStream = new SwitchablePersistenceStream(xInputStream);
168 m_xInputStream = m_pSwitchStream->getInputStream();
170 if ( m_nStorageMode & embed::ElementModes::WRITE )
172 // check that the stream allows to write
173 SAL_WARN( "package.xstor", "No stream for writing is provided!" );
177 // most of properties are holt by the storage but are not used
178 OStorage_Impl::OStorage_Impl( uno::Reference< io::XStream > const & xStream,
179 sal_Int32 nMode,
180 const uno::Sequence< beans::PropertyValue >& xProperties,
181 uno::Reference< uno::XComponentContext > const & xContext,
182 sal_Int32 nStorageType )
183 : m_xMutex( new comphelper::RefCountedMutex )
184 , m_pAntiImpl( nullptr )
185 , m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
186 , m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
187 , m_bBroadcastModified( false )
188 , m_bCommited( false )
189 , m_bIsRoot( true )
190 , m_bListCreated( false )
191 , m_nModifiedListenerCount( 0 )
192 , m_xContext( xContext )
193 , m_xProperties( xProperties )
194 , m_bHasCommonEncryptionData( false )
195 , m_pParent( nullptr )
196 , m_bControlMediaType( false )
197 , m_bMTFallbackUsed( false )
198 , m_bControlVersion( false )
199 , m_nStorageType( nStorageType )
200 , m_pRelStorElement( nullptr )
201 , m_nRelInfoStatus( RELINFO_NO_INIT )
203 // all the checks done below by assertion statements must be done by factory
204 SAL_WARN_IF( !xStream.is(), "package.xstor", "No stream is provided!" );
205 assert(xContext.is());
207 if ( m_nStorageMode & embed::ElementModes::WRITE )
209 m_pSwitchStream = new SwitchablePersistenceStream(xStream);
210 m_xStream = m_pSwitchStream.get();
212 else
214 m_pSwitchStream = new SwitchablePersistenceStream(xStream->getInputStream());
215 m_xInputStream = m_pSwitchStream->getInputStream();
219 OStorage_Impl::OStorage_Impl( OStorage_Impl* pParent,
220 sal_Int32 nMode,
221 uno::Reference< container::XNameContainer > const & xPackageFolder,
222 uno::Reference< lang::XSingleServiceFactory > xPackage,
223 uno::Reference< uno::XComponentContext > const & xContext,
224 sal_Int32 nStorageType )
225 : m_xMutex( new comphelper::RefCountedMutex )
226 , m_pAntiImpl( nullptr )
227 , m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
228 , m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
229 , m_bBroadcastModified( false )
230 , m_bCommited( false )
231 , m_bIsRoot( false )
232 , m_bListCreated( false )
233 , m_nModifiedListenerCount( 0 )
234 , m_xPackageFolder( xPackageFolder )
235 , m_xPackage(std::move( xPackage ))
236 , m_xContext( xContext )
237 , m_bHasCommonEncryptionData( false )
238 , m_pParent( pParent ) // can be empty in case of temporary readonly substorages and relation storage
239 , m_bControlMediaType( false )
240 , m_bMTFallbackUsed( false )
241 , m_bControlVersion( false )
242 , m_nStorageType( nStorageType )
243 , m_pRelStorElement( nullptr )
244 , m_nRelInfoStatus( RELINFO_NO_INIT )
246 SAL_WARN_IF( !xPackageFolder.is(), "package.xstor", "No package folder!" );
247 assert(xContext.is());
250 OStorage_Impl::~OStorage_Impl()
253 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
254 if ( m_pAntiImpl ) // root storage wrapper must set this member to NULL before destruction of object
256 SAL_WARN_IF( m_bIsRoot, "package.xstor", "The root storage wrapper must be disposed already" );
258 try {
259 m_pAntiImpl->InternalDispose( false );
261 catch ( const uno::Exception& )
263 TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
265 m_pAntiImpl = nullptr;
267 else if ( !m_aReadOnlyWrapVector.empty() )
269 for ( auto& rStorage : m_aReadOnlyWrapVector )
271 uno::Reference< embed::XStorage > xTmp = rStorage.m_xWeakRef;
272 if ( xTmp.is() )
273 try {
274 rStorage.m_pPointer->InternalDispose( false );
275 } catch( const uno::Exception& )
277 TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
281 m_aReadOnlyWrapVector.clear();
284 m_pParent = nullptr;
287 for (const auto & pair : m_aChildrenMap)
288 for (auto pElement : pair.second)
289 delete pElement;
290 m_aChildrenMap.clear();
292 std::for_each(m_aDeletedVector.begin(), m_aDeletedVector.end(), std::default_delete<SotElement_Impl>());
293 m_aDeletedVector.clear();
295 if ( m_nStorageType == embed::StorageFormats::OFOPXML && m_pRelStorElement )
297 delete m_pRelStorElement;
298 m_pRelStorElement = nullptr;
301 m_xPackageFolder.clear();
302 m_xPackage.clear();
304 OUString aPropertyName = u"URL"_ustr;
305 for (const auto& rProp : m_xProperties)
307 if ( rProp.Name == aPropertyName )
309 // the storage is URL based so all the streams are opened by factory and should be closed
312 if ( m_xInputStream.is() )
314 m_xInputStream->closeInput();
315 m_xInputStream.clear();
318 if ( m_xStream.is() )
320 uno::Reference< io::XInputStream > xInStr = m_xStream->getInputStream();
321 if ( xInStr.is() )
322 xInStr->closeInput();
324 uno::Reference< io::XOutputStream > xOutStr = m_xStream->getOutputStream();
325 if ( xOutStr.is() )
326 xOutStr->closeOutput();
328 m_xStream.clear();
331 catch (const uno::Exception&)
333 TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
339 void OStorage_Impl::SetReadOnlyWrap( OStorage& aStorage )
341 // Weak reference is used inside the holder so the refcount must not be zero at this point
342 OSL_ENSURE( aStorage.GetRefCount_Impl(), "There must be a reference alive to use this method!" );
343 m_aReadOnlyWrapVector.emplace_back( &aStorage );
346 void OStorage_Impl::RemoveReadOnlyWrap( const OStorage& aStorage )
348 for ( StorageHoldersType::iterator pStorageIter = m_aReadOnlyWrapVector.begin();
349 pStorageIter != m_aReadOnlyWrapVector.end();)
351 uno::Reference< embed::XStorage > xTmp = pStorageIter->m_xWeakRef;
352 if ( !xTmp.is() || pStorageIter->m_pPointer == &aStorage )
354 try {
355 pStorageIter->m_pPointer->InternalDispose( false );
356 } catch( const uno::Exception& )
358 TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
361 pStorageIter = m_aReadOnlyWrapVector.erase(pStorageIter);
363 else
364 ++pStorageIter;
368 void OStorage_Impl::OpenOwnPackage()
370 SAL_WARN_IF( !m_bIsRoot, "package.xstor", "Opening of the package has no sense!" );
372 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
374 if ( !m_xPackageFolder.is() )
376 if ( !m_xPackage.is() )
378 uno::Sequence< uno::Any > aArguments( 2 );
379 auto pArguments = aArguments.getArray();
380 if ( m_nStorageMode & embed::ElementModes::WRITE )
381 pArguments[ 0 ] <<= css::uno::Reference< css::io::XStream >(m_xStream);
382 else
384 SAL_WARN_IF( !m_xInputStream.is(), "package.xstor", "Input stream must be set for readonly access!" );
385 pArguments[ 0 ] <<= m_xInputStream;
386 // TODO: if input stream is not seekable or XSeekable interface is supported
387 // on XStream object a wrapper must be used
390 // do not allow elements to remove themself from the old container in case of insertion to another container
391 pArguments[ 1 ] <<= beans::NamedValue( u"AllowRemoveOnInsert"_ustr,
392 uno::Any( false ) );
394 sal_Int32 nArgNum = 2;
395 for (const auto& rProp : m_xProperties)
397 if ( rProp.Name == "RepairPackage"
398 || rProp.Name == "ProgressHandler"
399 || rProp.Name == "NoFileSync" )
401 // Forward these to the package.
402 beans::NamedValue aNamedValue( rProp.Name, rProp.Value );
403 aArguments.realloc( ++nArgNum );
404 pArguments = aArguments.getArray();
405 pArguments[nArgNum-1] <<= aNamedValue;
406 if (rProp.Name == "RepairPackage")
407 rProp.Value >>= m_bRepairPackage;
409 else if ( rProp.Name == "Password" )
411 // TODO: implement password setting for documents
412 // the password entry must be removed after setting
416 if ( m_nStorageType == embed::StorageFormats::ZIP )
418 // let the package support only plain zip format
419 beans::NamedValue aNamedValue;
420 aNamedValue.Name = "StorageFormat";
421 aNamedValue.Value <<= u"ZipFormat"_ustr;
422 aArguments.realloc( ++nArgNum );
423 pArguments = aArguments.getArray();
424 pArguments[nArgNum-1] <<= aNamedValue;
426 else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
428 // let the package support OFOPXML media type handling
429 beans::NamedValue aNamedValue;
430 aNamedValue.Name = "StorageFormat";
431 aNamedValue.Value <<= u"OFOPXMLFormat"_ustr;
432 aArguments.realloc( ++nArgNum );
433 pArguments = aArguments.getArray();
434 pArguments[nArgNum-1] <<= aNamedValue;
437 m_xPackage.set( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
438 u"com.sun.star.packages.comp.ZipPackage"_ustr, aArguments, m_xContext),
439 uno::UNO_QUERY );
442 uno::Reference< container::XHierarchicalNameAccess > xHNameAccess( m_xPackage, uno::UNO_QUERY );
443 SAL_WARN_IF( !xHNameAccess.is(), "package.xstor", "The package could not be created!" );
445 if ( xHNameAccess.is() )
447 uno::Any aFolder = xHNameAccess->getByHierarchicalName(u"/"_ustr);
448 aFolder >>= m_xPackageFolder;
452 SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "The package root folder can not be opened!" );
453 if ( !m_xPackageFolder.is() )
454 throw embed::InvalidStorageException( THROW_WHERE );
457 bool OStorage_Impl::HasChildren()
459 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
461 ReadContents();
462 return !m_aChildrenMap.empty();
465 void OStorage_Impl::GetStorageProperties()
467 if ( m_nStorageType != embed::StorageFormats::PACKAGE )
468 return;
470 uno::Reference< beans::XPropertySet > xProps( m_xPackageFolder, uno::UNO_QUERY_THROW );
472 if ( !m_bControlMediaType )
474 uno::Reference< beans::XPropertySet > xPackageProps( m_xPackage, uno::UNO_QUERY_THROW );
475 xPackageProps->getPropertyValue( MEDIATYPE_FALLBACK_USED_PROPERTY ) >>= m_bMTFallbackUsed;
477 static constexpr OUStringLiteral sMediaType(u"MediaType");
478 xProps->getPropertyValue( sMediaType ) >>= m_aMediaType;
479 m_bControlMediaType = true;
482 if ( !m_bControlVersion )
484 xProps->getPropertyValue( u"Version"_ustr ) >>= m_aVersion;
485 m_bControlVersion = true;
488 // the properties of OFOPXML will be handled directly
491 void OStorage_Impl::ReadRelInfoIfNecessary()
493 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
494 return;
496 if ( m_nRelInfoStatus == RELINFO_NO_INIT )
498 // Init from original stream
499 uno::Reference< io::XInputStream > xRelInfoStream
500 = GetRelInfoStreamForName( std::u16string_view() );
503 if ( xRelInfoStream.is() )
504 m_aRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
505 xRelInfoStream,
506 u"_rels/.rels",
507 m_xContext );
508 m_nRelInfoStatus = RELINFO_READ;
510 catch (css::uno::Exception &)
512 TOOLS_INFO_EXCEPTION("package.xstor", "");
515 else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
517 // Init from the new stream
520 if ( m_xNewRelInfoStream.is() )
521 m_aRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
522 m_xNewRelInfoStream,
523 u"_rels/.rels",
524 m_xContext );
526 m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ;
528 catch( const uno::Exception& )
530 m_nRelInfoStatus = RELINFO_CHANGED_BROKEN;
535 void OStorage_Impl::ReadContents()
537 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
539 if ( m_bListCreated )
540 return;
542 if ( m_bIsRoot )
543 OpenOwnPackage();
545 uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xPackageFolder, uno::UNO_QUERY_THROW );
546 uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
547 if ( !xEnum.is() )
548 throw uno::RuntimeException( THROW_WHERE );
550 m_bListCreated = true;
552 while( xEnum->hasMoreElements() )
554 try {
555 uno::Reference< container::XNamed > xNamed;
556 xEnum->nextElement() >>= xNamed;
558 if ( !xNamed.is() )
560 SAL_WARN( "package.xstor", "XNamed is not supported!" );
561 throw uno::RuntimeException( THROW_WHERE );
564 OUString aName = xNamed->getName();
565 SAL_WARN_IF( aName.isEmpty(), "package.xstor", "Empty name!" );
567 uno::Reference< container::XNameContainer > xNameContainer( xNamed, uno::UNO_QUERY );
569 std::unique_ptr<SotElement_Impl> xNewElement(new SotElement_Impl(aName, xNameContainer.is(), false));
570 if ( m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
572 if (!xNewElement->m_bIsStorage)
573 throw io::IOException( THROW_WHERE ); // TODO: Unexpected format
575 m_pRelStorElement = xNewElement.release();
576 CreateRelStorage();
578 else
580 if ( ( m_nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
582 // if a storage is truncated all of it elements are marked as deleted
583 xNewElement->m_bIsRemoved = true;
586 m_aChildrenMap[aName].push_back(xNewElement.release());
589 catch( const container::NoSuchElementException& )
591 TOOLS_WARN_EXCEPTION( "package.xstor", "hasMoreElements() implementation has problems!");
592 break;
595 if ( ( m_nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
597 // if a storage is truncated the relations information should be cleaned
598 m_xNewRelInfoStream.clear();
599 m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
600 m_nRelInfoStatus = RELINFO_CHANGED;
603 // cache changeable folder properties
604 GetStorageProperties();
607 void OStorage_Impl::CopyToStorage( const uno::Reference< embed::XStorage >& xDest, bool bDirect )
609 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
611 uno::Reference< beans::XPropertySet > xPropSet( xDest, uno::UNO_QUERY );
612 if ( !xPropSet.is() )
613 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
615 sal_Int32 nDestMode = embed::ElementModes::READ;
616 xPropSet->getPropertyValue( u"OpenMode"_ustr ) >>= nDestMode;
618 if ( !( nDestMode & embed::ElementModes::WRITE ) )
619 throw io::IOException( THROW_WHERE ); // TODO: access_denied
621 ReadContents();
623 if ( !m_xPackageFolder.is() )
624 throw embed::InvalidStorageException( THROW_WHERE );
626 for ( const auto& pair : m_aChildrenMap )
627 for (auto pElement : pair.second)
629 if ( !pElement->m_bIsRemoved )
630 CopyStorageElement( pElement, xDest, /*aName*/pair.first, bDirect );
633 // move storage properties to the destination one ( means changeable properties )
634 if ( m_nStorageType == embed::StorageFormats::PACKAGE )
636 xPropSet->setPropertyValue( u"MediaType"_ustr, uno::Any( m_aMediaType ) );
637 xPropSet->setPropertyValue( u"Version"_ustr, uno::Any( m_aVersion ) );
640 if ( m_nStorageType == embed::StorageFormats::PACKAGE )
642 // if this is a root storage, the common key from current one should be moved there
643 bool bIsRoot = false;
644 if ( ( xPropSet->getPropertyValue( u"IsRoot"_ustr ) >>= bIsRoot ) && bIsRoot )
648 uno::Reference< embed::XEncryptionProtectedStorage > xEncr( xDest, uno::UNO_QUERY );
649 if ( xEncr.is() )
651 xEncr->setEncryptionData( GetCommonRootEncryptionData().getAsConstNamedValueList() );
653 uno::Sequence< beans::NamedValue > aAlgorithms;
654 uno::Reference< beans::XPropertySet > xPackPropSet( m_xPackage, uno::UNO_QUERY_THROW );
655 xPackPropSet->getPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY )
656 >>= aAlgorithms;
657 xEncr->setEncryptionAlgorithms( aAlgorithms );
660 catch( const packages::NoEncryptionException& )
662 TOOLS_INFO_EXCEPTION("package.xstor", "No Encryption");
666 else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
669 // TODO/LATER: currently the optimization is not active
670 // uno::Reference< io::XInputStream > xRelInfoStream = GetRelInfoStreamForName( OUString() ); // own stream
671 // if ( xRelInfoStream.is() )
672 // {
673 // // Relations info stream is a writeonly property, introduced only to optimize copying
674 // // Should be used carefully since no check for stream consistency is done, and the stream must not stay locked
676 // OUString aRelInfoString = "RelationsInfoStream";
677 // xPropSet->setPropertyValue( aRelInfoString, uno::makeAny( GetSeekableTempCopy( xRelInfoStream, m_xFactory ) ) );
678 // }
680 uno::Reference< embed::XRelationshipAccess > xRels( xDest, uno::UNO_QUERY );
681 if ( !xRels.is() )
682 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
684 xRels->insertRelationships( GetAllRelationshipsIfAny(), false );
687 // if possible the destination storage should be committed after successful copying
688 uno::Reference< embed::XTransactedObject > xObjToCommit( xDest, uno::UNO_QUERY );
689 if ( xObjToCommit.is() )
690 xObjToCommit->commit();
693 void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
694 const uno::Reference< embed::XStorage >& xDest,
695 const OUString& aName,
696 bool bDirect )
698 SAL_WARN_IF( !xDest.is(), "package.xstor", "No destination storage!" );
699 SAL_WARN_IF( aName.isEmpty(), "package.xstor", "Empty element name!" );
701 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
703 uno::Reference< container::XNameAccess > xDestAccess( xDest, uno::UNO_QUERY_THROW );
704 if ( xDestAccess->hasByName( aName )
705 && !( pElement->m_bIsStorage && xDest->isStorageElement( aName ) ) )
706 xDest->removeElement( aName );
708 if ( pElement->m_bIsStorage )
710 uno::Reference< embed::XStorage > xSubDest =
711 xDest->openStorageElement( aName,
712 embed::ElementModes::WRITE );
714 SAL_WARN_IF( !xSubDest.is(), "package.xstor", "No destination substorage!" );
716 if (!pElement->m_xStorage)
718 OpenSubStorage( pElement, embed::ElementModes::READ );
719 if (!pElement->m_xStorage)
720 throw io::IOException( THROW_WHERE );
723 pElement->m_xStorage->CopyToStorage(xSubDest, bDirect);
725 else
727 if (!pElement->m_xStream)
729 OpenSubStream( pElement );
730 if (!pElement->m_xStream)
731 throw io::IOException( THROW_WHERE );
734 if (!pElement->m_xStream->IsEncrypted())
736 if ( bDirect )
738 // fill in the properties for the stream
739 uno::Sequence< beans::PropertyValue > aStrProps(0);
740 const uno::Sequence< beans::PropertyValue > aSrcPkgProps = pElement->m_xStream->GetStreamProperties();
741 sal_Int32 nNum = 0;
742 for ( const auto& rSrcPkgProp : aSrcPkgProps )
744 if ( rSrcPkgProp.Name == "MediaType" || rSrcPkgProp.Name == "Compressed" )
746 aStrProps.realloc( ++nNum );
747 auto pStrProps = aStrProps.getArray();
748 pStrProps[nNum-1].Name = rSrcPkgProp.Name;
749 pStrProps[nNum-1].Value = rSrcPkgProp.Value;
753 if ( m_nStorageType == embed::StorageFormats::PACKAGE )
755 aStrProps.realloc( ++nNum );
756 auto pStrProps = aStrProps.getArray();
757 pStrProps[nNum-1].Name = "UseCommonStoragePasswordEncryption";
758 pStrProps[nNum-1].Value <<= pElement->m_xStream->UsesCommonEncryption_Impl();
760 else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
762 // TODO/LATER: currently the optimization is not active
763 // uno::Reference< io::XInputStream > xInStream = GetRelInfoStreamForName( OUString() ); // own rels stream
764 // if ( xInStream.is() )
765 // {
766 // aStrProps.realloc( ++nNum );
767 // aStrProps[nNum-1].Name = "RelationsInfoStream";
768 // aStrProps[nNum-1].Value <<= GetSeekableTempCopy( xInStream, m_xFactory );
769 // }
771 uno::Reference< embed::XRelationshipAccess > xRels( xDest, uno::UNO_QUERY );
772 if ( !xRels.is() )
773 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
775 xRels->insertRelationships( GetAllRelationshipsIfAny(), false );
778 uno::Reference< embed::XOptimizedStorage > xOptDest( xDest, uno::UNO_QUERY_THROW );
779 uno::Reference < io::XInputStream > xInputToInsert;
781 if (pElement->m_xStream->HasTempFile_Impl() || !pElement->m_xStream->m_xPackageStream.is())
783 SAL_WARN_IF(!pElement->m_xStream->m_xPackageStream.is(), "package.xstor", "No package stream!");
785 // if the stream is modified - the temporary file must be used for insertion
786 xInputToInsert = pElement->m_xStream->GetTempFileAsInputStream();
788 else
790 // for now get just nonseekable access to the stream
791 // TODO/LATER: the raw stream can be used
793 xInputToInsert = pElement->m_xStream->m_xPackageStream->getDataStream();
796 if ( !xInputToInsert.is() )
797 throw io::IOException( THROW_WHERE );
799 xOptDest->insertStreamElementDirect( aName, xInputToInsert, aStrProps );
801 else
803 uno::Reference< io::XStream > xSubStr =
804 xDest->openStreamElement( aName,
805 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
806 SAL_WARN_IF( !xSubStr.is(), "package.xstor", "No destination substream!" );
808 pElement->m_xStream->CopyInternallyTo_Impl(xSubStr);
811 else if ( m_nStorageType != embed::StorageFormats::PACKAGE )
813 SAL_WARN( "package.xstor", "Encryption is only supported in package storage!" );
814 throw io::IOException( THROW_WHERE );
816 else if ( pElement->m_xStream->HasCachedEncryptionData()
817 && ( pElement->m_xStream->IsModified() || pElement->m_xStream->HasWriteOwner_Impl() ) )
819 ::comphelper::SequenceAsHashMap aCommonEncryptionData;
820 bool bHasCommonEncryptionData = false;
823 aCommonEncryptionData = GetCommonRootEncryptionData();
824 bHasCommonEncryptionData = true;
826 catch( const packages::NoEncryptionException& )
828 TOOLS_INFO_EXCEPTION("package.xstor", "No Encryption");
831 if (bHasCommonEncryptionData && ::package::PackageEncryptionDataLessOrEqual(pElement->m_xStream->GetCachedEncryptionData(), aCommonEncryptionData))
833 // If the stream can be opened with the common storage password
834 // it must be stored with the common storage password as well
835 uno::Reference< io::XStream > xDestStream =
836 xDest->openStreamElement( aName,
837 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
839 pElement->m_xStream->CopyInternallyTo_Impl( xDestStream );
841 uno::Reference< beans::XPropertySet > xProps( xDestStream, uno::UNO_QUERY_THROW );
842 xProps->setPropertyValue(
843 u"UseCommonStoragePasswordEncryption"_ustr,
844 uno::Any( true ) );
846 else
848 // the stream is already opened for writing or was changed
849 uno::Reference< embed::XStorage2 > xDest2( xDest, uno::UNO_QUERY_THROW );
850 uno::Reference< io::XStream > xSubStr =
851 xDest2->openEncryptedStream( aName,
852 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE,
853 pElement->m_xStream->GetCachedEncryptionData().getAsConstNamedValueList() );
854 SAL_WARN_IF( !xSubStr.is(), "package.xstor", "No destination substream!" );
856 pElement->m_xStream->CopyInternallyTo_Impl(xSubStr, pElement->m_xStream->GetCachedEncryptionData());
859 else
861 // the stream is not opened at all, so it can be just opened for reading
864 // If the stream can be opened with the common storage password
865 // it must be stored with the common storage password as well
867 uno::Reference< io::XStream > xOwnStream = pElement->m_xStream->GetStream(embed::ElementModes::READ,
868 false);
869 uno::Reference< io::XStream > xDestStream =
870 xDest->openStreamElement( aName,
871 embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
872 SAL_WARN_IF( !xDestStream.is(), "package.xstor", "No destination substream!" );
873 completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
875 uno::Reference< beans::XPropertySet > xProps( xDestStream, uno::UNO_QUERY_THROW );
876 xProps->setPropertyValue(
877 u"UseCommonStoragePasswordEncryption"_ustr,
878 uno::Any( true ) );
880 catch( const packages::WrongPasswordException& )
882 TOOLS_INFO_EXCEPTION("package.xstor", "Handled exception");
884 // If the common storage password does not allow to open the stream
885 // it could be copied in raw way, the problem is that the StartKey should be the same
886 // in the ODF1.2 package, so an invalid package could be produced if the stream
887 // is copied from ODF1.1 package, where it is allowed to have different StartKeys
888 uno::Reference< embed::XStorageRawAccess > xRawDest( xDest, uno::UNO_QUERY_THROW );
889 uno::Reference< io::XInputStream > xRawInStream = pElement->m_xStream->GetRawInStream();
890 xRawDest->insertRawEncrStreamElement( aName, xRawInStream );
896 uno::Sequence< uno::Sequence< beans::StringPair > > OStorage_Impl::GetAllRelationshipsIfAny()
898 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
899 return uno::Sequence< uno::Sequence< beans::StringPair > >();
901 ReadRelInfoIfNecessary();
903 if ( m_nRelInfoStatus != RELINFO_READ
904 && m_nRelInfoStatus != RELINFO_CHANGED_STREAM_READ
905 && m_nRelInfoStatus != RELINFO_CHANGED )
906 throw io::IOException( THROW_WHERE "Wrong relinfo stream!" );
907 // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
908 return m_aRelInfo;
911 void OStorage_Impl::CopyLastCommitTo( const uno::Reference< embed::XStorage >& xNewStor )
913 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
915 SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "A committed storage is incomplete!" );
916 if ( !m_xPackageFolder.is() )
917 throw uno::RuntimeException( THROW_WHERE );
919 OStorage_Impl aTempRepresent( nullptr,
920 embed::ElementModes::READ,
921 m_xPackageFolder,
922 m_xPackage,
923 m_xContext,
924 m_nStorageType);
926 // TODO/LATER: could use direct copying
927 aTempRepresent.CopyToStorage( xNewStor, false );
930 void OStorage_Impl::InsertIntoPackageFolder( const OUString& aName,
931 const uno::Reference< container::XNameContainer >& xParentPackageFolder )
933 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
935 SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "An inserted storage is incomplete!" );
936 uno::Reference< uno::XInterface > xTmp( m_xPackageFolder, uno::UNO_QUERY_THROW );
937 xParentPackageFolder->insertByName( aName, uno::Any( xTmp ) );
939 m_bCommited = false;
942 void OStorage_Impl::Commit()
944 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
946 if ( !m_bIsModified )
947 return;
949 // in case of a new empty storage it is possible that the contents are still not read
950 // ( the storage of course has no contents, but the initialization is postponed till the first use,
951 // thus if a new storage was created and committed immediately it must be initialized here )
952 ReadContents();
954 // if storage is committed it should have a valid Package representation
955 SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "The package representation should exist!" );
956 if ( !m_xPackageFolder.is() )
957 throw embed::InvalidStorageException( THROW_WHERE );
959 OSL_ENSURE( m_nStorageMode & embed::ElementModes::WRITE,
960 "Commit of readonly storage, should be detected before!" );
962 uno::Reference< container::XNameContainer > xNewPackageFolder;
964 // here the storage will switch to the temporary package folder
965 // if the storage was already committed and the parent was not committed after that
966 // the switch should not be done since the package folder in use is a temporary one;
967 // it can be detected by m_bCommited flag ( root storage doesn't need temporary representation )
968 if ( !m_bCommited && !m_bIsRoot )
970 uno::Sequence< uno::Any > aSeq{ uno::Any(true) };
971 xNewPackageFolder.set( m_xPackage->createInstanceWithArguments( aSeq ),
972 uno::UNO_QUERY );
974 else
975 xNewPackageFolder = m_xPackageFolder;
977 // remove replaced removed elements
978 for ( auto& pDeleted : m_aDeletedVector )
981 if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pDeleted->m_bIsStorage )
982 RemoveStreamRelInfo( pDeleted->m_aOriginalName );
984 // the removed elements are not in new temporary storage
985 if ( m_bCommited || m_bIsRoot )
986 xNewPackageFolder->removeByName( pDeleted->m_aOriginalName );
987 delete pDeleted;
988 pDeleted = nullptr;
990 m_aDeletedVector.clear();
992 // remove removed elements
993 for (auto mapIt = m_aChildrenMap.begin(); mapIt != m_aChildrenMap.end(); )
995 for (auto it = mapIt->second.begin(); it != mapIt->second.end(); )
997 // renamed and inserted elements must be really inserted to package later
998 // since they can conflict with removed elements
999 auto & pElement = *it;
1000 if ( pElement->m_bIsRemoved )
1002 if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pElement->m_bIsStorage )
1003 RemoveStreamRelInfo( pElement->m_aOriginalName );
1005 // the removed elements are not in new temporary storage
1006 if ( m_bCommited || m_bIsRoot )
1007 xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1009 delete pElement;
1010 it = mapIt->second.erase(it);
1012 else
1013 ++it;
1015 if (mapIt->second.empty())
1016 mapIt = m_aChildrenMap.erase(mapIt);
1017 else
1018 ++mapIt;
1022 // there should be no more deleted elements
1023 for ( const auto& pair : m_aChildrenMap )
1024 for (auto pElement : pair.second)
1026 // if it is a 'duplicate commit' inserted elements must be really inserted to package later
1027 // since they can conflict with renamed elements
1028 if ( !pElement->m_bIsInserted )
1030 // for now stream is opened in direct mode that means that in case
1031 // storage is committed all the streams from it are committed in current state.
1032 // following two steps are separated to allow easily implement transacted mode
1033 // for streams if we need it in future.
1034 // Only hierarchical access uses transacted streams currently
1035 if ( !pElement->m_bIsStorage && pElement->m_xStream
1036 && !pElement->m_xStream->IsTransacted() )
1037 pElement->m_xStream->Commit();
1039 // if the storage was not open, there is no need to commit it ???
1040 // the storage should be checked that it is committed
1041 if (pElement->m_bIsStorage && pElement->m_xStorage && pElement->m_xStorage->m_bCommited)
1043 // it's temporary PackageFolder should be inserted instead of current one
1044 // also the new copy of PackageFolder should be used by the children storages
1046 // the renamed elements are not in new temporary storage
1047 if ( m_bCommited || m_bIsRoot )
1048 xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1050 pElement->m_xStorage->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1052 else if (!pElement->m_bIsStorage && pElement->m_xStream && pElement->m_xStream->m_bFlushed)
1054 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1055 CommitStreamRelInfo( /*aName*/pair.first, pElement );
1057 // the renamed elements are not in new temporary storage
1058 if ( m_bCommited || m_bIsRoot )
1059 xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1061 pElement->m_xStream->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1063 else if ( !m_bCommited && !m_bIsRoot )
1065 // the element must be just copied to the new temporary package folder
1066 // the connection with the original package should not be lost just because
1067 // the element is still referred by the folder in the original hierarchy
1068 uno::Any aPackageElement = m_xPackageFolder->getByName( pElement->m_aOriginalName );
1069 xNewPackageFolder->insertByName( /*aName*/pair.first, aPackageElement );
1071 else if ( pair.first != pElement->m_aOriginalName )
1073 // this is the case when xNewPackageFolder refers to m_xPackageFolder
1074 // in case the name was changed and it is not a changed storage - rename the element
1075 uno::Any aPackageElement = xNewPackageFolder->getByName( pElement->m_aOriginalName );
1076 xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1077 xNewPackageFolder->insertByName( /*aName*/pair.first, aPackageElement );
1079 if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pElement->m_bIsStorage )
1081 if (!pElement->m_xStream)
1083 OpenSubStream( pElement );
1084 if (!pElement->m_xStream)
1085 throw uno::RuntimeException( THROW_WHERE );
1088 CommitStreamRelInfo( /*aName*/pair.first, pElement );
1092 pElement->m_aOriginalName = pair.first;
1096 for ( const auto& pair : m_aChildrenMap )
1097 for (auto pElement : pair.second)
1099 // now inserted elements can be inserted to the package
1100 if ( pElement->m_bIsInserted )
1102 pElement->m_aOriginalName = pair.first;
1104 if ( pElement->m_bIsStorage )
1106 OSL_ENSURE(pElement->m_xStorage, "An inserted storage is incomplete!");
1107 if (!pElement->m_xStorage)
1108 throw uno::RuntimeException( THROW_WHERE );
1110 if (pElement->m_xStorage->m_bCommited)
1112 pElement->m_xStorage->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1114 pElement->m_bIsInserted = false;
1117 else
1119 OSL_ENSURE(pElement->m_xStream, "An inserted stream is incomplete!");
1120 if (!pElement->m_xStream)
1121 throw uno::RuntimeException( THROW_WHERE );
1123 if (!pElement->m_xStream->IsTransacted())
1124 pElement->m_xStream->Commit();
1126 if (pElement->m_xStream->m_bFlushed)
1128 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1129 CommitStreamRelInfo( /*aName*/pair.first, pElement );
1131 pElement->m_xStream->InsertIntoPackageFolder( /*aName*/pair.first, xNewPackageFolder );
1133 pElement->m_bIsInserted = false;
1139 if ( m_nStorageType == embed::StorageFormats::PACKAGE )
1141 // move properties to the destination package folder
1142 uno::Reference< beans::XPropertySet > xProps( xNewPackageFolder, uno::UNO_QUERY_THROW );
1143 xProps->setPropertyValue( u"MediaType"_ustr, uno::Any( m_aMediaType ) );
1144 xProps->setPropertyValue( u"Version"_ustr, uno::Any( m_aVersion ) );
1147 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1148 CommitRelInfo( xNewPackageFolder ); // store own relations and commit complete relations storage
1150 if ( m_bIsRoot )
1152 uno::Reference< util::XChangesBatch > xChangesBatch( m_xPackage, uno::UNO_QUERY_THROW );
1155 xChangesBatch->commitChanges();
1157 catch( const lang::WrappedTargetException& r )
1159 css::uno::Any ex( cppu::getCaughtException() );
1160 // the wrapped UseBackupException means that the target medium can be corrupted
1161 embed::UseBackupException aException;
1162 if ( r.TargetException >>= aException )
1164 m_xStream.clear();
1165 m_xInputStream.clear();
1166 throw aException;
1169 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(ex));
1170 throw;
1173 else if ( !m_bCommited )
1175 m_xPackageFolder = std::move(xNewPackageFolder);
1176 m_bCommited = true;
1179 // after commit the mediatype treated as the correct one
1180 m_bMTFallbackUsed = false;
1183 void OStorage_Impl::Revert()
1185 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1187 if ( !( m_nStorageMode & embed::ElementModes::WRITE ) )
1188 return; // nothing to do
1190 // all the children must be removed
1191 // they will be created later on demand
1193 // rebuild the map - cannot do it in-place, because we're changing some of the key values
1194 std::unordered_map<OUString, std::vector<SotElement_Impl*>> oldMap;
1195 std::swap(oldMap, m_aChildrenMap);
1197 for (const auto & rPair : oldMap)
1198 for (auto pElement : rPair.second)
1200 if ( pElement->m_bIsInserted )
1201 delete pElement;
1202 else
1204 ClearElement( pElement );
1206 pElement->m_bIsRemoved = false;
1208 m_aChildrenMap[pElement->m_aOriginalName].push_back(pElement);
1212 // return replaced removed elements
1213 for ( auto& pDeleted : m_aDeletedVector )
1215 m_aChildrenMap[pDeleted->m_aOriginalName].push_back(pDeleted);
1217 ClearElement( pDeleted );
1219 pDeleted->m_bIsRemoved = false;
1221 m_aDeletedVector.clear();
1223 m_bControlMediaType = false;
1224 m_bControlVersion = false;
1226 GetStorageProperties();
1228 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1230 // currently the relations storage is changed only on commit
1231 m_xNewRelInfoStream.clear();
1232 m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1233 m_nRelInfoStatus = RELINFO_NO_INIT;
1237 ::comphelper::SequenceAsHashMap OStorage_Impl::GetCommonRootEncryptionData()
1239 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ;
1241 if ( m_nStorageType != embed::StorageFormats::PACKAGE )
1242 throw packages::NoEncryptionException( THROW_WHERE );
1244 if ( m_bIsRoot )
1246 if ( !m_bHasCommonEncryptionData )
1247 throw packages::NoEncryptionException( THROW_WHERE );
1249 return m_aCommonEncryptionData;
1251 else
1253 if ( !m_pParent )
1254 throw packages::NoEncryptionException( THROW_WHERE );
1256 return m_pParent->GetCommonRootEncryptionData();
1260 SotElement_Impl* OStorage_Impl::FindElement( const OUString& rName )
1262 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1264 SAL_WARN_IF( rName.isEmpty(), "package.xstor", "Name is empty!" );
1266 ReadContents();
1268 auto mapIt = m_aChildrenMap.find(rName);
1269 if (mapIt == m_aChildrenMap.end() && m_bRepairPackage)
1270 mapIt = std::find_if(m_aChildrenMap.begin(), m_aChildrenMap.end(),
1271 [&rName](const auto& pair)
1272 { return rName.equalsIgnoreAsciiCase(pair.first); });
1273 if (mapIt == m_aChildrenMap.end())
1274 return nullptr;
1275 for (auto pElement : mapIt->second)
1276 if (!pElement->m_bIsRemoved)
1277 return pElement;
1279 return nullptr;
1282 SotElement_Impl* OStorage_Impl::InsertStream( const OUString& aName, bool bEncr )
1284 SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1285 if ( !m_xPackage.is() )
1286 throw embed::InvalidStorageException( THROW_WHERE);
1288 uno::Sequence< uno::Any > aSeq{ uno::Any(false) };
1289 uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1291 SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new stream!" );
1292 if ( !xNewElement.is() )
1293 throw io::IOException( THROW_WHERE );
1295 uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xNewElement, uno::UNO_QUERY_THROW );
1297 OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE || !bEncr, "Only package storage supports encryption!" );
1298 if ( m_nStorageType != embed::StorageFormats::PACKAGE && bEncr )
1299 throw packages::NoEncryptionException( THROW_WHERE );
1301 // the mode is not needed for storage stream internal implementation
1302 SotElement_Impl* pNewElement = InsertElement( aName, false );
1303 pNewElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, bEncr, m_nStorageType, true));
1305 m_aChildrenMap[aName].push_back( pNewElement );
1306 m_bIsModified = true;
1307 m_bBroadcastModified = true;
1309 return pNewElement;
1312 void OStorage_Impl::InsertRawStream( const OUString& aName, const uno::Reference< io::XInputStream >& xInStream )
1314 // insert of raw stream means insert and commit
1315 SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1316 if ( !m_xPackage.is() )
1317 throw embed::InvalidStorageException( THROW_WHERE );
1319 if ( m_nStorageType != embed::StorageFormats::PACKAGE )
1320 throw packages::NoEncryptionException( THROW_WHERE );
1322 uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1323 uno::Reference< io::XInputStream > xInStrToInsert = xSeek.is() ? xInStream :
1324 GetSeekableTempCopy( xInStream );
1326 uno::Sequence< uno::Any > aSeq{ uno::Any(false) };
1327 uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1329 SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new stream!" );
1330 if ( !xNewElement.is() )
1331 throw io::IOException( THROW_WHERE );
1333 uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xNewElement, uno::UNO_QUERY_THROW );
1334 xPackageSubStream->setRawStream( xInStrToInsert );
1336 // the mode is not needed for storage stream internal implementation
1337 SotElement_Impl* pNewElement = InsertElement( aName, false );
1338 pNewElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, true, m_nStorageType, false));
1339 // the stream is inserted and must be treated as a committed one
1340 pNewElement->m_xStream->SetToBeCommited();
1342 m_aChildrenMap[aName].push_back( pNewElement );
1343 m_bIsModified = true;
1344 m_bBroadcastModified = true;
1347 std::unique_ptr<OStorage_Impl> OStorage_Impl::CreateNewStorageImpl( sal_Int32 nStorageMode )
1349 SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1350 if ( !m_xPackage.is() )
1351 throw embed::InvalidStorageException( THROW_WHERE );
1353 uno::Sequence< uno::Any > aSeq{ uno::Any(true) };
1354 uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1356 SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new storage!" );
1357 if ( !xNewElement.is() )
1358 throw io::IOException( THROW_WHERE );
1360 uno::Reference< container::XNameContainer > xPackageSubFolder( xNewElement, uno::UNO_QUERY_THROW );
1361 std::unique_ptr<OStorage_Impl> pResult(
1362 new OStorage_Impl( this, nStorageMode, xPackageSubFolder, m_xPackage, m_xContext, m_nStorageType ));
1363 pResult->m_bIsModified = true;
1365 return pResult;
1368 SotElement_Impl* OStorage_Impl::InsertStorage( const OUString& aName, sal_Int32 nStorageMode )
1370 SotElement_Impl* pNewElement = InsertElement( aName, true );
1372 pNewElement->m_xStorage = CreateNewStorageImpl(nStorageMode);
1374 m_aChildrenMap[aName].push_back( pNewElement );
1376 return pNewElement;
1379 SotElement_Impl* OStorage_Impl::InsertElement( const OUString& aName, bool bIsStorage )
1381 assert( FindElement(aName) == nullptr && "Should not try to insert existing element");
1383 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1385 SotElement_Impl* pDeletedElm = nullptr;
1387 auto it = m_aChildrenMap.find(aName);
1388 if (it != m_aChildrenMap.end())
1389 for (auto pElement : it->second)
1391 SAL_WARN_IF( !pElement->m_bIsRemoved, "package.xstor", "Try to insert an element instead of existing one!" );
1392 if ( pElement->m_bIsRemoved )
1394 SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted elements must be deleted immediately!" );
1395 pDeletedElm = pElement;
1399 if ( pDeletedElm )
1401 if ( pDeletedElm->m_bIsStorage )
1402 OpenSubStorage( pDeletedElm, embed::ElementModes::READWRITE );
1403 else
1404 OpenSubStream( pDeletedElm );
1406 auto & rVec = m_aChildrenMap[aName];
1407 std::erase(rVec, pDeletedElm);
1408 if (rVec.empty())
1409 m_aChildrenMap.erase(aName);
1410 m_aDeletedVector.push_back( pDeletedElm );
1413 // create new element
1414 return new SotElement_Impl( aName, bIsStorage, true );
1417 void OStorage_Impl::OpenSubStorage( SotElement_Impl* pElement, sal_Int32 nStorageMode )
1419 assert(pElement && "pElement is not set!");
1420 SAL_WARN_IF( !pElement->m_bIsStorage, "package.xstor", "Storage flag is not set!" );
1422 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1424 if (!pElement->m_xStorage)
1426 SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted element must be created already!" );
1428 uno::Reference< uno::XInterface > xTmp;
1429 m_xPackageFolder->getByName( pElement->m_aOriginalName ) >>= xTmp;
1430 if ( !xTmp.is() )
1431 throw container::NoSuchElementException( THROW_WHERE );
1433 uno::Reference< container::XNameContainer > xPackageSubFolder( xTmp, uno::UNO_QUERY_THROW );
1434 pElement->m_xStorage.reset(new OStorage_Impl(this, nStorageMode, xPackageSubFolder, m_xPackage, m_xContext, m_nStorageType));
1438 void OStorage_Impl::OpenSubStream( SotElement_Impl* pElement )
1440 assert(pElement && "pElement is not set!");
1441 SAL_WARN_IF( pElement->m_bIsStorage, "package.xstor", "Storage flag is set!" );
1443 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1445 if (pElement->m_xStream)
1446 return;
1448 SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted element must be created already!" );
1450 uno::Reference< uno::XInterface > xTmp;
1451 m_xPackageFolder->getByName( pElement->m_aOriginalName ) >>= xTmp;
1452 if ( !xTmp.is() )
1453 throw container::NoSuchElementException( THROW_WHERE );
1455 uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xTmp, uno::UNO_QUERY_THROW );
1457 // the stream can never be inserted here, because inserted stream element holds the stream till commit or destruction
1458 pElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, false, m_nStorageType, false, GetRelInfoStreamForName(pElement->m_aOriginalName)));
1461 uno::Sequence< OUString > OStorage_Impl::GetElementNames()
1463 ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1465 ReadContents();
1467 sal_Int32 nCnt = 0;
1468 for ( const auto& pair : m_aChildrenMap )
1469 for (auto pElement : pair.second)
1471 if ( !pElement->m_bIsRemoved )
1472 nCnt++;
1475 uno::Sequence<OUString> aElementNames(nCnt);
1476 OUString* pArray = aElementNames.getArray();
1477 for ( const auto& pair : m_aChildrenMap )
1478 for (auto pElement : pair.second)
1480 if ( !pElement->m_bIsRemoved )
1481 *pArray++ = pair.first;
1484 return aElementNames;
1487 void OStorage_Impl::RemoveElement( OUString const & rName, SotElement_Impl* pElement )
1489 assert(pElement);
1491 if ( (pElement->m_xStorage && ( pElement->m_xStorage->m_pAntiImpl || !pElement->m_xStorage->m_aReadOnlyWrapVector.empty() ))
1492 || (pElement->m_xStream && ( pElement->m_xStream->m_pAntiImpl || !pElement->m_xStream->m_aInputStreamsVector.empty() )) )
1493 throw io::IOException( THROW_WHERE ); // TODO: Access denied
1495 auto mapIt = m_aChildrenMap.find(rName);
1496 for (auto it = mapIt->second.begin(); it != mapIt->second.end(); ++it)
1497 if (pElement == *it)
1499 if ( pElement->m_bIsInserted )
1501 delete pElement;
1502 std::erase(mapIt->second, pElement);
1503 if (mapIt->second.empty())
1504 m_aChildrenMap.erase(mapIt);
1506 else
1508 pElement->m_bIsRemoved = true;
1509 ClearElement( pElement );
1511 return;
1513 assert(false && "not found");
1515 // TODO/OFOPXML: the rel stream should be removed as well
1518 void OStorage_Impl::ClearElement( SotElement_Impl* pElement )
1520 pElement->m_xStorage.reset();
1521 pElement->m_xStream.reset();
1524 void OStorage_Impl::CloneStreamElement( const OUString& aStreamName,
1525 bool bEncryptionDataProvided,
1526 const ::comphelper::SequenceAsHashMap& aEncryptionData,
1527 uno::Reference< io::XStream >& xTargetStream )
1529 SotElement_Impl *pElement = FindElement( aStreamName );
1530 if ( !pElement )
1532 // element does not exist, throw exception
1533 throw io::IOException( THROW_WHERE ); // TODO: access_denied
1535 else if ( pElement->m_bIsStorage )
1536 throw io::IOException( THROW_WHERE );
1538 if (!pElement->m_xStream)
1539 OpenSubStream( pElement );
1541 if (!pElement->m_xStream || !pElement->m_xStream->m_xPackageStream.is())
1542 throw io::IOException( THROW_WHERE ); // TODO: general_error
1544 // the existence of m_pAntiImpl of the child is not interesting,
1545 // the copy will be created internally
1547 // usual copying is not applicable here, only last flushed version of the
1548 // child stream should be used for copying. Probably the children m_xPackageStream
1549 // can be used as a base of a new stream, that would be copied to result
1550 // storage. The only problem is that some package streams can be accessed from outside
1551 // at the same time (now solved by wrappers that remember own position).
1553 if (bEncryptionDataProvided)
1554 pElement->m_xStream->GetCopyOfLastCommit(xTargetStream, aEncryptionData);
1555 else
1556 pElement->m_xStream->GetCopyOfLastCommit(xTargetStream);
1559 void OStorage_Impl::RemoveStreamRelInfo( std::u16string_view aOriginalName )
1561 // this method should be used only in OStorage_Impl::Commit() method
1562 // the aOriginalName can be empty, in this case the storage relation info should be removed
1564 if ( m_nStorageType == embed::StorageFormats::OFOPXML && m_xRelStorage.is() )
1566 OUString aRelStreamName = OUString::Concat(aOriginalName) + ".rels";
1568 if ( m_xRelStorage->hasByName( aRelStreamName ) )
1569 m_xRelStorage->removeElement( aRelStreamName );
1573 void OStorage_Impl::CreateRelStorage()
1575 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1576 return;
1578 if ( m_xRelStorage.is() )
1579 return;
1581 if ( !m_pRelStorElement )
1583 m_pRelStorElement = new SotElement_Impl( u"_rels"_ustr, true, true );
1584 m_pRelStorElement->m_xStorage = CreateNewStorageImpl(embed::ElementModes::WRITE);
1585 m_pRelStorElement->m_xStorage->m_pParent = nullptr; // the relation storage is completely controlled by parent
1588 if (!m_pRelStorElement->m_xStorage)
1589 OpenSubStorage( m_pRelStorElement, embed::ElementModes::WRITE );
1591 if (!m_pRelStorElement->m_xStorage)
1592 throw uno::RuntimeException( THROW_WHERE );
1594 m_xRelStorage = new OStorage(m_pRelStorElement->m_xStorage.get(), false);
1597 void OStorage_Impl::CommitStreamRelInfo( std::u16string_view rName, SotElement_Impl const * pStreamElement )
1599 // this method should be used only in OStorage_Impl::Commit() method
1601 // the stream element must be provided
1602 if ( !pStreamElement )
1603 throw uno::RuntimeException( THROW_WHERE );
1605 if (m_nStorageType == embed::StorageFormats::OFOPXML && pStreamElement->m_xStream)
1607 SAL_WARN_IF( rName.empty(), "package.xstor", "The name must not be empty!" );
1609 if ( !m_xRelStorage.is() )
1611 // Create new rels storage, this is commit scenario so it must be possible
1612 CreateRelStorage();
1615 pStreamElement->m_xStream->CommitStreamRelInfo(m_xRelStorage, pStreamElement->m_aOriginalName, rName);
1619 uno::Reference< io::XInputStream > OStorage_Impl::GetRelInfoStreamForName(
1620 std::u16string_view aName )
1622 if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1624 ReadContents();
1625 if ( m_xRelStorage.is() )
1627 OUString aRelStreamName = OUString::Concat(aName) + ".rels";
1628 if ( m_xRelStorage->hasByName( aRelStreamName ) )
1630 uno::Reference< io::XStream > xStream = m_xRelStorage->openStreamElement( aRelStreamName, embed::ElementModes::READ );
1631 if ( xStream.is() )
1632 return xStream->getInputStream();
1637 return uno::Reference< io::XInputStream >();
1640 void OStorage_Impl::CommitRelInfo( const uno::Reference< container::XNameContainer >& xNewPackageFolder )
1642 // this method should be used only in OStorage_Impl::Commit() method
1643 OUString aRelsStorName(u"_rels"_ustr);
1645 if ( !xNewPackageFolder.is() )
1646 throw uno::RuntimeException( THROW_WHERE );
1648 if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1649 return;
1651 if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN )
1652 throw io::IOException( THROW_WHERE );
1654 if (m_nRelInfoStatus == RELINFO_CHANGED)
1656 if (m_aRelInfo.hasElements())
1658 CreateRelStorage();
1660 uno::Reference<io::XStream> xRelsStream = m_xRelStorage->openStreamElement(
1661 u".rels"_ustr, embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE);
1663 uno::Reference<io::XOutputStream> xOutStream = xRelsStream->getOutputStream();
1664 if (!xOutStream.is())
1665 throw uno::RuntimeException(THROW_WHERE);
1667 ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xOutStream, m_aRelInfo,
1668 m_xContext);
1670 // set the mediatype
1671 uno::Reference<beans::XPropertySet> xPropSet(xRelsStream, uno::UNO_QUERY_THROW);
1672 xPropSet->setPropertyValue(
1673 u"MediaType"_ustr, uno::Any(u"application/vnd.openxmlformats-package.relationships+xml"_ustr));
1675 m_nRelInfoStatus = RELINFO_READ;
1677 else if (m_xRelStorage.is())
1678 RemoveStreamRelInfo(std::u16string_view()); // remove own rel info
1680 else if (m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1681 || m_nRelInfoStatus == RELINFO_CHANGED_STREAM)
1683 CreateRelStorage();
1685 uno::Reference<io::XStream> xRelsStream = m_xRelStorage->openStreamElement(
1686 u".rels"_ustr, embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE);
1688 uno::Reference<io::XOutputStream> xOutputStream = xRelsStream->getOutputStream();
1689 if (!xOutputStream.is())
1690 throw uno::RuntimeException(THROW_WHERE);
1692 uno::Reference<io::XSeekable> xSeek(m_xNewRelInfoStream, uno::UNO_QUERY_THROW);
1693 xSeek->seek(0);
1694 ::comphelper::OStorageHelper::CopyInputToOutput(m_xNewRelInfoStream, xOutputStream);
1696 // set the mediatype
1697 uno::Reference<beans::XPropertySet> xPropSet(xRelsStream, uno::UNO_QUERY_THROW);
1698 xPropSet->setPropertyValue(
1699 u"MediaType"_ustr,
1700 uno::Any(u"application/vnd.openxmlformats-package.relationships+xml"_ustr));
1702 m_xNewRelInfoStream.clear();
1703 if (m_nRelInfoStatus == RELINFO_CHANGED_STREAM)
1705 m_aRelInfo = uno::Sequence<uno::Sequence<beans::StringPair>>();
1706 m_nRelInfoStatus = RELINFO_NO_INIT;
1708 else
1709 m_nRelInfoStatus = RELINFO_READ;
1712 if ( !m_xRelStorage.is() )
1713 return;
1715 if ( m_xRelStorage->hasElements() )
1717 m_xRelStorage->commit();
1720 if ( xNewPackageFolder.is() && xNewPackageFolder->hasByName( aRelsStorName ) )
1721 xNewPackageFolder->removeByName( aRelsStorName );
1723 if ( !m_xRelStorage->hasElements() )
1725 // the empty relations storage should not be created
1726 delete m_pRelStorElement;
1727 m_pRelStorElement = nullptr;
1728 m_xRelStorage.clear();
1730 else if ( m_pRelStorElement && m_pRelStorElement->m_xStorage && xNewPackageFolder.is() )
1731 m_pRelStorElement->m_xStorage->InsertIntoPackageFolder( aRelsStorName, xNewPackageFolder );
1734 // OStorage implementation
1736 OStorage::OStorage( uno::Reference< io::XInputStream > const & xInputStream,
1737 sal_Int32 nMode,
1738 const uno::Sequence< beans::PropertyValue >& xProperties,
1739 uno::Reference< uno::XComponentContext > const & xContext,
1740 sal_Int32 nStorageType )
1741 : m_pImpl( new OStorage_Impl( xInputStream, nMode, xProperties, xContext, nStorageType ) )
1742 , m_xSharedMutex( m_pImpl->m_xMutex )
1743 , m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1744 , m_bReadOnlyWrap( false )
1746 m_pImpl->m_pAntiImpl = this;
1749 OStorage::OStorage( uno::Reference< io::XStream > const & xStream,
1750 sal_Int32 nMode,
1751 const uno::Sequence< beans::PropertyValue >& xProperties,
1752 uno::Reference< uno::XComponentContext > const & xContext,
1753 sal_Int32 nStorageType )
1754 : m_pImpl( new OStorage_Impl( xStream, nMode, xProperties, xContext, nStorageType ) )
1755 , m_xSharedMutex( m_pImpl->m_xMutex )
1756 , m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1757 , m_bReadOnlyWrap( false )
1759 m_pImpl->m_pAntiImpl = this;
1762 OStorage::OStorage( OStorage_Impl* pImpl, bool bReadOnlyWrap )
1763 : m_pImpl( pImpl )
1764 , m_xSharedMutex( m_pImpl->m_xMutex )
1765 , m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1766 , m_bReadOnlyWrap( bReadOnlyWrap )
1768 // this call can be done only from OStorage_Impl implementation to create child storage
1769 assert( m_pImpl && m_pImpl->m_xMutex.is() && "The provided pointer & mutex MUST NOT be empty!" );
1771 OSL_ENSURE( ( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE ||
1772 m_bReadOnlyWrap,
1773 "The wrapper can not allow writing in case implementation does not!" );
1775 if ( !bReadOnlyWrap )
1776 m_pImpl->m_pAntiImpl = this;
1779 OStorage::~OStorage()
1781 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
1782 if ( m_pImpl )
1784 osl_atomic_increment(&m_refCount); // to call dispose
1785 try {
1786 dispose();
1788 catch( const uno::RuntimeException& )
1790 TOOLS_INFO_EXCEPTION("package.xstor", "Handled exception");
1795 void OStorage::InternalDispose( bool bNotifyImpl )
1797 if ( !m_pImpl )
1798 return;
1800 // the source object is also a kind of locker for the current object
1801 // since the listeners could dispose the object while being notified
1802 lang::EventObject aSource( getXWeak() );
1803 m_aListenersContainer.disposeAndClear( aSource );
1805 if ( !m_pImpl )
1806 return;
1808 m_pImpl->m_nModifiedListenerCount = 0;
1810 if ( m_bReadOnlyWrap )
1812 OSL_ENSURE( m_aOpenSubComponentsVector.empty() || m_pSubElDispListener,
1813 "If any subelements are open the listener must exist!" );
1815 if (m_pSubElDispListener)
1817 m_pSubElDispListener->OwnerIsDisposed();
1819 // iterate through m_pData->m_aOpenSubComponentsVector
1820 // deregister m_pData->m_pSubElDispListener and dispose all of them
1821 if ( !m_aOpenSubComponentsVector.empty() )
1823 for ( const auto& pComp : m_aOpenSubComponentsVector )
1825 uno::Reference< lang::XComponent > xTmp = pComp;
1826 if ( xTmp.is() )
1828 xTmp->removeEventListener( uno::Reference< lang::XEventListener >(
1829 static_cast< lang::XEventListener* >( m_pSubElDispListener.get())));
1831 try {
1832 xTmp->dispose();
1833 } catch( const uno::Exception& )
1835 TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
1840 m_aOpenSubComponentsVector.clear();
1844 if ( bNotifyImpl )
1845 m_pImpl->RemoveReadOnlyWrap( *this );
1847 else
1849 m_pImpl->m_pAntiImpl = nullptr;
1851 if ( bNotifyImpl )
1853 if ( m_pImpl->m_bIsRoot )
1854 delete m_pImpl;
1855 else
1857 // the non-committed changes for the storage must be removed
1858 m_pImpl->Revert();
1863 m_pImpl = nullptr;
1866 void OStorage::ChildIsDisposed( const uno::Reference< uno::XInterface >& xChild )
1868 // this method can only be called by child disposing listener
1870 // this method must not contain any locking
1871 // the locking is done in the listener
1873 auto& rVec = m_aOpenSubComponentsVector;
1874 std::erase_if(rVec,
1875 [&xChild](const uno::Reference<lang::XComponent>& xTmp) {
1876 return !xTmp.is() || xTmp == xChild;
1880 void OStorage::BroadcastModifiedIfNecessary()
1882 // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
1883 if ( !m_pImpl )
1885 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
1886 throw lang::DisposedException( THROW_WHERE );
1889 if ( !m_pImpl->m_bBroadcastModified )
1890 return;
1892 m_pImpl->m_bBroadcastModified = false;
1894 SAL_WARN_IF( m_bReadOnlyWrap, "package.xstor", "The storage can not be modified at all!" );
1896 lang::EventObject aSource( getXWeak() );
1898 comphelper::OInterfaceContainerHelper2* pContainer =
1899 m_aListenersContainer.getContainer(
1900 cppu::UnoType<util::XModifyListener>::get());
1901 if ( pContainer )
1903 comphelper::OInterfaceIteratorHelper2 pIterator( *pContainer );
1904 while ( pIterator.hasMoreElements( ) )
1906 static_cast<util::XModifyListener*>( pIterator.next( ) )->modified( aSource );
1911 void OStorage::BroadcastTransaction( sal_Int8 nMessage )
1913 1 - preCommit
1914 2 - committed
1915 3 - preRevert
1916 4 - reverted
1919 // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
1920 if ( !m_pImpl )
1922 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
1923 throw lang::DisposedException( THROW_WHERE );
1926 SAL_WARN_IF( m_bReadOnlyWrap, "package.xstor", "The storage can not be modified at all!" );
1928 lang::EventObject aSource( getXWeak() );
1930 comphelper::OInterfaceContainerHelper2* pContainer =
1931 m_aListenersContainer.getContainer(
1932 cppu::UnoType<embed::XTransactionListener>::get());
1933 if ( !pContainer )
1934 return;
1936 comphelper::OInterfaceIteratorHelper2 pIterator( *pContainer );
1937 while ( pIterator.hasMoreElements( ) )
1939 OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!" );
1941 switch( nMessage )
1943 case STOR_MESS_PRECOMMIT:
1944 static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preCommit( aSource );
1945 break;
1946 case STOR_MESS_COMMITTED:
1947 static_cast<embed::XTransactionListener*>( pIterator.next( ) )->commited( aSource );
1948 break;
1949 case STOR_MESS_PREREVERT:
1950 static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preRevert( aSource );
1951 break;
1952 case STOR_MESS_REVERTED:
1953 static_cast<embed::XTransactionListener*>( pIterator.next( ) )->reverted( aSource );
1954 break;
1959 SotElement_Impl* OStorage::OpenStreamElement_Impl( const OUString& aStreamName, sal_Int32 nOpenMode, bool bEncr )
1961 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
1963 OSL_ENSURE( !m_bReadOnlyWrap || ( nOpenMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE,
1964 "An element can not be opened for writing in readonly storage!" );
1966 SotElement_Impl *pElement = m_pImpl->FindElement( aStreamName );
1967 if ( !pElement )
1969 // element does not exist, check if creation is allowed
1970 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
1971 || (( nOpenMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
1972 || ( nOpenMode & embed::ElementModes::NOCREATE ) == embed::ElementModes::NOCREATE )
1974 throw io::IOException("Element does not exist and cannot be "
1975 "created: \"" + aStreamName + "\""); // TODO: access_denied
1978 // create a new StreamElement and insert it into the list
1979 pElement = m_pImpl->InsertStream( aStreamName, bEncr );
1981 else if ( pElement->m_bIsStorage )
1983 throw io::IOException( THROW_WHERE );
1986 assert(pElement && "In case element can not be created an exception must be thrown!");
1988 if (!pElement->m_xStream)
1989 m_pImpl->OpenSubStream( pElement );
1991 if (!pElement->m_xStream)
1992 throw io::IOException( THROW_WHERE );
1994 return pElement;
1997 void OStorage::MakeLinkToSubComponent_Impl( const uno::Reference< lang::XComponent >& xComponent )
1999 if ( !xComponent.is() )
2000 throw uno::RuntimeException( THROW_WHERE );
2002 if (!m_pSubElDispListener)
2004 m_pSubElDispListener = new OChildDispListener_Impl( *this );
2007 xComponent->addEventListener( m_pSubElDispListener );
2009 m_aOpenSubComponentsVector.emplace_back(xComponent );
2012 // XInterface
2014 uno::Any SAL_CALL OStorage::queryInterface( const uno::Type& rType )
2016 // common interfaces
2017 uno::Any aReturn = ::cppu::queryInterface
2018 ( rType
2019 , static_cast<lang::XTypeProvider*> ( this )
2020 , static_cast<embed::XStorage*> ( this )
2021 , static_cast<embed::XStorage2*> ( this )
2022 , static_cast<embed::XTransactedObject*> ( this )
2023 , static_cast<embed::XTransactionBroadcaster*> ( this )
2024 , static_cast<util::XModifiable*> ( this )
2025 , static_cast<container::XNameAccess*> ( this )
2026 , static_cast<container::XElementAccess*> ( this )
2027 , static_cast<lang::XComponent*> ( this )
2028 , static_cast<beans::XPropertySet*> ( this )
2029 , static_cast<embed::XOptimizedStorage*> ( this ) );
2031 if ( aReturn.hasValue() )
2032 return aReturn ;
2034 aReturn = ::cppu::queryInterface
2035 ( rType
2036 , static_cast<embed::XHierarchicalStorageAccess*> ( this )
2037 , static_cast<embed::XHierarchicalStorageAccess2*> ( this ) );
2039 if ( aReturn.hasValue() )
2040 return aReturn ;
2042 if ( m_pImpl->m_nStorageType == embed::StorageFormats::PACKAGE )
2044 if ( m_pImpl->m_bIsRoot )
2046 aReturn = ::cppu::queryInterface
2047 ( rType
2048 , static_cast<embed::XStorageRawAccess*> ( this )
2049 , static_cast<embed::XEncryptionProtectedSource*> ( this )
2050 , static_cast<embed::XEncryptionProtectedSource2*> ( this )
2051 , static_cast<embed::XEncryptionProtectedStorage*> ( this ) );
2053 else
2055 aReturn = ::cppu::queryInterface
2056 ( rType
2057 , static_cast<embed::XStorageRawAccess*> ( this ) );
2060 else if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML )
2062 aReturn = ::cppu::queryInterface
2063 ( rType
2064 , static_cast<embed::XRelationshipAccess*> ( this ) );
2067 if ( aReturn.hasValue() )
2068 return aReturn ;
2070 return OWeakObject::queryInterface( rType );
2073 void SAL_CALL OStorage::acquire() noexcept
2075 OWeakObject::acquire();
2078 void SAL_CALL OStorage::release() noexcept
2080 OWeakObject::release();
2083 // XTypeProvider
2084 uno::Sequence< uno::Type > SAL_CALL OStorage::getTypes()
2086 if (! m_oTypeCollection)
2088 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2090 if (! m_oTypeCollection)
2092 if ( m_pImpl->m_nStorageType == embed::StorageFormats::PACKAGE )
2094 if ( m_pImpl->m_bIsRoot )
2096 m_oTypeCollection.emplace(
2097 cppu::UnoType<lang::XTypeProvider>::get()
2098 , cppu::UnoType<embed::XStorage>::get()
2099 , cppu::UnoType<embed::XStorage2>::get()
2100 , cppu::UnoType<embed::XStorageRawAccess>::get()
2101 , cppu::UnoType<embed::XTransactedObject>::get()
2102 , cppu::UnoType<embed::XTransactionBroadcaster>::get()
2103 , cppu::UnoType<util::XModifiable>::get()
2104 , cppu::UnoType<embed::XEncryptionProtectedStorage>::get()
2105 , cppu::UnoType<embed::XEncryptionProtectedSource2>::get()
2106 , cppu::UnoType<embed::XEncryptionProtectedSource>::get()
2107 , cppu::UnoType<beans::XPropertySet>::get());
2109 else
2111 m_oTypeCollection.emplace(
2112 cppu::UnoType<lang::XTypeProvider>::get()
2113 , cppu::UnoType<embed::XStorage>::get()
2114 , cppu::UnoType<embed::XStorage2>::get()
2115 , cppu::UnoType<embed::XStorageRawAccess>::get()
2116 , cppu::UnoType<embed::XTransactedObject>::get()
2117 , cppu::UnoType<embed::XTransactionBroadcaster>::get()
2118 , cppu::UnoType<util::XModifiable>::get()
2119 , cppu::UnoType<beans::XPropertySet>::get());
2122 else if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML )
2124 m_oTypeCollection.emplace(
2125 cppu::UnoType<lang::XTypeProvider>::get()
2126 , cppu::UnoType<embed::XStorage>::get()
2127 , cppu::UnoType<embed::XTransactedObject>::get()
2128 , cppu::UnoType<embed::XTransactionBroadcaster>::get()
2129 , cppu::UnoType<util::XModifiable>::get()
2130 , cppu::UnoType<embed::XRelationshipAccess>::get()
2131 , cppu::UnoType<beans::XPropertySet>::get());
2133 else
2135 m_oTypeCollection.emplace(
2136 cppu::UnoType<lang::XTypeProvider>::get()
2137 , cppu::UnoType<embed::XStorage>::get()
2138 , cppu::UnoType<embed::XTransactedObject>::get()
2139 , cppu::UnoType<embed::XTransactionBroadcaster>::get()
2140 , cppu::UnoType<util::XModifiable>::get()
2141 , cppu::UnoType<beans::XPropertySet>::get());
2146 return m_oTypeCollection->getTypes() ;
2149 uno::Sequence< sal_Int8 > SAL_CALL OStorage::getImplementationId()
2151 static const comphelper::UnoIdInit lcl_ImplId;
2152 return lcl_ImplId.getSeq();
2155 // XStorage
2156 void SAL_CALL OStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest )
2158 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2160 if ( !m_pImpl )
2162 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2163 throw lang::DisposedException( THROW_WHERE );
2166 if ( !xDest.is() || xDest == getXWeak() )
2167 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
2169 try {
2170 m_pImpl->CopyToStorage( xDest, false );
2172 catch( const embed::InvalidStorageException& )
2174 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2175 throw;
2177 catch( const lang::IllegalArgumentException& )
2179 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2180 throw;
2182 catch( const embed::StorageWrappedTargetException& )
2184 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2185 throw;
2187 catch( const io::IOException& )
2189 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2190 throw;
2192 catch( const uno::RuntimeException& )
2194 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2195 throw;
2197 catch( const uno::Exception& )
2199 uno::Any aCaught( ::cppu::getCaughtException() );
2200 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2202 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy storage!",
2203 uno::Reference< io::XInputStream >(),
2204 aCaught );
2208 uno::Reference< io::XStream > SAL_CALL OStorage::openStreamElement(
2209 const OUString& aStreamName, sal_Int32 nOpenMode )
2211 osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex());
2213 if ( !m_pImpl )
2215 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2216 throw lang::DisposedException( THROW_WHERE );
2219 if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
2220 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2222 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
2223 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable element name
2225 if ( ( nOpenMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
2226 throw io::IOException( THROW_WHERE ); // TODO: access denied
2228 uno::Reference< io::XStream > xResult;
2231 SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, false );
2232 assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
2234 xResult = pElement->m_xStream->GetStream(nOpenMode, false);
2235 SAL_WARN_IF( !xResult.is(), "package.xstor", "The method must throw exception instead of removing empty result!" );
2237 if ( m_bReadOnlyWrap )
2239 // before the storage disposes the stream it must deregister itself as listener
2240 uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY_THROW );
2241 MakeLinkToSubComponent_Impl( xStreamComponent );
2244 catch( const embed::InvalidStorageException& )
2246 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2247 throw;
2249 catch( const lang::IllegalArgumentException& )
2251 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2252 throw;
2254 catch( const packages::WrongPasswordException& )
2256 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2257 throw;
2259 catch( const embed::StorageWrappedTargetException& )
2261 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2262 throw;
2264 catch( const io::IOException& )
2266 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2267 throw;
2269 catch( const uno::RuntimeException& )
2271 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2272 throw;
2274 catch( const uno::Exception& )
2276 uno::Any aCaught( ::cppu::getCaughtException() );
2277 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2279 throw embed::StorageWrappedTargetException(THROW_WHERE "Can't open stream element!",
2280 uno::Reference< io::XInputStream >(),
2281 aCaught );
2284 aGuard.clear();
2286 BroadcastModifiedIfNecessary();
2288 return xResult;
2291 uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStreamElement(
2292 const OUString& aStreamName, sal_Int32 nOpenMode, const OUString& aPass )
2294 return openEncryptedStream( aStreamName, nOpenMode, ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
2297 uno::Reference< embed::XStorage > SAL_CALL OStorage::openStorageElement(
2298 const OUString& aStorName, sal_Int32 nStorageMode )
2300 return openStorageElement2(aStorName, nStorageMode);
2303 rtl::Reference< OStorage > OStorage::openStorageElement2(
2304 const OUString& aStorName, sal_Int32 nStorageMode )
2306 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2308 if ( !m_pImpl )
2310 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2311 throw lang::DisposedException( THROW_WHERE );
2314 if ( aStorName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStorName, false ) )
2315 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2317 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStorName == "_rels" )
2318 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2320 if ( ( nStorageMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
2321 throw io::IOException( THROW_WHERE ); // TODO: access denied
2323 if ( ( nStorageMode & embed::ElementModes::TRUNCATE )
2324 && !( nStorageMode & embed::ElementModes::WRITE ) )
2325 throw io::IOException( THROW_WHERE ); // TODO: access denied
2327 // it's always possible to read written storage in this implementation
2328 nStorageMode |= embed::ElementModes::READ;
2330 rtl::Reference< OStorage > xResult;
2333 SotElement_Impl *pElement = m_pImpl->FindElement( aStorName );
2334 if ( !pElement )
2336 // element does not exist, check if creation is allowed
2337 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
2338 || (( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
2339 || ( nStorageMode & embed::ElementModes::NOCREATE ) == embed::ElementModes::NOCREATE )
2340 throw io::IOException( THROW_WHERE ); // TODO: access_denied
2342 // create a new StorageElement and insert it into the list
2343 pElement = m_pImpl->InsertStorage( aStorName, nStorageMode );
2345 else if ( !pElement->m_bIsStorage )
2347 throw io::IOException( THROW_WHERE );
2349 else if (pElement->m_xStorage)
2351 // storage has already been opened; it may be opened another time, if it the mode allows to do so
2352 if (pElement->m_xStorage->m_pAntiImpl)
2354 throw io::IOException( THROW_WHERE ); // TODO: access_denied
2356 else if ( !pElement->m_xStorage->m_aReadOnlyWrapVector.empty()
2357 && ( nStorageMode & embed::ElementModes::WRITE ) )
2359 throw io::IOException( THROW_WHERE ); // TODO: access_denied
2361 else
2363 // in case parent storage allows writing the readonly mode of the child storage is
2364 // virtual, that means that it is just enough to change the flag to let it be writable
2365 // and since there is no AntiImpl nobody should be notified about it
2366 pElement->m_xStorage->m_nStorageMode = nStorageMode | embed::ElementModes::READ;
2368 if ( nStorageMode & embed::ElementModes::TRUNCATE )
2370 for (const auto & rPair : pElement->m_xStorage->m_aChildrenMap)
2371 for (auto pElementToDel : rPair.second)
2372 m_pImpl->RemoveElement( /*aName*/rPair.first, pElementToDel );
2377 if (!pElement->m_xStorage)
2378 m_pImpl->OpenSubStorage(pElement, nStorageMode);
2380 if (!pElement->m_xStorage)
2381 throw io::IOException( THROW_WHERE ); // TODO: general_error
2383 bool bReadOnlyWrap = ( ( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE );
2384 rtl::Reference<OStorage> pResultStorage = new OStorage(pElement->m_xStorage.get(), bReadOnlyWrap);
2385 xResult = pResultStorage;
2387 if ( bReadOnlyWrap )
2389 // Before this call is done the object must be refcounted already
2390 pElement->m_xStorage->SetReadOnlyWrap(*pResultStorage);
2392 // before the storage disposes the stream it must deregister itself as listener
2393 MakeLinkToSubComponent_Impl( xResult );
2396 catch( const embed::InvalidStorageException& )
2398 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2399 throw;
2401 catch( const lang::IllegalArgumentException& )
2403 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2404 throw;
2406 catch( const embed::StorageWrappedTargetException& )
2408 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2409 throw;
2411 catch( const io::IOException& )
2413 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2414 throw;
2416 catch( const uno::RuntimeException& )
2418 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2419 throw;
2421 catch( const uno::Exception& )
2423 uno::Any aCaught( ::cppu::getCaughtException() );
2424 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2426 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't open storage!",
2427 uno::Reference< io::XInputStream >(),
2428 aCaught );
2431 return xResult;
2434 uno::Reference< io::XStream > SAL_CALL OStorage::cloneStreamElement( const OUString& aStreamName )
2436 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2438 if ( !m_pImpl )
2440 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2441 throw lang::DisposedException( THROW_WHERE );
2444 if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
2445 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2447 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
2448 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2452 uno::Reference< io::XStream > xResult;
2453 m_pImpl->CloneStreamElement( aStreamName, false, ::comphelper::SequenceAsHashMap(), xResult );
2454 if ( !xResult.is() )
2455 throw uno::RuntimeException( THROW_WHERE );
2456 return xResult;
2458 catch( const embed::InvalidStorageException& )
2460 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2461 throw;
2463 catch( const lang::IllegalArgumentException& )
2465 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2466 throw;
2468 catch( const packages::WrongPasswordException& )
2470 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2471 throw;
2473 catch( const io::IOException& )
2475 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2476 throw;
2478 catch( const embed::StorageWrappedTargetException& )
2480 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2481 throw;
2483 catch( const uno::RuntimeException& )
2485 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2486 throw;
2488 catch( const uno::Exception& )
2490 uno::Any aCaught( ::cppu::getCaughtException() );
2491 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2493 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't clone stream!",
2494 uno::Reference< io::XInputStream >(),
2495 aCaught );
2499 uno::Reference< io::XStream > SAL_CALL OStorage::cloneEncryptedStreamElement(
2500 const OUString& aStreamName,
2501 const OUString& aPass )
2503 return cloneEncryptedStream( aStreamName, ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
2506 void SAL_CALL OStorage::copyLastCommitTo(
2507 const uno::Reference< embed::XStorage >& xTargetStorage )
2509 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2511 if ( !m_pImpl )
2513 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2514 throw lang::DisposedException( THROW_WHERE );
2519 m_pImpl->CopyLastCommitTo( xTargetStorage );
2521 catch( const embed::InvalidStorageException& )
2523 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2524 throw;
2526 catch( const lang::IllegalArgumentException& )
2528 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2529 throw;
2531 catch( const embed::StorageWrappedTargetException& )
2533 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2534 throw;
2536 catch( const io::IOException& )
2538 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2539 throw;
2541 catch( const uno::RuntimeException& )
2543 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2544 throw;
2546 catch( const uno::Exception& )
2548 uno::Any aCaught( ::cppu::getCaughtException() );
2549 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2551 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy last commit version!",
2552 uno::Reference< io::XInputStream >(),
2553 aCaught );
2558 void SAL_CALL OStorage::copyStorageElementLastCommitTo(
2559 const OUString& aStorName,
2560 const uno::Reference< embed::XStorage >& xTargetStorage )
2562 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2564 if ( !m_pImpl )
2566 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2567 throw lang::DisposedException( THROW_WHERE );
2570 if ( aStorName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStorName, false ) )
2571 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2573 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStorName == "_rels" )
2574 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2578 SotElement_Impl *pElement = m_pImpl->FindElement( aStorName );
2579 if ( !pElement )
2581 // element does not exist, throw exception
2582 throw io::IOException( THROW_WHERE ); // TODO: access_denied
2584 else if ( !pElement->m_bIsStorage )
2586 throw io::IOException( THROW_WHERE );
2589 if (!pElement->m_xStorage)
2590 m_pImpl->OpenSubStorage( pElement, embed::ElementModes::READ );
2592 if (!pElement->m_xStorage)
2593 throw io::IOException( THROW_WHERE ); // TODO: general_error
2595 // the existence of m_pAntiImpl of the child is not interesting,
2596 // the copy will be created internally
2598 pElement->m_xStorage->CopyLastCommitTo(xTargetStorage);
2600 catch( const embed::InvalidStorageException& )
2602 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2603 throw;
2605 catch( const lang::IllegalArgumentException& )
2607 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2608 throw;
2610 catch( const io::IOException& )
2612 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2613 throw;
2615 catch( const embed::StorageWrappedTargetException& )
2617 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2618 throw;
2620 catch( const uno::RuntimeException& )
2622 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2623 throw;
2625 catch( const uno::Exception& )
2627 uno::Any aCaught( ::cppu::getCaughtException() );
2628 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2630 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy last commit element version!",
2631 uno::Reference< io::XInputStream >(),
2632 aCaught );
2636 sal_Bool SAL_CALL OStorage::isStreamElement( const OUString& aElementName )
2638 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2640 if ( !m_pImpl )
2642 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2643 throw lang::DisposedException( THROW_WHERE );
2646 if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
2647 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2649 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
2650 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable name
2652 SotElement_Impl* pElement = nullptr;
2656 pElement = m_pImpl->FindElement( aElementName );
2658 catch( const embed::InvalidStorageException& )
2660 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2661 throw;
2663 catch( const lang::IllegalArgumentException& )
2665 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2666 throw;
2668 catch( const container::NoSuchElementException& )
2670 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2671 throw;
2673 catch( const uno::RuntimeException& )
2675 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2676 throw;
2678 catch( const uno::Exception& )
2680 uno::Any aCaught( ::cppu::getCaughtException() );
2681 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2683 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can't detect whether it is a stream!",
2684 uno::Reference< io::XInputStream >(),
2685 aCaught );
2688 if ( !pElement )
2689 throw container::NoSuchElementException( THROW_WHERE ); //???
2691 return !pElement->m_bIsStorage;
2694 sal_Bool SAL_CALL OStorage::isStorageElement( const OUString& aElementName )
2696 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2698 if ( !m_pImpl )
2700 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2701 throw lang::DisposedException( THROW_WHERE );
2704 if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
2705 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2707 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
2708 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
2710 SotElement_Impl* pElement = nullptr;
2714 pElement = m_pImpl->FindElement( aElementName );
2716 catch( const embed::InvalidStorageException& )
2718 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2719 throw;
2721 catch( const lang::IllegalArgumentException& )
2723 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2724 throw;
2726 catch( const container::NoSuchElementException& )
2728 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2729 throw;
2731 catch( const uno::RuntimeException& )
2733 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2734 throw;
2736 catch( const uno::Exception& )
2738 uno::Any aCaught( ::cppu::getCaughtException() );
2739 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2741 throw lang::WrappedTargetRuntimeException( THROW_WHERE "can't detect whether it is a storage",
2742 uno::Reference< io::XInputStream >(),
2743 aCaught );
2746 if ( !pElement )
2747 throw container::NoSuchElementException( THROW_WHERE ); //???
2749 return pElement->m_bIsStorage;
2752 void SAL_CALL OStorage::removeElement( const OUString& aElementName )
2755 osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
2757 if (!m_pImpl)
2759 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2760 throw lang::DisposedException(THROW_WHERE);
2763 if (aElementName.isEmpty()
2764 || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false))
2765 throw lang::IllegalArgumentException(THROW_WHERE "Unexpected entry name syntax.",
2766 uno::Reference<uno::XInterface>(), 1);
2768 if (m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels")
2769 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference<uno::XInterface>(),
2770 1); // TODO: unacceptable name
2772 if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
2773 throw io::IOException(THROW_WHERE); // TODO: access denied
2777 auto pElement = m_pImpl->FindElement(aElementName);
2778 if ( !pElement )
2779 throw container::NoSuchElementException(THROW_WHERE); //???
2781 m_pImpl->RemoveElement(aElementName, pElement);
2783 m_pImpl->m_bIsModified = true;
2784 m_pImpl->m_bBroadcastModified = true;
2786 catch (const embed::InvalidStorageException&)
2788 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2789 throw;
2791 catch (const lang::IllegalArgumentException&)
2793 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2794 throw;
2796 catch (const container::NoSuchElementException&)
2798 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2799 throw;
2801 catch (const io::IOException&)
2803 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2804 throw;
2806 catch (const embed::StorageWrappedTargetException&)
2808 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2809 throw;
2811 catch (const uno::RuntimeException&)
2813 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2814 throw;
2816 catch (const uno::Exception&)
2818 uno::Any aCaught(::cppu::getCaughtException());
2819 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2821 throw embed::StorageWrappedTargetException(THROW_WHERE "Can't remove element!",
2822 uno::Reference<io::XInputStream>(), aCaught);
2826 BroadcastModifiedIfNecessary();
2829 void SAL_CALL OStorage::renameElement( const OUString& aElementName, const OUString& aNewName )
2832 osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
2834 if (!m_pImpl)
2836 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2837 throw lang::DisposedException(THROW_WHERE);
2840 if (aElementName.isEmpty()
2841 || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false)
2842 || aNewName.isEmpty()
2843 || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aNewName, false))
2844 throw lang::IllegalArgumentException(THROW_WHERE "Unexpected entry name syntax.",
2845 uno::Reference<uno::XInterface>(), 1);
2847 if (m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML
2848 && (aElementName == "_rels" || aNewName == "_rels"))
2849 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference<uno::XInterface>(),
2850 0); // TODO: unacceptable element name
2852 if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
2853 throw io::IOException(THROW_WHERE); // TODO: access denied
2857 SotElement_Impl* pRefElement = m_pImpl->FindElement(aNewName);
2858 if (pRefElement)
2859 throw container::ElementExistException(THROW_WHERE); //???
2861 auto pElement = m_pImpl->FindElement( aElementName );
2862 if ( !pElement )
2863 throw container::NoSuchElementException(THROW_WHERE); //???
2865 auto mapIt = m_pImpl->m_aChildrenMap.find(aElementName);
2866 auto rVec = mapIt->second;
2867 for (auto it = rVec.begin(); it != rVec.end(); ++it)
2868 if (pElement == *it)
2870 std::erase(rVec, pElement);
2871 if (rVec.empty())
2872 m_pImpl->m_aChildrenMap.erase(mapIt);
2873 break;
2875 m_pImpl->m_aChildrenMap[aNewName].push_back(pElement);
2876 m_pImpl->m_bIsModified = true;
2877 m_pImpl->m_bBroadcastModified = true;
2879 catch (const embed::InvalidStorageException&)
2881 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2882 throw;
2884 catch (const lang::IllegalArgumentException&)
2886 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2887 throw;
2889 catch (const container::NoSuchElementException&)
2891 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2892 throw;
2894 catch (const container::ElementExistException&)
2896 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2897 throw;
2899 catch (const io::IOException&)
2901 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2902 throw;
2904 catch (const embed::StorageWrappedTargetException&)
2906 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2907 throw;
2909 catch (const uno::RuntimeException&)
2911 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2912 throw;
2914 catch (const uno::Exception&)
2916 uno::Any aCaught(::cppu::getCaughtException());
2917 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2919 throw embed::StorageWrappedTargetException(THROW_WHERE "Can't rename element!",
2920 uno::Reference<io::XInputStream>(), aCaught);
2924 BroadcastModifiedIfNecessary();
2927 void SAL_CALL OStorage::copyElementTo( const OUString& aElementName,
2928 const uno::Reference< embed::XStorage >& xDest,
2929 const OUString& aNewName )
2931 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2933 if ( !m_pImpl )
2935 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
2936 throw lang::DisposedException( THROW_WHERE );
2939 if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false )
2940 || aNewName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aNewName, false ) )
2941 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
2943 if ( !xDest.is() )
2944 // || xDest == getXWeak() )
2945 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
2947 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && ( aElementName == "_rels" || aNewName == "_rels" ) )
2948 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 ); // unacceptable element name
2952 SotElement_Impl* pElement = m_pImpl->FindElement( aElementName );
2953 if ( !pElement )
2954 throw container::NoSuchElementException( THROW_WHERE );
2956 uno::Reference< XNameAccess > xNameAccess( xDest, uno::UNO_QUERY_THROW );
2957 if ( xNameAccess->hasByName( aNewName ) )
2958 throw container::ElementExistException( THROW_WHERE );
2960 m_pImpl->CopyStorageElement( pElement, xDest, aNewName, false );
2962 catch( const embed::InvalidStorageException& )
2964 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2965 throw;
2967 catch( const lang::IllegalArgumentException& )
2969 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2970 throw;
2972 catch( const container::NoSuchElementException& )
2974 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2975 throw;
2977 catch( const container::ElementExistException& )
2979 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2980 throw;
2982 catch( const embed::StorageWrappedTargetException& )
2984 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2985 throw;
2987 catch( const io::IOException& )
2989 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2990 throw;
2992 catch( const uno::RuntimeException& )
2994 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2995 throw;
2997 catch( const uno::Exception& )
2999 uno::Any aCaught( ::cppu::getCaughtException() );
3000 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3002 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy element!",
3003 uno::Reference< io::XInputStream >(),
3004 aCaught );
3008 void SAL_CALL OStorage::moveElementTo( const OUString& aElementName,
3009 const uno::Reference< embed::XStorage >& xDest,
3010 const OUString& aNewName )
3013 osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3015 if (!m_pImpl)
3017 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3018 throw lang::DisposedException(THROW_WHERE);
3021 if (aElementName.isEmpty()
3022 || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false)
3023 || aNewName.isEmpty()
3024 || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aNewName, false))
3025 throw lang::IllegalArgumentException(THROW_WHERE "Unexpected entry name syntax.",
3026 uno::Reference<uno::XInterface>(), 1);
3028 if (!xDest.is() || xDest == getXWeak())
3029 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference<uno::XInterface>(), 2);
3031 if (m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML
3032 && (aElementName == "_rels" || aNewName == "_rels"))
3033 throw lang::IllegalArgumentException(THROW_WHERE, uno::Reference<uno::XInterface>(),
3034 0); // unacceptable element name
3036 if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
3037 throw io::IOException(THROW_WHERE); // TODO: access denied
3041 auto pElement = m_pImpl->FindElement( aElementName );
3042 if ( !pElement )
3043 throw container::NoSuchElementException(THROW_WHERE); //???
3045 uno::Reference<XNameAccess> xNameAccess(xDest, uno::UNO_QUERY_THROW);
3046 if (xNameAccess->hasByName(aNewName))
3047 throw container::ElementExistException(THROW_WHERE);
3049 m_pImpl->CopyStorageElement(pElement, xDest, aNewName, false);
3051 m_pImpl->RemoveElement(aElementName, pElement);
3053 m_pImpl->m_bIsModified = true;
3054 m_pImpl->m_bBroadcastModified = true;
3056 catch (const embed::InvalidStorageException&)
3058 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3059 throw;
3061 catch (const lang::IllegalArgumentException&)
3063 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3064 throw;
3066 catch (const container::NoSuchElementException&)
3068 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3069 throw;
3071 catch (const container::ElementExistException&)
3073 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3074 throw;
3076 catch (const embed::StorageWrappedTargetException&)
3078 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3079 throw;
3081 catch (const io::IOException&)
3083 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3084 throw;
3086 catch (const uno::RuntimeException&)
3088 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3089 throw;
3091 catch (const uno::Exception&)
3093 uno::Any aCaught(::cppu::getCaughtException());
3094 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3096 throw embed::StorageWrappedTargetException(THROW_WHERE "Can't move element!",
3097 uno::Reference<io::XInputStream>(), aCaught);
3101 BroadcastModifiedIfNecessary();
3104 // XStorage2
3105 uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStream(
3106 const OUString& aStreamName, sal_Int32 nOpenMode, const uno::Sequence< beans::NamedValue >& aEncryptionData )
3108 osl::ClearableMutexGuard aGuard( m_xSharedMutex->GetMutex() );
3110 if ( !m_pImpl )
3112 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3113 throw lang::DisposedException( THROW_WHERE );
3116 if ( ( nOpenMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
3117 throw io::IOException( THROW_WHERE ); // TODO: access denied
3119 if ( !aEncryptionData.hasElements() )
3120 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 3 );
3122 uno::Reference< io::XStream > xResult;
3125 SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, true );
3126 assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
3128 xResult = pElement->m_xStream->GetStream(nOpenMode, aEncryptionData, false);
3129 SAL_WARN_IF( !xResult.is(), "package.xstor", "The method must throw exception instead of removing empty result!" );
3131 if ( m_bReadOnlyWrap )
3133 // before the storage disposes the stream it must deregister itself as listener
3134 uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY_THROW );
3135 MakeLinkToSubComponent_Impl( xStreamComponent );
3138 catch( const embed::InvalidStorageException& )
3140 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3141 throw;
3143 catch( const lang::IllegalArgumentException& )
3145 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3146 throw;
3148 catch( const packages::NoEncryptionException& )
3150 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3151 throw;
3153 catch( const packages::WrongPasswordException& )
3155 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3156 throw;
3158 catch( const embed::StorageWrappedTargetException& )
3160 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3161 throw;
3163 catch( const io::IOException& )
3165 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3166 throw;
3168 catch( const uno::RuntimeException& )
3170 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3171 throw;
3173 catch( const uno::Exception& )
3175 uno::Any aCaught( ::cppu::getCaughtException() );
3176 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3178 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't open encrypted stream!",
3179 uno::Reference< io::XInputStream >(),
3180 aCaught );
3183 aGuard.clear();
3185 BroadcastModifiedIfNecessary();
3187 return xResult;
3190 uno::Reference< io::XStream > SAL_CALL OStorage::cloneEncryptedStream(
3191 const OUString& aStreamName,
3192 const uno::Sequence< beans::NamedValue >& aEncryptionData )
3194 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3196 if ( !m_pImpl )
3198 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3199 throw lang::DisposedException( THROW_WHERE );
3202 if ( !aEncryptionData.hasElements() )
3203 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
3207 uno::Reference< io::XStream > xResult;
3208 m_pImpl->CloneStreamElement( aStreamName, true, aEncryptionData, xResult );
3209 if ( !xResult.is() )
3210 throw uno::RuntimeException( THROW_WHERE );
3211 return xResult;
3213 catch( const embed::InvalidStorageException& )
3215 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3216 throw;
3218 catch( const lang::IllegalArgumentException& )
3220 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3221 throw;
3223 catch( const packages::NoEncryptionException& )
3225 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3226 throw;
3228 catch( const packages::WrongPasswordException& )
3230 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3231 throw;
3233 catch( const io::IOException& )
3235 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3236 throw;
3238 catch( const embed::StorageWrappedTargetException& )
3240 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3241 throw;
3243 catch( const uno::RuntimeException& )
3245 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3246 throw;
3248 catch( const uno::Exception& )
3250 uno::Any aCaught( ::cppu::getCaughtException() );
3251 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3253 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't clone encrypted stream!",
3254 uno::Reference< io::XInputStream >(),
3255 aCaught );
3259 // XStorageRawAccess
3260 uno::Reference< io::XInputStream > SAL_CALL OStorage::getPlainRawStreamElement(
3261 const OUString& sStreamName )
3263 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3265 if ( !m_pImpl )
3267 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3268 throw lang::DisposedException( THROW_WHERE );
3271 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML )
3272 throw uno::RuntimeException( THROW_WHERE ); // the interface is not supported and must not be accessible
3274 if ( sStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( sStreamName, false ) )
3275 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
3277 uno::Reference < io::XInputStream > xTempIn;
3280 SotElement_Impl* pElement = m_pImpl->FindElement( sStreamName );
3281 if ( !pElement )
3282 throw container::NoSuchElementException( THROW_WHERE );
3284 if (!pElement->m_xStream)
3286 m_pImpl->OpenSubStream( pElement );
3287 if (!pElement->m_xStream)
3288 throw io::IOException( THROW_WHERE );
3291 uno::Reference<io::XInputStream> xRawInStream = pElement->m_xStream->GetPlainRawInStream();
3292 if ( !xRawInStream.is() )
3293 throw io::IOException( THROW_WHERE );
3295 rtl::Reference < utl::TempFileFastService > xTempFile = new utl::TempFileFastService;
3296 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
3297 xTempIn = xTempFile->getInputStream();
3299 if ( !xTempOut.is() || !xTempIn.is() )
3300 throw io::IOException( THROW_WHERE );
3302 // Copy temporary file to a new one
3303 ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, xTempOut );
3304 xTempOut->closeOutput();
3305 xTempFile->seek( 0 );
3307 catch( const embed::InvalidStorageException& )
3309 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3310 throw;
3312 catch( const lang::IllegalArgumentException& )
3314 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3315 throw;
3317 catch( const container::NoSuchElementException& )
3319 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3320 throw;
3322 catch( const embed::StorageWrappedTargetException& )
3324 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3325 throw;
3327 catch( const io::IOException& )
3329 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3330 throw;
3332 catch( const uno::RuntimeException& )
3334 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3335 throw;
3337 catch( const uno::Exception& )
3339 uno::Any aCaught( ::cppu::getCaughtException() );
3340 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3342 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't get plain raw stream!",
3343 uno::Reference< io::XInputStream >(),
3344 aCaught );
3347 return xTempIn;
3350 uno::Reference< io::XInputStream > SAL_CALL OStorage::getRawEncrStreamElement(
3351 const OUString& sStreamName )
3353 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3355 if ( !m_pImpl )
3357 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3358 throw lang::DisposedException( THROW_WHERE );
3361 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
3362 throw packages::NoEncryptionException( THROW_WHERE );
3364 if ( sStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( sStreamName, false ) )
3365 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
3367 uno::Reference < io::XInputStream > xTempIn;
3370 SotElement_Impl* pElement = m_pImpl->FindElement( sStreamName );
3371 if ( !pElement )
3372 throw container::NoSuchElementException( THROW_WHERE );
3374 if (!pElement->m_xStream)
3376 m_pImpl->OpenSubStream( pElement );
3377 if (!pElement->m_xStream)
3378 throw io::IOException( THROW_WHERE );
3381 if (!pElement->m_xStream->IsEncrypted())
3382 throw packages::NoEncryptionException( THROW_WHERE );
3384 uno::Reference< io::XInputStream > xRawInStream = pElement->m_xStream->GetRawInStream();
3385 if ( !xRawInStream.is() )
3386 throw io::IOException( THROW_WHERE );
3388 rtl::Reference < utl::TempFileFastService > xTempFile = new utl::TempFileFastService;
3389 uno::Reference < io::XOutputStream > xTempOut = xTempFile;
3390 xTempIn = xTempFile;
3392 if ( !xTempFile )
3393 throw io::IOException( THROW_WHERE );
3395 // Copy temporary file to a new one
3396 ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, xTempOut );
3397 xTempFile->closeOutput();
3398 xTempFile->seek( 0 );
3401 catch( const embed::InvalidStorageException& )
3403 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3404 throw;
3406 catch( const lang::IllegalArgumentException& )
3408 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3409 throw;
3411 catch( const packages::NoEncryptionException& )
3413 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3414 throw;
3416 catch( const container::NoSuchElementException& )
3418 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3419 throw;
3421 catch( const embed::StorageWrappedTargetException& )
3423 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3424 throw;
3426 catch( const io::IOException& )
3428 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3429 throw;
3431 catch( const uno::RuntimeException& )
3433 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3434 throw;
3436 catch( const uno::Exception& )
3438 uno::Any aCaught( ::cppu::getCaughtException() );
3439 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3441 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't get raw stream!",
3442 uno::Reference< io::XInputStream >(),
3443 aCaught );
3446 return xTempIn;
3449 void SAL_CALL OStorage::insertRawEncrStreamElement( const OUString& aStreamName,
3450 const uno::Reference< io::XInputStream >& xInStream )
3452 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3454 if ( !m_pImpl )
3456 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3457 throw lang::DisposedException( THROW_WHERE );
3460 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
3461 throw embed::InvalidStorageException( THROW_WHERE );
3463 if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
3464 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
3466 if ( !xInStream.is() )
3467 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
3469 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) )
3470 throw io::IOException( THROW_WHERE ); // TODO: access denied
3474 SotElement_Impl* pElement = m_pImpl->FindElement( aStreamName );
3475 if ( pElement )
3476 throw container::ElementExistException( THROW_WHERE );
3478 m_pImpl->InsertRawStream( aStreamName, xInStream );
3480 catch( const embed::InvalidStorageException& )
3482 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3483 throw;
3485 catch( const lang::IllegalArgumentException& )
3487 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3488 throw;
3490 catch( const packages::NoRawFormatException& )
3492 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3493 throw;
3495 catch( const container::ElementExistException& )
3497 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3498 throw;
3500 catch( const embed::StorageWrappedTargetException& )
3502 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3503 throw;
3505 catch( const io::IOException& )
3507 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3508 throw;
3510 catch( const uno::RuntimeException& )
3512 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3513 throw;
3515 catch( const uno::Exception& )
3517 uno::Any aCaught( ::cppu::getCaughtException() );
3518 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3520 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't insert raw stream!",
3521 uno::Reference< io::XInputStream >(),
3522 aCaught );
3526 // XTransactedObject
3527 void SAL_CALL OStorage::commit()
3529 uno::Reference< util::XModifiable > xParentModif;
3531 try {
3532 BroadcastTransaction( STOR_MESS_PRECOMMIT );
3534 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3536 if ( !m_pImpl )
3538 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3539 throw lang::DisposedException( THROW_WHERE );
3542 if ( m_bReadOnlyWrap )
3543 throw io::IOException( THROW_WHERE ); // TODO: access_denied
3545 m_pImpl->Commit(); // the root storage initiates the storing to source
3547 // when the storage is committed the parent is modified
3548 if ( m_pImpl->m_pParent && m_pImpl->m_pParent->m_pAntiImpl )
3549 xParentModif = static_cast<util::XModifiable*>(m_pImpl->m_pParent->m_pAntiImpl);
3551 catch( const io::IOException& )
3553 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3554 throw;
3556 catch( const embed::StorageWrappedTargetException& )
3558 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3559 throw;
3561 catch( const uno::RuntimeException& )
3563 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3564 throw;
3566 catch( const uno::Exception& )
3568 uno::Any aCaught( ::cppu::getCaughtException() );
3569 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3571 throw embed::StorageWrappedTargetException( THROW_WHERE "Problems on commit!",
3572 getXWeak(),
3573 aCaught );
3576 setModified( false );
3577 if ( xParentModif.is() )
3578 xParentModif->setModified( true );
3580 BroadcastTransaction( STOR_MESS_COMMITTED );
3583 void SAL_CALL OStorage::revert()
3585 // the method removes all the changes done after last commit
3587 BroadcastTransaction( STOR_MESS_PREREVERT );
3590 osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3592 if (!m_pImpl)
3594 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3595 throw lang::DisposedException(THROW_WHERE);
3598 for (const auto & rPair : m_pImpl->m_aChildrenMap)
3599 for (auto pElement : rPair.second)
3601 bool bThrow = (pElement->m_xStorage
3602 && (pElement->m_xStorage->m_pAntiImpl
3603 || !pElement->m_xStorage->m_aReadOnlyWrapVector.empty()))
3604 || (pElement->m_xStream
3605 && (pElement->m_xStream->m_pAntiImpl
3606 || !pElement->m_xStream->m_aInputStreamsVector.empty()));
3607 if (bThrow)
3608 throw io::IOException(THROW_WHERE); // TODO: access denied
3611 if (m_bReadOnlyWrap || !m_pImpl->m_bListCreated)
3612 return; // nothing to do
3616 m_pImpl->Revert();
3617 m_pImpl->m_bIsModified = false;
3618 m_pImpl->m_bBroadcastModified = true;
3620 catch (const io::IOException&)
3622 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3623 throw;
3625 catch (const embed::StorageWrappedTargetException&)
3627 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3628 throw;
3630 catch (const uno::RuntimeException&)
3632 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3633 throw;
3635 catch (const uno::Exception&)
3637 uno::Any aCaught(::cppu::getCaughtException());
3638 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3640 throw embed::StorageWrappedTargetException(THROW_WHERE "Problems on revert!",
3641 getXWeak(),
3642 aCaught);
3646 setModified( false );
3647 BroadcastTransaction( STOR_MESS_REVERTED );
3650 // XTransactionBroadcaster
3651 void SAL_CALL OStorage::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3653 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3655 if ( !m_pImpl )
3657 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3658 throw lang::DisposedException( THROW_WHERE );
3661 m_aListenersContainer.addInterface( cppu::UnoType<embed::XTransactionListener>::get(),
3662 aListener );
3665 void SAL_CALL OStorage::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3667 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3669 if ( !m_pImpl )
3671 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3672 throw lang::DisposedException( THROW_WHERE );
3675 m_aListenersContainer.removeInterface( cppu::UnoType<embed::XTransactionListener>::get(),
3676 aListener );
3679 // XModifiable
3680 // TODO: if there will be no demand on this interface it will be removed from implementation,
3681 // I do not want to remove it now since it is still possible that it will be inserted
3682 // to the service back.
3684 sal_Bool SAL_CALL OStorage::isModified()
3686 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3688 if ( !m_pImpl )
3690 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3691 throw lang::DisposedException( THROW_WHERE );
3694 return m_pImpl->m_bIsModified;
3697 void SAL_CALL OStorage::setModified( sal_Bool bModified )
3700 osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3702 if (!m_pImpl)
3704 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3705 throw lang::DisposedException(THROW_WHERE);
3708 if (m_bReadOnlyWrap)
3709 throw beans::PropertyVetoException(THROW_WHERE); // TODO: access denied
3711 if (m_pImpl->m_bIsModified != bool(bModified))
3712 m_pImpl->m_bIsModified = bModified;
3715 if ( bModified )
3717 m_pImpl->m_bBroadcastModified = true;
3718 BroadcastModifiedIfNecessary();
3722 void SAL_CALL OStorage::addModifyListener(
3723 const uno::Reference< util::XModifyListener >& aListener )
3725 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3727 if ( !m_pImpl )
3729 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3730 throw lang::DisposedException( THROW_WHERE );
3733 osl_atomic_increment( &m_pImpl->m_nModifiedListenerCount );
3734 m_aListenersContainer.addInterface(
3735 cppu::UnoType<util::XModifyListener>::get(), aListener );
3738 void SAL_CALL OStorage::removeModifyListener(
3739 const uno::Reference< util::XModifyListener >& aListener )
3741 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3743 if ( !m_pImpl )
3745 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3746 throw lang::DisposedException( THROW_WHERE );
3749 osl_atomic_decrement( &m_pImpl->m_nModifiedListenerCount );
3750 m_aListenersContainer.removeInterface(
3751 cppu::UnoType<util::XModifyListener>::get(), aListener );
3754 // XNameAccess
3756 uno::Any SAL_CALL OStorage::getByName( const OUString& aName )
3758 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3760 if ( !m_pImpl )
3762 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3763 throw lang::DisposedException( THROW_WHERE );
3766 if ( aName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aName, false ) )
3767 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
3769 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
3770 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable element name
3772 uno::Any aResult;
3775 SotElement_Impl* pElement = m_pImpl->FindElement( aName );
3776 if ( !pElement )
3777 throw container::NoSuchElementException( THROW_WHERE );
3779 if ( pElement->m_bIsStorage )
3780 aResult <<= openStorageElement( aName, embed::ElementModes::READ );
3781 else
3782 aResult <<= openStreamElement( aName, embed::ElementModes::READ );
3784 catch( const container::NoSuchElementException& )
3786 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3787 throw;
3789 catch( const lang::WrappedTargetException& )
3791 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3792 throw;
3794 catch( const uno::RuntimeException& )
3796 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3797 throw;
3799 catch( const uno::Exception& )
3801 uno::Any aCaught( ::cppu::getCaughtException() );
3802 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3804 throw lang::WrappedTargetException( THROW_WHERE "Can not open storage!",
3805 getXWeak(),
3806 aCaught );
3809 return aResult;
3812 uno::Sequence< OUString > SAL_CALL OStorage::getElementNames()
3814 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3816 if ( !m_pImpl )
3818 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3819 throw lang::DisposedException( THROW_WHERE );
3824 return m_pImpl->GetElementNames();
3826 catch( const uno::RuntimeException& )
3828 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3829 throw;
3831 catch ( const uno::Exception& )
3833 uno::Any aCaught( ::cppu::getCaughtException() );
3834 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3836 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open storage!",
3837 getXWeak(),
3838 aCaught );
3842 sal_Bool SAL_CALL OStorage::hasByName( const OUString& aName )
3844 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3846 if ( !m_pImpl )
3848 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3849 throw lang::DisposedException( THROW_WHERE );
3852 if ( aName.isEmpty() )
3853 return false;
3855 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
3856 return false;
3858 SotElement_Impl* pElement = nullptr;
3861 pElement = m_pImpl->FindElement( aName );
3863 catch( const uno::RuntimeException& )
3865 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3866 throw;
3868 catch ( const uno::Exception& )
3870 uno::Any aCaught( ::cppu::getCaughtException() );
3871 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3873 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open storage!",
3874 getXWeak(),
3875 aCaught );
3878 return ( pElement != nullptr );
3881 uno::Type SAL_CALL OStorage::getElementType()
3883 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3885 if ( !m_pImpl )
3887 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3888 throw lang::DisposedException( THROW_WHERE );
3891 // it is a multitype container
3892 return uno::Type();
3895 sal_Bool SAL_CALL OStorage::hasElements()
3897 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3899 if ( !m_pImpl )
3901 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3902 throw lang::DisposedException( THROW_WHERE );
3907 return m_pImpl->HasChildren();
3909 catch( const uno::RuntimeException& )
3911 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3912 throw;
3914 catch( const uno::Exception& )
3916 uno::Any aCaught( ::cppu::getCaughtException() );
3917 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3919 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open storage!",
3920 getXWeak(),
3921 aCaught );
3925 // XComponent
3926 void SAL_CALL OStorage::dispose()
3928 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3930 if ( !m_pImpl )
3932 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3933 throw lang::DisposedException( THROW_WHERE );
3938 InternalDispose( true );
3940 catch( const uno::RuntimeException& )
3942 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3943 throw;
3945 catch( const uno::Exception& )
3947 uno::Any aCaught( ::cppu::getCaughtException() );
3948 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3950 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open storage!",
3951 getXWeak(),
3952 aCaught );
3956 void SAL_CALL OStorage::addEventListener(
3957 const uno::Reference< lang::XEventListener >& xListener )
3959 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3961 if ( !m_pImpl )
3963 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3964 throw lang::DisposedException( THROW_WHERE );
3967 m_aListenersContainer.addInterface(
3968 cppu::UnoType<lang::XEventListener>::get(), xListener );
3971 void SAL_CALL OStorage::removeEventListener(
3972 const uno::Reference< lang::XEventListener >& xListener )
3974 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3976 if ( !m_pImpl )
3978 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
3979 throw lang::DisposedException( THROW_WHERE );
3982 m_aListenersContainer.removeInterface(
3983 cppu::UnoType<lang::XEventListener>::get(), xListener );
3986 // XEncryptionProtectedSource
3988 void SAL_CALL OStorage::setEncryptionPassword( const OUString& aPass )
3990 setEncryptionData( ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
3993 void SAL_CALL OStorage::removeEncryption()
3995 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3997 if ( !m_pImpl )
3999 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4000 throw lang::DisposedException( THROW_WHERE );
4003 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
4004 throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
4006 SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "removeEncryption() method is not available for nonroot storages!" );
4007 if ( !m_pImpl->m_bIsRoot )
4008 return;
4010 try {
4011 m_pImpl->ReadContents();
4013 catch ( const uno::RuntimeException& )
4015 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4016 throw;
4018 catch ( const uno::Exception& )
4020 uno::Any aCaught( ::cppu::getCaughtException() );
4021 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4023 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4024 getXWeak(),
4025 aCaught );
4028 // TODO: check if the password is valid
4029 // update all streams that was encrypted with old password
4031 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4034 xPackPropSet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY,
4035 uno::Any( uno::Sequence< beans::NamedValue >() ) );
4037 m_pImpl->m_bHasCommonEncryptionData = false;
4038 m_pImpl->m_aCommonEncryptionData.clear();
4040 catch( const uno::RuntimeException& )
4042 TOOLS_WARN_EXCEPTION( "package.xstor", "The call must not fail, it is pretty simple!" );
4043 throw;
4045 catch( const uno::Exception& )
4047 TOOLS_WARN_EXCEPTION( "package.xstor", "The call must not fail, it is pretty simple!" );
4048 throw io::IOException( THROW_WHERE );
4052 // XEncryptionProtectedSource2
4054 void SAL_CALL OStorage::setEncryptionData( const uno::Sequence< beans::NamedValue >& aEncryptionData )
4056 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4058 if ( !m_pImpl )
4060 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4061 throw lang::DisposedException( THROW_WHERE );
4064 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
4065 throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
4067 if ( !aEncryptionData.hasElements() )
4068 throw uno::RuntimeException( THROW_WHERE "Unexpected empty encryption data!" );
4070 SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setEncryptionData() method is not available for nonroot storages!" );
4071 if ( !m_pImpl->m_bIsRoot )
4072 return;
4074 try {
4075 m_pImpl->ReadContents();
4077 catch ( const uno::RuntimeException& )
4079 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4080 throw;
4082 catch ( const uno::Exception& )
4084 uno::Any aCaught( ::cppu::getCaughtException() );
4085 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4087 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4088 getXWeak(),
4089 aCaught );
4092 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4095 ::comphelper::SequenceAsHashMap aEncryptionMap( aEncryptionData );
4096 xPackPropSet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY,
4097 uno::Any( aEncryptionMap.getAsConstNamedValueList() ) );
4099 m_pImpl->m_bHasCommonEncryptionData = true;
4100 m_pImpl->m_aCommonEncryptionData = std::move(aEncryptionMap);
4102 catch( const uno::Exception& )
4104 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:" );
4106 throw io::IOException( THROW_WHERE );
4110 sal_Bool SAL_CALL OStorage::hasEncryptionData()
4112 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4114 return m_pImpl && m_pImpl->m_bHasCommonEncryptionData;
4117 // XEncryptionProtectedStorage
4119 void SAL_CALL OStorage::setEncryptionAlgorithms( const uno::Sequence< beans::NamedValue >& aAlgorithms )
4121 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4123 if ( !m_pImpl )
4125 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4126 throw lang::DisposedException( THROW_WHERE );
4129 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
4130 throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
4132 if ( !aAlgorithms.hasElements() )
4133 throw uno::RuntimeException( THROW_WHERE "Unexpected empty encryption algorithms list!" );
4135 SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setEncryptionAlgorithms() method is not available for nonroot storages!" );
4136 if ( !m_pImpl->m_bIsRoot )
4137 return;
4139 try {
4140 m_pImpl->ReadContents();
4142 catch ( const uno::RuntimeException& )
4144 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4145 throw;
4147 catch ( const uno::Exception& )
4149 uno::Any aCaught( ::cppu::getCaughtException() );
4150 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4152 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4153 getXWeak(),
4154 aCaught );
4157 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4160 xPackPropSet->setPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY,
4161 uno::Any( aAlgorithms ) );
4163 catch ( const uno::RuntimeException& )
4165 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4166 throw;
4168 catch( const uno::Exception& )
4170 uno::Any aCaught( ::cppu::getCaughtException() );
4171 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4173 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4174 getXWeak(),
4175 aCaught );
4179 void SAL_CALL OStorage::setGpgProperties( const uno::Sequence< uno::Sequence< beans::NamedValue > >& aProps )
4181 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4183 if ( !m_pImpl )
4185 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4186 throw lang::DisposedException( THROW_WHERE );
4189 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
4190 throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
4192 if ( !aProps.hasElements() )
4193 throw uno::RuntimeException( THROW_WHERE "Unexpected empty encryption algorithms list!" );
4195 SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setGpgProperties() method is not available for nonroot storages!" );
4196 if ( !m_pImpl->m_bIsRoot )
4197 return;
4199 try {
4200 m_pImpl->ReadContents();
4202 catch ( const uno::RuntimeException& aRuntimeException )
4204 SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
4205 throw;
4207 catch ( const uno::Exception& )
4209 uno::Any aCaught( ::cppu::getCaughtException() );
4210 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4212 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4213 getXWeak(),
4214 aCaught );
4217 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4220 xPackPropSet->setPropertyValue( ENCRYPTION_GPG_PROPERTIES,
4221 uno::Any( aProps ) );
4223 catch ( const uno::RuntimeException& aRuntimeException )
4225 SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
4226 throw;
4228 catch( const uno::Exception& )
4230 uno::Any aCaught( ::cppu::getCaughtException() );
4231 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4233 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4234 getXWeak(),
4235 aCaught );
4239 uno::Sequence< beans::NamedValue > SAL_CALL OStorage::getEncryptionAlgorithms()
4241 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4243 if ( !m_pImpl )
4245 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4246 throw lang::DisposedException( THROW_WHERE );
4249 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
4250 throw uno::RuntimeException( THROW_WHERE ); // the interface must be visible only for package storage
4252 uno::Sequence< beans::NamedValue > aResult;
4253 SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "getEncryptionAlgorithms() method is not available for nonroot storages!" );
4254 if ( m_pImpl->m_bIsRoot )
4256 try {
4257 m_pImpl->ReadContents();
4259 catch ( const uno::RuntimeException& )
4261 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4262 throw;
4264 catch ( const uno::Exception& )
4266 uno::Any aCaught( ::cppu::getCaughtException() );
4267 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4269 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4270 getXWeak(),
4271 aCaught );
4274 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4277 xPackPropSet->getPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY ) >>= aResult;
4279 catch ( const uno::RuntimeException& )
4281 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4282 throw;
4284 catch( const uno::Exception& )
4286 uno::Any aCaught( ::cppu::getCaughtException() );
4287 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4289 throw lang::WrappedTargetRuntimeException( THROW_WHERE "Can not open package!",
4290 getXWeak(),
4291 aCaught );
4295 return aResult;
4298 // XPropertySet
4300 uno::Reference< beans::XPropertySetInfo > SAL_CALL OStorage::getPropertySetInfo()
4302 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4304 if ( !m_pImpl )
4306 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4307 throw lang::DisposedException( THROW_WHERE );
4310 //TODO:
4311 return uno::Reference< beans::XPropertySetInfo >();
4314 void SAL_CALL OStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
4316 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4318 if ( !m_pImpl )
4320 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4321 throw lang::DisposedException( THROW_WHERE );
4324 //TODO: think about interaction handler
4326 // WORKAROUND:
4327 // The old document might have no version in the manifest.xml, so we have to allow to set the version
4328 // even for readonly storages, so that the version from content.xml can be used.
4329 if ( m_bReadOnlyWrap && aPropertyName != "Version" )
4330 throw uno::RuntimeException( THROW_WHERE ); // TODO: Access denied
4332 if ( m_pImpl->m_nStorageType == embed::StorageFormats::ZIP )
4333 throw beans::UnknownPropertyException( aPropertyName );
4334 else if ( m_pImpl->m_nStorageType == embed::StorageFormats::PACKAGE )
4336 if ( aPropertyName == "MediaType" )
4338 aValue >>= m_pImpl->m_aMediaType;
4339 m_pImpl->m_bControlMediaType = true;
4341 m_pImpl->m_bBroadcastModified = true;
4342 m_pImpl->m_bIsModified = true;
4344 else if ( aPropertyName == "Version" )
4346 aValue >>= m_pImpl->m_aVersion;
4347 m_pImpl->m_bControlVersion = true;
4349 // this property can be set even for readonly storage
4350 if ( !m_bReadOnlyWrap )
4352 m_pImpl->m_bBroadcastModified = true;
4353 m_pImpl->m_bIsModified = true;
4356 else if ( ( m_pImpl->m_bIsRoot && ( aPropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY
4357 || aPropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY
4358 || aPropertyName == IS_INCONSISTENT_PROPERTY
4359 || aPropertyName == "URL"
4360 || aPropertyName == "RepairPackage"
4361 || aPropertyName == ENCRYPTION_GPG_PROPERTIES) )
4362 || aPropertyName == "IsRoot"
4363 || aPropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY )
4364 throw beans::PropertyVetoException( THROW_WHERE );
4365 else
4366 throw beans::UnknownPropertyException( aPropertyName );
4368 else if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML )
4370 if ( aPropertyName == "RelationsInfoStream" )
4372 uno::Reference< io::XInputStream > xInRelStream;
4373 if ( !( aValue >>= xInRelStream ) || !xInRelStream.is() )
4374 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
4376 uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY );
4377 if ( !xSeek.is() )
4379 // currently this is an internal property that is used for optimization
4380 // and the stream must support XSeekable interface
4381 // TODO/LATER: in future it can be changed if property is used from outside
4382 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
4385 m_pImpl->m_xNewRelInfoStream = std::move(xInRelStream);
4386 m_pImpl->m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
4387 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM;
4388 m_pImpl->m_bBroadcastModified = true;
4389 m_pImpl->m_bIsModified = true;
4391 else if ( aPropertyName == "RelationsInfo" )
4393 if ( !(aValue >>= m_pImpl->m_aRelInfo) )
4394 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
4396 m_pImpl->m_xNewRelInfoStream.clear();
4397 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4398 m_pImpl->m_bBroadcastModified = true;
4399 m_pImpl->m_bIsModified = true;
4401 else if ( ( m_pImpl->m_bIsRoot && ( aPropertyName == "URL" || aPropertyName == "RepairPackage") )
4402 || aPropertyName == "IsRoot" )
4403 throw beans::PropertyVetoException( THROW_WHERE );
4404 else
4405 throw beans::UnknownPropertyException( aPropertyName );
4407 else
4408 throw beans::UnknownPropertyException( aPropertyName );
4410 BroadcastModifiedIfNecessary();
4413 uno::Any SAL_CALL OStorage::getPropertyValue( const OUString& aPropertyName )
4415 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4417 if ( !m_pImpl )
4419 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4420 throw lang::DisposedException( THROW_WHERE );
4423 if ( m_pImpl->m_nStorageType == embed::StorageFormats::PACKAGE
4424 && ( aPropertyName == "MediaType" || aPropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY || aPropertyName == "Version" ) )
4428 m_pImpl->ReadContents();
4430 catch ( const uno::RuntimeException& )
4432 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4433 throw;
4435 catch ( const uno::Exception& )
4437 uno::Any aCaught( ::cppu::getCaughtException() );
4438 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4440 throw lang::WrappedTargetException(
4441 u"Can't read contents!"_ustr,
4442 getXWeak(),
4443 aCaught );
4446 if ( aPropertyName == "MediaType" )
4447 return uno::Any( m_pImpl->m_aMediaType );
4448 else if ( aPropertyName == "Version" )
4449 return uno::Any( m_pImpl->m_aVersion );
4450 else
4451 return uno::Any( m_pImpl->m_bMTFallbackUsed );
4453 else if ( aPropertyName == "IsRoot" )
4455 return uno::Any( m_pImpl->m_bIsRoot );
4457 else if ( aPropertyName == "OpenMode" )
4459 return uno::Any( m_pImpl->m_nStorageMode );
4461 else if ( m_pImpl->m_bIsRoot )
4463 if ( aPropertyName == "URL"
4464 || aPropertyName == "RepairPackage" )
4466 auto pProp = std::find_if(std::cbegin(m_pImpl->m_xProperties), std::cend(m_pImpl->m_xProperties),
4467 [&aPropertyName](const css::beans::PropertyValue& rProp) { return rProp.Name == aPropertyName; });
4468 if (pProp != std::cend(m_pImpl->m_xProperties))
4469 return pProp->Value;
4471 if ( aPropertyName == "URL" )
4472 return uno::Any( OUString() );
4474 return uno::Any( false ); // RepairPackage
4476 else if ( m_pImpl->m_nStorageType == embed::StorageFormats::PACKAGE
4477 && ( aPropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY
4478 || aPropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY
4479 || aPropertyName == ENCRYPTION_GPG_PROPERTIES
4480 || aPropertyName == IS_INCONSISTENT_PROPERTY ) )
4482 try {
4483 m_pImpl->ReadContents();
4484 uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4485 return xPackPropSet->getPropertyValue( aPropertyName );
4487 catch ( const uno::RuntimeException& )
4489 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4490 throw;
4492 catch ( const uno::Exception& )
4494 uno::Any aCaught( ::cppu::getCaughtException() );
4495 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4497 throw lang::WrappedTargetException( THROW_WHERE "Can not open package!",
4498 getXWeak(),
4499 aCaught );
4504 throw beans::UnknownPropertyException(aPropertyName);
4507 void SAL_CALL OStorage::addPropertyChangeListener(
4508 const OUString& /*aPropertyName*/,
4509 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
4511 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4513 if ( !m_pImpl )
4515 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4516 throw lang::DisposedException( THROW_WHERE );
4519 //TODO:
4522 void SAL_CALL OStorage::removePropertyChangeListener(
4523 const OUString& /*aPropertyName*/,
4524 const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
4526 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4528 if ( !m_pImpl )
4530 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4531 throw lang::DisposedException( THROW_WHERE );
4534 //TODO:
4537 void SAL_CALL OStorage::addVetoableChangeListener(
4538 const OUString& /*PropertyName*/,
4539 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
4541 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4543 if ( !m_pImpl )
4545 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4546 throw lang::DisposedException( THROW_WHERE );
4549 //TODO:
4552 void SAL_CALL OStorage::removeVetoableChangeListener(
4553 const OUString& /*PropertyName*/,
4554 const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
4556 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4558 if ( !m_pImpl )
4560 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4561 throw lang::DisposedException( THROW_WHERE );
4564 //TODO:
4567 // XRelationshipAccess
4569 // TODO/LATER: the storage and stream implementations of this interface are very similar, they could use a helper class
4571 sal_Bool SAL_CALL OStorage::hasByID( const OUString& sID )
4573 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4575 if ( !m_pImpl )
4577 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4578 throw lang::DisposedException( THROW_WHERE );
4581 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4582 throw uno::RuntimeException( THROW_WHERE );
4586 getRelationshipByID( sID );
4587 return true;
4589 catch( const container::NoSuchElementException& )
4591 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4594 return false;
4597 namespace
4600 const beans::StringPair* lcl_findPairByName(const uno::Sequence<beans::StringPair>& rSeq, const OUString& rName)
4602 return std::find_if(rSeq.begin(), rSeq.end(), [&rName](const beans::StringPair& rPair) { return rPair.First == rName; });
4607 OUString SAL_CALL OStorage::getTargetByID( const OUString& sID )
4609 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4611 if ( !m_pImpl )
4613 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4614 throw lang::DisposedException( THROW_WHERE );
4617 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4618 throw uno::RuntimeException( THROW_WHERE );
4620 const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
4621 auto pRel = lcl_findPairByName(aSeq, u"Target"_ustr);
4622 if (pRel != aSeq.end())
4623 return pRel->Second;
4625 return OUString();
4628 OUString SAL_CALL OStorage::getTypeByID( const OUString& sID )
4630 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4632 if ( !m_pImpl )
4634 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4635 throw lang::DisposedException( THROW_WHERE );
4638 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4639 throw uno::RuntimeException( THROW_WHERE );
4641 const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
4642 auto pRel = lcl_findPairByName(aSeq, u"Type"_ustr);
4643 if (pRel != aSeq.end())
4644 return pRel->Second;
4646 return OUString();
4649 uno::Sequence< beans::StringPair > SAL_CALL OStorage::getRelationshipByID( const OUString& sID )
4651 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4653 if ( !m_pImpl )
4655 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4656 throw lang::DisposedException( THROW_WHERE );
4659 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4660 throw uno::RuntimeException( THROW_WHERE );
4662 // TODO/LATER: in future the unification of the ID could be checked
4663 const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4664 const beans::StringPair aIDRel(u"Id"_ustr, sID);
4666 auto pRel = std::find_if(aSeq.begin(), aSeq.end(),
4667 [&aIDRel](const uno::Sequence<beans::StringPair>& rRel) {
4668 return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); });
4669 if (pRel != aSeq.end())
4670 return *pRel;
4672 throw container::NoSuchElementException( THROW_WHERE );
4675 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OStorage::getRelationshipsByType( const OUString& sType )
4677 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4679 if ( !m_pImpl )
4681 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4682 throw lang::DisposedException( THROW_WHERE );
4685 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4686 throw uno::RuntimeException( THROW_WHERE );
4688 // TODO/LATER: in future the unification of the ID could be checked
4689 const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4690 std::vector< uno::Sequence< beans::StringPair > > aResult;
4691 aResult.reserve(aSeq.getLength());
4693 std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResult),
4694 [&sType](const uno::Sequence<beans::StringPair>& rRel) {
4695 auto pRel = lcl_findPairByName(rRel, u"Type"_ustr);
4696 return pRel != rRel.end()
4697 // the type is usually a URL, so the check should be case insensitive
4698 && pRel->Second.equalsIgnoreAsciiCase( sType );
4701 return comphelper::containerToSequence(aResult);
4704 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OStorage::getAllRelationships()
4706 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4708 if ( !m_pImpl )
4710 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4711 throw lang::DisposedException( THROW_WHERE );
4714 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4715 throw uno::RuntimeException( THROW_WHERE );
4717 uno::Sequence< uno::Sequence< beans::StringPair > > aRet;
4720 aRet = m_pImpl->GetAllRelationshipsIfAny();
4722 catch (const io::IOException&)
4724 throw;
4726 catch (const uno::RuntimeException&)
4728 throw;
4730 catch (const uno::Exception &)
4732 uno::Any aCaught( ::cppu::getCaughtException() );
4733 throw lang::WrappedTargetRuntimeException(THROW_WHERE "Can't getAllRelationships!",
4734 uno::Reference< uno::XInterface >(),
4735 aCaught);
4738 return aRet;
4741 void SAL_CALL OStorage::insertRelationshipByID( const OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, sal_Bool bReplace )
4743 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4745 if ( !m_pImpl )
4747 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4748 throw lang::DisposedException( THROW_WHERE );
4751 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4752 throw uno::RuntimeException( THROW_WHERE );
4754 const beans::StringPair aIDRel(u"Id"_ustr, sID);
4756 uno::Sequence<beans::StringPair>* pResult = nullptr;
4758 // TODO/LATER: in future the unification of the ID could be checked
4759 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4760 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
4762 const auto& rRel = aSeq[nInd];
4763 if (std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end())
4764 pResult = &aSeq.getArray()[nInd];
4767 if ( pResult && !bReplace )
4768 throw container::ElementExistException( THROW_WHERE );
4770 if ( !pResult )
4772 const sal_Int32 nIDInd = aSeq.getLength();
4773 aSeq.realloc( nIDInd + 1 );
4774 pResult = &aSeq.getArray()[nIDInd];
4777 std::vector<beans::StringPair> aResult;
4778 aResult.reserve(aEntry.getLength() + 1);
4780 aResult.push_back(aIDRel);
4781 std::copy_if(aEntry.begin(), aEntry.end(), std::back_inserter(aResult),
4782 [](const beans::StringPair& rPair) { return rPair.First != "Id"; });
4784 *pResult = comphelper::containerToSequence(aResult);
4786 m_pImpl->m_aRelInfo = std::move(aSeq);
4787 m_pImpl->m_xNewRelInfoStream.clear();
4788 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4791 void SAL_CALL OStorage::removeRelationshipByID( const OUString& sID )
4793 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4795 if ( !m_pImpl )
4797 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4798 throw lang::DisposedException( THROW_WHERE );
4801 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4802 throw uno::RuntimeException( THROW_WHERE );
4804 uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4805 const beans::StringPair aIDRel(u"Id"_ustr, sID);
4806 auto pRel = std::find_if(std::cbegin(aSeq), std::cend(aSeq),
4807 [&aIDRel](const uno::Sequence< beans::StringPair >& rRel) {
4808 return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); });
4809 if (pRel != std::cend(aSeq))
4811 auto nInd = static_cast<sal_Int32>(std::distance(std::cbegin(aSeq), pRel));
4812 comphelper::removeElementAt(aSeq, nInd);
4814 m_pImpl->m_aRelInfo = std::move(aSeq);
4815 m_pImpl->m_xNewRelInfoStream.clear();
4816 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4818 // TODO/LATER: in future the unification of the ID could be checked
4819 return;
4822 throw container::NoSuchElementException( THROW_WHERE );
4825 void SAL_CALL OStorage::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, sal_Bool bReplace )
4827 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4829 if ( !m_pImpl )
4831 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4832 throw lang::DisposedException( THROW_WHERE );
4835 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4836 throw uno::RuntimeException( THROW_WHERE );
4838 OUString aIDTag( u"Id"_ustr );
4839 const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4840 std::vector< uno::Sequence<beans::StringPair> > aResultVec;
4841 aResultVec.reserve(aSeq.getLength() + aEntries.getLength());
4843 std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResultVec),
4844 [&aIDTag, &aEntries, bReplace](const uno::Sequence<beans::StringPair>& rTargetRel) {
4845 auto pTargetPair = lcl_findPairByName(rTargetRel, aIDTag);
4846 if (pTargetPair == rTargetRel.end())
4847 return false;
4849 bool bIsSourceSame = std::any_of(aEntries.begin(), aEntries.end(),
4850 [&pTargetPair](const uno::Sequence<beans::StringPair>& rSourceEntry) {
4851 return std::find(rSourceEntry.begin(), rSourceEntry.end(), *pTargetPair) != rSourceEntry.end(); });
4853 if ( bIsSourceSame && !bReplace )
4854 throw container::ElementExistException( THROW_WHERE );
4856 // if no such element in the provided sequence
4857 return !bIsSourceSame;
4860 std::transform(aEntries.begin(), aEntries.end(), std::back_inserter(aResultVec),
4861 [&aIDTag](const uno::Sequence<beans::StringPair>& rEntry) -> uno::Sequence<beans::StringPair> {
4862 auto pPair = lcl_findPairByName(rEntry, aIDTag);
4863 if (pPair == rEntry.end())
4864 throw io::IOException( THROW_WHERE ); // TODO: illegal relation ( no ID )
4866 auto aResult = comphelper::sequenceToContainer<std::vector<beans::StringPair>>(rEntry);
4867 auto nIDInd = std::distance(rEntry.begin(), pPair);
4868 std::rotate(aResult.begin(), std::next(aResult.begin(), nIDInd), std::next(aResult.begin(), nIDInd + 1));
4870 return comphelper::containerToSequence(aResult);
4873 m_pImpl->m_aRelInfo = comphelper::containerToSequence(aResultVec);
4874 m_pImpl->m_xNewRelInfoStream.clear();
4875 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4878 void SAL_CALL OStorage::clearRelationships()
4880 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4882 if ( !m_pImpl )
4884 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4885 throw lang::DisposedException( THROW_WHERE );
4888 if ( m_pImpl->m_nStorageType != embed::StorageFormats::OFOPXML )
4889 throw uno::RuntimeException( THROW_WHERE );
4891 m_pImpl->m_aRelInfo.realloc( 0 );
4892 m_pImpl->m_xNewRelInfoStream.clear();
4893 m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4896 // XOptimizedStorage
4897 void SAL_CALL OStorage::insertRawNonEncrStreamElementDirect(
4898 const OUString& /*sStreamName*/,
4899 const uno::Reference< io::XInputStream >& /*xInStream*/ )
4901 // not implemented currently because there is still no demand
4902 // might need to be implemented if direct copying of compressed streams is used
4903 throw io::IOException( THROW_WHERE );
4906 void SAL_CALL OStorage::insertStreamElementDirect(
4907 const OUString& aStreamName,
4908 const uno::Reference< io::XInputStream >& xInStream,
4909 const uno::Sequence< beans::PropertyValue >& aProps )
4911 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4913 if ( !m_pImpl )
4915 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4916 throw lang::DisposedException( THROW_WHERE );
4919 if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
4920 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
4922 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
4923 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
4925 if ( m_bReadOnlyWrap )
4926 throw io::IOException( THROW_WHERE ); // TODO: access denied
4930 SotElement_Impl* pElement = m_pImpl->FindElement( aStreamName );
4932 if ( pElement )
4933 throw container::ElementExistException( THROW_WHERE );
4935 pElement = OpenStreamElement_Impl( aStreamName, embed::ElementModes::READWRITE, false );
4936 assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
4938 pElement->m_xStream->InsertStreamDirectly(xInStream, aProps);
4940 catch( const embed::InvalidStorageException& )
4942 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4943 throw;
4945 catch( const lang::IllegalArgumentException& )
4947 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4948 throw;
4950 catch( const container::ElementExistException& )
4952 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4953 throw;
4955 catch( const embed::StorageWrappedTargetException& )
4957 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4958 throw;
4960 catch( const io::IOException& )
4962 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4963 throw;
4965 catch( const uno::RuntimeException& )
4967 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4968 throw;
4970 catch( const uno::Exception& )
4972 uno::Any aCaught( ::cppu::getCaughtException() );
4973 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4975 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't insert stream directly!",
4976 uno::Reference< io::XInputStream >(),
4977 aCaught );
4981 void SAL_CALL OStorage::copyElementDirectlyTo(
4982 const OUString& aElementName,
4983 const uno::Reference< embed::XOptimizedStorage >& xDest,
4984 const OUString& aNewName )
4986 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4988 if ( !m_pImpl )
4990 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
4991 throw lang::DisposedException( THROW_WHERE );
4994 if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false )
4995 || aNewName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aNewName, false ) )
4996 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
4998 if ( !xDest.is() || xDest == getXWeak() )
4999 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
5001 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && ( aElementName == "_rels" || aNewName == "_rels" ) )
5002 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 ); // unacceptable name
5006 SotElement_Impl* pElement = m_pImpl->FindElement( aElementName );
5007 if ( !pElement )
5008 throw container::NoSuchElementException( THROW_WHERE );
5010 uno::Reference< XNameAccess > xNameAccess( xDest, uno::UNO_QUERY_THROW );
5011 if ( xNameAccess->hasByName( aNewName ) )
5012 throw container::ElementExistException( THROW_WHERE );
5014 // let the element be copied directly
5015 uno::Reference< embed::XStorage > xStorDest( xDest, uno::UNO_QUERY_THROW );
5016 m_pImpl->CopyStorageElement( pElement, xStorDest, aNewName, true );
5018 catch( const embed::InvalidStorageException& )
5020 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5021 throw;
5023 catch( const lang::IllegalArgumentException& )
5025 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5026 throw;
5028 catch( const container::NoSuchElementException& )
5030 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5031 throw;
5033 catch( const container::ElementExistException& )
5035 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5036 throw;
5038 catch( const embed::StorageWrappedTargetException& )
5040 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5041 throw;
5043 catch( const io::IOException& )
5045 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5046 throw;
5048 catch( const uno::RuntimeException& )
5050 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5051 throw;
5053 catch( const uno::Exception& )
5055 uno::Any aCaught( ::cppu::getCaughtException() );
5056 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5058 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy element directly!",
5059 uno::Reference< io::XInputStream >(),
5060 aCaught );
5064 void SAL_CALL OStorage::writeAndAttachToStream( const uno::Reference< io::XStream >& xStream )
5066 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5068 if ( !m_pImpl )
5070 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5071 throw lang::DisposedException( THROW_WHERE );
5074 if ( !m_pImpl->m_bIsRoot )
5075 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
5077 if ( !m_pImpl->m_pSwitchStream )
5078 throw uno::RuntimeException( THROW_WHERE );
5082 m_pImpl->m_pSwitchStream->CopyAndSwitchPersistenceTo( xStream );
5084 catch( const embed::InvalidStorageException& )
5086 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5087 throw;
5089 catch( const lang::IllegalArgumentException& )
5091 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5092 throw;
5094 catch( const embed::StorageWrappedTargetException& )
5096 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5097 throw;
5099 catch( const io::IOException& )
5101 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:" );
5102 throw;
5104 catch( const uno::RuntimeException& )
5106 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5107 throw;
5109 catch( const uno::Exception& )
5111 uno::Any aCaught( ::cppu::getCaughtException() );
5112 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5114 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't write and attach to stream!",
5115 uno::Reference< io::XInputStream >(),
5116 aCaught );
5121 void SAL_CALL OStorage::attachToURL( const OUString& sURL,
5122 sal_Bool bReadOnly )
5124 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5126 if ( !m_pImpl )
5128 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5129 throw lang::DisposedException( THROW_WHERE );
5132 if ( !m_pImpl->m_bIsRoot )
5133 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
5135 if ( !m_pImpl->m_pSwitchStream )
5136 throw uno::RuntimeException( THROW_WHERE );
5138 uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
5139 ucb::SimpleFileAccess::create( m_pImpl->m_xContext ) );
5143 if ( bReadOnly )
5145 uno::Reference< io::XInputStream > xInputStream = xAccess->openFileRead( sURL );
5146 m_pImpl->m_pSwitchStream->SwitchPersistenceTo( xInputStream );
5148 else
5150 uno::Reference< io::XStream > xStream = xAccess->openFileReadWrite( sURL );
5151 m_pImpl->m_pSwitchStream->SwitchPersistenceTo( xStream );
5154 catch( const embed::InvalidStorageException& )
5156 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5157 throw;
5159 catch( const lang::IllegalArgumentException& )
5161 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5162 throw;
5164 catch( const embed::StorageWrappedTargetException& )
5166 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5167 throw;
5169 catch( const io::IOException& )
5171 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5172 throw;
5174 catch( const uno::RuntimeException& )
5176 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5177 throw;
5179 catch( const uno::Exception& )
5181 uno::Any aCaught( ::cppu::getCaughtException() );
5182 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5184 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't attach to URL!",
5185 uno::Reference< io::XInputStream >(),
5186 aCaught );
5190 uno::Any SAL_CALL OStorage::getElementPropertyValue( const OUString& aElementName, const OUString& aPropertyName )
5192 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5194 if ( !m_pImpl )
5196 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5197 throw lang::DisposedException( THROW_WHERE );
5200 if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
5201 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
5203 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
5204 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // TODO: unacceptable name
5208 SotElement_Impl *pElement = m_pImpl->FindElement( aElementName );
5209 if ( !pElement )
5210 throw container::NoSuchElementException( THROW_WHERE );
5212 // TODO/LATER: Currently it is only implemented for MediaType property of substorages, might be changed in future
5213 if ( !pElement->m_bIsStorage || m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE || aPropertyName != "MediaType" )
5214 throw beans::PropertyVetoException( THROW_WHERE );
5216 if (!pElement->m_xStorage)
5217 m_pImpl->OpenSubStorage( pElement, embed::ElementModes::READ );
5219 if (!pElement->m_xStorage)
5220 throw io::IOException( THROW_WHERE ); // TODO: general_error
5222 pElement->m_xStorage->ReadContents();
5223 return uno::Any(pElement->m_xStorage->m_aMediaType);
5225 catch( const embed::InvalidStorageException& )
5227 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5228 throw;
5230 catch( const lang::IllegalArgumentException& )
5232 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5233 throw;
5235 catch( const container::NoSuchElementException& )
5237 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5238 throw;
5240 catch( const beans::UnknownPropertyException& )
5242 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5243 throw;
5245 catch( const beans::PropertyVetoException& )
5247 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5248 throw;
5250 catch( const embed::StorageWrappedTargetException& )
5252 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5253 throw;
5255 catch( const io::IOException& )
5257 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5258 throw;
5260 catch( const uno::RuntimeException& )
5262 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5263 throw;
5265 catch( const uno::Exception& )
5267 uno::Any aCaught( ::cppu::getCaughtException() );
5268 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5270 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't get element property!",
5271 uno::Reference< io::XInputStream >(),
5272 aCaught );
5276 void SAL_CALL OStorage::copyStreamElementData( const OUString& aStreamName, const uno::Reference< io::XStream >& xTargetStream )
5278 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5280 if ( !m_pImpl )
5282 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5283 throw lang::DisposedException( THROW_WHERE );
5286 if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
5287 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
5289 if ( m_pImpl->m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
5290 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 1 ); // unacceptable name
5292 if ( !xTargetStream.is() )
5293 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 2 );
5297 uno::Reference< io::XStream > xNonconstRef = xTargetStream;
5298 m_pImpl->CloneStreamElement( aStreamName, false, ::comphelper::SequenceAsHashMap(), xNonconstRef );
5300 SAL_WARN_IF( xNonconstRef != xTargetStream, "package.xstor", "The provided stream reference seems not be filled in correctly!" );
5301 if ( xNonconstRef != xTargetStream )
5302 throw uno::RuntimeException( THROW_WHERE ); // if the stream reference is set it must not be changed!
5304 catch( const embed::InvalidStorageException& )
5306 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5307 throw;
5309 catch( const lang::IllegalArgumentException& )
5311 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5312 throw;
5314 catch( const packages::WrongPasswordException& )
5316 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5317 throw;
5319 catch( const io::IOException& )
5321 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5322 throw;
5324 catch( const embed::StorageWrappedTargetException& )
5326 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5327 throw;
5329 catch( const uno::RuntimeException& )
5331 TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5332 throw;
5334 catch( const uno::Exception& )
5336 uno::Any aCaught( ::cppu::getCaughtException() );
5337 SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5339 throw embed::StorageWrappedTargetException( THROW_WHERE "Can't copy stream data!",
5340 uno::Reference< io::XInputStream >(),
5341 aCaught );
5346 // XHierarchicalStorageAccess
5347 uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openStreamElementByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode )
5349 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5351 if ( !m_pImpl )
5353 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5354 throw lang::DisposedException( THROW_WHERE );
5357 if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5358 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
5360 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
5361 && ( nOpenMode & embed::ElementModes::WRITE ) )
5362 throw io::IOException( THROW_WHERE ); // Access denied
5364 std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5365 OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5367 uno::Reference< embed::XExtendedStorageStream > xResult;
5368 if ( aListPath.size() == 1 )
5372 // that must be a direct request for a stream
5373 // the transacted version of the stream should be opened
5375 SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamPath, nOpenMode, false );
5376 assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
5378 xResult.set(pElement->m_xStream->GetStream(nOpenMode, true),
5379 uno::UNO_QUERY_THROW);
5381 catch ( const container::NoSuchElementException & )
5383 throw io::IOException( THROW_WHERE ); // file not found
5386 else
5388 // there are still storages in between
5389 if (!m_pHierarchyHolder)
5390 m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5392 xResult = m_pHierarchyHolder->GetStreamHierarchically(
5393 ( m_pImpl->m_nStorageMode & embed::ElementModes::READWRITE ),
5394 aListPath,
5395 nOpenMode );
5398 if ( !xResult.is() )
5399 throw uno::RuntimeException( THROW_WHERE );
5401 return xResult;
5404 uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openEncryptedStreamElementByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode, const OUString& sPassword )
5406 return openEncryptedStreamByHierarchicalName( aStreamPath, nOpenMode, ::comphelper::OStorageHelper::CreatePackageEncryptionData( sPassword ) );
5409 void SAL_CALL OStorage::removeStreamElementByHierarchicalName( const OUString& aStreamPath )
5411 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5413 if ( !m_pImpl )
5415 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5416 throw lang::DisposedException( THROW_WHERE );
5419 if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5420 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
5422 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) )
5423 throw io::IOException( THROW_WHERE ); // Access denied
5425 std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5426 OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5428 if (!m_pHierarchyHolder)
5429 m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5431 m_pHierarchyHolder->RemoveStreamHierarchically(aListPath);
5434 // XHierarchicalStorageAccess2
5435 uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openEncryptedStreamByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode, const uno::Sequence< beans::NamedValue >& aEncryptionData )
5437 ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5439 if ( !m_pImpl )
5441 SAL_INFO("package.xstor", THROW_WHERE "Disposed!");
5442 throw lang::DisposedException( THROW_WHERE );
5445 if ( m_pImpl->m_nStorageType != embed::StorageFormats::PACKAGE )
5446 throw packages::NoEncryptionException( THROW_WHERE );
5448 if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5449 throw lang::IllegalArgumentException( THROW_WHERE "Unexpected entry name syntax.", uno::Reference< uno::XInterface >(), 1 );
5451 if ( !aEncryptionData.hasElements() )
5452 throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 3 );
5454 if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
5455 && ( nOpenMode & embed::ElementModes::WRITE ) )
5456 throw io::IOException( THROW_WHERE ); // Access denied
5458 std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5459 OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5461 uno::Reference< embed::XExtendedStorageStream > xResult;
5462 if ( aListPath.size() == 1 )
5464 // that must be a direct request for a stream
5465 // the transacted version of the stream should be opened
5467 SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamPath, nOpenMode, true );
5468 assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
5470 xResult.set(pElement->m_xStream->GetStream(nOpenMode, aEncryptionData, true),
5471 uno::UNO_QUERY_THROW);
5473 else
5475 // there are still storages in between
5476 if (!m_pHierarchyHolder)
5477 m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5479 xResult = m_pHierarchyHolder->GetStreamHierarchically(
5480 ( m_pImpl->m_nStorageMode & embed::ElementModes::READWRITE ),
5481 aListPath,
5482 nOpenMode,
5483 aEncryptionData );
5486 if ( !xResult.is() )
5487 throw uno::RuntimeException( THROW_WHERE );
5489 return xResult;
5492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */