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