diff options
Diffstat (limited to 'ucbhelper/source/provider')
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: */ |