Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <com/sun/star/uno/Reference.hxx>
21 : : #include <com/sun/star/embed/ElementModes.hpp>
22 : : #include <com/sun/star/embed/XHierarchicalStorageAccess2.hpp>
23 : : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
24 : :
25 : : #include "ohierarchyholder.hxx"
26 : :
27 : : using namespace ::com::sun::star;
28 : :
29 : : //===============================================
30 : : // OHierarchyHolder_Impl
31 : : //===============================================
32 : :
33 : : //-----------------------------------------------
34 : 1289 : uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
35 : : {
36 [ + - ][ + - ]: 1289 : uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
37 : :
38 [ - + ][ + - ]: 1289 : if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
39 [ # # ]: 0 : throw io::IOException();
40 : :
41 : : uno::Reference< embed::XExtendedStorageStream > xResult =
42 [ + - ]: 1289 : m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
43 [ - + ]: 1289 : if ( !xResult.is() )
44 [ # # ]: 0 : throw uno::RuntimeException();
45 : :
46 : 1289 : return xResult;
47 : : }
48 : :
49 : : //-----------------------------------------------
50 : 0 : void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
51 : : {
52 [ # # ][ # # ]: 0 : uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
53 : :
54 [ # # ]: 0 : m_xChild->RemoveStreamHierarchically( aListPath );
55 : 0 : }
56 : :
57 : : //-----------------------------------------------
58 : : // static
59 : 2578 : OStringList_Impl OHierarchyHolder_Impl::GetListPathFromString( const ::rtl::OUString& aPath )
60 : : {
61 [ + - ]: 2578 : OStringList_Impl aResult;
62 : 2578 : sal_Int32 nIndex = 0;
63 [ + + ]: 3950 : do
64 : : {
65 : 3950 : ::rtl::OUString aName = aPath.getToken( 0, '/', nIndex );
66 [ - + ]: 3950 : if ( aName.isEmpty() )
67 [ # # ]: 0 : throw lang::IllegalArgumentException();
68 : :
69 [ + - ]: 3950 : aResult.push_back( aName );
70 : : }
71 : : while ( nIndex >= 0 );
72 : :
73 : 2578 : return aResult;
74 : : }
75 : :
76 : : //===============================================
77 : : // OHierarchyElement_Impl
78 : : //===============================================
79 : :
80 : : //-----------------------------------------------
81 : 2661 : uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
82 : : {
83 [ + - ]: 2661 : ::osl::MutexGuard aGuard( m_aMutex );
84 : :
85 [ + - ][ - + ]: 2661 : if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
86 [ # # ]: 0 : throw io::IOException();
87 : :
88 [ - + ]: 2661 : if ( !aListPath.size() )
89 [ # # ]: 0 : throw uno::RuntimeException();
90 : :
91 : 2661 : ::rtl::OUString aNextName = *(aListPath.begin());
92 [ + - ]: 2661 : aListPath.erase( aListPath.begin() );
93 : :
94 : 2661 : uno::Reference< embed::XExtendedStorageStream > xResult;
95 : :
96 : 2661 : uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
97 [ + - ][ + - ]: 2661 : : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
[ + + ][ # # ]
[ + + ]
98 [ - + ]: 2661 : if ( !xOwnStor.is() )
99 [ # # ]: 0 : throw uno::RuntimeException();
100 : :
101 [ + + ]: 2661 : if ( !aListPath.size() )
102 : : {
103 [ + - ]: 1289 : if ( !aEncryptionData.size() )
104 : : {
105 [ + - ]: 1289 : uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
106 [ + - ][ + - ]: 1289 : xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode );
[ + - ]
107 : : }
108 : : else
109 : : {
110 [ # # ]: 0 : uno::Reference< embed::XHierarchicalStorageAccess2 > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
111 [ # # ][ # # ]: 0 : xResult = xHStorage->openEncryptedStreamByHierarchicalName( aNextName, nStreamMode, aEncryptionData.getAsConstNamedValueList() );
[ # # ][ # # ]
[ # # ]
112 : : }
113 : :
114 [ + - ]: 1289 : uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY );
115 [ - + ]: 1289 : if ( xTransact.is() )
116 : : {
117 : : // the existance of the transacted object means that the stream is opened for writing also
118 : : // so the whole chain must be commited
119 [ # # ]: 0 : uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW );
120 [ # # ][ # # ]: 0 : xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) );
[ # # ]
121 : : }
122 : : else
123 : : {
124 [ + - ]: 1289 : uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW );
125 [ + - ][ + - ]: 1289 : xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) );
[ + - ]
126 : : }
127 : :
128 [ + - ][ + - ]: 1289 : m_aOpenStreams.push_back( uno::WeakReference< embed::XExtendedStorageStream >( xResult ) );
[ + - ]
129 : : }
130 : : else
131 : : {
132 : 1372 : sal_Bool bNewElement = sal_False;
133 : 1372 : ::rtl::Reference< OHierarchyElement_Impl > aElement;
134 [ + - ]: 1372 : OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
135 [ + - ][ + + ]: 1372 : if ( aIter != m_aChildren.end() )
136 [ + - ][ + - ]: 883 : aElement = aIter->second;
137 : :
138 [ + + ]: 1372 : if ( !aElement.is() )
139 : : {
140 : 489 : bNewElement = sal_True;
141 [ + - ][ + - ]: 489 : uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode );
142 [ - + ]: 489 : if ( !xChildStorage.is() )
143 [ # # ]: 0 : throw uno::RuntimeException();
144 : :
145 [ + - ][ + - ]: 489 : aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
146 : : }
147 : :
148 [ + - ][ + - ]: 1372 : xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
149 [ - + ]: 1372 : if ( !xResult.is() )
150 [ # # ]: 0 : throw uno::RuntimeException();
151 : :
152 [ + + ]: 1372 : if ( bNewElement )
153 : : {
154 [ + - ][ + - ]: 489 : m_aChildren[aNextName] = aElement;
155 [ + - ]: 489 : aElement->SetParent( this );
156 : 1372 : }
157 : : }
158 : :
159 : : // the subelement was opened successfuly, remember the storage to let it be locked
160 [ + - ]: 2661 : m_xOwnStorage = xOwnStor;
161 : :
162 [ + - ]: 2661 : return xResult;
163 : : }
164 : :
165 : : //-----------------------------------------------
166 : 0 : void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
167 : : {
168 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
169 : :
170 [ # # ]: 0 : if ( !aListPath.size() )
171 [ # # ]: 0 : throw uno::RuntimeException();
172 : :
173 : 0 : ::rtl::OUString aNextName = *(aListPath.begin());
174 [ # # ]: 0 : aListPath.erase( aListPath.begin() );
175 : :
176 : 0 : uno::Reference< embed::XExtendedStorageStream > xResult;
177 : :
178 : 0 : uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
179 [ # # ][ # # ]: 0 : : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
[ # # ][ # # ]
[ # # ]
180 [ # # ]: 0 : if ( !xOwnStor.is() )
181 [ # # ]: 0 : throw uno::RuntimeException();
182 : :
183 [ # # ]: 0 : if ( !aListPath.size() )
184 : : {
185 [ # # ][ # # ]: 0 : xOwnStor->removeElement( aNextName );
186 : : }
187 : : else
188 : : {
189 : 0 : ::rtl::Reference< OHierarchyElement_Impl > aElement;
190 [ # # ]: 0 : OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
191 [ # # ][ # # ]: 0 : if ( aIter != m_aChildren.end() )
192 [ # # ][ # # ]: 0 : aElement = aIter->second;
193 : :
194 [ # # ]: 0 : if ( !aElement.is() )
195 : : {
196 [ # # ]: 0 : uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName,
197 [ # # ]: 0 : embed::ElementModes::READWRITE );
198 [ # # ]: 0 : if ( !xChildStorage.is() )
199 [ # # ]: 0 : throw uno::RuntimeException();
200 : :
201 [ # # ][ # # ]: 0 : aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
202 : : }
203 : :
204 [ # # ]: 0 : aElement->RemoveStreamHierarchically( aListPath );
205 : : }
206 : :
207 [ # # ]: 0 : uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY );
208 [ # # ]: 0 : if ( xTransact.is() )
209 [ # # ][ # # ]: 0 : xTransact->commit();
210 : :
211 [ # # ][ # # ]: 0 : TestForClosing();
212 : 0 : }
213 : :
214 : : //-----------------------------------------------
215 : 0 : void OHierarchyElement_Impl::Commit()
216 : : {
217 : 0 : ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
218 : 0 : ::rtl::Reference< OHierarchyElement_Impl > aParent;
219 : 0 : uno::Reference< embed::XStorage > xOwnStor;
220 : :
221 : : {
222 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
223 [ # # ]: 0 : aParent = m_rParent;
224 [ # # ][ # # ]: 0 : xOwnStor = m_xOwnStorage;
225 : : }
226 : :
227 [ # # ]: 0 : if ( xOwnStor.is() )
228 : : {
229 [ # # ]: 0 : uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW );
230 [ # # ][ # # ]: 0 : xTransact->commit();
231 [ # # ]: 0 : if ( aParent.is() )
232 [ # # ]: 0 : aParent->Commit();
233 : 0 : }
234 : 0 : }
235 : :
236 : : //-----------------------------------------------
237 : 1778 : void OHierarchyElement_Impl::TestForClosing()
238 : : {
239 : 1778 : ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
240 : : {
241 [ + - ]: 1778 : ::osl::MutexGuard aGuard( m_aMutex );
242 : :
243 [ + + ][ + - ]: 1778 : if ( !m_aOpenStreams.size() && !m_aChildren.size() )
[ + + ]
244 : : {
245 [ + + ]: 895 : if ( m_rParent.is() )
246 : : {
247 : : // only the root storage should not be disposed, other storages can be disposed
248 [ + - ]: 489 : if ( m_xOwnStorage.is() )
249 : : {
250 : : try
251 : : {
252 [ + - ][ + - ]: 489 : m_xOwnStorage->dispose();
253 : : }
254 [ # # ]: 0 : catch( uno::Exception& )
255 : : {}
256 : : }
257 : :
258 [ + - ]: 489 : m_rParent->RemoveElement( this );
259 : : }
260 : :
261 [ + - ]: 895 : m_xOwnStorage = uno::Reference< embed::XStorage >();
262 [ + - ]: 1778 : }
263 : 1778 : }
264 [ # # ]: 1778 : }
265 : :
266 : : //-----------------------------------------------
267 : 1289 : void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source )
268 : : throw ( uno::RuntimeException )
269 : : {
270 [ + - ]: 1289 : uno::Sequence< embed::XStorage > aStoragesToCommit;
271 : :
272 : : try
273 : : {
274 [ + - ]: 1289 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
275 [ + - ]: 1289 : uno::Reference< embed::XExtendedStorageStream > xStream( Source.Source, uno::UNO_QUERY );
276 : :
277 [ + + ]: 4667 : for ( OWeakStorRefList_Impl::iterator pStorageIter = m_aOpenStreams.begin();
278 : 3378 : pStorageIter != m_aOpenStreams.end(); )
279 : : {
280 : 2089 : OWeakStorRefList_Impl::iterator pTmp = pStorageIter++;
281 [ + + ][ + - ]: 2089 : if ( !pTmp->get().is() || pTmp->get() == xStream )
[ + - ][ + + ]
[ + + ][ + - ]
[ + + # #
# # ][ + - ]
282 [ + - ]: 2089 : m_aOpenStreams.erase( pTmp );
283 : : }
284 : :
285 [ + - ]: 1289 : aGuard.clear();
286 : :
287 [ + - ][ + - ]: 1289 : TestForClosing();
288 : : }
289 [ # # ]: 0 : catch( uno::Exception& )
290 : : {
291 [ # # ]: 0 : throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
292 [ + - ]: 1289 : }
293 : 1289 : }
294 : :
295 : : //-----------------------------------------------
296 : 489 : void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef )
297 : : {
298 : : {
299 [ + - ]: 489 : ::osl::MutexGuard aGuard( m_aMutex );
300 [ + - ][ + + ]: 1467 : for ( OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin();
301 [ + - ]: 978 : aIter != m_aChildren.end(); /* increment is done in body */)
302 : : {
303 : 489 : OHierarchyElementList_Impl::iterator aTmpIter = aIter;
304 : 489 : ++aIter;
305 : :
306 [ + - ][ + - ]: 489 : if ( aTmpIter->second == aRef )
307 [ + - ]: 489 : m_aChildren.erase( aTmpIter );
308 [ + - ]: 489 : }
309 : : }
310 : :
311 : 489 : TestForClosing();
312 : 489 : }
313 : :
314 : : // XTransactionListener
315 : : //-----------------------------------------------
316 : 0 : void SAL_CALL OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
317 : : throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
318 : : {
319 : 0 : }
320 : :
321 : : //-----------------------------------------------
322 : 0 : void SAL_CALL OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
323 : : throw (::com::sun::star::uno::RuntimeException)
324 : : {
325 : : try
326 : : {
327 [ # # ]: 0 : Commit();
328 : : }
329 [ # # ]: 0 : catch( const uno::Exception& e )
330 : : {
331 : : throw lang::WrappedTargetRuntimeException(
332 : : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can not commit storage sequence!" ) ),
333 : : uno::Reference< uno::XInterface >(),
334 [ # # # # : 0 : uno::makeAny( e ) );
# # ]
335 : : }
336 : 0 : }
337 : :
338 : : //-----------------------------------------------
339 : 0 : void SAL_CALL OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
340 : : throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
341 : : {
342 : 0 : }
343 : :
344 : : //-----------------------------------------------
345 : 0 : void SAL_CALL OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
346 : : throw (::com::sun::star::uno::RuntimeException)
347 : : {
348 : 0 : }
349 : :
350 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|