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_ucbhelper.hxx"
30 
31 /**************************************************************************
32 								TODO
33  **************************************************************************
34 
35  *************************************************************************/
36 #include <cppuhelper/interfacecontainer.hxx>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <ucbhelper/resultset.hxx>
39 #include <ucbhelper/resultsetmetadata.hxx>
40 
41 using namespace com::sun::star;
42 
43 //=========================================================================
44 
45 namespace ucbhelper_impl
46 {
47 
48 struct PropertyInfo
49 {
50 	const char*	pName;
51 	sal_Int32   nHandle;
52 	sal_Int16   nAttributes;
53 	const uno::Type& (*pGetCppuType)();
54 };
55 
56 static const uno::Type& sal_Int32_getCppuType()
57 {
58 	return getCppuType( static_cast< const sal_Int32 * >( 0 ) );
59 }
60 
61 static const uno::Type& sal_Bool_getCppuType()
62 {
63 	return getCppuBooleanType();
64 }
65 
66 static const PropertyInfo aPropertyTable[] =
67 {
68 	{ "IsRowCountFinal",
69 	  1000,
70 	  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
71 	  &sal_Bool_getCppuType
72 	},
73 	{ "RowCount",
74 	  1001,
75 	  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
76 	  &sal_Int32_getCppuType
77 	},
78 	{ 0,
79 	  0,
80 	  0,
81 	  0
82 	}
83 };
84 
85 #define RESULTSET_PROPERTY_COUNT 2
86 
87 //=========================================================================
88 //
89 // class PropertySetInfo
90 //
91 //=========================================================================
92 
93 class PropertySetInfo :
94 		public cppu::OWeakObject,
95         public lang::XTypeProvider,
96         public beans::XPropertySetInfo
97 {
98 	uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
99 	uno::Sequence< beans::Property >* 			 m_pProps;
100 
101 private:
102 	sal_Bool queryProperty(
103         const rtl::OUString& aName, beans::Property& rProp );
104 
105 public:
106 	PropertySetInfo(
107         const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
108         const PropertyInfo* pProps,
109         sal_Int32 nProps );
110 	virtual ~PropertySetInfo();
111 
112 	// XInterface
113 	XINTERFACE_DECL()
114 
115 	// XTypeProvider
116 	XTYPEPROVIDER_DECL()
117 
118 	// XPropertySetInfo
119     virtual uno::Sequence< beans::Property > SAL_CALL getProperties()
120 		throw( uno::RuntimeException );
121     virtual beans::Property SAL_CALL getPropertyByName(
122             const rtl::OUString& aName )
123 		throw( beans::UnknownPropertyException, uno::RuntimeException );
124     virtual sal_Bool SAL_CALL hasPropertyByName( const rtl::OUString& Name )
125 		throw( uno::RuntimeException );
126 };
127 
128 //=========================================================================
129 //
130 // PropertyChangeListenerContainer.
131 //
132 //=========================================================================
133 
134 struct equalStr_Impl
135 {
136 	bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const
137   	{
138 		return !!( s1 == s2 );
139 	}
140 };
141 
142 struct hashStr_Impl
143 {
144 	size_t operator()( const rtl::OUString& rName ) const
145 	{
146 		return rName.hashCode();
147 	}
148 };
149 
150 typedef cppu::OMultiTypeInterfaceContainerHelperVar
151 <
152 	rtl::OUString,
153 	hashStr_Impl,
154 	equalStr_Impl
155 > PropertyChangeListenerContainer;
156 
157 //=========================================================================
158 //
159 // class PropertyChangeListeners.
160 //
161 //=========================================================================
162 
163 class PropertyChangeListeners : public PropertyChangeListenerContainer
164 {
165 public:
166 	PropertyChangeListeners( osl::Mutex& rMtx )
167 	: PropertyChangeListenerContainer( rMtx ) {}
168 };
169 
170 } // namespace ucbhelper_impl
171 
172 using namespace ucbhelper_impl;
173 
174 namespace ucbhelper
175 {
176 
177 //=========================================================================
178 //
179 // struct ResultSet_Impl.
180 //
181 //=========================================================================
182 
183 struct ResultSet_Impl
184 {
185 	uno::Reference< lang::XMultiServiceFactory > 	m_xSMgr;
186 	uno::Reference< com::sun::star::ucb::XCommandEnvironment > 	m_xEnv;
187 	uno::Reference< beans::XPropertySetInfo >     	m_xPropSetInfo;
188 	uno::Reference< sdbc::XResultSetMetaData >   	m_xMetaData;
189 	uno::Sequence< beans::Property >              	m_aProperties;
190 	rtl::Reference< ResultSetDataSupplier >	        m_xDataSupplier;
191 	osl::Mutex						 	m_aMutex;
192 	cppu::OInterfaceContainerHelper* 	m_pDisposeEventListeners;
193 	PropertyChangeListeners*			m_pPropertyChangeListeners;
194 	sal_Int32						 	m_nPos;
195 	sal_Bool 						 	m_bWasNull;
196 	sal_Bool 						 	m_bAfterLast;
197 
198 	inline ResultSet_Impl(
199         const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
200         const uno::Sequence< beans::Property >& rProperties,
201         const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
202         const uno::Reference< com::sun::star::ucb::XCommandEnvironment >&
203             rxEnv );
204 	inline ~ResultSet_Impl();
205 };
206 
207 inline ResultSet_Impl::ResultSet_Impl(
208     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
209     const uno::Sequence< beans::Property >& rProperties,
210     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
211     const uno::Reference< com::sun::star::ucb::XCommandEnvironment >& rxEnv )
212 : m_xSMgr( rxSMgr ),
213   m_xEnv( rxEnv ),
214   m_aProperties( rProperties ),
215   m_xDataSupplier( rDataSupplier ),
216   m_pDisposeEventListeners( 0 ),
217   m_pPropertyChangeListeners( 0 ),
218   m_nPos( 0 ), // Position is one-based. Zero means: before first element.
219   m_bWasNull( sal_False ),
220   m_bAfterLast( sal_False )
221 {
222 }
223 
224 //=========================================================================
225 inline ResultSet_Impl::~ResultSet_Impl()
226 {
227 	delete m_pDisposeEventListeners;
228 	delete m_pPropertyChangeListeners;
229 }
230 
231 //=========================================================================
232 //=========================================================================
233 //
234 // ResultSet Implementation.
235 //
236 //=========================================================================
237 //=========================================================================
238 
239 ResultSet::ResultSet(
240     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
241     const uno::Sequence< beans::Property >& rProperties,
242     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier )
243 : m_pImpl( new ResultSet_Impl(
244                rxSMgr,
245                rProperties,
246                rDataSupplier,
247                uno::Reference< com::sun::star::ucb::XCommandEnvironment >() ) )
248 {
249 	rDataSupplier->m_pResultSet = this;
250 }
251 
252 //=========================================================================
253 ResultSet::ResultSet(
254     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
255     const uno::Sequence< beans::Property >& rProperties,
256     const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
257     const uno::Reference< com::sun::star::ucb::XCommandEnvironment >& rxEnv )
258 : m_pImpl( new ResultSet_Impl( rxSMgr, rProperties, rDataSupplier, rxEnv ) )
259 {
260 	rDataSupplier->m_pResultSet = this;
261 }
262 
263 //=========================================================================
264 // virtual
265 ResultSet::~ResultSet()
266 {
267 	delete m_pImpl;
268 }
269 
270 //=========================================================================
271 //
272 // XInterface methods.
273 //
274 //=========================================================================
275 
276 XINTERFACE_IMPL_9( ResultSet,
277 				   lang::XTypeProvider,
278 				   lang::XServiceInfo,
279 				   lang::XComponent,
280 				   com::sun::star::ucb::XContentAccess,
281 				   sdbc::XResultSet,
282 				   sdbc::XResultSetMetaDataSupplier,
283 				   sdbc::XRow,
284 				   sdbc::XCloseable,
285 				   beans::XPropertySet );
286 
287 //=========================================================================
288 //
289 // XTypeProvider methods.
290 //
291 //=========================================================================
292 
293 XTYPEPROVIDER_IMPL_9( ResultSet,
294 					  lang::XTypeProvider,
295 				   	  lang::XServiceInfo,
296 					  lang::XComponent,
297 					  com::sun::star::ucb::XContentAccess,
298 					  sdbc::XResultSet,
299 					  sdbc::XResultSetMetaDataSupplier,
300 					  sdbc::XRow,
301 					  sdbc::XCloseable,
302 					  beans::XPropertySet );
303 
304 //=========================================================================
305 //
306 // XServiceInfo methods.
307 //
308 //=========================================================================
309 
310 XSERVICEINFO_NOFACTORY_IMPL_1( ResultSet,
311 		 		   rtl::OUString::createFromAscii( "ResultSet" ),
312 		 		   rtl::OUString::createFromAscii( RESULTSET_SERVICE_NAME ) );
313 
314 //=========================================================================
315 //
316 // XComponent methods.
317 //
318 //=========================================================================
319 
320 // virtual
321 void SAL_CALL ResultSet::dispose()
322 	throw( uno::RuntimeException )
323 {
324 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
325 
326 	if ( m_pImpl->m_pDisposeEventListeners &&
327 		 m_pImpl->m_pDisposeEventListeners->getLength() )
328 	{
329 		lang::EventObject aEvt;
330 		aEvt.Source = static_cast< lang::XComponent * >( this );
331 		m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
332 	}
333 
334 	if ( m_pImpl->m_pPropertyChangeListeners )
335 	{
336 		lang::EventObject aEvt;
337 		aEvt.Source = static_cast< beans::XPropertySet * >( this );
338 		m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
339 	}
340 
341 	m_pImpl->m_xDataSupplier->close();
342 }
343 
344 //=========================================================================
345 // virtual
346 void SAL_CALL ResultSet::addEventListener(
347         const uno::Reference< lang::XEventListener >& Listener )
348 	throw( uno::RuntimeException )
349 {
350 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
351 
352 	if ( !m_pImpl->m_pDisposeEventListeners )
353 		m_pImpl->m_pDisposeEventListeners =
354             new cppu::OInterfaceContainerHelper( m_pImpl->m_aMutex );
355 
356 	m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
357 }
358 
359 //=========================================================================
360 // virtual
361 void SAL_CALL ResultSet::removeEventListener(
362         const uno::Reference< lang::XEventListener >& Listener )
363 	throw( uno::RuntimeException )
364 {
365 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
366 
367 	if ( m_pImpl->m_pDisposeEventListeners )
368 		m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
369 }
370 
371 //=========================================================================
372 //
373 // XResultSetMetaDataSupplier methods.
374 //
375 //=========================================================================
376 
377 // virtual
378 uno::Reference< sdbc::XResultSetMetaData > SAL_CALL ResultSet::getMetaData()
379 	throw( sdbc::SQLException, uno::RuntimeException )
380 {
381 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
382 
383 	if ( !m_pImpl->m_xMetaData.is() )
384 		m_pImpl->m_xMetaData = new ResultSetMetaData( m_pImpl->m_xSMgr,
385 													  m_pImpl->m_aProperties );
386 
387 	return m_pImpl->m_xMetaData;
388 }
389 
390 //=========================================================================
391 //
392 // XResultSet methods.
393 //
394 //=========================================================================
395 
396 // virtual
397 sal_Bool SAL_CALL ResultSet::next()
398 	throw( sdbc::SQLException, uno::RuntimeException )
399 {
400 	// Note: Cursor is initially positioned before the first row.
401 	//       First call to 'next()' moves it to first row.
402 
403 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
404 
405 	if ( m_pImpl->m_bAfterLast )
406 	{
407 		m_pImpl->m_xDataSupplier->validate();
408 		return sal_False;
409 	}
410 
411 	// getResult works zero-based!
412 	if ( !m_pImpl->m_xDataSupplier->getResult( m_pImpl->m_nPos ) )
413 	{
414 		m_pImpl->m_bAfterLast = sal_True;
415 		m_pImpl->m_xDataSupplier->validate();
416 		return sal_False;
417 	}
418 
419 	m_pImpl->m_nPos++;
420 	m_pImpl->m_xDataSupplier->validate();
421 	return sal_True;
422 }
423 
424 //=========================================================================
425 // virtual
426 sal_Bool SAL_CALL ResultSet::isBeforeFirst()
427 	throw( sdbc::SQLException, uno::RuntimeException )
428 {
429 	if ( m_pImpl->m_bAfterLast )
430 	{
431 		m_pImpl->m_xDataSupplier->validate();
432 		return sal_False;
433 	}
434 
435 	// getResult works zero-based!
436 	if ( !m_pImpl->m_xDataSupplier->getResult( 0 ) )
437 	{
438 		m_pImpl->m_xDataSupplier->validate();
439 		return sal_False;
440 	}
441 
442 	m_pImpl->m_xDataSupplier->validate();
443 	return ( m_pImpl->m_nPos == 0 );
444 }
445 
446 //=========================================================================
447 // virtual
448 sal_Bool SAL_CALL ResultSet::isAfterLast()
449 	throw( sdbc::SQLException, uno::RuntimeException )
450 {
451 	m_pImpl->m_xDataSupplier->validate();
452 	return m_pImpl->m_bAfterLast;
453 }
454 
455 //=========================================================================
456 // virtual
457 sal_Bool SAL_CALL ResultSet::isFirst()
458 	throw( sdbc::SQLException, uno::RuntimeException )
459 {
460 	if ( m_pImpl->m_bAfterLast )
461 	{
462 		m_pImpl->m_xDataSupplier->validate();
463 		return sal_False;
464 	}
465 
466 	m_pImpl->m_xDataSupplier->validate();
467 	return ( m_pImpl->m_nPos == 1 );
468 }
469 
470 //=========================================================================
471 // virtual
472 sal_Bool SAL_CALL ResultSet::isLast()
473 	throw( sdbc::SQLException, uno::RuntimeException )
474 {
475 	if ( m_pImpl->m_bAfterLast )
476 	{
477 		m_pImpl->m_xDataSupplier->validate();
478 		return sal_False;
479 	}
480 
481 	sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
482 	if ( !nCount )
483 	{
484 		m_pImpl->m_xDataSupplier->validate();
485 		return sal_False;
486 	}
487 
488 	m_pImpl->m_xDataSupplier->validate();
489 	return ( m_pImpl->m_nPos == nCount );
490 }
491 
492 //=========================================================================
493 // virtual
494 void SAL_CALL ResultSet::beforeFirst()
495 	throw( sdbc::SQLException, uno::RuntimeException )
496 {
497 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
498 	m_pImpl->m_bAfterLast = sal_False;
499 	m_pImpl->m_nPos = 0;
500 	m_pImpl->m_xDataSupplier->validate();
501 }
502 
503 //=========================================================================
504 // virtual
505 void SAL_CALL ResultSet::afterLast()
506 	throw( sdbc::SQLException, uno::RuntimeException )
507 {
508 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
509 	m_pImpl->m_bAfterLast = sal_True;
510 	m_pImpl->m_xDataSupplier->validate();
511 }
512 
513 //=========================================================================
514 // virtual
515 sal_Bool SAL_CALL ResultSet::first()
516 	throw( sdbc::SQLException, uno::RuntimeException )
517 {
518 	// getResult works zero-based!
519 	if ( m_pImpl->m_xDataSupplier->getResult( 0 ) )
520 	{
521 		osl::MutexGuard aGuard( m_pImpl->m_aMutex );
522 		m_pImpl->m_bAfterLast = sal_False;
523 		m_pImpl->m_nPos = 1;
524 		m_pImpl->m_xDataSupplier->validate();
525 		return sal_True;
526 	}
527 
528 	m_pImpl->m_xDataSupplier->validate();
529 	return sal_False;
530 }
531 
532 //=========================================================================
533 // virtual
534 sal_Bool SAL_CALL ResultSet::last()
535 	throw( sdbc::SQLException, uno::RuntimeException )
536 {
537 	sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
538 	if ( nCount )
539 	{
540 		osl::MutexGuard aGuard( m_pImpl->m_aMutex );
541 		m_pImpl->m_bAfterLast = sal_False;
542 		m_pImpl->m_nPos = nCount;
543 		m_pImpl->m_xDataSupplier->validate();
544 		return sal_True;
545 	}
546 
547 	m_pImpl->m_xDataSupplier->validate();
548 	return sal_False;
549 }
550 
551 //=========================================================================
552 // virtual
553 sal_Int32 SAL_CALL ResultSet::getRow()
554 	throw( sdbc::SQLException, uno::RuntimeException )
555 {
556 	if ( m_pImpl->m_bAfterLast )
557 	{
558 		m_pImpl->m_xDataSupplier->validate();
559 		return 0;
560 	}
561 
562 	m_pImpl->m_xDataSupplier->validate();
563 	return m_pImpl->m_nPos;
564 }
565 
566 //=========================================================================
567 // virtual
568 sal_Bool SAL_CALL ResultSet::absolute( sal_Int32 row )
569 	throw( sdbc::SQLException, uno::RuntimeException )
570 {
571 /*
572 	If the row number is positive, the cursor moves to the given row number
573 	with respect to the beginning of the result set. The first row is row 1,
574 	the second is row 2, and so on.
575 
576 	If the given row number is negative, the cursor moves to an absolute row
577 	position with respect to the end of the result set. For example, calling
578 	absolaute( -1 ) positions the cursor on the last row, absolaute( -2 )
579 	indicates the next-to-last row, and so on.
580 
581 	An attempt to position the cursor beyond the first/last row in the result
582 	set leaves the cursor before/after the first/last row, respectively.
583 
584 	Calling absolute( 1 ) is the same as calling first().
585 
586     Calling absolute( -1 ) is the same as calling last().
587 */
588 	if ( row < 0 )
589 	{
590 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
591 
592 		if ( ( row * -1 ) > nCount )
593 		{
594 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
595 			m_pImpl->m_bAfterLast = sal_False;
596 			m_pImpl->m_nPos = 0;
597 			m_pImpl->m_xDataSupplier->validate();
598 			return sal_False;
599 		}
600 		else // |row| <= nCount
601 		{
602 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
603 			m_pImpl->m_bAfterLast = sal_False;
604 			m_pImpl->m_nPos = ( nCount + row + 1 );
605 			m_pImpl->m_xDataSupplier->validate();
606 			return sal_True;
607 		}
608 	}
609 	else if ( row == 0 )
610 	{
611 	    // @throws SQLException
612 		//		... if row is 0 ...
613 		throw sdbc::SQLException();
614 	}
615 	else // row > 0
616 	{
617 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
618 
619 		if ( row <= nCount )
620 		{
621 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
622 			m_pImpl->m_bAfterLast = sal_False;
623 			m_pImpl->m_nPos = row;
624 			m_pImpl->m_xDataSupplier->validate();
625 			return sal_True;
626 		}
627 		else // row > nCount
628 		{
629 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
630 			m_pImpl->m_bAfterLast = sal_True;
631 			m_pImpl->m_xDataSupplier->validate();
632 			return sal_False;
633 		}
634 	}
635 
636 	// unreachable...
637 }
638 
639 //=========================================================================
640 // virtual
641 sal_Bool SAL_CALL ResultSet::relative( sal_Int32 rows )
642 	throw( sdbc::SQLException, uno::RuntimeException )
643 {
644 /*
645 	Attempting to move beyond the first/last row in the result set
646 	positions the cursor before/after the the first/last row.
647 
648 	Calling relative( 0 ) is valid, but does not change the cursor position.
649 
650     Calling relative( 1 ) is different from calling next() because it makes
651 	sense to call next() when there is no current row, for example,	when
652 	the cursor is positioned before the first row or after the last	row of
653 	the result set.
654 */
655 	if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
656 	{
657 		// "No current row".
658 		throw sdbc::SQLException();
659 	}
660 
661 	if ( rows < 0 )
662 	{
663 		if ( ( m_pImpl->m_nPos + rows ) > 0 )
664 		{
665 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
666 			m_pImpl->m_bAfterLast = sal_False;
667 			m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
668 			m_pImpl->m_xDataSupplier->validate();
669 			return sal_True;
670 		}
671 		else
672 		{
673 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
674 			m_pImpl->m_bAfterLast = sal_False;
675 			m_pImpl->m_nPos = 0;
676 			m_pImpl->m_xDataSupplier->validate();
677 			return sal_False;
678 		}
679 	}
680 	else if ( rows == 0 )
681 	{
682 		// nop.
683 		m_pImpl->m_xDataSupplier->validate();
684 		return sal_True;
685 	}
686 	else // rows > 0
687 	{
688 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
689 		if ( ( m_pImpl->m_nPos + rows ) <= nCount )
690 		{
691 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
692 			m_pImpl->m_bAfterLast = sal_False;
693 			m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
694 			m_pImpl->m_xDataSupplier->validate();
695 			return sal_True;
696 		}
697 		else
698 		{
699 			osl::MutexGuard aGuard( m_pImpl->m_aMutex );
700 			m_pImpl->m_bAfterLast = sal_True;
701 			m_pImpl->m_xDataSupplier->validate();
702 			return sal_False;
703 		}
704 	}
705 
706 	// unreachable...
707 }
708 
709 //=========================================================================
710 // virtual
711 sal_Bool SAL_CALL ResultSet::previous()
712 	throw( sdbc::SQLException, uno::RuntimeException )
713 {
714 /*
715 	previous() is not the same as relative( -1 ) because it makes sense
716 	to call previous() when there is no current row.
717 */
718 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
719 
720 	if ( m_pImpl->m_bAfterLast )
721 	{
722 		m_pImpl->m_bAfterLast = sal_False;
723 		sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
724 		m_pImpl->m_nPos = nCount;
725 	}
726 	else if ( m_pImpl->m_nPos )
727 		m_pImpl->m_nPos--;
728 
729 	if ( m_pImpl->m_nPos )
730 	{
731 		m_pImpl->m_xDataSupplier->validate();
732 		return sal_True;
733 	}
734 
735 	m_pImpl->m_xDataSupplier->validate();
736 	return sal_False;
737 }
738 
739 //=========================================================================
740 // virtual
741 void SAL_CALL ResultSet::refreshRow()
742 	throw( sdbc::SQLException, uno::RuntimeException )
743 {
744 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
745 	if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
746 		return;
747 
748 	m_pImpl->m_xDataSupplier->releasePropertyValues( m_pImpl->m_nPos );
749 	m_pImpl->m_xDataSupplier->validate();
750 }
751 
752 //=========================================================================
753 // virtual
754 sal_Bool SAL_CALL ResultSet::rowUpdated()
755 	throw( sdbc::SQLException, uno::RuntimeException )
756 {
757 	m_pImpl->m_xDataSupplier->validate();
758 	return sal_False;
759 }
760 
761 //=========================================================================
762 // virtual
763 sal_Bool SAL_CALL ResultSet::rowInserted()
764 	throw( sdbc::SQLException, uno::RuntimeException )
765 {
766 	m_pImpl->m_xDataSupplier->validate();
767 	return sal_False;
768 }
769 
770 //=========================================================================
771 // virtual
772 sal_Bool SAL_CALL ResultSet::rowDeleted()
773 	throw( sdbc::SQLException, uno::RuntimeException )
774 {
775 	m_pImpl->m_xDataSupplier->validate();
776 	return sal_False;
777 }
778 
779 //=========================================================================
780 // virtual
781 uno::Reference< uno::XInterface > SAL_CALL ResultSet::getStatement()
782 	throw( sdbc::SQLException, uno::RuntimeException )
783 {
784 /*
785 	returns the Statement that produced this ResultSet object. If the
786 	result set was generated some other way, ... this method returns null.
787 */
788 	m_pImpl->m_xDataSupplier->validate();
789 	return uno::Reference< uno::XInterface >();
790 }
791 
792 //=========================================================================
793 //
794 // XRow methods.
795 //
796 //=========================================================================
797 
798 // virtual
799 sal_Bool SAL_CALL ResultSet::wasNull()
800 	throw( sdbc::SQLException, uno::RuntimeException )
801 {
802 	// This method can not be implemented correctly!!! Imagine different
803 	// threads doing a getXYZ - wasNull calling sequence on the same
804 	// implementation object...
805 
806 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
807 	{
808 		uno::Reference< sdbc::XRow > xValues
809 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
810 														m_pImpl->m_nPos - 1 );
811 		if ( xValues.is() )
812 		{
813 			m_pImpl->m_xDataSupplier->validate();
814 			return xValues->wasNull();
815 		}
816 	}
817 
818 	m_pImpl->m_xDataSupplier->validate();
819 	return m_pImpl->m_bWasNull;
820 }
821 
822 //=========================================================================
823 // virtual
824 rtl::OUString SAL_CALL ResultSet::getString( sal_Int32 columnIndex )
825 	throw( sdbc::SQLException, uno::RuntimeException )
826 {
827 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
828 	{
829 		uno::Reference< sdbc::XRow > xValues
830 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
831 														m_pImpl->m_nPos - 1 );
832 		if ( xValues.is() )
833 		{
834 			m_pImpl->m_bWasNull = sal_False;
835 			m_pImpl->m_xDataSupplier->validate();
836 			return xValues->getString( columnIndex );
837 		}
838 	}
839 
840 	m_pImpl->m_bWasNull = sal_True;
841 	m_pImpl->m_xDataSupplier->validate();
842 	return rtl::OUString();
843 }
844 
845 //=========================================================================
846 // virtual
847 sal_Bool SAL_CALL ResultSet::getBoolean( sal_Int32 columnIndex )
848 	throw( sdbc::SQLException, uno::RuntimeException )
849 {
850 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
851 	{
852 		uno::Reference< sdbc::XRow > xValues
853 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
854 														m_pImpl->m_nPos - 1 );
855 		if ( xValues.is() )
856 		{
857 			m_pImpl->m_bWasNull = sal_False;
858 			m_pImpl->m_xDataSupplier->validate();
859 			return xValues->getBoolean( columnIndex );
860 		}
861 	}
862 
863 	m_pImpl->m_bWasNull = sal_True;
864 	m_pImpl->m_xDataSupplier->validate();
865 	return sal_False;
866 }
867 
868 //=========================================================================
869 // virtual
870 sal_Int8 SAL_CALL ResultSet::getByte( sal_Int32 columnIndex )
871 	throw( sdbc::SQLException, uno::RuntimeException )
872 {
873 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
874 	{
875 		uno::Reference< sdbc::XRow > xValues
876 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
877 														m_pImpl->m_nPos - 1 );
878 		if ( xValues.is() )
879 		{
880 			m_pImpl->m_bWasNull = sal_False;
881 			m_pImpl->m_xDataSupplier->validate();
882 			return xValues->getByte( columnIndex );
883 		}
884 	}
885 
886 	m_pImpl->m_bWasNull = sal_True;
887 	m_pImpl->m_xDataSupplier->validate();
888 	return 0;
889 }
890 
891 //=========================================================================
892 // virtual
893 sal_Int16 SAL_CALL ResultSet::getShort( sal_Int32 columnIndex )
894 	throw( sdbc::SQLException, uno::RuntimeException )
895 {
896 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
897 	{
898 		uno::Reference< sdbc::XRow > xValues
899 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
900 														m_pImpl->m_nPos - 1 );
901 		if ( xValues.is() )
902 		{
903 			m_pImpl->m_bWasNull = sal_False;
904 			m_pImpl->m_xDataSupplier->validate();
905 			return xValues->getShort( columnIndex );
906 		}
907 	}
908 
909 	m_pImpl->m_bWasNull = sal_True;
910 	m_pImpl->m_xDataSupplier->validate();
911 	return 0;
912 }
913 
914 //=========================================================================
915 // virtual
916 sal_Int32 SAL_CALL ResultSet::getInt( sal_Int32 columnIndex )
917 	throw( sdbc::SQLException, uno::RuntimeException )
918 {
919 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
920 	{
921 		uno::Reference< sdbc::XRow > xValues
922 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
923 														m_pImpl->m_nPos - 1 );
924 		if ( xValues.is() )
925 		{
926 			m_pImpl->m_bWasNull = sal_False;
927 			m_pImpl->m_xDataSupplier->validate();
928 			return xValues->getInt( columnIndex );
929 		}
930 	}
931 
932 	m_pImpl->m_bWasNull = sal_True;
933 	m_pImpl->m_xDataSupplier->validate();
934 	return 0;
935 }
936 
937 //=========================================================================
938 // virtual
939 sal_Int64 SAL_CALL ResultSet::getLong( sal_Int32 columnIndex )
940 	throw( sdbc::SQLException, uno::RuntimeException )
941 {
942 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
943 	{
944 		uno::Reference< sdbc::XRow > xValues
945 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
946 														m_pImpl->m_nPos - 1 );
947 		if ( xValues.is() )
948 		{
949 			m_pImpl->m_bWasNull = sal_False;
950 			m_pImpl->m_xDataSupplier->validate();
951 			return xValues->getLong( columnIndex );
952 		}
953 	}
954 
955 	m_pImpl->m_bWasNull = sal_True;
956 	m_pImpl->m_xDataSupplier->validate();
957 	return 0;
958 }
959 
960 //=========================================================================
961 // virtual
962 float SAL_CALL ResultSet::getFloat( sal_Int32 columnIndex )
963 	throw( sdbc::SQLException, uno::RuntimeException )
964 {
965 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
966 	{
967 		uno::Reference< sdbc::XRow > xValues
968 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
969 														m_pImpl->m_nPos - 1 );
970 		if ( xValues.is() )
971 		{
972 			m_pImpl->m_bWasNull = sal_False;
973 			m_pImpl->m_xDataSupplier->validate();
974 			return xValues->getFloat( columnIndex );
975 		}
976 	}
977 
978 	m_pImpl->m_bWasNull = sal_True;
979 	m_pImpl->m_xDataSupplier->validate();
980 	return 0;
981 }
982 
983 //=========================================================================
984 // virtual
985 double SAL_CALL ResultSet::getDouble( sal_Int32 columnIndex )
986 	throw( sdbc::SQLException, uno::RuntimeException )
987 {
988 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
989 	{
990 		uno::Reference< sdbc::XRow > xValues
991 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
992 														m_pImpl->m_nPos - 1 );
993 		if ( xValues.is() )
994 		{
995 			m_pImpl->m_bWasNull = sal_False;
996 			m_pImpl->m_xDataSupplier->validate();
997 			return xValues->getDouble( columnIndex );
998 		}
999 	}
1000 
1001 	m_pImpl->m_bWasNull = sal_True;
1002 	m_pImpl->m_xDataSupplier->validate();
1003 	return 0;
1004 }
1005 
1006 //=========================================================================
1007 // virtual
1008 uno::Sequence< sal_Int8 > SAL_CALL
1009 ResultSet::getBytes( sal_Int32 columnIndex )
1010 	throw( sdbc::SQLException, uno::RuntimeException )
1011 {
1012 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1013 	{
1014 		uno::Reference< sdbc::XRow > xValues
1015 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1016 														m_pImpl->m_nPos - 1 );
1017 		if ( xValues.is() )
1018 		{
1019 			m_pImpl->m_bWasNull = sal_False;
1020 			m_pImpl->m_xDataSupplier->validate();
1021 			return xValues->getBytes( columnIndex );
1022 		}
1023 	}
1024 
1025 	m_pImpl->m_bWasNull = sal_True;
1026 	m_pImpl->m_xDataSupplier->validate();
1027 	return uno::Sequence< sal_Int8 >();
1028 }
1029 
1030 //=========================================================================
1031 // virtual
1032 util::Date SAL_CALL ResultSet::getDate( sal_Int32 columnIndex )
1033 	throw( sdbc::SQLException, uno::RuntimeException )
1034 {
1035 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1036 	{
1037 		uno::Reference< sdbc::XRow > xValues
1038 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1039 														m_pImpl->m_nPos - 1 );
1040 		if ( xValues.is() )
1041 		{
1042 			m_pImpl->m_bWasNull = sal_False;
1043 			m_pImpl->m_xDataSupplier->validate();
1044 			return xValues->getDate( columnIndex );
1045 		}
1046 	}
1047 
1048 	m_pImpl->m_bWasNull = sal_True;
1049 	m_pImpl->m_xDataSupplier->validate();
1050 	return util::Date();
1051 }
1052 
1053 //=========================================================================
1054 // virtual
1055 util::Time SAL_CALL ResultSet::getTime( sal_Int32 columnIndex )
1056 	throw( sdbc::SQLException, uno::RuntimeException )
1057 {
1058 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1059 	{
1060 		uno::Reference< sdbc::XRow > xValues
1061 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1062 														m_pImpl->m_nPos - 1 );
1063 		if ( xValues.is() )
1064 		{
1065 			m_pImpl->m_bWasNull = sal_False;
1066 			m_pImpl->m_xDataSupplier->validate();
1067 			return xValues->getTime( columnIndex );
1068 		}
1069 	}
1070 
1071 	m_pImpl->m_bWasNull = sal_True;
1072 	m_pImpl->m_xDataSupplier->validate();
1073 	return util::Time();
1074 }
1075 
1076 //=========================================================================
1077 // virtual
1078 util::DateTime SAL_CALL
1079 ResultSet::getTimestamp( sal_Int32 columnIndex )
1080 	throw( sdbc::SQLException, uno::RuntimeException )
1081 {
1082 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1083 	{
1084 		uno::Reference< sdbc::XRow > xValues
1085 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1086 														m_pImpl->m_nPos - 1 );
1087 		if ( xValues.is() )
1088 		{
1089 			m_pImpl->m_bWasNull = sal_False;
1090 			m_pImpl->m_xDataSupplier->validate();
1091 			return xValues->getTimestamp( columnIndex );
1092 		}
1093 	}
1094 
1095 	m_pImpl->m_bWasNull = sal_True;
1096 	m_pImpl->m_xDataSupplier->validate();
1097 	return util::DateTime();
1098 }
1099 
1100 //=========================================================================
1101 // virtual
1102 uno::Reference< io::XInputStream > SAL_CALL
1103 ResultSet::getBinaryStream( sal_Int32 columnIndex )
1104 	throw( sdbc::SQLException, uno::RuntimeException )
1105 {
1106 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1107 	{
1108 		uno::Reference< sdbc::XRow > xValues
1109 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1110 														m_pImpl->m_nPos - 1 );
1111 		if ( xValues.is() )
1112 		{
1113 			m_pImpl->m_bWasNull = sal_False;
1114 			m_pImpl->m_xDataSupplier->validate();
1115 			return xValues->getBinaryStream( columnIndex );
1116 		}
1117 	}
1118 
1119 	m_pImpl->m_bWasNull = sal_True;
1120 	m_pImpl->m_xDataSupplier->validate();
1121 	return uno::Reference< io::XInputStream >();
1122 }
1123 
1124 //=========================================================================
1125 // virtual
1126 uno::Reference< io::XInputStream > SAL_CALL
1127 ResultSet::getCharacterStream( sal_Int32 columnIndex )
1128 	throw( sdbc::SQLException, uno::RuntimeException )
1129 {
1130 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1131 	{
1132 		uno::Reference< sdbc::XRow > xValues
1133 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1134 														m_pImpl->m_nPos - 1 );
1135 		if ( xValues.is() )
1136 		{
1137 			m_pImpl->m_bWasNull = sal_False;
1138 			m_pImpl->m_xDataSupplier->validate();
1139 			return xValues->getCharacterStream( columnIndex );
1140 		}
1141 	}
1142 
1143 	m_pImpl->m_bWasNull = sal_True;
1144 	m_pImpl->m_xDataSupplier->validate();
1145 	return uno::Reference< io::XInputStream >();
1146 }
1147 
1148 //=========================================================================
1149 // virtual
1150 uno::Any SAL_CALL ResultSet::getObject(
1151         sal_Int32 columnIndex,
1152         const uno::Reference< container::XNameAccess >& typeMap )
1153 	throw( sdbc::SQLException, uno::RuntimeException )
1154 {
1155 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1156 	{
1157 		uno::Reference< sdbc::XRow > xValues
1158 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1159 														m_pImpl->m_nPos - 1 );
1160 		if ( xValues.is() )
1161 		{
1162 			m_pImpl->m_bWasNull = sal_False;
1163 			m_pImpl->m_xDataSupplier->validate();
1164 			return xValues->getObject( columnIndex, typeMap );
1165 		}
1166 	}
1167 
1168 	m_pImpl->m_bWasNull = sal_True;
1169 	m_pImpl->m_xDataSupplier->validate();
1170 	return uno::Any();
1171 }
1172 
1173 //=========================================================================
1174 // virtual
1175 uno::Reference< sdbc::XRef > SAL_CALL
1176 ResultSet::getRef( sal_Int32 columnIndex )
1177 	throw( sdbc::SQLException, uno::RuntimeException )
1178 {
1179 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1180 	{
1181 		uno::Reference< sdbc::XRow > xValues
1182 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1183 														m_pImpl->m_nPos - 1 );
1184 		if ( xValues.is() )
1185 		{
1186 			m_pImpl->m_bWasNull = sal_False;
1187 			m_pImpl->m_xDataSupplier->validate();
1188 			return xValues->getRef( columnIndex );
1189 		}
1190 	}
1191 
1192 	m_pImpl->m_bWasNull = sal_True;
1193 	m_pImpl->m_xDataSupplier->validate();
1194 	return uno::Reference< sdbc::XRef >();
1195 }
1196 
1197 //=========================================================================
1198 // virtual
1199 uno::Reference< sdbc::XBlob > SAL_CALL
1200 ResultSet::getBlob( sal_Int32 columnIndex )
1201 	throw( sdbc::SQLException, uno::RuntimeException )
1202 {
1203 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1204 	{
1205 		uno::Reference< sdbc::XRow > xValues
1206 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1207 														m_pImpl->m_nPos - 1 );
1208 		if ( xValues.is() )
1209 		{
1210 			m_pImpl->m_bWasNull = sal_False;
1211 			m_pImpl->m_xDataSupplier->validate();
1212 			return xValues->getBlob( columnIndex );
1213 		}
1214 	}
1215 
1216 	m_pImpl->m_bWasNull = sal_True;
1217 	m_pImpl->m_xDataSupplier->validate();
1218 	return uno::Reference< sdbc::XBlob >();
1219 }
1220 
1221 //=========================================================================
1222 // virtual
1223 uno::Reference< sdbc::XClob > SAL_CALL
1224 ResultSet::getClob( sal_Int32 columnIndex )
1225 	throw( sdbc::SQLException, uno::RuntimeException )
1226 {
1227 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1228 	{
1229 		uno::Reference< sdbc::XRow > xValues
1230 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1231 														m_pImpl->m_nPos - 1 );
1232 		if ( xValues.is() )
1233 		{
1234 			m_pImpl->m_bWasNull = sal_False;
1235 			m_pImpl->m_xDataSupplier->validate();
1236 			return xValues->getClob( columnIndex );
1237 		}
1238 	}
1239 
1240 	m_pImpl->m_bWasNull = sal_True;
1241 	m_pImpl->m_xDataSupplier->validate();
1242 	return uno::Reference< sdbc::XClob >();
1243 }
1244 
1245 //=========================================================================
1246 // virtual
1247 uno::Reference< sdbc::XArray > SAL_CALL
1248 ResultSet::getArray( sal_Int32 columnIndex )
1249 	throw( sdbc::SQLException, uno::RuntimeException )
1250 {
1251 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1252 	{
1253 		uno::Reference< sdbc::XRow > xValues
1254 			= m_pImpl->m_xDataSupplier->queryPropertyValues(
1255 														m_pImpl->m_nPos - 1 );
1256 		if ( xValues.is() )
1257 		{
1258 			m_pImpl->m_bWasNull = sal_False;
1259 			m_pImpl->m_xDataSupplier->validate();
1260 			return xValues->getArray( columnIndex );
1261 		}
1262 	}
1263 
1264 	m_pImpl->m_bWasNull = sal_True;
1265 	m_pImpl->m_xDataSupplier->validate();
1266 	return uno::Reference< sdbc::XArray >();
1267 }
1268 
1269 //=========================================================================
1270 //
1271 // XCloseable methods.
1272 //
1273 //=========================================================================
1274 
1275 // virtual
1276 void SAL_CALL ResultSet::close()
1277 	throw( sdbc::SQLException, uno::RuntimeException )
1278 {
1279 	m_pImpl->m_xDataSupplier->close();
1280 	m_pImpl->m_xDataSupplier->validate();
1281 }
1282 
1283 //=========================================================================
1284 //
1285 // XContentAccess methods.
1286 //
1287 //=========================================================================
1288 
1289 // virtual
1290 rtl::OUString SAL_CALL ResultSet::queryContentIdentifierString()
1291 	throw( uno::RuntimeException )
1292 {
1293 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1294 		return m_pImpl->m_xDataSupplier->queryContentIdentifierString(
1295 														m_pImpl->m_nPos - 1 );
1296 
1297 	return rtl::OUString();
1298 }
1299 
1300 //=========================================================================
1301 // virtual
1302 uno::Reference< com::sun::star::ucb::XContentIdentifier > SAL_CALL
1303 ResultSet::queryContentIdentifier()
1304 	throw( uno::RuntimeException )
1305 {
1306 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1307 		return m_pImpl->m_xDataSupplier->queryContentIdentifier(
1308 														m_pImpl->m_nPos - 1 );
1309 
1310 	return uno::Reference< com::sun::star::ucb::XContentIdentifier >();
1311 }
1312 
1313 //=========================================================================
1314 // virtual
1315 uno::Reference< com::sun::star::ucb::XContent > SAL_CALL
1316 ResultSet::queryContent()
1317 	throw( uno::RuntimeException )
1318 {
1319 	if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
1320 		return m_pImpl->m_xDataSupplier->queryContent( m_pImpl->m_nPos - 1 );
1321 
1322 	return uno::Reference< com::sun::star::ucb::XContent >();
1323 }
1324 
1325 //=========================================================================
1326 //
1327 // XPropertySet methods.
1328 //
1329 //=========================================================================
1330 
1331 // virtual
1332 uno::Reference< beans::XPropertySetInfo > SAL_CALL
1333 ResultSet::getPropertySetInfo()
1334 	throw( uno::RuntimeException )
1335 {
1336 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1337 
1338 	if ( !m_pImpl->m_xPropSetInfo.is() )
1339 		m_pImpl->m_xPropSetInfo
1340 			= new PropertySetInfo( m_pImpl->m_xSMgr,
1341 								   aPropertyTable,
1342 								   RESULTSET_PROPERTY_COUNT );
1343 	return m_pImpl->m_xPropSetInfo;
1344 }
1345 
1346 //=========================================================================
1347 // virtual
1348 void SAL_CALL ResultSet::setPropertyValue( const rtl::OUString& aPropertyName,
1349 										   const uno::Any& )
1350 	throw( beans::UnknownPropertyException,
1351 		   beans::PropertyVetoException,
1352 		   lang::IllegalArgumentException,
1353 		   lang::WrappedTargetException,
1354 		   uno::RuntimeException )
1355 {
1356 	if ( !aPropertyName.getLength() )
1357 		throw beans::UnknownPropertyException();
1358 
1359 	if ( aPropertyName.equals(
1360 				rtl::OUString::createFromAscii( "RowCount" ) ) )
1361 	{
1362 		// property is read-only.
1363 		throw lang::IllegalArgumentException();
1364 	}
1365 	else if ( aPropertyName.equals(
1366 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1367 	{
1368 		// property is read-only.
1369 		throw lang::IllegalArgumentException();
1370 	}
1371 	else
1372 	{
1373 		throw beans::UnknownPropertyException();
1374 	}
1375 }
1376 
1377 //=========================================================================
1378 // virtual
1379 uno::Any SAL_CALL ResultSet::getPropertyValue(
1380         const rtl::OUString& PropertyName )
1381 	throw( beans::UnknownPropertyException,
1382 		   lang::WrappedTargetException,
1383 		   uno::RuntimeException )
1384 {
1385 	if ( !PropertyName.getLength() )
1386 		throw beans::UnknownPropertyException();
1387 
1388 	uno::Any aValue;
1389 
1390 	if ( PropertyName.equals(
1391 				rtl::OUString::createFromAscii( "RowCount" ) ) )
1392 	{
1393 		aValue <<= m_pImpl->m_xDataSupplier->currentCount();
1394 	}
1395 	else if ( PropertyName.equals(
1396 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1397 	{
1398 		aValue <<= m_pImpl->m_xDataSupplier->isCountFinal();
1399 	}
1400 	else
1401 	{
1402 		throw beans::UnknownPropertyException();
1403 	}
1404 
1405 	return aValue;
1406 }
1407 
1408 //=========================================================================
1409 // virtual
1410 void SAL_CALL ResultSet::addPropertyChangeListener(
1411         const rtl::OUString& aPropertyName,
1412         const uno::Reference< beans::XPropertyChangeListener >& xListener )
1413 	throw( beans::UnknownPropertyException,
1414 		   lang::WrappedTargetException,
1415 		   uno::RuntimeException )
1416 {
1417 	// Note: An empty property name means a listener for "all" properties.
1418 
1419 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1420 
1421 	if ( aPropertyName.getLength() &&
1422 	     !aPropertyName.equals(
1423 				rtl::OUString::createFromAscii( "RowCount" ) ) &&
1424 		 !aPropertyName.equals(
1425 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1426 		throw beans::UnknownPropertyException();
1427 
1428 	if ( !m_pImpl->m_pPropertyChangeListeners )
1429 		m_pImpl->m_pPropertyChangeListeners
1430 			= new PropertyChangeListeners( m_pImpl->m_aMutex );
1431 
1432 	m_pImpl->m_pPropertyChangeListeners->addInterface(
1433 												aPropertyName, xListener );
1434 }
1435 
1436 //=========================================================================
1437 // virtual
1438 void SAL_CALL ResultSet::removePropertyChangeListener(
1439         const rtl::OUString& aPropertyName,
1440 		const uno::Reference< beans::XPropertyChangeListener >& xListener )
1441 	throw( beans::UnknownPropertyException,
1442 		   lang::WrappedTargetException,
1443 		   uno::RuntimeException )
1444 {
1445 	osl::MutexGuard aGuard( m_pImpl->m_aMutex );
1446 
1447 	if ( aPropertyName.getLength() &&
1448 	     !aPropertyName.equals(
1449 				rtl::OUString::createFromAscii( "RowCount" ) ) &&
1450 		 !aPropertyName.equals(
1451 				rtl::OUString::createFromAscii( "IsRowCountFinal" ) ) )
1452 		throw beans::UnknownPropertyException();
1453 
1454 	if ( m_pImpl->m_pPropertyChangeListeners )
1455 		m_pImpl->m_pPropertyChangeListeners->removeInterface(
1456 													aPropertyName, xListener );
1457 
1458 }
1459 
1460 //=========================================================================
1461 // virtual
1462 void SAL_CALL ResultSet::addVetoableChangeListener(
1463         const rtl::OUString&,
1464         const uno::Reference< beans::XVetoableChangeListener >& )
1465 	throw( beans::UnknownPropertyException,
1466 		   lang::WrappedTargetException,
1467 		   uno::RuntimeException )
1468 {
1469 	//	No constrained props, at the moment.
1470 }
1471 
1472 //=========================================================================
1473 // virtual
1474 void SAL_CALL ResultSet::removeVetoableChangeListener(
1475         const rtl::OUString&,
1476         const uno::Reference< beans::XVetoableChangeListener >& )
1477 	throw( beans::UnknownPropertyException,
1478 		   lang::WrappedTargetException,
1479 		   uno::RuntimeException )
1480 {
1481 	//	No constrained props, at the moment.
1482 }
1483 
1484 //=========================================================================
1485 //
1486 // Non-interface methods.
1487 //
1488 //=========================================================================
1489 
1490 void ResultSet::propertyChanged( const beans::PropertyChangeEvent& rEvt )
1491 {
1492 	if ( !m_pImpl->m_pPropertyChangeListeners )
1493 		return;
1494 
1495 	// Notify listeners interested especially in the changed property.
1496 	cppu::OInterfaceContainerHelper* pPropsContainer
1497 		= m_pImpl->m_pPropertyChangeListeners->getContainer(
1498 														rEvt.PropertyName );
1499 	if ( pPropsContainer )
1500 	{
1501 		cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
1502 		while ( aIter.hasMoreElements() )
1503 		{
1504 			uno::Reference< beans::XPropertyChangeListener > xListener(
1505                 aIter.next(), uno::UNO_QUERY );
1506 			if ( xListener.is() )
1507 				xListener->propertyChange( rEvt );
1508 		}
1509 	}
1510 
1511 	// Notify listeners interested in all properties.
1512 	pPropsContainer
1513 		= m_pImpl->m_pPropertyChangeListeners->getContainer( rtl::OUString() );
1514 	if ( pPropsContainer )
1515 	{
1516 		cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
1517 		while ( aIter.hasMoreElements() )
1518 		{
1519 			uno::Reference< beans::XPropertyChangeListener > xListener(
1520                 aIter.next(), uno::UNO_QUERY );
1521 			if ( xListener.is() )
1522 				xListener->propertyChange( rEvt );
1523 		}
1524 	}
1525 }
1526 
1527 //=========================================================================
1528 void ResultSet::rowCountChanged( sal_uInt32 nOld, sal_uInt32 nNew )
1529 {
1530 	OSL_ENSURE( nOld < nNew, "ResultSet::rowCountChanged - nOld >= nNew!" );
1531 
1532 	if ( !m_pImpl->m_pPropertyChangeListeners )
1533 		return;
1534 
1535 	propertyChanged(
1536 		beans::PropertyChangeEvent(
1537             static_cast< cppu::OWeakObject * >( this ),
1538             rtl::OUString::createFromAscii( "RowCount" ),
1539             sal_False,
1540             1001,
1541             uno::makeAny( nOld ),	  // old value
1542             uno::makeAny( nNew ) ) ); // new value
1543 }
1544 
1545 //=========================================================================
1546 void ResultSet::rowCountFinal()
1547 {
1548 	if ( !m_pImpl->m_pPropertyChangeListeners )
1549 		return;
1550 
1551 	propertyChanged(
1552 		beans::PropertyChangeEvent(
1553             static_cast< cppu::OWeakObject * >( this ),
1554             rtl::OUString::createFromAscii( "IsRowCountFinal" ),
1555             sal_False,
1556             1000,
1557 			uno:: makeAny( sal_False ),	  // old value
1558             uno::makeAny( sal_True ) ) ); // new value
1559 }
1560 
1561 //=========================================================================
1562 const uno::Sequence< beans::Property >&	ResultSet::getProperties()
1563 {
1564 	return m_pImpl->m_aProperties;
1565 }
1566 
1567 //=========================================================================
1568 const uno::Reference< com::sun::star::ucb::XCommandEnvironment >&
1569 ResultSet::getEnvironment()
1570 {
1571 	return m_pImpl->m_xEnv;
1572 }
1573 
1574 } // namespace ucbhelper
1575 
1576 namespace ucbhelper_impl {
1577 
1578 //=========================================================================
1579 //=========================================================================
1580 //
1581 // PropertySetInfo Implementation.
1582 //
1583 //=========================================================================
1584 //=========================================================================
1585 
1586 PropertySetInfo::PropertySetInfo(
1587     const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
1588     const PropertyInfo* pProps,
1589     sal_Int32 nProps )
1590 : m_xSMgr( rxSMgr )
1591 {
1592 	m_pProps = new uno::Sequence< beans::Property >( nProps );
1593 
1594 	if ( nProps )
1595 	{
1596 		const PropertyInfo* pEntry = pProps;
1597 		beans::Property* pProperties = m_pProps->getArray();
1598 
1599 		for ( sal_Int32 n = 0; n < nProps; ++n )
1600 		{
1601 			beans::Property& rProp = pProperties[ n ];
1602 
1603 			rProp.Name		 = rtl::OUString::createFromAscii( pEntry->pName );
1604     		rProp.Handle	 = pEntry->nHandle;
1605     		rProp.Type		 = pEntry->pGetCppuType();
1606     		rProp.Attributes = pEntry->nAttributes;
1607 
1608 			pEntry++;
1609 		}
1610 	}
1611 }
1612 
1613 //=========================================================================
1614 // virtual
1615 PropertySetInfo::~PropertySetInfo()
1616 {
1617 	delete m_pProps;
1618 }
1619 
1620 //=========================================================================
1621 //
1622 // XInterface methods.
1623 //
1624 //=========================================================================
1625 
1626 XINTERFACE_IMPL_2( PropertySetInfo,
1627 				   lang::XTypeProvider,
1628 				   beans::XPropertySetInfo );
1629 
1630 //=========================================================================
1631 //
1632 // XTypeProvider methods.
1633 //
1634 //=========================================================================
1635 
1636 XTYPEPROVIDER_IMPL_2( PropertySetInfo,
1637 				   	  lang::XTypeProvider,
1638 				   	  beans::XPropertySetInfo );
1639 
1640 //=========================================================================
1641 //
1642 // XPropertySetInfo methods.
1643 //
1644 //=========================================================================
1645 
1646 // virtual
1647 uno::Sequence< beans::Property > SAL_CALL PropertySetInfo::getProperties()
1648 	throw( uno::RuntimeException )
1649 {
1650 	return uno::Sequence< beans::Property >( *m_pProps );
1651 }
1652 
1653 //=========================================================================
1654 // virtual
1655 beans::Property SAL_CALL PropertySetInfo::getPropertyByName(
1656         const rtl::OUString& aName )
1657 	throw( beans::UnknownPropertyException, uno::RuntimeException )
1658 {
1659 	beans::Property aProp;
1660 	if ( queryProperty( aName, aProp ) )
1661 		return aProp;
1662 
1663 	throw beans::UnknownPropertyException();
1664 }
1665 
1666 //=========================================================================
1667 // virtual
1668 sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName(
1669         const rtl::OUString& Name )
1670 	throw( uno::RuntimeException )
1671 {
1672 	beans::Property aProp;
1673 	return queryProperty( Name, aProp );
1674 }
1675 
1676 //=========================================================================
1677 sal_Bool PropertySetInfo::queryProperty(
1678     const rtl::OUString& aName, beans::Property& rProp )
1679 {
1680 	sal_Int32 nCount = m_pProps->getLength();
1681 	const beans::Property* pProps = m_pProps->getConstArray();
1682 	for ( sal_Int32 n = 0; n < nCount; ++n )
1683 	{
1684 		const beans::Property& rCurr = pProps[ n ];
1685 		if ( rCurr.Name == aName )
1686 		{
1687 			rProp = rCurr;
1688 			return sal_True;
1689 		}
1690 	}
1691 
1692 	return sal_False;
1693 }
1694 
1695 } // namespace ucbhelper_impl
1696