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