1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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/embed/XTransactedObject.hpp>
24 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
25 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
27 #include "ohierarchyholder.hxx"
29 using namespace ::com::sun::star
;
31 //===============================================
32 // OHierarchyHolder_Impl
33 //===============================================
35 //-----------------------------------------------
36 uno::Reference
< embed::XExtendedStorageStream
> OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode
, OStringList_Impl
& aListPath
, sal_Int32 nStreamMode
, const ::comphelper::SequenceAsHashMap
& aEncryptionData
)
38 uno::Reference
< embed::XStorage
> xOwnStor( m_xWeakOwnStorage
.get(), uno::UNO_QUERY_THROW
);
40 if ( !( nStorageMode
& embed::ElementModes::WRITE
) && ( nStreamMode
& embed::ElementModes::WRITE
) )
41 throw io::IOException();
43 uno::Reference
< embed::XExtendedStorageStream
> xResult
=
44 m_xChild
->GetStreamHierarchically( nStorageMode
, aListPath
, nStreamMode
, aEncryptionData
);
46 throw uno::RuntimeException();
51 //-----------------------------------------------
52 void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl
& aListPath
)
54 uno::Reference
< embed::XStorage
> xOwnStor( m_xWeakOwnStorage
.get(), uno::UNO_QUERY_THROW
);
56 m_xChild
->RemoveStreamHierarchically( aListPath
);
59 //-----------------------------------------------
61 OStringList_Impl
OHierarchyHolder_Impl::GetListPathFromString( const OUString
& aPath
)
63 OStringList_Impl aResult
;
67 OUString aName
= aPath
.getToken( 0, '/', nIndex
);
68 if ( aName
.isEmpty() )
69 throw lang::IllegalArgumentException();
71 aResult
.push_back( aName
);
73 while ( nIndex
>= 0 );
78 //===============================================
79 // OHierarchyElement_Impl
80 //===============================================
82 //-----------------------------------------------
83 uno::Reference
< embed::XExtendedStorageStream
> OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode
, OStringList_Impl
& aListPath
, sal_Int32 nStreamMode
, const ::comphelper::SequenceAsHashMap
& aEncryptionData
)
85 ::osl::MutexGuard
aGuard( m_aMutex
);
87 if ( !( nStorageMode
& embed::ElementModes::WRITE
) && ( nStreamMode
& embed::ElementModes::WRITE
) )
88 throw io::IOException();
90 if ( !aListPath
.size() )
91 throw uno::RuntimeException();
93 OUString aNextName
= *(aListPath
.begin());
94 aListPath
.erase( aListPath
.begin() );
96 uno::Reference
< embed::XExtendedStorageStream
> xResult
;
98 uno::Reference
< embed::XStorage
> xOwnStor
;
100 xOwnStor
= m_xOwnStorage
.is() ? m_xOwnStorage
101 : uno::Reference
< embed::XStorage
>( m_xWeakOwnStorage
.get(), uno::UNO_QUERY
);
102 if ( !xOwnStor
.is() )
103 throw uno::RuntimeException();
105 if ( !aListPath
.size() )
107 if ( !aEncryptionData
.size() )
109 uno::Reference
< embed::XHierarchicalStorageAccess
> xHStorage( xOwnStor
, uno::UNO_QUERY_THROW
);
110 xResult
= xHStorage
->openStreamElementByHierarchicalName( aNextName
, nStreamMode
);
114 uno::Reference
< embed::XHierarchicalStorageAccess2
> xHStorage( xOwnStor
, uno::UNO_QUERY_THROW
);
115 xResult
= xHStorage
->openEncryptedStreamByHierarchicalName( aNextName
, nStreamMode
, aEncryptionData
.getAsConstNamedValueList() );
118 uno::Reference
< embed::XTransactedObject
> xTransact( xResult
, uno::UNO_QUERY
);
119 if ( xTransact
.is() )
121 // the existance of the transacted object means that the stream is opened for writing also
122 // so the whole chain must be commited
123 uno::Reference
< embed::XTransactionBroadcaster
> xTrBroadcast( xTransact
, uno::UNO_QUERY_THROW
);
124 xTrBroadcast
->addTransactionListener( static_cast< embed::XTransactionListener
* >( this ) );
128 uno::Reference
< lang::XComponent
> xStreamComp( xResult
, uno::UNO_QUERY_THROW
);
129 xStreamComp
->addEventListener( static_cast< lang::XEventListener
* >( this ) );
132 m_aOpenStreams
.push_back( uno::WeakReference
< embed::XExtendedStorageStream
>( xResult
) );
136 sal_Bool bNewElement
= sal_False
;
137 ::rtl::Reference
< OHierarchyElement_Impl
> aElement
;
138 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.find( aNextName
);
139 if ( aIter
!= m_aChildren
.end() )
140 aElement
= aIter
->second
;
142 if ( !aElement
.is() )
144 bNewElement
= sal_True
;
145 uno::Reference
< embed::XStorage
> xChildStorage
= xOwnStor
->openStorageElement( aNextName
, nStorageMode
);
146 if ( !xChildStorage
.is() )
147 throw uno::RuntimeException();
149 aElement
= new OHierarchyElement_Impl( NULL
, xChildStorage
);
152 xResult
= aElement
->GetStreamHierarchically( nStorageMode
, aListPath
, nStreamMode
, aEncryptionData
);
154 throw uno::RuntimeException();
158 m_aChildren
[aNextName
] = aElement
;
159 aElement
->SetParent( this );
163 // the subelement was opened successfully, remember the storage to let it be locked
164 m_xOwnStorage
= xOwnStor
;
169 //-----------------------------------------------
170 void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl
& aListPath
)
172 ::osl::MutexGuard
aGuard( m_aMutex
);
174 if ( !aListPath
.size() )
175 throw uno::RuntimeException();
177 OUString aNextName
= *(aListPath
.begin());
178 aListPath
.erase( aListPath
.begin() );
180 uno::Reference
< embed::XExtendedStorageStream
> xResult
;
182 uno::Reference
< embed::XStorage
> xOwnStor
;
184 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();
189 if ( !aListPath
.size() )
191 xOwnStor
->removeElement( aNextName
);
195 ::rtl::Reference
< OHierarchyElement_Impl
> aElement
;
196 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.find( aNextName
);
197 if ( aIter
!= m_aChildren
.end() )
198 aElement
= aIter
->second
;
200 if ( !aElement
.is() )
202 uno::Reference
< embed::XStorage
> xChildStorage
= xOwnStor
->openStorageElement( aNextName
,
203 embed::ElementModes::READWRITE
);
204 if ( !xChildStorage
.is() )
205 throw uno::RuntimeException();
207 aElement
= new OHierarchyElement_Impl( NULL
, xChildStorage
);
210 aElement
->RemoveStreamHierarchically( aListPath
);
213 uno::Reference
< embed::XTransactedObject
> xTransact( xOwnStor
, uno::UNO_QUERY
);
214 if ( xTransact
.is() )
220 //-----------------------------------------------
221 void OHierarchyElement_Impl::Commit()
223 ::rtl::Reference
< OHierarchyElement_Impl
> aLocker( this );
224 ::rtl::Reference
< OHierarchyElement_Impl
> aParent
;
225 uno::Reference
< embed::XStorage
> xOwnStor
;
228 ::osl::MutexGuard
aGuard( m_aMutex
);
230 xOwnStor
= m_xOwnStorage
;
235 uno::Reference
< embed::XTransactedObject
> xTransact( xOwnStor
, uno::UNO_QUERY_THROW
);
242 //-----------------------------------------------
243 void OHierarchyElement_Impl::TestForClosing()
245 ::rtl::Reference
< OHierarchyElement_Impl
> aLocker( this );
247 ::osl::MutexGuard
aGuard( m_aMutex
);
249 if ( !m_aOpenStreams
.size() && !m_aChildren
.size() )
251 if ( m_rParent
.is() )
253 // only the root storage should not be disposed, other storages can be disposed
254 if ( m_xOwnStorage
.is() )
258 m_xOwnStorage
->dispose();
260 catch( uno::Exception
& )
264 m_rParent
->RemoveElement( this );
267 m_xOwnStorage
= uno::Reference
< embed::XStorage
>();
272 //-----------------------------------------------
273 void SAL_CALL
OHierarchyElement_Impl::disposing( const lang::EventObject
& Source
)
274 throw ( uno::RuntimeException
)
276 uno::Sequence
< embed::XStorage
> aStoragesToCommit
;
280 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
281 uno::Reference
< embed::XExtendedStorageStream
> xStream( Source
.Source
, uno::UNO_QUERY
);
283 for ( OWeakStorRefList_Impl::iterator pStorageIter
= m_aOpenStreams
.begin();
284 pStorageIter
!= m_aOpenStreams
.end(); )
286 OWeakStorRefList_Impl::iterator pTmp
= pStorageIter
++;
287 if ( !pTmp
->get().is() || pTmp
->get() == xStream
)
288 m_aOpenStreams
.erase( pTmp
);
295 catch( uno::Exception
& )
297 throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
301 //-----------------------------------------------
302 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference
< OHierarchyElement_Impl
>& aRef
)
305 ::osl::MutexGuard
aGuard( m_aMutex
);
306 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.begin();
307 const OHierarchyElementList_Impl::const_iterator aEnd
= m_aChildren
.end();
308 while (aIter
!= aEnd
)
310 if (aIter
->second
== aRef
)
311 aIter
= m_aChildren
.erase(aIter
);
320 // XTransactionListener
321 //-----------------------------------------------
322 void SAL_CALL
OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
323 throw (::com::sun::star::uno::Exception
, ::com::sun::star::uno::RuntimeException
)
327 //-----------------------------------------------
328 void SAL_CALL
OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
329 throw (::com::sun::star::uno::RuntimeException
)
335 catch( const uno::Exception
& e
)
337 throw lang::WrappedTargetRuntimeException(
338 "Can not commit storage sequence!",
339 uno::Reference
< uno::XInterface
>(),
344 //-----------------------------------------------
345 void SAL_CALL
OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
346 throw (::com::sun::star::uno::Exception
, ::com::sun::star::uno::RuntimeException
)
350 //-----------------------------------------------
351 void SAL_CALL
OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
352 throw (::com::sun::star::uno::RuntimeException
)
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */