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  noexcept
61 {
62  OWeakObject::acquire();
63 }
64 
66  noexcept
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 { "com.sun.star.ucb.CachedContentResultSetStub" };
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.getArray()[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  auto pRows = aRet.Rows.getArray();
226  bool bOldOriginal_AfterLast = false;
227  if( !nOldOriginal_Pos )
228  bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast();
229  sal_Int32 nN = 1;
230  try
231  {
232  bool bValidNewPos = false;
233  try
234  {
235  /*if( nOldOriginal_Pos != nRowStartPosition )*/
236  bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition );
237  }
238  catch( SQLException& )
239  {
240  aRet.Rows.realloc( 0 );
241  aRet.FetchError = FetchError::EXCEPTION;
242  return aRet;
243  }
244  if( !bValidNewPos )
245  {
246  aRet.Rows.realloc( 0 );
247  aRet.FetchError = FetchError::EXCEPTION;
248 
249  /*restore old position*/
250  if( nOldOriginal_Pos )
251  m_xResultSetOrigin->absolute( nOldOriginal_Pos );
252  else if( bOldOriginal_AfterLast )
253  m_xResultSetOrigin->afterLast();
254  else
255  m_xResultSetOrigin->beforeFirst();
256 
257  return aRet;
258  }
259  for( ; nN <= nRowCount; )
260  {
261  impl_loadRow( pRows[nN-1] );
262  nN++;
263  if( nN <= nRowCount )
264  {
265  if( bDirection )
266  {
267  if( !m_xResultSetOrigin->next() )
268  {
269  aRet.Rows.realloc( nN-1 );
270  aRet.FetchError = FetchError::ENDOFDATA;
271  break;
272  }
273  }
274  else
275  {
276  if( !m_xResultSetOrigin->previous() )
277  {
278  aRet.Rows.realloc( nN-1 );
279  aRet.FetchError = FetchError::ENDOFDATA;
280  break;
281  }
282  }
283  }
284  }
285  }
286  catch( SQLException& )
287  {
288  aRet.Rows.realloc( nN-1 );
289  aRet.FetchError = FetchError::EXCEPTION;
290  }
291  /*restore old position*/
292  if( nOldOriginal_Pos )
293  m_xResultSetOrigin->absolute( nOldOriginal_Pos );
294  else if( bOldOriginal_AfterLast )
295  m_xResultSetOrigin->afterLast();
296  else
297  m_xResultSetOrigin->beforeFirst();
298  return aRet;
299 }
300 
301 FetchResult SAL_CALL CachedContentResultSetStub
302  ::fetch( sal_Int32 nRowStartPosition
303  , sal_Int32 nRowCount, sal_Bool bDirection )
304 {
305  impl_init_xRowOrigin();
306  return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
307  [&](css::uno::Any& rRowContent)
308  { return impl_getCurrentRowContent(rRowContent, m_xRowOrigin); });
309 }
310 
311 sal_Int32 CachedContentResultSetStub
312  ::impl_getColumnCount()
313 {
314  sal_Int32 nCount;
315  bool bCached;
316  {
317  osl::Guard< osl::Mutex > aGuard( m_aMutex );
318  nCount = m_nColumnCount;
319  bCached = m_bColumnCountCached;
320  }
321  if( !bCached )
322  {
323  try
324  {
325  Reference< XResultSetMetaData > xMetaData = getMetaData();
326  if( xMetaData.is() )
327  nCount = xMetaData->getColumnCount();
328  }
329  catch( SQLException& )
330  {
331  OSL_FAIL( "couldn't determine the column count" );
332  nCount = 0;
333  }
334  }
335  osl::Guard< osl::Mutex > aGuard( m_aMutex );
336  m_nColumnCount = nCount;
337  m_bColumnCountCached = true;
338  return m_nColumnCount;
339 }
340 
341 void CachedContentResultSetStub
342  ::impl_getCurrentRowContent( Any& rRowContent
343  , const Reference< XRow >& xRow )
344 {
345  sal_Int32 nCount = impl_getColumnCount();
346 
347  Sequence< Any > aContent( nCount );
348  auto aContentRange = asNonConstRange(aContent);
349  for( sal_Int32 nN = 1; nN <= nCount; nN++ )
350  {
351  aContentRange[nN-1] = xRow->getObject( nN, nullptr );
352  }
353 
354  rRowContent <<= aContent;
355 }
356 
357 void CachedContentResultSetStub
358  ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, bool bFetchDirection )
359 {
360  //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResultSets
361 
362  //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls
363 
364  //if the underlying ResultSet has a property FetchSize and FetchDirection,
365  //we will set these properties, if the new given parameters are different from the last ones
366 
367  if( !m_bNeedToPropagateFetchSize )
368  return;
369 
370  bool bNeedAction;
371  sal_Int32 nLastSize;
372  bool bLastDirection;
373  bool bFirstPropagationDone;
374  {
375  osl::Guard< osl::Mutex > aGuard( m_aMutex );
376  bNeedAction = m_bNeedToPropagateFetchSize;
377  nLastSize = m_nLastFetchSize;
378  bLastDirection = m_bLastFetchDirection;
379  bFirstPropagationDone = m_bFirstFetchSizePropagationDone;
380  }
381  if( !bNeedAction )
382  return;
383 
384  if( nLastSize == nFetchSize
385  && bLastDirection == bFetchDirection
386  && bFirstPropagationDone )
387  return;
388 
389  if(!bFirstPropagationDone)
390  {
391  //check whether the properties 'FetchSize' and 'FetchDirection' do exist
392 
393  Reference< XPropertySetInfo > xPropertySetInfo = getPropertySetInfo();
394  bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize );
395  bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection );
396 
397  if(!bHasSize || !bHasDirection)
398  {
399  osl::Guard< osl::Mutex > aGuard( m_aMutex );
400  m_bNeedToPropagateFetchSize = false;
401  return;
402  }
403  }
404 
405  bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone;
406  bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone;
407 
408  {
409  osl::Guard< osl::Mutex > aGuard( m_aMutex );
410  m_bFirstFetchSizePropagationDone = true;
411  m_nLastFetchSize = nFetchSize;
412  m_bLastFetchDirection = bFetchDirection;
413  }
414 
415  if( bSetSize )
416  {
417  Any aValue;
418  aValue <<= nFetchSize;
419  try
420  {
421  setPropertyValue( m_aPropertyNameForFetchSize, aValue );
422  }
423  catch( css::uno::Exception& ) {}
424  }
425  if( !bSetDirection )
426  return;
427 
428  sal_Int32 nFetchDirection = FetchDirection::FORWARD;
429  if( !bFetchDirection )
430  nFetchDirection = FetchDirection::REVERSE;
431  Any aValue;
432  aValue <<= nFetchDirection;
433  try
434  {
435  setPropertyValue( m_aPropertyNameForFetchDirection, aValue );
436  }
437  catch( css::uno::Exception& ) {}
438 }
439 
440 
441 // XFetchProviderForContentAccess methods.
442 
443 
444 void CachedContentResultSetStub
445  ::impl_getCurrentContentIdentifierString( Any& rAny
446  , const Reference< XContentAccess >& xContentAccess )
447 {
448  rAny <<= xContentAccess->queryContentIdentifierString();
449 }
450 
451 void CachedContentResultSetStub
452  ::impl_getCurrentContentIdentifier( Any& rAny
453  , const Reference< XContentAccess >& xContentAccess )
454 {
455  rAny <<= xContentAccess->queryContentIdentifier();
456 }
457 
458 void CachedContentResultSetStub
459  ::impl_getCurrentContent( Any& rAny
460  , const Reference< XContentAccess >& xContentAccess )
461 {
462  rAny <<= xContentAccess->queryContent();
463 }
464 
465 //virtual
466 FetchResult SAL_CALL CachedContentResultSetStub
467  ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
468  , sal_Int32 nRowCount, sal_Bool bDirection )
469 {
470  impl_init_xContentAccessOrigin();
471  return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
472  [&](css::uno::Any& rRowContent)
473  { return impl_getCurrentContentIdentifierString(rRowContent, m_xContentAccessOrigin); });
474 }
475 
476 //virtual
477 FetchResult SAL_CALL CachedContentResultSetStub
478  ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
479  , sal_Int32 nRowCount, sal_Bool bDirection )
480 {
481  impl_init_xContentAccessOrigin();
482  return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
483  [&](css::uno::Any& rRowContent)
484  { return impl_getCurrentContentIdentifier(rRowContent, m_xContentAccessOrigin); });
485 }
486 
487 //virtual
488 FetchResult SAL_CALL CachedContentResultSetStub
489  ::fetchContents( sal_Int32 nRowStartPosition
490  , sal_Int32 nRowCount, sal_Bool bDirection )
491 {
492  impl_init_xContentAccessOrigin();
493  return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
494  [&](css::uno::Any& rRowContent)
495  { return impl_getCurrentContent(rRowContent, m_xContentAccessOrigin); });
496 }
497 
498 
499 
500 
502 {
503 }
504 
506 {
507 }
508 
509 
510 // CachedContentResultSetStubFactory XServiceInfo methods.
511 
513 {
514  return "com.sun.star.comp.ucb.CachedContentResultSetStubFactory";
515 }
516 sal_Bool SAL_CALL CachedContentResultSetStubFactory::supportsService( const OUString& ServiceName )
517 {
518  return cppu::supportsService( this, ServiceName );
519 }
520 css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetStubFactory::getSupportedServiceNames()
521 {
522  return { "com.sun.star.ucb.CachedContentResultSetStubFactory" };
523 }
524 
525 // Service factory implementation.
526 
527 
528 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
530  css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
531 {
532  return cppu::acquire(new CachedContentResultSetStubFactory());
533 }
534 
535 
536 
537 
538 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
539 
540 
541  //virtual
542 Reference< XResultSet > SAL_CALL CachedContentResultSetStubFactory
543  ::createCachedContentResultSetStub(
544  const Reference< XResultSet > & xSource )
545 {
546  if( xSource.is() )
547  {
549  return xRet;
550  }
551  return nullptr;
552 }
553 
554 
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Type
virtual OUString SAL_CALL getImplementationName() override
CachedContentResultSetStub(css::uno::Reference< css::sdbc::XResultSet > const &xOrigin)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
css::ucb::FetchResult impl_fetchHelper(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, bool bDirection, std::function< void(css::uno::Any &rRowContent)> impl_loadRow)
virtual void SAL_CALL release() noexcept override
int nCount
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
std::mutex m_aMutex
virtual void SAL_CALL acquire() noexcept override
class SAL_NO_VTABLE XPropertySet
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
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)
#define CPPU_TYPE_REF(T)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * ucb_CachedContentResultSetStubFactory_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
css::uno::Reference< css::sdbc::XResultSet > m_xResultSetOrigin
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool m_bDetectedRangeSegmentation false
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override