bump product version to 7.6.3.2-android
[LibreOffice.git] / package / source / xstor / ohierarchyholder.cxx
blobeafdf4a567f420875b96ff672480cea987b039f0
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 <sal/config.h>
22 #include <com/sun/star/io/IOException.hpp>
23 #include <com/sun/star/uno/Reference.hxx>
24 #include <com/sun/star/embed/ElementModes.hpp>
25 #include <com/sun/star/embed/XHierarchicalStorageAccess2.hpp>
26 #include <com/sun/star/embed/XTransactedObject.hpp>
27 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
28 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
30 #include <cppuhelper/exc_hlp.hxx>
31 #include <o3tl/string_view.hxx>
33 #include "ohierarchyholder.hxx"
35 using namespace ::com::sun::star;
37 // OHierarchyHolder_Impl
39 uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, std::vector<OUString>& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
41 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
43 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
44 throw io::IOException("invalid storage/stream mode combo");
46 uno::Reference< embed::XExtendedStorageStream > xResult =
47 m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
48 if ( !xResult.is() )
49 throw uno::RuntimeException();
51 return xResult;
54 void OHierarchyHolder_Impl::RemoveStreamHierarchically( std::vector<OUString>& aListPath )
56 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
58 m_xChild->RemoveStreamHierarchically( aListPath );
61 // static
62 std::vector<OUString> OHierarchyHolder_Impl::GetListPathFromString( std::u16string_view aPath )
64 std::vector<OUString> aResult;
65 sal_Int32 nIndex = 0;
68 OUString aName( o3tl::getToken(aPath, 0, '/', nIndex ) );
69 if ( aName.isEmpty() )
70 throw lang::IllegalArgumentException();
72 aResult.push_back( aName );
74 while ( nIndex >= 0 );
76 return aResult;
79 // OHierarchyElement_Impl
81 uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, std::vector<OUString>& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
83 std::unique_lock aGuard( m_aMutex );
85 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
86 throw io::IOException("invalid storage/stream mode combo");
88 if ( aListPath.empty() )
89 throw uno::RuntimeException();
91 OUString aNextName = *(aListPath.begin());
92 aListPath.erase( aListPath.begin() );
94 uno::Reference< embed::XExtendedStorageStream > xResult;
96 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
97 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
99 if ( aListPath.empty() )
101 if ( aEncryptionData.empty() )
103 uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
104 xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode );
106 else
108 uno::Reference< embed::XHierarchicalStorageAccess2 > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
109 xResult = xHStorage->openEncryptedStreamByHierarchicalName( aNextName, nStreamMode, aEncryptionData.getAsConstNamedValueList() );
112 uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY );
113 if ( xTransact.is() )
115 // the existence of the transacted object means that the stream is opened for writing also
116 // so the whole chain must be committed
117 uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW );
118 xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) );
120 else
122 uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW );
123 xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) );
126 m_aOpenStreams.emplace_back( xResult );
128 else
130 bool bNewElement = false;
131 ::rtl::Reference< OHierarchyElement_Impl > aElement;
132 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
133 if ( aIter != m_aChildren.end() )
134 aElement = aIter->second;
136 if ( !aElement.is() )
138 bNewElement = true;
139 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode );
140 if ( !xChildStorage.is() )
141 throw uno::RuntimeException();
143 aElement = new OHierarchyElement_Impl( xChildStorage );
146 xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
147 if ( !xResult.is() )
148 throw uno::RuntimeException();
150 if ( bNewElement )
152 m_aChildren[aNextName] = aElement;
153 aElement->SetParent( this );
157 // the subelement was opened successfully, remember the storage to let it be locked
158 m_xOwnStorage = xOwnStor;
160 return xResult;
163 void OHierarchyElement_Impl::RemoveStreamHierarchically( std::vector<OUString>& aListPath )
165 std::unique_lock aGuard( m_aMutex );
167 if ( aListPath.empty() )
168 throw uno::RuntimeException();
170 OUString aNextName = *(aListPath.begin());
171 aListPath.erase( aListPath.begin() );
173 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
174 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
176 if ( aListPath.empty() )
178 xOwnStor->removeElement( aNextName );
180 else
182 ::rtl::Reference< OHierarchyElement_Impl > aElement;
183 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
184 if ( aIter != m_aChildren.end() )
185 aElement = aIter->second;
187 if ( !aElement.is() )
189 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName,
190 embed::ElementModes::READWRITE );
191 if ( !xChildStorage.is() )
192 throw uno::RuntimeException();
194 aElement = new OHierarchyElement_Impl( xChildStorage );
197 aElement->RemoveStreamHierarchically( aListPath );
200 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY );
201 if ( xTransact.is() )
202 xTransact->commit();
204 TestForClosing();
207 void OHierarchyElement_Impl::Commit()
209 ::rtl::Reference< OHierarchyElement_Impl > xKeepAlive( this );
210 ::rtl::Reference< OHierarchyElement_Impl > aParent;
211 uno::Reference< embed::XStorage > xOwnStor;
214 std::unique_lock aGuard( m_aMutex );
215 aParent = m_rParent;
216 xOwnStor = m_xOwnStorage;
219 if ( xOwnStor.is() )
221 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW );
222 xTransact->commit();
223 if ( aParent.is() )
224 aParent->Commit();
228 void OHierarchyElement_Impl::TestForClosing()
230 ::rtl::Reference< OHierarchyElement_Impl > xKeepAlive( this );
232 std::unique_lock aGuard( m_aMutex );
234 if ( m_aOpenStreams.empty() && m_aChildren.empty() )
236 if ( m_rParent.is() )
238 // only the root storage should not be disposed, other storages can be disposed
239 if ( m_xOwnStorage.is() )
243 m_xOwnStorage->dispose();
245 catch( uno::Exception& )
249 m_rParent->RemoveElement( this );
252 m_xOwnStorage.clear();
257 void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source )
262 std::unique_lock aGuard(m_aMutex);
263 uno::Reference< embed::XExtendedStorageStream > xStream(Source.Source, uno::UNO_QUERY);
265 m_aOpenStreams.erase(std::remove_if(m_aOpenStreams.begin(), m_aOpenStreams.end(),
266 [&xStream](const OWeakStorRefVector_Impl::value_type& rxStorage) {
267 return !rxStorage.get().is() || rxStorage.get() == xStream; }),
268 m_aOpenStreams.end());
271 TestForClosing();
273 catch( uno::Exception& ex )
275 css::uno::Any anyEx = cppu::getCaughtException();
276 throw lang::WrappedTargetRuntimeException( ex.Message,
277 nullptr, anyEx ); // no exception must happen here, usually an exception means disaster
281 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef )
284 std::unique_lock aGuard( m_aMutex );
285 OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin();
286 while (aIter != m_aChildren.end())
288 if (aIter->second == aRef )
289 aIter = m_aChildren.erase(aIter);
290 else
291 ++aIter;
295 TestForClosing();
298 // XTransactionListener
299 void SAL_CALL OHierarchyElement_Impl::preCommit( const css::lang::EventObject& /*aEvent*/ )
303 void SAL_CALL OHierarchyElement_Impl::commited( const css::lang::EventObject& /*aEvent*/ )
307 Commit();
309 catch( const uno::Exception& )
311 css::uno::Any anyEx = cppu::getCaughtException();
312 throw lang::WrappedTargetRuntimeException(
313 "Can not commit storage sequence!",
314 uno::Reference< uno::XInterface >(),
315 anyEx );
319 void SAL_CALL OHierarchyElement_Impl::preRevert( const css::lang::EventObject& /*aEvent*/ )
323 void SAL_CALL OHierarchyElement_Impl::reverted( const css::lang::EventObject& /*aEvent*/ )
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */