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 .
20 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
24 #include "filrset.hxx"
25 #include <com/sun/star/ucb/OpenMode.hpp>
27 #include <com/sun/star/uno/Reference.h>
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/ucb/ListActionType.hpp>
31 #include <com/sun/star/ucb/XSourceInitialization.hpp>
32 #include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
33 #include <ucbhelper/resultsetmetadata.hxx>
35 using namespace fileaccess
;
36 using namespace com::sun::star
;
38 #if OSL_DEBUG_LEVEL > 0
39 #define THROW_WHERE SAL_WHERE
41 #define THROW_WHERE ""
44 XResultSet_impl::XResultSet_impl( shell
* pMyShell
,
45 const OUString
& aUnqPath
,
47 const uno::Sequence
< beans::Property
>& seq
,
48 const uno::Sequence
< ucb::NumberedSortingInfo
>& seqSort
)
49 : m_pMyShell( pMyShell
)
50 , m_xProvider( pMyShell
->m_pProvider
)
52 , m_nWasNull ( false )
53 , m_nOpenMode( OpenMode
)
54 , m_bRowCountFinal( false )
55 , m_aBaseDirectory( aUnqPath
)
56 , m_aFolder( aUnqPath
)
58 , m_sSortingInfo( seqSort
)
59 , m_pDisposeEventListeners( 0 )
60 , m_pRowCountListeners( 0 )
61 , m_pIsFinalListeners( 0 )
63 , m_nErrorCode( TASKHANDLER_NO_ERROR
)
64 , m_nMinorErrorCode( TASKHANDLER_NO_ERROR
)
66 osl::FileBase::RC err
= m_aFolder
.open();
67 if( err
!= osl::FileBase::E_None
)
72 m_nErrorCode
= TASKHANDLING_OPEN_FOR_DIRECTORYLISTING
;
73 m_nMinorErrorCode
= err
;
78 m_pMyShell
->registerNotifier( m_aBaseDirectory
,this );
82 XResultSet_impl::~XResultSet_impl()
84 m_pMyShell
->deregisterNotifier( m_aBaseDirectory
,this );
89 delete m_pDisposeEventListeners
;
90 delete m_pRowCountListeners
;
91 delete m_pIsFinalListeners
;
102 XResultSet_impl::disposing( const lang::EventObject
& )
103 throw( uno::RuntimeException
, std::exception
)
110 XResultSet_impl::addEventListener(
111 const uno::Reference
< lang::XEventListener
>& Listener
)
112 throw( uno::RuntimeException
, std::exception
)
114 osl::MutexGuard
aGuard( m_aMutex
);
116 if ( ! m_pDisposeEventListeners
)
117 m_pDisposeEventListeners
=
118 new cppu::OInterfaceContainerHelper( m_aEventListenerMutex
);
120 m_pDisposeEventListeners
->addInterface( Listener
);
125 XResultSet_impl::removeEventListener(
126 const uno::Reference
< lang::XEventListener
>& Listener
)
127 throw( uno::RuntimeException
, std::exception
)
129 osl::MutexGuard
aGuard( m_aMutex
);
131 if ( m_pDisposeEventListeners
)
132 m_pDisposeEventListeners
->removeInterface( Listener
);
138 XResultSet_impl::dispose()
139 throw( uno::RuntimeException
, std::exception
)
141 osl::MutexGuard
aGuard( m_aMutex
);
143 lang::EventObject aEvt
;
144 aEvt
.Source
= static_cast< lang::XComponent
* >( this );
146 if ( m_pDisposeEventListeners
&& m_pDisposeEventListeners
->getLength() )
148 m_pDisposeEventListeners
->disposeAndClear( aEvt
);
150 if( m_pRowCountListeners
&& m_pRowCountListeners
->getLength() )
152 m_pRowCountListeners
->disposeAndClear( aEvt
);
154 if( m_pIsFinalListeners
&& m_pIsFinalListeners
->getLength() )
156 m_pIsFinalListeners
->disposeAndClear( aEvt
);
162 void XResultSet_impl::rowCountChanged()
164 sal_Int32 aOldValue
,aNewValue
;
165 uno::Sequence
< uno::Reference
< uno::XInterface
> > seq
;
167 osl::MutexGuard
aGuard( m_aMutex
);
168 if( m_pRowCountListeners
)
169 seq
= m_pRowCountListeners
->getElements();
170 aNewValue
= m_aItems
.size();
171 aOldValue
= aNewValue
-1;
173 beans::PropertyChangeEvent aEv
;
174 aEv
.PropertyName
= "RowCount";
176 aEv
.PropertyHandle
= -1;
177 aEv
.OldValue
<<= aOldValue
;
178 aEv
.NewValue
<<= aNewValue
;
179 for( sal_Int32 i
= 0; i
< seq
.getLength(); ++i
)
181 uno::Reference
< beans::XPropertyChangeListener
> listener(
182 seq
[i
], uno::UNO_QUERY
);
184 listener
->propertyChange( aEv
);
189 void XResultSet_impl::isFinalChanged()
191 uno::Sequence
< uno::Reference
< XInterface
> > seq
;
193 osl::MutexGuard
aGuard( m_aMutex
);
194 if( m_pIsFinalListeners
)
195 seq
= m_pIsFinalListeners
->getElements();
196 m_bRowCountFinal
= true;
198 beans::PropertyChangeEvent aEv
;
199 aEv
.PropertyName
= "IsRowCountFinal";
201 aEv
.PropertyHandle
= -1;
204 aEv
.OldValue
<<= fval
;
205 aEv
.NewValue
<<= tval
;
206 for( sal_Int32 i
= 0; i
< seq
.getLength(); ++i
)
208 uno::Reference
< beans::XPropertyChangeListener
> listener(
209 seq
[i
], uno::UNO_QUERY
);
211 listener
->propertyChange( aEv
);
217 XResultSet_impl::OneMore(
219 throw( sdbc::SQLException
,
220 uno::RuntimeException
)
225 osl::FileBase::RC err
;
228 osl::DirectoryItem m_aDirIte
;
229 uno::Reference
< sdbc::XRow
> aRow
;
233 err
= m_aFolder
.getNextItem( m_aDirIte
);
235 if( err
== osl::FileBase::E_NOENT
|| err
== osl::FileBase::E_INVAL
)
239 return ( m_nIsOpen
= false );
241 else if( err
== osl::FileBase::E_None
)
243 aRow
= m_pMyShell
->getv(
244 this, m_sProperty
, m_aDirIte
, aUnqPath
, IsRegular
);
246 if( m_nOpenMode
== ucb::OpenMode::DOCUMENTS
&& IsRegular
)
248 osl::MutexGuard
aGuard( m_aMutex
);
249 m_aItems
.push_back( aRow
);
251 uno::Reference
< ucb::XContentIdentifier
>() );
252 m_aUnqPath
.push_back( aUnqPath
);
257 else if( m_nOpenMode
== ucb::OpenMode::DOCUMENTS
&& ! IsRegular
)
261 else if( m_nOpenMode
== ucb::OpenMode::FOLDERS
&& ! IsRegular
)
263 osl::MutexGuard
aGuard( m_aMutex
);
264 m_aItems
.push_back( aRow
);
266 uno::Reference
< ucb::XContentIdentifier
>() );
267 m_aUnqPath
.push_back( aUnqPath
);
271 else if( m_nOpenMode
== ucb::OpenMode::FOLDERS
&& IsRegular
)
277 osl::MutexGuard
aGuard( m_aMutex
);
278 m_aItems
.push_back( aRow
);
280 uno::Reference
< ucb::XContentIdentifier
>() );
281 m_aUnqPath
.push_back( aUnqPath
);
286 else // error fetching anything
288 throw sdbc::SQLException( THROW_WHERE
, uno::Reference
< uno::XInterface
>(), OUString(), 0, uno::Any() );
298 XResultSet_impl::next(
300 throw( sdbc::SQLException
,
301 uno::RuntimeException
, std::exception
)
304 if( ++m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) ) test
= true;
312 XResultSet_impl::isBeforeFirst(
314 throw( sdbc::SQLException
,
315 uno::RuntimeException
, std::exception
)
322 XResultSet_impl::isAfterLast(
324 throw( sdbc::SQLException
,
325 uno::RuntimeException
, std::exception
)
327 return m_nRow
>= sal::static_int_cast
<sal_Int32
>(m_aItems
.size()); // Cannot happen, if m_aFolder.isOpen()
332 XResultSet_impl::isFirst(
334 throw( sdbc::SQLException
,
335 uno::RuntimeException
, std::exception
)
342 XResultSet_impl::isLast(
344 throw( sdbc::SQLException
,
345 uno::RuntimeException
, std::exception
)
347 if( m_nRow
== sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) - 1 )
355 XResultSet_impl::beforeFirst(
357 throw( sdbc::SQLException
,
358 uno::RuntimeException
, std::exception
)
365 XResultSet_impl::afterLast(
367 throw( sdbc::SQLException
,
368 uno::RuntimeException
, std::exception
)
370 m_nRow
= sal::static_int_cast
<sal_Int32
>(m_aItems
.size());
377 XResultSet_impl::first(
379 throw( sdbc::SQLException
,
380 uno::RuntimeException
, std::exception
)
388 XResultSet_impl::last(
390 throw( sdbc::SQLException
,
391 uno::RuntimeException
, std::exception
)
393 m_nRow
= sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) - 1;
401 XResultSet_impl::getRow(
403 throw( sdbc::SQLException
,
404 uno::RuntimeException
, std::exception
)
406 // Test, whether behind last row
407 if( -1 == m_nRow
|| m_nRow
>= sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) )
415 sal_Bool SAL_CALL
XResultSet_impl::absolute( sal_Int32 row
)
416 throw( sdbc::SQLException
, uno::RuntimeException
, std::exception
)
421 if( row
>= sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) )
422 while( row
-- && OneMore() )
428 m_nRow
+= ( row
+ 1 );
433 return 0<= m_nRow
&& m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size());
440 XResultSet_impl::relative(
442 throw( sdbc::SQLException
,
443 uno::RuntimeException
, std::exception
)
445 if( isAfterLast() || isBeforeFirst() )
446 throw sdbc::SQLException( THROW_WHERE
, uno::Reference
< uno::XInterface
>(), OUString(), 0, uno::Any() );
448 while( row
-- ) next();
450 while( row
++ && m_nRow
> - 1 ) previous();
452 return 0 <= m_nRow
&& m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size());
458 XResultSet_impl::previous(
460 throw( sdbc::SQLException
,
461 uno::RuntimeException
, std::exception
)
463 if( m_nRow
> sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) )
464 m_nRow
= sal::static_int_cast
<sal_Int32
>(m_aItems
.size()); // Correct Handling of afterLast
465 if( 0 <= m_nRow
) -- m_nRow
;
467 return 0 <= m_nRow
&& m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size());
472 XResultSet_impl::refreshRow(
474 throw( sdbc::SQLException
,
475 uno::RuntimeException
, std::exception
)
477 // get the row from the filesystem
483 XResultSet_impl::rowUpdated(
485 throw( sdbc::SQLException
,
486 uno::RuntimeException
, std::exception
)
492 XResultSet_impl::rowInserted(
494 throw( sdbc::SQLException
,
495 uno::RuntimeException
, std::exception
)
501 XResultSet_impl::rowDeleted(
503 throw( sdbc::SQLException
,
504 uno::RuntimeException
, std::exception
)
510 uno::Reference
< uno::XInterface
> SAL_CALL
511 XResultSet_impl::getStatement(
513 throw( sdbc::SQLException
,
514 uno::RuntimeException
, std::exception
)
516 return uno::Reference
< uno::XInterface
>();
523 XResultSet_impl::close(
525 throw( sdbc::SQLException
,
526 uno::RuntimeException
, std::exception
)
532 osl::MutexGuard
aGuard( m_aMutex
);
540 XResultSet_impl::queryContentIdentifierString(
542 throw( uno::RuntimeException
, std::exception
)
544 uno::Reference
< ucb::XContentIdentifier
> xContentId
545 = queryContentIdentifier();
547 if( xContentId
.is() )
548 return xContentId
->getContentIdentifier();
554 uno::Reference
< ucb::XContentIdentifier
> SAL_CALL
555 XResultSet_impl::queryContentIdentifier(
557 throw( uno::RuntimeException
, std::exception
)
559 if( 0 <= m_nRow
&& m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) )
561 if( ! m_aIdents
[m_nRow
].is() )
563 FileContentIdentifier
* p
564 = new FileContentIdentifier( m_aUnqPath
[ m_nRow
] );
565 m_aIdents
[m_nRow
] = uno::Reference
< ucb::XContentIdentifier
>(p
);
567 return m_aIdents
[m_nRow
];
569 return uno::Reference
< ucb::XContentIdentifier
>();
573 uno::Reference
< ucb::XContent
> SAL_CALL
574 XResultSet_impl::queryContent(
576 throw( uno::RuntimeException
, std::exception
)
578 if( 0 <= m_nRow
&& m_nRow
< sal::static_int_cast
<sal_Int32
>(m_aItems
.size()) )
579 return m_pMyShell
->m_pProvider
->queryContent( queryContentIdentifier() );
581 return uno::Reference
< ucb::XContent
>();
589 uno::Reference
< sdbc::XResultSet
> SAL_CALL
590 XResultSet_impl::getStaticResultSet()
591 throw( ucb::ListenerAlreadySetException
,
592 uno::RuntimeException
, std::exception
)
594 osl::MutexGuard
aGuard( m_aMutex
);
596 if ( m_xListener
.is() )
597 throw ucb::ListenerAlreadySetException( THROW_WHERE
);
599 return uno::Reference
< sdbc::XResultSet
>( this );
605 XResultSet_impl::setListener(
606 const uno::Reference
< ucb::XDynamicResultSetListener
>& Listener
)
607 throw( ucb::ListenerAlreadySetException
,
608 uno::RuntimeException
, std::exception
)
610 osl::ClearableMutexGuard
aGuard( m_aMutex
);
612 if ( m_xListener
.is() )
613 throw ucb::ListenerAlreadySetException( THROW_WHERE
);
615 m_xListener
= Listener
;
618 // Create "welcome event" and send it to listener.
621 // Note: We only have the implementation for a static result set at the
622 // moment (src590). The dynamic result sets passed to the listener
623 // are a fake. This implementation will never call "notify" at the
624 // listener to propagate any changes!!!
627 aInfo
<<= ucb::WelcomeDynamicResultSetStruct( this, /* "old" */
630 uno::Sequence
< ucb::ListAction
> aActions( 1 );
631 aActions
.getArray()[ 0 ] = ucb::ListAction( 0, // Position; not used
632 0, // Count; not used
633 ucb::ListActionType::WELCOME
,
639 static_cast< cppu::OWeakObject
* >( this ), aActions
) );
645 XResultSet_impl::connectToCache(
646 const uno::Reference
< ucb::XDynamicResultSet
> & xCache
)
647 throw( ucb::ListenerAlreadySetException
,
648 ucb::AlreadyInitializedException
,
649 ucb::ServiceNotFoundException
,
650 uno::RuntimeException
, std::exception
)
652 if( m_xListener
.is() )
653 throw ucb::ListenerAlreadySetException( THROW_WHERE
);
655 throw ucb::ListenerAlreadySetException( THROW_WHERE
);
657 uno::Reference
< ucb::XSourceInitialization
> xTarget(
658 xCache
, uno::UNO_QUERY
);
659 if( xTarget
.is() && m_pMyShell
->m_xContext
.is() )
661 uno::Reference
< ucb::XCachedDynamicResultSetStubFactory
> xStubFactory
;
665 = ucb::CachedDynamicResultSetStubFactory::create(
666 m_pMyShell
->m_xContext
);
668 catch ( uno::Exception
const & )
672 if( xStubFactory
.is() )
674 xStubFactory
->connectToCache(
675 this, xCache
,m_sSortingInfo
, NULL
);
679 throw ucb::ServiceNotFoundException( THROW_WHERE
);
685 XResultSet_impl::getCapabilities()
686 throw( uno::RuntimeException
, std::exception
)
688 // Never set ucb::ContentResultSetCapability::SORTED
689 // - Underlying content cannot provide sorted data...
693 // XResultSetMetaDataSupplier
694 uno::Reference
< sdbc::XResultSetMetaData
> SAL_CALL
695 XResultSet_impl::getMetaData(
697 throw( sdbc::SQLException
,
698 uno::RuntimeException
, std::exception
)
700 for ( sal_Int32 n
= 0; n
< m_sProperty
.getLength(); ++n
)
702 if ( m_sProperty
.getConstArray()[ n
].Name
== "Title" )
704 // @@@ #82177# - Determine correct value!
705 bool bCaseSensitiveChildren
= false;
707 std::vector
< ::ucbhelper::ResultSetColumnData
>
708 aColumnData( m_sProperty
.getLength() );
709 aColumnData
[ n
].isCaseSensitive
= bCaseSensitiveChildren
;
711 ::ucbhelper::ResultSetMetaData
* p
=
712 new ::ucbhelper::ResultSetMetaData(
713 m_pMyShell
->m_xContext
,
716 return uno::Reference
< sdbc::XResultSetMetaData
>( p
);
720 ::ucbhelper::ResultSetMetaData
* p
=
721 new ::ucbhelper::ResultSetMetaData( m_pMyShell
->m_xContext
, m_sProperty
);
722 return uno::Reference
< sdbc::XResultSetMetaData
>( p
);
728 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
729 XResultSet_impl::getPropertySetInfo()
730 throw( uno::RuntimeException
, std::exception
)
733 uno::Sequence
< beans::Property
> seq(2);
734 seq
[0].Name
= "RowCount";
736 seq
[0].Type
= cppu::UnoType
<sal_Int32
>::get();
737 seq
[0].Attributes
= beans::PropertyAttribute::READONLY
;
739 seq
[0].Name
= "IsRowCountFinal";
741 seq
[0].Type
= cppu::UnoType
<sal_Bool
>::get();
742 seq
[0].Attributes
= beans::PropertyAttribute::READONLY
;
744 XPropertySetInfo_impl
* p
= new XPropertySetInfo_impl( m_pMyShell
,
746 return uno::Reference
< beans::XPropertySetInfo
> ( p
);
751 void SAL_CALL
XResultSet_impl::setPropertyValue(
752 const OUString
& aPropertyName
, const uno::Any
& )
753 throw( beans::UnknownPropertyException
,
754 beans::PropertyVetoException
,
755 lang::IllegalArgumentException
,
756 lang::WrappedTargetException
,
757 uno::RuntimeException
, std::exception
)
759 if( aPropertyName
== "IsRowCountFinal" ||
760 aPropertyName
== "RowCount" )
762 throw beans::UnknownPropertyException( THROW_WHERE
);
766 uno::Any SAL_CALL
XResultSet_impl::getPropertyValue(
767 const OUString
& PropertyName
)
768 throw( beans::UnknownPropertyException
,
769 lang::WrappedTargetException
,
770 uno::RuntimeException
, std::exception
)
772 if( PropertyName
== "IsRowCountFinal" )
775 aAny
<<= m_bRowCountFinal
;
778 else if ( PropertyName
== "RowCount" )
781 sal_Int32 count
= sal::static_int_cast
<sal_Int32
>(m_aItems
.size());
786 throw beans::UnknownPropertyException( THROW_WHERE
);
790 void SAL_CALL
XResultSet_impl::addPropertyChangeListener(
791 const OUString
& aPropertyName
,
792 const uno::Reference
< beans::XPropertyChangeListener
>& xListener
)
793 throw( beans::UnknownPropertyException
,
794 lang::WrappedTargetException
,
795 uno::RuntimeException
, std::exception
)
797 if( aPropertyName
== "IsRowCountFinal" )
799 osl::MutexGuard
aGuard( m_aMutex
);
800 if ( ! m_pIsFinalListeners
)
801 m_pIsFinalListeners
=
802 new cppu::OInterfaceContainerHelper( m_aEventListenerMutex
);
804 m_pIsFinalListeners
->addInterface( xListener
);
806 else if ( aPropertyName
== "RowCount" )
808 osl::MutexGuard
aGuard( m_aMutex
);
809 if ( ! m_pRowCountListeners
)
810 m_pRowCountListeners
=
811 new cppu::OInterfaceContainerHelper( m_aEventListenerMutex
);
812 m_pRowCountListeners
->addInterface( xListener
);
815 throw beans::UnknownPropertyException( THROW_WHERE
);
819 void SAL_CALL
XResultSet_impl::removePropertyChangeListener(
820 const OUString
& aPropertyName
,
821 const uno::Reference
< beans::XPropertyChangeListener
>& aListener
)
822 throw( beans::UnknownPropertyException
,
823 lang::WrappedTargetException
,
824 uno::RuntimeException
, std::exception
)
826 if( aPropertyName
== "IsRowCountFinal" &&
827 m_pIsFinalListeners
)
829 osl::MutexGuard
aGuard( m_aMutex
);
830 m_pIsFinalListeners
->removeInterface( aListener
);
832 else if ( aPropertyName
== "RowCount" &&
833 m_pRowCountListeners
)
835 osl::MutexGuard
aGuard( m_aMutex
);
837 m_pRowCountListeners
->removeInterface( aListener
);
840 throw beans::UnknownPropertyException( THROW_WHERE
);
843 void SAL_CALL
XResultSet_impl::addVetoableChangeListener(
845 const uno::Reference
< beans::XVetoableChangeListener
>& )
846 throw( beans::UnknownPropertyException
,
847 lang::WrappedTargetException
,
848 uno::RuntimeException
, std::exception
)
853 void SAL_CALL
XResultSet_impl::removeVetoableChangeListener(
855 const uno::Reference
< beans::XVetoableChangeListener
>& )
856 throw( beans::UnknownPropertyException
,
857 lang::WrappedTargetException
,
858 uno::RuntimeException
, std::exception
)
862 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */