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