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