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