summaryrefslogtreecommitdiffstats
path: root/ucbhelper/source/provider
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /ucbhelper/source/provider
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ucbhelper/source/provider')
-rw-r--r--ucbhelper/source/provider/authenticationfallback.cxx31
-rw-r--r--ucbhelper/source/provider/cancelcommandexecution.cxx115
-rw-r--r--ucbhelper/source/provider/contenthelper.cxx863
-rw-r--r--ucbhelper/source/provider/contentidentifier.cxx91
-rw-r--r--ucbhelper/source/provider/contentinfo.cxx318
-rw-r--r--ucbhelper/source/provider/contentinfo.hxx119
-rw-r--r--ucbhelper/source/provider/interactionrequest.cxx626
-rw-r--r--ucbhelper/source/provider/propertyvalueset.cxx680
-rw-r--r--ucbhelper/source/provider/providerhelper.cxx497
-rw-r--r--ucbhelper/source/provider/registerucb.cxx139
-rw-r--r--ucbhelper/source/provider/resultset.cxx1486
-rw-r--r--ucbhelper/source/provider/resultsethelper.cxx252
-rw-r--r--ucbhelper/source/provider/resultsetmetadata.cxx397
-rw-r--r--ucbhelper/source/provider/simpleauthenticationrequest.cxx147
-rw-r--r--ucbhelper/source/provider/simplecertificatevalidationrequest.cxx42
-rw-r--r--ucbhelper/source/provider/simpleinteractionrequest.cxx92
-rw-r--r--ucbhelper/source/provider/simpleioerrorrequest.cxx44
-rw-r--r--ucbhelper/source/provider/simpleioerrorrequest.hxx65
-rw-r--r--ucbhelper/source/provider/simplenameclashresolverequest.cxx157
19 files changed, 6161 insertions, 0 deletions
diff --git a/ucbhelper/source/provider/authenticationfallback.cxx b/ucbhelper/source/provider/authenticationfallback.cxx
new file mode 100644
index 0000000000..04491520bd
--- /dev/null
+++ b/ucbhelper/source/provider/authenticationfallback.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <ucbhelper/authenticationfallback.hxx>
+#include <com/sun/star/ucb/AuthenticationFallbackRequest.hpp>
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+AuthenticationFallbackRequest::AuthenticationFallbackRequest(
+ const OUString & rInstructions,
+ const OUString & rURL )
+{
+
+ ucb::AuthenticationFallbackRequest aRequest;
+ aRequest.instructions = rInstructions;
+ aRequest.url = rURL;
+
+ setRequest( uno::Any( aRequest ) );
+ m_xAuthFallback = new InteractionAuthFallback( this );
+
+ setContinuations({ new InteractionAbort(this), m_xAuthFallback });
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/cancelcommandexecution.cxx b/ucbhelper/source/provider/cancelcommandexecution.cxx
new file mode 100644
index 0000000000..57166e49b0
--- /dev/null
+++ b/ucbhelper/source/provider/cancelcommandexecution.cxx
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/ucb/CommandFailedException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include <ucbhelper/interactionrequest.hxx>
+#include <ucbhelper/cancelcommandexecution.hxx>
+#include "simpleioerrorrequest.hxx"
+
+using namespace com::sun::star;
+
+namespace ucbhelper
+{
+
+
+void cancelCommandExecution( const uno::Any & rException,
+ const uno::Reference<
+ ucb::XCommandEnvironment > & xEnv )
+{
+ if ( xEnv.is() )
+ {
+ uno::Reference<
+ task::XInteractionHandler > xIH = xEnv->getInteractionHandler();
+ if ( xIH.is() )
+ {
+ rtl::Reference< ucbhelper::InteractionRequest > xRequest
+ = new ucbhelper::InteractionRequest( rException );
+
+ xRequest->setContinuations({ new ucbhelper::InteractionAbort(xRequest.get()) });
+
+ xIH->handle( xRequest );
+
+ rtl::Reference< ucbhelper::InteractionContinuation > xSelection
+ = xRequest->getSelection();
+
+ if ( xSelection.is() )
+ throw ucb::CommandFailedException(
+ OUString(),
+ uno::Reference< uno::XInterface >(),
+ rException );
+ }
+ }
+
+ cppu::throwException( rException );
+ OSL_FAIL( "Return from cppu::throwException call!!!" );
+ throw uno::RuntimeException();
+}
+
+
+void cancelCommandExecution( const ucb::IOErrorCode eError,
+ const uno::Sequence< uno::Any > & rArgs,
+ const uno::Reference<
+ ucb::XCommandEnvironment > & xEnv,
+ const OUString & rMessage,
+ const uno::Reference<
+ ucb::XCommandProcessor > & xContext )
+{
+ if ( !xEnv )
+ {
+ // Fast path
+
+ ucb::InteractiveAugmentedIOException aRequest(
+ rMessage, xContext, task::InteractionClassification_ERROR, eError, rArgs);
+ cppu::throwException( uno::Any( aRequest ) );
+ }
+ else
+ {
+ rtl::Reference< ucbhelper::SimpleIOErrorRequest > xRequest
+ = new ucbhelper::SimpleIOErrorRequest(
+ eError, rArgs, rMessage, xContext );
+ uno::Reference<
+ task::XInteractionHandler > xIH = xEnv->getInteractionHandler();
+ if ( xIH.is() )
+ {
+ xIH->handle( xRequest );
+
+ rtl::Reference< ucbhelper::InteractionContinuation > xSelection
+ = xRequest->getSelection();
+
+ if ( xSelection.is() )
+ throw ucb::CommandFailedException( OUString(),
+ xContext,
+ xRequest->getRequest() );
+ }
+ cppu::throwException( xRequest->getRequest() );
+ }
+
+ OSL_FAIL( "Return from cppu::throwException call!!!" );
+ throw uno::RuntimeException();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/contenthelper.cxx b/ucbhelper/source/provider/contenthelper.cxx
new file mode 100644
index 0000000000..1e5147f6fb
--- /dev/null
+++ b/ucbhelper/source/provider/contenthelper.cxx
@@ -0,0 +1,863 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/ucb/ContentAction.hpp>
+#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
+#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
+#include <com/sun/star/beans/IllegalTypeException.hpp>
+#include <com/sun/star/beans/NotRemoveableException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyExistException.hpp>
+#include <com/sun/star/beans/PropertySetInfoChange.hpp>
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/interfacecontainer.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <ucbhelper/contenthelper.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include "contentinfo.hxx"
+#include <ucbhelper/providerhelper.hxx>
+#include <ucbhelper/macros.hxx>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+
+#include <unordered_map>
+#include <utility>
+
+using namespace com::sun::star;
+
+namespace ucbhelper_impl
+{
+
+namespace {
+
+class PropertyEventSequence
+{
+ uno::Sequence< beans::PropertyChangeEvent > m_aSeq;
+ sal_uInt32 m_nPos;
+
+public:
+ explicit PropertyEventSequence( sal_uInt32 nSize )
+ : m_aSeq( nSize ), m_nPos( 0 ) {};
+
+ void append( const beans::PropertyChangeEvent& rEvt )
+ { m_aSeq.getArray()[ m_nPos ] = rEvt; ++m_nPos; }
+
+ const uno::Sequence< beans::PropertyChangeEvent >& getEvents()
+ { m_aSeq.realloc( m_nPos ); return m_aSeq; }
+};
+
+}
+
+typedef void* XPropertiesChangeListenerPtr; // -> Compiler problems!
+
+namespace {
+
+struct equalPtr
+{
+ bool operator()( const XPropertiesChangeListenerPtr& rp1,
+ const XPropertiesChangeListenerPtr& rp2 ) const
+ {
+ return ( rp1 == rp2 );
+ }
+};
+
+struct hashPtr
+{
+ size_t operator()( const XPropertiesChangeListenerPtr& rp ) const
+ {
+ return reinterpret_cast<size_t>(rp);
+ }
+};
+
+}
+
+typedef std::unordered_map
+<
+ XPropertiesChangeListenerPtr,
+ PropertyEventSequence,
+ hashPtr,
+ equalPtr
+>
+PropertiesEventListenerMap;
+
+typedef cppu::OMultiTypeInterfaceContainerHelperVar<OUString>
+ PropertyChangeListeners;
+
+struct ContentImplHelper_Impl
+{
+ rtl::Reference< ::ucbhelper::PropertySetInfo > m_xPropSetInfo;
+ rtl::Reference< ::ucbhelper::CommandProcessorInfo > m_xCommandsInfo;
+ std::unique_ptr<cppu::OInterfaceContainerHelper> m_pDisposeEventListeners;
+ std::unique_ptr<comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>>
+ m_pContentEventListeners;
+ std::unique_ptr<comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>>
+ m_pPropSetChangeListeners;
+ std::unique_ptr<cppu::OInterfaceContainerHelper> m_pCommandChangeListeners;
+ std::unique_ptr<PropertyChangeListeners> m_pPropertyChangeListeners;
+};
+
+} // namespace ucbhelper_impl
+
+using namespace ucbhelper_impl;
+
+namespace ucbhelper {
+
+ContentImplHelper::ContentImplHelper(
+ uno::Reference< uno::XComponentContext > xContext,
+ rtl::Reference< ContentProviderImplHelper > xProvider,
+ uno::Reference<
+ css::ucb::XContentIdentifier > Identifier )
+: m_pImpl( new ContentImplHelper_Impl ),
+ m_xContext(std::move( xContext )),
+ m_xIdentifier(std::move( Identifier )),
+ m_xProvider(std::move( xProvider )),
+ m_nCommandId( 0 )
+{
+}
+
+// virtual
+ContentImplHelper::~ContentImplHelper()
+{
+}
+
+void SAL_CALL ContentImplHelper::release()
+ noexcept
+{
+ // #144882# - Call to OWeakObject::release may destroy m_xProvider.
+ // Prevent this.
+ rtl::Reference< ContentProviderImplHelper > xKeepProviderAlive(
+ m_xProvider );
+
+ osl::MutexGuard aGuard( m_xProvider->m_aMutex );
+ OWeakObject::release();
+}
+
+uno::Any SAL_CALL ContentImplHelper::queryInterface( const uno::Type & rType )
+{
+ css::uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >(this),
+ static_cast< lang::XServiceInfo * >(this),
+ static_cast< lang::XComponent * >(this),
+ static_cast< css::ucb::XContent * >(this),
+ static_cast< css::ucb::XCommandProcessor * >(this),
+ static_cast< beans::XPropertiesChangeNotifier * >(this),
+ static_cast< css::ucb::XCommandInfoChangeNotifier * >(this),
+ static_cast< beans::XPropertyContainer * >(this),
+ static_cast< beans::XPropertySetInfoChangeNotifier * >(this),
+ static_cast< container::XChild * >(this));
+ return aRet.hasValue() ? aRet : cppu::OWeakObject::queryInterface( rType );
+}
+
+XTYPEPROVIDER_IMPL_10( ContentImplHelper,
+ lang::XTypeProvider,
+ lang::XServiceInfo,
+ lang::XComponent,
+ css::ucb::XContent,
+ css::ucb::XCommandProcessor,
+ beans::XPropertiesChangeNotifier,
+ css::ucb::XCommandInfoChangeNotifier,
+ beans::XPropertyContainer,
+ beans::XPropertySetInfoChangeNotifier,
+ container::XChild );
+
+// virtual
+sal_Bool SAL_CALL ContentImplHelper::supportsService(
+ const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::dispose()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pImpl->m_pDisposeEventListeners &&
+ m_pImpl->m_pDisposeEventListeners->getLength() )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< lang::XComponent * >( this );
+ m_pImpl->m_pDisposeEventListeners->disposeAndClear( aEvt );
+ }
+
+ if ( m_pImpl->m_pContentEventListeners &&
+ m_pImpl->m_pContentEventListeners->getLength() )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< css::ucb::XContent * >( this );
+ m_pImpl->m_pContentEventListeners->disposeAndClear( aEvt );
+ }
+
+ if ( m_pImpl->m_pPropSetChangeListeners &&
+ m_pImpl->m_pPropSetChangeListeners->getLength() )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source
+ = static_cast< beans::XPropertySetInfoChangeNotifier * >( this );
+ m_pImpl->m_pPropSetChangeListeners->disposeAndClear( aEvt );
+ }
+
+ if ( m_pImpl->m_pCommandChangeListeners &&
+ m_pImpl->m_pCommandChangeListeners->getLength() )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< css::ucb::XCommandInfoChangeNotifier * >( this );
+ m_pImpl->m_pCommandChangeListeners->disposeAndClear( aEvt );
+ }
+
+ if ( m_pImpl->m_pPropertyChangeListeners )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source
+ = static_cast< beans::XPropertiesChangeNotifier * >( this );
+ m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aEvt );
+ }
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pDisposeEventListeners )
+ m_pImpl->m_pDisposeEventListeners.reset(
+ new cppu::OInterfaceContainerHelper( m_aMutex ));
+
+ m_pImpl->m_pDisposeEventListeners->addInterface( Listener );
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removeEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pImpl->m_pDisposeEventListeners )
+ m_pImpl->m_pDisposeEventListeners->removeInterface( Listener );
+}
+
+// virtual
+uno::Reference< css::ucb::XContentIdentifier > SAL_CALL
+ContentImplHelper::getIdentifier()
+{
+ return m_xIdentifier;
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addContentEventListener(
+ const uno::Reference< css::ucb::XContentEventListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pContentEventListeners )
+ m_pImpl->m_pContentEventListeners.reset(
+ new comphelper::OInterfaceContainerHelper3<css::ucb::XContentEventListener>( m_aMutex ));
+
+ m_pImpl->m_pContentEventListeners->addInterface( Listener );
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removeContentEventListener(
+ const uno::Reference< css::ucb::XContentEventListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pImpl->m_pContentEventListeners )
+ m_pImpl->m_pContentEventListeners->removeInterface( Listener );
+}
+
+// virtual
+sal_Int32 SAL_CALL ContentImplHelper::createCommandIdentifier()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // Just increase counter on every call to generate an identifier.
+ return ++m_nCommandId;
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addPropertiesChangeListener(
+ const uno::Sequence< OUString >& PropertyNames,
+ const uno::Reference< beans::XPropertiesChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ m_pImpl->m_pPropertyChangeListeners.reset(
+ new PropertyChangeListeners( m_aMutex ));
+
+ if ( !PropertyNames.hasElements() )
+ {
+ // Note: An empty sequence means a listener for "all" properties.
+ m_pImpl->m_pPropertyChangeListeners->addInterface(
+ OUString(), Listener );
+ }
+ else
+ {
+ for ( const OUString& rName : PropertyNames )
+ {
+ if ( !rName.isEmpty() )
+ m_pImpl->m_pPropertyChangeListeners->addInterface(
+ rName, Listener );
+ }
+ }
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removePropertiesChangeListener(
+ const uno::Sequence< OUString >& PropertyNames,
+ const uno::Reference< beans::XPropertiesChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ return;
+
+ if ( !PropertyNames.hasElements() )
+ {
+ // Note: An empty sequence means a listener for "all" properties.
+ m_pImpl->m_pPropertyChangeListeners->removeInterface(
+ OUString(), Listener );
+ }
+ else
+ {
+ for ( const OUString& rName : PropertyNames )
+ {
+ if ( !rName.isEmpty() )
+ m_pImpl->m_pPropertyChangeListeners->removeInterface(
+ rName, Listener );
+ }
+ }
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addCommandInfoChangeListener(
+ const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pCommandChangeListeners )
+ m_pImpl->m_pCommandChangeListeners.reset(
+ new cppu::OInterfaceContainerHelper( m_aMutex ));
+
+ m_pImpl->m_pCommandChangeListeners->addInterface( Listener );
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removeCommandInfoChangeListener(
+ const uno::Reference< css::ucb::XCommandInfoChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pImpl->m_pCommandChangeListeners )
+ m_pImpl->m_pCommandChangeListeners->removeInterface( Listener );
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addProperty(
+ const OUString& Name,
+ sal_Int16 Attributes,
+ const uno::Any& DefaultValue )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // Make sure a property with the requested name does not already
+ // exist in dynamic and static(!) properties.
+
+ // @@@ Need real command environment here, but where to get it from?
+ // XPropertyContainer interface should be replaced by
+ // XCommandProcessor commands!
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv;
+
+ if ( getPropertySetInfo( xEnv )->hasPropertyByName( Name ) )
+ {
+ // Property does already exist.
+ throw beans::PropertyExistException();
+ }
+
+ // Add a new dynamic property.
+ // Open/create persistent property set.
+ uno::Reference< css::ucb::XPersistentPropertySet > xSet(
+ getAdditionalPropertySet( true ) );
+
+ OSL_ENSURE( xSet.is(),
+ "ContentImplHelper::addProperty - No property set!" );
+
+ if ( !xSet.is() )
+ return;
+
+ uno::Reference< beans::XPropertyContainer > xContainer(
+ xSet, uno::UNO_QUERY );
+
+ OSL_ENSURE(
+ xContainer.is(),
+ "ContentImplHelper::addProperty - No property container!" );
+
+ if ( !xContainer.is() )
+ return;
+
+ // Property is always removable.
+ Attributes |= beans::PropertyAttribute::REMOVABLE;
+
+ try
+ {
+ xContainer->addProperty( Name, Attributes, DefaultValue );
+ }
+ catch ( beans::PropertyExistException const & )
+ {
+ OSL_FAIL( "ContentImplHelper::addProperty - Exists!" );
+ throw;
+ }
+ catch ( beans::IllegalTypeException const & )
+ {
+ OSL_FAIL( "ContentImplHelper::addProperty - Wrong Type!" );
+ throw;
+ }
+ catch ( lang::IllegalArgumentException const & )
+ {
+ OSL_FAIL( "ContentImplHelper::addProperty - Illegal Arg!" );
+ throw;
+ }
+
+ // Success!
+
+ if ( m_pImpl->m_xPropSetInfo.is() )
+ {
+ // Info cached in propertyset info is invalid now!
+ m_pImpl->m_xPropSetInfo->reset();
+ }
+
+ // Notify propertyset info change listeners.
+ if ( m_pImpl->m_pPropSetChangeListeners &&
+ m_pImpl->m_pPropSetChangeListeners->getLength() )
+ {
+ beans::PropertySetInfoChangeEvent evt(
+ getXWeak(),
+ Name,
+ -1, // No handle available
+ beans::PropertySetInfoChange::PROPERTY_INSERTED );
+ notifyPropertySetInfoChange( evt );
+ }
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removeProperty( const OUString& Name )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ try
+ {
+ // @@@ Need real command environment here, but where to get it from?
+ // XPropertyContainer interface should be replaced by
+ // XCommandProcessor commands!
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv;
+
+ beans::Property aProp
+ = getPropertySetInfo( xEnv )->getPropertyByName( Name );
+
+ if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVABLE ) )
+ {
+ // Not removable!
+ throw beans::NotRemoveableException();
+ }
+ }
+ catch ( beans::UnknownPropertyException const & )
+ {
+ OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" );
+ throw;
+ }
+
+ // Try to remove property from dynamic property set.
+ // Open persistent property set, if exists.
+ uno::Reference< css::ucb::XPersistentPropertySet > xSet(
+ getAdditionalPropertySet( false ) );
+ if ( !xSet.is() )
+ return;
+
+ uno::Reference< beans::XPropertyContainer > xContainer(
+ xSet, uno::UNO_QUERY );
+
+ OSL_ENSURE(
+ xContainer.is(),
+ "ContentImplHelper::removeProperty - No property container!" );
+
+ if ( !xContainer.is() )
+ return;
+
+ try
+ {
+ xContainer->removeProperty( Name );
+ }
+ catch ( beans::UnknownPropertyException const & )
+ {
+ OSL_FAIL( "ContentImplHelper::removeProperty - Unknown!" );
+ throw;
+ }
+ catch ( beans::NotRemoveableException const & )
+ {
+ OSL_FAIL(
+ "ContentImplHelper::removeProperty - Unremovable!" );
+ throw;
+ }
+
+ xContainer = nullptr;
+
+ // Success!
+
+ if ( !xSet->getPropertySetInfo()->getProperties().hasElements() )
+ {
+ // Remove empty propertyset from registry.
+ uno::Reference< css::ucb::XPropertySetRegistry >
+ xReg = xSet->getRegistry();
+ if ( xReg.is() )
+ {
+ OUString aKey( xSet->getKey() );
+ xSet = nullptr;
+ xReg->removePropertySet( aKey );
+ }
+ }
+
+ if ( m_pImpl->m_xPropSetInfo.is() )
+ {
+ // Info cached in propertyset info is invalid now!
+ m_pImpl->m_xPropSetInfo->reset();
+ }
+
+ // Notify propertyset info change listeners.
+ if ( m_pImpl->m_pPropSetChangeListeners &&
+ m_pImpl->m_pPropSetChangeListeners->getLength() )
+ {
+ beans::PropertySetInfoChangeEvent evt(
+ getXWeak(),
+ Name,
+ -1, // No handle available
+ beans::PropertySetInfoChange::PROPERTY_REMOVED );
+ notifyPropertySetInfoChange( evt );
+ }
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::addPropertySetInfoChangeListener(
+ const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_pPropSetChangeListeners )
+ m_pImpl->m_pPropSetChangeListeners.reset(
+ new comphelper::OInterfaceContainerHelper3<beans::XPropertySetInfoChangeListener>( m_aMutex ));
+
+ m_pImpl->m_pPropSetChangeListeners->addInterface( Listener );
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::removePropertySetInfoChangeListener(
+ const uno::Reference< beans::XPropertySetInfoChangeListener >& Listener )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pImpl->m_pPropSetChangeListeners )
+ m_pImpl->m_pPropSetChangeListeners->removeInterface( Listener );
+}
+
+// virtual
+uno::Reference< uno::XInterface > SAL_CALL ContentImplHelper::getParent()
+{
+ uno::Reference< uno::XInterface > xParent;
+ OUString aURL = getParentURL();
+
+ if ( !aURL.isEmpty() )
+ {
+ uno::Reference< css::ucb::XContentIdentifier > xId(
+ new ContentIdentifier( aURL ) );
+ try
+ {
+ xParent.set( m_xProvider->queryContent( xId ) );
+ }
+ catch ( css::ucb::IllegalIdentifierException const & )
+ {
+ }
+ }
+
+ return xParent;
+}
+
+// virtual
+void SAL_CALL ContentImplHelper::setParent(
+ const uno::Reference< uno::XInterface >& )
+{
+ throw lang::NoSupportException();
+}
+
+uno::Reference< css::ucb::XPersistentPropertySet >
+ContentImplHelper::getAdditionalPropertySet( bool bCreate )
+{
+ // Get propertyset from provider.
+ return m_xProvider->getAdditionalPropertySet(
+ m_xIdentifier->getContentIdentifier(), bCreate );
+}
+
+bool ContentImplHelper::renameAdditionalPropertySet(
+ const OUString& rOldKey,
+ const OUString& rNewKey )
+{
+ return m_xProvider->renameAdditionalPropertySet(
+ rOldKey, rNewKey, true/*bRecursive*/ );
+}
+
+bool ContentImplHelper::copyAdditionalPropertySet(
+ const OUString& rSourceKey,
+ const OUString& rTargetKey )
+{
+ return m_xProvider->copyAdditionalPropertySet(
+ rSourceKey, rTargetKey, true/*bRecursive*/ );
+}
+
+bool ContentImplHelper::removeAdditionalPropertySet()
+{
+ return m_xProvider->removeAdditionalPropertySet(
+ m_xIdentifier->getContentIdentifier(), true/*bRecursive*/ );
+}
+
+void ContentImplHelper::notifyPropertiesChange(
+ const uno::Sequence< beans::PropertyChangeEvent >& evt ) const
+{
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ return;
+
+ sal_Int32 nCount = evt.getLength();
+ if ( !nCount )
+ return;
+
+ // First, notify listeners interested in changes of every property.
+ cppu::OInterfaceContainerHelper* pAllPropsContainer
+ = m_pImpl->m_pPropertyChangeListeners->getContainer(
+ OUString() );
+ if ( pAllPropsContainer )
+ {
+ cppu::OInterfaceIteratorHelper aIter( *pAllPropsContainer );
+ while ( aIter.hasMoreElements() )
+ {
+ // Propagate event.
+ static_cast< beans::XPropertiesChangeListener* >(
+ aIter.next())->propertiesChange( evt );
+ }
+ }
+
+ PropertiesEventListenerMap aListeners;
+
+ for ( const beans::PropertyChangeEvent& rEvent : evt )
+ {
+ const OUString& rName = rEvent.PropertyName;
+
+ cppu::OInterfaceContainerHelper* pPropsContainer
+ = m_pImpl->m_pPropertyChangeListeners->getContainer( rName );
+ if ( pPropsContainer )
+ {
+ cppu::OInterfaceIteratorHelper aIter( *pPropsContainer );
+ while ( aIter.hasMoreElements() )
+ {
+ PropertyEventSequence* p = nullptr;
+
+ beans::XPropertiesChangeListener* pListener =
+ static_cast< beans::XPropertiesChangeListener * >(
+ aIter.next() );
+ PropertiesEventListenerMap::iterator it =
+ aListeners.find( pListener );
+ if ( it == aListeners.end() )
+ {
+ // Not in map - create and insert new entry.
+ p = &aListeners.emplace( pListener, PropertyEventSequence(nCount)).first->second;
+ }
+ else
+ p = &it->second;
+
+ if ( p )
+ p->append( rEvent );
+ }
+ }
+ }
+
+ // Notify listeners.
+ PropertiesEventListenerMap::iterator it = aListeners.begin();
+ while ( !aListeners.empty() )
+ {
+ beans::XPropertiesChangeListener* pListener =
+ static_cast< beans::XPropertiesChangeListener * >( (*it).first );
+ PropertyEventSequence pSeq = std::move(it->second);
+
+ // Remove current element.
+ aListeners.erase( it );
+
+ // Propagate event.
+ pListener->propertiesChange( pSeq.getEvents() );
+
+ it = aListeners.begin();
+ }
+}
+
+void ContentImplHelper::notifyPropertySetInfoChange(
+ const beans::PropertySetInfoChangeEvent& evt ) const
+{
+ if ( !m_pImpl->m_pPropSetChangeListeners )
+ return;
+
+ // Notify event listeners.
+ m_pImpl->m_pPropSetChangeListeners->notifyEach( &beans::XPropertySetInfoChangeListener::propertySetInfoChange, evt );
+}
+
+void ContentImplHelper::notifyContentEvent(
+ const css::ucb::ContentEvent& evt ) const
+{
+ if ( !m_pImpl->m_pContentEventListeners )
+ return;
+
+ // Notify event listeners.
+ m_pImpl->m_pContentEventListeners->notifyEach( &css::ucb::XContentEventListener::contentEvent, evt);
+}
+
+void ContentImplHelper::inserted()
+{
+ // Content is not yet registered at provider.
+ m_xProvider->registerNewContent( this );
+
+ // If the parent content is currently not instantiated, there can be
+ // no listeners interested in changes ;-)
+
+ rtl::Reference< ContentImplHelper > xParent
+ = m_xProvider->queryExistingContent( getParentURL() );
+
+ if ( xParent.is() )
+ {
+ css::ucb::ContentEvent aEvt(
+ xParent->getXWeak(), // Source
+ css::ucb::ContentAction::INSERTED, // Action
+ this, // Content
+ xParent->getIdentifier() ); // Id
+ xParent->notifyContentEvent( aEvt );
+ }
+}
+
+void ContentImplHelper::deleted()
+{
+ uno::Reference< css::ucb::XContent > xThis = this;
+
+ rtl::Reference< ContentImplHelper > xParent
+ = m_xProvider->queryExistingContent( getParentURL() );
+
+ if ( xParent.is() )
+ {
+ // Let parent notify "REMOVED" event.
+ css::ucb::ContentEvent aEvt(
+ xParent->getXWeak(),
+ css::ucb::ContentAction::REMOVED,
+ this,
+ xParent->getIdentifier() );
+ xParent->notifyContentEvent( aEvt );
+ }
+
+ // Notify "DELETED" event.
+ css::ucb::ContentEvent aEvt1(
+ getXWeak(),
+ css::ucb::ContentAction::DELETED,
+ this,
+ getIdentifier() );
+ notifyContentEvent( aEvt1 );
+
+ m_xProvider->removeContent( this );
+}
+
+bool ContentImplHelper::exchange(
+ const uno::Reference< css::ucb::XContentIdentifier >& rNewId )
+{
+ uno::Reference< css::ucb::XContent > xThis = this;
+
+ osl::ClearableMutexGuard aGuard( m_aMutex );
+
+ rtl::Reference< ContentImplHelper > xContent
+ = m_xProvider->queryExistingContent( rNewId );
+ if ( xContent.is() )
+ {
+ // @@@
+ // Big trouble. Another object with the new identity exists.
+ // How shall I mutate to / merge with the other object?
+ return false;
+ }
+
+ uno::Reference< css::ucb::XContentIdentifier > xOldId
+ = getIdentifier();
+
+ // Re-insert at provider.
+ m_xProvider->removeContent( this );
+ m_xIdentifier = rNewId;
+ m_xProvider->registerNewContent( this );
+
+ aGuard.clear();
+
+ // Notify "EXCHANGED" event.
+ css::ucb::ContentEvent aEvt(
+ getXWeak(),
+ css::ucb::ContentAction::EXCHANGED,
+ this,
+ xOldId );
+ notifyContentEvent( aEvt );
+ return true;
+}
+
+uno::Reference< css::ucb::XCommandInfo >
+ContentImplHelper::getCommandInfo(
+ const uno::Reference< css::ucb::XCommandEnvironment > & xEnv,
+ bool bCache )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_xCommandsInfo.is() )
+ m_pImpl->m_xCommandsInfo
+ = new CommandProcessorInfo( xEnv, this );
+ else if ( !bCache )
+ m_pImpl->m_xCommandsInfo->reset();
+
+ return m_pImpl->m_xCommandsInfo;
+}
+
+uno::Reference< beans::XPropertySetInfo >
+ContentImplHelper::getPropertySetInfo(
+ const uno::Reference< css::ucb::XCommandEnvironment > & xEnv,
+ bool bCache )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_xPropSetInfo.is() )
+ m_pImpl->m_xPropSetInfo
+ = new PropertySetInfo( xEnv, this );
+ else if ( !bCache )
+ m_pImpl->m_xPropSetInfo->reset();
+
+ return m_pImpl->m_xPropSetInfo;
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/contentidentifier.cxx b/ucbhelper/source/provider/contentidentifier.cxx
new file mode 100644
index 0000000000..2a5da953d9
--- /dev/null
+++ b/ucbhelper/source/provider/contentidentifier.cxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ucbhelper/contentidentifier.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::ucb;
+
+
+namespace ucbhelper
+{
+
+struct ContentIdentifier_Impl
+{
+ OUString m_aContentId;
+ OUString m_aProviderScheme;
+
+ explicit ContentIdentifier_Impl( const OUString& rURL );
+};
+
+
+// ContentIdentifier_Impl Implementation.
+
+
+ContentIdentifier_Impl::ContentIdentifier_Impl(const OUString& rURL )
+{
+ // Normalize URL scheme ( it's case insensitive ).
+
+ // The content provider scheme is the part before the first ':'
+ // within the content id.
+ sal_Int32 nPos = rURL.indexOf( ':' );
+ if ( nPos != -1 )
+ {
+ OUString aScheme( rURL.copy( 0, nPos ) );
+ m_aProviderScheme = aScheme.toAsciiLowerCase();
+ m_aContentId = rURL.replaceAt( 0, nPos, aScheme );
+ }
+}
+
+
+// ContentIdentifier Implementation.
+
+
+ContentIdentifier::ContentIdentifier( const OUString& rURL )
+ : m_pImpl( new ContentIdentifier_Impl( rURL ) )
+{
+}
+
+
+// virtual
+ContentIdentifier::~ContentIdentifier()
+{
+}
+
+
+// XContentIdentifier methods.
+
+
+// virtual
+OUString SAL_CALL ContentIdentifier::getContentIdentifier()
+{
+ return m_pImpl->m_aContentId;
+}
+
+
+// virtual
+OUString SAL_CALL ContentIdentifier::getContentProviderScheme()
+{
+ return m_pImpl->m_aProviderScheme;
+}
+
+} /* namespace ucbhelper */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/contentinfo.cxx b/ucbhelper/source/provider/contentinfo.cxx
new file mode 100644
index 0000000000..1e513604eb
--- /dev/null
+++ b/ucbhelper/source/provider/contentinfo.cxx
@@ -0,0 +1,318 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
+#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+
+#include <ucbhelper/contenthelper.hxx>
+#include <utility>
+#include "contentinfo.hxx"
+
+using namespace com::sun::star;
+
+
+// PropertySetInfo Implementation.
+
+
+namespace ucbhelper {
+
+PropertySetInfo::PropertySetInfo(
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv,
+ ContentImplHelper* pContent )
+: m_xEnv(std::move( xEnv )),
+ m_pContent( pContent )
+{
+}
+
+
+// virtual
+PropertySetInfo::~PropertySetInfo()
+{
+}
+
+
+// XPropertySetInfo methods.
+
+
+// virtual
+uno::Sequence< beans::Property > SAL_CALL PropertySetInfo::getProperties()
+{
+ std::unique_lock aGuard( m_aMutex );
+ return getPropertiesImpl();
+}
+
+const uno::Sequence< beans::Property > & PropertySetInfo::getPropertiesImpl()
+{
+ if ( m_xProps )
+ return *m_xProps;
+
+ // Get info for core ( native) properties.
+
+ try
+ {
+ m_xProps = m_pContent->getProperties( m_xEnv );
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ throw;
+ }
+ catch ( uno::Exception const & )
+ {
+ m_xProps.emplace();
+ }
+
+ // Get info for additional properties.
+
+ uno::Reference< css::ucb::XPersistentPropertySet >
+ xSet ( m_pContent->getAdditionalPropertySet( false ) );
+
+ if ( xSet.is() )
+ {
+ // Get property set info.
+ uno::Reference< beans::XPropertySetInfo > xInfo(
+ xSet->getPropertySetInfo() );
+ if ( xInfo.is() )
+ {
+ const uno::Sequence< beans::Property >& rAddProps
+ = xInfo->getProperties();
+ sal_Int32 nAddProps = rAddProps.getLength();
+ if ( nAddProps > 0 )
+ {
+ sal_Int32 nPos = m_xProps->getLength();
+ m_xProps->realloc( nPos + nAddProps );
+
+ std::copy(rAddProps.begin(), rAddProps.end(),
+ std::next(m_xProps->getArray(), nPos));
+ }
+ }
+ }
+ return *m_xProps;
+}
+
+
+// virtual
+beans::Property SAL_CALL PropertySetInfo::getPropertyByName(
+ const OUString& aName )
+{
+ beans::Property aProp;
+ if ( queryProperty( aName, aProp ) )
+ return aProp;
+
+ throw beans::UnknownPropertyException(aName);
+}
+
+
+// virtual
+sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName(
+ const OUString& Name )
+{
+ beans::Property aProp;
+ return queryProperty( Name, aProp );
+}
+
+
+// Non-Interface methods.
+
+
+void PropertySetInfo::reset()
+{
+ std::unique_lock aGuard( m_aMutex );
+ m_xProps.reset();
+}
+
+
+bool PropertySetInfo::queryProperty(
+ std::u16string_view rName, beans::Property& rProp )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ getPropertiesImpl();
+
+ const beans::Property* pProps = m_xProps->getConstArray();
+ sal_Int32 nCount = m_xProps->getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::Property& rCurrProp = pProps[ n ];
+ if ( rCurrProp.Name == rName )
+ {
+ rProp = rCurrProp;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// CommandProcessorInfo Implementation.
+
+
+CommandProcessorInfo::CommandProcessorInfo(
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv,
+ ContentImplHelper* pContent )
+: m_xEnv(std::move( xEnv )),
+ m_pContent( pContent )
+{
+}
+
+
+// virtual
+CommandProcessorInfo::~CommandProcessorInfo()
+{
+}
+
+
+// XCommandInfo methods.
+
+
+// virtual
+uno::Sequence< css::ucb::CommandInfo > SAL_CALL CommandProcessorInfo::getCommands()
+{
+ std::unique_lock aGuard( m_aMutex );
+ return getCommandsImpl();
+}
+
+const uno::Sequence< css::ucb::CommandInfo > & CommandProcessorInfo::getCommandsImpl()
+{
+ if ( m_xCommands )
+ return *m_xCommands;
+
+ // Get info for commands.
+
+ try
+ {
+ m_xCommands = m_pContent->getCommands( m_xEnv );
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ throw;
+ }
+ catch ( uno::Exception const & )
+ {
+ m_xCommands.emplace();
+ }
+ return *m_xCommands;
+}
+
+
+// virtual
+css::ucb::CommandInfo SAL_CALL
+CommandProcessorInfo::getCommandInfoByName(
+ const OUString& Name )
+{
+ css::ucb::CommandInfo aInfo;
+ if ( queryCommand( Name, aInfo ) )
+ return aInfo;
+
+ throw css::ucb::UnsupportedCommandException();
+}
+
+
+// virtual
+css::ucb::CommandInfo SAL_CALL
+CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle )
+{
+ css::ucb::CommandInfo aInfo;
+ if ( queryCommand( Handle, aInfo ) )
+ return aInfo;
+
+ throw css::ucb::UnsupportedCommandException();
+}
+
+
+// virtual
+sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName(
+ const OUString& Name )
+{
+ css::ucb::CommandInfo aInfo;
+ return queryCommand( Name, aInfo );
+}
+
+
+// virtual
+sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle )
+{
+ css::ucb::CommandInfo aInfo;
+ return queryCommand( Handle, aInfo );
+}
+
+
+// Non-Interface methods.
+
+
+void CommandProcessorInfo::reset()
+{
+ std::unique_lock aGuard( m_aMutex );
+ m_xCommands.reset();
+}
+
+
+bool CommandProcessorInfo::queryCommand(
+ std::u16string_view rName,
+ css::ucb::CommandInfo& rCommand )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ getCommandsImpl();
+
+ const css::ucb::CommandInfo* pCommands
+ = m_xCommands->getConstArray();
+ sal_Int32 nCount = m_xCommands->getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const css::ucb::CommandInfo& rCurrCommand = pCommands[ n ];
+ if ( rCurrCommand.Name == rName )
+ {
+ rCommand = rCurrCommand;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool CommandProcessorInfo::queryCommand(
+ sal_Int32 nHandle,
+ css::ucb::CommandInfo& rCommand )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ getCommandsImpl();
+
+ const css::ucb::CommandInfo* pCommands = m_xCommands->getConstArray();
+ sal_Int32 nCount = m_xCommands->getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const css::ucb::CommandInfo& rCurrCommand = pCommands[ n ];
+ if ( rCurrCommand.Handle == nHandle )
+ {
+ rCommand = rCurrCommand;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/contentinfo.hxx b/ucbhelper/source/provider/contentinfo.hxx
new file mode 100644
index 0000000000..b24a291ccb
--- /dev/null
+++ b/ucbhelper/source/provider/contentinfo.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef UCBHELPER_SOURCE_PROVIDER_CONTENTINFO_HXX
+#define UCBHELPER_SOURCE_PROVIDER_CONTENTINFO_HXX
+
+#include <optional>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <mutex>
+
+namespace com::sun::star::ucb { class XCommandEnvironment; }
+
+namespace ucbhelper {
+
+
+
+
+class ContentImplHelper;
+
+/**
+ * This class provides a propertyset info ( the complete implementation of
+ * the interface XPropertySetInfo ) for an object derived from class
+ * ucb::ContentImplHelper. The implementation takes care about Additional
+ * Core Properties that may have been added to the content.
+ */
+class PropertySetInfo :
+ public cppu::WeakImplHelper<css::beans::XPropertySetInfo>
+{
+ css::uno::Reference< css::ucb::XCommandEnvironment >
+ m_xEnv;
+ std::optional<css::uno::Sequence< css::beans::Property >>
+ m_xProps;
+ std::mutex m_aMutex;
+ ContentImplHelper* m_pContent;
+
+private:
+ bool queryProperty( std::u16string_view rName,
+ css::beans::Property& rProp );
+ const css::uno::Sequence< css::beans::Property > & getPropertiesImpl();
+
+public:
+ PropertySetInfo( css::uno::Reference< css::ucb::XCommandEnvironment > xEnv,
+ ContentImplHelper* pContent );
+ virtual ~PropertySetInfo() override;
+
+ // XPropertySetInfo
+ virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override;
+ virtual css::beans::Property SAL_CALL getPropertyByName( const OUString& aName ) override;
+ virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
+
+ // Non-Interface methods.
+ void reset();
+};
+
+
+
+
+/**
+ * This class provides a command info ( the complete implementation of
+ * the interface XCommandInfo ) for an object derived from class
+ * ucb::ContentImplHelper.
+ */
+class CommandProcessorInfo :
+ public cppu::WeakImplHelper<css::ucb::XCommandInfo>
+{
+ css::uno::Reference< css::ucb::XCommandEnvironment >
+ m_xEnv;
+ std::optional<css::uno::Sequence< css::ucb::CommandInfo >>
+ m_xCommands;
+ std::mutex m_aMutex;
+ ContentImplHelper* m_pContent;
+
+private:
+ bool queryCommand( std::u16string_view rName,
+ css::ucb::CommandInfo& rCommand );
+ bool queryCommand( sal_Int32 nHandle,
+ css::ucb::CommandInfo& rCommand );
+ const css::uno::Sequence< css::ucb::CommandInfo > & getCommandsImpl();
+
+public:
+ CommandProcessorInfo( css::uno::Reference< css::ucb::XCommandEnvironment > xEnv,
+ ContentImplHelper* pContent );
+ virtual ~CommandProcessorInfo() override;
+
+ // XCommandInfo
+ virtual css::uno::Sequence< css::ucb::CommandInfo > SAL_CALL getCommands() override;
+ virtual css::ucb::CommandInfo SAL_CALL getCommandInfoByName( const OUString& Name ) override;
+ virtual css::ucb::CommandInfo SAL_CALL getCommandInfoByHandle( sal_Int32 Handle ) override;
+ virtual sal_Bool SAL_CALL hasCommandByName( const OUString& Name ) override;
+ virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle ) override;
+
+ // Non-Interface methods.
+ void reset();
+};
+
+} // namespace ucbhelper
+
+#endif /* ! UCBHELPER_SOURCE_PROVIDER_CONTENTINFO_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/interactionrequest.cxx b/ucbhelper/source/provider/interactionrequest.cxx
new file mode 100644
index 0000000000..0ac7ec9499
--- /dev/null
+++ b/ucbhelper/source/provider/interactionrequest.cxx
@@ -0,0 +1,626 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ucbhelper/interactionrequest.hxx>
+
+#include <rtl/ref.hxx>
+#include <osl/diagnose.h>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <utility>
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+
+// InteractionRequest Implementation.
+
+
+namespace ucbhelper
+{
+
+struct InteractionRequest_Impl
+{
+ rtl::Reference< InteractionContinuation > m_xSelection;
+ css::uno::Any m_aRequest;
+ css::uno::Sequence<
+ css::uno::Reference<
+ css::task::XInteractionContinuation > > m_aContinuations;
+
+ InteractionRequest_Impl() {}
+ explicit InteractionRequest_Impl( uno::Any aRequest )
+ : m_aRequest(std::move( aRequest )) {}
+};
+
+}
+
+
+InteractionRequest::InteractionRequest()
+: m_pImpl( new InteractionRequest_Impl )
+{
+}
+
+
+InteractionRequest::InteractionRequest( const uno::Any & rRequest )
+: m_pImpl( new InteractionRequest_Impl( rRequest ) )
+{
+}
+
+
+// virtual
+InteractionRequest::~InteractionRequest()
+{
+}
+
+
+void InteractionRequest::setRequest( const uno::Any & rRequest )
+{
+ m_pImpl->m_aRequest = rRequest;
+}
+
+
+void InteractionRequest::setContinuations(
+ const uno::Sequence< uno::Reference<
+ task::XInteractionContinuation > > & rContinuations )
+{
+ m_pImpl->m_aContinuations = rContinuations;
+}
+
+
+rtl::Reference< InteractionContinuation > const &
+InteractionRequest::getSelection() const
+{
+ return m_pImpl->m_xSelection;
+}
+
+
+void InteractionRequest::setSelection(
+ const rtl::Reference< InteractionContinuation > & rxSelection )
+{
+ m_pImpl->m_xSelection = rxSelection;
+}
+
+
+// XInterface methods.
+
+
+// XInteractionRequest methods.
+
+
+// virtual
+uno::Any SAL_CALL InteractionRequest::getRequest()
+{
+ return m_pImpl->m_aRequest;
+}
+
+
+// virtual
+uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL
+InteractionRequest::getContinuations()
+{
+ return m_pImpl->m_aContinuations;
+}
+
+
+// InteractionContinuation Implementation.
+
+
+InteractionContinuation::InteractionContinuation(
+ InteractionRequest * pRequest )
+: m_pRequest( pRequest )
+{
+}
+
+
+// virtual
+InteractionContinuation::~InteractionContinuation()
+{
+}
+
+
+void InteractionContinuation::recordSelection()
+{
+ m_pRequest->setSelection( this );
+}
+
+
+// InteractionAbort Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionAbort::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< task::XInteractionAbort * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL InteractionAbort::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionAbort::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<task::XInteractionAbort>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionAbort::select()
+{
+ recordSelection();
+}
+
+
+// InteractionRetry Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionRetry::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< task::XInteractionRetry * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL InteractionRetry::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionRetry::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<task::XInteractionRetry>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionRetry::select()
+{
+ recordSelection();
+}
+
+
+// InteractionApprove Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionApprove::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< task::XInteractionApprove * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL InteractionApprove::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionApprove::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<task::XInteractionApprove>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionApprove::select()
+{
+ recordSelection();
+}
+
+
+// InteractionDisapprove Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionDisapprove::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< task::XInteractionDisapprove * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL InteractionDisapprove::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionDisapprove::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<task::XInteractionDisapprove>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionDisapprove::select()
+{
+ recordSelection();
+}
+
+
+// InteractionSupplyAuthentication Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionSupplyAuthentication::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< ucb::XInteractionSupplyAuthentication * >( this ),
+ static_cast< ucb::XInteractionSupplyAuthentication2 * >( this ));
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL
+InteractionSupplyAuthentication::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionSupplyAuthentication::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<ucb::XInteractionSupplyAuthentication2>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionSupplyAuthentication::select()
+{
+ recordSelection();
+}
+
+
+// XInteractionSupplyAuthentication methods.
+
+
+// virtual
+sal_Bool SAL_CALL
+InteractionSupplyAuthentication::canSetRealm()
+{
+ return m_bCanSetRealm;
+}
+
+
+// virtual
+void SAL_CALL
+InteractionSupplyAuthentication::setRealm( const OUString& Realm )
+{
+ OSL_ENSURE( m_bCanSetPassword,
+ "InteractionSupplyAuthentication::setRealm - Not supported!" );
+
+ if ( m_bCanSetRealm )
+ m_aRealm = Realm;
+}
+
+
+// virtual
+sal_Bool SAL_CALL
+InteractionSupplyAuthentication::canSetUserName()
+{
+ return m_bCanSetUserName;
+}
+
+
+// virtual
+void SAL_CALL
+InteractionSupplyAuthentication::setUserName( const OUString& UserName )
+{
+ OSL_ENSURE( m_bCanSetUserName,
+ "InteractionSupplyAuthentication::setUserName - Not supported!" );
+
+ if ( m_bCanSetUserName )
+ m_aUserName = UserName;
+}
+
+
+// virtual
+sal_Bool SAL_CALL
+InteractionSupplyAuthentication::canSetPassword()
+{
+ return m_bCanSetPassword;
+}
+
+
+// virtual
+void SAL_CALL
+InteractionSupplyAuthentication::setPassword( const OUString& Password )
+{
+ OSL_ENSURE( m_bCanSetPassword,
+ "InteractionSupplyAuthentication::setPassword - Not supported!" );
+
+ if ( m_bCanSetPassword )
+ m_aPassword = Password;
+}
+
+
+// virtual
+uno::Sequence< ucb::RememberAuthentication > SAL_CALL
+InteractionSupplyAuthentication::getRememberPasswordModes(
+ ucb::RememberAuthentication& Default )
+{
+ Default = m_eDefaultRememberPasswordMode;
+ return m_aRememberPasswordModes;
+}
+
+
+// virtual
+void SAL_CALL
+InteractionSupplyAuthentication::setRememberPassword(
+ ucb::RememberAuthentication Remember )
+{
+ m_eRememberPasswordMode = Remember;
+}
+
+
+// virtual
+sal_Bool SAL_CALL
+InteractionSupplyAuthentication::canSetAccount()
+{
+ return m_bCanSetAccount;
+}
+
+
+// virtual
+void SAL_CALL
+InteractionSupplyAuthentication::setAccount( const OUString& /*Account*/ )
+{
+ OSL_ENSURE( m_bCanSetAccount,
+ "InteractionSupplyAuthentication::setAccount - Not supported!" );
+}
+
+
+// virtual
+uno::Sequence< ucb::RememberAuthentication > SAL_CALL
+InteractionSupplyAuthentication::getRememberAccountModes(
+ ucb::RememberAuthentication& Default )
+{
+ Default = m_eDefaultRememberAccountMode;
+ return m_aRememberAccountModes;
+}
+
+
+// virtual
+void SAL_CALL InteractionSupplyAuthentication::setRememberAccount(
+ ucb::RememberAuthentication )
+{
+}
+
+
+// XInteractionSupplyAuthentication2 methods.
+
+
+// virtual
+sal_Bool SAL_CALL
+InteractionSupplyAuthentication::canUseSystemCredentials(
+ sal_Bool& Default )
+{
+ Default = false;
+ return m_bCanUseSystemCredentials;
+}
+
+
+// virtual
+void SAL_CALL InteractionSupplyAuthentication::setUseSystemCredentials(
+ sal_Bool UseSystemCredentials )
+{
+ if ( m_bCanUseSystemCredentials )
+ m_bUseSystemCredentials = UseSystemCredentials;
+}
+
+
+// InteractionReplaceExistingData Implementation.
+
+
+// XInterface methods.
+
+
+// virtual
+uno::Any SAL_CALL
+InteractionReplaceExistingData::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< ucb::XInteractionReplaceExistingData * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+
+// XTypeProvider methods.
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL
+InteractionReplaceExistingData::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+// virtual
+uno::Sequence< uno::Type > SAL_CALL InteractionReplaceExistingData::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<ucb::XInteractionReplaceExistingData>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+
+// XInteractionContinuation methods.
+
+
+// virtual
+void SAL_CALL InteractionReplaceExistingData::select()
+{
+ recordSelection();
+}
+
+// InteractionAuthFallback Implementation
+
+// XInterface methods.
+
+// virtual
+uno::Any SAL_CALL
+InteractionAuthFallback::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< ucb::XInteractionAuthFallback * >( this ));
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+// XInteractionContinuation methods.
+
+// virtual
+void SAL_CALL InteractionAuthFallback::select()
+{
+ recordSelection();
+}
+
+// XInteractionAuthFallback methods
+
+// virtual
+void SAL_CALL InteractionAuthFallback::setCode( const OUString& code )
+{
+ m_aCode = code;
+}
+
+const OUString& InteractionAuthFallback::getCode() const
+{
+ return m_aCode;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/propertyvalueset.cxx b/ucbhelper/source/provider/propertyvalueset.cxx
new file mode 100644
index 0000000000..b019d3b9c8
--- /dev/null
+++ b/ucbhelper/source/provider/propertyvalueset.cxx
@@ -0,0 +1,680 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <vector>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/script/CannotConvertException.hpp>
+#include <com/sun/star/script/Converter.hpp>
+
+#include <osl/diagnose.h>
+#include <ucbhelper/propertyvalueset.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace com::sun::star::io;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::script;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+
+enum class PropsSet {
+ NONE = 0x00000000,
+ String = 0x00000001,
+ Boolean = 0x00000002,
+ Byte = 0x00000004,
+ Short = 0x00000008,
+ Int = 0x00000010,
+ Long = 0x00000020,
+ Float = 0x00000040,
+ Double = 0x00000080,
+ Bytes = 0x00000100,
+ Date = 0x00000200,
+ Time = 0x00000400,
+ Timestamp = 0x00000800,
+ BinaryStream = 0x00001000,
+ CharacterStream = 0x00002000,
+ Ref = 0x00004000,
+ Blob = 0x00008000,
+ Clob = 0x00010000,
+ Array = 0x00020000,
+ Object = 0x00040000
+};
+namespace o3tl {
+ template<> struct typed_flags<PropsSet> : is_typed_flags<PropsSet, 0x0007ffff> {};
+}
+
+namespace ucbhelper_impl
+{
+
+
+struct PropertyValue
+{
+ OUString sPropertyName;
+
+ PropsSet nPropsSet;
+ PropsSet nOrigValue;
+
+ OUString aString; // getString
+ bool bBoolean; // getBoolean
+ sal_Int8 nByte; // getByte
+ sal_Int16 nShort; // getShort
+ sal_Int32 nInt; // getInt
+ sal_Int64 nLong; // getLong
+ float nFloat; // getFloat
+ double nDouble; // getDouble
+
+ Sequence< sal_Int8 > aBytes; // getBytes
+ Date aDate; // getDate
+ Time aTime; // getTime
+ DateTime aTimestamp; // getTimestamp
+ Reference< XInputStream > xBinaryStream; // getBinaryStream
+ Reference< XInputStream > xCharacterStream; // getCharacterStream
+ Reference< XRef > xRef; // getRef
+ Reference< XBlob > xBlob; // getBlob
+ Reference< XClob > xClob; // getClob
+ Reference< XArray > xArray; // getArray
+ Any aObject; // getObject
+
+ PropertyValue()
+ : nPropsSet( PropsSet::NONE ), nOrigValue( PropsSet::NONE ),
+ bBoolean(false),
+ nByte(0),
+ nShort(0),
+ nInt(0),
+ nLong(0),
+ nFloat(0.0),
+ nDouble(0.0)
+ {}
+};
+} // namespace ucbhelper_impl
+
+using namespace ucbhelper_impl;
+
+namespace ucbhelper
+{
+
+class PropertyValues : public std::vector< ucbhelper_impl::PropertyValue > {};
+
+} // namespace ucbhelper
+
+
+namespace ucbhelper {
+
+
+// PropertyValueSet Implementation.
+
+
+PropertyValueSet::PropertyValueSet(
+ const Reference< XComponentContext >& rxContext )
+: m_xContext( rxContext ),
+ m_pValues( new PropertyValues ),
+ m_bWasNull( false ),
+ m_bTriedToGetTypeConverter( false )
+
+{
+}
+
+
+// virtual
+PropertyValueSet::~PropertyValueSet()
+{
+}
+
+
+// XRow methods.
+
+
+template <class T, T ucbhelper_impl::PropertyValue::*_member_name_>
+T PropertyValueSet::getValue(PropsSet nTypeName, sal_Int32 columnIndex)
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ T aValue {}; /* default ctor */
+
+ m_bWasNull = true;
+
+ if ( ( columnIndex < 1 ) || ( o3tl::make_unsigned(columnIndex) > m_pValues->size() ) )
+ {
+ OSL_FAIL( "PropertyValueSet - index out of range!" );
+ return aValue;
+ }
+ ucbhelper_impl::PropertyValue& rValue = (*m_pValues)[ columnIndex - 1 ];
+
+ if ( rValue.nOrigValue == PropsSet::NONE )
+ return aValue;
+
+ if ( rValue.nPropsSet & nTypeName )
+ {
+ /* Values is present natively... */
+ aValue = rValue.*_member_name_;
+ m_bWasNull = false;
+ return aValue;
+ }
+
+ if ( !(rValue.nPropsSet & PropsSet::Object) )
+ {
+ /* Value is not (yet) available as Any. Create it. */
+ getObject( columnIndex, Reference< XNameAccess >() );
+ }
+
+ if ( rValue.nPropsSet & PropsSet::Object )
+ {
+ /* Value is available as Any. */
+
+ if ( rValue.aObject.hasValue() )
+ {
+ /* Try to convert into native value. */
+ if ( rValue.aObject >>= aValue )
+ {
+ rValue.*_member_name_ = aValue;
+ rValue.nPropsSet |= nTypeName;
+ m_bWasNull = false;
+ }
+ else
+ {
+ /* Last chance. Try type converter service... */
+
+ Reference< XTypeConverter > xConverter = getTypeConverter();
+ if ( xConverter.is() )
+ {
+ try
+ {
+ Any aConvAny = xConverter->convertTo(
+ rValue.aObject,
+ cppu::UnoType<T>::get() );
+
+ if ( aConvAny >>= aValue )
+ {
+ rValue.*_member_name_ = aValue;
+ rValue.nPropsSet |= nTypeName;
+ m_bWasNull = false;
+ }
+ }
+ catch (const IllegalArgumentException&)
+ {
+ }
+ catch (const CannotConvertException&)
+ {
+ }
+ }
+ }
+ }
+ }
+
+ return aValue;
+}
+
+
+// virtual
+sal_Bool SAL_CALL PropertyValueSet::wasNull()
+{
+ // This method can not be implemented correctly!!! Imagine different
+ // threads doing a getXYZ - wasNull calling sequence on the same
+ // implementation object...
+ return m_bWasNull;
+}
+
+
+// virtual
+OUString SAL_CALL PropertyValueSet::getString( sal_Int32 columnIndex )
+{
+ return getValue<OUString, &ucbhelper_impl::PropertyValue::aString>(PropsSet::String, columnIndex);
+}
+
+
+// virtual
+sal_Bool SAL_CALL PropertyValueSet::getBoolean( sal_Int32 columnIndex )
+{
+ return getValue<bool, &ucbhelper_impl::PropertyValue::bBoolean>(PropsSet::Boolean, columnIndex);
+}
+
+
+// virtual
+sal_Int8 SAL_CALL PropertyValueSet::getByte( sal_Int32 columnIndex )
+{
+ return getValue<sal_Int8, &ucbhelper_impl::PropertyValue::nByte>(PropsSet::Byte, columnIndex);
+}
+
+
+// virtual
+sal_Int16 SAL_CALL PropertyValueSet::getShort( sal_Int32 columnIndex )
+{
+ return getValue<sal_Int16, &ucbhelper_impl::PropertyValue::nShort>(PropsSet::Short, columnIndex);
+}
+
+
+// virtual
+sal_Int32 SAL_CALL PropertyValueSet::getInt( sal_Int32 columnIndex )
+{
+ return getValue<sal_Int32, &ucbhelper_impl::PropertyValue::nInt>(PropsSet::Int, columnIndex);
+}
+
+
+// virtual
+sal_Int64 SAL_CALL PropertyValueSet::getLong( sal_Int32 columnIndex )
+{
+ return getValue<sal_Int64, &ucbhelper_impl::PropertyValue::nLong>(PropsSet::Long, columnIndex);
+}
+
+
+// virtual
+float SAL_CALL PropertyValueSet::getFloat( sal_Int32 columnIndex )
+{
+ return getValue<float, &ucbhelper_impl::PropertyValue::nFloat>(PropsSet::Float, columnIndex);
+}
+
+
+// virtual
+double SAL_CALL PropertyValueSet::getDouble( sal_Int32 columnIndex )
+{
+ return getValue<double, &ucbhelper_impl::PropertyValue::nDouble>(PropsSet::Double, columnIndex);
+}
+
+
+// virtual
+Sequence< sal_Int8 > SAL_CALL
+PropertyValueSet::getBytes( sal_Int32 columnIndex )
+{
+ return getValue<Sequence< sal_Int8 >, &ucbhelper_impl::PropertyValue::aBytes>(PropsSet::Bytes, columnIndex);
+}
+
+
+// virtual
+Date SAL_CALL PropertyValueSet::getDate( sal_Int32 columnIndex )
+{
+ return getValue<Date, &ucbhelper_impl::PropertyValue::aDate>(PropsSet::Date, columnIndex);
+}
+
+
+// virtual
+Time SAL_CALL PropertyValueSet::getTime( sal_Int32 columnIndex )
+{
+ return getValue<Time, &ucbhelper_impl::PropertyValue::aTime>(PropsSet::Time, columnIndex);
+}
+
+
+// virtual
+DateTime SAL_CALL PropertyValueSet::getTimestamp( sal_Int32 columnIndex )
+{
+ return getValue<DateTime, &ucbhelper_impl::PropertyValue::aTimestamp>(PropsSet::Timestamp, columnIndex);
+}
+
+
+// virtual
+Reference< XInputStream > SAL_CALL
+PropertyValueSet::getBinaryStream( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XInputStream >, &ucbhelper_impl::PropertyValue::xBinaryStream>(PropsSet::BinaryStream, columnIndex);
+}
+
+
+// virtual
+Reference< XInputStream > SAL_CALL
+PropertyValueSet::getCharacterStream( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XInputStream >, &ucbhelper_impl::PropertyValue::xCharacterStream>(PropsSet::CharacterStream, columnIndex);
+}
+
+
+// virtual
+Any SAL_CALL PropertyValueSet::getObject(
+ sal_Int32 columnIndex,
+ const Reference< XNameAccess >& )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ Any aValue;
+
+ m_bWasNull = true;
+
+ if ( ( columnIndex < 1 )
+ || ( o3tl::make_unsigned(columnIndex) > m_pValues->size() ) )
+ {
+ OSL_FAIL( "PropertyValueSet - index out of range!" );
+ }
+ else
+ {
+ ucbhelper_impl::PropertyValue& rValue
+ = (*m_pValues)[ columnIndex - 1 ];
+
+ if ( rValue.nPropsSet & PropsSet::Object )
+ {
+ // Values is present natively...
+ aValue = rValue.aObject;
+ m_bWasNull = false;
+ }
+ else
+ {
+ // Make Any from original value.
+
+ switch ( rValue.nOrigValue )
+ {
+ case PropsSet::NONE:
+ break;
+
+ case PropsSet::String:
+ aValue <<= rValue.aString;
+ break;
+
+ case PropsSet::Boolean:
+ aValue <<= rValue.bBoolean;
+ break;
+
+ case PropsSet::Byte:
+ aValue <<= rValue.nByte;
+ break;
+
+ case PropsSet::Short:
+ aValue <<= rValue.nShort;
+ break;
+
+ case PropsSet::Int:
+ aValue <<= rValue.nInt;
+ break;
+
+ case PropsSet::Long:
+ aValue <<= rValue.nLong;
+ break;
+
+ case PropsSet::Float:
+ aValue <<= rValue.nFloat;
+ break;
+
+ case PropsSet::Double:
+ aValue <<= rValue.nDouble;
+ break;
+
+ case PropsSet::Bytes:
+ aValue <<= rValue.aBytes;
+ break;
+
+ case PropsSet::Date:
+ aValue <<= rValue.aDate;
+ break;
+
+ case PropsSet::Time:
+ aValue <<= rValue.aTime;
+ break;
+
+ case PropsSet::Timestamp:
+ aValue <<= rValue.aTimestamp;
+ break;
+
+ case PropsSet::BinaryStream:
+ aValue <<= rValue.xBinaryStream;
+ break;
+
+ case PropsSet::CharacterStream:
+ aValue <<= rValue.xCharacterStream;
+ break;
+
+ case PropsSet::Ref:
+ aValue <<= rValue.xRef;
+ break;
+
+ case PropsSet::Blob:
+ aValue <<= rValue.xBlob;
+ break;
+
+ case PropsSet::Clob:
+ aValue <<= rValue.xClob;
+ break;
+
+ case PropsSet::Array:
+ aValue <<= rValue.xArray;
+ break;
+
+ case PropsSet::Object:
+ // Fall-through is intended!
+ default:
+ OSL_FAIL( "PropertyValueSet::getObject - "
+ "Wrong original type" );
+ break;
+ }
+
+ if ( aValue.hasValue() )
+ {
+ rValue.aObject = aValue;
+ rValue.nPropsSet |= PropsSet::Object;
+ m_bWasNull = false;
+ }
+ }
+ }
+
+ return aValue;
+}
+
+
+// virtual
+Reference< XRef > SAL_CALL PropertyValueSet::getRef( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XRef >, &ucbhelper_impl::PropertyValue::xRef>(PropsSet::Ref, columnIndex);
+}
+
+
+// virtual
+Reference< XBlob > SAL_CALL PropertyValueSet::getBlob( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XBlob >, &ucbhelper_impl::PropertyValue::xBlob>(PropsSet::Blob, columnIndex);
+}
+
+
+// virtual
+Reference< XClob > SAL_CALL PropertyValueSet::getClob( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XClob >, &ucbhelper_impl::PropertyValue::xClob>(PropsSet::Clob, columnIndex);
+}
+
+
+// virtual
+Reference< XArray > SAL_CALL PropertyValueSet::getArray( sal_Int32 columnIndex )
+{
+ return getValue<Reference< XArray >, &ucbhelper_impl::PropertyValue::xArray>(PropsSet::Array, columnIndex);
+}
+
+
+// XColumnLocate methods.
+
+
+// virtual
+sal_Int32 SAL_CALL PropertyValueSet::findColumn( const OUString& columnName )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( !columnName.isEmpty() )
+ {
+ sal_Int32 nCount = m_pValues->size();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ if ( (*m_pValues)[ n ].sPropertyName == columnName )
+ return n + 1; // Index is 1-based.
+ }
+ }
+ return 0;
+}
+
+
+// Non-interface methods.
+
+
+const Reference< XTypeConverter >& PropertyValueSet::getTypeConverter()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( !m_bTriedToGetTypeConverter && !m_xTypeConverter.is() )
+ {
+ m_bTriedToGetTypeConverter = true;
+ m_xTypeConverter = Converter::create(m_xContext);
+
+ OSL_ENSURE( m_xTypeConverter.is(),
+ "PropertyValueSet::getTypeConverter() - "
+ "Service 'com.sun.star.script.Converter' n/a!" );
+ }
+ return m_xTypeConverter;
+}
+
+
+template <class T, T ucbhelper_impl::PropertyValue::*_member_name_>
+void PropertyValueSet::appendValue(const OUString& rPropName, PropsSet nTypeName, const T& rValue)
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ ucbhelper_impl::PropertyValue aNewValue;
+ aNewValue.sPropertyName = rPropName;
+ aNewValue.nPropsSet = nTypeName;
+ aNewValue.nOrigValue = nTypeName;
+ aNewValue.*_member_name_ = rValue;
+
+ m_pValues->push_back( aNewValue );
+}
+
+
+void PropertyValueSet::appendString( const OUString& rPropName,
+ const OUString& rValue )
+{
+ appendValue<OUString, &ucbhelper_impl::PropertyValue::aString>(rPropName, PropsSet::String, rValue);
+}
+
+
+void PropertyValueSet::appendBoolean( const OUString& rPropName,
+ bool bValue )
+{
+ appendValue<bool, &ucbhelper_impl::PropertyValue::bBoolean>(rPropName, PropsSet::Boolean, bValue);
+}
+
+
+void PropertyValueSet::appendLong( const OUString& rPropName,
+ sal_Int64 nValue )
+{
+ appendValue<sal_Int64, &ucbhelper_impl::PropertyValue::nLong>(rPropName, PropsSet::Long, nValue);
+}
+
+
+void PropertyValueSet::appendTimestamp( const OUString& rPropName,
+ const DateTime& rValue )
+{
+ appendValue<DateTime, &ucbhelper_impl::PropertyValue::aTimestamp>(rPropName, PropsSet::Timestamp, rValue);
+}
+
+
+void PropertyValueSet::appendObject( const OUString& rPropName,
+ const Any& rValue )
+{
+ appendValue<Any, &ucbhelper_impl::PropertyValue::aObject>(rPropName, PropsSet::Object, rValue);
+}
+
+
+void PropertyValueSet::appendVoid( const OUString& rPropName )
+{
+ appendValue<Any, &ucbhelper_impl::PropertyValue::aObject>(rPropName, PropsSet::NONE, Any());
+}
+
+
+void PropertyValueSet::appendPropertySet(
+ const Reference< XPropertySet >& rxSet )
+{
+ if ( !rxSet.is() )
+ return;
+
+ Reference< XPropertySetInfo > xInfo = rxSet->getPropertySetInfo();
+ if ( !xInfo.is() )
+ return;
+
+ const Sequence< Property > aProps = xInfo->getProperties();
+
+ Reference< XPropertyAccess > xPropertyAccess( rxSet, UNO_QUERY );
+ if ( xPropertyAccess.is() )
+ {
+ // Efficient: Get all prop values with one ( remote) call.
+
+ const Sequence< css::beans::PropertyValue > aPropValues
+ = xPropertyAccess->getPropertyValues();
+
+ for ( const css::beans::PropertyValue& rPropValue : aPropValues )
+ {
+ // Find info for current property value.
+ auto pProp = std::find_if(aProps.begin(), aProps.end(),
+ [&rPropValue](const Property& rProp) { return rProp.Name == rPropValue.Name; });
+ if (pProp != aProps.end())
+ {
+ // Found!
+ appendObject( *pProp, rPropValue.Value );
+ }
+ }
+ }
+ else
+ {
+ // Get every single prop value with one ( remote) call.
+
+ for ( const Property& rProp : aProps )
+ {
+ try
+ {
+ Any aValue = rxSet->getPropertyValue( rProp.Name );
+
+ if ( aValue.hasValue() )
+ appendObject( rProp, aValue );
+ }
+ catch (const UnknownPropertyException&)
+ {
+ }
+ catch (const WrappedTargetException&)
+ {
+ }
+ }
+ }
+}
+
+
+bool PropertyValueSet::appendPropertySetValue(
+ const Reference< XPropertySet >& rxSet,
+ const Property& rProperty )
+{
+ if ( rxSet.is() )
+ {
+ try
+ {
+ Any aValue = rxSet->getPropertyValue( rProperty.Name );
+ if ( aValue.hasValue() )
+ {
+ appendObject( rProperty, aValue );
+ return true;
+ }
+ }
+ catch (const UnknownPropertyException&)
+ {
+ }
+ catch (const WrappedTargetException&)
+ {
+ }
+ }
+
+ // Error.
+ return false;
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/providerhelper.cxx b/ucbhelper/source/provider/providerhelper.cxx
new file mode 100644
index 0000000000..a15ba5457b
--- /dev/null
+++ b/ucbhelper/source/provider/providerhelper.cxx
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/beans/IllegalTypeException.hpp>
+#include <com/sun/star/beans/PropertyExistException.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/ucb/Store.hpp>
+#include <com/sun/star/ucb/XPropertySetRegistry.hpp>
+#include <com/sun/star/ucb/XPropertySetRegistryFactory.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <ucbhelper/contenthelper.hxx>
+#include <ucbhelper/providerhelper.hxx>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <cppuhelper/weakref.hxx>
+
+#include <unordered_map>
+#include <utility>
+
+using namespace com::sun::star;
+
+namespace ucbhelper_impl
+{
+
+typedef std::unordered_map
+<
+ OUString,
+ uno::WeakReference< ucb::XContent >
+>
+Contents;
+
+struct ContentProviderImplHelper_Impl
+{
+ uno::Reference< css::ucb::XPropertySetRegistry > m_xPropertySetRegistry;
+ Contents m_aContents;
+};
+
+} // namespace ucbhelper_impl
+
+namespace ucbhelper {
+
+ContentProviderImplHelper::ContentProviderImplHelper(
+ uno::Reference< uno::XComponentContext > xContext )
+: m_pImpl( new ucbhelper_impl::ContentProviderImplHelper_Impl ),
+ m_xContext(std::move( xContext ))
+{
+}
+
+// virtual
+ContentProviderImplHelper::~ContentProviderImplHelper()
+{
+}
+
+// virtual
+sal_Bool SAL_CALL ContentProviderImplHelper::supportsService(
+ const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+// virtual
+sal_Int32 SAL_CALL ContentProviderImplHelper::compareContentIds(
+ const uno::Reference< css::ucb::XContentIdentifier >& Id1,
+ const uno::Reference< css::ucb::XContentIdentifier >& Id2 )
+{
+ // Simply do a string compare.
+
+ OUString aURL1( Id1->getContentIdentifier() );
+ OUString aURL2( Id2->getContentIdentifier() );
+
+ return aURL1.compareTo( aURL2 );
+}
+
+void ContentProviderImplHelper::cleanupRegisteredContents()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ucbhelper_impl::Contents::iterator it
+ = m_pImpl->m_aContents.begin();
+ while( it != m_pImpl->m_aContents.end() )
+ {
+ uno::Reference< ucb::XContent > xContent( (*it).second );
+ if ( !xContent.is() )
+ {
+ ucbhelper_impl::Contents::iterator tmp = it;
+ ++it;
+ m_pImpl->m_aContents.erase( tmp );
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+void ContentProviderImplHelper::removeContent( ContentImplHelper* pContent )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ cleanupRegisteredContents();
+
+ const OUString aURL(
+ pContent->getIdentifier()->getContentIdentifier() );
+
+ ucbhelper_impl::Contents::iterator it = m_pImpl->m_aContents.find( aURL );
+
+ if ( it != m_pImpl->m_aContents.end() )
+ m_pImpl->m_aContents.erase( it );
+}
+
+rtl::Reference< ContentImplHelper >
+ContentProviderImplHelper::queryExistingContent(
+ const uno::Reference< css::ucb::XContentIdentifier >& Identifier )
+{
+ return queryExistingContent( Identifier->getContentIdentifier() );
+}
+
+rtl::Reference< ContentImplHelper >
+ContentProviderImplHelper::queryExistingContent( const OUString& rURL )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ cleanupRegisteredContents();
+
+ // Check, if a content with given id already exists...
+
+ ucbhelper_impl::Contents::const_iterator it
+ = m_pImpl->m_aContents.find( rURL );
+ if ( it != m_pImpl->m_aContents.end() )
+ {
+ uno::Reference< ucb::XContent > xContent( (*it).second );
+ if ( xContent.is() )
+ {
+ return rtl::Reference< ContentImplHelper >(
+ static_cast< ContentImplHelper * >( xContent.get() ) );
+ }
+ }
+ return rtl::Reference< ContentImplHelper >();
+}
+
+void ContentProviderImplHelper::queryExistingContents(
+ ContentRefList& rContents )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ cleanupRegisteredContents();
+
+ for ( const auto& rContent : m_pImpl->m_aContents )
+ {
+ uno::Reference< ucb::XContent > xContent( rContent.second );
+ if ( xContent.is() )
+ {
+ rContents.emplace_back(
+ static_cast< ContentImplHelper * >( xContent.get() ) );
+ }
+ }
+}
+
+void ContentProviderImplHelper::registerNewContent(
+ const uno::Reference< ucb::XContent > & xContent )
+{
+ if ( !xContent.is() )
+ return;
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ cleanupRegisteredContents();
+
+ const OUString aURL(
+ xContent->getIdentifier()->getContentIdentifier() );
+ ucbhelper_impl::Contents::const_iterator it
+ = m_pImpl->m_aContents.find( aURL );
+ if ( it == m_pImpl->m_aContents.end() )
+ m_pImpl->m_aContents[ aURL ] = xContent;
+}
+
+uno::Reference< css::ucb::XPropertySetRegistry >
+ContentProviderImplHelper::getAdditionalPropertySetRegistry()
+{
+ // Get propertyset registry.
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pImpl->m_xPropertySetRegistry.is() )
+ {
+ uno::Reference< css::ucb::XPropertySetRegistryFactory >
+ xRegFac = css::ucb::Store::create( m_xContext );
+
+ // Open/create a registry.
+ m_pImpl->m_xPropertySetRegistry
+ = xRegFac->createPropertySetRegistry( OUString() );
+
+ OSL_ENSURE( m_pImpl->m_xPropertySetRegistry.is(),
+ "ContentProviderImplHelper::getAdditionalPropertySet - "
+ "Error opening registry!" );
+ }
+
+ return m_pImpl->m_xPropertySetRegistry;
+}
+
+uno::Reference< css::ucb::XPersistentPropertySet >
+ContentProviderImplHelper::getAdditionalPropertySet(
+ const OUString& rKey, bool bCreate )
+{
+ // Get propertyset registry.
+ getAdditionalPropertySetRegistry();
+
+ if ( m_pImpl->m_xPropertySetRegistry.is() )
+ {
+ // Open/create persistent property set.
+ return m_pImpl->m_xPropertySetRegistry->openPropertySet(
+ rKey, bCreate );
+ }
+
+ return uno::Reference< css::ucb::XPersistentPropertySet >();
+}
+
+bool ContentProviderImplHelper::renameAdditionalPropertySet(
+ const OUString& rOldKey,
+ const OUString& rNewKey,
+ bool bRecursive )
+{
+ if ( rOldKey == rNewKey )
+ return true;
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( bRecursive )
+ {
+ // Get propertyset registry.
+ getAdditionalPropertySetRegistry();
+
+ if ( !m_pImpl->m_xPropertySetRegistry.is() )
+ return false;
+
+ uno::Reference< container::XNameAccess > xNameAccess(
+ m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
+ if ( !xNameAccess.is() )
+ return false;
+
+ const uno::Sequence< OUString > aKeys
+ = xNameAccess->getElementNames();
+ if ( aKeys.hasElements() )
+ {
+ OUString aOldKeyWithSlash = rOldKey;
+ OUString aOldKeyWithoutSlash;
+ if ( !aOldKeyWithSlash.endsWith("/") )
+ {
+ aOldKeyWithSlash += "/";
+ aOldKeyWithoutSlash = rOldKey;
+ }
+ else if ( !rOldKey.isEmpty() )
+ aOldKeyWithoutSlash
+ = rOldKey.copy( 0, rOldKey.getLength() - 1 );
+
+ for ( const OUString& rKey : aKeys )
+ {
+ if ( rKey.startsWith( aOldKeyWithSlash )
+ || rKey == aOldKeyWithoutSlash )
+ {
+ OUString aNewKey
+ = rKey.replaceAt(
+ 0, rOldKey.getLength(), rNewKey );
+ if ( !renameAdditionalPropertySet(
+ rKey, aNewKey, false ) )
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Get old property set, if exists.
+ uno::Reference< css::ucb::XPersistentPropertySet > xOldSet
+ = getAdditionalPropertySet( rOldKey, false );
+ if ( xOldSet.is() )
+ {
+ // Rename property set.
+ uno::Reference< container::XNamed > xNamed(
+ xOldSet, uno::UNO_QUERY );
+ if ( !xNamed.is() )
+ return false;
+
+ // ??? throws no exceptions and has no return value ???
+ xNamed->setName( rNewKey );
+ }
+ }
+ return true;
+}
+
+bool ContentProviderImplHelper::copyAdditionalPropertySet(
+ const OUString& rSourceKey,
+ const OUString& rTargetKey,
+ bool bRecursive )
+{
+ if ( rSourceKey == rTargetKey )
+ return true;
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( bRecursive )
+ {
+ // Get propertyset registry.
+ getAdditionalPropertySetRegistry();
+
+ if ( !m_pImpl->m_xPropertySetRegistry.is() )
+ return false;
+
+ uno::Reference< container::XNameAccess > xNameAccess(
+ m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
+ if ( !xNameAccess.is() )
+ return false;
+
+ const uno::Sequence< OUString > aKeys
+ = xNameAccess->getElementNames();
+ if ( aKeys.hasElements() )
+ {
+ OUString aSrcKeyWithSlash = rSourceKey;
+ OUString aSrcKeyWithoutSlash;
+ if ( !aSrcKeyWithSlash.endsWith("/") )
+ {
+ aSrcKeyWithSlash += "/";
+ aSrcKeyWithoutSlash = rSourceKey;
+ }
+ else if ( !rSourceKey.isEmpty() )
+ aSrcKeyWithoutSlash = rSourceKey.copy(
+ 0, rSourceKey.getLength() - 1 );
+
+ for ( const OUString& rKey : aKeys )
+ {
+ if ( rKey.startsWith(aSrcKeyWithSlash )
+ || rKey == aSrcKeyWithoutSlash )
+ {
+ OUString aNewKey
+ = rKey.replaceAt(
+ 0, rSourceKey.getLength(), rTargetKey );
+ if ( !copyAdditionalPropertySet(
+ rKey, aNewKey, false ) )
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Get old property set, if exists.
+ uno::Reference< css::ucb::XPersistentPropertySet >
+ xOldPropSet = getAdditionalPropertySet( rSourceKey, false );
+ if ( !xOldPropSet.is() )
+ return false;
+
+ uno::Reference< beans::XPropertySetInfo > xPropSetInfo
+ = xOldPropSet->getPropertySetInfo();
+ if ( !xPropSetInfo.is() )
+ return false;
+
+ uno::Reference< beans::XPropertyAccess > xOldPropAccess(
+ xOldPropSet, uno::UNO_QUERY );
+ if ( !xOldPropAccess.is() )
+ return false;
+
+ // Obtain all values from old set.
+ const uno::Sequence< beans::PropertyValue > aValues
+ = xOldPropAccess->getPropertyValues();
+
+ const uno::Sequence< beans::Property > aProps
+ = xPropSetInfo->getProperties();
+
+ if ( aValues.hasElements() )
+ {
+ // Fail, if property set with new key already exists.
+ uno::Reference< css::ucb::XPersistentPropertySet >
+ xNewPropSet
+ = getAdditionalPropertySet( rTargetKey, false );
+ if ( xNewPropSet.is() )
+ return false;
+
+ // Create new, empty set.
+ xNewPropSet = getAdditionalPropertySet( rTargetKey, true );
+ if ( !xNewPropSet.is() )
+ return false;
+
+ uno::Reference< beans::XPropertyContainer > xNewPropContainer(
+ xNewPropSet, uno::UNO_QUERY );
+ if ( !xNewPropContainer.is() )
+ return false;
+
+ for ( const beans::PropertyValue& rValue : aValues )
+ {
+ sal_Int16 nAttribs = 0;
+ auto pProp = std::find_if(aProps.begin(), aProps.end(),
+ [&rValue](const beans::Property& rProp) { return rProp.Name == rValue.Name; });
+ if (pProp != aProps.end())
+ nAttribs = pProp->Attributes;
+
+ try
+ {
+ xNewPropContainer->addProperty(
+ rValue.Name, nAttribs, rValue.Value );
+ }
+ catch ( beans::PropertyExistException & )
+ {
+ }
+ catch ( beans::IllegalTypeException & )
+ {
+ }
+ catch ( lang::IllegalArgumentException & )
+ {
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool ContentProviderImplHelper::removeAdditionalPropertySet(
+ const OUString& rKey, bool bRecursive )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( bRecursive )
+ {
+ // Get propertyset registry.
+ getAdditionalPropertySetRegistry();
+
+ if ( !m_pImpl->m_xPropertySetRegistry.is() )
+ return false;
+
+ uno::Reference< container::XNameAccess > xNameAccess(
+ m_pImpl->m_xPropertySetRegistry, uno::UNO_QUERY );
+ if ( !xNameAccess.is() )
+ return false;
+
+ const uno::Sequence< OUString > aKeys
+ = xNameAccess->getElementNames();
+ if ( aKeys.hasElements() )
+ {
+ OUString aKeyWithSlash = rKey;
+ OUString aKeyWithoutSlash;
+ if ( !aKeyWithSlash.endsWith("/") )
+ {
+ aKeyWithSlash += "/";
+ aKeyWithoutSlash = rKey;
+ }
+ else if ( !rKey.isEmpty() )
+ aKeyWithoutSlash
+ = rKey.copy( 0, rKey.getLength() - 1 );
+
+ for ( const OUString& rCurrKey : aKeys )
+ {
+ if ( rCurrKey.startsWith(aKeyWithSlash )
+ || rCurrKey == aKeyWithoutSlash )
+ {
+ if ( !removeAdditionalPropertySet(
+ rCurrKey, false ) )
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Get propertyset registry.
+ getAdditionalPropertySetRegistry();
+
+ if ( !m_pImpl->m_xPropertySetRegistry.is() )
+ return false;
+
+ m_pImpl->m_xPropertySetRegistry->removePropertySet( rKey );
+ }
+ return true;
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/registerucb.cxx b/ucbhelper/source/provider/registerucb.cxx
new file mode 100644
index 0000000000..baf0e5b3f6
--- /dev/null
+++ b/ucbhelper/source/provider/registerucb.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ucbhelper/registerucb.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/ucb/DuplicateProviderException.hpp>
+#include <com/sun/star/ucb/XContentProviderManager.hpp>
+#include <com/sun/star/ucb/XParameterizedContentProvider.hpp>
+#include <com/sun/star/ucb/ContentProviderProxyFactory.hpp>
+#include <com/sun/star/ucb/XContentProviderFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include <osl/diagnose.h>
+
+using namespace com::sun::star;
+
+namespace ucbhelper {
+
+bool
+registerAtUcb(
+ uno::Reference< ucb::XContentProviderManager > const & rManager,
+ uno::Reference< uno::XComponentContext > const & rxContext,
+ OUString const & rName,
+ OUString const & rArguments,
+ OUString const & rTemplate)
+{
+ OSL_ENSURE(rxContext.is(),
+ "ucb::registerAtUcb(): No service factory");
+
+ bool bNoProxy = rArguments.startsWith("{noproxy}");
+ OUString
+ aProviderArguments(bNoProxy ?
+ rArguments.
+ copy(RTL_CONSTASCII_LENGTH("{noproxy}")) :
+ rArguments);
+
+ uno::Reference< ucb::XContentProvider > xProvider;
+
+ if (!rName.isEmpty())
+ {
+ // First, try to instantiate proxy for provider:
+ if (!bNoProxy)
+ {
+ uno::Reference< ucb::XContentProviderFactory > xProxyFactory;
+ try
+ {
+ xProxyFactory = ucb::ContentProviderProxyFactory::create( rxContext );
+ }
+ catch (uno::Exception const &) {}
+ OSL_ENSURE(xProxyFactory.is(), "No ContentProviderProxyFactory");
+ if (xProxyFactory.is())
+ xProvider = xProxyFactory->createContentProvider(rName);
+ }
+
+ // Then, try to instantiate provider directly:
+ if (!xProvider.is())
+ try
+ {
+ xProvider.set(
+ rxContext->getServiceManager()->createInstanceWithContext(rName, rxContext),
+ uno::UNO_QUERY);
+ }
+ catch (uno::RuntimeException const &) { throw; }
+ catch (uno::Exception const &) {}
+ }
+
+ uno::Reference< ucb::XParameterizedContentProvider >
+ xParameterized(xProvider, uno::UNO_QUERY);
+ if (xParameterized.is())
+ {
+ uno::Reference< ucb::XContentProvider > xInstance;
+ try
+ {
+ xInstance = xParameterized->registerInstance(rTemplate,
+ aProviderArguments,
+ true);
+ //@@@ if this call replaces an old instance, the commit-or-
+ // rollback code below will not work
+ }
+ catch (lang::IllegalArgumentException const &) {}
+
+ if (xInstance.is())
+ xProvider = xInstance;
+ }
+
+ bool bSuccess = false;
+ if (rManager.is() && (rName.isEmpty() || xProvider.is()))
+ {
+ try
+ {
+ rManager->registerContentProvider(xProvider, rTemplate, true);
+ bSuccess = true;
+ }
+ catch (ucb::DuplicateProviderException const &)
+ {
+ if (xParameterized.is())
+ try
+ {
+ xParameterized->deregisterInstance(rTemplate,
+ aProviderArguments);
+ }
+ catch (lang::IllegalArgumentException const &) {}
+ }
+ catch (...)
+ {
+ if (xParameterized.is())
+ try
+ {
+ xParameterized->deregisterInstance(rTemplate,
+ aProviderArguments);
+ }
+ catch (lang::IllegalArgumentException const &) {}
+ catch (uno::RuntimeException const &) {}
+ throw;
+ }
+ }
+ return bSuccess;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/resultset.cxx b/ucbhelper/source/provider/resultset.cxx
new file mode 100644
index 0000000000..61682f4fd5
--- /dev/null
+++ b/ucbhelper/source/provider/resultset.cxx
@@ -0,0 +1,1486 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <mutex>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/multiinterfacecontainer4.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/sdbc/SQLException.hpp>
+#include <ucbhelper/resultset.hxx>
+#include <ucbhelper/resultsetmetadata.hxx>
+#include <ucbhelper/macros.hxx>
+#include <utility>
+#include <osl/diagnose.h>
+
+using namespace com::sun::star;
+
+
+namespace ucbhelper_impl
+{
+
+namespace {
+
+struct PropertyInfo
+{
+ const char* pName;
+ sal_Int32 nHandle;
+ sal_Int16 nAttributes;
+ const uno::Type& (*pGetCppuType)();
+};
+
+}
+
+static const uno::Type& sal_Int32_getCppuType()
+{
+ return cppu::UnoType<sal_Int32>::get();
+}
+
+static const uno::Type& sal_Bool_getCppuType()
+{
+ return cppu::UnoType<bool>::get();
+}
+
+const PropertyInfo aPropertyTable[] =
+{
+ { "IsRowCountFinal",
+ 1000,
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
+ &sal_Bool_getCppuType
+ },
+ { "RowCount",
+ 1001,
+ beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY,
+ &sal_Int32_getCppuType
+ },
+ { nullptr,
+ 0,
+ 0,
+ nullptr
+ }
+};
+
+#define RESULTSET_PROPERTY_COUNT 2
+
+
+
+namespace {
+
+class PropertySetInfo :
+ public cppu::OWeakObject,
+ public lang::XTypeProvider,
+ public beans::XPropertySetInfo
+{
+ uno::Sequence< beans::Property > m_aProps;
+
+private:
+ bool queryProperty(
+ std::u16string_view aName, beans::Property& rProp ) const;
+
+public:
+ PropertySetInfo(
+ const PropertyInfo* pProps,
+ sal_Int32 nProps );
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire()
+ noexcept override;
+ virtual void SAL_CALL release()
+ noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+
+ // XPropertySetInfo
+ virtual uno::Sequence< beans::Property > SAL_CALL getProperties() override;
+ virtual beans::Property SAL_CALL getPropertyByName(
+ const OUString& aName ) override;
+ virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override;
+};
+
+}
+
+typedef comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, css::beans::XPropertyChangeListener>
+ PropertyChangeListeners;
+
+} // namespace ucbhelper_impl
+
+using namespace ucbhelper_impl;
+
+namespace ucbhelper
+{
+
+
+// struct ResultSet_Impl.
+
+
+struct ResultSet_Impl
+{
+ uno::Reference< uno::XComponentContext > m_xContext;
+ uno::Reference< css::ucb::XCommandEnvironment > m_xEnv;
+ uno::Reference< beans::XPropertySetInfo > m_xPropSetInfo;
+ uno::Reference< sdbc::XResultSetMetaData > m_xMetaData;
+ uno::Sequence< beans::Property > m_aProperties;
+ rtl::Reference< ResultSetDataSupplier > m_xDataSupplier;
+ std::mutex m_aMutex;
+ comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_aDisposeEventListeners;
+ std::unique_ptr<PropertyChangeListeners> m_pPropertyChangeListeners;
+ sal_Int32 m_nPos;
+ bool m_bWasNull;
+ bool m_bAfterLast;
+
+ inline ResultSet_Impl(
+ uno::Reference< uno::XComponentContext > xContext,
+ const uno::Sequence< beans::Property >& rProperties,
+ rtl::Reference< ResultSetDataSupplier > xDataSupplier,
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv );
+};
+
+inline ResultSet_Impl::ResultSet_Impl(
+ uno::Reference< uno::XComponentContext > xContext,
+ const uno::Sequence< beans::Property >& rProperties,
+ rtl::Reference< ResultSetDataSupplier > xDataSupplier,
+ uno::Reference< css::ucb::XCommandEnvironment > xEnv )
+: m_xContext(std::move( xContext )),
+ m_xEnv(std::move( xEnv )),
+ m_aProperties( rProperties ),
+ m_xDataSupplier(std::move( xDataSupplier )),
+ m_nPos( 0 ), // Position is one-based. Zero means: before first element.
+ m_bWasNull( false ),
+ m_bAfterLast( false )
+{
+}
+
+
+// ResultSet Implementation.
+
+
+ResultSet::ResultSet(
+ const uno::Reference< uno::XComponentContext >& rxContext,
+ const uno::Sequence< beans::Property >& rProperties,
+ const rtl::Reference< ResultSetDataSupplier >& rDataSupplier )
+: m_pImpl( new ResultSet_Impl(
+ rxContext,
+ rProperties,
+ rDataSupplier,
+ uno::Reference< css::ucb::XCommandEnvironment >() ) )
+{
+ rDataSupplier->m_pResultSet = this;
+}
+
+
+ResultSet::ResultSet(
+ const uno::Reference< uno::XComponentContext >& rxContext,
+ const uno::Sequence< beans::Property >& rProperties,
+ const rtl::Reference< ResultSetDataSupplier >& rDataSupplier,
+ const uno::Reference< css::ucb::XCommandEnvironment >& rxEnv )
+: m_pImpl( new ResultSet_Impl( rxContext, rProperties, rDataSupplier, rxEnv ) )
+{
+ rDataSupplier->m_pResultSet = this;
+}
+
+
+// virtual
+ResultSet::~ResultSet()
+{
+}
+
+
+// XServiceInfo methods.
+
+OUString SAL_CALL ResultSet::getImplementationName()
+{
+ return "ResultSet";
+}
+
+sal_Bool SAL_CALL ResultSet::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+css::uno::Sequence< OUString > SAL_CALL ResultSet::getSupportedServiceNames()
+{
+ return { RESULTSET_SERVICE_NAME };
+}
+
+
+// XComponent methods.
+
+
+// virtual
+void SAL_CALL ResultSet::dispose()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_aDisposeEventListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< lang::XComponent * >( this );
+ m_pImpl->m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt );
+ }
+
+ if ( m_pImpl->m_pPropertyChangeListeners )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< beans::XPropertySet * >( this );
+ m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aGuard, aEvt );
+ }
+
+ m_pImpl->m_xDataSupplier->close();
+}
+
+
+// virtual
+void SAL_CALL ResultSet::addEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ m_pImpl->m_aDisposeEventListeners.addInterface( aGuard, Listener );
+}
+
+
+// virtual
+void SAL_CALL ResultSet::removeEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ m_pImpl->m_aDisposeEventListeners.removeInterface( aGuard, Listener );
+}
+
+
+// XResultSetMetaDataSupplier methods.
+
+
+// virtual
+uno::Reference< sdbc::XResultSetMetaData > SAL_CALL ResultSet::getMetaData()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !m_pImpl->m_xMetaData.is() )
+ m_pImpl->m_xMetaData = new ResultSetMetaData( m_pImpl->m_xContext,
+ m_pImpl->m_aProperties );
+
+ return m_pImpl->m_xMetaData;
+}
+
+
+// XResultSet methods.
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::next()
+{
+ // Note: Cursor is initially positioned before the first row.
+ // First call to 'next()' moves it to first row.
+
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ // getResult works zero-based!
+ if ( !m_pImpl->m_xDataSupplier->getResult( m_pImpl->m_nPos ) )
+ {
+ m_pImpl->m_bAfterLast = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ m_pImpl->m_nPos++;
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::isBeforeFirst()
+{
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ // getResult works zero-based!
+ if ( !m_pImpl->m_xDataSupplier->getResult( 0 ) )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return ( m_pImpl->m_nPos == 0 );
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::isAfterLast()
+{
+ m_pImpl->m_xDataSupplier->validate();
+ return m_pImpl->m_bAfterLast;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::isFirst()
+{
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return ( m_pImpl->m_nPos == 1 );
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::isLast()
+{
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+ if ( !nCount )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return ( m_pImpl->m_nPos == nCount );
+}
+
+
+// virtual
+void SAL_CALL ResultSet::beforeFirst()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = 0;
+ m_pImpl->m_xDataSupplier->validate();
+}
+
+
+// virtual
+void SAL_CALL ResultSet::afterLast()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = true;
+ m_pImpl->m_xDataSupplier->validate();
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::first()
+{
+ // getResult works zero-based!
+ if ( m_pImpl->m_xDataSupplier->getResult( 0 ) )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = 1;
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::last()
+{
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+ if ( nCount )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = nCount;
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSet::getRow()
+{
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return m_pImpl->m_nPos;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::absolute( sal_Int32 row )
+{
+/*
+ If the row number is positive, the cursor moves to the given row number
+ with respect to the beginning of the result set. The first row is row 1,
+ the second is row 2, and so on.
+
+ If the given row number is negative, the cursor moves to an absolute row
+ position with respect to the end of the result set. For example, calling
+ absolute( -1 ) positions the cursor on the last row, absolute( -2 )
+ indicates the next-to-last row, and so on.
+
+ An attempt to position the cursor beyond the first/last row in the result
+ set leaves the cursor before/after the first/last row, respectively.
+
+ Calling absolute( 1 ) is the same as calling first().
+
+ Calling absolute( -1 ) is the same as calling last().
+*/
+ if ( row < 0 )
+ {
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+
+ if ( ( row * -1 ) > nCount )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = 0;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+ else // |row| <= nCount
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = ( nCount + row + 1 );
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+ }
+ else if ( row == 0 )
+ {
+ // @throws SQLException
+ // ... if row is 0 ...
+ throw sdbc::SQLException();
+ }
+ else // row > 0
+ {
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+
+ if ( row <= nCount )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = row;
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+ else // row > nCount
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+ }
+
+ // unreachable...
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::relative( sal_Int32 rows )
+{
+/*
+ Attempting to move beyond the first/last row in the result set
+ positions the cursor before/after the first/last row.
+
+ Calling relative( 0 ) is valid, but does not change the cursor position.
+
+ Calling relative( 1 ) is different from calling next() because it makes
+ sense to call next() when there is no current row, for example, when
+ the cursor is positioned before the first row or after the last row of
+ the result set.
+*/
+ if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
+ {
+ // "No current row".
+ throw sdbc::SQLException();
+ }
+
+ if ( rows < 0 )
+ {
+ if ( ( m_pImpl->m_nPos + rows ) > 0 )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+ else
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = 0;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+ }
+ else if ( rows == 0 )
+ {
+ // nop.
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+ else // rows > 0
+ {
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+ if ( ( m_pImpl->m_nPos + rows ) <= nCount )
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = false;
+ m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows );
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+ else
+ {
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ m_pImpl->m_bAfterLast = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+ }
+ }
+
+ // unreachable...
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::previous()
+{
+/*
+ previous() is not the same as relative( -1 ) because it makes sense
+ to call previous() when there is no current row.
+*/
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_bAfterLast )
+ {
+ m_pImpl->m_bAfterLast = false;
+ sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount();
+ m_pImpl->m_nPos = nCount;
+ }
+ else if ( m_pImpl->m_nPos )
+ m_pImpl->m_nPos--;
+
+ if ( m_pImpl->m_nPos )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return true;
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+void SAL_CALL ResultSet::refreshRow()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+ if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) )
+ return;
+
+ m_pImpl->m_xDataSupplier->releasePropertyValues( m_pImpl->m_nPos );
+ m_pImpl->m_xDataSupplier->validate();
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::rowUpdated()
+{
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::rowInserted()
+{
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::rowDeleted()
+{
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+uno::Reference< uno::XInterface > SAL_CALL ResultSet::getStatement()
+{
+/*
+ returns the Statement that produced this ResultSet object. If the
+ result set was generated some other way, ... this method returns null.
+*/
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< uno::XInterface >();
+}
+
+
+// XRow methods.
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::wasNull()
+{
+ // This method can not be implemented correctly!!! Imagine different
+ // threads doing a getXYZ - wasNull calling sequence on the same
+ // implementation object...
+
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->wasNull();
+ }
+ }
+
+ m_pImpl->m_xDataSupplier->validate();
+ return m_pImpl->m_bWasNull;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSet::getString( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getString( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return OUString();
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSet::getBoolean( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getBoolean( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return false;
+}
+
+
+// virtual
+sal_Int8 SAL_CALL ResultSet::getByte( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getByte( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+sal_Int16 SAL_CALL ResultSet::getShort( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getShort( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSet::getInt( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getInt( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+sal_Int64 SAL_CALL ResultSet::getLong( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getLong( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+float SAL_CALL ResultSet::getFloat( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getFloat( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+double SAL_CALL ResultSet::getDouble( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getDouble( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return 0;
+}
+
+
+// virtual
+uno::Sequence< sal_Int8 > SAL_CALL
+ResultSet::getBytes( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getBytes( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Sequence< sal_Int8 >();
+}
+
+
+// virtual
+util::Date SAL_CALL ResultSet::getDate( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getDate( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return util::Date();
+}
+
+
+// virtual
+util::Time SAL_CALL ResultSet::getTime( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getTime( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return util::Time();
+}
+
+
+// virtual
+util::DateTime SAL_CALL
+ResultSet::getTimestamp( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getTimestamp( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return util::DateTime();
+}
+
+
+// virtual
+uno::Reference< io::XInputStream > SAL_CALL
+ResultSet::getBinaryStream( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getBinaryStream( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< io::XInputStream >();
+}
+
+
+// virtual
+uno::Reference< io::XInputStream > SAL_CALL
+ResultSet::getCharacterStream( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getCharacterStream( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< io::XInputStream >();
+}
+
+
+// virtual
+uno::Any SAL_CALL ResultSet::getObject(
+ sal_Int32 columnIndex,
+ const uno::Reference< container::XNameAccess >& typeMap )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getObject( columnIndex, typeMap );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Any();
+}
+
+
+// virtual
+uno::Reference< sdbc::XRef > SAL_CALL
+ResultSet::getRef( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getRef( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< sdbc::XRef >();
+}
+
+
+// virtual
+uno::Reference< sdbc::XBlob > SAL_CALL
+ResultSet::getBlob( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getBlob( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< sdbc::XBlob >();
+}
+
+
+// virtual
+uno::Reference< sdbc::XClob > SAL_CALL
+ResultSet::getClob( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getClob( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< sdbc::XClob >();
+}
+
+
+// virtual
+uno::Reference< sdbc::XArray > SAL_CALL
+ResultSet::getArray( sal_Int32 columnIndex )
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ {
+ uno::Reference< sdbc::XRow > xValues
+ = m_pImpl->m_xDataSupplier->queryPropertyValues(
+ m_pImpl->m_nPos - 1 );
+ if ( xValues.is() )
+ {
+ m_pImpl->m_bWasNull = false;
+ m_pImpl->m_xDataSupplier->validate();
+ return xValues->getArray( columnIndex );
+ }
+ }
+
+ m_pImpl->m_bWasNull = true;
+ m_pImpl->m_xDataSupplier->validate();
+ return uno::Reference< sdbc::XArray >();
+}
+
+
+// XCloseable methods.
+
+
+// virtual
+void SAL_CALL ResultSet::close()
+{
+ m_pImpl->m_xDataSupplier->close();
+ m_pImpl->m_xDataSupplier->validate();
+}
+
+
+// XContentAccess methods.
+
+
+// virtual
+OUString SAL_CALL ResultSet::queryContentIdentifierString()
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ return m_pImpl->m_xDataSupplier->queryContentIdentifierString(
+ m_pImpl->m_nPos - 1 );
+
+ return OUString();
+}
+
+
+// virtual
+uno::Reference< css::ucb::XContentIdentifier > SAL_CALL
+ResultSet::queryContentIdentifier()
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ return m_pImpl->m_xDataSupplier->queryContentIdentifier(
+ m_pImpl->m_nPos - 1 );
+
+ return uno::Reference< css::ucb::XContentIdentifier >();
+}
+
+
+// virtual
+uno::Reference< css::ucb::XContent > SAL_CALL
+ResultSet::queryContent()
+{
+ if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast )
+ return m_pImpl->m_xDataSupplier->queryContent( m_pImpl->m_nPos - 1 );
+
+ return uno::Reference< css::ucb::XContent >();
+}
+
+
+// XPropertySet methods.
+
+
+// virtual
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+ResultSet::getPropertySetInfo()
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !m_pImpl->m_xPropSetInfo.is() )
+ m_pImpl->m_xPropSetInfo
+ = new PropertySetInfo( aPropertyTable,
+ RESULTSET_PROPERTY_COUNT );
+ return m_pImpl->m_xPropSetInfo;
+}
+
+
+// virtual
+void SAL_CALL ResultSet::setPropertyValue( const OUString& aPropertyName,
+ const uno::Any& )
+{
+ if ( aPropertyName == "RowCount" )
+ {
+ // property is read-only.
+ throw lang::IllegalArgumentException();
+ }
+ else if ( aPropertyName == "IsRowCountFinal" )
+ {
+ // property is read-only.
+ throw lang::IllegalArgumentException();
+ }
+ else
+ {
+ throw beans::UnknownPropertyException(aPropertyName);
+ }
+}
+
+
+// virtual
+uno::Any SAL_CALL ResultSet::getPropertyValue(
+ const OUString& PropertyName )
+{
+ uno::Any aValue;
+
+ if ( PropertyName == "RowCount" )
+ {
+ aValue <<= m_pImpl->m_xDataSupplier->currentCount();
+ }
+ else if ( PropertyName == "IsRowCountFinal" )
+ {
+ aValue <<= m_pImpl->m_xDataSupplier->isCountFinal();
+ }
+ else
+ {
+ throw beans::UnknownPropertyException(PropertyName);
+ }
+
+ return aValue;
+}
+
+
+// virtual
+void SAL_CALL ResultSet::addPropertyChangeListener(
+ const OUString& aPropertyName,
+ const uno::Reference< beans::XPropertyChangeListener >& xListener )
+{
+ // Note: An empty property name means a listener for "all" properties.
+
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !aPropertyName.isEmpty() &&
+ aPropertyName != "RowCount" &&
+ aPropertyName != "IsRowCountFinal" )
+ throw beans::UnknownPropertyException(aPropertyName);
+
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ m_pImpl->m_pPropertyChangeListeners.reset(
+ new PropertyChangeListeners());
+
+ m_pImpl->m_pPropertyChangeListeners->addInterface(aGuard,
+ aPropertyName, xListener );
+}
+
+
+// virtual
+void SAL_CALL ResultSet::removePropertyChangeListener(
+ const OUString& aPropertyName,
+ const uno::Reference< beans::XPropertyChangeListener >& xListener )
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !aPropertyName.isEmpty() &&
+ aPropertyName != "RowCount" &&
+ aPropertyName != "IsRowCountFinal" )
+ throw beans::UnknownPropertyException(aPropertyName);
+
+ if ( m_pImpl->m_pPropertyChangeListeners )
+ m_pImpl->m_pPropertyChangeListeners->removeInterface(aGuard,
+ aPropertyName, xListener );
+
+}
+
+
+// virtual
+void SAL_CALL ResultSet::addVetoableChangeListener(
+ const OUString&,
+ const uno::Reference< beans::XVetoableChangeListener >& )
+{
+ // No constrained props, at the moment.
+}
+
+
+// virtual
+void SAL_CALL ResultSet::removeVetoableChangeListener(
+ const OUString&,
+ const uno::Reference< beans::XVetoableChangeListener >& )
+{
+ // No constrained props, at the moment.
+}
+
+
+// Non-interface methods.
+
+
+void ResultSet::propertyChanged( const beans::PropertyChangeEvent& rEvt ) const
+{
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ return;
+
+ // Notify listeners interested especially in the changed property.
+ comphelper::OInterfaceContainerHelper4<beans::XPropertyChangeListener>* pPropsContainer
+ = m_pImpl->m_pPropertyChangeListeners->getContainer(aGuard,
+ rEvt.PropertyName );
+ if ( pPropsContainer )
+ {
+ pPropsContainer->notifyEach(aGuard, &beans::XPropertyChangeListener::propertyChange, rEvt);
+ }
+
+ // Notify listeners interested in all properties.
+ pPropsContainer
+ = m_pImpl->m_pPropertyChangeListeners->getContainer( aGuard, OUString() );
+ if ( pPropsContainer )
+ {
+ pPropsContainer->notifyEach( aGuard, &beans::XPropertyChangeListener::propertyChange, rEvt);
+ }
+}
+
+
+void ResultSet::rowCountChanged( sal_uInt32 nOld, sal_uInt32 nNew )
+{
+ OSL_ENSURE( nOld < nNew, "ResultSet::rowCountChanged - nOld >= nNew!" );
+
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ return;
+
+ propertyChanged(
+ beans::PropertyChangeEvent(
+ getXWeak(),
+ "RowCount",
+ false,
+ 1001,
+ uno::Any( nOld ), // old value
+ uno::Any( nNew ) ) ); // new value
+}
+
+
+void ResultSet::rowCountFinal()
+{
+ if ( !m_pImpl->m_pPropertyChangeListeners )
+ return;
+
+ propertyChanged(
+ beans::PropertyChangeEvent(
+ getXWeak(),
+ "IsRowCountFinal",
+ false,
+ 1000,
+ uno:: Any( false ), // old value
+ uno::Any( true ) ) ); // new value
+}
+
+
+const uno::Sequence< beans::Property >& ResultSet::getProperties() const
+{
+ return m_pImpl->m_aProperties;
+}
+
+
+const uno::Reference< css::ucb::XCommandEnvironment >&
+ResultSet::getEnvironment() const
+{
+ return m_pImpl->m_xEnv;
+}
+
+} // namespace ucbhelper
+
+namespace ucbhelper_impl {
+
+
+// PropertySetInfo Implementation.
+
+
+PropertySetInfo::PropertySetInfo(
+ const PropertyInfo* pProps,
+ sal_Int32 nProps )
+ : m_aProps( nProps )
+{
+
+ if ( !nProps )
+ return;
+
+ const PropertyInfo* pEntry = pProps;
+ beans::Property* pProperties = m_aProps.getArray();
+
+ for ( sal_Int32 n = 0; n < nProps; ++n )
+ {
+ beans::Property& rProp = pProperties[ n ];
+
+ rProp.Name = OUString::createFromAscii( pEntry->pName );
+ rProp.Handle = pEntry->nHandle;
+ rProp.Type = pEntry->pGetCppuType();
+ rProp.Attributes = pEntry->nAttributes;
+
+ pEntry++;
+ }
+}
+
+
+
+// XInterface methods.
+void SAL_CALL PropertySetInfo::acquire()
+ noexcept
+{
+ OWeakObject::acquire();
+}
+
+void SAL_CALL PropertySetInfo::release()
+ noexcept
+{
+ OWeakObject::release();
+}
+
+css::uno::Any SAL_CALL PropertySetInfo::queryInterface(
+ const css::uno::Type & rType )
+{
+ css::uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider* >(this),
+ static_cast< beans::XPropertySetInfo* >(this)
+ );
+ return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
+}
+
+// XTypeProvider methods.
+
+
+XTYPEPROVIDER_IMPL_2( PropertySetInfo,
+ lang::XTypeProvider,
+ beans::XPropertySetInfo );
+
+
+// XPropertySetInfo methods.
+
+
+// virtual
+uno::Sequence< beans::Property > SAL_CALL PropertySetInfo::getProperties()
+{
+ return m_aProps;
+}
+
+
+// virtual
+beans::Property SAL_CALL PropertySetInfo::getPropertyByName(
+ const OUString& aName )
+{
+ beans::Property aProp;
+ if ( queryProperty( aName, aProp ) )
+ return aProp;
+
+ throw beans::UnknownPropertyException(aName);
+}
+
+
+// virtual
+sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName(
+ const OUString& Name )
+{
+ beans::Property aProp;
+ return queryProperty( Name, aProp );
+}
+
+
+bool PropertySetInfo::queryProperty(
+ std::u16string_view aName, beans::Property& rProp ) const
+{
+ sal_Int32 nCount = m_aProps.getLength();
+ const beans::Property* pProps = m_aProps.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::Property& rCurr = pProps[ n ];
+ if ( rCurr.Name == aName )
+ {
+ rProp = rCurr;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace ucbhelper_impl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/resultsethelper.cxx b/ucbhelper/source/provider/resultsethelper.cxx
new file mode 100644
index 0000000000..788e6811a1
--- /dev/null
+++ b/ucbhelper/source/provider/resultsethelper.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+/* TODO
+ - This implementation is far away from completion. It has no interface
+ for changes notifications etc.
+ */
+
+#include <com/sun/star/ucb/ListActionType.hpp>
+#include <com/sun/star/ucb/ListenerAlreadySetException.hpp>
+#include <com/sun/star/ucb/ServiceNotFoundException.hpp>
+#include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp>
+#include <com/sun/star/ucb/CachedDynamicResultSetStubFactory.hpp>
+#include <com/sun/star/ucb/XSourceInitialization.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <ucbhelper/resultsethelper.hxx>
+#include <utility>
+
+#include <osl/diagnose.h>
+
+using namespace com::sun::star;
+
+
+// ResultSetImplHelper Implementation.
+
+
+namespace ucbhelper {
+
+
+ResultSetImplHelper::ResultSetImplHelper(
+ uno::Reference< uno::XComponentContext > xContext,
+ css::ucb::OpenCommandArgument2 aCommand )
+: m_bStatic( false ),
+ m_bInitDone( false ),
+ m_aCommand(std::move( aCommand )),
+ m_xContext(std::move( xContext ))
+{
+}
+
+
+// virtual
+ResultSetImplHelper::~ResultSetImplHelper()
+{
+}
+
+
+// XServiceInfo methods.
+
+OUString SAL_CALL ResultSetImplHelper::getImplementationName()
+{
+ return "ResultSetImplHelper";
+}
+
+sal_Bool SAL_CALL ResultSetImplHelper::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+css::uno::Sequence< OUString > SAL_CALL ResultSetImplHelper::getSupportedServiceNames()
+{
+ return { DYNAMICRESULTSET_SERVICE_NAME };
+}
+
+// XComponent methods.
+
+
+// virtual
+void SAL_CALL ResultSetImplHelper::dispose()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_aDisposeEventListeners.getLength(aGuard) )
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< lang::XComponent * >( this );
+ m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt );
+ }
+}
+
+
+// virtual
+void SAL_CALL ResultSetImplHelper::addEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aDisposeEventListeners.addInterface( aGuard, Listener );
+}
+
+
+// virtual
+void SAL_CALL ResultSetImplHelper::removeEventListener(
+ const uno::Reference< lang::XEventListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ m_aDisposeEventListeners.removeInterface( aGuard, Listener );
+}
+
+
+// XDynamicResultSet methods.
+
+
+// virtual
+uno::Reference< sdbc::XResultSet > SAL_CALL
+ResultSetImplHelper::getStaticResultSet()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_xListener.is() )
+ throw css::ucb::ListenerAlreadySetException();
+
+ init( true );
+ return m_xResultSet1;
+}
+
+
+// virtual
+void SAL_CALL ResultSetImplHelper::setListener(
+ const uno::Reference< css::ucb::XDynamicResultSetListener >& Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_bStatic || m_xListener.is() )
+ throw css::ucb::ListenerAlreadySetException();
+
+ m_xListener = Listener;
+
+
+ // Create "welcome event" and send it to listener.
+
+
+ // Note: We only have the implementation for a static result set at the
+ // moment (src590). The dynamic result sets passed to the listener
+ // are a fake. This implementation will never call "notify" at the
+ // listener to propagate any changes!!!
+
+ init( false );
+
+ uno::Any aInfo;
+ aInfo <<= css::ucb::WelcomeDynamicResultSetStruct(
+ m_xResultSet1 /* "old" */,
+ m_xResultSet2 /* "new" */ );
+
+ uno::Sequence< css::ucb::ListAction > aActions {
+ css::ucb::ListAction(
+ 0, // Position; not used
+ 0, // Count; not used
+ css::ucb::ListActionType::WELCOME,
+ aInfo ) };
+ aGuard.unlock();
+
+ Listener->notify(
+ css::ucb::ListEvent(
+ getXWeak(), aActions ) );
+}
+
+
+// virtual
+sal_Int16 SAL_CALL ResultSetImplHelper::getCapabilities()
+{
+ // ! css::ucb::ContentResultSetCapability::SORTED
+ return 0;
+}
+
+
+// virtual
+void SAL_CALL ResultSetImplHelper::connectToCache(
+ const uno::Reference< css::ucb::XDynamicResultSet > & xCache )
+{
+ if ( m_xListener.is() )
+ throw css::ucb::ListenerAlreadySetException();
+
+ if ( m_bStatic )
+ throw css::ucb::ListenerAlreadySetException();
+
+ uno::Reference< css::ucb::XSourceInitialization > xTarget( xCache, uno::UNO_QUERY );
+ if ( xTarget.is() )
+ {
+ uno::Reference< css::ucb::XCachedDynamicResultSetStubFactory > xStubFactory;
+ try
+ {
+ xStubFactory
+ = css::ucb::CachedDynamicResultSetStubFactory::create(
+ m_xContext );
+ }
+ catch ( uno::Exception const & )
+ {
+ }
+
+ if ( xStubFactory.is() )
+ {
+ xStubFactory->connectToCache(
+ this, xCache, m_aCommand.SortingInfo, nullptr );
+ return;
+ }
+ }
+ throw css::ucb::ServiceNotFoundException();
+}
+
+
+// Non-interface methods.
+
+
+void ResultSetImplHelper::init( bool bStatic )
+{
+ if ( m_bInitDone )
+ return;
+
+ if ( bStatic )
+ {
+ // virtual... derived class fills m_xResultSet1
+ initStatic();
+
+ OSL_ENSURE( m_xResultSet1.is(),
+ "ResultSetImplHelper::init - No 1st result set!" );
+ m_bStatic = true;
+ }
+ else
+ {
+ // virtual... derived class fills m_xResultSet1 and m_xResultSet2
+ initDynamic();
+
+ OSL_ENSURE( m_xResultSet1.is(),
+ "ResultSetImplHelper::init - No 1st result set!" );
+ OSL_ENSURE( m_xResultSet2.is(),
+ "ResultSetImplHelper::init - No 2nd result set!" );
+ m_bStatic = false;
+ }
+ m_bInitDone = true;
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/resultsetmetadata.cxx b/ucbhelper/source/provider/resultsetmetadata.cxx
new file mode 100644
index 0000000000..759aaf1e70
--- /dev/null
+++ b/ucbhelper/source/provider/resultsetmetadata.cxx
@@ -0,0 +1,397 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/diagnose.h>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XArray.hpp>
+#include <com/sun/star/sdbc/XBlob.hpp>
+#include <com/sun/star/sdbc/XClob.hpp>
+#include <com/sun/star/sdbc/XRef.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/ucb/PropertiesManager.hpp>
+#include <ucbhelper/resultsetmetadata.hxx>
+#include <mutex>
+
+using namespace com::sun::star::beans;
+using namespace com::sun::star::io;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::sdbc;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+
+
+namespace ucbhelper_impl {
+
+struct ResultSetMetaData_Impl
+{
+ std::mutex m_aMutex;
+ std::vector< ::ucbhelper::ResultSetColumnData > m_aColumnData;
+ bool m_bObtainedTypes;
+
+ explicit ResultSetMetaData_Impl( sal_Int32 nSize )
+ : m_aColumnData( nSize ), m_bObtainedTypes( false ) {}
+
+ explicit ResultSetMetaData_Impl(
+ std::vector< ::ucbhelper::ResultSetColumnData >&& rColumnData )
+ : m_aColumnData( std::move(rColumnData) ), m_bObtainedTypes( false ) {}
+};
+
+}
+
+using namespace ucbhelper_impl;
+
+namespace ucbhelper {
+
+
+// ResultSetMetaData Implementation.
+
+
+ResultSetMetaData::ResultSetMetaData(
+ const Reference< XComponentContext >& rxContext,
+ const Sequence< Property >& rProps )
+: m_pImpl( new ResultSetMetaData_Impl( rProps.getLength() ) ),
+ m_xContext( rxContext ),
+ m_aProps( rProps )
+{
+}
+
+
+ResultSetMetaData::ResultSetMetaData(
+ const Reference< XComponentContext >& rxContext,
+ const Sequence< Property >& rProps,
+ std::vector< ResultSetColumnData >&& rColumnData )
+: m_pImpl( new ResultSetMetaData_Impl( std::move(rColumnData) ) ),
+ m_xContext( rxContext ),
+ m_aProps( rProps )
+{
+ OSL_ENSURE( m_pImpl->m_aColumnData.size() == sal_uInt32( rProps.getLength() ),
+ "ResultSetMetaData ctor - different array sizes!" );
+}
+
+
+// virtual
+ResultSetMetaData::~ResultSetMetaData()
+{
+}
+
+
+// XResultSetMetaData methods.
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::getColumnCount()
+{
+ return m_aProps.getLength();
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isAutoIncrement( sal_Int32 /*column*/ )
+{
+ /*
+ Checks whether column is automatically numbered, which makes it
+ read-only.
+ */
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isCaseSensitive( sal_Int32 column )
+{
+ if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
+ return false;
+
+ return m_pImpl->m_aColumnData[ column - 1 ].isCaseSensitive;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isSearchable( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isCurrency( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::isNullable( sal_Int32 /*column*/ )
+{
+ return ColumnValue::NULLABLE;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isSigned( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::getColumnDisplaySize( sal_Int32 /*column*/ )
+{
+ /*
+ Gets the normal maximum width in characters for column.
+ */
+ return 16;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getColumnLabel( sal_Int32 column )
+{
+ /*
+ Gets the suggested column title for column, to be used in print-
+ outs and displays.
+ */
+
+ if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
+ return OUString();
+
+ return m_aProps.getConstArray()[ column - 1 ].Name;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getColumnName( sal_Int32 column )
+{
+ /*
+ Gets the name of column.
+ */
+
+ if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
+ return OUString();
+
+ return m_aProps.getConstArray()[ column - 1 ].Name;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getSchemaName( sal_Int32 /*column*/ )
+{
+ /*
+ Gets the schema name for the table from which column of this
+ result set was derived.
+ Because this feature is not widely supported, the return value
+ for many DBMSs will be an empty string.
+ */
+ return OUString();
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::getPrecision( sal_Int32 /*column*/ )
+{
+ return -1;
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::getScale( sal_Int32 /*column*/ )
+{
+ return 0;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getTableName( sal_Int32 /*column*/ )
+{
+ /*
+ Gets the name of the table from which column of this result set
+ was derived or "" if there is none (for example, for a join).
+ Because this feature is not widely supported, the return value
+ for many DBMSs will be an empty string.
+ */
+ return OUString();
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getCatalogName( sal_Int32 /*column*/ )
+{
+ /*
+ Gets the catalog name for the table from which column of this
+ result set was derived.
+ Because this feature is not widely supported, the return value
+ for many DBMSs will be an empty string.
+ */
+ return OUString();
+}
+
+
+// virtual
+sal_Int32 SAL_CALL ResultSetMetaData::getColumnType( sal_Int32 column )
+{
+ /*
+ Gets the JDBC type for the value stored in column. ... The STRUCT
+ and DISTINCT type codes are always returned for structured and
+ distinct types, regardless of whether the value will be mapped
+ according to the standard mapping or be a custom mapping.
+ */
+
+ if ( ( column < 1 ) || ( column > m_aProps.getLength() ) )
+ return DataType::SQLNULL;
+
+ if ( m_aProps.getConstArray()[ column - 1 ].Type
+ == cppu::UnoType<void>::get() )
+ {
+ // No type given. Try UCB's Properties Manager...
+
+ std::unique_lock aGuard( m_pImpl->m_aMutex );
+
+ if ( !m_pImpl->m_bObtainedTypes )
+ {
+ try
+ {
+ Reference< XPropertySetInfo > xInfo = PropertiesManager::create( m_xContext );
+ // Less (remote) calls...
+
+ const Sequence< Property > aProps = xInfo->getProperties();
+
+ for ( Property& rProp : asNonConstRange(m_aProps) )
+ {
+ auto pProp = std::find_if(aProps.begin(), aProps.end(),
+ [&rProp](const Property& rProp1) { return rProp.Name == rProp1.Name; });
+ if (pProp != aProps.end())
+ {
+ // Found...
+ rProp.Type = pProp->Type;
+ }
+ }
+ }
+ catch ( RuntimeException& )
+ {
+ throw;
+ }
+ catch ( Exception& )
+ {
+ // createInstance
+ }
+
+ m_pImpl->m_bObtainedTypes = true;
+ }
+ }
+
+ const Type& rType = m_aProps.getConstArray()[ column - 1 ].Type;
+ sal_Int32 nType = DataType::OTHER;
+
+ if ( rType == cppu::UnoType<OUString>::get() )
+ nType = DataType::VARCHAR; // XRow::getString
+ else if ( rType == cppu::UnoType<bool>::get() )
+ nType = DataType::BIT; // XRow::getBoolean
+ else if ( rType == cppu::UnoType<sal_Int32>::get() )
+ nType = DataType::INTEGER; // XRow::getInt
+ else if ( rType == cppu::UnoType<sal_Int64>::get() )
+ nType = DataType::BIGINT; // XRow::getLong
+ else if ( rType == cppu::UnoType<sal_Int16>::get() )
+ nType = DataType::SMALLINT; // XRow::getShort
+ else if ( rType == cppu::UnoType<sal_Int8>::get() )
+ nType = DataType::TINYINT; // XRow::getByte
+ else if ( rType == cppu::UnoType<float>::get() )
+ nType = DataType::REAL; // XRow::getFloat
+ else if ( rType == cppu::UnoType<double>::get() )
+ nType = DataType::DOUBLE; // XRow::getDouble
+ else if ( rType == cppu::UnoType<Sequence<sal_Int8>>::get() )
+ nType = DataType::VARBINARY;// XRow::getBytes
+ else if ( rType == cppu::UnoType<Date>::get() )
+ nType = DataType::DATE; // XRow::getDate
+ else if ( rType == cppu::UnoType<Time>::get() )
+ nType = DataType::TIME; // XRow::getTime
+ else if ( rType == cppu::UnoType<DateTime>::get() )
+ nType = DataType::TIMESTAMP;// XRow::getTimestamp
+ else if ( rType == cppu::UnoType<XInputStream>::get() )
+ nType = DataType::LONGVARBINARY; // XRow::getBinaryStream
+// nType = DataType::LONGVARCHAR; // XRow::getCharacterStream
+ else if ( rType == cppu::UnoType<XClob>::get() )
+ nType = DataType::CLOB; // XRow::getClob
+ else if ( rType == cppu::UnoType<XBlob>::get() )
+ nType = DataType::BLOB; // XRow::getBlob
+ else if ( rType == cppu::UnoType<XArray>::get() )
+ nType = DataType::ARRAY;// XRow::getArray
+ else if ( rType == cppu::UnoType<XRef>::get() )
+ nType = DataType::REF;// XRow::getRef
+ else
+ nType = DataType::OBJECT;// XRow::getObject
+
+ return nType;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getColumnTypeName( sal_Int32 /*column*/ )
+{
+ /*
+ Gets the type name used by this particular data source for the
+ values stored in column. If the type code for the type of value
+ stored in column is STRUCT, DISTINCT or JAVA_OBJECT, this method
+ returns a fully-qualified SQL type name.
+ */
+ return OUString();
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isReadOnly( sal_Int32 /*column*/ )
+{
+ return true;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isWritable( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+// virtual
+sal_Bool SAL_CALL ResultSetMetaData::isDefinitelyWritable( sal_Int32 /*column*/ )
+{
+ return false;
+}
+
+
+// virtual
+OUString SAL_CALL ResultSetMetaData::getColumnServiceName( sal_Int32 /*column*/ )
+{
+ /*
+ Returns the fully-qualified name of the service whose instances
+ are manufactured if XResultSet::getObject is called to retrieve
+ a value from the column.
+ */
+ return OUString();
+}
+
+} // namespace ucbhelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simpleauthenticationrequest.cxx b/ucbhelper/source/provider/simpleauthenticationrequest.cxx
new file mode 100644
index 0000000000..972864d9aa
--- /dev/null
+++ b/ucbhelper/source/provider/simpleauthenticationrequest.cxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ucb/URLAuthenticationRequest.hpp>
+#include <ucbhelper/simpleauthenticationrequest.hxx>
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+
+SimpleAuthenticationRequest::SimpleAuthenticationRequest(
+ const OUString & rURL,
+ const OUString & rServerName,
+ const OUString & rRealm,
+ const OUString & rUserName,
+ const OUString & rPassword,
+ bool bAllowUseSystemCredentials,
+ bool bAllowSessionStoring )
+{
+
+ // Fill request...
+ ucb::URLAuthenticationRequest aRequest;
+// aRequest.Message = // OUString
+// aRequest.Context = // XInterface
+ aRequest.Classification = task::InteractionClassification_ERROR;
+ aRequest.ServerName = rServerName;
+// aRequest.Diagnostic = // OUString
+ aRequest.HasRealm = !rRealm.isEmpty();
+ if ( aRequest.HasRealm )
+ aRequest.Realm = rRealm;
+ aRequest.HasUserName = true;
+ aRequest.UserName = rUserName;
+ aRequest.HasPassword = true;
+ aRequest.Password = rPassword;
+ aRequest.HasAccount = false;
+ aRequest.URL = rURL;
+
+ initialize(aRequest,
+ false,
+ true,
+ true,
+ aRequest.HasAccount,
+ bAllowUseSystemCredentials,
+ bAllowSessionStoring );
+}
+
+
+SimpleAuthenticationRequest::SimpleAuthenticationRequest(
+ const OUString & rURL,
+ const OUString & rServerName,
+ EntityType eRealmType,
+ const OUString & rRealm,
+ EntityType eUserNameType,
+ const OUString & rUserName,
+ EntityType ePasswordType,
+ const OUString & rPassword)
+{
+ // Fill request...
+ ucb::URLAuthenticationRequest aRequest;
+// aRequest.Message = // OUString
+// aRequest.Context = // XInterface
+ aRequest.Classification = task::InteractionClassification_ERROR;
+ aRequest.ServerName = rServerName;
+// aRequest.Diagnostic = // OUString
+ aRequest.HasRealm = eRealmType != ENTITY_NA;
+ if ( aRequest.HasRealm )
+ aRequest.Realm = rRealm;
+ aRequest.HasUserName = eUserNameType != ENTITY_NA;
+ if ( aRequest.HasUserName )
+ aRequest.UserName = rUserName;
+ aRequest.HasPassword = ePasswordType != ENTITY_NA;
+ if ( aRequest.HasPassword )
+ aRequest.Password = rPassword;
+ aRequest.HasAccount = false;
+ aRequest.URL = rURL;
+
+ initialize(aRequest,
+ eRealmType == ENTITY_MODIFY,
+ eUserNameType == ENTITY_MODIFY,
+ ePasswordType == ENTITY_MODIFY,
+ false,
+ false,
+ true );
+}
+
+
+void SimpleAuthenticationRequest::initialize(
+ const ucb::URLAuthenticationRequest & rRequest,
+ bool bCanSetRealm,
+ bool bCanSetUserName,
+ bool bCanSetPassword,
+ bool bCanSetAccount,
+ bool bAllowUseSystemCredentials,
+ bool bAllowSessionStoring )
+{
+ setRequest( uno::Any( rRequest ) );
+
+ // Fill continuations...
+ unsigned int nSize = 2;
+
+ if( bAllowSessionStoring )
+ nSize++;
+
+ uno::Sequence< ucb::RememberAuthentication > aRememberModes( nSize );
+ auto it = aRememberModes.getArray();
+ *it++ = ucb::RememberAuthentication_NO;
+
+ if( bAllowSessionStoring )
+ *it++ = ucb::RememberAuthentication_SESSION;
+
+ *it = ucb::RememberAuthentication_PERSISTENT;
+
+ m_xAuthSupplier
+ = new InteractionSupplyAuthentication(
+ this,
+ bCanSetRealm,
+ bCanSetUserName,
+ bCanSetPassword,
+ bCanSetAccount,
+ aRememberModes, // rRememberPasswordModes
+ ucb::RememberAuthentication_SESSION, // eDefaultRememberPasswordMode
+ aRememberModes, // rRememberAccountModes
+ ucb::RememberAuthentication_SESSION, // eDefaultRememberAccountMode
+ bAllowUseSystemCredentials // bCanUseSystemCredentials,
+ );
+
+ setContinuations(
+ { new InteractionAbort(this), new InteractionRetry(this), m_xAuthSupplier });
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simplecertificatevalidationrequest.cxx b/ucbhelper/source/provider/simplecertificatevalidationrequest.cxx
new file mode 100644
index 0000000000..e1dba7a35d
--- /dev/null
+++ b/ucbhelper/source/provider/simplecertificatevalidationrequest.cxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ucb/CertificateValidationRequest.hpp>
+#include <ucbhelper/simplecertificatevalidationrequest.hxx>
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+
+SimpleCertificateValidationRequest::SimpleCertificateValidationRequest( sal_Int32 lCertificateValidity,
+ const css::uno::Reference<css::security::XCertificate>& certificate,
+ const OUString & hostname)
+{
+ // Fill request...
+ ucb::CertificateValidationRequest aRequest;
+ aRequest.CertificateValidity = lCertificateValidity;
+ aRequest.Certificate = certificate;
+ aRequest.HostName = hostname;
+
+ setRequest( uno::Any( aRequest ) );
+
+ setContinuations({ new InteractionAbort(this), new InteractionApprove(this) });
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simpleinteractionrequest.cxx b/ucbhelper/source/provider/simpleinteractionrequest.cxx
new file mode 100644
index 0000000000..d846be5d35
--- /dev/null
+++ b/ucbhelper/source/provider/simpleinteractionrequest.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <ucbhelper/simpleinteractionrequest.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+
+SimpleInteractionRequest::SimpleInteractionRequest(
+ const uno::Any & rRequest,
+ const ContinuationFlags nContinuations )
+: InteractionRequest( rRequest )
+{
+ // Set continuations.
+ OSL_ENSURE( nContinuations != ContinuationFlags::NONE,
+ "SimpleInteractionRequest - No continuation!" );
+
+ std::vector< uno::Reference< task::XInteractionContinuation > > aContinuations;
+ if ( nContinuations & ContinuationFlags::Abort )
+ {
+ aContinuations.push_back( new InteractionAbort( this ) );
+ }
+ if ( nContinuations & ContinuationFlags::Retry )
+ {
+ aContinuations.push_back( new InteractionRetry( this ) );
+ }
+ if ( nContinuations & ContinuationFlags::Approve )
+ {
+ aContinuations.push_back( new InteractionApprove( this ) );
+ }
+ if ( nContinuations & ContinuationFlags::Disapprove )
+ {
+ aContinuations.push_back( new InteractionDisapprove( this ) );
+ }
+ setContinuations( comphelper::containerToSequence(aContinuations) );
+}
+
+
+ContinuationFlags SimpleInteractionRequest::getResponse() const
+{
+ rtl::Reference< InteractionContinuation > xSelection = getSelection();
+ if ( xSelection.is() )
+ {
+ InteractionContinuation * pSelection = xSelection.get();
+
+ uno::Reference< task::XInteractionAbort > xAbort(
+ pSelection, uno::UNO_QUERY );
+ if ( xAbort.is() )
+ return ContinuationFlags::Abort;
+
+ uno::Reference< task::XInteractionRetry > xRetry(
+ pSelection, uno::UNO_QUERY );
+ if ( xRetry.is() )
+ return ContinuationFlags::Retry;
+
+ uno::Reference< task::XInteractionApprove > xApprove(
+ pSelection, uno::UNO_QUERY );
+ if ( xApprove.is() )
+ return ContinuationFlags::Approve;
+
+ uno::Reference< task::XInteractionDisapprove > xDisapprove(
+ pSelection, uno::UNO_QUERY );
+ if ( xDisapprove.is() )
+ return ContinuationFlags::Disapprove;
+
+ OSL_FAIL( "SimpleInteractionRequest::getResponse - Unknown continuation!" );
+ }
+ return ContinuationFlags::NONE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simpleioerrorrequest.cxx b/ucbhelper/source/provider/simpleioerrorrequest.cxx
new file mode 100644
index 0000000000..0c0857f915
--- /dev/null
+++ b/ucbhelper/source/provider/simpleioerrorrequest.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/ucb/XCommandProcessor.hpp>
+#include "simpleioerrorrequest.hxx"
+
+using namespace com::sun::star;
+using namespace ucbhelper;
+
+
+SimpleIOErrorRequest::SimpleIOErrorRequest(
+ const ucb::IOErrorCode eError,
+ const uno::Sequence< uno::Any > & rArgs,
+ const OUString & rMessage,
+ const uno::Reference< ucb::XCommandProcessor > & xContext )
+{
+ // Fill request...
+ ucb::InteractiveAugmentedIOException aRequest(
+ rMessage, xContext, task::InteractionClassification_ERROR, eError, rArgs);
+
+ setRequest( uno::Any( aRequest ) );
+
+ // Fill continuations...
+ setContinuations({ new InteractionAbort(this) });
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simpleioerrorrequest.hxx b/ucbhelper/source/provider/simpleioerrorrequest.hxx
new file mode 100644
index 0000000000..134f10a9aa
--- /dev/null
+++ b/ucbhelper/source/provider/simpleioerrorrequest.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef UCBHELPER_SOURCE_PROVIDER_SIMPLEIOERRORREQUEST_HXX
+#define UCBHELPER_SOURCE_PROVIDER_SIMPLEIOERRORREQUEST_HXX
+
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <ucbhelper/interactionrequest.hxx>
+
+namespace com::sun::star::ucb { class XCommandProcessor; }
+
+namespace ucbhelper {
+
+/**
+ * This class implements a simple IO error interaction request. Instances
+ * can be passed directly to XInteractionHandler::handle(...). Each
+ * instance contains an InteractiveIOException and one interaction
+ * continuation: "Abort".
+ *
+ * @see css::ucb::InteractiveIOException
+ * @see InteractionAbort
+ */
+class SimpleIOErrorRequest final : public ucbhelper::InteractionRequest
+{
+public:
+ /**
+ * Constructor.
+ *
+ * @param xContext contains the command processor that executes the
+ * command related to the request.
+ *
+ * @param eError is the error code to pass along with the request.
+ *
+ * qparam rArgs are additional parameters according to the specification
+ * of the error code. Refer to com/sun/star/ucb/IOErrorCode.idl
+ * for details.
+ */
+ SimpleIOErrorRequest( const css::ucb::IOErrorCode eError,
+ const css::uno::Sequence< css::uno::Any > & rArgs,
+ const OUString & rMessage,
+ const css::uno::Reference< css::ucb::XCommandProcessor > & xContext
+ );
+};
+
+} // namespace ucbhelper
+
+#endif /* ! UCBHELPER_SOURCE_PROVIDER_SIMPLEIOERRORREQUEST_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucbhelper/source/provider/simplenameclashresolverequest.cxx b/ucbhelper/source/provider/simplenameclashresolverequest.cxx
new file mode 100644
index 0000000000..652bdcdbb1
--- /dev/null
+++ b/ucbhelper/source/provider/simplenameclashresolverequest.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ucb/NameClashResolveRequest.hpp>
+#include <com/sun/star/ucb/XInteractionSupplyName.hpp>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <ucbhelper/simplenameclashresolverequest.hxx>
+
+using namespace com::sun::star;
+
+namespace ucbhelper {
+
+/**
+ * This class implements a standard interaction continuation, namely the
+ * interface XInteractionSupplyName. Instances of this class can be passed
+ * along with an interaction request to indicate the possibility to
+ * supply a new name.
+ */
+class InteractionSupplyName : public InteractionContinuation,
+ public css::lang::XTypeProvider,
+ public css::ucb::XInteractionSupplyName
+{
+ OUString m_aName;
+
+public:
+ explicit InteractionSupplyName( InteractionRequest * pRequest )
+ : InteractionContinuation( pRequest ) {}
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL
+ queryInterface( const css::uno::Type & rType ) override;
+ virtual void SAL_CALL acquire()
+ noexcept override;
+ virtual void SAL_CALL release()
+ noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL
+ getTypes() override;
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL
+ getImplementationId() override;
+
+ // XInteractionContinuation
+ virtual void SAL_CALL select() override;
+
+ // XInteractionSupplyName
+ virtual void SAL_CALL setName( const OUString& Name ) override;
+
+ // Non-interface methods.
+
+ /**
+ * This method returns the name that was supplied by the interaction
+ * handler.
+ *
+ * @return the name.
+ */
+ const OUString & getName() const { return m_aName; }
+};
+
+void SAL_CALL InteractionSupplyName::acquire()
+ noexcept
+{
+ OWeakObject::acquire();
+}
+
+void SAL_CALL InteractionSupplyName::release()
+ noexcept
+{
+ OWeakObject::release();
+}
+
+uno::Any SAL_CALL
+InteractionSupplyName::queryInterface( const uno::Type & rType )
+{
+ uno::Any aRet = cppu::queryInterface( rType,
+ static_cast< lang::XTypeProvider * >( this ),
+ static_cast< task::XInteractionContinuation * >( this ),
+ static_cast< ucb::XInteractionSupplyName * >( this ) );
+
+ return aRet.hasValue()
+ ? aRet : InteractionContinuation::queryInterface( rType );
+}
+
+uno::Sequence< sal_Int8 > SAL_CALL InteractionSupplyName::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+uno::Sequence< uno::Type > SAL_CALL InteractionSupplyName::getTypes()
+{
+ static cppu::OTypeCollection s_aCollection(
+ cppu::UnoType<lang::XTypeProvider>::get(),
+ cppu::UnoType<ucb::XInteractionSupplyName>::get() );
+
+ return s_aCollection.getTypes();
+}
+
+void SAL_CALL InteractionSupplyName::select()
+{
+ recordSelection();
+}
+
+void SAL_CALL
+InteractionSupplyName::setName( const OUString& Name )
+{
+ m_aName = Name;
+}
+
+SimpleNameClashResolveRequest::~SimpleNameClashResolveRequest() {}
+
+SimpleNameClashResolveRequest::SimpleNameClashResolveRequest(
+ const OUString & rTargetFolderURL,
+ const OUString & rClashingName )
+{
+ // Fill request...
+ ucb::NameClashResolveRequest aRequest;
+// aRequest.Message = // OUString
+// aRequest.Context = // XInterface
+ aRequest.Classification = task::InteractionClassification_QUERY;
+ aRequest.TargetFolderURL = rTargetFolderURL;
+ aRequest.ClashingName = rClashingName;
+ aRequest.ProposedNewName = OUString();
+
+ setRequest( uno::Any( aRequest ) );
+
+ // Fill continuations...
+ m_xNameSupplier = new InteractionSupplyName( this );
+
+ setContinuations({ new InteractionAbort(this), m_xNameSupplier,
+ new InteractionReplaceExistingData(this) });
+}
+
+OUString const & SimpleNameClashResolveRequest::getNewName() const
+{
+ return m_xNameSupplier->getName();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */