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