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
29using namespace com::sun::star::beans;
30using namespace com::sun::star::lang;
31using namespace com::sun::star::sdbc;
32using namespace com::sun::star::ucb;
33using namespace com::sun::star::uno;
34using namespace com::sun::star::util;
35using 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{
55}
56
57
58// XInterface methods.
60 noexcept
61{
62 OWeakObject::acquire();
63}
64
66 noexcept
67{
68 OWeakObject::release();
69}
70
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
96 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
97{
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
111}
112
113
114//virtual
116 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
117{
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
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
168sal_Bool SAL_CALL CachedContentResultSetStub::supportsService( const OUString& ServiceName )
169{
170 return cppu::supportsService( this, ServiceName );
171}
172
173css::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
301FetchResult SAL_CALL CachedContentResultSetStub
302 ::fetch( sal_Int32 nRowStartPosition
303 , sal_Int32 nRowCount, sal_Bool bDirection )
304{
306 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
307 [&](css::uno::Any& rRowContent)
308 { return impl_getCurrentRowContent(rRowContent, m_xRowOrigin); });
309}
310
313{
314 sal_Int32 nCount;
315 bool bCached;
316 {
317 osl::Guard< osl::Mutex > aGuard( m_aMutex );
319 bCached = m_bColumnCountCached;
320 }
321 if( !bCached )
322 {
323 try
324 {
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 );
338 return m_nColumnCount;
339}
340
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
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
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
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 );
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 );
411 m_nLastFetchSize = nFetchSize;
412 m_bLastFetchDirection = bFetchDirection;
413 }
414
415 if( bSetSize )
416 {
417 Any aValue;
418 aValue <<= nFetchSize;
419 try
420 {
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 {
436 }
437 catch( css::uno::Exception& ) {}
438}
439
440
441// XFetchProviderForContentAccess methods.
442
443
446 , const Reference< XContentAccess >& xContentAccess )
447{
448 rAny <<= xContentAccess->queryContentIdentifierString();
449}
450
453 , const Reference< XContentAccess >& xContentAccess )
454{
455 rAny <<= xContentAccess->queryContentIdentifier();
456}
457
460 , const Reference< XContentAccess >& xContentAccess )
461{
462 rAny <<= xContentAccess->queryContent();
463}
464
465//virtual
466FetchResult SAL_CALL CachedContentResultSetStub
467 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
468 , sal_Int32 nRowCount, sal_Bool bDirection )
469{
471 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
472 [&](css::uno::Any& rRowContent)
474}
475
476//virtual
477FetchResult SAL_CALL CachedContentResultSetStub
478 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
479 , sal_Int32 nRowCount, sal_Bool bDirection )
480{
482 return impl_fetchHelper( nRowStartPosition, nRowCount, bDirection,
483 [&](css::uno::Any& rRowContent)
485}
486
487//virtual
488FetchResult SAL_CALL CachedContentResultSetStub
489 ::fetchContents( sal_Int32 nRowStartPosition
490 , sal_Int32 nRowCount, sal_Bool bDirection )
491{
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}
517{
518 return cppu::supportsService( this, ServiceName );
519}
520css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetStubFactory::getSupportedServiceNames()
521{
522 return { "com.sun.star.ucb.CachedContentResultSetStubFactory" };
523}
524
525// Service factory implementation.
526
527
528extern "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
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: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * ucb_CachedContentResultSetStubFactory_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
virtual OUString SAL_CALL getImplementationName() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL createCachedContentResultSetStub(const css::uno::Reference< css::sdbc::XResultSet > &xSource) override
virtual void SAL_CALL acquire() noexcept override
virtual void impl_propertyChange(const css::beans::PropertyChangeEvent &evt) override
virtual css::ucb::FetchResult SAL_CALL fetchContentIdentifierStrings(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, sal_Bool bDirection) override
virtual void impl_vetoableChange(const css::beans::PropertyChangeEvent &aEvent) override
void impl_propagateFetchSizeAndDirection(sal_Int32 nFetchSize, bool bFetchDirection)
static void impl_getCurrentContent(css::uno::Any &rAny, const css::uno::Reference< css::ucb::XContentAccess > &xContentAccess)
virtual css::ucb::FetchResult SAL_CALL fetch(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, sal_Bool bDirection) override
virtual void SAL_CALL release() noexcept override
virtual OUString SAL_CALL getImplementationName() override
virtual css::ucb::FetchResult SAL_CALL fetchContents(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, sal_Bool bDirection) override
css::ucb::FetchResult impl_fetchHelper(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, bool bDirection, std::function< void(css::uno::Any &rRowContent)> impl_loadRow)
static void impl_getCurrentContentIdentifierString(css::uno::Any &rAny, const css::uno::Reference< css::ucb::XContentAccess > &xContentAccess)
static void impl_getCurrentContentIdentifier(css::uno::Any &rAny, const css::uno::Reference< css::ucb::XContentAccess > &xContentAccess)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::ucb::FetchResult SAL_CALL fetchContentIdentifiers(sal_Int32 nRowStartPosition, sal_Int32 nRowCount, sal_Bool bDirection) override
void impl_getCurrentRowContent(css::uno::Any &rRowContent, const css::uno::Reference< css::sdbc::XRow > &xRow)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
CachedContentResultSetStub(css::uno::Reference< css::sdbc::XResultSet > const &xOrigin)
css::uno::Reference< css::sdbc::XResultSet > m_xResultSetOrigin
void impl_notifyVetoableChangeListeners(const css::beans::PropertyChangeEvent &rEvt)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
css::uno::Reference< css::sdbc::XRow > m_xRowOrigin
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
css::uno::Reference< css::ucb::XContentAccess > m_xContentAccessOrigin
! call impl_init_xRowOrigin() bevor you access this member
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
void impl_notifyPropertyChangeListeners(const css::beans::PropertyChangeEvent &rEvt)
int nCount
#define CPPU_TYPE_REF(T)
class SAL_NO_VTABLE XPropertySet
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
XTYPEPROVIDER_COMMON_IMPL(UcbContentProviderProxy)
unsigned char sal_Bool