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 <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
)
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
);
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
);
91 throw DisposedException();
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
;
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.
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
)
138 xSourceComponent
.set(m_xSource
, UNO_QUERY
);
140 if( m_pDisposeEventListeners
&& m_pDisposeEventListeners
->getLength() )
143 aEvt
.Source
= static_cast< XComponent
* >( this );
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
);
157 m_bInDispose
= false;
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
);
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
);
190 void DynamicResultSetWrapper::impl_disposing( const EventObject
& )
192 impl_EnsureNotDisposed();
194 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
196 if( !m_xSource
.is() )
199 //release all references to the broadcaster:
201 m_xSourceResultOne
.clear();//?? or only when not static??
202 m_xSourceResultTwo
.clear();//??
203 //@todo m_xMyResultOne.clear(); ???
204 //@todo m_xMyResultTwo.clear(); ???
208 void DynamicResultSetWrapper::impl_notify( const ListEvent
& Changes
)
210 impl_EnsureNotDisposed();
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
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
;
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
.set( css::uno::Reference
< css::ucb::XDynamicResultSetListener
>(m_xMyListenerImpl
.get()), UNO_QUERY
);
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: */