xref: /trunk/main/ucbhelper/source/provider/resultset.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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