Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / cacher / dynamicresultsetwrapper.cxx
blobad1f580bf1faa746b0d1226650077fe666ba3932
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 <cppuhelper/queryinterface.hxx>
23 #include <osl/diagnose.h>
24 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/ListenerAlreadySetException.hpp>
27 #include <com/sun/star/ucb/ServiceNotFoundException.hpp>
28 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
29 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
31 using namespace com::sun::star::lang;
32 using namespace com::sun::star::sdbc;
33 using namespace com::sun::star::ucb;
34 using namespace com::sun::star::uno;
35 using namespace comphelper;
38 // class DynamicResultSetWrapper
41 DynamicResultSetWrapper::DynamicResultSetWrapper(
42 Reference< XDynamicResultSet > const & xOrigin
43 , const Reference< XComponentContext > & rxContext )
45 : m_bDisposed( false )
46 , m_bInDispose( false )
47 , m_xContext( rxContext )
48 , m_bStatic( false )
49 , m_bGotWelcome( false )
50 , m_xSource( xOrigin )
51 // , m_xSourceResultCurrent( NULL )
52 // , m_bUseOne( NULL )
54 m_xMyListenerImpl = new DynamicResultSetWrapperListener( this );
55 //call impl_init() at the end of constructor of derived class
58 void DynamicResultSetWrapper::impl_init()
60 //call this at the end of constructor of derived class
63 Reference< XDynamicResultSet > xSource;
65 osl::Guard< osl::Mutex > aGuard( m_aMutex );
66 xSource = m_xSource;
67 m_xSource = nullptr;
69 if( xSource.is() )
70 setSource( xSource );
73 DynamicResultSetWrapper::~DynamicResultSetWrapper()
75 //call impl_deinit() at start of destructor of derived class
78 void DynamicResultSetWrapper::impl_deinit()
80 //call this at start of destructor of derived class
82 m_xMyListenerImpl->impl_OwnerDies();
85 void DynamicResultSetWrapper::impl_EnsureNotDisposed()
87 osl::Guard< osl::Mutex > aGuard( m_aMutex );
88 if( m_bDisposed )
89 throw DisposedException();
92 //virtual
93 void DynamicResultSetWrapper::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet )
95 osl::Guard< osl::Mutex > aGuard( m_aMutex );
96 OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" );
97 m_xSourceResultOne = xResultSet;
98 m_xMyResultOne = xResultSet;
101 //virtual
102 void DynamicResultSetWrapper::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet )
104 osl::Guard< osl::Mutex > aGuard( m_aMutex );
105 OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" );
106 m_xSourceResultTwo = xResultSet;
107 m_xMyResultTwo = xResultSet;
110 // XInterface methods.
111 css::uno::Any SAL_CALL DynamicResultSetWrapper::queryInterface( const css::uno::Type & rType )
113 //list all interfaces inclusive baseclasses of interfaces
114 css::uno::Any aRet = cppu::queryInterface( rType,
115 static_cast< XComponent* >(this), //base of XDynamicResultSet
116 static_cast< XDynamicResultSet* >(this),
117 static_cast< XSourceInitialization* >(this)
119 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
122 // XComponent methods.
124 // virtual
125 void SAL_CALL DynamicResultSetWrapper::dispose()
127 impl_EnsureNotDisposed();
129 Reference< XComponent > xSourceComponent;
131 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
132 if( m_bInDispose || m_bDisposed )
133 return;
134 m_bInDispose = true;
136 xSourceComponent = m_xSource;
138 if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
140 EventObject aEvt;
141 aEvt.Source = static_cast< XComponent * >( this );
143 aGuard.clear();
144 m_pDisposeEventListeners->disposeAndClear( aEvt );
148 /* //@todo ?? ( only if java collection needs to long )
149 if( xSourceComponent.is() )
150 xSourceComponent->dispose();
153 osl::Guard< osl::Mutex > aGuard( m_aMutex );
154 m_bDisposed = true;
155 m_bInDispose = false;
159 // virtual
160 void SAL_CALL DynamicResultSetWrapper::addEventListener( const Reference< XEventListener >& Listener )
162 impl_EnsureNotDisposed();
163 osl::Guard< osl::Mutex > aGuard( m_aMutex );
165 if ( !m_pDisposeEventListeners )
166 m_pDisposeEventListeners.reset(
167 new OInterfaceContainerHelper2( m_aContainerMutex ) );
169 m_pDisposeEventListeners->addInterface( Listener );
173 // virtual
174 void SAL_CALL DynamicResultSetWrapper::removeEventListener( const Reference< XEventListener >& Listener )
176 impl_EnsureNotDisposed();
177 osl::Guard< osl::Mutex > aGuard( m_aMutex );
179 if ( m_pDisposeEventListeners )
180 m_pDisposeEventListeners->removeInterface( Listener );
184 // own methods
187 //virtual
188 void DynamicResultSetWrapper::impl_disposing( const EventObject& )
190 impl_EnsureNotDisposed();
192 osl::Guard< osl::Mutex > aGuard( m_aMutex );
194 if( !m_xSource.is() )
195 return;
197 //release all references to the broadcaster:
198 m_xSource.clear();
199 m_xSourceResultOne.clear();//?? or only when not static??
200 m_xSourceResultTwo.clear();//??
201 //@todo m_xMyResultOne.clear(); ???
202 //@todo m_xMyResultTwo.clear(); ???
205 //virtual
206 void DynamicResultSetWrapper::impl_notify( const ListEvent& Changes )
208 impl_EnsureNotDisposed();
209 //@todo
211 <p>The Listener is allowed to blockade this call, until he really want to go
212 to the new version. The only situation, where the listener has to return the
213 update call at once is, while he disposes his broadcaster or while he is
214 removing himself as listener (otherwise you deadlock)!!!
216 // handle the actions in the list
218 ListEvent aNewEvent;
219 aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
220 aNewEvent.Changes = Changes.Changes;
223 osl::Guard< osl::Mutex > aGuard( m_aMutex );
224 for( ListAction& rAction : aNewEvent.Changes )
226 if (m_bGotWelcome)
227 break;
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 = m_xMyListenerImpl.get();
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: */