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 661 : uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
35 : {
36 661 : uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
37 :
38 661 : if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
39 0 : throw io::IOException();
40 :
41 : uno::Reference< embed::XExtendedStorageStream > xResult =
42 661 : m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
43 661 : if ( !xResult.is() )
44 0 : throw uno::RuntimeException();
45 :
46 661 : 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 1322 : OStringList_Impl OHierarchyHolder_Impl::GetListPathFromString( const ::rtl::OUString& aPath )
60 : {
61 1322 : OStringList_Impl aResult;
62 1322 : sal_Int32 nIndex = 0;
63 2034 : do
64 : {
65 2034 : ::rtl::OUString aName = aPath.getToken( 0, '/', nIndex );
66 2034 : if ( aName.isEmpty() )
67 0 : throw lang::IllegalArgumentException();
68 :
69 2034 : aResult.push_back( aName );
70 : }
71 : while ( nIndex >= 0 );
72 :
73 1322 : return aResult;
74 : }
75 :
76 : //===============================================
77 : // OHierarchyElement_Impl
78 : //===============================================
79 :
80 : //-----------------------------------------------
81 1373 : uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData )
82 : {
83 1373 : ::osl::MutexGuard aGuard( m_aMutex );
84 :
85 1373 : if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
86 0 : throw io::IOException();
87 :
88 1373 : if ( !aListPath.size() )
89 0 : throw uno::RuntimeException();
90 :
91 1373 : ::rtl::OUString aNextName = *(aListPath.begin());
92 1373 : aListPath.erase( aListPath.begin() );
93 :
94 1373 : uno::Reference< embed::XExtendedStorageStream > xResult;
95 :
96 1373 : uno::Reference< embed::XStorage > xOwnStor;
97 :
98 1373 : xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
99 1373 : : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
100 1373 : if ( !xOwnStor.is() )
101 0 : throw uno::RuntimeException();
102 :
103 1373 : if ( !aListPath.size() )
104 : {
105 661 : if ( !aEncryptionData.size() )
106 : {
107 661 : uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
108 661 : xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode );
109 : }
110 : else
111 : {
112 0 : uno::Reference< embed::XHierarchicalStorageAccess2 > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
113 0 : xResult = xHStorage->openEncryptedStreamByHierarchicalName( aNextName, nStreamMode, aEncryptionData.getAsConstNamedValueList() );
114 : }
115 :
116 661 : uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY );
117 661 : if ( xTransact.is() )
118 : {
119 : // the existance of the transacted object means that the stream is opened for writing also
120 : // so the whole chain must be commited
121 0 : uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW );
122 0 : xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) );
123 : }
124 : else
125 : {
126 661 : uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW );
127 661 : xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) );
128 : }
129 :
130 661 : m_aOpenStreams.push_back( uno::WeakReference< embed::XExtendedStorageStream >( xResult ) );
131 : }
132 : else
133 : {
134 712 : sal_Bool bNewElement = sal_False;
135 712 : ::rtl::Reference< OHierarchyElement_Impl > aElement;
136 712 : OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
137 712 : if ( aIter != m_aChildren.end() )
138 462 : aElement = aIter->second;
139 :
140 712 : if ( !aElement.is() )
141 : {
142 250 : bNewElement = sal_True;
143 250 : uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode );
144 250 : if ( !xChildStorage.is() )
145 0 : throw uno::RuntimeException();
146 :
147 250 : aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
148 : }
149 :
150 712 : xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aEncryptionData );
151 712 : if ( !xResult.is() )
152 0 : throw uno::RuntimeException();
153 :
154 712 : if ( bNewElement )
155 : {
156 250 : m_aChildren[aNextName] = aElement;
157 250 : aElement->SetParent( this );
158 712 : }
159 : }
160 :
161 : // the subelement was opened successfuly, remember the storage to let it be locked
162 1373 : m_xOwnStorage = xOwnStor;
163 :
164 1373 : return xResult;
165 : }
166 :
167 : //-----------------------------------------------
168 0 : void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
169 : {
170 0 : ::osl::MutexGuard aGuard( m_aMutex );
171 :
172 0 : if ( !aListPath.size() )
173 0 : throw uno::RuntimeException();
174 :
175 0 : ::rtl::OUString aNextName = *(aListPath.begin());
176 0 : aListPath.erase( aListPath.begin() );
177 :
178 0 : uno::Reference< embed::XExtendedStorageStream > xResult;
179 :
180 0 : uno::Reference< embed::XStorage > xOwnStor;
181 :
182 0 : xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
183 0 : : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
184 0 : if ( !xOwnStor.is() )
185 0 : throw uno::RuntimeException();
186 :
187 0 : if ( !aListPath.size() )
188 : {
189 0 : xOwnStor->removeElement( aNextName );
190 : }
191 : else
192 : {
193 0 : ::rtl::Reference< OHierarchyElement_Impl > aElement;
194 0 : OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
195 0 : if ( aIter != m_aChildren.end() )
196 0 : aElement = aIter->second;
197 :
198 0 : if ( !aElement.is() )
199 : {
200 0 : uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName,
201 0 : embed::ElementModes::READWRITE );
202 0 : if ( !xChildStorage.is() )
203 0 : throw uno::RuntimeException();
204 :
205 0 : aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
206 : }
207 :
208 0 : aElement->RemoveStreamHierarchically( aListPath );
209 : }
210 :
211 0 : uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY );
212 0 : if ( xTransact.is() )
213 0 : xTransact->commit();
214 :
215 0 : TestForClosing();
216 0 : }
217 :
218 : //-----------------------------------------------
219 0 : void OHierarchyElement_Impl::Commit()
220 : {
221 0 : ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
222 0 : ::rtl::Reference< OHierarchyElement_Impl > aParent;
223 0 : uno::Reference< embed::XStorage > xOwnStor;
224 :
225 : {
226 0 : ::osl::MutexGuard aGuard( m_aMutex );
227 0 : aParent = m_rParent;
228 0 : xOwnStor = m_xOwnStorage;
229 : }
230 :
231 0 : if ( xOwnStor.is() )
232 : {
233 0 : uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW );
234 0 : xTransact->commit();
235 0 : if ( aParent.is() )
236 0 : aParent->Commit();
237 0 : }
238 0 : }
239 :
240 : //-----------------------------------------------
241 911 : void OHierarchyElement_Impl::TestForClosing()
242 : {
243 911 : ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
244 : {
245 911 : ::osl::MutexGuard aGuard( m_aMutex );
246 :
247 911 : if ( !m_aOpenStreams.size() && !m_aChildren.size() )
248 : {
249 449 : if ( m_rParent.is() )
250 : {
251 : // only the root storage should not be disposed, other storages can be disposed
252 250 : if ( m_xOwnStorage.is() )
253 : {
254 : try
255 : {
256 250 : m_xOwnStorage->dispose();
257 : }
258 0 : catch( uno::Exception& )
259 : {}
260 : }
261 :
262 250 : m_rParent->RemoveElement( this );
263 : }
264 :
265 449 : m_xOwnStorage = uno::Reference< embed::XStorage >();
266 911 : }
267 911 : }
268 911 : }
269 :
270 : //-----------------------------------------------
271 661 : void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source )
272 : throw ( uno::RuntimeException )
273 : {
274 661 : uno::Sequence< embed::XStorage > aStoragesToCommit;
275 :
276 : try
277 : {
278 661 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
279 661 : uno::Reference< embed::XExtendedStorageStream > xStream( Source.Source, uno::UNO_QUERY );
280 :
281 4131 : for ( OWeakStorRefList_Impl::iterator pStorageIter = m_aOpenStreams.begin();
282 3470 : pStorageIter != m_aOpenStreams.end(); )
283 : {
284 1074 : OWeakStorRefList_Impl::iterator pTmp = pStorageIter++;
285 1074 : if ( !pTmp->get().is() || pTmp->get() == xStream )
286 661 : m_aOpenStreams.erase( pTmp );
287 : }
288 :
289 661 : aGuard.clear();
290 :
291 661 : TestForClosing();
292 : }
293 0 : catch( uno::Exception& )
294 : {
295 0 : throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
296 661 : }
297 661 : }
298 :
299 : //-----------------------------------------------
300 250 : void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef )
301 : {
302 : {
303 250 : ::osl::MutexGuard aGuard( m_aMutex );
304 1250 : for ( OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin();
305 1000 : aIter != m_aChildren.end(); /* increment is done in body */)
306 : {
307 250 : OHierarchyElementList_Impl::iterator aTmpIter = aIter;
308 250 : ++aIter;
309 :
310 250 : if ( aTmpIter->second == aRef )
311 250 : m_aChildren.erase( aTmpIter );
312 250 : }
313 : }
314 :
315 250 : TestForClosing();
316 250 : }
317 :
318 : // XTransactionListener
319 : //-----------------------------------------------
320 0 : void SAL_CALL OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
321 : throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
322 : {
323 0 : }
324 :
325 : //-----------------------------------------------
326 0 : void SAL_CALL OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
327 : throw (::com::sun::star::uno::RuntimeException)
328 : {
329 : try
330 : {
331 0 : Commit();
332 : }
333 0 : catch( const uno::Exception& e )
334 : {
335 : throw lang::WrappedTargetRuntimeException(
336 : "Can not commit storage sequence!",
337 : uno::Reference< uno::XInterface >(),
338 0 : uno::makeAny( e ) );
339 : }
340 0 : }
341 :
342 : //-----------------------------------------------
343 0 : void SAL_CALL OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
344 : throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
345 : {
346 0 : }
347 :
348 : //-----------------------------------------------
349 0 : void SAL_CALL OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
350 : throw (::com::sun::star::uno::RuntimeException)
351 : {
352 0 : }
353 :
354 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|