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