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