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 <cachedcontentresultsetstub.hxx>
28 #include <com/sun/star/sdbc/FetchDirection.hpp>
29 #include <com/sun/star/ucb/FetchError.hpp>
30 #include <osl/diagnose.h>
31
32 using namespace com::sun::star::beans;
33 using namespace com::sun::star::lang;
34 using namespace com::sun::star::sdbc;
35 using namespace com::sun::star::ucb;
36 using namespace com::sun::star::uno;
37 using namespace com::sun::star::util;
38 using namespace cppu;
39 using namespace rtl;
40
CachedContentResultSetStub(Reference<XResultSet> xOrigin)41 CachedContentResultSetStub::CachedContentResultSetStub( Reference< XResultSet > xOrigin )
42 : ContentResultSetWrapper( xOrigin )
43 , m_nColumnCount( 0 )
44 , m_bColumnCountCached( sal_False )
45 , m_bNeedToPropagateFetchSize( sal_True )
46 , m_bFirstFetchSizePropagationDone( sal_False )
47 , m_nLastFetchSize( 1 )//this value is not important at all
48 , m_bLastFetchDirection( sal_True )//this value is not important at all
49 , m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) )
50 , m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) )
51 {
52 impl_init();
53 }
54
~CachedContentResultSetStub()55 CachedContentResultSetStub::~CachedContentResultSetStub()
56 {
57 impl_deinit();
58 }
59
60 //--------------------------------------------------------------------------
61 // XInterface methods.
62 //--------------------------------------------------------------------------
XINTERFACE_COMMON_IMPL(CachedContentResultSetStub)63 XINTERFACE_COMMON_IMPL( CachedContentResultSetStub )
64
65 Any SAL_CALL CachedContentResultSetStub
66 ::queryInterface( const Type& rType )
67 {
68 //list all interfaces inclusive baseclasses of interfaces
69
70 Any aRet = ContentResultSetWrapper::queryInterface( rType );
71 if( aRet.hasValue() )
72 return aRet;
73
74 aRet = cppu::queryInterface( rType
75 , static_cast< XTypeProvider* >( this )
76 , static_cast< XServiceInfo* >( this )
77 , static_cast< XFetchProvider* >( this )
78 , static_cast< XFetchProviderForContentAccess* >( this )
79 );
80
81 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
82 }
83
84 //--------------------------------------------------------------------------
85 // own methods. ( inherited )
86 //--------------------------------------------------------------------------
87
88 //virtual
89 void SAL_CALL CachedContentResultSetStub
impl_propertyChange(const PropertyChangeEvent & rEvt)90 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
91 {
92 impl_EnsureNotDisposed();
93
94 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
95 //because it will ignore them anyway and we can save this remote calls
96 if( rEvt.PropertyName == m_aPropertyNameForFetchSize
97 || rEvt.PropertyName == m_aPropertyNameForFetchDirection )
98 return;
99
100 PropertyChangeEvent aEvt( rEvt );
101 aEvt.Source = static_cast< XPropertySet * >( this );
102 aEvt.Further = sal_False;
103
104 impl_notifyPropertyChangeListeners( aEvt );
105 }
106
107
108 //virtual
109 void SAL_CALL CachedContentResultSetStub
impl_vetoableChange(const PropertyChangeEvent & rEvt)110 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
111 {
112 impl_EnsureNotDisposed();
113
114 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
115 //because it will ignore them anyway and we can save this remote calls
116 if( rEvt.PropertyName == m_aPropertyNameForFetchSize
117 || rEvt.PropertyName == m_aPropertyNameForFetchDirection )
118 return;
119
120 PropertyChangeEvent aEvt( rEvt );
121 aEvt.Source = static_cast< XPropertySet * >( this );
122 aEvt.Further = sal_False;
123
124 impl_notifyVetoableChangeListeners( aEvt );
125 }
126
127 //--------------------------------------------------------------------------
128 // XTypeProvider methods.
129 //--------------------------------------------------------------------------
130
XTYPEPROVIDER_COMMON_IMPL(CachedContentResultSetStub)131 XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub )
132 //list all interfaces exclusive baseclasses
133 Sequence< Type > SAL_CALL CachedContentResultSetStub
134 ::getTypes()
135 {
136 static Sequence< Type >* pTypes = NULL;
137 if( !pTypes )
138 {
139 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
140 if( !pTypes )
141 {
142 pTypes = new Sequence< Type >(13);
143 (*pTypes)[0] = CPPU_TYPE_REF( XTypeProvider );
144 (*pTypes)[1] = CPPU_TYPE_REF( XServiceInfo );
145 (*pTypes)[2] = CPPU_TYPE_REF( XComponent );
146 (*pTypes)[3] = CPPU_TYPE_REF( XCloseable );
147 (*pTypes)[4] = CPPU_TYPE_REF( XResultSetMetaDataSupplier );
148 (*pTypes)[5] = CPPU_TYPE_REF( XPropertySet );
149 (*pTypes)[6] = CPPU_TYPE_REF( XPropertyChangeListener );
150 (*pTypes)[7] = CPPU_TYPE_REF( XVetoableChangeListener );
151 (*pTypes)[8] = CPPU_TYPE_REF( XResultSet );
152 (*pTypes)[9] = CPPU_TYPE_REF( XContentAccess );
153 (*pTypes)[10] = CPPU_TYPE_REF( XRow );
154 (*pTypes)[11] = CPPU_TYPE_REF( XFetchProvider );
155 (*pTypes)[12] = CPPU_TYPE_REF( XFetchProviderForContentAccess );
156 }
157 }
158 return *pTypes;
159 /*
160 static cppu::OTypeCollection * pCollection = 0;
161 if (!pCollection)
162 {
163 osl::MutexGuard aGuard(osl::Mutex::getGlobalMutex());
164 if (!pCollection)
165 {
166 static cppu::OTypeCollection
167 aTheCollection(
168 getCppuType(
169 static_cast< Reference< XTypeProvider >
170 const * >(
171 0)),
172 getCppuType(
173 static_cast< Reference< XServiceInfo >
174 const * >(
175 0)),
176 getCppuType(
177 static_cast< Reference< XComponent >
178 const * >(
179 0)),
180 getCppuType(
181 static_cast< Reference< XCloseable >
182 const * >(
183 0)),
184 getCppuType(
185 static_cast< Reference< XResultSetMetaDataSupplier >
186 const * >(
187 0)),
188 getCppuType(
189 static_cast< Reference< XPropertySet >
190 const * >(
191 0)),
192 getCppuType(
193 static_cast< Reference< XPropertyChangeListener >
194 const * >(
195 0)),
196 getCppuType(
197 static_cast< Reference< XVetoableChangeListener >
198 const * >(
199 0)),
200 getCppuType(
201 static_cast< Reference< XResultSet >
202 const * >(
203 0)),
204 getCppuType(
205 static_cast< Reference< XContentAccess >
206 const * >(
207 0)),
208 getCppuType(
209 static_cast< Reference< XRow >
210 const * >(
211 0)),
212 getCppuType(
213 static_cast< Reference< XFetchProvider >
214 const * >(
215 0)),
216 getCppuType(
217 static_cast< Reference< XFetchProviderForContentAccess >
218 const * >(
219 0))
220 );
221 pCollection = &aTheCollection;
222 }
223 }
224 return pCollection->getTypes();
225 */
226 }
227
228 //--------------------------------------------------------------------------
229 // XServiceInfo methods.
230 //--------------------------------------------------------------------------
231
232 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSetStub,
233 OUString::createFromAscii(
234 "com.sun.star.comp.ucb.CachedContentResultSetStub" ),
235 OUString::createFromAscii(
236 CACHED_CRS_STUB_SERVICE_NAME ) );
237
238 //-----------------------------------------------------------------
239 // XFetchProvider methods.
240 //-----------------------------------------------------------------
241
242 #define FETCH_XXX( impl_loadRow, loadInterface ) \
243 impl_EnsureNotDisposed(); \
244 if( !m_xResultSetOrigin.is() ) \
245 { \
246 OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \
247 throw RuntimeException(); \
248 } \
249 impl_propagateFetchSizeAndDirection( nRowCount, bDirection ); \
250 FetchResult aRet; \
251 aRet.StartIndex = nRowStartPosition; \
252 aRet.Orientation = bDirection; \
253 aRet.FetchError = FetchError::SUCCESS; /*ENDOFDATA, EXCEPTION*/ \
254 sal_Int32 nOldOriginal_Pos = m_xResultSetOrigin->getRow(); \
255 if( impl_isForwardOnly() ) \
256 { \
257 if( nOldOriginal_Pos != nRowStartPosition ) \
258 { \
259 /*@todo*/ \
260 aRet.FetchError = FetchError::EXCEPTION; \
261 return aRet; \
262 } \
263 if( nRowCount != 1 ) \
264 aRet.FetchError = FetchError::EXCEPTION; \
265 \
266 aRet.Rows.realloc( 1 ); \
267 \
268 try \
269 { \
270 impl_loadRow( aRet.Rows[0], loadInterface ); \
271 } \
272 catch( SQLException& ) \
273 { \
274 aRet.Rows.realloc( 0 ); \
275 aRet.FetchError = FetchError::EXCEPTION; \
276 return aRet; \
277 } \
278 return aRet; \
279 } \
280 aRet.Rows.realloc( nRowCount ); \
281 sal_Bool bOldOriginal_AfterLast = sal_False; \
282 if( !nOldOriginal_Pos ) \
283 bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast(); \
284 sal_Int32 nN = 1; \
285 sal_Bool bValidNewPos = sal_False; \
286 try \
287 { \
288 try \
289 { \
290 /*if( nOldOriginal_Pos != nRowStartPosition )*/ \
291 bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition ); \
292 } \
293 catch( SQLException& ) \
294 { \
295 aRet.Rows.realloc( 0 ); \
296 aRet.FetchError = FetchError::EXCEPTION; \
297 return aRet; \
298 } \
299 if( !bValidNewPos ) \
300 { \
301 aRet.Rows.realloc( 0 ); \
302 aRet.FetchError = FetchError::EXCEPTION; \
303 \
304 /*restore old position*/ \
305 if( nOldOriginal_Pos ) \
306 m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \
307 else if( bOldOriginal_AfterLast ) \
308 m_xResultSetOrigin->afterLast(); \
309 else \
310 m_xResultSetOrigin->beforeFirst(); \
311 \
312 return aRet; \
313 } \
314 for( ; nN <= nRowCount; ) \
315 { \
316 impl_loadRow( aRet.Rows[nN-1], loadInterface ); \
317 nN++; \
318 if( nN <= nRowCount ) \
319 { \
320 if( bDirection ) \
321 { \
322 if( !m_xResultSetOrigin->next() ) \
323 { \
324 aRet.Rows.realloc( nN-1 ); \
325 aRet.FetchError = FetchError::ENDOFDATA; \
326 break; \
327 } \
328 } \
329 else \
330 { \
331 if( !m_xResultSetOrigin->previous() ) \
332 { \
333 aRet.Rows.realloc( nN-1 ); \
334 aRet.FetchError = FetchError::ENDOFDATA; \
335 break; \
336 } \
337 } \
338 } \
339 } \
340 } \
341 catch( SQLException& ) \
342 { \
343 aRet.Rows.realloc( nN-1 ); \
344 aRet.FetchError = FetchError::EXCEPTION; \
345 } \
346 /*restore old position*/ \
347 if( nOldOriginal_Pos ) \
348 m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \
349 else if( bOldOriginal_AfterLast ) \
350 m_xResultSetOrigin->afterLast(); \
351 else \
352 m_xResultSetOrigin->beforeFirst(); \
353 return aRet;
354
355 FetchResult SAL_CALL CachedContentResultSetStub
fetch(sal_Int32 nRowStartPosition,sal_Int32 nRowCount,sal_Bool bDirection)356 ::fetch( sal_Int32 nRowStartPosition
357 , sal_Int32 nRowCount, sal_Bool bDirection )
358 {
359 impl_init_xRowOrigin();
360 FETCH_XXX( impl_getCurrentRowContent, m_xRowOrigin );
361 }
362
363 sal_Int32 SAL_CALL CachedContentResultSetStub
impl_getColumnCount()364 ::impl_getColumnCount()
365 {
366 sal_Int32 nCount;
367 sal_Bool bCached;
368 {
369 osl::Guard< osl::Mutex > aGuard( m_aMutex );
370 nCount = m_nColumnCount;
371 bCached = m_bColumnCountCached;
372 }
373 if( !bCached )
374 {
375 try
376 {
377 Reference< XResultSetMetaData > xMetaData = getMetaData();
378 if( xMetaData.is() )
379 nCount = xMetaData->getColumnCount();
380 }
381 catch( SQLException& )
382 {
383 OSL_ENSURE( sal_False, "couldn't determine the column count" );
384 nCount = 0;
385 }
386 }
387 osl::Guard< osl::Mutex > aGuard( m_aMutex );
388 m_nColumnCount = nCount;
389 m_bColumnCountCached = sal_True;
390 return m_nColumnCount;
391 }
392
393 void SAL_CALL CachedContentResultSetStub
impl_getCurrentRowContent(Any & rRowContent,Reference<XRow> xRow)394 ::impl_getCurrentRowContent( Any& rRowContent
395 , Reference< XRow > xRow )
396 {
397 sal_Int32 nCount = impl_getColumnCount();
398
399 Sequence< Any > aContent( nCount );
400 for( sal_Int32 nN = 1; nN <= nCount; nN++ )
401 {
402 aContent[nN-1] = xRow->getObject( nN, NULL );
403 }
404
405 rRowContent <<= aContent;
406 }
407
408 void SAL_CALL CachedContentResultSetStub
impl_propagateFetchSizeAndDirection(sal_Int32 nFetchSize,sal_Bool bFetchDirection)409 ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, sal_Bool bFetchDirection )
410 {
411 //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResultSets
412
413 //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls
414
415 //if the underlying ResultSet has a property FetchSize and FetchDirection,
416 //we will set these properties, if the new given parameters are different from the last ones
417
418 if( !m_bNeedToPropagateFetchSize )
419 return;
420
421 sal_Bool bNeedAction;
422 sal_Int32 nLastSize;
423 sal_Bool bLastDirection;
424 sal_Bool bFirstPropagationDone;
425 {
426 osl::Guard< osl::Mutex > aGuard( m_aMutex );
427 bNeedAction = m_bNeedToPropagateFetchSize;
428 nLastSize = m_nLastFetchSize;
429 bLastDirection = m_bLastFetchDirection;
430 bFirstPropagationDone = m_bFirstFetchSizePropagationDone;
431 }
432 if( bNeedAction )
433 {
434 if( nLastSize == nFetchSize
435 && bLastDirection == bFetchDirection
436 && bFirstPropagationDone == sal_True )
437 return;
438
439 if(!bFirstPropagationDone)
440 {
441 //check whether the properties 'FetchSize' and 'FetchDirection' do exist
442
443 Reference< XPropertySetInfo > xPropertySetInfo = getPropertySetInfo();
444 sal_Bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize );
445 sal_Bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection );
446
447 if(!bHasSize || !bHasDirection)
448 {
449 osl::Guard< osl::Mutex > aGuard( m_aMutex );
450 m_bNeedToPropagateFetchSize = sal_False;
451 return;
452 }
453 }
454
455 sal_Bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone;
456 sal_Bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone;
457
458 {
459 osl::Guard< osl::Mutex > aGuard( m_aMutex );
460 m_bFirstFetchSizePropagationDone = sal_True;
461 m_nLastFetchSize = nFetchSize;
462 m_bLastFetchDirection = bFetchDirection;
463 }
464
465 if( bSetSize )
466 {
467 Any aValue;
468 aValue <<= nFetchSize;
469 try
470 {
471 setPropertyValue( m_aPropertyNameForFetchSize, aValue );
472 }
473 catch( com::sun::star::uno::Exception& ) {}
474 }
475 if( bSetDirection )
476 {
477 sal_Int32 nFetchDirection = FetchDirection::FORWARD;
478 if( !bFetchDirection )
479 nFetchDirection = FetchDirection::REVERSE;
480 Any aValue;
481 aValue <<= nFetchDirection;
482 try
483 {
484 setPropertyValue( m_aPropertyNameForFetchDirection, aValue );
485 }
486 catch( com::sun::star::uno::Exception& ) {}
487 }
488
489 }
490 }
491
492 //-----------------------------------------------------------------
493 // XFetchProviderForContentAccess methods.
494 //-----------------------------------------------------------------
495
496 void SAL_CALL CachedContentResultSetStub
impl_getCurrentContentIdentifierString(Any & rAny,Reference<XContentAccess> xContentAccess)497 ::impl_getCurrentContentIdentifierString( Any& rAny
498 , Reference< XContentAccess > xContentAccess )
499 {
500 rAny <<= xContentAccess->queryContentIdentifierString();
501 }
502
503 void SAL_CALL CachedContentResultSetStub
impl_getCurrentContentIdentifier(Any & rAny,Reference<XContentAccess> xContentAccess)504 ::impl_getCurrentContentIdentifier( Any& rAny
505 , Reference< XContentAccess > xContentAccess )
506 {
507 rAny <<= xContentAccess->queryContentIdentifier();
508 }
509
510 void SAL_CALL CachedContentResultSetStub
impl_getCurrentContent(Any & rAny,Reference<XContentAccess> xContentAccess)511 ::impl_getCurrentContent( Any& rAny
512 , Reference< XContentAccess > xContentAccess )
513 {
514 rAny <<= xContentAccess->queryContent();
515 }
516
517 //virtual
518 FetchResult SAL_CALL CachedContentResultSetStub
fetchContentIdentifierStrings(sal_Int32 nRowStartPosition,sal_Int32 nRowCount,sal_Bool bDirection)519 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
520 , sal_Int32 nRowCount, sal_Bool bDirection )
521 {
522 impl_init_xContentAccessOrigin();
523 FETCH_XXX( impl_getCurrentContentIdentifierString, m_xContentAccessOrigin );
524 }
525
526 //virtual
527 FetchResult SAL_CALL CachedContentResultSetStub
fetchContentIdentifiers(sal_Int32 nRowStartPosition,sal_Int32 nRowCount,sal_Bool bDirection)528 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
529 , sal_Int32 nRowCount, sal_Bool bDirection )
530 {
531 impl_init_xContentAccessOrigin();
532 FETCH_XXX( impl_getCurrentContentIdentifier, m_xContentAccessOrigin );
533 }
534
535 //virtual
536 FetchResult SAL_CALL CachedContentResultSetStub
fetchContents(sal_Int32 nRowStartPosition,sal_Int32 nRowCount,sal_Bool bDirection)537 ::fetchContents( sal_Int32 nRowStartPosition
538 , sal_Int32 nRowCount, sal_Bool bDirection )
539 {
540 impl_init_xContentAccessOrigin();
541 FETCH_XXX( impl_getCurrentContent, m_xContentAccessOrigin );
542 }
543
544 //--------------------------------------------------------------------------
545 //--------------------------------------------------------------------------
546 // class CachedContentResultSetStubFactory
547 //--------------------------------------------------------------------------
548 //--------------------------------------------------------------------------
549
CachedContentResultSetStubFactory(const Reference<XMultiServiceFactory> & rSMgr)550 CachedContentResultSetStubFactory::CachedContentResultSetStubFactory(
551 const Reference< XMultiServiceFactory > & rSMgr )
552 {
553 m_xSMgr = rSMgr;
554 }
555
~CachedContentResultSetStubFactory()556 CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory()
557 {
558 }
559
560 //--------------------------------------------------------------------------
561 // CachedContentResultSetStubFactory XInterface methods.
562 //--------------------------------------------------------------------------
563
564 XINTERFACE_IMPL_3( CachedContentResultSetStubFactory,
565 XTypeProvider,
566 XServiceInfo,
567 XCachedContentResultSetStubFactory );
568
569 //--------------------------------------------------------------------------
570 // CachedContentResultSetStubFactory XTypeProvider methods.
571 //--------------------------------------------------------------------------
572
573 XTYPEPROVIDER_IMPL_3( CachedContentResultSetStubFactory,
574 XTypeProvider,
575 XServiceInfo,
576 XCachedContentResultSetStubFactory );
577
578 //--------------------------------------------------------------------------
579 // CachedContentResultSetStubFactory XServiceInfo methods.
580 //--------------------------------------------------------------------------
581
582 XSERVICEINFO_IMPL_1( CachedContentResultSetStubFactory,
583 OUString::createFromAscii(
584 "com.sun.star.comp.ucb.CachedContentResultSetStubFactory" ),
585 OUString::createFromAscii(
586 CACHED_CRS_STUB_FACTORY_NAME ) );
587
588 //--------------------------------------------------------------------------
589 // Service factory implementation.
590 //--------------------------------------------------------------------------
591
592 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetStubFactory );
593
594 //--------------------------------------------------------------------------
595 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
596 //--------------------------------------------------------------------------
597
598 //virtual
599 Reference< XResultSet > SAL_CALL CachedContentResultSetStubFactory
createCachedContentResultSetStub(const Reference<XResultSet> & xSource)600 ::createCachedContentResultSetStub(
601 const Reference< XResultSet > & xSource )
602 {
603 if( xSource.is() )
604 {
605 Reference< XResultSet > xRet;
606 xRet = new CachedContentResultSetStub( xSource );
607 return xRet;
608 }
609 return NULL;
610 }
611