merge the formfield patch from ooo-build
[ooovba.git] / package / source / xstor / ohierarchyholder.cxx
blob4dc127ac873dea3b06d8372ac6d753b881b4565a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ohierarchyholder.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_package.hxx"
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <com/sun/star/embed/ElementModes.hpp>
35 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
38 #include "ohierarchyholder.hxx"
40 using namespace ::com::sun::star;
42 //===============================================
43 // OHierarchyHolder_Impl
44 //===============================================
46 //-----------------------------------------------
47 uno::Reference< embed::XExtendedStorageStream > OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::rtl::OUString& aPass )
49 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
51 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
52 throw io::IOException();
54 uno::Reference< embed::XExtendedStorageStream > xResult =
55 m_xChild->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aPass );
56 if ( !xResult.is() )
57 throw uno::RuntimeException();
59 return xResult;
62 //-----------------------------------------------
63 void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
65 uno::Reference< embed::XStorage > xOwnStor( m_xWeakOwnStorage.get(), uno::UNO_QUERY_THROW );
67 m_xChild->RemoveStreamHierarchically( aListPath );
70 //-----------------------------------------------
71 // static
72 OStringList_Impl OHierarchyHolder_Impl::GetListPathFromString( const ::rtl::OUString& aPath )
74 OStringList_Impl aResult;
75 sal_Int32 nIndex = 0;
78 ::rtl::OUString aName = aPath.getToken( 0, '/', nIndex );
79 if ( !aName.getLength() )
80 throw lang::IllegalArgumentException();
82 aResult.push_back( aName );
84 while ( nIndex >= 0 );
86 return aResult;
89 //===============================================
90 // OHierarchyElement_Impl
91 //===============================================
93 //-----------------------------------------------
94 uno::Reference< embed::XExtendedStorageStream > OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode, OStringList_Impl& aListPath, sal_Int32 nStreamMode, const ::rtl::OUString& aPass )
96 ::osl::MutexGuard aGuard( m_aMutex );
98 if ( !( nStorageMode & embed::ElementModes::WRITE ) && ( nStreamMode & embed::ElementModes::WRITE ) )
99 throw io::IOException();
101 if ( !aListPath.size() )
102 throw uno::RuntimeException();
104 ::rtl::OUString aNextName = *(aListPath.begin());
105 aListPath.erase( aListPath.begin() );
107 uno::Reference< embed::XExtendedStorageStream > xResult;
109 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
110 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
111 if ( !xOwnStor.is() )
112 throw uno::RuntimeException();
114 if ( !aListPath.size() )
116 uno::Reference< embed::XHierarchicalStorageAccess > xHStorage( xOwnStor, uno::UNO_QUERY_THROW );
117 if ( !aPass.getLength() )
118 xResult = xHStorage->openStreamElementByHierarchicalName( aNextName, nStreamMode );
119 else
120 xResult = xHStorage->openEncryptedStreamElementByHierarchicalName( aNextName, nStreamMode, aPass );
122 uno::Reference< embed::XTransactedObject > xTransact( xResult, uno::UNO_QUERY );
123 if ( xTransact.is() )
125 // the existance of the transacted object means that the stream is opened for writing also
126 // so the whole chain must be commited
127 uno::Reference< embed::XTransactionBroadcaster > xTrBroadcast( xTransact, uno::UNO_QUERY_THROW );
128 xTrBroadcast->addTransactionListener( static_cast< embed::XTransactionListener* >( this ) );
130 else
132 uno::Reference< lang::XComponent > xStreamComp( xResult, uno::UNO_QUERY_THROW );
133 xStreamComp->addEventListener( static_cast< lang::XEventListener* >( this ) );
136 m_aOpenStreams.push_back( uno::WeakReference< embed::XExtendedStorageStream >( xResult ) );
138 else
140 sal_Bool bNewElement = sal_False;
141 ::rtl::Reference< OHierarchyElement_Impl > aElement;
142 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
143 if ( aIter != m_aChildren.end() )
144 aElement = aIter->second;
146 if ( !aElement.is() )
148 bNewElement = sal_True;
149 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName, nStorageMode );
150 if ( !xChildStorage.is() )
151 throw uno::RuntimeException();
153 aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
156 xResult = aElement->GetStreamHierarchically( nStorageMode, aListPath, nStreamMode, aPass );
157 if ( !xResult.is() )
158 throw uno::RuntimeException();
160 if ( bNewElement )
162 m_aChildren[aNextName] = aElement;
163 aElement->SetParent( this );
167 // the subelement was opened successfuly, remember the storage to let it be locked
168 m_xOwnStorage = xOwnStor;
170 return xResult;
173 //-----------------------------------------------
174 void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl& aListPath )
176 ::osl::MutexGuard aGuard( m_aMutex );
178 if ( !aListPath.size() )
179 throw uno::RuntimeException();
181 ::rtl::OUString aNextName = *(aListPath.begin());
182 aListPath.erase( aListPath.begin() );
184 uno::Reference< embed::XExtendedStorageStream > xResult;
186 uno::Reference< embed::XStorage > xOwnStor = m_xOwnStorage.is() ? m_xOwnStorage
187 : uno::Reference< embed::XStorage >( m_xWeakOwnStorage.get(), uno::UNO_QUERY );
188 if ( !xOwnStor.is() )
189 throw uno::RuntimeException();
191 if ( !aListPath.size() )
193 xOwnStor->removeElement( aNextName );
195 else
197 sal_Bool bNewElement = sal_False;
198 ::rtl::Reference< OHierarchyElement_Impl > aElement;
199 OHierarchyElementList_Impl::iterator aIter = m_aChildren.find( aNextName );
200 if ( aIter != m_aChildren.end() )
201 aElement = aIter->second;
203 if ( !aElement.is() )
205 bNewElement = sal_True;
206 uno::Reference< embed::XStorage > xChildStorage = xOwnStor->openStorageElement( aNextName,
207 embed::ElementModes::READWRITE );
208 if ( !xChildStorage.is() )
209 throw uno::RuntimeException();
211 aElement = new OHierarchyElement_Impl( NULL, xChildStorage );
214 aElement->RemoveStreamHierarchically( aListPath );
217 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY );
218 if ( xTransact.is() )
219 xTransact->commit();
221 TestForClosing();
224 //-----------------------------------------------
225 void OHierarchyElement_Impl::Commit()
227 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
228 ::rtl::Reference< OHierarchyElement_Impl > aParent;
229 uno::Reference< embed::XStorage > xOwnStor;
232 ::osl::MutexGuard aGuard( m_aMutex );
233 aParent = m_rParent;
234 xOwnStor = m_xOwnStorage;
237 if ( xOwnStor.is() )
239 uno::Reference< embed::XTransactedObject > xTransact( xOwnStor, uno::UNO_QUERY_THROW );
240 xTransact->commit();
241 if ( aParent.is() )
242 aParent->Commit();
246 //-----------------------------------------------
247 void OHierarchyElement_Impl::TestForClosing()
249 ::rtl::Reference< OHierarchyElement_Impl > aLocker( this );
251 ::osl::MutexGuard aGuard( m_aMutex );
253 if ( !m_aOpenStreams.size() && !m_aChildren.size() )
255 if ( m_rParent.is() )
257 // only the root storage should not be disposed, other storages can be disposed
258 if ( m_xOwnStorage.is() )
262 m_xOwnStorage->dispose();
264 catch( uno::Exception& )
268 m_rParent->RemoveElement( this );
271 m_xOwnStorage = uno::Reference< embed::XStorage >();
276 //-----------------------------------------------
277 void SAL_CALL OHierarchyElement_Impl::disposing( const lang::EventObject& Source )
278 throw ( uno::RuntimeException )
280 uno::Sequence< embed::XStorage > aStoragesToCommit;
284 ::osl::ClearableMutexGuard aGuard( m_aMutex );
285 uno::Reference< embed::XExtendedStorageStream > xStream( Source.Source, uno::UNO_QUERY );
287 for ( OWeakStorRefList_Impl::iterator pStorageIter = m_aOpenStreams.begin();
288 pStorageIter != m_aOpenStreams.end(); )
290 OWeakStorRefList_Impl::iterator pTmp = pStorageIter++;
291 if ( !pTmp->get().is() || pTmp->get() == xStream )
292 m_aOpenStreams.erase( pTmp );
295 aGuard.clear();
297 TestForClosing();
299 catch( uno::Exception& )
301 throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
305 //-----------------------------------------------
306 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference< OHierarchyElement_Impl >& aRef )
309 ::osl::MutexGuard aGuard( m_aMutex );
310 for ( OHierarchyElementList_Impl::iterator aIter = m_aChildren.begin();
311 aIter != m_aChildren.end(); /* increment is done in body */)
313 OHierarchyElementList_Impl::iterator aTmpIter = aIter;
314 aIter++;
316 if ( aTmpIter->second == aRef )
317 m_aChildren.erase( aTmpIter );
321 TestForClosing();
324 // XTransactionListener
325 //-----------------------------------------------
326 void SAL_CALL OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
327 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
331 //-----------------------------------------------
332 void SAL_CALL OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
333 throw (::com::sun::star::uno::RuntimeException)
337 Commit();
339 catch( uno::Exception& e )
341 throw lang::WrappedTargetRuntimeException(
342 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can not commit storage sequence!" ) ),
343 uno::Reference< uno::XInterface >(),
344 uno::makeAny( e ) );
348 //-----------------------------------------------
349 void SAL_CALL OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
350 throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
354 //-----------------------------------------------
355 void SAL_CALL OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
356 throw (::com::sun::star::uno::RuntimeException)