xref: /AOO41X/main/ucb/source/cacher/cachedcontentresultset.cxx (revision 2f86921c33504fdff5a030df6c0b258927045abb)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26 
27 #include <cachedcontentresultset.hxx>
28 #include <com/sun/star/sdbc/FetchDirection.hpp>
29 #include <com/sun/star/ucb/FetchError.hpp>
30 #include <com/sun/star/ucb/ResultSetException.hpp>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/script/XTypeConverter.hpp>
33 #include <com/sun/star/sdbc/ResultSetType.hpp>
34 #include <rtl/ustring.hxx>
35 #include <osl/diagnose.h>
36 
37 using namespace com::sun::star::beans;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::script;
40 using namespace com::sun::star::sdbc;
41 using namespace com::sun::star::ucb;
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::util;
44 using namespace cppu;
45 using namespace rtl;
46 
47 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE 256
48 #define COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION FetchDirection::FORWARD
49 
50 //--------------------------------------------------------------------------
51 //--------------------------------------------------------------------------
52 //define for getXXX methods of interface XRow
53 //--------------------------------------------------------------------------
54 //--------------------------------------------------------------------------
55 
56 //if you change this macro please pay attention to
57 //function ::getObject, where this is similar implemented
58 
59 #define XROW_GETXXX( getXXX, Type )                     \
60 impl_EnsureNotDisposed();                               \
61 ReacquireableGuard aGuard( m_aMutex );                  \
62 sal_Int32 nRow = m_nRow;                                \
63 sal_Int32 nFetchSize = m_nFetchSize;                    \
64 sal_Int32 nFetchDirection = m_nFetchDirection;          \
65 if( !m_aCache.hasRow( nRow ) )                          \
66 {                                                       \
67     if( !m_aCache.hasCausedException( nRow ) )          \
68 {                                                       \
69         if( !m_xFetchProvider.is() )                    \
70         {                                               \
71             OSL_ENSURE( sal_False, "broadcaster was disposed already" );    \
72             throw SQLException();                       \
73         }                                               \
74         aGuard.clear();                                 \
75         if( impl_isForwardOnly() )                      \
76             applyPositionToOrigin( nRow );              \
77                                                         \
78         impl_fetchData( nRow, nFetchSize, nFetchDirection ); \
79     }                                                   \
80     aGuard.reacquire();                                 \
81     if( !m_aCache.hasRow( nRow ) )                      \
82     {                                                   \
83         m_bLastReadWasFromCache = sal_False;            \
84         aGuard.clear();                                 \
85         applyPositionToOrigin( nRow );                  \
86         impl_init_xRowOrigin();                         \
87         return m_xRowOrigin->getXXX( columnIndex );     \
88     }                                                   \
89 }                                                       \
90 const Any& rValue = m_aCache.getAny( nRow, columnIndex );\
91 Type aRet = Type();                                     \
92 m_bLastReadWasFromCache = sal_True;                     \
93 m_bLastCachedReadWasNull = !( rValue >>= aRet );        \
94 /* Last chance. Try type converter service... */        \
95 if ( m_bLastCachedReadWasNull && rValue.hasValue() )    \
96 {                                                       \
97     Reference< XTypeConverter > xConverter              \
98                                 = getTypeConverter();   \
99     if ( xConverter.is() )                              \
100     {                                                   \
101         try                                             \
102         {                                               \
103             Any aConvAny = xConverter->convertTo(       \
104                 rValue,                                 \
105                 getCppuType( static_cast<               \
106                     const Type * >( 0 ) ) );            \
107             m_bLastCachedReadWasNull = !( aConvAny >>= aRet ); \
108         }                                               \
109         catch ( IllegalArgumentException )              \
110         {                                               \
111         }                                               \
112         catch ( CannotConvertException )                \
113         {                                               \
114         }                                               \
115     }                                                   \
116 }                                                       \
117 return aRet;
118 
119 //--------------------------------------------------------------------------
120 //--------------------------------------------------------------------------
121 // CCRS_Cache methoeds.
122 //--------------------------------------------------------------------------
123 //--------------------------------------------------------------------------
124 
CCRS_Cache(const Reference<XContentIdentifierMapping> & xMapping)125 CachedContentResultSet::CCRS_Cache::CCRS_Cache(
126     const Reference< XContentIdentifierMapping > & xMapping )
127     : m_pResult( NULL )
128     , m_xContentIdentifierMapping( xMapping )
129     , m_pMappedReminder( NULL )
130 {
131 }
132 
~CCRS_Cache()133 CachedContentResultSet::CCRS_Cache::~CCRS_Cache()
134 {
135     delete m_pResult;
136 }
137 
138 void SAL_CALL CachedContentResultSet::CCRS_Cache
clear()139     ::clear()
140 {
141     if( m_pResult )
142     {
143         delete m_pResult;
144         m_pResult = NULL;
145     }
146     clearMappedReminder();
147 }
148 
149 void SAL_CALL CachedContentResultSet::CCRS_Cache
loadData(const FetchResult & rResult)150     ::loadData( const FetchResult& rResult )
151 {
152     clear();
153     m_pResult = new FetchResult( rResult );
154 }
155 
156 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
hasRow(sal_Int32 row)157     ::hasRow( sal_Int32 row )
158 {
159     if( !m_pResult )
160         return sal_False;
161     long nStart = m_pResult->StartIndex;
162     long nEnd = nStart;
163     if( m_pResult->Orientation )
164         nEnd += m_pResult->Rows.getLength() - 1;
165     else
166         nStart -= m_pResult->Rows.getLength() + 1;
167 
168     return nStart <= row && row <= nEnd;
169 }
170 
171 sal_Int32 SAL_CALL CachedContentResultSet::CCRS_Cache
getMaxRow()172     ::getMaxRow()
173 {
174     if( !m_pResult )
175         return 0;
176     long nEnd = m_pResult->StartIndex;
177     if( m_pResult->Orientation )
178         return nEnd += m_pResult->Rows.getLength() - 1;
179     else
180         return nEnd;
181 }
182 
183 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
hasKnownLast()184     ::hasKnownLast()
185 {
186     if( !m_pResult )
187         return sal_False;
188 
189     if( ( m_pResult->FetchError & FetchError::ENDOFDATA )
190         && m_pResult->Orientation
191         && m_pResult->Rows.getLength() )
192         return sal_True;
193 
194     return sal_False;
195 }
196 
197 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
hasCausedException(sal_Int32 nRow)198     ::hasCausedException( sal_Int32 nRow )
199 {
200     if( !m_pResult )
201         return sal_False;
202     if( !( m_pResult->FetchError & FetchError::EXCEPTION ) )
203         return sal_False;
204 
205     long nEnd = m_pResult->StartIndex;
206     if( m_pResult->Orientation )
207         nEnd += m_pResult->Rows.getLength();
208 
209     return nRow == nEnd+1;
210 }
211 
212 Any& SAL_CALL CachedContentResultSet::CCRS_Cache
getRowAny(sal_Int32 nRow)213     ::getRowAny( sal_Int32 nRow )
214     throw( SQLException,
215     RuntimeException )
216 {
217     if( !nRow )
218         throw SQLException();
219     if( !m_pResult )
220         throw SQLException();
221     if( !hasRow( nRow ) )
222         throw SQLException();
223 
224     long nDiff = nRow - m_pResult->StartIndex;
225     if( nDiff < 0 )
226         nDiff *= -1;
227 
228     return (m_pResult->Rows)[nDiff];
229 }
230 
231 void SAL_CALL CachedContentResultSet::CCRS_Cache
remindMapped(sal_Int32 nRow)232     ::remindMapped( sal_Int32 nRow )
233 {
234     //remind that this row was mapped
235     if( !m_pResult )
236         return;
237     long nDiff = nRow - m_pResult->StartIndex;
238     if( nDiff < 0 )
239         nDiff *= -1;
240     Sequence< sal_Bool >* pMappedReminder = getMappedReminder();
241     if( nDiff < pMappedReminder->getLength() )
242         (*pMappedReminder)[nDiff] = sal_True;
243 }
244 
245 sal_Bool SAL_CALL CachedContentResultSet::CCRS_Cache
isRowMapped(sal_Int32 nRow)246     ::isRowMapped( sal_Int32 nRow )
247 {
248     if( !m_pMappedReminder || !m_pResult )
249         return sal_False;
250     long nDiff = nRow - m_pResult->StartIndex;
251     if( nDiff < 0 )
252         nDiff *= -1;
253     if( nDiff < m_pMappedReminder->getLength() )
254         return (*m_pMappedReminder)[nDiff];
255     return sal_False;
256 }
257 
258 void SAL_CALL CachedContentResultSet::CCRS_Cache
clearMappedReminder()259     ::clearMappedReminder()
260 {
261     delete m_pMappedReminder;
262     m_pMappedReminder = NULL;
263 }
264 
265 Sequence< sal_Bool >* SAL_CALL CachedContentResultSet::CCRS_Cache
getMappedReminder()266     ::getMappedReminder()
267 {
268     if( !m_pMappedReminder )
269     {
270         sal_Int32 nCount = m_pResult->Rows.getLength();
271         m_pMappedReminder = new Sequence< sal_Bool >( nCount );
272         for( ;nCount; nCount-- )
273             (*m_pMappedReminder)[nCount] = sal_False;
274     }
275     return m_pMappedReminder;
276 }
277 
278 const Any& SAL_CALL CachedContentResultSet::CCRS_Cache
getAny(sal_Int32 nRow,sal_Int32 nColumnIndex)279     ::getAny( sal_Int32 nRow, sal_Int32 nColumnIndex )
280     throw( SQLException,
281     RuntimeException )
282 {
283     if( !nColumnIndex )
284         throw SQLException();
285     if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
286     {
287         Any& rRow = getRowAny( nRow );
288         Sequence< Any > aValue;
289         rRow >>= aValue;
290         if( m_xContentIdentifierMapping->mapRow( aValue ) )
291         {
292             rRow <<= aValue;
293             remindMapped( nRow );
294         }
295         else
296             m_xContentIdentifierMapping.clear();
297     }
298     const Sequence< Any >& rRow =
299         (* reinterpret_cast< const Sequence< Any > * >
300         (getRowAny( nRow ).getValue() ));
301 
302     if( nColumnIndex > rRow.getLength() )
303         throw SQLException();
304     return rRow[nColumnIndex-1];
305 }
306 
307 const rtl::OUString& SAL_CALL CachedContentResultSet::CCRS_Cache
getContentIdentifierString(sal_Int32 nRow)308     ::getContentIdentifierString( sal_Int32 nRow )
309     throw( com::sun::star::uno::RuntimeException )
310 {
311     try
312     {
313         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
314         {
315             Any& rRow = getRowAny( nRow );
316             rtl::OUString aValue;
317             rRow >>= aValue;
318             rRow <<= m_xContentIdentifierMapping->mapContentIdentifierString( aValue );
319             remindMapped( nRow );
320         }
321         return (* reinterpret_cast< const rtl::OUString * >
322                 (getRowAny( nRow ).getValue() ));
323     }
324     catch( SQLException )
325     {
326         throw RuntimeException();
327     }
328 }
329 
330 const Reference< XContentIdentifier >& SAL_CALL CachedContentResultSet::CCRS_Cache
getContentIdentifier(sal_Int32 nRow)331     ::getContentIdentifier( sal_Int32 nRow )
332     throw( com::sun::star::uno::RuntimeException )
333 {
334     try
335     {
336         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
337         {
338             Any& rRow = getRowAny( nRow );
339             Reference< XContentIdentifier > aValue;
340             rRow >>= aValue;
341             rRow <<= m_xContentIdentifierMapping->mapContentIdentifier( aValue );
342             remindMapped( nRow );
343         }
344         return (* reinterpret_cast< const Reference< XContentIdentifier > * >
345                 (getRowAny( nRow ).getValue() ));
346     }
347     catch( SQLException )
348     {
349         throw RuntimeException();
350     }
351 }
352 
353 const Reference< XContent >& SAL_CALL CachedContentResultSet::CCRS_Cache
getContent(sal_Int32 nRow)354     ::getContent( sal_Int32 nRow )
355     throw( com::sun::star::uno::RuntimeException )
356 {
357     try
358     {
359         if( m_xContentIdentifierMapping.is() && !isRowMapped( nRow ) )
360         {
361             Any& rRow = getRowAny( nRow );
362             Reference< XContent > aValue;
363             rRow >>= aValue;
364             rRow <<= m_xContentIdentifierMapping->mapContent( aValue );
365             remindMapped( nRow );
366         }
367         return (* reinterpret_cast< const Reference< XContent > * >
368                 (getRowAny( nRow ).getValue() ));
369     }
370     catch( SQLException )
371     {
372         throw RuntimeException();
373     }
374 }
375 
376 //--------------------------------------------------------------------------
377 //--------------------------------------------------------------------------
378 // class CCRS_PropertySetInfo
379 //--------------------------------------------------------------------------
380 //--------------------------------------------------------------------------
381 
382 class CCRS_PropertySetInfo :
383                 public cppu::OWeakObject,
384                 public com::sun::star::lang::XTypeProvider,
385                 public com::sun::star::beans::XPropertySetInfo
386 {
387     friend class CachedContentResultSet;
388 
389     //my Properties
390     Sequence< com::sun::star::beans::Property >*
391                             m_pProperties;
392 
393     //some helping variables ( names for my special properties )
394     static rtl::OUString    m_aPropertyNameForCount;
395     static rtl::OUString    m_aPropertyNameForFinalCount;
396     static rtl::OUString    m_aPropertyNameForFetchSize;
397     static rtl::OUString    m_aPropertyNameForFetchDirection;
398 
399     long                    m_nFetchSizePropertyHandle;
400     long                    m_nFetchDirectionPropertyHandle;
401 
402 private:
403     sal_Int32 SAL_CALL
404     impl_getRemainedHandle() const;
405 
406     sal_Bool SAL_CALL
407     impl_queryProperty(
408             const rtl::OUString& rName
409             , com::sun::star::beans::Property& rProp ) const;
410     sal_Int32 SAL_CALL
411     impl_getPos( const rtl::OUString& rName ) const;
412 
413     static sal_Bool SAL_CALL
414     impl_isMyPropertyName( const rtl::OUString& rName );
415 
416 public:
417     CCRS_PropertySetInfo(   Reference<
418             XPropertySetInfo > xPropertySetInfoOrigin );
419 
420     virtual ~CCRS_PropertySetInfo();
421 
422     // XInterface
423     XINTERFACE_DECL()
424 
425     // XTypeProvider
426     XTYPEPROVIDER_DECL()
427 
428     // XPropertySetInfo
429     virtual Sequence< com::sun::star::beans::Property > SAL_CALL
430     getProperties()
431         throw( RuntimeException );
432 
433     virtual com::sun::star::beans::Property SAL_CALL
434     getPropertyByName( const rtl::OUString& aName )
435         throw( com::sun::star::beans::UnknownPropertyException, RuntimeException );
436 
437     virtual sal_Bool SAL_CALL
438     hasPropertyByName( const rtl::OUString& Name )
439         throw( RuntimeException );
440 };
441 
442 OUString    CCRS_PropertySetInfo::m_aPropertyNameForCount( OUString::createFromAscii( "RowCount" ) );
443 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFinalCount( OUString::createFromAscii( "IsRowCountFinal" ) );
444 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) );
445 OUString    CCRS_PropertySetInfo::m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) );
446 
CCRS_PropertySetInfo(Reference<XPropertySetInfo> xInfo)447 CCRS_PropertySetInfo::CCRS_PropertySetInfo(
448         Reference< XPropertySetInfo > xInfo )
449         : m_pProperties( NULL )
450         , m_nFetchSizePropertyHandle( -1 )
451         , m_nFetchDirectionPropertyHandle( -1 )
452 {
453     //initialize list of properties:
454 
455     // it is required, that the received xInfo contains the two
456     // properties with names 'm_aPropertyNameForCount' and
457     // 'm_aPropertyNameForFinalCount'
458 
459     if( xInfo.is() )
460     {
461         Sequence<Property> aProps = xInfo->getProperties();
462         m_pProperties = new Sequence<Property> ( aProps );
463     }
464     else
465     {
466         OSL_ENSURE( sal_False, "The received XPropertySetInfo doesn't contain required properties" );
467         m_pProperties = new Sequence<Property>;
468     }
469 
470     //ensure, that we haven't got the Properties 'FetchSize' and 'Direction' twice:
471     sal_Int32 nFetchSize = impl_getPos( m_aPropertyNameForFetchSize );
472     sal_Int32 nFetchDirection = impl_getPos( m_aPropertyNameForFetchDirection );
473     sal_Int32 nDeleted = 0;
474     if( nFetchSize != -1 )
475         nDeleted++;
476     if( nFetchDirection != -1 )
477         nDeleted++;
478 
479     Sequence< Property >* pOrigProps = new Sequence<Property> ( *m_pProperties );
480     sal_Int32 nOrigProps = pOrigProps->getLength();
481 
482     m_pProperties->realloc( nOrigProps + 2 - nDeleted );//note that nDeleted is <= 2
483     for( sal_Int32 n = 0, m = 0; n < nOrigProps; n++, m++ )
484     {
485         if( n == nFetchSize || n == nFetchDirection )
486             m--;
487         else
488             (*m_pProperties)[ m ] = (*pOrigProps)[ n ];
489     }
490     {
491         Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted ];
492         rMyProp.Name = m_aPropertyNameForFetchSize;
493         rMyProp.Type = getCppuType( static_cast< const sal_Int32 * >( 0 ) );
494         rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
495 
496         if( nFetchSize != -1 )
497             m_nFetchSizePropertyHandle = (*pOrigProps)[nFetchSize].Handle;
498         else
499             m_nFetchSizePropertyHandle = impl_getRemainedHandle();
500 
501         rMyProp.Handle = m_nFetchSizePropertyHandle;
502 
503     }
504     {
505         Property& rMyProp = (*m_pProperties)[ nOrigProps - nDeleted + 1 ];
506         rMyProp.Name = m_aPropertyNameForFetchDirection;
507         rMyProp.Type = getCppuType( static_cast< const sal_Bool * >( 0 ) );
508         rMyProp.Attributes = PropertyAttribute::BOUND | PropertyAttribute::MAYBEDEFAULT;
509 
510         if( nFetchSize != -1 )
511             m_nFetchDirectionPropertyHandle = (*pOrigProps)[nFetchDirection].Handle;
512         else
513             m_nFetchDirectionPropertyHandle = impl_getRemainedHandle();
514 
515         m_nFetchDirectionPropertyHandle = rMyProp.Handle;
516     }
517     delete pOrigProps;
518 }
519 
~CCRS_PropertySetInfo()520 CCRS_PropertySetInfo::~CCRS_PropertySetInfo()
521 {
522     delete m_pProperties;
523 }
524 
525 //--------------------------------------------------------------------------
526 // XInterface methods.
527 //--------------------------------------------------------------------------
528 //list all interfaces inclusive baseclasses of interfaces
529 XINTERFACE_IMPL_2( CCRS_PropertySetInfo
530                   , XTypeProvider
531                   , XPropertySetInfo
532                   );
533 
534 //--------------------------------------------------------------------------
535 // XTypeProvider methods.
536 //--------------------------------------------------------------------------
537 //list all interfaces exclusive baseclasses
538 XTYPEPROVIDER_IMPL_2( CCRS_PropertySetInfo
539                     , XTypeProvider
540                     , XPropertySetInfo
541                     );
542 //--------------------------------------------------------------------------
543 // XPropertySetInfo methods.
544 //--------------------------------------------------------------------------
545 //virtual
546 Sequence< Property > SAL_CALL CCRS_PropertySetInfo
getProperties()547     ::getProperties() throw( RuntimeException )
548 {
549     return *m_pProperties;
550 }
551 
552 //virtual
553 Property SAL_CALL CCRS_PropertySetInfo
getPropertyByName(const rtl::OUString & aName)554     ::getPropertyByName( const rtl::OUString& aName )
555         throw( UnknownPropertyException, RuntimeException )
556 {
557     if ( !aName.getLength() )
558         throw UnknownPropertyException();
559 
560     Property aProp;
561     if ( impl_queryProperty( aName, aProp ) )
562         return aProp;
563 
564     throw UnknownPropertyException();
565 }
566 
567 //virtual
568 sal_Bool SAL_CALL CCRS_PropertySetInfo
hasPropertyByName(const rtl::OUString & Name)569     ::hasPropertyByName( const rtl::OUString& Name )
570         throw( RuntimeException )
571 {
572     return ( impl_getPos( Name ) != -1 );
573 }
574 
575 //--------------------------------------------------------------------------
576 // impl_ methods.
577 //--------------------------------------------------------------------------
578 
579 sal_Int32 SAL_CALL CCRS_PropertySetInfo
impl_getPos(const OUString & rName) const580             ::impl_getPos( const OUString& rName ) const
581 {
582     for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
583     {
584         const Property& rMyProp = (*m_pProperties)[nN];
585         if( rMyProp.Name == rName )
586             return nN;
587     }
588     return -1;
589 }
590 
591 sal_Bool SAL_CALL CCRS_PropertySetInfo
impl_queryProperty(const OUString & rName,Property & rProp) const592         ::impl_queryProperty( const OUString& rName, Property& rProp ) const
593 {
594     for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
595     {
596         const Property& rMyProp = (*m_pProperties)[nN];
597         if( rMyProp.Name == rName )
598         {
599             rProp.Name = rMyProp.Name;
600             rProp.Handle = rMyProp.Handle;
601             rProp.Type = rMyProp.Type;
602             rProp.Attributes = rMyProp.Attributes;
603 
604             return sal_True;
605         }
606     }
607     return sal_False;
608 }
609 
610 //static
611 sal_Bool SAL_CALL CCRS_PropertySetInfo
impl_isMyPropertyName(const OUString & rPropertyName)612         ::impl_isMyPropertyName( const OUString& rPropertyName )
613 {
614     return ( rPropertyName == m_aPropertyNameForCount
615     || rPropertyName == m_aPropertyNameForFinalCount
616     || rPropertyName == m_aPropertyNameForFetchSize
617     || rPropertyName == m_aPropertyNameForFetchDirection );
618 }
619 
620 sal_Int32 SAL_CALL CCRS_PropertySetInfo
impl_getRemainedHandle() const621             ::impl_getRemainedHandle( ) const
622 {
623     sal_Int32 nHandle = 1;
624 
625     if( !m_pProperties )
626     {
627         OSL_ENSURE( sal_False, "Properties not initialized yet" );
628         return nHandle;
629     }
630     sal_Bool bFound = sal_True;
631     while( bFound )
632     {
633         bFound = sal_False;
634         for( sal_Int32 nN = m_pProperties->getLength(); nN--; )
635         {
636             if( nHandle == (*m_pProperties)[nN].Handle )
637             {
638                 bFound = sal_True;
639                 nHandle++;
640                 break;
641             }
642         }
643     }
644     return nHandle;
645 }
646 
647 //--------------------------------------------------------------------------
648 //--------------------------------------------------------------------------
649 // class CachedContentResultSet
650 //--------------------------------------------------------------------------
651 //--------------------------------------------------------------------------
652 
CachedContentResultSet(const Reference<XMultiServiceFactory> & xSMgr,const Reference<XResultSet> & xOrigin,const Reference<XContentIdentifierMapping> & xContentIdentifierMapping)653 CachedContentResultSet::CachedContentResultSet(
654                   const Reference< XMultiServiceFactory > & xSMgr
655                 , const Reference< XResultSet > & xOrigin
656                 , const Reference< XContentIdentifierMapping > &
657                     xContentIdentifierMapping )
658                 : ContentResultSetWrapper( xOrigin )
659 
660                 , m_xSMgr( xSMgr )
661                 , m_xFetchProvider( NULL )
662                 , m_xFetchProviderForContentAccess( NULL )
663 
664                 , m_xMyPropertySetInfo( NULL )
665                 , m_pMyPropSetInfo( NULL )
666 
667                 , m_xContentIdentifierMapping( xContentIdentifierMapping )
668                 , m_nRow( 0 ) // Position is one-based. Zero means: before first element.
669                 , m_bAfterLast( sal_False )
670                 , m_nLastAppliedPos( 0 )
671                 , m_bAfterLastApplied( sal_False )
672                 , m_nKnownCount( 0 )
673                 , m_bFinalCount( sal_False )
674                 , m_nFetchSize(
675                     COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE )
676                 , m_nFetchDirection(
677                     COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION )
678 
679                 , m_bLastReadWasFromCache( sal_False )
680                 , m_bLastCachedReadWasNull( sal_True )
681                 , m_aCache( m_xContentIdentifierMapping )
682                 , m_aCacheContentIdentifierString( m_xContentIdentifierMapping )
683                 , m_aCacheContentIdentifier( m_xContentIdentifierMapping )
684                 , m_aCacheContent( m_xContentIdentifierMapping )
685                 , m_bTriedToGetTypeConverter( sal_False )
686                 , m_xTypeConverter( NULL )
687 {
688     m_xFetchProvider = Reference< XFetchProvider >( m_xResultSetOrigin, UNO_QUERY );
689     OSL_ENSURE( m_xFetchProvider.is(), "interface XFetchProvider is required" );
690 
691     m_xFetchProviderForContentAccess = Reference< XFetchProviderForContentAccess >( m_xResultSetOrigin, UNO_QUERY );
692     OSL_ENSURE( m_xFetchProviderForContentAccess.is(), "interface XFetchProviderForContentAccess is required" );
693 
694     impl_init();
695 };
696 
~CachedContentResultSet()697 CachedContentResultSet::~CachedContentResultSet()
698 {
699     impl_deinit();
700     //do not delete m_pMyPropSetInfo, cause it is hold via reference
701 };
702 
703 //--------------------------------------------------------------------------
704 // impl_ methods.
705 //--------------------------------------------------------------------------
706 
707 sal_Bool SAL_CALL CachedContentResultSet
applyPositionToOrigin(sal_Int32 nRow)708     ::applyPositionToOrigin( sal_Int32 nRow )
709     throw( SQLException,
710            RuntimeException )
711 {
712     impl_EnsureNotDisposed();
713     //-------------------------------------------------------------------------
714     /**
715     @returns
716         <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
717         the result set.
718     */
719 
720     ReacquireableGuard aGuard( m_aMutex );
721     OSL_ENSURE( nRow >= 0, "only positive values supported" );
722     if( !m_xResultSetOrigin.is() )
723     {
724         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
725         return sal_False;
726     }
727 //  OSL_ENSURE( nRow <= m_nKnownCount, "don't step into regions you don't know with this method" );
728 
729     sal_Int32 nLastAppliedPos = m_nLastAppliedPos;
730     sal_Bool bAfterLastApplied = m_bAfterLastApplied;
731     sal_Bool bAfterLast = m_bAfterLast;
732     sal_Int32 nForwardOnly = m_nForwardOnly;
733 
734     aGuard.clear();
735 
736     if( bAfterLastApplied || nLastAppliedPos != nRow )
737     {
738         if( nForwardOnly == 1 )
739         {
740             if( bAfterLastApplied || bAfterLast || !nRow || nRow < nLastAppliedPos )
741                 throw SQLException();
742 
743             sal_Int32 nN = nRow - nLastAppliedPos;
744             sal_Int32 nM;
745             for( nM = 0; nN--; nM++ )
746             {
747                 if( !m_xResultSetOrigin->next() )
748                     break;
749             }
750 
751             aGuard.reacquire();
752             m_nLastAppliedPos += nM;
753             m_bAfterLastApplied = nRow != m_nLastAppliedPos;
754             return nRow == m_nLastAppliedPos;
755         }
756 
757         if( !nRow ) //absolute( 0 ) will throw exception
758         {
759             m_xResultSetOrigin->beforeFirst();
760 
761             aGuard.reacquire();
762             m_nLastAppliedPos = 0;
763             m_bAfterLastApplied = sal_False;
764             return sal_False;
765         }
766         try
767         {
768             //move absolute, if !nLastAppliedPos
769             //because move relative would throw exception
770             if( !nLastAppliedPos || bAfterLast || bAfterLastApplied )
771             {
772                 sal_Bool bValid = m_xResultSetOrigin->absolute( nRow );
773 
774                 aGuard.reacquire();
775                 m_nLastAppliedPos = nRow;
776                 m_bAfterLastApplied = !bValid;
777                 return bValid;
778             }
779             else
780             {
781                 sal_Bool bValid = m_xResultSetOrigin->relative( nRow - nLastAppliedPos );
782 
783                 aGuard.reacquire();
784                 m_nLastAppliedPos += ( nRow - nLastAppliedPos );
785                 m_bAfterLastApplied = !bValid;
786                 return bValid;
787             }
788         }
789         catch( SQLException& rEx )
790         {
791             if( !bAfterLastApplied && !bAfterLast && nRow > nLastAppliedPos && impl_isForwardOnly() )
792             {
793                 sal_Int32 nN = nRow - nLastAppliedPos;
794                 sal_Int32 nM;
795                 for( nM = 0; nN--; nM++ )
796                 {
797                     if( !m_xResultSetOrigin->next() )
798                         break;
799                 }
800 
801                 aGuard.reacquire();
802                 m_nLastAppliedPos += nM;
803                 m_bAfterLastApplied = nRow != m_nLastAppliedPos;
804             }
805             else
806                 throw rEx;
807         }
808 
809         return nRow == m_nLastAppliedPos;
810     }
811     return sal_True;
812 };
813 
814 //--------------------------------------------------------------------------
815 //--------------------------------------------------------------------------
816 //define for fetching data
817 //--------------------------------------------------------------------------
818 //--------------------------------------------------------------------------
819 
820 #define FETCH_XXX( aCache, fetchInterface, fetchMethod )            \
821 sal_Bool bDirection = !!(                                           \
822     nFetchDirection != FetchDirection::REVERSE );                   \
823 FetchResult aResult =                                               \
824     fetchInterface->fetchMethod( nRow, nFetchSize, bDirection );    \
825 osl::ClearableGuard< osl::Mutex > aGuard2( m_aMutex );              \
826 aCache.loadData( aResult );                                         \
827 sal_Int32 nMax = aCache.getMaxRow();                                \
828 sal_Int32 nCurCount = m_nKnownCount;                                \
829 sal_Bool bIsFinalCount = aCache.hasKnownLast();                     \
830 sal_Bool bCurIsFinalCount = m_bFinalCount;                          \
831 aGuard2.clear();                                                    \
832 if( nMax > nCurCount )                                              \
833     impl_changeRowCount( nCurCount, nMax );                         \
834 if( bIsFinalCount && !bCurIsFinalCount )                            \
835     impl_changeIsRowCountFinal( bCurIsFinalCount, bIsFinalCount );
836 
837 void SAL_CALL CachedContentResultSet
impl_fetchData(sal_Int32 nRow,sal_Int32 nFetchSize,sal_Int32 nFetchDirection)838     ::impl_fetchData( sal_Int32 nRow
839         , sal_Int32 nFetchSize, sal_Int32 nFetchDirection )
840         throw( com::sun::star::uno::RuntimeException )
841 {
842     FETCH_XXX( m_aCache, m_xFetchProvider, fetch );
843 }
844 
845 void SAL_CALL CachedContentResultSet
impl_changeRowCount(sal_Int32 nOld,sal_Int32 nNew)846     ::impl_changeRowCount( sal_Int32 nOld, sal_Int32 nNew )
847 {
848     OSL_ENSURE( nNew > nOld, "RowCount only can grow" );
849     if( nNew <= nOld )
850         return;
851 
852     //create PropertyChangeEvent and set value
853     PropertyChangeEvent aEvt;
854     {
855         osl::Guard< osl::Mutex > aGuard( m_aMutex );
856         aEvt.Source =  static_cast< XPropertySet * >( this );
857         aEvt.Further = sal_False;
858         aEvt.OldValue <<= nOld;
859         aEvt.NewValue <<= nNew;
860 
861         m_nKnownCount = nNew;
862     }
863 
864     //send PropertyChangeEvent to listeners
865     impl_notifyPropertyChangeListeners( aEvt );
866 }
867 
868 void SAL_CALL CachedContentResultSet
impl_changeIsRowCountFinal(sal_Bool bOld,sal_Bool bNew)869     ::impl_changeIsRowCountFinal( sal_Bool bOld, sal_Bool bNew )
870 {
871     OSL_ENSURE( !bOld && bNew, "This change is not allowed for IsRowCountFinal" );
872     if( ! (!bOld && bNew ) )
873         return;
874 
875     //create PropertyChangeEvent and set value
876     PropertyChangeEvent aEvt;
877     {
878         osl::Guard< osl::Mutex > aGuard( m_aMutex );
879         aEvt.Source =  static_cast< XPropertySet * >( this );
880         aEvt.Further = sal_False;
881         aEvt.OldValue <<= bOld;
882         aEvt.NewValue <<= bNew;
883 
884         m_bFinalCount = bNew;
885     }
886 
887     //send PropertyChangeEvent to listeners
888     impl_notifyPropertyChangeListeners( aEvt );
889 }
890 
891 sal_Bool SAL_CALL CachedContentResultSet
impl_isKnownValidPosition(sal_Int32 nRow)892     ::impl_isKnownValidPosition( sal_Int32 nRow )
893 {
894     return m_nKnownCount && nRow
895             && nRow <= m_nKnownCount;
896 }
897 
898 sal_Bool SAL_CALL CachedContentResultSet
impl_isKnownInvalidPosition(sal_Int32 nRow)899     ::impl_isKnownInvalidPosition( sal_Int32 nRow )
900 {
901     if( !nRow )
902         return sal_True;
903     if( !m_bFinalCount )
904         return sal_False;
905     return nRow > m_nKnownCount;
906 }
907 
908 
909 //virtual
910 void SAL_CALL CachedContentResultSet
impl_initPropertySetInfo()911     ::impl_initPropertySetInfo()
912 {
913     ContentResultSetWrapper::impl_initPropertySetInfo();
914 
915     osl::Guard< osl::Mutex > aGuard( m_aMutex );
916     if( m_pMyPropSetInfo )
917         return;
918     m_pMyPropSetInfo = new CCRS_PropertySetInfo( m_xPropertySetInfo );
919     m_xMyPropertySetInfo = m_pMyPropSetInfo;
920     m_xPropertySetInfo = m_xMyPropertySetInfo;
921 }
922 
923 //--------------------------------------------------------------------------
924 // XInterface methods. ( inherited )
925 //--------------------------------------------------------------------------
XINTERFACE_COMMON_IMPL(CachedContentResultSet)926 XINTERFACE_COMMON_IMPL( CachedContentResultSet )
927 
928 Any SAL_CALL CachedContentResultSet
929     ::queryInterface( const Type&  rType )
930     throw ( RuntimeException )
931 {
932     //list all interfaces inclusive baseclasses of interfaces
933 
934     Any aRet = ContentResultSetWrapper::queryInterface( rType );
935     if( aRet.hasValue() )
936         return aRet;
937 
938     aRet = cppu::queryInterface( rType,
939                 static_cast< XTypeProvider* >( this ),
940                 static_cast< XServiceInfo* >( this ) );
941 
942     return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
943 }
944 
945 //--------------------------------------------------------------------------
946 // XTypeProvider methods.
947 //--------------------------------------------------------------------------
948 //list all interfaces exclusive baseclasses
949 XTYPEPROVIDER_IMPL_11( CachedContentResultSet
950                     , XTypeProvider
951                     , XServiceInfo
952                     , XComponent
953                     , XCloseable
954                     , XResultSetMetaDataSupplier
955                     , XPropertySet
956 
957                     , XPropertyChangeListener
958                     , XVetoableChangeListener
959 
960                     , XContentAccess
961 
962                     , XResultSet
963                     , XRow );
964 
965 //--------------------------------------------------------------------------
966 // XServiceInfo methods.
967 //--------------------------------------------------------------------------
968 
969 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSet,
970                            OUString::createFromAscii(
971                             "com.sun.star.comp.ucb.CachedContentResultSet" ),
972                            OUString::createFromAscii(
973                             CACHED_CONTENT_RESULTSET_SERVICE_NAME ) );
974 
975 //--------------------------------------------------------------------------
976 // XPropertySet methods. ( inherited )
977 //--------------------------------------------------------------------------
978 
979 // virtual
980 void SAL_CALL CachedContentResultSet
setPropertyValue(const OUString & aPropertyName,const Any & aValue)981     ::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
982     throw( UnknownPropertyException,
983            PropertyVetoException,
984            IllegalArgumentException,
985            WrappedTargetException,
986            RuntimeException )
987 {
988     impl_EnsureNotDisposed();
989 
990     if( !getPropertySetInfo().is() )
991     {
992         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
993         throw UnknownPropertyException();
994     }
995 
996     Property aProp = m_pMyPropSetInfo->getPropertyByName( aPropertyName );
997         //throws UnknownPropertyException, if so
998 
999     if( aProp.Attributes & PropertyAttribute::READONLY )
1000     {
1001         //It is assumed, that the properties
1002         //'RowCount' and 'IsRowCountFinal' are readonly!
1003         throw IllegalArgumentException();
1004     }
1005     if( aProp.Name == CCRS_PropertySetInfo
1006                         ::m_aPropertyNameForFetchDirection )
1007     {
1008         //check value
1009         sal_Int32 nNew;
1010         if( !( aValue >>= nNew ) )
1011         {
1012             throw IllegalArgumentException();
1013         }
1014 
1015         if( nNew == FetchDirection::UNKNOWN )
1016         {
1017             nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_DIRECTION;
1018         }
1019         else if( !( nNew == FetchDirection::FORWARD
1020                 || nNew == FetchDirection::REVERSE ) )
1021         {
1022             throw IllegalArgumentException();
1023         }
1024 
1025         //create PropertyChangeEvent and set value
1026         PropertyChangeEvent aEvt;
1027         {
1028             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1029             aEvt.Source =  static_cast< XPropertySet * >( this );
1030             aEvt.PropertyName = aPropertyName;
1031             aEvt.Further = sal_False;
1032             aEvt.PropertyHandle = m_pMyPropSetInfo->
1033                                     m_nFetchDirectionPropertyHandle;
1034             aEvt.OldValue <<= m_nFetchDirection;
1035             aEvt.NewValue <<= nNew;
1036 
1037             m_nFetchDirection = nNew;
1038         }
1039 
1040         //send PropertyChangeEvent to listeners
1041         impl_notifyPropertyChangeListeners( aEvt );
1042     }
1043     else if( aProp.Name == CCRS_PropertySetInfo
1044                         ::m_aPropertyNameForFetchSize )
1045     {
1046         //check value
1047         sal_Int32 nNew;
1048         if( !( aValue >>= nNew ) )
1049         {
1050             throw IllegalArgumentException();
1051         }
1052 
1053         if( nNew < 0 )
1054         {
1055             nNew = COMSUNSTARUCBCCRS_DEFAULT_FETCH_SIZE;
1056         }
1057 
1058         //create PropertyChangeEvent and set value
1059         PropertyChangeEvent aEvt;
1060         {
1061             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1062             aEvt.Source =  static_cast< XPropertySet * >( this );
1063             aEvt.PropertyName = aPropertyName;
1064             aEvt.Further = sal_False;
1065             aEvt.PropertyHandle = m_pMyPropSetInfo->
1066                                     m_nFetchSizePropertyHandle;
1067             aEvt.OldValue <<= m_nFetchSize;
1068             aEvt.NewValue <<= nNew;
1069 
1070             m_nFetchSize = nNew;
1071         }
1072 
1073         //send PropertyChangeEvent to listeners
1074         impl_notifyPropertyChangeListeners( aEvt );
1075     }
1076     else
1077     {
1078         impl_init_xPropertySetOrigin();
1079         {
1080             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1081             if( !m_xPropertySetOrigin.is() )
1082             {
1083                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1084                 return;
1085             }
1086         }
1087         m_xPropertySetOrigin->setPropertyValue( aPropertyName, aValue );
1088     }
1089 }
1090 
1091 //--------------------------------------------------------------------------
1092 // virtual
1093 Any SAL_CALL CachedContentResultSet
getPropertyValue(const OUString & rPropertyName)1094     ::getPropertyValue( const OUString& rPropertyName )
1095     throw( UnknownPropertyException,
1096            WrappedTargetException,
1097            RuntimeException )
1098 {
1099     impl_EnsureNotDisposed();
1100 
1101     if( !getPropertySetInfo().is() )
1102     {
1103         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1104         throw UnknownPropertyException();
1105     }
1106 
1107     Property aProp = m_pMyPropSetInfo->getPropertyByName( rPropertyName );
1108         //throws UnknownPropertyException, if so
1109 
1110     Any aValue;
1111     if( rPropertyName == CCRS_PropertySetInfo
1112                         ::m_aPropertyNameForCount )
1113     {
1114         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1115         aValue <<= m_nKnownCount;
1116     }
1117     else if( rPropertyName == CCRS_PropertySetInfo
1118                             ::m_aPropertyNameForFinalCount )
1119     {
1120         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1121         aValue <<= m_bFinalCount;
1122     }
1123     else if( rPropertyName == CCRS_PropertySetInfo
1124                             ::m_aPropertyNameForFetchSize )
1125     {
1126         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1127         aValue <<= m_nFetchSize;
1128     }
1129     else if( rPropertyName == CCRS_PropertySetInfo
1130                             ::m_aPropertyNameForFetchDirection )
1131     {
1132         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1133         aValue <<= m_nFetchDirection;
1134     }
1135     else
1136     {
1137         impl_init_xPropertySetOrigin();
1138         {
1139             osl::Guard< osl::Mutex > aGuard( m_aMutex );
1140             if( !m_xPropertySetOrigin.is() )
1141             {
1142                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1143                 throw UnknownPropertyException();
1144             }
1145         }
1146         aValue = m_xPropertySetOrigin->getPropertyValue( rPropertyName );
1147     }
1148     return aValue;
1149 }
1150 
1151 //--------------------------------------------------------------------------
1152 // own methods.  ( inherited )
1153 //--------------------------------------------------------------------------
1154 
1155 //virtual
1156 void SAL_CALL CachedContentResultSet
impl_disposing(const EventObject & rEventObject)1157     ::impl_disposing( const EventObject& rEventObject )
1158     throw( RuntimeException )
1159 {
1160     {
1161         impl_EnsureNotDisposed();
1162         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1163         //release all references to the broadcaster:
1164         m_xFetchProvider.clear();
1165         m_xFetchProviderForContentAccess.clear();
1166     }
1167     ContentResultSetWrapper::impl_disposing( rEventObject );
1168 }
1169 
1170 //virtual
1171 void SAL_CALL CachedContentResultSet
impl_propertyChange(const PropertyChangeEvent & rEvt)1172     ::impl_propertyChange( const PropertyChangeEvent& rEvt )
1173     throw( RuntimeException )
1174 {
1175     impl_EnsureNotDisposed();
1176 
1177     PropertyChangeEvent aEvt( rEvt );
1178     aEvt.Source = static_cast< XPropertySet * >( this );
1179     aEvt.Further = sal_False;
1180     //---------
1181 
1182     if( CCRS_PropertySetInfo
1183             ::impl_isMyPropertyName( rEvt.PropertyName ) )
1184     {
1185         //don't notify foreign events on fetchsize and fetchdirection
1186         if( aEvt.PropertyName == CCRS_PropertySetInfo
1187                                 ::m_aPropertyNameForFetchSize
1188         || aEvt.PropertyName == CCRS_PropertySetInfo
1189                                 ::m_aPropertyNameForFetchDirection )
1190             return;
1191 
1192         //adjust my props 'RowCount' and 'IsRowCountFinal'
1193         if( aEvt.PropertyName == CCRS_PropertySetInfo
1194                             ::m_aPropertyNameForCount )
1195         {//RowCount changed
1196 
1197             //check value
1198             sal_Int32 nNew = 0;
1199             if( !( aEvt.NewValue >>= nNew ) )
1200             {
1201                 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1202                 return;
1203             }
1204 
1205             impl_changeRowCount( m_nKnownCount, nNew );
1206         }
1207         else if( aEvt.PropertyName == CCRS_PropertySetInfo
1208                                 ::m_aPropertyNameForFinalCount )
1209         {//IsRowCountFinal changed
1210 
1211             //check value
1212             sal_Bool bNew = sal_False;
1213             if( !( aEvt.NewValue >>= bNew ) )
1214             {
1215                 OSL_ENSURE( sal_False, "PropertyChangeEvent contains wrong data" );
1216                 return;
1217             }
1218             impl_changeIsRowCountFinal( m_bFinalCount, bNew );
1219         }
1220         return;
1221     }
1222 
1223     //-----------
1224     impl_notifyPropertyChangeListeners( aEvt );
1225 }
1226 
1227 
1228 //virtual
1229 void SAL_CALL CachedContentResultSet
impl_vetoableChange(const PropertyChangeEvent & rEvt)1230     ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
1231     throw( PropertyVetoException,
1232            RuntimeException )
1233 {
1234     impl_EnsureNotDisposed();
1235 
1236     //don't notify events on my properties, cause they are not vetoable
1237     if( CCRS_PropertySetInfo
1238             ::impl_isMyPropertyName( rEvt.PropertyName ) )
1239     {
1240         return;
1241     }
1242 
1243 
1244     PropertyChangeEvent aEvt( rEvt );
1245     aEvt.Source = static_cast< XPropertySet * >( this );
1246     aEvt.Further = sal_False;
1247 
1248     impl_notifyVetoableChangeListeners( aEvt );
1249 }
1250 
1251 //--------------------------------------------------------------------------
1252 // XContentAccess methods. ( inherited ) ( -- position dependent )
1253 //--------------------------------------------------------------------------
1254 
1255 #define XCONTENTACCESS_queryXXX( queryXXX, XXX, TYPE )              \
1256 impl_EnsureNotDisposed();                                   \
1257 ReacquireableGuard aGuard( m_aMutex );                      \
1258 sal_Int32 nRow = m_nRow;                                    \
1259 sal_Int32 nFetchSize = m_nFetchSize;                        \
1260 sal_Int32 nFetchDirection = m_nFetchDirection;              \
1261 if( !m_aCache##XXX.hasRow( nRow ) )                         \
1262 {                                                           \
1263     if( !m_aCache##XXX.hasCausedException( nRow ) )         \
1264 {                                                           \
1265         if( !m_xFetchProviderForContentAccess.is() )        \
1266         {                                                   \
1267             OSL_ENSURE( sal_False, "broadcaster was disposed already" );\
1268             throw RuntimeException();                       \
1269         }                                                   \
1270         aGuard.clear();                                     \
1271         if( impl_isForwardOnly() )                          \
1272             applyPositionToOrigin( nRow );                  \
1273                                                             \
1274         FETCH_XXX( m_aCache##XXX, m_xFetchProviderForContentAccess, fetch##XXX##s ); \
1275     }                                                       \
1276     aGuard.reacquire();                                     \
1277     if( !m_aCache##XXX.hasRow( nRow ) )                     \
1278     {                                                       \
1279         aGuard.clear();                                     \
1280         applyPositionToOrigin( nRow );                      \
1281         TYPE aRet = ContentResultSetWrapper::queryXXX();    \
1282         if( m_xContentIdentifierMapping.is() )              \
1283             return m_xContentIdentifierMapping->map##XXX( aRet );\
1284         return aRet;                                        \
1285     }                                                       \
1286 }                                                           \
1287 return m_aCache##XXX.get##XXX( nRow );
1288 
1289 //--------------------------------------------------------------------------
1290 // virtual
1291 OUString SAL_CALL CachedContentResultSet
queryContentIdentifierString()1292     ::queryContentIdentifierString()
1293     throw( RuntimeException )
1294 {
1295     XCONTENTACCESS_queryXXX( queryContentIdentifierString, ContentIdentifierString, OUString )
1296 }
1297 
1298 //--------------------------------------------------------------------------
1299 // virtual
1300 Reference< XContentIdentifier > SAL_CALL CachedContentResultSet
queryContentIdentifier()1301     ::queryContentIdentifier()
1302     throw( RuntimeException )
1303 {
1304     XCONTENTACCESS_queryXXX( queryContentIdentifier, ContentIdentifier, Reference< XContentIdentifier > )
1305 }
1306 
1307 //--------------------------------------------------------------------------
1308 // virtual
1309 Reference< XContent > SAL_CALL CachedContentResultSet
queryContent()1310     ::queryContent()
1311     throw( RuntimeException )
1312 {
1313     XCONTENTACCESS_queryXXX( queryContent, Content, Reference< XContent > )
1314 }
1315 
1316 //-----------------------------------------------------------------
1317 // XResultSet methods. ( inherited )
1318 //-----------------------------------------------------------------
1319 //virtual
1320 
1321 sal_Bool SAL_CALL CachedContentResultSet
next()1322     ::next()
1323     throw( SQLException,
1324            RuntimeException )
1325 {
1326     impl_EnsureNotDisposed();
1327 
1328     ReacquireableGuard aGuard( m_aMutex );
1329     //after last
1330     if( m_bAfterLast )
1331         return sal_False;
1332     //last
1333     aGuard.clear();
1334     if( isLast() )
1335     {
1336         aGuard.reacquire();
1337         m_nRow++;
1338         m_bAfterLast = sal_True;
1339         return sal_False;
1340     }
1341     aGuard.reacquire();
1342     //known valid position
1343     if( impl_isKnownValidPosition( m_nRow + 1 ) )
1344     {
1345         m_nRow++;
1346         return sal_True;
1347     }
1348 
1349     //unknown position
1350     sal_Int32 nRow = m_nRow;
1351     aGuard.clear();
1352 
1353     sal_Bool bValid = applyPositionToOrigin( nRow + 1 );
1354 
1355     aGuard.reacquire();
1356     m_nRow = nRow + 1;
1357     m_bAfterLast = !bValid;
1358     return bValid;
1359 }
1360 
1361 //virtual
1362 sal_Bool SAL_CALL CachedContentResultSet
previous()1363     ::previous()
1364     throw( SQLException,
1365            RuntimeException )
1366 {
1367     impl_EnsureNotDisposed();
1368 
1369     if( impl_isForwardOnly() )
1370         throw SQLException();
1371 
1372     ReacquireableGuard aGuard( m_aMutex );
1373     //before first ?:
1374     if( !m_bAfterLast && !m_nRow )
1375         return sal_False;
1376     //first ?:
1377     if( !m_bAfterLast && m_nKnownCount && m_nRow == 1 )
1378     {
1379         m_nRow--;
1380         m_bAfterLast = sal_False;
1381         return sal_False;
1382     }
1383     //known valid position ?:
1384     if( impl_isKnownValidPosition( m_nRow - 1 ) )
1385     {
1386         m_nRow--;
1387         m_bAfterLast = sal_False;
1388         return sal_True;
1389     }
1390     //unknown position:
1391     sal_Int32 nRow = m_nRow;
1392     aGuard.clear();
1393 
1394     sal_Bool bValid = applyPositionToOrigin( nRow - 1  );
1395 
1396     aGuard.reacquire();
1397     m_nRow = nRow - 1;
1398     m_bAfterLast = sal_False;
1399     return bValid;
1400 }
1401 
1402 //virtual
1403 sal_Bool SAL_CALL CachedContentResultSet
absolute(sal_Int32 row)1404     ::absolute( sal_Int32 row )
1405     throw( SQLException,
1406            RuntimeException )
1407 {
1408     impl_EnsureNotDisposed();
1409 
1410     if( !row )
1411         throw SQLException();
1412 
1413     if( impl_isForwardOnly() )
1414         throw SQLException();
1415 
1416     ReacquireableGuard aGuard( m_aMutex );
1417 
1418     if( !m_xResultSetOrigin.is() )
1419     {
1420         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1421         return sal_False;
1422     }
1423     if( row < 0 )
1424     {
1425         if( m_bFinalCount )
1426         {
1427             sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1428             sal_Bool bValid = sal_True;
1429             if( nNewRow <= 0 )
1430             {
1431                 nNewRow = 0;
1432                 bValid = sal_False;
1433             }
1434             m_nRow = nNewRow;
1435             m_bAfterLast = sal_False;
1436             return bValid;
1437         }
1438         //unknown final count:
1439         aGuard.clear();
1440 
1441         // Solaris has problems catching or propagating derived exceptions
1442         // when only the base class is known, so make ResultSetException
1443         // (derived from SQLException) known here:
1444         sal_Bool bValid;
1445         try
1446         {
1447             bValid = m_xResultSetOrigin->absolute( row );
1448         }
1449         catch (ResultSetException &)
1450         {
1451             throw;
1452         }
1453 
1454         aGuard.reacquire();
1455         if( m_bFinalCount )
1456         {
1457             sal_Int32 nNewRow = m_nKnownCount + 1 + row;
1458             if( nNewRow < 0 )
1459                 nNewRow = 0;
1460             m_nLastAppliedPos = nNewRow;
1461             m_nRow = nNewRow;
1462             m_bAfterLastApplied = m_bAfterLast = sal_False;
1463             return bValid;
1464         }
1465         aGuard.clear();
1466 
1467         sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1468 
1469         aGuard.reacquire();
1470         m_nLastAppliedPos = nCurRow;
1471         m_nRow = nCurRow;
1472         m_bAfterLast = sal_False;
1473         return nCurRow != 0;
1474     }
1475     //row > 0:
1476     if( m_bFinalCount )
1477     {
1478         if( row > m_nKnownCount )
1479         {
1480             m_nRow = m_nKnownCount + 1;
1481             m_bAfterLast = sal_True;
1482             return sal_False;
1483         }
1484         m_nRow = row;
1485         m_bAfterLast = sal_False;
1486         return sal_True;
1487     }
1488     //unknown new position:
1489     aGuard.clear();
1490 
1491     sal_Bool bValid = m_xResultSetOrigin->absolute( row );
1492 
1493     aGuard.reacquire();
1494     if( m_bFinalCount )
1495     {
1496         sal_Int32 nNewRow = row;
1497         if( nNewRow > m_nKnownCount )
1498         {
1499             nNewRow = m_nKnownCount + 1;
1500             m_bAfterLastApplied = m_bAfterLast = sal_True;
1501         }
1502         else
1503             m_bAfterLastApplied = m_bAfterLast = sal_False;
1504 
1505         m_nLastAppliedPos = nNewRow;
1506         m_nRow = nNewRow;
1507         return bValid;
1508     }
1509     aGuard.clear();
1510 
1511     sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1512     sal_Bool bIsAfterLast = m_xResultSetOrigin->isAfterLast();
1513 
1514     aGuard.reacquire();
1515     m_nLastAppliedPos = nCurRow;
1516     m_nRow = nCurRow;
1517     m_bAfterLastApplied = m_bAfterLast = bIsAfterLast;
1518     return nCurRow && !bIsAfterLast;
1519 }
1520 
1521 //virtual
1522 sal_Bool SAL_CALL CachedContentResultSet
relative(sal_Int32 rows)1523     ::relative( sal_Int32 rows )
1524     throw( SQLException,
1525            RuntimeException )
1526 {
1527     impl_EnsureNotDisposed();
1528 
1529     if( impl_isForwardOnly() )
1530         throw SQLException();
1531 
1532     ReacquireableGuard aGuard( m_aMutex );
1533     if( m_bAfterLast || impl_isKnownInvalidPosition( m_nRow ) )
1534         throw SQLException();
1535 
1536     if( !rows )
1537         return sal_True;
1538 
1539     sal_Int32 nNewRow = m_nRow + rows;
1540         if( nNewRow < 0 )
1541             nNewRow = 0;
1542 
1543     if( impl_isKnownValidPosition( nNewRow ) )
1544     {
1545         m_nRow = nNewRow;
1546         m_bAfterLast = sal_False;
1547         return sal_True;
1548     }
1549     else
1550     {
1551         //known invalid new position:
1552         if( nNewRow == 0 )
1553         {
1554             m_bAfterLast = sal_False;
1555             m_nRow = 0;
1556             return sal_False;
1557         }
1558         if( m_bFinalCount && nNewRow > m_nKnownCount )
1559         {
1560             m_bAfterLast = sal_True;
1561             m_nRow = m_nKnownCount + 1;
1562             return sal_False;
1563         }
1564         //unknown new position:
1565         aGuard.clear();
1566         sal_Bool bValid = applyPositionToOrigin( nNewRow );
1567 
1568         aGuard.reacquire();
1569         m_nRow = nNewRow;
1570         m_bAfterLast = !bValid && nNewRow > 0;
1571         return bValid;
1572     }
1573 }
1574 
1575 
1576 //virtual
1577 sal_Bool SAL_CALL CachedContentResultSet
first()1578     ::first()
1579     throw( SQLException,
1580            RuntimeException )
1581 {
1582     impl_EnsureNotDisposed();
1583 
1584     if( impl_isForwardOnly() )
1585         throw SQLException();
1586 
1587     ReacquireableGuard aGuard( m_aMutex );
1588     if( impl_isKnownValidPosition( 1 ) )
1589     {
1590         m_nRow = 1;
1591         m_bAfterLast = sal_False;
1592         return sal_True;
1593     }
1594     if( impl_isKnownInvalidPosition( 1 ) )
1595     {
1596         m_nRow = 1;
1597         m_bAfterLast = sal_False;
1598         return sal_False;
1599     }
1600     //unknown position
1601     aGuard.clear();
1602 
1603     sal_Bool bValid = applyPositionToOrigin( 1 );
1604 
1605     aGuard.reacquire();
1606     m_nRow = 1;
1607     m_bAfterLast = sal_False;
1608     return bValid;
1609 }
1610 
1611 //virtual
1612 sal_Bool SAL_CALL CachedContentResultSet
last()1613     ::last()
1614     throw( SQLException,
1615            RuntimeException )
1616 {
1617     impl_EnsureNotDisposed();
1618 
1619     if( impl_isForwardOnly() )
1620         throw SQLException();
1621 
1622     ReacquireableGuard aGuard( m_aMutex );
1623     if( m_bFinalCount )
1624     {
1625         m_nRow = m_nKnownCount;
1626         m_bAfterLast = sal_False;
1627         return m_nKnownCount != 0;
1628     }
1629     //unknown position
1630     if( !m_xResultSetOrigin.is() )
1631     {
1632         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1633         return sal_False;
1634     }
1635     aGuard.clear();
1636 
1637     sal_Bool bValid = m_xResultSetOrigin->last();
1638 
1639     aGuard.reacquire();
1640     m_bAfterLastApplied = m_bAfterLast = sal_False;
1641     if( m_bFinalCount )
1642     {
1643         m_nLastAppliedPos = m_nKnownCount;
1644         m_nRow = m_nKnownCount;
1645         return bValid;
1646     }
1647     aGuard.clear();
1648 
1649     sal_Int32 nCurRow = m_xResultSetOrigin->getRow();
1650 
1651     aGuard.reacquire();
1652     m_nLastAppliedPos = nCurRow;
1653     m_nRow = nCurRow;
1654     OSL_ENSURE( nCurRow >= m_nKnownCount, "position of last row < known Count, that could not be" );
1655     m_nKnownCount = nCurRow;
1656     m_bFinalCount = sal_True;
1657     return nCurRow != 0;
1658 }
1659 
1660 //virtual
1661 void SAL_CALL CachedContentResultSet
beforeFirst()1662     ::beforeFirst()
1663     throw( SQLException,
1664            RuntimeException )
1665 {
1666     impl_EnsureNotDisposed();
1667 
1668     if( impl_isForwardOnly() )
1669         throw SQLException();
1670 
1671     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1672     m_nRow = 0;
1673     m_bAfterLast = sal_False;
1674 }
1675 
1676 //virtual
1677 void SAL_CALL CachedContentResultSet
afterLast()1678     ::afterLast()
1679     throw( SQLException,
1680            RuntimeException )
1681 {
1682     impl_EnsureNotDisposed();
1683 
1684     if( impl_isForwardOnly() )
1685         throw SQLException();
1686 
1687     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1688     m_nRow = 1;
1689     m_bAfterLast = sal_True;
1690 }
1691 
1692 //virtual
1693 sal_Bool SAL_CALL CachedContentResultSet
isAfterLast()1694     ::isAfterLast()
1695     throw( SQLException,
1696            RuntimeException )
1697 {
1698     impl_EnsureNotDisposed();
1699 
1700     ReacquireableGuard aGuard( m_aMutex );
1701     if( !m_bAfterLast )
1702         return sal_False;
1703     if( m_nKnownCount )
1704         return m_bAfterLast;
1705     if( m_bFinalCount )
1706         return sal_False;
1707 
1708     if( !m_xResultSetOrigin.is() )
1709     {
1710         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1711         return sal_False;
1712     }
1713     aGuard.clear();
1714 
1715     //find out whethter the original resultset contains rows or not
1716     m_xResultSetOrigin->afterLast();
1717 
1718     aGuard.reacquire();
1719     m_bAfterLastApplied = sal_True;
1720     aGuard.clear();
1721 
1722     return m_xResultSetOrigin->isAfterLast();
1723 }
1724 
1725 //virtual
1726 sal_Bool SAL_CALL CachedContentResultSet
isBeforeFirst()1727     ::isBeforeFirst()
1728     throw( SQLException,
1729            RuntimeException )
1730 {
1731     impl_EnsureNotDisposed();
1732 
1733     ReacquireableGuard aGuard( m_aMutex );
1734     if( m_bAfterLast )
1735         return sal_False;
1736     if( m_nRow )
1737         return sal_False;
1738     if( m_nKnownCount )
1739         return !m_nRow;
1740     if( m_bFinalCount )
1741         return sal_False;
1742 
1743     if( !m_xResultSetOrigin.is() )
1744     {
1745         OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1746         return sal_False;
1747     }
1748     aGuard.clear();
1749 
1750     //find out whethter the original resultset contains rows or not
1751     m_xResultSetOrigin->beforeFirst();
1752 
1753     aGuard.reacquire();
1754     m_bAfterLastApplied = sal_False;
1755     m_nLastAppliedPos = 0;
1756     aGuard.clear();
1757 
1758     return m_xResultSetOrigin->isBeforeFirst();
1759 }
1760 
1761 //virtual
1762 sal_Bool SAL_CALL CachedContentResultSet
isFirst()1763     ::isFirst()
1764     throw( SQLException,
1765            RuntimeException )
1766 {
1767     impl_EnsureNotDisposed();
1768 
1769     sal_Int32 nRow = 0;
1770     Reference< XResultSet > xResultSetOrigin;
1771 
1772     {
1773         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1774         if( m_bAfterLast )
1775             return sal_False;
1776         if( m_nRow != 1 )
1777             return sal_False;
1778         if( m_nKnownCount )
1779             return m_nRow == 1;
1780         if( m_bFinalCount )
1781             return sal_False;
1782 
1783         nRow = m_nRow;
1784         xResultSetOrigin = m_xResultSetOrigin;
1785     }
1786 
1787     //need to ask origin
1788     {
1789         if( applyPositionToOrigin( nRow ) )
1790             return xResultSetOrigin->isFirst();
1791         else
1792             return sal_False;
1793     }
1794 }
1795 
1796 //virtual
1797 sal_Bool SAL_CALL CachedContentResultSet
isLast()1798     ::isLast()
1799     throw( SQLException,
1800            RuntimeException )
1801 {
1802     impl_EnsureNotDisposed();
1803 
1804     sal_Int32 nRow = 0;
1805     Reference< XResultSet > xResultSetOrigin;
1806     {
1807         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1808         if( m_bAfterLast )
1809             return sal_False;
1810         if( m_nRow < m_nKnownCount )
1811             return sal_False;
1812         if( m_bFinalCount )
1813             return m_nKnownCount && m_nRow == m_nKnownCount;
1814 
1815         nRow = m_nRow;
1816         xResultSetOrigin = m_xResultSetOrigin;
1817     }
1818 
1819     //need to ask origin
1820     {
1821         if( applyPositionToOrigin( nRow ) )
1822             return xResultSetOrigin->isLast();
1823         else
1824             return sal_False;
1825     }
1826 }
1827 
1828 
1829 //virtual
1830 sal_Int32 SAL_CALL CachedContentResultSet
getRow()1831     ::getRow()
1832     throw( SQLException,
1833            RuntimeException )
1834 {
1835     impl_EnsureNotDisposed();
1836 
1837     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1838     if( m_bAfterLast )
1839         return 0;
1840     return m_nRow;
1841 }
1842 
1843 //virtual
1844 void SAL_CALL CachedContentResultSet
refreshRow()1845     ::refreshRow()
1846     throw( SQLException,
1847            RuntimeException )
1848 {
1849     impl_EnsureNotDisposed();
1850 
1851     //the ContentResultSet is static and will not change
1852     //therefore we don't need to reload anything
1853 }
1854 
1855 //virtual
1856 sal_Bool SAL_CALL CachedContentResultSet
rowUpdated()1857     ::rowUpdated()
1858     throw( SQLException,
1859            RuntimeException )
1860 {
1861     impl_EnsureNotDisposed();
1862 
1863     //the ContentResultSet is static and will not change
1864     return sal_False;
1865 }
1866 //virtual
1867 sal_Bool SAL_CALL CachedContentResultSet
rowInserted()1868     ::rowInserted()
1869     throw( SQLException,
1870            RuntimeException )
1871 {
1872     impl_EnsureNotDisposed();
1873 
1874     //the ContentResultSet is static and will not change
1875     return sal_False;
1876 }
1877 
1878 //virtual
1879 sal_Bool SAL_CALL CachedContentResultSet
rowDeleted()1880     ::rowDeleted()
1881     throw( SQLException,
1882            RuntimeException )
1883 {
1884     impl_EnsureNotDisposed();
1885 
1886     //the ContentResultSet is static and will not change
1887     return sal_False;
1888 }
1889 
1890 //virtual
1891 Reference< XInterface > SAL_CALL CachedContentResultSet
getStatement()1892     ::getStatement()
1893     throw( SQLException,
1894            RuntimeException )
1895 {
1896     impl_EnsureNotDisposed();
1897     //@todo ?return anything
1898     return Reference< XInterface >();
1899 }
1900 
1901 //-----------------------------------------------------------------
1902 // XRow methods. ( inherited )
1903 //-----------------------------------------------------------------
1904 
1905 //virtual
1906 sal_Bool SAL_CALL CachedContentResultSet
wasNull()1907     ::wasNull()
1908     throw( SQLException,
1909            RuntimeException )
1910 {
1911     impl_EnsureNotDisposed();
1912     impl_init_xRowOrigin();
1913     {
1914         osl::Guard< osl::Mutex > aGuard( m_aMutex );
1915         if( m_bLastReadWasFromCache )
1916             return m_bLastCachedReadWasNull;
1917         if( !m_xRowOrigin.is() )
1918         {
1919             OSL_ENSURE( sal_False, "broadcaster was disposed already" );
1920             return sal_False;
1921         }
1922     }
1923     return m_xRowOrigin->wasNull();
1924 }
1925 
1926 //virtual
1927 rtl::OUString SAL_CALL CachedContentResultSet
getString(sal_Int32 columnIndex)1928     ::getString( sal_Int32 columnIndex )
1929     throw( SQLException,
1930            RuntimeException )
1931 {
1932     XROW_GETXXX( getString, OUString );
1933 }
1934 
1935 //virtual
1936 sal_Bool SAL_CALL CachedContentResultSet
getBoolean(sal_Int32 columnIndex)1937     ::getBoolean( sal_Int32 columnIndex )
1938     throw( SQLException,
1939            RuntimeException )
1940 {
1941     XROW_GETXXX( getBoolean, sal_Bool );
1942 }
1943 
1944 //virtual
1945 sal_Int8 SAL_CALL CachedContentResultSet
getByte(sal_Int32 columnIndex)1946     ::getByte( sal_Int32 columnIndex )
1947     throw( SQLException,
1948            RuntimeException )
1949 {
1950     XROW_GETXXX( getByte, sal_Int8 );
1951 }
1952 
1953 //virtual
1954 sal_Int16 SAL_CALL CachedContentResultSet
getShort(sal_Int32 columnIndex)1955     ::getShort( sal_Int32 columnIndex )
1956     throw( SQLException,
1957            RuntimeException )
1958 {
1959     XROW_GETXXX( getShort, sal_Int16 );
1960 }
1961 
1962 //virtual
1963 sal_Int32 SAL_CALL CachedContentResultSet
getInt(sal_Int32 columnIndex)1964     ::getInt( sal_Int32 columnIndex )
1965     throw( SQLException,
1966            RuntimeException )
1967 {
1968     XROW_GETXXX( getInt, sal_Int32 );
1969 }
1970 
1971 //virtual
1972 sal_Int64 SAL_CALL CachedContentResultSet
getLong(sal_Int32 columnIndex)1973     ::getLong( sal_Int32 columnIndex )
1974     throw( SQLException,
1975            RuntimeException )
1976 {
1977     XROW_GETXXX( getLong, sal_Int64 );
1978 }
1979 
1980 //virtual
1981 float SAL_CALL CachedContentResultSet
getFloat(sal_Int32 columnIndex)1982     ::getFloat( sal_Int32 columnIndex )
1983     throw( SQLException,
1984            RuntimeException )
1985 {
1986     XROW_GETXXX( getFloat, float );
1987 }
1988 
1989 //virtual
1990 double SAL_CALL CachedContentResultSet
getDouble(sal_Int32 columnIndex)1991     ::getDouble( sal_Int32 columnIndex )
1992     throw( SQLException,
1993            RuntimeException )
1994 {
1995     XROW_GETXXX( getDouble, double );
1996 }
1997 
1998 //virtual
1999 Sequence< sal_Int8 > SAL_CALL CachedContentResultSet
getBytes(sal_Int32 columnIndex)2000     ::getBytes( sal_Int32 columnIndex )
2001     throw( SQLException,
2002            RuntimeException )
2003 {
2004     XROW_GETXXX( getBytes, Sequence< sal_Int8 > );
2005 }
2006 
2007 //virtual
2008 Date SAL_CALL CachedContentResultSet
getDate(sal_Int32 columnIndex)2009     ::getDate( sal_Int32 columnIndex )
2010     throw( SQLException,
2011            RuntimeException )
2012 {
2013     XROW_GETXXX( getDate, Date );
2014 }
2015 
2016 //virtual
2017 Time SAL_CALL CachedContentResultSet
getTime(sal_Int32 columnIndex)2018     ::getTime( sal_Int32 columnIndex )
2019     throw( SQLException,
2020            RuntimeException )
2021 {
2022     XROW_GETXXX( getTime, Time );
2023 }
2024 
2025 //virtual
2026 DateTime SAL_CALL CachedContentResultSet
getTimestamp(sal_Int32 columnIndex)2027     ::getTimestamp( sal_Int32 columnIndex )
2028     throw( SQLException,
2029            RuntimeException )
2030 {
2031     XROW_GETXXX( getTimestamp, DateTime );
2032 }
2033 
2034 //virtual
2035 Reference< com::sun::star::io::XInputStream >
2036     SAL_CALL CachedContentResultSet
getBinaryStream(sal_Int32 columnIndex)2037     ::getBinaryStream( sal_Int32 columnIndex )
2038     throw( SQLException,
2039            RuntimeException )
2040 {
2041     XROW_GETXXX( getBinaryStream, Reference< com::sun::star::io::XInputStream > );
2042 }
2043 
2044 //virtual
2045 Reference< com::sun::star::io::XInputStream >
2046     SAL_CALL CachedContentResultSet
getCharacterStream(sal_Int32 columnIndex)2047     ::getCharacterStream( sal_Int32 columnIndex )
2048     throw( SQLException,
2049            RuntimeException )
2050 {
2051     XROW_GETXXX( getCharacterStream, Reference< com::sun::star::io::XInputStream > );
2052 }
2053 
2054 //virtual
2055 Any SAL_CALL CachedContentResultSet
getObject(sal_Int32 columnIndex,const Reference<com::sun::star::container::XNameAccess> & typeMap)2056     ::getObject( sal_Int32 columnIndex,
2057            const Reference<
2058             com::sun::star::container::XNameAccess >& typeMap )
2059     throw( SQLException,
2060            RuntimeException )
2061 {
2062     //if you change this macro please pay attention to
2063     //define XROW_GETXXX, where this is similar implemented
2064 
2065     ReacquireableGuard aGuard( m_aMutex );
2066     sal_Int32 nRow = m_nRow;
2067     sal_Int32 nFetchSize = m_nFetchSize;
2068     sal_Int32 nFetchDirection = m_nFetchDirection;
2069     if( !m_aCache.hasRow( nRow ) )
2070     {
2071         if( !m_aCache.hasCausedException( nRow ) )
2072         {
2073             if( !m_xFetchProvider.is() )
2074             {
2075                 OSL_ENSURE( sal_False, "broadcaster was disposed already" );
2076                 return Any();
2077             }
2078             aGuard.clear();
2079 
2080             impl_fetchData( nRow, nFetchSize, nFetchDirection );
2081         }
2082         aGuard.reacquire();
2083         if( !m_aCache.hasRow( nRow ) )
2084         {
2085             m_bLastReadWasFromCache = sal_False;
2086             aGuard.clear();
2087             applyPositionToOrigin( nRow );
2088             impl_init_xRowOrigin();
2089             return m_xRowOrigin->getObject( columnIndex, typeMap );
2090         }
2091     }
2092     //@todo: pay attention to typeMap
2093     const Any& rValue = m_aCache.getAny( nRow, columnIndex );
2094     Any aRet;
2095     m_bLastReadWasFromCache = sal_True;
2096     m_bLastCachedReadWasNull = !( rValue >>= aRet );
2097     return aRet;
2098 }
2099 
2100 //virtual
2101 Reference< XRef > SAL_CALL CachedContentResultSet
getRef(sal_Int32 columnIndex)2102     ::getRef( sal_Int32 columnIndex )
2103     throw( SQLException,
2104            RuntimeException )
2105 {
2106     XROW_GETXXX( getRef, Reference< XRef > );
2107 }
2108 
2109 //virtual
2110 Reference< XBlob > SAL_CALL CachedContentResultSet
getBlob(sal_Int32 columnIndex)2111     ::getBlob( sal_Int32 columnIndex )
2112     throw( SQLException,
2113            RuntimeException )
2114 {
2115     XROW_GETXXX( getBlob, Reference< XBlob > );
2116 }
2117 
2118 //virtual
2119 Reference< XClob > SAL_CALL CachedContentResultSet
getClob(sal_Int32 columnIndex)2120     ::getClob( sal_Int32 columnIndex )
2121     throw( SQLException,
2122            RuntimeException )
2123 {
2124     XROW_GETXXX( getClob, Reference< XClob > );
2125 }
2126 
2127 //virtual
2128 Reference< XArray > SAL_CALL CachedContentResultSet
getArray(sal_Int32 columnIndex)2129     ::getArray( sal_Int32 columnIndex )
2130     throw( SQLException,
2131            RuntimeException )
2132 {
2133     XROW_GETXXX( getArray, Reference< XArray > );
2134 }
2135 
2136 //-----------------------------------------------------------------
2137 // Type Converter Support
2138 //-----------------------------------------------------------------
2139 
getTypeConverter()2140 const Reference< XTypeConverter >& CachedContentResultSet::getTypeConverter()
2141 {
2142     osl::Guard< osl::Mutex > aGuard( m_aMutex );
2143 
2144     if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
2145     {
2146         m_bTriedToGetTypeConverter = sal_True;
2147         m_xTypeConverter = Reference< XTypeConverter >(
2148                                 m_xSMgr->createInstance(
2149                                     OUString::createFromAscii(
2150                                         "com.sun.star.script.Converter" ) ),
2151                                 UNO_QUERY );
2152 
2153         OSL_ENSURE( m_xTypeConverter.is(),
2154                     "PropertyValueSet::getTypeConverter() - "
2155                     "Service 'com.sun.star.script.Converter' n/a!" );
2156     }
2157     return m_xTypeConverter;
2158 }
2159 
2160 //--------------------------------------------------------------------------
2161 //--------------------------------------------------------------------------
2162 // class CachedContentResultSetFactory
2163 //--------------------------------------------------------------------------
2164 //--------------------------------------------------------------------------
2165 
CachedContentResultSetFactory(const Reference<XMultiServiceFactory> & rSMgr)2166 CachedContentResultSetFactory::CachedContentResultSetFactory(
2167         const Reference< XMultiServiceFactory > & rSMgr )
2168 {
2169     m_xSMgr = rSMgr;
2170 }
2171 
~CachedContentResultSetFactory()2172 CachedContentResultSetFactory::~CachedContentResultSetFactory()
2173 {
2174 }
2175 
2176 //--------------------------------------------------------------------------
2177 // CachedContentResultSetFactory XInterface methods.
2178 //--------------------------------------------------------------------------
2179 
2180 XINTERFACE_IMPL_3( CachedContentResultSetFactory,
2181                    XTypeProvider,
2182                    XServiceInfo,
2183                    XCachedContentResultSetFactory );
2184 
2185 //--------------------------------------------------------------------------
2186 // CachedContentResultSetFactory XTypeProvider methods.
2187 //--------------------------------------------------------------------------
2188 
2189 XTYPEPROVIDER_IMPL_3( CachedContentResultSetFactory,
2190                       XTypeProvider,
2191                       XServiceInfo,
2192                       XCachedContentResultSetFactory );
2193 
2194 //--------------------------------------------------------------------------
2195 // CachedContentResultSetFactory XServiceInfo methods.
2196 //--------------------------------------------------------------------------
2197 
2198 XSERVICEINFO_IMPL_1( CachedContentResultSetFactory,
2199                      OUString::createFromAscii(
2200                         "com.sun.star.comp.ucb.CachedContentResultSetFactory" ),
2201                      OUString::createFromAscii(
2202                         CACHED_CONTENT_RESULTSET_FACTORY_NAME ) );
2203 
2204 //--------------------------------------------------------------------------
2205 // Service factory implementation.
2206 //--------------------------------------------------------------------------
2207 
2208 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetFactory );
2209 
2210 //--------------------------------------------------------------------------
2211 // CachedContentResultSetFactory XCachedContentResultSetFactory methods.
2212 //--------------------------------------------------------------------------
2213 
2214     //virtual
2215 Reference< XResultSet > SAL_CALL CachedContentResultSetFactory
createCachedContentResultSet(const Reference<XResultSet> & xSource,const Reference<XContentIdentifierMapping> & xMapping)2216     ::createCachedContentResultSet(
2217             const Reference< XResultSet > & xSource,
2218             const Reference< XContentIdentifierMapping > & xMapping )
2219             throw( com::sun::star::uno::RuntimeException )
2220 {
2221     Reference< XResultSet > xRet;
2222     xRet = new CachedContentResultSet( m_xSMgr, xSource, xMapping );
2223     return xRet;
2224 }
2225 
2226