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_cacher.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