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
;
40 DynamicResultSetWrapper::DynamicResultSetWrapper(
41 Reference
< XDynamicResultSet
> const & xOrigin
42 , const Reference
< XComponentContext
> & rxContext
)
44 : m_bDisposed( false )
45 , m_bInDispose( false )
46 , m_xContext( rxContext
)
48 , m_bGotWelcome( false )
49 , m_xSource( xOrigin
)
50 // , m_xSourceResultCurrent( NULL )
51 // , m_bUseOne( NULL )
53 m_xMyListenerImpl
= new DynamicResultSetWrapperListener( this );
54 //call impl_init() at the end of constructor of derived class
57 void DynamicResultSetWrapper::impl_init()
59 //call this at the end of constructor of derived class
62 Reference
< XDynamicResultSet
> xSource
;
64 std::unique_lock
aGuard( m_aMutex
);
72 DynamicResultSetWrapper::~DynamicResultSetWrapper()
74 //call impl_deinit() at start of destructor of derived class
77 void DynamicResultSetWrapper::impl_deinit()
79 //call this at start of destructor of derived class
81 m_xMyListenerImpl
->impl_OwnerDies();
84 void DynamicResultSetWrapper::impl_EnsureNotDisposed(std::unique_lock
<std::mutex
>& /*rGuard*/)
87 throw DisposedException();
91 void DynamicResultSetWrapper::impl_InitResultSetOne( std::unique_lock
<std::mutex
>& /*rGuard*/, const Reference
< XResultSet
>& xResultSet
)
93 OSL_ENSURE( !m_xSourceResultOne
.is(), "Source ResultSet One is set already" );
94 m_xSourceResultOne
= xResultSet
;
95 m_xMyResultOne
= xResultSet
;
99 void DynamicResultSetWrapper::impl_InitResultSetTwo( std::unique_lock
<std::mutex
>& /*rGuard*/, const Reference
< XResultSet
>& xResultSet
)
101 OSL_ENSURE( !m_xSourceResultTwo
.is(), "Source ResultSet Two is set already" );
102 m_xSourceResultTwo
= xResultSet
;
103 m_xMyResultTwo
= xResultSet
;
106 // XInterface methods.
107 css::uno::Any SAL_CALL
DynamicResultSetWrapper::queryInterface( const css::uno::Type
& rType
)
109 //list all interfaces inclusive baseclasses of interfaces
110 css::uno::Any aRet
= cppu::queryInterface( rType
,
111 static_cast< XComponent
* >(this), //base of XDynamicResultSet
112 static_cast< XDynamicResultSet
* >(this),
113 static_cast< XSourceInitialization
* >(this)
115 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
118 // XComponent methods.
121 void SAL_CALL
DynamicResultSetWrapper::dispose()
123 std::unique_lock
aGuard( m_aMutex
);
124 impl_EnsureNotDisposed(aGuard
);
126 Reference
< XComponent
> xSourceComponent
;
127 if( m_bInDispose
|| m_bDisposed
)
131 xSourceComponent
= m_xSource
;
133 if( m_aDisposeEventListeners
.getLength(aGuard
) )
136 aEvt
.Source
= static_cast< XComponent
* >( this );
137 m_aDisposeEventListeners
.disposeAndClear( aGuard
, aEvt
);
140 /* //@todo ?? ( only if java collection needs to long )
141 if( xSourceComponent.is() )
142 xSourceComponent->dispose();
146 m_bInDispose
= false;
151 void SAL_CALL
DynamicResultSetWrapper::addEventListener( const Reference
< XEventListener
>& Listener
)
153 std::unique_lock
aGuard( m_aMutex
);
154 impl_EnsureNotDisposed(aGuard
);
156 m_aDisposeEventListeners
.addInterface( aGuard
, Listener
);
161 void SAL_CALL
DynamicResultSetWrapper::removeEventListener( const Reference
< XEventListener
>& Listener
)
163 std::unique_lock
aGuard( m_aMutex
);
164 impl_EnsureNotDisposed(aGuard
);
166 m_aDisposeEventListeners
.removeInterface( aGuard
, Listener
);
174 void DynamicResultSetWrapper::impl_disposing( const EventObject
& )
176 std::unique_lock
aGuard( m_aMutex
);
178 impl_EnsureNotDisposed(aGuard
);
180 if( !m_xSource
.is() )
183 //release all references to the broadcaster:
185 m_xSourceResultOne
.clear();//?? or only when not static??
186 m_xSourceResultTwo
.clear();//??
187 //@todo m_xMyResultOne.clear(); ???
188 //@todo m_xMyResultTwo.clear(); ???
192 void DynamicResultSetWrapper::impl_notify( const ListEvent
& Changes
)
194 std::unique_lock
aGuard( m_aMutex
);
195 impl_EnsureNotDisposed(aGuard
);
198 <p>The Listener is allowed to blockade this call, until he really want to go
199 to the new version. The only situation, where the listener has to return the
200 update call at once is, while he disposes his broadcaster or while he is
201 removing himself as listener (otherwise you deadlock)!!!
203 // handle the actions in the list
206 aNewEvent
.Source
= static_cast< XDynamicResultSet
* >( this );
207 aNewEvent
.Changes
= Changes
.Changes
;
209 for( ListAction
& rAction
: asNonConstRange(aNewEvent
.Changes
) )
214 switch( rAction
.ListActionType
)
216 case ListActionType::WELCOME
:
218 WelcomeDynamicResultSetStruct aWelcome
;
219 if( rAction
.ActionInfo
>>= aWelcome
)
221 impl_InitResultSetOne( aGuard
, aWelcome
.Old
);
222 impl_InitResultSetTwo( aGuard
, aWelcome
.New
);
223 m_bGotWelcome
= true;
225 aWelcome
.Old
= m_xMyResultOne
;
226 aWelcome
.New
= m_xMyResultTwo
;
228 rAction
.ActionInfo
<<= aWelcome
;
232 OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
233 //throw RuntimeException();
239 OSL_ENSURE( m_bGotWelcome
, "first notification was without WELCOME" );
243 if( !m_xListener
.is() )
244 m_aListenerSet
.wait();
245 m_xListener
->notify( aNewEvent
);
248 m_bUseOne = !m_bUseOne;
250 m_xSourceResultCurrent = m_xSourceResultOne;
252 m_xSourceResultCurrent = m_xSourceResultTwo;
257 // XSourceInitialization
260 void SAL_CALL
DynamicResultSetWrapper::setSource( const Reference
< XInterface
> & Source
)
262 std::unique_lock
aGuard( m_aMutex
);
263 impl_EnsureNotDisposed(aGuard
);
265 throw AlreadyInitializedException();
267 Reference
< XDynamicResultSet
> xSourceDynamic( Source
, UNO_QUERY
);
268 OSL_ENSURE( xSourceDynamic
.is(),
269 "the given source is not of required type XDynamicResultSet" );
271 Reference
< XDynamicResultSetListener
> xListener
;
272 Reference
< XDynamicResultSetListener
> xMyListenerImpl
;
274 bool bStatic
= false;
275 m_xSource
= xSourceDynamic
;
276 xListener
= m_xListener
;
278 xMyListenerImpl
= m_xMyListenerImpl
.get();
280 xSourceDynamic
->setListener( m_xMyListenerImpl
);
283 Reference
< XComponent
> xSourceComponent( Source
, UNO_QUERY
);
284 xSourceComponent
->addEventListener( xMyListenerImpl
);
293 Reference
< XResultSet
> SAL_CALL
DynamicResultSetWrapper::getStaticResultSet()
295 std::unique_lock
aGuard( m_aMutex
);
296 impl_EnsureNotDisposed(aGuard
);
298 if( m_xListener
.is() )
299 throw ListenerAlreadySetException();
301 Reference
< XDynamicResultSet
> xSource
= m_xSource
;
302 Reference
< XEventListener
> xMyListenerImpl
= m_xMyListenerImpl
;
309 xSource
->addEventListener( xMyListenerImpl
);
316 Reference
< XResultSet
> xResultSet
= xSource
->getStaticResultSet();
317 impl_InitResultSetOne( aGuard
, xResultSet
);
318 return m_xMyResultOne
;
322 void SAL_CALL
DynamicResultSetWrapper::setListener( const Reference
< XDynamicResultSetListener
> & Listener
)
324 std::unique_lock
aGuard( m_aMutex
);
325 impl_EnsureNotDisposed(aGuard
);
327 if( m_xListener
.is() )
328 throw ListenerAlreadySetException();
330 throw ListenerAlreadySetException();
332 m_xListener
= Listener
;
333 m_aDisposeEventListeners
.addInterface( aGuard
, Listener
);
335 Reference
< XDynamicResultSet
> xSource
= m_xSource
;
336 Reference
< XDynamicResultSetListener
> xMyListenerImpl
= m_xMyListenerImpl
;
341 xSource
->setListener( xMyListenerImpl
);
343 m_aListenerSet
.set();
347 void SAL_CALL
DynamicResultSetWrapper::connectToCache( const Reference
< XDynamicResultSet
> & xCache
)
349 std::unique_lock
aGuard( m_aMutex
);
350 impl_EnsureNotDisposed(aGuard
);
352 if( m_xListener
.is() )
353 throw ListenerAlreadySetException();
355 throw ListenerAlreadySetException();
358 Reference
< XSourceInitialization
> xTarget( xCache
, UNO_QUERY
);
359 OSL_ENSURE( xTarget
.is(), "The given Target doesn't have the required interface 'XSourceInitialization'" );
360 if( xTarget
.is() && m_xContext
.is() )
362 //@todo m_aSourceSet.wait();?
364 Reference
< XCachedDynamicResultSetStubFactory
> xStubFactory
;
367 xStubFactory
= CachedDynamicResultSetStubFactory::create( m_xContext
);
369 catch ( Exception
const & )
373 if( xStubFactory
.is() )
375 xStubFactory
->connectToCache(
376 this, xCache
, Sequence
< NumberedSortingInfo
> (), nullptr );
380 OSL_FAIL( "could not connect to cache" );
381 throw ServiceNotFoundException();
385 sal_Int16 SAL_CALL
DynamicResultSetWrapper::getCapabilities()
388 std::unique_lock
aGuard( m_aMutex
);
389 impl_EnsureNotDisposed(aGuard
);
392 Reference
< XDynamicResultSet
> xSource
;
394 std::unique_lock
aGuard( m_aMutex
);
397 return xSource
->getCapabilities();
403 DynamicResultSetWrapperListener::DynamicResultSetWrapperListener(
404 DynamicResultSetWrapper
* pOwner
)
410 DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener()
416 // XInterface methods.
418 void SAL_CALL
DynamicResultSetWrapperListener::acquire()
421 OWeakObject::acquire();
424 void SAL_CALL
DynamicResultSetWrapperListener::release()
427 OWeakObject::release();
430 css::uno::Any SAL_CALL
DynamicResultSetWrapperListener::queryInterface( const css::uno::Type
& rType
)
432 css::uno::Any aRet
= cppu::queryInterface( rType
,
433 static_cast< XDynamicResultSetListener
* >(this),
434 static_cast< XEventListener
* >(this)
436 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
439 // XDynamicResultSetListener methods:
442 void SAL_CALL
DynamicResultSetWrapperListener::disposing( const EventObject
& rEventObject
)
444 std::unique_lock
aGuard( m_aMutex
);
447 m_pOwner
->impl_disposing( rEventObject
);
451 void SAL_CALL
DynamicResultSetWrapperListener::notify( const ListEvent
& Changes
)
453 std::unique_lock
aGuard( m_aMutex
);
456 m_pOwner
->impl_notify( Changes
);
463 void DynamicResultSetWrapperListener::impl_OwnerDies()
465 std::unique_lock
aGuard( m_aMutex
);
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */