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, only called from ContentResultSetWrapperListener
96 ::impl_propertyChange( const PropertyChangeEvent& rEvt )
97{
98 std::unique_lock aGuard(m_aMutex);
100
101 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet
102 //because it will ignore them anyway and we can save this remote calls
103 if( rEvt.PropertyName == m_aPropertyNameForFetchSize
104 || rEvt.PropertyName == m_aPropertyNameForFetchDirection )
105 return;
106
107 PropertyChangeEvent aEvt( rEvt );
108 aEvt.Source = static_cast< XPropertySet * >( this );
109 aEvt.Further = false;
110
112}
113
114
115//virtual, only called from ContentResultSetWrapperListener
117 ::impl_vetoableChange( const PropertyChangeEvent& rEvt )
118{
119 std::unique_lock aGuard(m_aMutex);
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 = false;
131
133}
134
135
136// XTypeProvider methods.
137
138
140//list all interfaces exclusive baseclasses
142 ::getTypes()
143{
144 static Sequence<Type> ourTypes(
145 { CPPU_TYPE_REF( XTypeProvider ),
146 CPPU_TYPE_REF( XServiceInfo ),
147 CPPU_TYPE_REF( XComponent ),
148 CPPU_TYPE_REF( XCloseable ),
149 CPPU_TYPE_REF( XResultSetMetaDataSupplier ),
151 CPPU_TYPE_REF( XPropertyChangeListener ),
152 CPPU_TYPE_REF( XVetoableChangeListener ),
153 CPPU_TYPE_REF( XResultSet ),
154 CPPU_TYPE_REF( XContentAccess ),
155 CPPU_TYPE_REF( XRow ),
156 CPPU_TYPE_REF( XFetchProvider ),
157 CPPU_TYPE_REF( XFetchProviderForContentAccess ) } );
158
159 return ourTypes;
160}
161
162
163// XServiceInfo methods.
164
166{
167 return "com.sun.star.comp.ucb.CachedContentResultSetStub";
168}
169
170sal_Bool SAL_CALL CachedContentResultSetStub::supportsService( const OUString& ServiceName )
171{
172 return cppu::supportsService( this, ServiceName );
173}
174
175css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetStub::getSupportedServiceNames()
176{
177 return { "com.sun.star.ucb.CachedContentResultSetStub" };
178}
179
180
181
182// XFetchProvider methods.
183
184
186 std::unique_lock<std::mutex>& rGuard,
187 sal_Int32 nRowStartPosition, sal_Int32 nRowCount, bool bDirection,
188 std::function<void( std::unique_lock<std::mutex>&, css::uno::Any& rRowContent)> impl_loadRow)
189{
191 if( !m_xResultSetOrigin.is() )
192 {
193 OSL_FAIL( "broadcaster was disposed already" );
194 throw RuntimeException();
195 }
196 impl_propagateFetchSizeAndDirection( rGuard, nRowCount, bDirection );
197 FetchResult aRet;
198 aRet.StartIndex = nRowStartPosition;
199 aRet.Orientation = bDirection;
200 aRet.FetchError = FetchError::SUCCESS; /*ENDOFDATA, EXCEPTION*/
201 sal_Int32 nOldOriginal_Pos = m_xResultSetOrigin->getRow();
202 if( impl_isForwardOnly(rGuard) )
203 {
204 if( nOldOriginal_Pos != nRowStartPosition )
205 {
206 /*@todo*/
207 aRet.FetchError = FetchError::EXCEPTION;
208 return aRet;
209 }
210 if( nRowCount != 1 )
211 aRet.FetchError = FetchError::EXCEPTION;
212
213 aRet.Rows.realloc( 1 );
214
215 try
216 {
217 impl_loadRow( rGuard, aRet.Rows.getArray()[0] );
218 }
219 catch( SQLException& )
220 {
221 aRet.Rows.realloc( 0 );
222 aRet.FetchError = FetchError::EXCEPTION;
223 return aRet;
224 }
225 return aRet;
226 }
227 aRet.Rows.realloc( nRowCount );
228 auto pRows = aRet.Rows.getArray();
229 bool bOldOriginal_AfterLast = false;
230 if( !nOldOriginal_Pos )
231 bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast();
232 sal_Int32 nN = 1;
233 try
234 {
235 bool bValidNewPos = false;
236 try
237 {
238 /*if( nOldOriginal_Pos != nRowStartPosition )*/
239 bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition );
240 }
241 catch( SQLException& )
242 {
243 aRet.Rows.realloc( 0 );
244 aRet.FetchError = FetchError::EXCEPTION;
245 return aRet;
246 }
247 if( !bValidNewPos )
248 {
249 aRet.Rows.realloc( 0 );
250 aRet.FetchError = FetchError::EXCEPTION;
251
252 /*restore old position*/
253 if( nOldOriginal_Pos )
254 m_xResultSetOrigin->absolute( nOldOriginal_Pos );
255 else if( bOldOriginal_AfterLast )
256 m_xResultSetOrigin->afterLast();
257 else
258 m_xResultSetOrigin->beforeFirst();
259
260 return aRet;
261 }
262 for( ; nN <= nRowCount; )
263 {
264 impl_loadRow( rGuard, pRows[nN-1] );
265 nN++;
266 if( nN <= nRowCount )
267 {
268 if( bDirection )
269 {
270 if( !m_xResultSetOrigin->next() )
271 {
272 aRet.Rows.realloc( nN-1 );
273 aRet.FetchError = FetchError::ENDOFDATA;
274 break;
275 }
276 }
277 else
278 {
279 if( !m_xResultSetOrigin->previous() )
280 {
281 aRet.Rows.realloc( nN-1 );
282 aRet.FetchError = FetchError::ENDOFDATA;
283 break;
284 }
285 }
286 }
287 }
288 }
289 catch( SQLException& )
290 {
291 aRet.Rows.realloc( nN-1 );
292 aRet.FetchError = FetchError::EXCEPTION;
293 }
294 /*restore old position*/
295 if( nOldOriginal_Pos )
296 m_xResultSetOrigin->absolute( nOldOriginal_Pos );
297 else if( bOldOriginal_AfterLast )
298 m_xResultSetOrigin->afterLast();
299 else
300 m_xResultSetOrigin->beforeFirst();
301 return aRet;
302}
303
304FetchResult SAL_CALL CachedContentResultSetStub
305 ::fetch( sal_Int32 nRowStartPosition
306 , sal_Int32 nRowCount, sal_Bool bDirection )
307{
308 std::unique_lock aGuard(m_aMutex);
309 impl_init_xRowOrigin(aGuard);
310 return impl_fetchHelper( aGuard, nRowStartPosition, nRowCount, bDirection,
311 [&](std::unique_lock<std::mutex>& rGuard, css::uno::Any& rRowContent)
312 { return impl_getCurrentRowContent(rGuard, rRowContent, m_xRowOrigin); });
313}
314
316 ::impl_getColumnCount(std::unique_lock<std::mutex>& /*rGuard*/)
317{
318 sal_Int32 nCount;
319 bool bCached;
321 bCached = m_bColumnCountCached;
322 if( !bCached )
323 {
324 try
325 {
327 if( xMetaData.is() )
328 nCount = xMetaData->getColumnCount();
329 }
330 catch( SQLException& )
331 {
332 OSL_FAIL( "couldn't determine the column count" );
333 nCount = 0;
334 }
335 }
338 return m_nColumnCount;
339}
340
342 ::impl_getCurrentRowContent( std::unique_lock<std::mutex>& rGuard, Any& rRowContent
343 , const Reference< XRow >& xRow )
344{
345 sal_Int32 nCount = impl_getColumnCount(rGuard);
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( std::unique_lock<std::mutex>& rGuard, 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 bNeedAction = m_bNeedToPropagateFetchSize;
375 nLastSize = m_nLastFetchSize;
376 bLastDirection = m_bLastFetchDirection;
377 bFirstPropagationDone = m_bFirstFetchSizePropagationDone;
378 if( !bNeedAction )
379 return;
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
391 bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize );
392 bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection );
393
394 if(!bHasSize || !bHasDirection)
395 {
397 return;
398 }
399 }
400
401 bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone;
402 bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone;
403
405 m_nLastFetchSize = nFetchSize;
406 m_bLastFetchDirection = bFetchDirection;
407
408 if( bSetSize )
409 {
410 Any aValue;
411 aValue <<= nFetchSize;
412 try
413 {
415 }
416 catch( css::uno::Exception& ) {}
417 }
418 if( !bSetDirection )
419 return;
420
421 sal_Int32 nFetchDirection = FetchDirection::FORWARD;
422 if( !bFetchDirection )
423 nFetchDirection = FetchDirection::REVERSE;
424 Any aValue;
425 aValue <<= nFetchDirection;
426 try
427 {
429 }
430 catch( css::uno::Exception& ) {}
431}
432
433
434// XFetchProviderForContentAccess methods.
435
436
438 ::impl_getCurrentContentIdentifierString( std::unique_lock<std::mutex>& /*rGuard*/, Any& rAny
439 , const Reference< XContentAccess >& xContentAccess )
440{
441 rAny <<= xContentAccess->queryContentIdentifierString();
442}
443
445 ::impl_getCurrentContentIdentifier( std::unique_lock<std::mutex>& /*rGuard*/, Any& rAny
446 , const Reference< XContentAccess >& xContentAccess )
447{
448 rAny <<= xContentAccess->queryContentIdentifier();
449}
450
452 ::impl_getCurrentContent( std::unique_lock<std::mutex>& /*rGuard*/, Any& rAny
453 , const Reference< XContentAccess >& xContentAccess )
454{
455 rAny <<= xContentAccess->queryContent();
456}
457
458//virtual
459FetchResult SAL_CALL CachedContentResultSetStub
460 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
461 , sal_Int32 nRowCount, sal_Bool bDirection )
462{
463 std::unique_lock aGuard( m_aMutex );
465 return impl_fetchHelper( aGuard, nRowStartPosition, nRowCount, bDirection,
466 [&](std::unique_lock<std::mutex>& rGuard, css::uno::Any& rRowContent)
467 { return impl_getCurrentContentIdentifierString(rGuard, rRowContent, m_xContentAccessOrigin); });
468}
469
470//virtual
471FetchResult SAL_CALL CachedContentResultSetStub
472 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
473 , sal_Int32 nRowCount, sal_Bool bDirection )
474{
475 std::unique_lock aGuard( m_aMutex );
477 return impl_fetchHelper( aGuard, nRowStartPosition, nRowCount, bDirection,
478 [&](std::unique_lock<std::mutex>& rGuard, css::uno::Any& rRowContent)
479 { return impl_getCurrentContentIdentifier(rGuard, rRowContent, m_xContentAccessOrigin); });
480}
481
482//virtual
483FetchResult SAL_CALL CachedContentResultSetStub
484 ::fetchContents( sal_Int32 nRowStartPosition
485 , sal_Int32 nRowCount, sal_Bool bDirection )
486{
487 std::unique_lock aGuard( m_aMutex );
489 return impl_fetchHelper( aGuard, nRowStartPosition, nRowCount, bDirection,
490 [&](std::unique_lock<std::mutex>& rGuard, css::uno::Any& rRowContent)
491 { return impl_getCurrentContent(rGuard, rRowContent, m_xContentAccessOrigin); });
492}
493
494
495
496
498{
499}
500
502{
503}
504
505
506// CachedContentResultSetStubFactory XServiceInfo methods.
507
509{
510 return "com.sun.star.comp.ucb.CachedContentResultSetStubFactory";
511}
513{
514 return cppu::supportsService( this, ServiceName );
515}
516css::uno::Sequence< OUString > SAL_CALL CachedContentResultSetStubFactory::getSupportedServiceNames()
517{
518 return { "com.sun.star.ucb.CachedContentResultSetStubFactory" };
519}
520
521// Service factory implementation.
522
523
524extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
526 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
527{
528 return cppu::acquire(new CachedContentResultSetStubFactory());
529}
530
531
532
533
534// CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
535
536
537 //virtual
540 const Reference< XResultSet > & xSource )
541{
542 if( xSource.is() )
543 {
545 return xRet;
546 }
547 return nullptr;
548}
549
550
551/* 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
static void impl_getCurrentContentIdentifier(std::unique_lock< std::mutex > &rGuard, css::uno::Any &rAny, const css::uno::Reference< css::ucb::XContentAccess > &xContentAccess)
virtual void impl_vetoableChange(const css::beans::PropertyChangeEvent &aEvent) override
css::ucb::FetchResult impl_fetchHelper(std::unique_lock< std::mutex > &rGuard, sal_Int32 nRowStartPosition, sal_Int32 nRowCount, bool bDirection, std::function< void(std::unique_lock< std::mutex > &, css::uno::Any &rRowContent)> impl_loadRow)
static void impl_getCurrentContent(std::unique_lock< std::mutex > &rGuard, css::uno::Any &rAny, const css::uno::Reference< css::ucb::XContentAccess > &xContentAccess)
static void impl_getCurrentContentIdentifierString(std::unique_lock< std::mutex > &rGuard, 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
void impl_getCurrentRowContent(std::unique_lock< std::mutex > &rGuard, css::uno::Any &rRowContent, const css::uno::Reference< css::sdbc::XRow > &xRow)
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
void impl_propagateFetchSizeAndDirection(std::unique_lock< std::mutex > &rGuard, sal_Int32 nFetchSize, bool bFetchDirection)
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
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
sal_Int32 impl_getColumnCount(std::unique_lock< std::mutex > &)
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(std::unique_lock< std::mutex > &rGuard, const css::beans::PropertyChangeEvent &rEvt)
void impl_EnsureNotDisposed(std::unique_lock< std::mutex > &rGuard)
virtual void setPropertyValueImpl(std::unique_lock< std::mutex > &rGuard, const OUString &aPropertyName, const css::uno::Any &aValue)
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
css::uno::Reference< css::sdbc::XRow > m_xRowOrigin
bool impl_isForwardOnly(std::unique_lock< std::mutex > &rGuard)
void impl_init_xRowOrigin(std::unique_lock< std::mutex > &)
void impl_notifyPropertyChangeListeners(std::unique_lock< std::mutex > &rGuard, const css::beans::PropertyChangeEvent &rEvt)
void impl_init_xContentAccessOrigin(std::unique_lock< std::mutex > &)
css::uno::Reference< css::ucb::XContentAccess > m_xContentAccessOrigin
! call impl_init_xRowOrigin() bevor you access this member
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override final
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
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