1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ohierarchyholder.cxx,v $
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
);
57 throw uno::RuntimeException();
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 //-----------------------------------------------
72 OStringList_Impl
OHierarchyHolder_Impl::GetListPathFromString( const ::rtl::OUString
& aPath
)
74 OStringList_Impl aResult
;
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 );
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
);
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 ) );
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
) );
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
);
158 throw uno::RuntimeException();
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
;
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
);
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() )
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
);
234 xOwnStor
= m_xOwnStorage
;
239 uno::Reference
< embed::XTransactedObject
> xTransact( xOwnStor
, uno::UNO_QUERY_THROW
);
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
);
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
;
316 if ( aTmpIter
->second
== aRef
)
317 m_aChildren
.erase( aTmpIter
);
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
)
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
>(),
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
)