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