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