1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "cachedcontentresultsetstub.hxx"
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>
26 #include <cppuhelper/queryinterface.hxx>
27 #include <ucbhelper/macros.hxx>
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
;
38 CachedContentResultSetStub::CachedContentResultSetStub( Reference
< XResultSet
> const & xOrigin
)
39 : ContentResultSetWrapper( xOrigin
)
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") )
52 CachedContentResultSetStub::~CachedContentResultSetStub()
58 // XInterface methods.
59 void SAL_CALL
CachedContentResultSetStub::acquire()
62 OWeakObject::acquire();
65 void SAL_CALL
CachedContentResultSetStub::release()
68 OWeakObject::release();
71 Any SAL_CALL CachedContentResultSetStub
72 ::queryInterface( const Type
& rType
)
74 //list all interfaces inclusive baseclasses of interfaces
76 Any aRet
= ContentResultSetWrapper::queryInterface( rType
);
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 )
87 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
91 // own methods. ( inherited )
94 //virtual, only called from ContentResultSetWrapperListener
95 void CachedContentResultSetStub
96 ::impl_propertyChange( const PropertyChangeEvent
& rEvt
)
98 std::unique_lock
aGuard(m_aMutex
);
99 impl_EnsureNotDisposed(aGuard
);
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
)
107 PropertyChangeEvent
aEvt( rEvt
);
108 aEvt
.Source
= static_cast< XPropertySet
* >( this );
109 aEvt
.Further
= false;
111 impl_notifyPropertyChangeListeners( aGuard
, aEvt
);
115 //virtual, only called from ContentResultSetWrapperListener
116 void CachedContentResultSetStub
117 ::impl_vetoableChange( const PropertyChangeEvent
& rEvt
)
119 std::unique_lock
aGuard(m_aMutex
);
120 impl_EnsureNotDisposed(aGuard
);
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
)
128 PropertyChangeEvent
aEvt( rEvt
);
129 aEvt
.Source
= static_cast< XPropertySet
* >( this );
130 aEvt
.Further
= false;
132 impl_notifyVetoableChangeListeners( aGuard
, aEvt
);
136 // XTypeProvider methods.
139 XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub
)
140 //list all interfaces exclusive baseclasses
141 Sequence
< Type
> SAL_CALL CachedContentResultSetStub
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
),
150 CPPU_TYPE_REF( XPropertySet
),
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
) } );
163 // XServiceInfo methods.
165 OUString SAL_CALL
CachedContentResultSetStub::getImplementationName()
167 return "com.sun.star.comp.ucb.CachedContentResultSetStub";
170 sal_Bool SAL_CALL
CachedContentResultSetStub::supportsService( const OUString
& ServiceName
)
172 return cppu::supportsService( this, ServiceName
);
175 css::uno::Sequence
< OUString
> SAL_CALL
CachedContentResultSetStub::getSupportedServiceNames()
177 return { "com.sun.star.ucb.CachedContentResultSetStub" };
182 // XFetchProvider methods.
185 FetchResult
CachedContentResultSetStub::impl_fetchHelper(
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
)
190 impl_EnsureNotDisposed(rGuard
);
191 if( !m_xResultSetOrigin
.is() )
193 OSL_FAIL( "broadcaster was disposed already" );
194 throw RuntimeException();
196 impl_propagateFetchSizeAndDirection( rGuard
, nRowCount
, bDirection
);
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
) )
204 if( nOldOriginal_Pos
!= nRowStartPosition
)
207 aRet
.FetchError
= FetchError::EXCEPTION
;
211 aRet
.FetchError
= FetchError::EXCEPTION
;
213 aRet
.Rows
.realloc( 1 );
217 impl_loadRow( rGuard
, aRet
.Rows
.getArray()[0] );
219 catch( SQLException
& )
221 aRet
.Rows
.realloc( 0 );
222 aRet
.FetchError
= FetchError::EXCEPTION
;
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();
235 bool bValidNewPos
= false;
238 /*if( nOldOriginal_Pos != nRowStartPosition )*/
239 bValidNewPos
= m_xResultSetOrigin
->absolute( nRowStartPosition
);
241 catch( SQLException
& )
243 aRet
.Rows
.realloc( 0 );
244 aRet
.FetchError
= FetchError::EXCEPTION
;
249 aRet
.Rows
.realloc( 0 );
250 aRet
.FetchError
= FetchError::EXCEPTION
;
252 /*restore old position*/
253 if( nOldOriginal_Pos
)
254 m_xResultSetOrigin
->absolute( nOldOriginal_Pos
);
255 else if( bOldOriginal_AfterLast
)
256 m_xResultSetOrigin
->afterLast();
258 m_xResultSetOrigin
->beforeFirst();
262 for( ; nN
<= nRowCount
; )
264 impl_loadRow( rGuard
, pRows
[nN
-1] );
266 if( nN
<= nRowCount
)
270 if( !m_xResultSetOrigin
->next() )
272 aRet
.Rows
.realloc( nN
-1 );
273 aRet
.FetchError
= FetchError::ENDOFDATA
;
279 if( !m_xResultSetOrigin
->previous() )
281 aRet
.Rows
.realloc( nN
-1 );
282 aRet
.FetchError
= FetchError::ENDOFDATA
;
289 catch( SQLException
& )
291 aRet
.Rows
.realloc( nN
-1 );
292 aRet
.FetchError
= FetchError::EXCEPTION
;
294 /*restore old position*/
295 if( nOldOriginal_Pos
)
296 m_xResultSetOrigin
->absolute( nOldOriginal_Pos
);
297 else if( bOldOriginal_AfterLast
)
298 m_xResultSetOrigin
->afterLast();
300 m_xResultSetOrigin
->beforeFirst();
304 FetchResult SAL_CALL CachedContentResultSetStub
305 ::fetch( sal_Int32 nRowStartPosition
306 , sal_Int32 nRowCount
, sal_Bool bDirection
)
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
); });
315 sal_Int32 CachedContentResultSetStub
316 ::impl_getColumnCount(std::unique_lock
<std::mutex
>& /*rGuard*/)
320 nCount
= m_nColumnCount
;
321 bCached
= m_bColumnCountCached
;
326 Reference
< XResultSetMetaData
> xMetaData
= getMetaData();
328 nCount
= xMetaData
->getColumnCount();
330 catch( SQLException
& )
332 OSL_FAIL( "couldn't determine the column count" );
336 m_nColumnCount
= nCount
;
337 m_bColumnCountCached
= true;
338 return m_nColumnCount
;
341 void CachedContentResultSetStub
342 ::impl_getCurrentRowContent( std::unique_lock
<std::mutex
>& rGuard
, Any
& rRowContent
343 , const Reference
< XRow
>& xRow
)
345 sal_Int32 nCount
= impl_getColumnCount(rGuard
);
347 Sequence
< Any
> aContent( nCount
);
348 auto aContentRange
= asNonConstRange(aContent
);
349 for( sal_Int32 nN
= 1; nN
<= nCount
; nN
++ )
351 aContentRange
[nN
-1] = xRow
->getObject( nN
, nullptr );
354 rRowContent
<<= aContent
;
357 void CachedContentResultSetStub
358 ::impl_propagateFetchSizeAndDirection( std::unique_lock
<std::mutex
>& rGuard
, sal_Int32 nFetchSize
, bool bFetchDirection
)
360 //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResultSets
362 //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls
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
367 if( !m_bNeedToPropagateFetchSize
)
373 bool bFirstPropagationDone
;
374 bNeedAction
= m_bNeedToPropagateFetchSize
;
375 nLastSize
= m_nLastFetchSize
;
376 bLastDirection
= m_bLastFetchDirection
;
377 bFirstPropagationDone
= m_bFirstFetchSizePropagationDone
;
381 if( nLastSize
== nFetchSize
382 && bLastDirection
== bFetchDirection
383 && bFirstPropagationDone
)
386 if(!bFirstPropagationDone
)
388 //check whether the properties 'FetchSize' and 'FetchDirection' do exist
390 Reference
< XPropertySetInfo
> xPropertySetInfo
= getPropertySetInfo();
391 bool bHasSize
= xPropertySetInfo
->hasPropertyByName( m_aPropertyNameForFetchSize
);
392 bool bHasDirection
= xPropertySetInfo
->hasPropertyByName( m_aPropertyNameForFetchDirection
);
394 if(!bHasSize
|| !bHasDirection
)
396 m_bNeedToPropagateFetchSize
= false;
401 bool bSetSize
= ( nLastSize
!=nFetchSize
) || !bFirstPropagationDone
;
402 bool bSetDirection
= ( bLastDirection
!=bFetchDirection
) || !bFirstPropagationDone
;
404 m_bFirstFetchSizePropagationDone
= true;
405 m_nLastFetchSize
= nFetchSize
;
406 m_bLastFetchDirection
= bFetchDirection
;
411 aValue
<<= nFetchSize
;
414 setPropertyValueImpl( rGuard
, m_aPropertyNameForFetchSize
, aValue
);
416 catch( css::uno::Exception
& ) {}
421 sal_Int32 nFetchDirection
= FetchDirection::FORWARD
;
422 if( !bFetchDirection
)
423 nFetchDirection
= FetchDirection::REVERSE
;
425 aValue
<<= nFetchDirection
;
428 setPropertyValueImpl( rGuard
, m_aPropertyNameForFetchDirection
, aValue
);
430 catch( css::uno::Exception
& ) {}
434 // XFetchProviderForContentAccess methods.
437 void CachedContentResultSetStub
438 ::impl_getCurrentContentIdentifierString( std::unique_lock
<std::mutex
>& /*rGuard*/, Any
& rAny
439 , const Reference
< XContentAccess
>& xContentAccess
)
441 rAny
<<= xContentAccess
->queryContentIdentifierString();
444 void CachedContentResultSetStub
445 ::impl_getCurrentContentIdentifier( std::unique_lock
<std::mutex
>& /*rGuard*/, Any
& rAny
446 , const Reference
< XContentAccess
>& xContentAccess
)
448 rAny
<<= xContentAccess
->queryContentIdentifier();
451 void CachedContentResultSetStub
452 ::impl_getCurrentContent( std::unique_lock
<std::mutex
>& /*rGuard*/, Any
& rAny
453 , const Reference
< XContentAccess
>& xContentAccess
)
455 rAny
<<= xContentAccess
->queryContent();
459 FetchResult SAL_CALL CachedContentResultSetStub
460 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition
461 , sal_Int32 nRowCount
, sal_Bool bDirection
)
463 std::unique_lock
aGuard( m_aMutex
);
464 impl_init_xContentAccessOrigin(aGuard
);
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
); });
471 FetchResult SAL_CALL CachedContentResultSetStub
472 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition
473 , sal_Int32 nRowCount
, sal_Bool bDirection
)
475 std::unique_lock
aGuard( m_aMutex
);
476 impl_init_xContentAccessOrigin(aGuard
);
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
); });
483 FetchResult SAL_CALL CachedContentResultSetStub
484 ::fetchContents( sal_Int32 nRowStartPosition
485 , sal_Int32 nRowCount
, sal_Bool bDirection
)
487 std::unique_lock
aGuard( m_aMutex
);
488 impl_init_xContentAccessOrigin(aGuard
);
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
); });
497 CachedContentResultSetStubFactory::CachedContentResultSetStubFactory()
501 CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory()
506 // CachedContentResultSetStubFactory XServiceInfo methods.
508 OUString SAL_CALL
CachedContentResultSetStubFactory::getImplementationName()
510 return "com.sun.star.comp.ucb.CachedContentResultSetStubFactory";
512 sal_Bool SAL_CALL
CachedContentResultSetStubFactory::supportsService( const OUString
& ServiceName
)
514 return cppu::supportsService( this, ServiceName
);
516 css::uno::Sequence
< OUString
> SAL_CALL
CachedContentResultSetStubFactory::getSupportedServiceNames()
518 return { "com.sun.star.ucb.CachedContentResultSetStubFactory" };
521 // Service factory implementation.
524 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
525 ucb_CachedContentResultSetStubFactory_get_implementation(
526 css::uno::XComponentContext
* , css::uno::Sequence
<css::uno::Any
> const&)
528 return cppu::acquire(new CachedContentResultSetStubFactory());
534 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods.
538 Reference
< XResultSet
> SAL_CALL CachedContentResultSetStubFactory
539 ::createCachedContentResultSetStub(
540 const Reference
< XResultSet
> & xSource
)
544 Reference
< XResultSet
> xRet
= new CachedContentResultSetStub( xSource
);
551 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */