Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / file / filrset.cxx
blob5f0d4ec3a25c563163984fd4ea9b63d25d4c71cc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <com/sun/star/sdbc/SQLException.hpp>
24 #include <com/sun/star/ucb/ListenerAlreadySetException.hpp>
25 #include <com/sun/star/ucb/ServiceNotFoundException.hpp>
26 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
27 #include "filid.hxx"
28 #include "filtask.hxx"
29 #include "filprp.hxx"
30 #include "filrset.hxx"
31 #include <com/sun/star/ucb/OpenMode.hpp>
32 #include "prov.hxx"
33 #include <com/sun/star/uno/Reference.h>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/ucb/ListActionType.hpp>
37 #include <com/sun/star/ucb/XSourceInitialization.hpp>
38 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
39 #include <ucbhelper/resultsetmetadata.hxx>
41 using namespace fileaccess;
42 using namespace com::sun::star;
44 #if OSL_DEBUG_LEVEL > 0
45 #define THROW_WHERE SAL_WHERE
46 #else
47 #define THROW_WHERE ""
48 #endif
50 XResultSet_impl::XResultSet_impl( TaskManager* pMyShell,
51 const OUString& aUnqPath,
52 sal_Int32 OpenMode,
53 const uno::Sequence< beans::Property >& seq,
54 const uno::Sequence< ucb::NumberedSortingInfo >& seqSort )
55 : m_pMyShell( pMyShell )
56 , m_nRow( -1 )
57 , m_nWasNull ( false )
58 , m_nOpenMode( OpenMode )
59 , m_bRowCountFinal( false )
60 , m_aBaseDirectory( aUnqPath )
61 , m_aFolder( aUnqPath )
62 , m_sProperty( seq )
63 , m_sSortingInfo( seqSort )
64 , m_nErrorCode( TASKHANDLER_NO_ERROR )
65 , m_nMinorErrorCode( TASKHANDLER_NO_ERROR )
67 osl::FileBase::RC err = m_aFolder.open();
68 if( err != osl::FileBase::E_None )
70 m_nIsOpen = false;
71 m_aFolder.close();
73 m_nErrorCode = TASKHANDLING_OPEN_FOR_DIRECTORYLISTING;
74 m_nMinorErrorCode = err;
76 else
77 m_nIsOpen = true;
81 XResultSet_impl::~XResultSet_impl()
83 if( m_nIsOpen )
84 m_aFolder.close();
88 void SAL_CALL
89 XResultSet_impl::disposing( const lang::EventObject& )
91 // To do, but what
95 void SAL_CALL
96 XResultSet_impl::addEventListener(
97 const uno::Reference< lang::XEventListener >& Listener )
99 std::unique_lock aGuard( m_aMutex );
101 m_aDisposeEventListeners.addInterface( aGuard, Listener );
105 void SAL_CALL
106 XResultSet_impl::removeEventListener(
107 const uno::Reference< lang::XEventListener >& Listener )
109 std::unique_lock aGuard( m_aMutex );
111 m_aDisposeEventListeners.removeInterface( aGuard, Listener );
115 void SAL_CALL
116 XResultSet_impl::dispose()
118 std::unique_lock aGuard( m_aMutex );
120 lang::EventObject aEvt;
121 aEvt.Source = static_cast< lang::XComponent * >( this );
123 m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt );
124 m_aRowCountListeners.disposeAndClear( aGuard, aEvt );
125 m_aIsFinalListeners.disposeAndClear( aGuard, aEvt );
129 void XResultSet_impl::rowCountChanged(std::unique_lock<std::mutex>& rGuard)
131 sal_Int32 aOldValue,aNewValue;
132 std::vector< uno::Reference< beans::XPropertyChangeListener > > seq = m_aRowCountListeners.getElements(rGuard);
133 aNewValue = m_aItems.size();
134 aOldValue = aNewValue-1;
135 beans::PropertyChangeEvent aEv;
136 aEv.PropertyName = "RowCount";
137 aEv.Further = false;
138 aEv.PropertyHandle = -1;
139 aEv.OldValue <<= aOldValue;
140 aEv.NewValue <<= aNewValue;
141 for( const auto& listener : seq )
142 listener->propertyChange( aEv );
146 void XResultSet_impl::isFinalChanged()
148 std::vector< uno::Reference< beans::XPropertyChangeListener > > seq;
150 std::unique_lock aGuard( m_aMutex );
151 seq = m_aIsFinalListeners.getElements(aGuard);
152 m_bRowCountFinal = true;
154 beans::PropertyChangeEvent aEv;
155 aEv.PropertyName = "IsRowCountFinal";
156 aEv.Further = false;
157 aEv.PropertyHandle = -1;
158 aEv.OldValue <<= false;
159 aEv.NewValue <<= true;
160 for( const auto& listener : seq )
161 listener->propertyChange( aEv );
165 bool
166 XResultSet_impl::OneMore()
168 if( ! m_nIsOpen )
169 return false;
171 osl::FileBase::RC err;
172 bool IsRegular;
173 OUString aUnqPath;
174 osl::DirectoryItem aDirIte;
175 uno::Reference< sdbc::XRow > aRow;
177 while( true )
179 err = m_aFolder.getNextItem( aDirIte );
181 if( err == osl::FileBase::E_NOENT || err == osl::FileBase::E_INVAL )
183 m_aFolder.close();
184 isFinalChanged();
185 m_nIsOpen = false;
186 return m_nIsOpen;
188 else if( err == osl::FileBase::E_None )
190 if (!m_pMyShell->getv( m_sProperty, aDirIte, aUnqPath, IsRegular, aRow ))
192 SAL_WARN(
193 "ucb.ucp.file",
194 "getting dir item in <" << m_aBaseDirectory << "> failed");
195 continue;
198 if( m_nOpenMode == ucb::OpenMode::DOCUMENTS && IsRegular )
200 std::unique_lock aGuard( m_aMutex );
201 m_aItems.push_back( aRow );
202 m_aIdents.emplace_back( );
203 m_aUnqPath.push_back( aUnqPath );
204 rowCountChanged(aGuard);
205 return true;
208 else if( m_nOpenMode == ucb::OpenMode::DOCUMENTS && ! IsRegular )
210 continue;
212 else if( m_nOpenMode == ucb::OpenMode::FOLDERS && ! IsRegular )
214 std::unique_lock aGuard( m_aMutex );
215 m_aItems.push_back( aRow );
216 m_aIdents.emplace_back( );
217 m_aUnqPath.push_back( aUnqPath );
218 rowCountChanged(aGuard);
219 return true;
221 else if( m_nOpenMode == ucb::OpenMode::FOLDERS && IsRegular )
223 continue;
225 else
227 std::unique_lock aGuard( m_aMutex );
228 m_aItems.push_back( aRow );
229 m_aIdents.emplace_back( );
230 m_aUnqPath.push_back( aUnqPath );
231 rowCountChanged(aGuard);
232 return true;
235 else // error fetching anything
237 throw sdbc::SQLException( THROW_WHERE, uno::Reference< uno::XInterface >(), OUString(), 0, uno::Any() );
243 sal_Bool SAL_CALL
244 XResultSet_impl::next()
246 bool test;
247 if( ++m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) ) test = true;
248 else
249 test = OneMore();
250 return test;
254 sal_Bool SAL_CALL
255 XResultSet_impl::isBeforeFirst()
257 return m_nRow == -1;
261 sal_Bool SAL_CALL
262 XResultSet_impl::isAfterLast()
264 return m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()); // Cannot happen, if m_aFolder.isOpen()
268 sal_Bool SAL_CALL
269 XResultSet_impl::isFirst()
271 return m_nRow == 0;
275 sal_Bool SAL_CALL
276 XResultSet_impl::isLast()
278 if( m_nRow == sal::static_int_cast<sal_Int32>(m_aItems.size()) - 1 )
279 return ! OneMore();
280 else
281 return false;
285 void SAL_CALL
286 XResultSet_impl::beforeFirst()
288 m_nRow = -1;
292 void SAL_CALL
293 XResultSet_impl::afterLast()
295 m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size());
296 while( OneMore() )
297 ++m_nRow;
301 sal_Bool SAL_CALL
302 XResultSet_impl::first()
304 m_nRow = -1;
305 return next();
309 sal_Bool SAL_CALL
310 XResultSet_impl::last()
312 m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size()) - 1;
313 while( OneMore() )
314 ++m_nRow;
315 return true;
319 sal_Int32 SAL_CALL
320 XResultSet_impl::getRow()
322 // Test, whether behind last row
323 if( -1 == m_nRow || m_nRow >= sal::static_int_cast<sal_Int32>(m_aItems.size()) )
324 return 0;
325 else
326 return m_nRow+1;
330 sal_Bool SAL_CALL XResultSet_impl::absolute( sal_Int32 row )
332 if( row >= 0 )
334 m_nRow = row - 1;
335 if( row >= sal::static_int_cast<sal_Int32>(m_aItems.size()) )
336 while( row-- && OneMore() )
339 else
341 last();
342 m_nRow += ( row + 1 );
343 if( m_nRow < -1 )
344 m_nRow = -1;
347 return 0<= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size());
351 sal_Bool SAL_CALL
352 XResultSet_impl::relative( sal_Int32 row )
354 if( isAfterLast() || isBeforeFirst() )
355 throw sdbc::SQLException( THROW_WHERE, uno::Reference< uno::XInterface >(), OUString(), 0, uno::Any() );
356 if( row > 0 )
357 while( row-- ) next();
358 else if( row < 0 )
359 while( row++ && m_nRow > - 1 ) previous();
361 return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size());
365 sal_Bool SAL_CALL
366 XResultSet_impl::previous()
368 if( m_nRow > sal::static_int_cast<sal_Int32>(m_aItems.size()) )
369 m_nRow = sal::static_int_cast<sal_Int32>(m_aItems.size()); // Correct Handling of afterLast
370 if( 0 <= m_nRow ) -- m_nRow;
372 return 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size());
376 void SAL_CALL
377 XResultSet_impl::refreshRow()
379 // get the row from the filesystem
383 sal_Bool SAL_CALL
384 XResultSet_impl::rowUpdated()
386 return false;
389 sal_Bool SAL_CALL
390 XResultSet_impl::rowInserted()
392 return false;
395 sal_Bool SAL_CALL
396 XResultSet_impl::rowDeleted()
398 return false;
402 uno::Reference< uno::XInterface > SAL_CALL
403 XResultSet_impl::getStatement()
405 return uno::Reference< uno::XInterface >();
409 // XCloseable
411 void SAL_CALL
412 XResultSet_impl::close()
414 if( m_nIsOpen )
416 m_aFolder.close();
417 isFinalChanged();
418 std::unique_lock aGuard( m_aMutex );
419 m_nIsOpen = false;
424 OUString SAL_CALL
425 XResultSet_impl::queryContentIdentifierString()
427 uno::Reference< ucb::XContentIdentifier > xContentId
428 = queryContentIdentifier();
430 if( xContentId.is() )
431 return xContentId->getContentIdentifier();
432 else
433 return OUString();
437 uno::Reference< ucb::XContentIdentifier > SAL_CALL
438 XResultSet_impl::queryContentIdentifier()
440 if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) )
442 if( ! m_aIdents[m_nRow].is() )
444 m_aIdents[m_nRow].set( new FileContentIdentifier( m_aUnqPath[ m_nRow ] ) );
446 return m_aIdents[m_nRow];
448 return uno::Reference< ucb::XContentIdentifier >();
452 uno::Reference< ucb::XContent > SAL_CALL
453 XResultSet_impl::queryContent()
455 if( 0 <= m_nRow && m_nRow < sal::static_int_cast<sal_Int32>(m_aItems.size()) )
456 return m_pMyShell->m_pProvider->queryContent( queryContentIdentifier() );
457 else
458 return uno::Reference< ucb::XContent >();
462 // XDynamicResultSet
465 // virtual
466 uno::Reference< sdbc::XResultSet > SAL_CALL
467 XResultSet_impl::getStaticResultSet()
469 std::unique_lock aGuard( m_aMutex );
471 if ( m_xListener.is() )
472 throw ucb::ListenerAlreadySetException( THROW_WHERE );
474 return uno::Reference< sdbc::XResultSet >( this );
478 // virtual
479 void SAL_CALL
480 XResultSet_impl::setListener(
481 const uno::Reference< ucb::XDynamicResultSetListener >& Listener )
483 std::unique_lock aGuard( m_aMutex );
485 if ( m_xListener.is() )
486 throw ucb::ListenerAlreadySetException( THROW_WHERE );
488 m_xListener = Listener;
491 // Create "welcome event" and send it to listener.
494 // Note: We only have the implementation for a static result set at the
495 // moment (src590). The dynamic result sets passed to the listener
496 // are a fake. This implementation will never call "notify" at the
497 // listener to propagate any changes!!!
499 uno::Any aInfo;
500 aInfo <<= ucb::WelcomeDynamicResultSetStruct( this, /* "old" */
501 this /* "new" */ );
503 uno::Sequence< ucb::ListAction > aActions( 1 );
504 aActions.getArray()[ 0 ] = ucb::ListAction( 0, // Position; not used
505 0, // Count; not used
506 ucb::ListActionType::WELCOME,
507 aInfo );
508 aGuard.unlock();
510 Listener->notify(
511 ucb::ListEvent(
512 static_cast< cppu::OWeakObject * >( this ), aActions ) );
516 // virtual
517 void SAL_CALL
518 XResultSet_impl::connectToCache(
519 const uno::Reference< ucb::XDynamicResultSet > & xCache )
521 if( m_xListener.is() )
522 throw ucb::ListenerAlreadySetException( THROW_WHERE );
524 uno::Reference< ucb::XSourceInitialization > xTarget(
525 xCache, uno::UNO_QUERY );
526 if( xTarget.is() && m_pMyShell->m_xContext.is() )
528 uno::Reference< ucb::XCachedDynamicResultSetStubFactory > xStubFactory;
531 xStubFactory
532 = ucb::CachedDynamicResultSetStubFactory::create(
533 m_pMyShell->m_xContext );
535 catch ( uno::Exception const & )
539 if( xStubFactory.is() )
541 xStubFactory->connectToCache(
542 this, xCache,m_sSortingInfo, nullptr );
543 return;
546 throw ucb::ServiceNotFoundException( THROW_WHERE );
550 // virtual
551 sal_Int16 SAL_CALL
552 XResultSet_impl::getCapabilities()
554 // Never set ucb::ContentResultSetCapability::SORTED
555 // - Underlying content cannot provide sorted data...
556 return 0;
559 // XResultSetMetaDataSupplier
560 uno::Reference< sdbc::XResultSetMetaData > SAL_CALL
561 XResultSet_impl::getMetaData()
563 auto pProp = std::find_if(std::cbegin(m_sProperty), std::cend(m_sProperty),
564 [](const beans::Property& rProp) { return rProp.Name == "Title"; });
565 if (pProp != std::cend(m_sProperty))
567 std::vector< ::ucbhelper::ResultSetColumnData >
568 aColumnData( m_sProperty.getLength() );
569 auto n = std::distance(std::cbegin(m_sProperty), pProp);
570 // @@@ #82177# - Determine correct value!
571 aColumnData[ n ].isCaseSensitive = false;
573 return new ::ucbhelper::ResultSetMetaData(
574 m_pMyShell->m_xContext,
575 m_sProperty,
576 std::move(aColumnData) );
579 return new ::ucbhelper::ResultSetMetaData( m_pMyShell->m_xContext, m_sProperty );
583 // XPropertySet
584 uno::Reference< beans::XPropertySetInfo > SAL_CALL
585 XResultSet_impl::getPropertySetInfo()
588 uno::Sequence< beans::Property > seq
590 { "RowCount", -1, cppu::UnoType<sal_Int32>::get(), beans::PropertyAttribute::READONLY },
591 { "IsRowCountFinal", -1, cppu::UnoType<sal_Bool>::get(), beans::PropertyAttribute::READONLY }
594 return new XPropertySetInfo_impl( m_pMyShell, seq );
598 void SAL_CALL XResultSet_impl::setPropertyValue(
599 const OUString& aPropertyName, const uno::Any& )
601 if( aPropertyName == "IsRowCountFinal" ||
602 aPropertyName == "RowCount" )
603 return;
604 throw beans::UnknownPropertyException( aPropertyName );
608 uno::Any SAL_CALL XResultSet_impl::getPropertyValue(
609 const OUString& PropertyName )
611 if( PropertyName == "IsRowCountFinal" )
613 return uno::Any(m_bRowCountFinal);
615 else if ( PropertyName == "RowCount" )
617 sal_Int32 count = sal::static_int_cast<sal_Int32>(m_aItems.size());
618 return uno::Any(count);
620 else
621 throw beans::UnknownPropertyException( PropertyName );
625 void SAL_CALL XResultSet_impl::addPropertyChangeListener(
626 const OUString& aPropertyName,
627 const uno::Reference< beans::XPropertyChangeListener >& xListener )
629 if( aPropertyName == "IsRowCountFinal" )
631 std::unique_lock aGuard( m_aMutex );
633 m_aIsFinalListeners.addInterface( aGuard, xListener );
635 else if ( aPropertyName == "RowCount" )
637 std::unique_lock aGuard( m_aMutex );
639 m_aRowCountListeners.addInterface( aGuard, xListener );
641 else
642 throw beans::UnknownPropertyException( aPropertyName );
646 void SAL_CALL XResultSet_impl::removePropertyChangeListener(
647 const OUString& aPropertyName,
648 const uno::Reference< beans::XPropertyChangeListener >& aListener )
650 if( aPropertyName == "IsRowCountFinal" )
652 std::unique_lock aGuard( m_aMutex );
654 m_aIsFinalListeners.removeInterface( aGuard, aListener );
656 else if ( aPropertyName == "RowCount" )
658 std::unique_lock aGuard( m_aMutex );
660 m_aRowCountListeners.removeInterface( aGuard, aListener );
662 else
663 throw beans::UnknownPropertyException( aPropertyName );
666 void SAL_CALL XResultSet_impl::addVetoableChangeListener(
667 const OUString&,
668 const uno::Reference< beans::XVetoableChangeListener >& )
673 void SAL_CALL XResultSet_impl::removeVetoableChangeListener(
674 const OUString&,
675 const uno::Reference< beans::XVetoableChangeListener >& )
679 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */