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