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 .
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
)
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
);
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
);
89 throw DisposedException();
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
;
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.
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
)
136 xSourceComponent
= m_xSource
;
138 if( m_pDisposeEventListeners
&& m_pDisposeEventListeners
->getLength() )
141 aEvt
.Source
= static_cast< XComponent
* >( this );
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
);
155 m_bInDispose
= false;
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
);
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
);
188 void DynamicResultSetWrapper::impl_disposing( const EventObject
& )
190 impl_EnsureNotDisposed();
192 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
194 if( !m_xSource
.is() )
197 //release all references to the broadcaster:
199 m_xSourceResultOne
.clear();//?? or only when not static??
200 m_xSourceResultTwo
.clear();//??
201 //@todo m_xMyResultOne.clear(); ???
202 //@todo m_xMyResultTwo.clear(); ???
206 void DynamicResultSetWrapper::impl_notify( const ListEvent
& Changes
)
208 impl_EnsureNotDisposed();
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
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
)
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
;
247 OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
248 //throw RuntimeException();
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;
264 m_xSourceResultCurrent = m_xSourceResultOne;
266 m_xSourceResultCurrent = m_xSourceResultTwo;
271 // XSourceInitialization
274 void SAL_CALL
DynamicResultSetWrapper::setSource( const Reference
< XInterface
> & Source
)
276 impl_EnsureNotDisposed();
278 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
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
;
298 xMyListenerImpl
= m_xMyListenerImpl
.get();
301 xSourceDynamic
->setListener( m_xMyListenerImpl
.get() );
304 Reference
< XComponent
> xSourceComponent( Source
, UNO_QUERY
);
305 xSourceComponent
->addEventListener( Reference
< XEventListener
> ::query( xMyListenerImpl
) );
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();
327 xMyListenerImpl
= m_xMyListenerImpl
.get();
332 xSource
->addEventListener( xMyListenerImpl
);
338 Reference
< XResultSet
> xResultSet
= xSource
->getStaticResultSet();
339 impl_InitResultSetOne( xResultSet
);
340 return m_xMyResultOne
;
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();
355 throw ListenerAlreadySetException();
357 m_xListener
= Listener
;
358 addEventListener( Reference
< XEventListener
>::query( Listener
) );
361 xMyListenerImpl
= m_xMyListenerImpl
.get();
364 xSource
->setListener( xMyListenerImpl
);
366 m_aListenerSet
.set();
370 void SAL_CALL
DynamicResultSetWrapper::connectToCache( const Reference
< XDynamicResultSet
> & xCache
)
372 impl_EnsureNotDisposed();
374 if( m_xListener
.is() )
375 throw ListenerAlreadySetException();
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 );
401 OSL_FAIL( "could not connect to cache" );
402 throw ServiceNotFoundException();
406 sal_Int16 SAL_CALL
DynamicResultSetWrapper::getCapabilities()
408 impl_EnsureNotDisposed();
411 Reference
< XDynamicResultSet
> xSource
;
413 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
416 return xSource
->getCapabilities();
420 // class DynamicResultSetWrapperListener
423 DynamicResultSetWrapperListener::DynamicResultSetWrapperListener(
424 DynamicResultSetWrapper
* pOwner
)
430 DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener()
436 // XInterface methods.
438 void SAL_CALL
DynamicResultSetWrapperListener::acquire()
441 OWeakObject::acquire();
444 void SAL_CALL
DynamicResultSetWrapperListener::release()
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:
462 void SAL_CALL
DynamicResultSetWrapperListener::disposing( const EventObject
& rEventObject
)
464 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
467 m_pOwner
->impl_disposing( rEventObject
);
471 void SAL_CALL
DynamicResultSetWrapperListener::notify( const ListEvent
& Changes
)
473 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
476 m_pOwner
->impl_notify( Changes
);
483 void DynamicResultSetWrapperListener::impl_OwnerDies()
485 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */