LibreOffice Module ucb (master)  1
dynamicresultsetwrapper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
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>
30 
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;
36 
37 
38 // class DynamicResultSetWrapper
39 
40 
42  Reference< XDynamicResultSet > const & xOrigin
43  , const Reference< XComponentContext > & rxContext )
44 
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 )
53 {
55  //call impl_init() at the end of constructor of derived class
56 };
57 
59 {
60  //call this at the end of constructor of derived class
61 
62 
64  {
65  osl::Guard< osl::Mutex > aGuard( m_aMutex );
66  xSource = m_xSource;
67  m_xSource = nullptr;
68  }
69  if( xSource.is() )
70  setSource( xSource );
71 }
72 
74 {
75  //call impl_deinit() at start of destructor of derived class
76 };
77 
79 {
80  //call this at start of destructor of derived class
81 
82  m_xMyListenerImpl->impl_OwnerDies();
83 }
84 
86 {
87  osl::Guard< osl::Mutex > aGuard( m_aMutex );
88  if( m_bDisposed )
89  throw DisposedException();
90 }
91 
92 //virtual
94 {
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;
99 }
100 
101 //virtual
103 {
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;
108 }
109 
110 // XInterface methods.
111 css::uno::Any SAL_CALL DynamicResultSetWrapper::queryInterface( const css::uno::Type & rType )
112 {
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)
118  );
119  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
120 }
121 
122 // XComponent methods.
123 
124 // virtual
126 {
128 
129  Reference< XComponent > xSourceComponent;
130  {
131  osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
132  if( m_bInDispose || m_bDisposed )
133  return;
134  m_bInDispose = true;
135 
136  xSourceComponent = m_xSource;
137 
139  {
140  EventObject aEvt;
141  aEvt.Source = static_cast< XComponent * >( this );
142 
143  aGuard.clear();
144  m_pDisposeEventListeners->disposeAndClear( aEvt );
145  }
146  }
147 
148  /* //@todo ?? ( only if java collection needs to long )
149  if( xSourceComponent.is() )
150  xSourceComponent->dispose();
151  */
152 
153  osl::Guard< osl::Mutex > aGuard( m_aMutex );
154  m_bDisposed = true;
155  m_bInDispose = false;
156 }
157 
158 
159 // virtual
161 {
163  osl::Guard< osl::Mutex > aGuard( m_aMutex );
164 
168 
169  m_pDisposeEventListeners->addInterface( Listener );
170 }
171 
172 
173 // virtual
175 {
177  osl::Guard< osl::Mutex > aGuard( m_aMutex );
178 
180  m_pDisposeEventListeners->removeInterface( Listener );
181 }
182 
183 
184 // own methods
185 
186 
187 //virtual
188 void DynamicResultSetWrapper::impl_disposing( const EventObject& )
189 {
191 
192  osl::Guard< osl::Mutex > aGuard( m_aMutex );
193 
194  if( !m_xSource.is() )
195  return;
196 
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(); ???
203 }
204 
205 //virtual
206 void DynamicResultSetWrapper::impl_notify( const ListEvent& Changes )
207 {
209  //@todo
210  /*
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)!!!
215  */
216  // handle the actions in the list
217 
218  ListEvent aNewEvent;
219  aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
220  aNewEvent.Changes = Changes.Changes;
221 
222  {
223  osl::Guard< osl::Mutex > aGuard( m_aMutex );
224  for( ListAction& rAction : aNewEvent.Changes )
225  {
226  if (m_bGotWelcome)
227  break;
228 
229  switch( rAction.ListActionType )
230  {
231  case ListActionType::WELCOME:
232  {
233  WelcomeDynamicResultSetStruct aWelcome;
234  if( rAction.ActionInfo >>= aWelcome )
235  {
236  impl_InitResultSetOne( aWelcome.Old );
237  impl_InitResultSetTwo( aWelcome.New );
238  m_bGotWelcome = true;
239 
240  aWelcome.Old = m_xMyResultOne;
241  aWelcome.New = m_xMyResultTwo;
242 
243  rAction.ActionInfo <<= aWelcome;
244  }
245  else
246  {
247  OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
248  //throw RuntimeException();
249  }
250  break;
251  }
252  }
253  }
254  OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" );
255  }
256 
257  if( !m_xListener.is() )
258  m_aListenerSet.wait();
259  m_xListener->notify( aNewEvent );
260 
261  /*
262  m_bUseOne = !m_bUseOne;
263  if( m_bUseOne )
264  m_xSourceResultCurrent = m_xSourceResultOne;
265  else
266  m_xSourceResultCurrent = m_xSourceResultTwo;
267  */
268 }
269 
270 
271 // XSourceInitialization
272 
273 //virtual
275 {
277  {
278  osl::Guard< osl::Mutex > aGuard( m_aMutex );
279  if( m_xSource.is() )
280  {
281  throw AlreadyInitializedException();
282  }
283  }
284 
285  Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY );
286  OSL_ENSURE( xSourceDynamic.is(),
287  "the given source is not of required type XDynamicResultSet" );
288 
291 
292  bool bStatic = false;
293  {
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();
299  }
300  if( xListener.is() )
301  xSourceDynamic->setListener( m_xMyListenerImpl.get() );
302  else if( bStatic )
303  {
304  Reference< XComponent > xSourceComponent( Source, UNO_QUERY );
305  xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) );
306  }
307  m_aSourceSet.set();
308 }
309 
310 
311 // XDynamicResultSet
312 
313 //virtual
315 {
317 
319  Reference< XEventListener > xMyListenerImpl;
320  {
321  osl::Guard< osl::Mutex > aGuard( m_aMutex );
322  if( m_xListener.is() )
323  throw ListenerAlreadySetException();
324 
325  xSource = m_xSource;
326  m_bStatic = true;
327  xMyListenerImpl = m_xMyListenerImpl.get();
328  }
329 
330  if( xSource.is() )
331  {
332  xSource->addEventListener( xMyListenerImpl );
333  }
334  if( !xSource.is() )
335  m_aSourceSet.wait();
336 
337 
338  Reference< XResultSet > xResultSet = xSource->getStaticResultSet();
339  impl_InitResultSetOne( xResultSet );
340  return m_xMyResultOne;
341 }
342 
343 //virtual
345 {
347 
350  {
351  osl::Guard< osl::Mutex > aGuard( m_aMutex );
352  if( m_xListener.is() )
353  throw ListenerAlreadySetException();
354  if( m_bStatic )
355  throw ListenerAlreadySetException();
356 
357  m_xListener = Listener;
359 
360  xSource = m_xSource;
361  xMyListenerImpl = m_xMyListenerImpl.get();
362  }
363  if ( xSource.is() )
364  xSource->setListener( xMyListenerImpl );
365 
366  m_aListenerSet.set();
367 }
368 
369 //virtual
371 {
373 
374  if( m_xListener.is() )
375  throw ListenerAlreadySetException();
376  if( m_bStatic )
377  throw ListenerAlreadySetException();
378 
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() )
382  {
383  //@todo m_aSourceSet.wait();?
384 
386  try
387  {
388  xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
389  }
390  catch ( Exception const & )
391  {
392  }
393 
394  if( xStubFactory.is() )
395  {
396  xStubFactory->connectToCache(
397  this, xCache, Sequence< NumberedSortingInfo > (), nullptr );
398  return;
399  }
400  }
401  OSL_FAIL( "could not connect to cache" );
402  throw ServiceNotFoundException();
403 }
404 
405 //virtual
407 {
409 
410  m_aSourceSet.wait();
412  {
413  osl::Guard< osl::Mutex > aGuard( m_aMutex );
414  xSource = m_xSource;
415  }
416  return xSource->getCapabilities();
417 }
418 
419 
420 // class DynamicResultSetWrapperListener
421 
422 
424  DynamicResultSetWrapper* pOwner )
425  : m_pOwner( pOwner )
426 {
427 
428 }
429 
431 {
432 
433 }
434 
435 
436 // XInterface methods.
437 
439  throw()
440 {
441  OWeakObject::acquire();
442 }
443 
445  throw()
446 {
447  OWeakObject::release();
448 }
449 
450 css::uno::Any SAL_CALL DynamicResultSetWrapperListener::queryInterface( const css::uno::Type & rType )
451 {
452  css::uno::Any aRet = cppu::queryInterface( rType,
453  static_cast< XDynamicResultSetListener* >(this),
454  static_cast< XEventListener* >(this)
455  );
456  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
457 }
458 
459 // XDynamicResultSetListener methods:
460 
461 //virtual
462 void SAL_CALL DynamicResultSetWrapperListener::disposing( const EventObject& rEventObject )
463 {
464  osl::Guard< osl::Mutex > aGuard( m_aMutex );
465 
466  if( m_pOwner )
467  m_pOwner->impl_disposing( rEventObject );
468 }
469 
470 //virtual
471 void SAL_CALL DynamicResultSetWrapperListener::notify( const ListEvent& Changes )
472 {
473  osl::Guard< osl::Mutex > aGuard( m_aMutex );
474 
475  if( m_pOwner )
476  m_pOwner->impl_notify( Changes );
477 }
478 
479 
480 // own methods:
481 
482 
484 {
485  osl::Guard< osl::Mutex > aGuard( m_aMutex );
486 
487  m_pOwner = nullptr;
488 }
489 
490 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SAL_CALL setListener(const css::uno::Reference< css::ucb::XDynamicResultSetListener > &Listener) override
virtual void impl_InitResultSetTwo(const css::uno::Reference< css::sdbc::XResultSet > &xResultSet)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL connectToCache(const css::uno::Reference< css::ucb::XDynamicResultSet > &xCache) override
css::uno::Reference< css::sdbc::XResultSet > m_xMyResultTwo
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &Listener) override
css::uno::Reference< css::ucb::XDynamicResultSetListener > m_xListener
virtual void impl_disposing(const css::lang::EventObject &Source)
virtual sal_Int16 SAL_CALL getCapabilities() override
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &Listener) override
virtual void SAL_CALL acquire() override
virtual void impl_InitResultSetOne(const css::uno::Reference< css::sdbc::XResultSet > &xResultSet)
virtual void SAL_CALL dispose() override
osl::Mutex m_aContainerMutex
In dispose call.
rtl::Reference< DynamicResultSetWrapperListener > m_xMyListenerImpl
DynamicResultSetWrapper(css::uno::Reference< css::ucb::XDynamicResultSet > const &xOrigin, const css::uno::Reference< css::uno::XComponentContext > &rxContext)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual ~DynamicResultSetWrapper() override
bool m_bInDispose
Dispose call ready.
std::unique_ptr< comphelper::OInterfaceContainerHelper2 > m_pDisposeEventListeners
css::uno::Reference< css::sdbc::XResultSet > m_xMyResultOne
css::uno::Reference< css::ucb::XDynamicResultSet > m_xSource
css::uno::Reference< css::sdbc::XResultSet > m_xSourceResultTwo
css::uno::Reference< css::uno::XComponentContext > m_xContext
void impl_notify(const css::ucb::ListEvent &Changes)
DynamicResultSetWrapperListener(DynamicResultSetWrapper *pOwner)
const Reference< XRow > m_xSource
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL notify(const css::ucb::ListEvent &Changes) override
css::uno::Reference< css::sdbc::XResultSet > m_xSourceResultOne
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL getStaticResultSet() override
virtual void SAL_CALL setSource(const css::uno::Reference< css::uno::XInterface > &Source) override
virtual void SAL_CALL release() override
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
const uno::Reference< uno::XComponentContext > m_xContext