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( false )
47 : , m_bInDispose( false )
48 : , m_pDisposeEventListeners( NULL )
49 : , m_xContext( rxContext )
50 : , m_bStatic( false )
51 : , m_bGotWelcome( 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 : // XInterface methods.
125 0 : css::uno::Any SAL_CALL DynamicResultSetWrapper::queryInterface( const css::uno::Type & rType )
126 : throw( css::uno::RuntimeException, std::exception )
127 : {
128 : //list all interfaces inclusive baseclasses of interfaces
129 : css::uno::Any aRet = cppu::queryInterface( rType,
130 : (static_cast< XComponent* >(this)), //base of XDynamicResultSet
131 : (static_cast< XDynamicResultSet* >(this)),
132 : (static_cast< XSourceInitialization* >(this))
133 0 : );
134 0 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
135 : }
136 :
137 : // XComponent methods.
138 :
139 : // virtual
140 0 : void SAL_CALL DynamicResultSetWrapper
141 : ::dispose() throw( RuntimeException, std::exception )
142 : {
143 0 : impl_EnsureNotDisposed();
144 :
145 0 : Reference< XComponent > xSourceComponent;
146 : {
147 0 : osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
148 0 : if( m_bInDispose || m_bDisposed )
149 0 : return;
150 0 : m_bInDispose = true;
151 :
152 0 : xSourceComponent = Reference< XComponent >(m_xSource, UNO_QUERY);
153 :
154 0 : if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
155 : {
156 0 : EventObject aEvt;
157 0 : aEvt.Source = static_cast< XComponent * >( this );
158 :
159 0 : aGuard.clear();
160 0 : m_pDisposeEventListeners->disposeAndClear( aEvt );
161 0 : }
162 : }
163 :
164 : /* //@todo ?? ( only if java collection needs to long )
165 : if( xSourceComponent.is() )
166 : xSourceComponent->dispose();
167 : */
168 :
169 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
170 0 : m_bDisposed = true;
171 0 : m_bInDispose = false;
172 : }
173 :
174 :
175 : // virtual
176 0 : void SAL_CALL DynamicResultSetWrapper
177 : ::addEventListener( const Reference< XEventListener >& Listener )
178 : throw( RuntimeException, std::exception )
179 : {
180 0 : impl_EnsureNotDisposed();
181 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
182 :
183 0 : if ( !m_pDisposeEventListeners )
184 : m_pDisposeEventListeners =
185 0 : new OInterfaceContainerHelper( m_aContainerMutex );
186 :
187 0 : m_pDisposeEventListeners->addInterface( Listener );
188 0 : }
189 :
190 :
191 : // virtual
192 0 : void SAL_CALL DynamicResultSetWrapper
193 : ::removeEventListener( const Reference< XEventListener >& Listener )
194 : throw( RuntimeException, std::exception )
195 : {
196 0 : impl_EnsureNotDisposed();
197 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
198 :
199 0 : if ( m_pDisposeEventListeners )
200 0 : m_pDisposeEventListeners->removeInterface( Listener );
201 0 : }
202 :
203 :
204 : // own methods
205 :
206 :
207 : //virtual
208 0 : void SAL_CALL DynamicResultSetWrapper
209 : ::impl_disposing( const EventObject& )
210 : throw( RuntimeException )
211 : {
212 0 : impl_EnsureNotDisposed();
213 :
214 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
215 :
216 0 : if( !m_xSource.is() )
217 0 : return;
218 :
219 : //release all references to the broadcaster:
220 0 : m_xSource.clear();
221 0 : m_xSourceResultOne.clear();//?? or only when not static??
222 0 : m_xSourceResultTwo.clear();//??
223 : //@todo m_xMyResultOne.clear(); ???
224 : //@todo m_xMyResultTwo.clear(); ???
225 : }
226 :
227 : //virtual
228 0 : void SAL_CALL DynamicResultSetWrapper
229 : ::impl_notify( const ListEvent& Changes )
230 : throw( RuntimeException )
231 : {
232 0 : impl_EnsureNotDisposed();
233 : //@todo
234 : /*
235 : <p>The Listener is allowed to blockade this call, until he really want to go
236 : to the new version. The only situation, where the listener has to return the
237 : update call at once is, while he disposes his broadcaster or while he is
238 : removing himsef as listener (otherwise you deadlock)!!!
239 : */
240 : // handle the actions in the list
241 :
242 0 : ListEvent aNewEvent;
243 0 : aNewEvent.Source = static_cast< XDynamicResultSet * >( this );
244 0 : aNewEvent.Changes = Changes.Changes;
245 :
246 : {
247 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
248 0 : for( long i=0; !m_bGotWelcome && i<Changes.Changes.getLength(); i++ )
249 : {
250 0 : ListAction& rAction = aNewEvent.Changes[i];
251 0 : switch( rAction.ListActionType )
252 : {
253 : case ListActionType::WELCOME:
254 : {
255 0 : WelcomeDynamicResultSetStruct aWelcome;
256 0 : if( rAction.ActionInfo >>= aWelcome )
257 : {
258 0 : impl_InitResultSetOne( aWelcome.Old );
259 0 : impl_InitResultSetTwo( aWelcome.New );
260 0 : m_bGotWelcome = true;
261 :
262 0 : aWelcome.Old = m_xMyResultOne;
263 0 : aWelcome.New = m_xMyResultTwo;
264 :
265 0 : rAction.ActionInfo <<= aWelcome;
266 : }
267 : else
268 : {
269 : OSL_FAIL( "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" );
270 : //throw RuntimeException();
271 : }
272 0 : break;
273 : }
274 : }
275 : }
276 0 : OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" );
277 : }
278 :
279 0 : if( !m_xListener.is() )
280 0 : m_aListenerSet.wait();
281 0 : m_xListener->notify( aNewEvent );
282 :
283 : /*
284 : m_bUseOne = !m_bUseOne;
285 : if( m_bUseOne )
286 : m_xSourceResultCurrent = m_xSourceResultOne;
287 : else
288 : m_xSourceResultCurrent = m_xSourceResultTwo;
289 : */
290 0 : }
291 :
292 :
293 : // XSourceInitialization
294 :
295 : //virtual
296 0 : void SAL_CALL DynamicResultSetWrapper
297 : ::setSource( const Reference< XInterface > & Source )
298 : throw( AlreadyInitializedException, RuntimeException, std::exception )
299 : {
300 0 : impl_EnsureNotDisposed();
301 : {
302 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
303 0 : if( m_xSource.is() )
304 : {
305 0 : throw AlreadyInitializedException();
306 0 : }
307 : }
308 :
309 0 : Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY );
310 : OSL_ENSURE( xSourceDynamic.is(),
311 : "the given source is not of required type XDynamicResultSet" );
312 :
313 0 : Reference< XDynamicResultSetListener > xListener = NULL;
314 0 : Reference< XDynamicResultSetListener > xMyListenerImpl = NULL;
315 :
316 0 : bool bStatic = false;
317 : {
318 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
319 0 : m_xSource = xSourceDynamic;
320 0 : xListener = m_xListener;
321 0 : bStatic = m_bStatic;
322 0 : xMyListenerImpl = m_xMyListenerImpl;
323 : }
324 0 : if( xListener.is() )
325 0 : xSourceDynamic->setListener( m_xMyListenerImpl );
326 0 : else if( bStatic )
327 : {
328 0 : Reference< XComponent > xSourceComponent( Source, UNO_QUERY );
329 0 : xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) );
330 : }
331 0 : m_aSourceSet.set();
332 0 : }
333 :
334 :
335 : // XDynamicResultSet
336 :
337 : //virtual
338 0 : Reference< XResultSet > SAL_CALL DynamicResultSetWrapper
339 : ::getStaticResultSet()
340 : throw( ListenerAlreadySetException, RuntimeException, std::exception )
341 : {
342 0 : impl_EnsureNotDisposed();
343 :
344 0 : Reference< XDynamicResultSet > xSource = NULL;
345 0 : Reference< XEventListener > xMyListenerImpl = NULL;
346 : {
347 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
348 0 : if( m_xListener.is() )
349 0 : throw ListenerAlreadySetException();
350 :
351 0 : xSource = m_xSource;
352 0 : m_bStatic = true;
353 0 : xMyListenerImpl = Reference< XEventListener > ::query( m_xMyListenerImpl );
354 : }
355 :
356 0 : if( xSource.is() )
357 : {
358 0 : xSource->addEventListener( xMyListenerImpl );
359 : }
360 0 : if( !xSource.is() )
361 0 : m_aSourceSet.wait();
362 :
363 :
364 0 : Reference< XResultSet > xResultSet = xSource->getStaticResultSet();
365 0 : impl_InitResultSetOne( xResultSet );
366 0 : return m_xMyResultOne;
367 : }
368 :
369 : //virtual
370 0 : void SAL_CALL DynamicResultSetWrapper
371 : ::setListener( const Reference<
372 : XDynamicResultSetListener > & Listener )
373 : throw( ListenerAlreadySetException, RuntimeException, std::exception )
374 : {
375 0 : impl_EnsureNotDisposed();
376 :
377 0 : Reference< XDynamicResultSet > xSource = NULL;
378 0 : Reference< XDynamicResultSetListener > xMyListenerImpl = NULL;
379 : {
380 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
381 0 : if( m_xListener.is() )
382 0 : throw ListenerAlreadySetException();
383 0 : if( m_bStatic )
384 0 : throw ListenerAlreadySetException();
385 :
386 0 : m_xListener = Listener;
387 0 : addEventListener( Reference< XEventListener >::query( Listener ) );
388 :
389 0 : xSource = m_xSource;
390 0 : xMyListenerImpl = m_xMyListenerImpl;
391 : }
392 0 : if ( xSource.is() )
393 0 : xSource->setListener( xMyListenerImpl );
394 :
395 0 : m_aListenerSet.set();
396 0 : }
397 :
398 : //virtual
399 0 : void SAL_CALL DynamicResultSetWrapper
400 : ::connectToCache( const Reference< XDynamicResultSet > & xCache )
401 : throw( ListenerAlreadySetException, AlreadyInitializedException, ServiceNotFoundException, RuntimeException, std::exception )
402 : {
403 0 : impl_EnsureNotDisposed();
404 :
405 0 : if( m_xListener.is() )
406 0 : throw ListenerAlreadySetException();
407 0 : if( m_bStatic )
408 0 : throw ListenerAlreadySetException();
409 :
410 0 : Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY );
411 : OSL_ENSURE( xTarget.is(), "The given Target dosn't have the required interface 'XSourceInitialization'" );
412 0 : if( xTarget.is() && m_xContext.is() )
413 : {
414 : //@todo m_aSourceSet.wait();?
415 :
416 0 : Reference< XCachedDynamicResultSetStubFactory > xStubFactory;
417 : try
418 : {
419 0 : xStubFactory = CachedDynamicResultSetStubFactory::create( m_xContext );
420 : }
421 0 : catch ( Exception const & )
422 : {
423 : }
424 :
425 0 : if( xStubFactory.is() )
426 : {
427 0 : xStubFactory->connectToCache(
428 0 : this, xCache, Sequence< NumberedSortingInfo > (), NULL );
429 0 : return;
430 0 : }
431 : }
432 : OSL_FAIL( "could not connect to cache" );
433 0 : throw ServiceNotFoundException();
434 : }
435 :
436 : //virtual
437 0 : sal_Int16 SAL_CALL DynamicResultSetWrapper
438 : ::getCapabilities()
439 : throw( RuntimeException, std::exception )
440 : {
441 0 : impl_EnsureNotDisposed();
442 :
443 0 : m_aSourceSet.wait();
444 0 : Reference< XDynamicResultSet > xSource = NULL;
445 : {
446 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
447 0 : xSource = m_xSource;
448 : }
449 0 : return xSource->getCapabilities();
450 : }
451 :
452 :
453 :
454 : // class DynamicResultSetWrapperListener
455 :
456 :
457 :
458 0 : DynamicResultSetWrapperListener::DynamicResultSetWrapperListener(
459 : DynamicResultSetWrapper* pOwner )
460 0 : : m_pOwner( pOwner )
461 : {
462 :
463 0 : }
464 :
465 0 : DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener()
466 : {
467 :
468 0 : }
469 :
470 :
471 : // XInterface methods.
472 :
473 0 : void SAL_CALL DynamicResultSetWrapperListener::acquire()
474 : throw()
475 : {
476 0 : OWeakObject::acquire();
477 0 : }
478 :
479 0 : void SAL_CALL DynamicResultSetWrapperListener::release()
480 : throw()
481 : {
482 0 : OWeakObject::release();
483 0 : }
484 :
485 0 : css::uno::Any SAL_CALL DynamicResultSetWrapperListener::queryInterface( const css::uno::Type & rType )
486 : throw( css::uno::RuntimeException, std::exception )
487 : {
488 : css::uno::Any aRet = cppu::queryInterface( rType,
489 : (static_cast< XDynamicResultSetListener* >(this)),
490 : (static_cast< XEventListener* >(this))
491 0 : );
492 0 : return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
493 : }
494 :
495 : // XDynamicResultSetListener methods:
496 :
497 : //virtual
498 0 : void SAL_CALL DynamicResultSetWrapperListener
499 : ::disposing( const EventObject& rEventObject )
500 : throw( RuntimeException, std::exception )
501 : {
502 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
503 :
504 0 : if( m_pOwner )
505 0 : m_pOwner->impl_disposing( rEventObject );
506 0 : }
507 :
508 : //virtual
509 0 : void SAL_CALL DynamicResultSetWrapperListener
510 : ::notify( const ListEvent& Changes )
511 : throw( RuntimeException, std::exception )
512 : {
513 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
514 :
515 0 : if( m_pOwner )
516 0 : m_pOwner->impl_notify( Changes );
517 0 : }
518 :
519 :
520 : // own methods:
521 :
522 :
523 0 : void SAL_CALL DynamicResultSetWrapperListener
524 : ::impl_OwnerDies()
525 : {
526 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
527 :
528 0 : m_pOwner = NULL;
529 0 : }
530 :
531 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|