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 
39 
41  Reference< XDynamicResultSet > const & xOrigin
42  , const Reference< XComponentContext > & rxContext )
43 
44  : m_bDisposed( false )
45  , m_bInDispose( false )
46  , m_xContext( rxContext )
47  , m_bStatic( false )
48  , m_bGotWelcome( false )
49  , m_xSource( xOrigin )
50  // , m_xSourceResultCurrent( NULL )
51  // , m_bUseOne( NULL )
52 {
54  //call impl_init() at the end of constructor of derived class
55 };
56 
58 {
59  //call this at the end of constructor of derived class
60 
61 
63  {
64  osl::Guard< osl::Mutex > aGuard( m_aMutex );
65  xSource = m_xSource;
66  m_xSource = nullptr;
67  }
68  if( xSource.is() )
69  setSource( xSource );
70 }
71 
73 {
74  //call impl_deinit() at start of destructor of derived class
75 };
76 
78 {
79  //call this at start of destructor of derived class
80 
81  m_xMyListenerImpl->impl_OwnerDies();
82 }
83 
85 {
86  osl::Guard< osl::Mutex > aGuard( m_aMutex );
87  if( m_bDisposed )
88  throw DisposedException();
89 }
90 
91 //virtual
93 {
94  osl::Guard< osl::Mutex > aGuard( m_aMutex );
95  OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" );
96  m_xSourceResultOne = xResultSet;
97  m_xMyResultOne = xResultSet;
98 }
99 
100 //virtual
102 {
103  osl::Guard< osl::Mutex > aGuard( m_aMutex );
104  OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" );
105  m_xSourceResultTwo = xResultSet;
106  m_xMyResultTwo = xResultSet;
107 }
108 
109 // XInterface methods.
110 css::uno::Any SAL_CALL DynamicResultSetWrapper::queryInterface( const css::uno::Type & rType )
111 {
112  //list all interfaces inclusive baseclasses of interfaces
113  css::uno::Any aRet = cppu::queryInterface( rType,
114  static_cast< XComponent* >(this), //base of XDynamicResultSet
115  static_cast< XDynamicResultSet* >(this),
116  static_cast< XSourceInitialization* >(this)
117  );
118  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
119 }
120 
121 // XComponent methods.
122 
123 // virtual
125 {
127 
128  Reference< XComponent > xSourceComponent;
129  {
130  osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
131  if( m_bInDispose || m_bDisposed )
132  return;
133  m_bInDispose = true;
134 
135  xSourceComponent = m_xSource;
136 
138  {
139  EventObject aEvt;
140  aEvt.Source = static_cast< XComponent * >( this );
141 
142  aGuard.clear();
143  m_pDisposeEventListeners->disposeAndClear( aEvt );
144  }
145  }
146 
147  /* //@todo ?? ( only if java collection needs to long )
148  if( xSourceComponent.is() )
149  xSourceComponent->dispose();
150  */
151 
152  osl::Guard< osl::Mutex > aGuard( m_aMutex );
153  m_bDisposed = true;
154  m_bInDispose = false;
155 }
156 
157 
158 // virtual
160 {
162  osl::Guard< osl::Mutex > aGuard( m_aMutex );
163 
167 
168  m_pDisposeEventListeners->addInterface( Listener );
169 }
170 
171 
172 // virtual
174 {
176  osl::Guard< osl::Mutex > aGuard( m_aMutex );
177 
179  m_pDisposeEventListeners->removeInterface( Listener );
180 }
181 
182 
183 // own methods
184 
185 
186 //virtual
187 void DynamicResultSetWrapper::impl_disposing( const EventObject& )
188 {
190 
191  osl::Guard< osl::Mutex > aGuard( m_aMutex );
192 
193  if( !m_xSource.is() )
194  return;
195 
196  //release all references to the broadcaster:
197  m_xSource.clear();
198  m_xSourceResultOne.clear();//?? or only when not static??
199  m_xSourceResultTwo.clear();//??
200  //@todo m_xMyResultOne.clear(); ???
201  //@todo m_xMyResultTwo.clear(); ???
202 }
203 
204 //virtual
205 void DynamicResultSetWrapper::impl_notify( const ListEvent& Changes )
206 {
208  //@todo
209  /*
210  <p>The Listener is allowed to blockade this call, until he really want to go
211  to the new version. The only situation, where the listener has to return the
212  update call at once is, while he disposes his broadcaster or while he is
213  removing himself as listener (otherwise you deadlock)!!!
214  */
215  // handle the actions in the list
216 
217  ListEvent aNewEvent;
218  aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
219  aNewEvent.Changes = Changes.Changes;
220 
221  {
222  osl::Guard< osl::Mutex > aGuard( m_aMutex );
223  for( ListAction& rAction : aNewEvent.Changes )
224  {
225  if (m_bGotWelcome)
226  break;
227 
228  switch( rAction.ListActionType )
229  {
230  case ListActionType::WELCOME:
231  {
232  WelcomeDynamicResultSetStruct aWelcome;
233  if( rAction.ActionInfo >>= aWelcome )
234  {
235  impl_InitResultSetOne( aWelcome.Old );
236  impl_InitResultSetTwo( aWelcome.New );
237  m_bGotWelcome = true;
238 
239  aWelcome.Old = m_xMyResultOne;
240  aWelcome.New = m_xMyResultTwo;
241 
242  rAction.ActionInfo <<= aWelcome;
243  }
244  else
245  {
246  OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
247  //throw RuntimeException();
248  }
249  break;
250  }
251  }
252  }
253  OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" );
254  }
255 
256  if( !m_xListener.is() )
257  m_aListenerSet.wait();
258  m_xListener->notify( aNewEvent );
259 
260  /*
261  m_bUseOne = !m_bUseOne;
262  if( m_bUseOne )
263  m_xSourceResultCurrent = m_xSourceResultOne;
264  else
265  m_xSourceResultCurrent = m_xSourceResultTwo;
266  */
267 }
268 
269 
270 // XSourceInitialization
271 
272 //virtual
274 {
276  {
277  osl::Guard< osl::Mutex > aGuard( m_aMutex );
278  if( m_xSource.is() )
279  {
280  throw AlreadyInitializedException();
281  }
282  }
283 
284  Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY );
285  OSL_ENSURE( xSourceDynamic.is(),
286  "the given source is not of required type XDynamicResultSet" );
287 
290 
291  bool bStatic = false;
292  {
293  osl::Guard< osl::Mutex > aGuard( m_aMutex );
294  m_xSource = xSourceDynamic;
295  xListener = m_xListener;
296  bStatic = m_bStatic;
297  xMyListenerImpl = m_xMyListenerImpl.get();
298  }
299  if( xListener.is() )
300  xSourceDynamic->setListener( m_xMyListenerImpl.get() );
301  else if( bStatic )
302  {
303  Reference< XComponent > xSourceComponent( Source, UNO_QUERY );
304  xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) );
305  }
306  m_aSourceSet.set();
307 }
308 
309 
310 // XDynamicResultSet
311 
312 //virtual
314 {
316 
318  Reference< XEventListener > xMyListenerImpl;
319  {
320  osl::Guard< osl::Mutex > aGuard( m_aMutex );
321  if( m_xListener.is() )
322  throw ListenerAlreadySetException();
323 
324  xSource = m_xSource;
325  m_bStatic = true;
326  xMyListenerImpl = m_xMyListenerImpl.get();
327  }
328 
329  if( xSource.is() )
330  {
331  xSource->addEventListener( xMyListenerImpl );
332  }
333  if( !xSource.is() )
334  m_aSourceSet.wait();
335 
336 
337  Reference< XResultSet > xResultSet = xSource->getStaticResultSet();
338  impl_InitResultSetOne( xResultSet );
339  return m_xMyResultOne;
340 }
341 
342 //virtual
344 {
346 
349  {
350  osl::Guard< osl::Mutex > aGuard( m_aMutex );
351  if( m_xListener.is() )
352  throw ListenerAlreadySetException();
353  if( m_bStatic )
354  throw ListenerAlreadySetException();
355 
356  m_xListener = Listener;
358 
359  xSource = m_xSource;
360  xMyListenerImpl = m_xMyListenerImpl.get();
361  }
362  if ( xSource.is() )
363  xSource->setListener( xMyListenerImpl );
364 
365  m_aListenerSet.set();
366 }
367 
368 //virtual
370 {
372 
373  if( m_xListener.is() )
374  throw ListenerAlreadySetException();
375  if( m_bStatic )
376  throw ListenerAlreadySetException();
377 
378  Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
379  OSL_ENSURE( xTarget.is(), "The given Target doesn't have the required interface 'XSourceInitialization'" );
380  if( xTarget.is() && m_xContext.is() )
381  {
382  //@todo m_aSourceSet.wait();?
383 
385  try
386  {
387  xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
388  }
389  catch ( Exception const & )
390  {
391  }
392 
393  if( xStubFactory.is() )
394  {
395  xStubFactory->connectToCache(
396  this, xCache, Sequence< NumberedSortingInfo > (), nullptr );
397  return;
398  }
399  }
400  OSL_FAIL( "could not connect to cache" );
401  throw ServiceNotFoundException();
402 }
403 
404 //virtual
406 {
408 
409  m_aSourceSet.wait();
411  {
412  osl::Guard< osl::Mutex > aGuard( m_aMutex );
413  xSource = m_xSource;
414  }
415  return xSource->getCapabilities();
416 }
417 
418 
419 
420 
422  DynamicResultSetWrapper* pOwner )
423  : m_pOwner( pOwner )
424 {
425 
426 }
427 
429 {
430 
431 }
432 
433 
434 // XInterface methods.
435 
437  throw()
438 {
439  OWeakObject::acquire();
440 }
441 
443  throw()
444 {
445  OWeakObject::release();
446 }
447 
448 css::uno::Any SAL_CALL DynamicResultSetWrapperListener::queryInterface( const css::uno::Type & rType )
449 {
450  css::uno::Any aRet = cppu::queryInterface( rType,
451  static_cast< XDynamicResultSetListener* >(this),
452  static_cast< XEventListener* >(this)
453  );
454  return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
455 }
456 
457 // XDynamicResultSetListener methods:
458 
459 //virtual
460 void SAL_CALL DynamicResultSetWrapperListener::disposing( const EventObject& rEventObject )
461 {
462  osl::Guard< osl::Mutex > aGuard( m_aMutex );
463 
464  if( m_pOwner )
465  m_pOwner->impl_disposing( rEventObject );
466 }
467 
468 //virtual
469 void SAL_CALL DynamicResultSetWrapperListener::notify( const ListEvent& Changes )
470 {
471  osl::Guard< osl::Mutex > aGuard( m_aMutex );
472 
473  if( m_pOwner )
474  m_pOwner->impl_notify( Changes );
475 }
476 
477 
478 // own methods:
479 
480 
482 {
483  osl::Guard< osl::Mutex > aGuard( m_aMutex );
484 
485  m_pOwner = nullptr;
486 }
487 
488 /* 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
bool m_bDisposed
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
Reference< XInterface > xTarget
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
ContentProvider * m_pOwner
Definition: pkgprovider.cxx:58
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
Reference< XComponentContext > m_xContext
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)