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 // OHierarchyHolder_Impl
33 uno::Reference
< embed::XExtendedStorageStream
> OHierarchyHolder_Impl::GetStreamHierarchically( sal_Int32 nStorageMode
, OStringList_Impl
& aListPath
, sal_Int32 nStreamMode
, const ::comphelper::SequenceAsHashMap
& aEncryptionData
)
35 uno::Reference
< embed::XStorage
> xOwnStor( m_xWeakOwnStorage
.get(), uno::UNO_QUERY_THROW
);
37 if ( !( nStorageMode
& embed::ElementModes::WRITE
) && ( nStreamMode
& embed::ElementModes::WRITE
) )
38 throw io::IOException();
40 uno::Reference
< embed::XExtendedStorageStream
> xResult
=
41 m_xChild
->GetStreamHierarchically( nStorageMode
, aListPath
, nStreamMode
, aEncryptionData
);
43 throw uno::RuntimeException();
48 void OHierarchyHolder_Impl::RemoveStreamHierarchically( OStringList_Impl
& aListPath
)
50 uno::Reference
< embed::XStorage
> xOwnStor( m_xWeakOwnStorage
.get(), uno::UNO_QUERY_THROW
);
52 m_xChild
->RemoveStreamHierarchically( aListPath
);
56 OStringList_Impl
OHierarchyHolder_Impl::GetListPathFromString( const OUString
& aPath
)
58 OStringList_Impl aResult
;
62 OUString aName
= aPath
.getToken( 0, '/', nIndex
);
63 if ( aName
.isEmpty() )
64 throw lang::IllegalArgumentException();
66 aResult
.push_back( aName
);
68 while ( nIndex
>= 0 );
73 // OHierarchyElement_Impl
75 uno::Reference
< embed::XExtendedStorageStream
> OHierarchyElement_Impl::GetStreamHierarchically( sal_Int32 nStorageMode
, OStringList_Impl
& aListPath
, sal_Int32 nStreamMode
, const ::comphelper::SequenceAsHashMap
& aEncryptionData
)
77 ::osl::MutexGuard
aGuard( m_aMutex
);
79 if ( !( nStorageMode
& embed::ElementModes::WRITE
) && ( nStreamMode
& embed::ElementModes::WRITE
) )
80 throw io::IOException();
82 if ( !aListPath
.size() )
83 throw uno::RuntimeException();
85 OUString aNextName
= *(aListPath
.begin());
86 aListPath
.erase( aListPath
.begin() );
88 uno::Reference
< embed::XExtendedStorageStream
> xResult
;
90 uno::Reference
< embed::XStorage
> xOwnStor
;
92 xOwnStor
= m_xOwnStorage
.is() ? m_xOwnStorage
93 : uno::Reference
< embed::XStorage
>( m_xWeakOwnStorage
.get(), uno::UNO_QUERY
);
95 throw uno::RuntimeException();
97 if ( !aListPath
.size() )
99 if ( !aEncryptionData
.size() )
101 uno::Reference
< embed::XHierarchicalStorageAccess
> xHStorage( xOwnStor
, uno::UNO_QUERY_THROW
);
102 xResult
= xHStorage
->openStreamElementByHierarchicalName( aNextName
, nStreamMode
);
106 uno::Reference
< embed::XHierarchicalStorageAccess2
> xHStorage( xOwnStor
, uno::UNO_QUERY_THROW
);
107 xResult
= xHStorage
->openEncryptedStreamByHierarchicalName( aNextName
, nStreamMode
, aEncryptionData
.getAsConstNamedValueList() );
110 uno::Reference
< embed::XTransactedObject
> xTransact( xResult
, uno::UNO_QUERY
);
111 if ( xTransact
.is() )
113 // the existence of the transacted object means that the stream is opened for writing also
114 // so the whole chain must be committed
115 uno::Reference
< embed::XTransactionBroadcaster
> xTrBroadcast( xTransact
, uno::UNO_QUERY_THROW
);
116 xTrBroadcast
->addTransactionListener( static_cast< embed::XTransactionListener
* >( this ) );
120 uno::Reference
< lang::XComponent
> xStreamComp( xResult
, uno::UNO_QUERY_THROW
);
121 xStreamComp
->addEventListener( static_cast< lang::XEventListener
* >( this ) );
124 m_aOpenStreams
.push_back( uno::WeakReference
< embed::XExtendedStorageStream
>( xResult
) );
128 bool bNewElement
= false;
129 ::rtl::Reference
< OHierarchyElement_Impl
> aElement
;
130 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.find( aNextName
);
131 if ( aIter
!= m_aChildren
.end() )
132 aElement
= aIter
->second
;
134 if ( !aElement
.is() )
137 uno::Reference
< embed::XStorage
> xChildStorage
= xOwnStor
->openStorageElement( aNextName
, nStorageMode
);
138 if ( !xChildStorage
.is() )
139 throw uno::RuntimeException();
141 aElement
= new OHierarchyElement_Impl( NULL
, xChildStorage
);
144 xResult
= aElement
->GetStreamHierarchically( nStorageMode
, aListPath
, nStreamMode
, aEncryptionData
);
146 throw uno::RuntimeException();
150 m_aChildren
[aNextName
] = aElement
;
151 aElement
->SetParent( this );
155 // the subelement was opened successfully, remember the storage to let it be locked
156 m_xOwnStorage
= xOwnStor
;
161 void OHierarchyElement_Impl::RemoveStreamHierarchically( OStringList_Impl
& aListPath
)
163 ::osl::MutexGuard
aGuard( m_aMutex
);
165 if ( !aListPath
.size() )
166 throw uno::RuntimeException();
168 OUString aNextName
= *(aListPath
.begin());
169 aListPath
.erase( aListPath
.begin() );
171 uno::Reference
< embed::XExtendedStorageStream
> xResult
;
173 uno::Reference
< embed::XStorage
> xOwnStor
;
175 xOwnStor
= m_xOwnStorage
.is() ? m_xOwnStorage
176 : uno::Reference
< embed::XStorage
>( m_xWeakOwnStorage
.get(), uno::UNO_QUERY
);
177 if ( !xOwnStor
.is() )
178 throw uno::RuntimeException();
180 if ( !aListPath
.size() )
182 xOwnStor
->removeElement( aNextName
);
186 ::rtl::Reference
< OHierarchyElement_Impl
> aElement
;
187 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.find( aNextName
);
188 if ( aIter
!= m_aChildren
.end() )
189 aElement
= aIter
->second
;
191 if ( !aElement
.is() )
193 uno::Reference
< embed::XStorage
> xChildStorage
= xOwnStor
->openStorageElement( aNextName
,
194 embed::ElementModes::READWRITE
);
195 if ( !xChildStorage
.is() )
196 throw uno::RuntimeException();
198 aElement
= new OHierarchyElement_Impl( NULL
, xChildStorage
);
201 aElement
->RemoveStreamHierarchically( aListPath
);
204 uno::Reference
< embed::XTransactedObject
> xTransact( xOwnStor
, uno::UNO_QUERY
);
205 if ( xTransact
.is() )
211 void OHierarchyElement_Impl::Commit()
213 ::rtl::Reference
< OHierarchyElement_Impl
> aLocker( this );
214 ::rtl::Reference
< OHierarchyElement_Impl
> aParent
;
215 uno::Reference
< embed::XStorage
> xOwnStor
;
218 ::osl::MutexGuard
aGuard( m_aMutex
);
220 xOwnStor
= m_xOwnStorage
;
225 uno::Reference
< embed::XTransactedObject
> xTransact( xOwnStor
, uno::UNO_QUERY_THROW
);
232 void OHierarchyElement_Impl::TestForClosing()
234 ::rtl::Reference
< OHierarchyElement_Impl
> aLocker( this );
236 ::osl::MutexGuard
aGuard( m_aMutex
);
238 if ( m_aOpenStreams
.empty() && m_aChildren
.empty() )
240 if ( m_rParent
.is() )
242 // only the root storage should not be disposed, other storages can be disposed
243 if ( m_xOwnStorage
.is() )
247 m_xOwnStorage
->dispose();
249 catch( uno::Exception
& )
253 m_rParent
->RemoveElement( this );
256 m_xOwnStorage
= uno::Reference
< embed::XStorage
>();
261 void SAL_CALL
OHierarchyElement_Impl::disposing( const lang::EventObject
& Source
)
262 throw ( uno::RuntimeException
, std::exception
)
266 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
267 uno::Reference
< embed::XExtendedStorageStream
> xStream( Source
.Source
, uno::UNO_QUERY
);
269 for ( OWeakStorRefList_Impl::iterator pStorageIter
= m_aOpenStreams
.begin();
270 pStorageIter
!= m_aOpenStreams
.end(); )
272 OWeakStorRefList_Impl::iterator pTmp
= pStorageIter
++;
273 if ( !pTmp
->get().is() || pTmp
->get() == xStream
)
274 m_aOpenStreams
.erase( pTmp
);
281 catch( uno::Exception
& )
283 throw uno::RuntimeException(); // no exception must happen here, usually an exception means disaster
287 void OHierarchyElement_Impl::RemoveElement( const ::rtl::Reference
< OHierarchyElement_Impl
>& aRef
)
290 ::osl::MutexGuard
aGuard( m_aMutex
);
291 OHierarchyElementList_Impl::iterator aIter
= m_aChildren
.begin();
292 while (aIter
!= m_aChildren
.end())
294 if (aIter
->second
== aRef
)
295 aIter
= m_aChildren
.erase(aIter
);
304 // XTransactionListener
305 void SAL_CALL
OHierarchyElement_Impl::preCommit( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
306 throw (::com::sun::star::uno::Exception
, ::com::sun::star::uno::RuntimeException
, std::exception
)
310 void SAL_CALL
OHierarchyElement_Impl::commited( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
311 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
317 catch( const uno::Exception
& e
)
319 throw lang::WrappedTargetRuntimeException(
320 "Can not commit storage sequence!",
321 uno::Reference
< uno::XInterface
>(),
326 void SAL_CALL
OHierarchyElement_Impl::preRevert( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
327 throw (::com::sun::star::uno::Exception
, ::com::sun::star::uno::RuntimeException
, std::exception
)
331 void SAL_CALL
OHierarchyElement_Impl::reverted( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
332 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */