Line data Source code
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 :
21 : #include <dynamicresultsetwrapper.hxx>
22 : #include <ucbhelper/macros.hxx>
23 : #include <osl/diagnose.h>
24 : #include <rtl/ustring.hxx>
25 : #include <com/sun/star/ucb/ListActionType.hpp>
26 : #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
27 : #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
28 :
29 : using namespace com::sun::star::lang;
30 : using namespace com::sun::star::sdbc;
31 : using namespace com::sun::star::ucb;
32 : using namespace com::sun::star::uno;
33 : using namespace cppu;
34 :
35 :
36 : //--------------------------------------------------------------------------
37 : //--------------------------------------------------------------------------
38 : // class DynamicResultSetWrapper
39 : //--------------------------------------------------------------------------
40 : //--------------------------------------------------------------------------
41 :
42 0 : DynamicResultSetWrapper::DynamicResultSetWrapper(
43 : Reference< XDynamicResultSet > xOrigin
44 : , const Reference< XComponentContext > & rxContext )
45 :
46 : : m_bDisposed( sal_False )
47 : , m_bInDispose( sal_False )
48 : , m_pDisposeEventListeners( NULL )
49 : , m_xContext( rxContext )
50 : , m_bStatic( sal_False )
51 : , m_bGotWelcome( sal_False )
52 : , m_xSource( xOrigin )
53 : , m_xSourceResultOne( NULL )
54 : , m_xSourceResultTwo( NULL )
55 : // , m_xSourceResultCurrent( NULL )
56 : // , m_bUseOne( NULL )
57 : , m_xMyResultOne( NULL )
58 : , m_xMyResultTwo( NULL )
59 0 : , m_xListener( NULL )
60 : {
61 0 : m_pMyListenerImpl = new DynamicResultSetWrapperListener( this );
62 0 : m_xMyListenerImpl = Reference< XDynamicResultSetListener >( m_pMyListenerImpl );
63 : //call impl_init() at the end of constructor of derived class
64 0 : };
65 :
66 0 : void SAL_CALL DynamicResultSetWrapper::impl_init()
67 : {
68 : //call this at the end of constructor of derived class
69 : //
70 :
71 0 : Reference< XDynamicResultSet > xSource = NULL;
72 : {
73 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
74 0 : xSource = m_xSource;
75 0 : m_xSource = NULL;
76 : }
77 0 : if( xSource.is() )
78 0 : setSource( xSource );
79 0 : }
80 :
81 0 : DynamicResultSetWrapper::~DynamicResultSetWrapper()
82 : {
83 : //call impl_deinit() at start of destructor of derived class
84 :
85 0 : delete m_pDisposeEventListeners;
86 0 : };
87 :
88 0 : void SAL_CALL DynamicResultSetWrapper::impl_deinit()
89 : {
90 : //call this at start of destructor of derived class
91 : //
92 0 : m_pMyListenerImpl->impl_OwnerDies();
93 0 : }
94 :
95 0 : void SAL_CALL DynamicResultSetWrapper
96 : ::impl_EnsureNotDisposed()
97 : throw( DisposedException, RuntimeException )
98 : {
99 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
100 0 : if( m_bDisposed )
101 0 : throw DisposedException();
102 0 : }
103 :
104 : //virtual
105 0 : void SAL_CALL DynamicResultSetWrapper
106 : ::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet )
107 : {
108 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
109 : OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" );
110 0 : m_xSourceResultOne = xResultSet;
111 0 : m_xMyResultOne = xResultSet;
112 0 : }
113 :
114 : //virtual
115 0 : void SAL_CALL DynamicResultSetWrapper
116 : ::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet )
117 : {
118 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
119 : OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" );
120 0 : m_xSourceResultTwo = xResultSet;
121 0 : m_xMyResultTwo = xResultSet;
122 0 : }
123 :
124 : //--------------------------------------------------------------------------
125 : // XInterface methods.
126 : //--------------------------------------------------------------------------
127 : //list all interfaces inclusive baseclasses of interfaces
128 0 : QUERYINTERFACE_IMPL_START( DynamicResultSetWrapper )
129 : (static_cast< XComponent* >(this)) //base of XDynamicResultSet
130 : , (static_cast< XDynamicResultSet* >(this))
131 : , (static_cast< XSourceInitialization* >(this))
132 0 : QUERYINTERFACE_IMPL_END
133 :
134 : //--------------------------------------------------------------------------
135 : // XComponent methods.
136 : //--------------------------------------------------------------------------
137 : // virtual
138 0 : void SAL_CALL DynamicResultSetWrapper
139 : ::dispose() throw( RuntimeException )
140 : {
141 0 : impl_EnsureNotDisposed();
142 :
143 0 : Reference< XComponent > xSourceComponent;
144 : {
145 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
146 0 : if( m_bInDispose || m_bDisposed )
147 0 : return;
148 0 : m_bInDispose = sal_True;
149 :
150 0 : xSourceComponent = Reference< XComponent >(m_xSource, UNO_QUERY);
151 :
152 0 : if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
153 : {
154 0 : EventObject aEvt;
155 0 : aEvt.Source = static_cast< XComponent * >( this );
156 :
157 0 : aGuard.clear();
158 0 : m_pDisposeEventListeners->disposeAndClear( aEvt );
159 0 : }
160 : }
161 :
162 : /* //@todo ?? ( only if java collection needs to long )
163 : if( xSourceComponent.is() )
164 : xSourceComponent->dispose();
165 : */
166 :
167 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
168 0 : m_bDisposed = sal_True;
169 0 : m_bInDispose = sal_False;
170 : }
171 :
172 : //--------------------------------------------------------------------------
173 : // virtual
174 0 : void SAL_CALL DynamicResultSetWrapper
175 : ::addEventListener( const Reference< XEventListener >& Listener )
176 : throw( RuntimeException )
177 : {
178 0 : impl_EnsureNotDisposed();
179 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
180 :
181 0 : if ( !m_pDisposeEventListeners )
182 : m_pDisposeEventListeners =
183 0 : new OInterfaceContainerHelper( m_aContainerMutex );
184 :
185 0 : m_pDisposeEventListeners->addInterface( Listener );
186 0 : }
187 :
188 : //--------------------------------------------------------------------------
189 : // virtual
190 0 : void SAL_CALL DynamicResultSetWrapper
191 : ::removeEventListener( const Reference< XEventListener >& Listener )
192 : throw( RuntimeException )
193 : {
194 0 : impl_EnsureNotDisposed();
195 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
196 :
197 0 : if ( m_pDisposeEventListeners )
198 0 : m_pDisposeEventListeners->removeInterface( Listener );
199 0 : }
200 :
201 : //--------------------------------------------------------------------------
202 : // own methods
203 : //--------------------------------------------------------------------------
204 :
205 : //virtual
206 0 : void SAL_CALL DynamicResultSetWrapper
207 : ::impl_disposing( const EventObject& )
208 : throw( RuntimeException )
209 : {
210 0 : impl_EnsureNotDisposed();
211 :
212 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
213 :
214 0 : if( !m_xSource.is() )
215 0 : return;
216 :
217 : //release all references to the broadcaster:
218 0 : m_xSource.clear();
219 0 : m_xSourceResultOne.clear();//?? or only when not static??
220 0 : m_xSourceResultTwo.clear();//??
221 : //@todo m_xMyResultOne.clear(); ???
222 : //@todo m_xMyResultTwo.clear(); ???
223 : }
224 :
225 : //virtual
226 0 : void SAL_CALL DynamicResultSetWrapper
227 : ::impl_notify( const ListEvent& Changes )
228 : throw( RuntimeException )
229 : {
230 0 : impl_EnsureNotDisposed();
231 : //@todo
232 : /*
233 : <p>The Listener is allowed to blockade this call, until he really want to go
234 : to the new version. The only situation, where the listener has to return the
235 : update call at once is, while he disposes his broadcaster or while he is
236 : removing himsef as listener (otherwise you deadlock)!!!
237 : */
238 : // handle the actions in the list
239 :
240 0 : ListEvent aNewEvent;
241 0 : aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
242 0 : aNewEvent.Changes = Changes.Changes;
243 :
244 : {
245 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
246 0 : for( long i=0; !m_bGotWelcome && i<Changes.Changes.getLength(); i++ )
247 : {
248 0 : ListAction& rAction = aNewEvent.Changes[i];
249 0 : switch( rAction.ListActionType )
250 : {
251 : case ListActionType::WELCOME:
252 : {
253 0 : WelcomeDynamicResultSetStruct aWelcome;
254 0 : if( rAction.ActionInfo >>= aWelcome )
255 : {
256 0 : impl_InitResultSetOne( aWelcome.Old );
257 0 : impl_InitResultSetTwo( aWelcome.New );
258 0 : m_bGotWelcome = sal_True;
259 :
260 0 : aWelcome.Old = m_xMyResultOne;
261 0 : aWelcome.New = m_xMyResultTwo;
262 :
263 0 : rAction.ActionInfo <<= aWelcome;
264 : }
265 : else
266 : {
267 : OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
268 : //throw RuntimeException();
269 : }
270 0 : break;
271 : }
272 : }
273 : }
274 0 : OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" );
275 : }
276 :
277 0 : if( !m_xListener.is() )
278 0 : m_aListenerSet.wait();
279 0 : m_xListener->notify( aNewEvent );
280 :
281 : /*
282 : m_bUseOne = !m_bUseOne;
283 : if( m_bUseOne )
284 : m_xSourceResultCurrent = m_xSourceResultOne;
285 : else
286 : m_xSourceResultCurrent = m_xSourceResultTwo;
287 : */
288 0 : }
289 :
290 : //--------------------------------------------------------------------------
291 : // XSourceInitialization
292 : //--------------------------------------------------------------------------
293 : //virtual
294 0 : void SAL_CALL DynamicResultSetWrapper
295 : ::setSource( const Reference< XInterface > & Source )
296 : throw( AlreadyInitializedException, RuntimeException )
297 : {
298 0 : impl_EnsureNotDisposed();
299 : {
300 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
301 0 : if( m_xSource.is() )
302 : {
303 0 : throw AlreadyInitializedException();
304 0 : }
305 : }
306 :
307 0 : Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY );
308 : OSL_ENSURE( xSourceDynamic.is(),
309 : "the given source is not of required type XDynamicResultSet" );
310 :
311 0 : Reference< XDynamicResultSetListener > xListener = NULL;
312 0 : Reference< XDynamicResultSetListener > xMyListenerImpl = NULL;
313 :
314 0 : sal_Bool bStatic = sal_False;
315 : {
316 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
317 0 : m_xSource = xSourceDynamic;
318 0 : xListener = m_xListener;
319 0 : bStatic = m_bStatic;
320 0 : xMyListenerImpl = m_xMyListenerImpl;
321 : }
322 0 : if( xListener.is() )
323 0 : xSourceDynamic->setListener( m_xMyListenerImpl );
324 0 : else if( bStatic )
325 : {
326 0 : Reference< XComponent > xSourceComponent( Source, UNO_QUERY );
327 0 : xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) );
328 : }
329 0 : m_aSourceSet.set();
330 0 : }
331 :
332 : //--------------------------------------------------------------------------
333 : // XDynamicResultSet
334 : //--------------------------------------------------------------------------
335 : //virtual
336 0 : Reference< XResultSet > SAL_CALL DynamicResultSetWrapper
337 : ::getStaticResultSet()
338 : throw( ListenerAlreadySetException, RuntimeException )
339 : {
340 0 : impl_EnsureNotDisposed();
341 :
342 0 : Reference< XDynamicResultSet > xSource = NULL;
343 0 : Reference< XEventListener > xMyListenerImpl = NULL;
344 : {
345 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
346 0 : if( m_xListener.is() )
347 0 : throw ListenerAlreadySetException();
348 :
349 0 : xSource = m_xSource;
350 0 : m_bStatic = sal_True;
351 0 : xMyListenerImpl = Reference< XEventListener > ::query( m_xMyListenerImpl );
352 : }
353 :
354 0 : if( xSource.is() )
355 : {
356 0 : xSource->addEventListener( xMyListenerImpl );
357 : }
358 0 : if( !xSource.is() )
359 0 : m_aSourceSet.wait();
360 :
361 :
362 0 : Reference< XResultSet > xResultSet = xSource->getStaticResultSet();
363 0 : impl_InitResultSetOne( xResultSet );
364 0 : return m_xMyResultOne;
365 : }
366 :
367 : //virtual
368 0 : void SAL_CALL DynamicResultSetWrapper
369 : ::setListener( const Reference<
370 : XDynamicResultSetListener > & Listener )
371 : throw( ListenerAlreadySetException, RuntimeException )
372 : {
373 0 : impl_EnsureNotDisposed();
374 :
375 0 : Reference< XDynamicResultSet > xSource = NULL;
376 0 : Reference< XDynamicResultSetListener > xMyListenerImpl = NULL;
377 : {
378 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
379 0 : if( m_xListener.is() )
380 0 : throw ListenerAlreadySetException();
381 0 : if( m_bStatic )
382 0 : throw ListenerAlreadySetException();
383 :
384 0 : m_xListener = Listener;
385 0 : addEventListener( Reference< XEventListener >::query( Listener ) );
386 :
387 0 : xSource = m_xSource;
388 0 : xMyListenerImpl = m_xMyListenerImpl;
389 : }
390 0 : if ( xSource.is() )
391 0 : xSource->setListener( xMyListenerImpl );
392 :
393 0 : m_aListenerSet.set();
394 0 : }
395 :
396 : //virtual
397 0 : void SAL_CALL DynamicResultSetWrapper
398 : ::connectToCache( const Reference< XDynamicResultSet > & xCache )
399 : throw( ListenerAlreadySetException, AlreadyInitializedException, ServiceNotFoundException, RuntimeException )
400 : {
401 0 : impl_EnsureNotDisposed();
402 :
403 0 : if( m_xListener.is() )
404 0 : throw ListenerAlreadySetException();
405 0 : if( m_bStatic )
406 0 : throw ListenerAlreadySetException();
407 :
408 0 : Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
409 : OSL_ENSURE( xTarget.is(), "The given Target dosn't have the required interface 'XSourceInitialization'" );
410 0 : if( xTarget.is() && m_xContext.is() )
411 : {
412 : //@todo m_aSourceSet.wait();?
413 :
414 0 : Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
415 : try
416 : {
417 0 : xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
418 : }
419 0 : catch ( Exception const & )
420 : {
421 : }
422 :
423 0 : if( xStubFactory.is() )
424 : {
425 0 : xStubFactory->connectToCache(
426 0 : this, xCache, Sequence< NumberedSortingInfo > (), NULL );
427 0 : return;
428 0 : }
429 : }
430 : OSL_FAIL( "could not connect to cache" );
431 0 : throw ServiceNotFoundException();
432 : }
433 :
434 : //virtual
435 0 : sal_Int16 SAL_CALL DynamicResultSetWrapper
436 : ::getCapabilities()
437 : throw( RuntimeException )
438 : {
439 0 : impl_EnsureNotDisposed();
440 :
441 0 : m_aSourceSet.wait();
442 0 : Reference< XDynamicResultSet > xSource = NULL;
443 : {
444 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
445 0 : xSource = m_xSource;
446 : }
447 0 : return xSource->getCapabilities();
448 : }
449 :
450 : //--------------------------------------------------------------------------
451 : //--------------------------------------------------------------------------
452 : // class DynamicResultSetWrapperListener
453 : //--------------------------------------------------------------------------
454 : //--------------------------------------------------------------------------
455 :
456 0 : DynamicResultSetWrapperListener::DynamicResultSetWrapperListener(
457 : DynamicResultSetWrapper* pOwner )
458 0 : : m_pOwner( pOwner )
459 : {
460 :
461 0 : }
462 :
463 0 : DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener()
464 : {
465 :
466 0 : }
467 :
468 : //--------------------------------------------------------------------------
469 : // XInterface methods.
470 : //--------------------------------------------------------------------------
471 : //list all interfaces inclusive baseclasses of interfaces
472 0 : XINTERFACE_IMPL_2( DynamicResultSetWrapperListener
473 : , XDynamicResultSetListener
474 : , XEventListener //base of XDynamicResultSetListener
475 : );
476 :
477 : //--------------------------------------------------------------------------
478 : // XDynamicResultSetListener methods:
479 : //--------------------------------------------------------------------------
480 : //virtual
481 0 : void SAL_CALL DynamicResultSetWrapperListener
482 : ::disposing( const EventObject& rEventObject )
483 : throw( RuntimeException )
484 : {
485 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
486 :
487 0 : if( m_pOwner )
488 0 : m_pOwner->impl_disposing( rEventObject );
489 0 : }
490 :
491 : //virtual
492 0 : void SAL_CALL DynamicResultSetWrapperListener
493 : ::notify( const ListEvent& Changes )
494 : throw( RuntimeException )
495 : {
496 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
497 :
498 0 : if( m_pOwner )
499 0 : m_pOwner->impl_notify( Changes );
500 0 : }
501 :
502 : //--------------------------------------------------------------------------
503 : // own methods:
504 : //--------------------------------------------------------------------------
505 :
506 0 : void SAL_CALL DynamicResultSetWrapperListener
507 : ::impl_OwnerDies()
508 : {
509 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
510 :
511 0 : m_pOwner = NULL;
512 0 : }
513 :
514 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|