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