lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / ucb / source / cacher / dynamicresultsetwrapper.cxx
blobc7aa27949429ad8e5b798f4ed15854cde2daaca6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include "dynamicresultsetwrapper.hxx"
22 #include <ucbhelper/macros.hxx>
23 #include <cppuhelper/queryinterface.hxx>
24 #include <osl/diagnose.h>
25 #include <rtl/ustring.hxx>
26 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
27 #include <com/sun/star/ucb/ListActionType.hpp>
28 #include <com/sun/star/ucb/ListenerAlreadySetException.hpp>
29 #include <com/sun/star/ucb/ServiceNotFoundException.hpp>
30 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
31 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::sdbc;
35 using namespace com::sun::star::ucb;
36 using namespace com::sun::star::uno;
37 using namespace comphelper;
40 // class DynamicResultSetWrapper
43 DynamicResultSetWrapper::DynamicResultSetWrapper(
44 Reference< XDynamicResultSet > const & xOrigin
45 , const Reference< XComponentContext > & rxContext )
47 : m_bDisposed( false )
48 , m_bInDispose( false )
49 , m_xContext( rxContext )
50 , m_bStatic( false )
51 , m_bGotWelcome( false )
52 , m_xSource( xOrigin )
53 // , m_xSourceResultCurrent( NULL )
54 // , m_bUseOne( NULL )
56 m_xMyListenerImpl = new DynamicResultSetWrapperListener( this );
57 //call impl_init() at the end of constructor of derived class
60 void DynamicResultSetWrapper::impl_init()
62 //call this at the end of constructor of derived class
65 Reference< XDynamicResultSet > xSource;
67 osl::Guard< osl::Mutex > aGuard( m_aMutex );
68 xSource = m_xSource;
69 m_xSource = nullptr;
71 if( xSource.is() )
72 setSource( xSource );
75 DynamicResultSetWrapper::~DynamicResultSetWrapper()
77 //call impl_deinit() at start of destructor of derived class
80 void DynamicResultSetWrapper::impl_deinit()
82 //call this at start of destructor of derived class
84 m_xMyListenerImpl->impl_OwnerDies();
87 void DynamicResultSetWrapper::impl_EnsureNotDisposed()
89 osl::Guard< osl::Mutex > aGuard( m_aMutex );
90 if( m_bDisposed )
91 throw DisposedException();
94 //virtual
95 void DynamicResultSetWrapper::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet )
97 osl::Guard< osl::Mutex > aGuard( m_aMutex );
98 OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" );
99 m_xSourceResultOne = xResultSet;
100 m_xMyResultOne = xResultSet;
103 //virtual
104 void DynamicResultSetWrapper::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet )
106 osl::Guard< osl::Mutex > aGuard( m_aMutex );
107 OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" );
108 m_xSourceResultTwo = xResultSet;
109 m_xMyResultTwo = xResultSet;
112 // XInterface methods.
113 css::uno::Any SAL_CALL DynamicResultSetWrapper::queryInterface( const css::uno::Type & rType )
115 //list all interfaces inclusive baseclasses of interfaces
116 css::uno::Any aRet = cppu::queryInterface( rType,
117 static_cast< XComponent* >(this), //base of XDynamicResultSet
118 static_cast< XDynamicResultSet* >(this),
119 static_cast< XSourceInitialization* >(this)
121 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
124 // XComponent methods.
126 // virtual
127 void SAL_CALL DynamicResultSetWrapper::dispose()
129 impl_EnsureNotDisposed();
131 Reference< XComponent > xSourceComponent;
133 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
134 if( m_bInDispose || m_bDisposed )
135 return;
136 m_bInDispose = true;
138 xSourceComponent.set(m_xSource, UNO_QUERY);
140 if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
142 EventObject aEvt;
143 aEvt.Source = static_cast< XComponent * >( this );
145 aGuard.clear();
146 m_pDisposeEventListeners->disposeAndClear( aEvt );
150 /* //@todo ?? ( only if java collection needs to long )
151 if( xSourceComponent.is() )
152 xSourceComponent->dispose();
155 osl::Guard< osl::Mutex > aGuard( m_aMutex );
156 m_bDisposed = true;
157 m_bInDispose = false;
161 // virtual
162 void SAL_CALL DynamicResultSetWrapper::addEventListener( const Reference< XEventListener >& Listener )
164 impl_EnsureNotDisposed();
165 osl::Guard< osl::Mutex > aGuard( m_aMutex );
167 if ( !m_pDisposeEventListeners )
168 m_pDisposeEventListeners.reset(
169 new OInterfaceContainerHelper2( m_aContainerMutex ) );
171 m_pDisposeEventListeners->addInterface( Listener );
175 // virtual
176 void SAL_CALL DynamicResultSetWrapper::removeEventListener( const Reference< XEventListener >& Listener )
178 impl_EnsureNotDisposed();
179 osl::Guard< osl::Mutex > aGuard( m_aMutex );
181 if ( m_pDisposeEventListeners )
182 m_pDisposeEventListeners->removeInterface( Listener );
186 // own methods
189 //virtual
190 void DynamicResultSetWrapper::impl_disposing( const EventObject& )
192 impl_EnsureNotDisposed();
194 osl::Guard< osl::Mutex > aGuard( m_aMutex );
196 if( !m_xSource.is() )
197 return;
199 //release all references to the broadcaster:
200 m_xSource.clear();
201 m_xSourceResultOne.clear();//?? or only when not static??
202 m_xSourceResultTwo.clear();//??
203 //@todo m_xMyResultOne.clear(); ???
204 //@todo m_xMyResultTwo.clear(); ???
207 //virtual
208 void DynamicResultSetWrapper::impl_notify( const ListEvent& Changes )
210 impl_EnsureNotDisposed();
211 //@todo
213 <p>The Listener is allowed to blockade this call, until he really want to go
214 to the new version. The only situation, where the listener has to return the
215 update call at once is, while he disposes his broadcaster or while he is
216 removing himself as listener (otherwise you deadlock)!!!
218 // handle the actions in the list
220 ListEvent aNewEvent;
221 aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
222 aNewEvent.Changes = Changes.Changes;
225 osl::Guard< osl::Mutex > aGuard( m_aMutex );
226 for( long i=0; !m_bGotWelcome && i<Changes.Changes.getLength(); i++ )
228 ListAction& rAction = aNewEvent.Changes[i];
229 switch( rAction.ListActionType )
231 case ListActionType::WELCOME:
233 WelcomeDynamicResultSetStruct aWelcome;
234 if( rAction.ActionInfo >>= aWelcome )
236 impl_InitResultSetOne( aWelcome.Old );
237 impl_InitResultSetTwo( aWelcome.New );
238 m_bGotWelcome = true;
240 aWelcome.Old = m_xMyResultOne;
241 aWelcome.New = m_xMyResultTwo;
243 rAction.ActionInfo <<= aWelcome;
245 else
247 OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
248 //throw RuntimeException();
250 break;
254 OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" );
257 if( !m_xListener.is() )
258 m_aListenerSet.wait();
259 m_xListener->notify( aNewEvent );
262 m_bUseOne = !m_bUseOne;
263 if( m_bUseOne )
264 m_xSourceResultCurrent = m_xSourceResultOne;
265 else
266 m_xSourceResultCurrent = m_xSourceResultTwo;
271 // XSourceInitialization
273 //virtual
274 void SAL_CALL DynamicResultSetWrapper::setSource( const Reference< XInterface > & Source )
276 impl_EnsureNotDisposed();
278 osl::Guard< osl::Mutex > aGuard( m_aMutex );
279 if( m_xSource.is() )
281 throw AlreadyInitializedException();
285 Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY );
286 OSL_ENSURE( xSourceDynamic.is(),
287 "the given source is not of required type XDynamicResultSet" );
289 Reference< XDynamicResultSetListener > xListener;
290 Reference< XDynamicResultSetListener > xMyListenerImpl;
292 bool bStatic = false;
294 osl::Guard< osl::Mutex > aGuard( m_aMutex );
295 m_xSource = xSourceDynamic;
296 xListener = m_xListener;
297 bStatic = m_bStatic;
298 xMyListenerImpl = m_xMyListenerImpl.get();
300 if( xListener.is() )
301 xSourceDynamic->setListener( m_xMyListenerImpl.get() );
302 else if( bStatic )
304 Reference< XComponent > xSourceComponent( Source, UNO_QUERY );
305 xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) );
307 m_aSourceSet.set();
311 // XDynamicResultSet
313 //virtual
314 Reference< XResultSet > SAL_CALL DynamicResultSetWrapper::getStaticResultSet()
316 impl_EnsureNotDisposed();
318 Reference< XDynamicResultSet > xSource;
319 Reference< XEventListener > xMyListenerImpl;
321 osl::Guard< osl::Mutex > aGuard( m_aMutex );
322 if( m_xListener.is() )
323 throw ListenerAlreadySetException();
325 xSource = m_xSource;
326 m_bStatic = true;
327 xMyListenerImpl.set( css::uno::Reference< css::ucb::XDynamicResultSetListener >(m_xMyListenerImpl.get()), UNO_QUERY );
330 if( xSource.is() )
332 xSource->addEventListener( xMyListenerImpl );
334 if( !xSource.is() )
335 m_aSourceSet.wait();
338 Reference< XResultSet > xResultSet = xSource->getStaticResultSet();
339 impl_InitResultSetOne( xResultSet );
340 return m_xMyResultOne;
343 //virtual
344 void SAL_CALL DynamicResultSetWrapper::setListener( const Reference< XDynamicResultSetListener > & Listener )
346 impl_EnsureNotDisposed();
348 Reference< XDynamicResultSet > xSource;
349 Reference< XDynamicResultSetListener > xMyListenerImpl;
351 osl::Guard< osl::Mutex > aGuard( m_aMutex );
352 if( m_xListener.is() )
353 throw ListenerAlreadySetException();
354 if( m_bStatic )
355 throw ListenerAlreadySetException();
357 m_xListener = Listener;
358 addEventListener( Reference< XEventListener >::query( Listener ) );
360 xSource = m_xSource;
361 xMyListenerImpl = m_xMyListenerImpl.get();
363 if ( xSource.is() )
364 xSource->setListener( xMyListenerImpl );
366 m_aListenerSet.set();
369 //virtual
370 void SAL_CALL DynamicResultSetWrapper::connectToCache( const Reference< XDynamicResultSet > & xCache )
372 impl_EnsureNotDisposed();
374 if( m_xListener.is() )
375 throw ListenerAlreadySetException();
376 if( m_bStatic )
377 throw ListenerAlreadySetException();
379 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
380 OSL_ENSURE( xTarget.is(), "The given Target doesn't have the required interface 'XSourceInitialization'" );
381 if( xTarget.is() && m_xContext.is() )
383 //@todo m_aSourceSet.wait();?
385 Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
388 xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
390 catch ( Exception const & )
394 if( xStubFactory.is() )
396 xStubFactory->connectToCache(
397 this, xCache, Sequence< NumberedSortingInfo > (), nullptr );
398 return;
401 OSL_FAIL( "could not connect to cache" );
402 throw ServiceNotFoundException();
405 //virtual
406 sal_Int16 SAL_CALL DynamicResultSetWrapper::getCapabilities()
408 impl_EnsureNotDisposed();
410 m_aSourceSet.wait();
411 Reference< XDynamicResultSet > xSource;
413 osl::Guard< osl::Mutex > aGuard( m_aMutex );
414 xSource = m_xSource;
416 return xSource->getCapabilities();
420 // class DynamicResultSetWrapperListener
423 DynamicResultSetWrapperListener::DynamicResultSetWrapperListener(
424 DynamicResultSetWrapper* pOwner )
425 : m_pOwner( pOwner )
430 DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener()
436 // XInterface methods.
438 void SAL_CALL DynamicResultSetWrapperListener::acquire()
439 throw()
441 OWeakObject::acquire();
444 void SAL_CALL DynamicResultSetWrapperListener::release()
445 throw()
447 OWeakObject::release();
450 css::uno::Any SAL_CALL DynamicResultSetWrapperListener::queryInterface( const css::uno::Type & rType )
452 css::uno::Any aRet = cppu::queryInterface( rType,
453 static_cast< XDynamicResultSetListener* >(this),
454 static_cast< XEventListener* >(this)
456 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
459 // XDynamicResultSetListener methods:
461 //virtual
462 void SAL_CALL DynamicResultSetWrapperListener::disposing( const EventObject& rEventObject )
464 osl::Guard< osl::Mutex > aGuard( m_aMutex );
466 if( m_pOwner )
467 m_pOwner->impl_disposing( rEventObject );
470 //virtual
471 void SAL_CALL DynamicResultSetWrapperListener::notify( const ListEvent& Changes )
473 osl::Guard< osl::Mutex > aGuard( m_aMutex );
475 if( m_pOwner )
476 m_pOwner->impl_notify( Changes );
480 // own methods:
483 void DynamicResultSetWrapperListener::impl_OwnerDies()
485 osl::Guard< osl::Mutex > aGuard( m_aMutex );
487 m_pOwner = nullptr;
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */