bump product version to 4.1.6.2
[LibreOffice.git] / package / source / xstor / ohierarchyholder.cxx
blobd4ef19be57d73927fe53021a508e878aa7e4785d
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 <com/sun/star/uno/Reference.hxx>
21 #include <com/sun/star/embed/ElementModes.hpp>
22 #include <com/sun/star/embed/XHierarchicalStorageAccess2.hpp>
23 #include <com/sun/star/embed/XTransactedObject.hpp>
24 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
25 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
27 #include "ohierarchyholder.hxx"
29 using namespace ::com::sun::star;
31 //===============================================
32 // OHierarchyHolder_Impl
33 //===============================================
35 //-----------------------------------------------
36 uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
38 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
40 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
41 throw io::IOException();
43 uno::Reference< embed::XExtendedStorageStream > xResult =
44 m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
45 if ( !xResult.is() )
46 throw uno::RuntimeException();
48 return xResult;
51 //-----------------------------------------------
52 void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
54 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
56 m_xChild->RemoveStreamHierarchically( aListPath );
59 //-----------------------------------------------
60 // static
61 OStringList_Impl OHierarchyHolder_Impl::GetListPathFromString( const OUString& aPath )
63 OStringList_Impl aResult;
64 sal_Int32 nIndex = 0;
67 OUString aName = aPath.getToken( 0, '/', nIndex );
68 if ( aName.isEmpty() )
69 throw lang::IllegalArgumentException();
71 aResult.push_back( aName );
73 while ( nIndex >= 0 );
75 return aResult;
78 //===============================================
79 // OHierarchyElement_Impl
80 //===============================================
82 //-----------------------------------------------
83 uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
85 ::osl::MutexGuard aGuard( m_aMutex );
87 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
88 throw io::IOException();
90 if ( !aListPath.size() )
91 throw uno::RuntimeException();
93 OUString aNextName = *(aListPath.begin());
94 aListPath.erase( aListPath.begin() );
96 uno::Reference< embed::XExtendedStorageStream > xResult;
98 uno::Reference< embed::XStorage > xOwnStor;
100 xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
101 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
102 if ( !xOwnStor.is() )
103 throw uno::RuntimeException();
105 if ( !aListPath.size() )
107 if ( !aEncryptionData.size() )
109 uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
110 xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode );
112 else
114 uno::Reference< embed::XHierarchicalStorageAccess2 > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
115 xResult = xHStorage->openEncryptedStreamByHierarchicalName( aNextName, nStreamMode, aEncryptionData.getAsConstNamedValueList() );
118 uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY );
119 if ( xTransact.is() )
121 // the existance of the transacted object means that the stream is opened for writing also
122 // so the whole chain must be commited
123 uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW );
124 xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) );
126 else
128 uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW );
129 xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) );
132 m_aOpenStreams.push_back( uno::WeakReference< embed::XExtendedStorageStream >( xResult ) );
134 else
136 sal_Bool bNewElement = sal_False;
137 ::rtl::Reference< OHierarchyElement_Impl > aElement;
138 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
139 if ( aIter != m_aChildren.end() )
140 aElement = aIter->second;
142 if ( !aElement.is() )
144 bNewElement = sal_True;
145 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode );
146 if ( !xChildStorage.is() )
147 throw uno::RuntimeException();
149 aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
152 xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
153 if ( !xResult.is() )
154 throw uno::RuntimeException();
156 if ( bNewElement )
158 m_aChildren[aNextName] = aElement;
159 aElement->SetParent( this );
163 // the subelement was opened successfully, remember the storage to let it be locked
164 m_xOwnStorage = xOwnStor;
166 return xResult;
169 //-----------------------------------------------
170 void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
172 ::osl::MutexGuard aGuard( m_aMutex );
174 if ( !aListPath.size() )
175 throw uno::RuntimeException();
177 OUString aNextName = *(aListPath.begin());
178 aListPath.erase( aListPath.begin() );
180 uno::Reference< embed::XExtendedStorageStream > xResult;
182 uno::Reference< embed::XStorage > xOwnStor;
184 xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
185 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
186 if ( !xOwnStor.is() )
187 throw uno::RuntimeException();
189 if ( !aListPath.size() )
191 xOwnStor->removeElement( aNextName );
193 else
195 ::rtl::Reference< OHierarchyElement_Impl > aElement;
196 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
197 if ( aIter != m_aChildren.end() )
198 aElement = aIter->second;
200 if ( !aElement.is() )
202 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName,
203 embed::ElementModes::READWRITE );
204 if ( !xChildStorage.is() )
205 throw uno::RuntimeException();
207 aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
210 aElement->RemoveStreamHierarchically( aListPath );
213 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY );
214 if ( xTransact.is() )
215 xTransact->commit();
217 TestForClosing();
220 //-----------------------------------------------
221 void OHierarchyElement_Impl::Commit()
223 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
224 ::rtl::Reference< OHierarchyElement_Impl > aParent;
225 uno::Reference< embed::XStorage > xOwnStor;
228 ::osl::MutexGuard aGuard( m_aMutex );
229 aParent = m_rParent;
230 xOwnStor = m_xOwnStorage;
233 if ( xOwnStor.is() )
235 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW );
236 xTransact->commit();
237 if ( aParent.is() )
238 aParent->Commit();
242 //-----------------------------------------------
243 void OHierarchyElement_Impl::TestForClosing()
245 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
247 ::osl::MutexGuard aGuard( m_aMutex );
249 if ( !m_aOpenStreams.size() && !m_aChildren.size() )
251 if ( m_rParent.is() )
253 // only the root storage should not be disposed, other storages can be disposed
254 if ( m_xOwnStorage.is() )
258 m_xOwnStorage->dispose();
260 catch( uno::Exception& )
264 m_rParent->RemoveElement( this );
267 m_xOwnStorage = uno::Reference< embed::XStorage >();
272 //-----------------------------------------------
273 void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source )
274 throw ( uno::RuntimeException )
276 uno::Sequence< embed::XStorage > aStoragesToCommit;
280 ::osl::ClearableMutexGuard aGuard( m_aMutex );
281 uno::Reference< embed::XExtendedStorageStream > xStream( Source.Source, uno::UNO_QUERY );
283 for ( OWeakStorRefList_Impl::iterator pStorageIter = m_aOpenStreams.begin();
284 pStorageIter != m_aOpenStreams.end(); )
286 OWeakStorRefList_Impl::iterator pTmp = pStorageIter++;
287 if ( !pTmp->get().is() || pTmp->get() == xStream )
288 m_aOpenStreams.erase( pTmp );
291 aGuard.clear();
293 TestForClosing();
295 catch( uno::Exception& )
297 throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
301 //-----------------------------------------------
302 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef )
305 ::osl::MutexGuard aGuard( m_aMutex );
306 OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin();
307 const OHierarchyElementList_Impl::const_iterator aEnd = m_aChildren.end();
308 while (aIter != aEnd)
310 if (aIter->second == aRef )
311 aIter = m_aChildren.erase(aIter);
312 else
313 ++aIter;
317 TestForClosing();
320 // XTransactionListener
321 //-----------------------------------------------
322 void SAL_CALL OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
323 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
327 //-----------------------------------------------
328 void SAL_CALL OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
329 throw (::com::sun::star::uno::RuntimeException)
333 Commit();
335 catch( const uno::Exception& e )
337 throw lang::WrappedTargetRuntimeException(
338 "Can not commit storage sequence!",
339 uno::Reference< uno::XInterface >(),
340 uno::makeAny( e ) );
344 //-----------------------------------------------
345 void SAL_CALL OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
346 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
350 //-----------------------------------------------
351 void SAL_CALL OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
352 throw (::com::sun::star::uno::RuntimeException)
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */