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