From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- ucb/source/ucp/ext/ucpext.component | 26 ++ ucb/source/ucp/ext/ucpext_content.cxx | 624 +++++++++++++++++++++++++++++ ucb/source/ucp/ext/ucpext_content.hxx | 134 +++++++ ucb/source/ucp/ext/ucpext_datasupplier.cxx | 313 +++++++++++++++ ucb/source/ucp/ext/ucpext_datasupplier.hxx | 88 ++++ ucb/source/ucp/ext/ucpext_provider.cxx | 171 ++++++++ ucb/source/ucp/ext/ucpext_provider.hxx | 54 +++ ucb/source/ucp/ext/ucpext_resultset.cxx | 75 ++++ ucb/source/ucp/ext/ucpext_resultset.hxx | 61 +++ 9 files changed, 1546 insertions(+) create mode 100644 ucb/source/ucp/ext/ucpext.component create mode 100644 ucb/source/ucp/ext/ucpext_content.cxx create mode 100644 ucb/source/ucp/ext/ucpext_content.hxx create mode 100644 ucb/source/ucp/ext/ucpext_datasupplier.cxx create mode 100644 ucb/source/ucp/ext/ucpext_datasupplier.hxx create mode 100644 ucb/source/ucp/ext/ucpext_provider.cxx create mode 100644 ucb/source/ucp/ext/ucpext_provider.hxx create mode 100644 ucb/source/ucp/ext/ucpext_resultset.cxx create mode 100644 ucb/source/ucp/ext/ucpext_resultset.hxx (limited to 'ucb/source/ucp/ext') diff --git a/ucb/source/ucp/ext/ucpext.component b/ucb/source/ucp/ext/ucpext.component new file mode 100644 index 000000000..879837e5f --- /dev/null +++ b/ucb/source/ucp/ext/ucpext.component @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/ucb/source/ucp/ext/ucpext_content.cxx b/ucb/source/ucp/ext/ucpext_content.cxx new file mode 100644 index 000000000..71d6cbbae --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_content.cxx @@ -0,0 +1,624 @@ +/* -*- 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 "ucpext_content.hxx" +#include "ucpext_provider.hxx" +#include "ucpext_resultset.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace ucb::ucp::ext +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::XCommandEnvironment; + using ::com::sun::star::ucb::Command; + using ::com::sun::star::beans::Property; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::ucb::OpenCommandArgument2; + using ::com::sun::star::ucb::XDynamicResultSet; + using ::com::sun::star::ucb::UnsupportedCommandException; + using ::com::sun::star::sdbc::XRow; + using ::com::sun::star::beans::PropertyChangeEvent; + using ::com::sun::star::lang::IllegalAccessException; + using ::com::sun::star::ucb::CommandInfo; + using ::com::sun::star::deployment::PackageInformationProvider; + using ::com::sun::star::deployment::XPackageInformationProvider; + + namespace OpenMode = ::com::sun::star::ucb::OpenMode; + namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute; + + + //= helper + + namespace + { + + OUString lcl_compose( std::u16string_view i_rBaseURL, const OUString& i_rRelativeURL ) + { + ENSURE_OR_RETURN( !i_rBaseURL.empty(), "illegal base URL", i_rRelativeURL ); + + OUStringBuffer aComposer( i_rBaseURL ); + if ( !o3tl::ends_with(i_rBaseURL, u"/") ) + aComposer.append( '/' ); + aComposer.append( i_rRelativeURL ); + return aComposer.makeStringAndClear(); + } + + + struct SelectPropertyName + { + const OUString& operator()( const Property& i_rProperty ) const + { + return i_rProperty.Name; + } + }; + } + + + //= Content + + + Content::Content( const Reference< XComponentContext >& rxContext, ::ucbhelper::ContentProviderImplHelper* i_pProvider, + const Reference< XContentIdentifier >& i_rIdentifier ) + :Content_Base( rxContext, i_pProvider, i_rIdentifier ) + ,m_eExtContentType( E_UNKNOWN ) + { + const OUString sURL( getIdentifier()->getContentIdentifier() ); + if ( denotesRootContent( sURL ) ) + { + m_eExtContentType = E_ROOT; + } + else + { + const std::u16string_view sRelativeURL( sURL.subView( ContentProvider::getRootURL().getLength() ) ); + const size_t nSepPos = sRelativeURL.find( '/' ); + if ( ( nSepPos == std::u16string_view::npos ) || ( nSepPos == sRelativeURL.size() - 1 ) ) + { + m_eExtContentType = E_EXTENSION_ROOT; + } + else + { + m_eExtContentType = E_EXTENSION_CONTENT; + } + } + + if ( m_eExtContentType == E_ROOT ) + return; + + const OUString sRootURL = ContentProvider::getRootURL(); + m_sExtensionId = sURL.copy( sRootURL.getLength() ); + + const sal_Int32 nNextSep = m_sExtensionId.indexOf( '/' ); + if ( nNextSep > -1 ) + { + m_sPathIntoExtension = m_sExtensionId.copy( nNextSep + 1 ); + m_sExtensionId = m_sExtensionId.copy( 0, nNextSep ); + } + m_sExtensionId = Content::decodeIdentifier( m_sExtensionId ); + } + + + Content::~Content() + { + } + + + OUString SAL_CALL Content::getImplementationName() + { + return "org.openoffice.comp.ucp.ext.Content"; + } + + + Sequence< OUString > SAL_CALL Content::getSupportedServiceNames() + { + return { "com.sun.star.ucb.Content", "com.sun.star.ucb.ExtensionContent" }; + } + + + OUString SAL_CALL Content::getContentType() + { + impl_determineContentType(); + return *m_aContentType; + } + + + Any SAL_CALL Content::execute( const Command& aCommand, sal_Int32 /* CommandId */, const Reference< XCommandEnvironment >& i_rEnvironment ) + { + Any aRet; + + if ( aCommand.Name == "getPropertyValues" ) + { + Sequence< Property > Properties; + if ( !( aCommand.Argument >>= Properties ) ) + { + ::ucbhelper::cancelCommandExecution( Any( IllegalArgumentException( + OUString(), *this, -1 ) ), + i_rEnvironment ); + // unreachable + } + + aRet <<= getPropertyValues( Properties, i_rEnvironment ); + } + else if ( aCommand.Name == "setPropertyValues" ) + { + Sequence< PropertyValue > aProperties; + if ( !( aCommand.Argument >>= aProperties ) ) + { + ::ucbhelper::cancelCommandExecution( Any( IllegalArgumentException( + OUString(), *this, -1 ) ), + i_rEnvironment ); + // unreachable + } + + if ( !aProperties.hasElements() ) + { + ::ucbhelper::cancelCommandExecution( Any( IllegalArgumentException( + OUString(), *this, -1 ) ), + i_rEnvironment ); + // unreachable + } + + aRet <<= setPropertyValues( aProperties ); + } + else if ( aCommand.Name == "getPropertySetInfo" ) + { + // implemented by base class. + aRet <<= getPropertySetInfo( i_rEnvironment ); + } + else if ( aCommand.Name == "getCommandInfo" ) + { + // implemented by base class. + aRet <<= getCommandInfo( i_rEnvironment ); + } + else if ( aCommand.Name == "open" ) + { + OpenCommandArgument2 aOpenCommand; + if ( !( aCommand.Argument >>= aOpenCommand ) ) + { + ::ucbhelper::cancelCommandExecution( Any( IllegalArgumentException( + OUString(), *this, -1 ) ), + i_rEnvironment ); + // unreachable + } + + bool bOpenFolder = + ( ( aOpenCommand.Mode == OpenMode::ALL ) || + ( aOpenCommand.Mode == OpenMode::FOLDERS ) || + ( aOpenCommand.Mode == OpenMode::DOCUMENTS ) ); + + + if ( bOpenFolder && impl_isFolder() ) + { + Reference< XDynamicResultSet > xSet = new ResultSet( m_xContext, this, aOpenCommand, i_rEnvironment ); + aRet <<= xSet; + } + + if ( aOpenCommand.Sink.is() ) + { + const OUString sPhysicalContentURL( getPhysicalURL() ); + ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEnvironment, m_xContext ); + aRet = aRequestedContent.executeCommand( "open", Any( aOpenCommand ) ); + } + } + + else + { + ::ucbhelper::cancelCommandExecution( Any( UnsupportedCommandException( + OUString(), *this ) ), + i_rEnvironment ); + // unreachable + } + + return aRet; + } + + + void SAL_CALL Content::abort( sal_Int32 ) + { + } + + + OUString Content::encodeIdentifier( const OUString& i_rIdentifier ) + { + return ::rtl::Uri::encode( i_rIdentifier, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + + + OUString Content::decodeIdentifier( const OUString& i_rIdentifier ) + { + return ::rtl::Uri::decode( i_rIdentifier, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + } + + + bool Content::denotesRootContent( const OUString& i_rContentIdentifier ) + { + const OUString sRootURL( ContentProvider::getRootURL() ); + if ( i_rContentIdentifier == sRootURL ) + return true; + + // the root URL contains only two trailing /, but we also recognize 3 of them as denoting the root URL + if ( i_rContentIdentifier.match( sRootURL ) + && ( i_rContentIdentifier.getLength() == sRootURL.getLength() + 1 ) + && ( i_rContentIdentifier[ i_rContentIdentifier.getLength() - 1 ] == '/' ) + ) + return true; + + return false; + } + + + OUString Content::getParentURL() + { + const OUString sRootURL( ContentProvider::getRootURL() ); + + switch ( m_eExtContentType ) + { + case E_ROOT: + // don't have a parent + return sRootURL; + + case E_EXTENSION_ROOT: + // our parent is the root itself + return sRootURL; + + case E_EXTENSION_CONTENT: + { + const OUString sURL = m_xIdentifier->getContentIdentifier(); + + // cut the root URL + if ( !sURL.match( sRootURL ) ) + { + SAL_INFO( "ucb.ucp.ext", "illegal URL structure - no root" ); + break; + } + + OUString sRelativeURL( sURL.copy( sRootURL.getLength() ) ); + + // cut the extension ID + const OUString sSeparatedExtensionId( encodeIdentifier( m_sExtensionId ) + "/" ); + if ( !sRelativeURL.match( sSeparatedExtensionId ) ) + { + SAL_INFO( "ucb.ucp.ext", "illegal URL structure - no extension ID" ); + break; + } + + sRelativeURL = sRelativeURL.copy( sSeparatedExtensionId.getLength() ); + + // cut the final slash (if any) + if ( sRelativeURL.isEmpty() ) + { + SAL_INFO( "ucb.ucp.ext", "illegal URL structure - ExtensionContent should have a level below the extension ID" ); + break; + } + + if ( sRelativeURL.endsWith("/") ) + sRelativeURL = sRelativeURL.copy( 0, sRelativeURL.getLength() - 1 ); + + // remove the last segment + const sal_Int32 nLastSep = sRelativeURL.lastIndexOf( '/' ); + sRelativeURL = sRelativeURL.copy( 0, nLastSep != -1 ? nLastSep : 0 ); + + return sRootURL + sSeparatedExtensionId + sRelativeURL; + } + + default: + OSL_FAIL( "Content::getParentURL: unhandled case!" ); + break; + } + return OUString(); + } + + + Reference< XRow > Content::getArtificialNodePropertyValues( const Reference< XComponentContext >& rxContext, + const Sequence< Property >& i_rProperties, const OUString& i_rTitle ) + { + // note: empty sequence means "get values of all supported properties". + ::rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rxContext ); + + if ( i_rProperties.hasElements() ) + { + for ( const Property& rProp : i_rProperties ) + { + // Process Core properties. + if ( rProp.Name == "ContentType" ) + { + xRow->appendString ( rProp, ContentProvider::getArtificialNodeContentType() ); + } + else if ( rProp.Name == "Title" ) + { + xRow->appendString ( rProp, i_rTitle ); + } + else if ( rProp.Name == "IsDocument" ) + { + xRow->appendBoolean( rProp, false ); + } + else if ( rProp.Name == "IsFolder" ) + { + xRow->appendBoolean( rProp, true ); + } + else + { + // append empty entry. + xRow->appendVoid( rProp ); + } + } + } + else + { + // Append all Core Properties. + xRow->appendString ( Property( "ContentType", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + ContentProvider::getArtificialNodeContentType() ); + xRow->appendString ( Property( "Title", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + i_rTitle ); + xRow->appendBoolean( Property( "IsDocument", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + false ); + xRow->appendBoolean( Property( "IsFolder", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY ), + true ); + } + + return xRow; + } + + + OUString Content::getPhysicalURL() const + { + ENSURE_OR_RETURN( m_eExtContentType != E_ROOT, "illegal call", OUString() ); + + // create a ucb::XContent for the physical file within the deployed extension + const Reference< XPackageInformationProvider > xPackageInfo = PackageInformationProvider::get(m_xContext); + const OUString sPackageLocation( xPackageInfo->getPackageLocation( m_sExtensionId ) ); + + if ( m_sPathIntoExtension.isEmpty() ) + return sPackageLocation; + return lcl_compose( sPackageLocation, m_sPathIntoExtension ); + } + + + Reference< XRow > Content::getPropertyValues( const Sequence< Property >& i_rProperties, const Reference< XCommandEnvironment >& i_rEnv ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + + switch ( m_eExtContentType ) + { + case E_ROOT: + return getArtificialNodePropertyValues( m_xContext, i_rProperties, ContentProvider::getRootURL() ); + case E_EXTENSION_ROOT: + return getArtificialNodePropertyValues( m_xContext, i_rProperties, m_sExtensionId ); + case E_EXTENSION_CONTENT: + { + const OUString sPhysicalContentURL( getPhysicalURL() ); + ::ucbhelper::Content aRequestedContent( sPhysicalContentURL, i_rEnv, m_xContext ); + + // translate the property request + Sequence< OUString > aPropertyNames( i_rProperties.getLength() ); + ::std::transform( + i_rProperties.begin(), + i_rProperties.end(), + aPropertyNames.getArray(), + SelectPropertyName() + ); + const Sequence< Any > aPropertyValues = aRequestedContent.getPropertyValues( aPropertyNames ); + const ::rtl::Reference< ::ucbhelper::PropertyValueSet > xValueRow = new ::ucbhelper::PropertyValueSet( m_xContext ); + sal_Int32 i=0; + for ( const Any* value = aPropertyValues.getConstArray(); + value != aPropertyValues.getConstArray() + aPropertyValues.getLength(); + ++value, ++i + ) + { + xValueRow->appendObject( aPropertyNames[i], *value ); + } + return xValueRow; + } + + default: + OSL_FAIL( "Content::getPropertyValues: unhandled case!" ); + break; + } + + OSL_FAIL( "Content::getPropertyValues: unreachable!" ); + return nullptr; + } + + + Sequence< Any > Content::setPropertyValues( const Sequence< PropertyValue >& i_rValues) + { + ::osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); + + Sequence< Any > aRet( i_rValues.getLength() ); + + PropertyChangeEvent aEvent; + aEvent.Source = static_cast< cppu::OWeakObject * >( this ); + aEvent.Further = false; + aEvent.PropertyHandle = -1; + + for ( auto& rRet : asNonConstRange(aRet) ) + { + // all our properties are read-only ... + rRet <<= IllegalAccessException("property is read-only.", *this ); + } + + return aRet; + } + + + Sequence< CommandInfo > Content::getCommands( const Reference< XCommandEnvironment > & /*xEnv*/ ) + { + static const CommandInfo aCommandInfoTable[] = + { + // Mandatory commands + + CommandInfo( + "getCommandInfo", + -1, + cppu::UnoType::get() + ), + CommandInfo( + "getPropertySetInfo", + -1, + cppu::UnoType::get() + ), + CommandInfo( + "getPropertyValues", + -1, + cppu::UnoType>::get() + ), + CommandInfo( + "setPropertyValues", + -1, + cppu::UnoType>::get() + ) + + // Optional standard commands + + , CommandInfo( + "open", + -1, + cppu::UnoType::get() + ) + }; + + return Sequence< CommandInfo >( aCommandInfoTable, SAL_N_ELEMENTS(aCommandInfoTable) ); + } + + + Sequence< Property > Content::getProperties( const Reference< XCommandEnvironment > & /*xEnv*/ ) + { + static const Property aProperties[] = + { + Property( + "ContentType", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + "IsDocument", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + "IsFolder", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ), + Property( + "Title", + -1, + cppu::UnoType::get(), + PropertyAttribute::BOUND | PropertyAttribute::READONLY + ) + }; + return Sequence< Property >( aProperties, SAL_N_ELEMENTS( aProperties ) ); + } + + + bool Content::impl_isFolder() + { + if ( !!m_aIsFolder ) + return *m_aIsFolder; + + bool bIsFolder = false; + try + { + Sequence< Property > aProps{ { /*Name*/ "IsFolder", {}, {}, {} } }; + Reference< XRow > xRow( getPropertyValues( aProps, nullptr ), UNO_SET_THROW ); + bIsFolder = xRow->getBoolean(1); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("ucb.ucp.ext"); + } + m_aIsFolder = bIsFolder; + return *m_aIsFolder; + } + + + void Content::impl_determineContentType() + { + if ( !!m_aContentType ) + return; + + m_aContentType = ContentProvider::getArtificialNodeContentType(); + if ( m_eExtContentType != E_EXTENSION_CONTENT ) + return; + + try + { + Sequence< Property > aProps{ { /*Name*/ "ContentType", {}, {}, {} } }; + Reference< XRow > xRow( getPropertyValues( aProps, nullptr ), UNO_SET_THROW ); + m_aContentType = xRow->getString(1); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("ucb.ucp.ext"); + } + } + + +} // namespace ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_content.hxx b/ucb/source/ucp/ext/ucpext_content.hxx new file mode 100644 index 000000000..3e7136f07 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_content.hxx @@ -0,0 +1,134 @@ +/* -*- 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 . + */ + +#pragma once + +#include +#include + +#include + +#include + + +namespace ucb::ucp::ext +{ + + + //= ExtensionContentType + + enum ExtensionContentType + { + E_ROOT, + E_EXTENSION_ROOT, + E_EXTENSION_CONTENT, + + E_UNKNOWN + }; + + + //= ContentProvider + + typedef ::ucbhelper::ContentImplHelper Content_Base; + class Content : public Content_Base + { + public: + Content( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + ::ucbhelper::ContentProviderImplHelper* pProvider, + const css::uno::Reference< css::ucb::XContentIdentifier >& Identifier + ); + + static css::uno::Reference< css::sdbc::XRow > + getArtificialNodePropertyValues( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Sequence< css::beans::Property >& rProperties, + const OUString& rTitle + ); + + css::uno::Reference< css::sdbc::XRow > + getPropertyValues( + const css::uno::Sequence< css::beans::Property >& rProperties, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv + ); + + static OUString + encodeIdentifier( const OUString& i_rIdentifier ); + static OUString + decodeIdentifier( const OUString& i_rIdentifier ); + + virtual OUString getParentURL() override; + + ExtensionContentType getExtensionContentType() const { return m_eExtContentType; } + + /** retrieves the URL of the underlying physical content. Not to be called when getExtensionContentType() + returns E_ROOT. + */ + OUString getPhysicalURL() const; + + protected: + virtual ~Content() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XContent + virtual OUString SAL_CALL getContentType() override; + + // XCommandProcessor + virtual css::uno::Any SAL_CALL + execute( + const css::ucb::Command& aCommand, + sal_Int32 CommandId, + const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment + ) override; + + virtual void SAL_CALL + abort( + sal_Int32 CommandId + ) override; + + private: + virtual css::uno::Sequence< css::beans::Property > getProperties( const css::uno::Reference< css::ucb::XCommandEnvironment >& i_rEnv ) override; + virtual css::uno::Sequence< css::ucb::CommandInfo > getCommands( const css::uno::Reference< css::ucb::XCommandEnvironment >& i_rEnv ) override; + + css::uno::Sequence< css::uno::Any > + setPropertyValues( + const css::uno::Sequence< css::beans::PropertyValue >& rValues + ); + + static bool denotesRootContent( const OUString& i_rContentIdentifier ); + + bool impl_isFolder(); + void impl_determineContentType(); + + private: + ExtensionContentType m_eExtContentType; + ::std::optional< bool > m_aIsFolder; + ::std::optional< OUString > m_aContentType; + OUString m_sExtensionId; + OUString m_sPathIntoExtension; + }; + + +} // namespace ucb::ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_datasupplier.cxx b/ucb/source/ucp/ext/ucpext_datasupplier.cxx new file mode 100644 index 000000000..3c515358f --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_datasupplier.cxx @@ -0,0 +1,313 @@ +/* -*- 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 "ucpext_datasupplier.hxx" +#include "ucpext_content.hxx" +#include "ucpext_provider.hxx" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace ucb::ucp::ext +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::sdbc::XRow; + using ::com::sun::star::ucb::IllegalIdentifierException; + using ::com::sun::star::deployment::PackageInformationProvider; + using ::com::sun::star::deployment::XPackageInformationProvider; + using ::com::sun::star::sdbc::XResultSet; + + + //= helper + + namespace + { + OUString lcl_compose( std::u16string_view i_rBaseURL, const OUString& i_rRelativeURL ) + { + ENSURE_OR_RETURN( !i_rBaseURL.empty(), "illegal base URL", i_rRelativeURL ); + + OUStringBuffer aComposer( i_rBaseURL ); + if ( !o3tl::ends_with(i_rBaseURL, u"/") ) + aComposer.append( '/' ); + aComposer.append( i_rRelativeURL ); + return aComposer.makeStringAndClear(); + } + } + + + //= DataSupplier + + + DataSupplier::DataSupplier( const Reference< XComponentContext >& rxContext, + const ::rtl::Reference< Content >& i_rContent ) + :m_xContent( i_rContent ) + ,m_xContext( rxContext ) + { + } + + + void DataSupplier::fetchData() + { + try + { + const Reference< XPackageInformationProvider > xPackageInfo = PackageInformationProvider::get( m_xContext ); + + const OUString sContentIdentifier( m_xContent->getIdentifier()->getContentIdentifier() ); + + switch ( m_xContent->getExtensionContentType() ) + { + case E_ROOT: + { + const Sequence< Sequence< OUString > > aExtensionInfo( xPackageInfo->getExtensionList() ); + for ( auto const & extInfo : aExtensionInfo ) + { + if ( !extInfo.hasElements() ) + { + SAL_WARN( "ucb.ucp.ext", "illegal extension info" ); + continue; + } + + const OUString& rLocalId = extInfo[0]; + ResultListEntry aEntry; + aEntry.sId = ContentProvider::getRootURL() + Content::encodeIdentifier( rLocalId ) + "/"; + m_aResults.push_back( aEntry ); + } + } + break; + case E_EXTENSION_ROOT: + case E_EXTENSION_CONTENT: + { + const OUString sPackageLocation( m_xContent->getPhysicalURL() ); + ::ucbhelper::Content aWrappedContent( sPackageLocation, getResultSet()->getEnvironment(), m_xContext ); + + // obtain the properties which our result set is set up for from the wrapped content + Sequence< OUString > aPropertyNames { "Title" }; + + const Reference< XResultSet > xFolderContent( aWrappedContent.createCursor( aPropertyNames ), UNO_SET_THROW ); + const Reference< XRow > xContentRow( xFolderContent, UNO_QUERY_THROW ); + while ( xFolderContent->next() ) + { + ResultListEntry aEntry; + aEntry.sId = lcl_compose( sContentIdentifier, xContentRow->getString( 1 ) ); + m_aResults.push_back( aEntry ); + } + } + break; + default: + OSL_FAIL( "DataSupplier::fetchData: unimplemented content type!" ); + break; + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("ucb.ucp.ext"); + } + } + + + DataSupplier::~DataSupplier() + { + } + + + OUString DataSupplier::queryContentIdentifierString( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + + if ( i_nIndex < m_aResults.size() ) + { + const OUString sId = m_aResults[ i_nIndex ].sId; + if ( !sId.isEmpty() ) + return sId; + } + + OSL_FAIL( "DataSupplier::queryContentIdentifierString: illegal index, or illegal result entry id!" ); + return OUString(); + } + + + Reference< XContentIdentifier > DataSupplier::queryContentIdentifier( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + + if ( i_nIndex < m_aResults.size() ) + { + Reference< XContentIdentifier > xId( m_aResults[ i_nIndex ].xId ); + if ( xId.is() ) + return xId; + } + + OUString sId = queryContentIdentifierString( i_nIndex ); + if ( !sId.isEmpty() ) + { + Reference< XContentIdentifier > xId = new ::ucbhelper::ContentIdentifier( sId ); + m_aResults[ i_nIndex ].xId = xId; + return xId; + } + + return Reference< XContentIdentifier >(); + } + + + Reference< XContent > DataSupplier::queryContent( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + ENSURE_OR_RETURN( i_nIndex < m_aResults.size(), "illegal index!", nullptr ); + + + ::rtl::Reference< Content > pContent( m_aResults[ i_nIndex ].pContent ); + if ( pContent.is() ) + return pContent; + + Reference< XContentIdentifier > xId( queryContentIdentifier( i_nIndex ) ); + if ( xId.is() ) + { + try + { + Reference< XContent > xContent( m_xContent->getProvider()->queryContent( xId ) ); + pContent.set( dynamic_cast< Content* >( xContent.get() ) ); + OSL_ENSURE( pContent.is() || !xContent.is(), "DataSupplier::queryContent: invalid content implementation!" ); + m_aResults[ i_nIndex ].pContent = pContent; + return pContent; + + } + catch ( const IllegalIdentifierException& ) + { + DBG_UNHANDLED_EXCEPTION("ucb.ucp.ext"); + } + } + + return Reference< XContent >(); + } + + + bool DataSupplier::getResult( sal_uInt32 i_nIndex ) + { + ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex ); + + // true if result already present. + return m_aResults.size() > i_nIndex; + } + + + sal_uInt32 DataSupplier::totalCount() + { + ::osl::ClearableGuard< ::osl::Mutex > aGuard( m_aMutex ); + return m_aResults.size(); + } + + + sal_uInt32 DataSupplier::currentCount() + { + return m_aResults.size(); + } + + + bool DataSupplier::isCountFinal() + { + return true; + } + + + Reference< XRow > DataSupplier::queryPropertyValues( sal_uInt32 i_nIndex ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + ENSURE_OR_RETURN( i_nIndex < m_aResults.size(), "DataSupplier::queryPropertyValues: illegal index!", nullptr ); + + Reference< XRow > xRow = m_aResults[ i_nIndex ].xRow; + if ( xRow.is() ) + return xRow; + + ENSURE_OR_RETURN( queryContent( i_nIndex ).is(), "could not retrieve the content", nullptr ); + + switch ( m_xContent->getExtensionContentType() ) + { + case E_ROOT: + { + const OUString& rId( m_aResults[ i_nIndex ].sId ); + const OUString sRootURL( ContentProvider::getRootURL() ); + OUString sTitle = Content::decodeIdentifier( rId.copy( sRootURL.getLength() ) ); + if ( sTitle.endsWith("/") ) + sTitle = sTitle.copy( 0, sTitle.getLength() - 1 ); + xRow = Content::getArtificialNodePropertyValues( m_xContext, getResultSet()->getProperties(), sTitle ); + } + break; + + case E_EXTENSION_ROOT: + case E_EXTENSION_CONTENT: + { + xRow = m_aResults[ i_nIndex ].pContent->getPropertyValues( + getResultSet()->getProperties(), getResultSet()->getEnvironment() ); + } + break; + default: + OSL_FAIL( "DataSupplier::queryPropertyValues: unhandled case!" ); + break; + } + + m_aResults[ i_nIndex ].xRow = xRow; + return xRow; + } + + + void DataSupplier::releasePropertyValues( sal_uInt32 i_nIndex ) + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex ); + + if ( i_nIndex < m_aResults.size() ) + m_aResults[ i_nIndex ].xRow.clear(); + } + + + void DataSupplier::close() + { + } + + + void DataSupplier::validate() + { + } + + +} // namespace ucb::ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_datasupplier.hxx b/ucb/source/ucp/ext/ucpext_datasupplier.hxx new file mode 100644 index 000000000..f0118d679 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_datasupplier.hxx @@ -0,0 +1,88 @@ +/* -*- 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 . + */ + +#pragma once + +#include "ucpext_content.hxx" + +#include +#include + +#include + + +namespace ucb::ucp::ext +{ + + + class Content; + + + //= DataSupplier + + class DataSupplier : public ::ucbhelper::ResultSetDataSupplier + { + public: + DataSupplier( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const rtl::Reference< Content >& rContent + ); + + void fetchData(); + + protected: + virtual ~DataSupplier() override; + + virtual OUString queryContentIdentifierString( sal_uInt32 nIndex ) override; + virtual css::uno::Reference< css::ucb::XContentIdentifier > queryContentIdentifier( sal_uInt32 nIndex ) override; + virtual css::uno::Reference< css::ucb::XContent > queryContent( sal_uInt32 nIndex ) override; + + virtual bool getResult( sal_uInt32 nIndex ) override; + + virtual sal_uInt32 totalCount() override; + virtual sal_uInt32 currentCount() override; + virtual bool isCountFinal() override; + + virtual css::uno::Reference< css::sdbc::XRow > queryPropertyValues( sal_uInt32 nIndex ) override; + virtual void releasePropertyValues( sal_uInt32 nIndex ) override; + + virtual void close() override; + + virtual void validate() override; + + private: + struct ResultListEntry + { + OUString sId; + css::uno::Reference< css::ucb::XContentIdentifier > xId; + ::rtl::Reference< Content > pContent; + css::uno::Reference< css::sdbc::XRow > xRow; + }; + typedef ::std::vector< ResultListEntry > ResultList; + ::osl::Mutex m_aMutex; + ResultList m_aResults; + ::rtl::Reference< Content > m_xContent; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + }; + + +} // namespace ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_provider.cxx b/ucb/source/ucp/ext/ucpext_provider.cxx new file mode 100644 index 000000000..765ea7856 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_provider.cxx @@ -0,0 +1,171 @@ +/* -*- 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 "ucpext_provider.hxx" +#include "ucpext_content.hxx" + +#include +#include +#include +#include +#include + + +namespace ucb::ucp::ext +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::IllegalIdentifierException; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::uno::XComponentContext; + + + //= ContentProvider + + + ContentProvider::ContentProvider( const Reference< XComponentContext >& rxContext ) + :ContentProvider_Base( rxContext ) + { + } + + + ContentProvider::~ContentProvider() + { + } + + + OUString SAL_CALL ContentProvider::getImplementationName() + { + return "org.openoffice.comp.ucp.ext.ContentProvider"; + } + + + Sequence< OUString > SAL_CALL ContentProvider::getSupportedServiceNames( ) + { + return { "com.sun.star.ucb.ContentProvider", "com.sun.star.ucb.ExtensionContentProvider" }; + } + + + OUString ContentProvider::getRootURL() + { + return "vnd.sun.star.extension://"; + } + + + OUString ContentProvider::getArtificialNodeContentType() + { + return "application/vnd.sun.star.extension-content"; + } + + + namespace + { + void lcl_ensureAndTransfer( std::u16string_view& io_rIdentifierFragment, OUStringBuffer& o_rNormalization, const sal_Unicode i_nLeadingChar ) + { + if ( ( io_rIdentifierFragment.empty() ) || ( io_rIdentifierFragment[0] != i_nLeadingChar ) ) + throw IllegalIdentifierException(); + io_rIdentifierFragment = io_rIdentifierFragment.substr( 1 ); + o_rNormalization.append( i_nLeadingChar ); + } + } + + + Reference< XContent > SAL_CALL ContentProvider::queryContent( const Reference< XContentIdentifier >& i_rIdentifier ) + { + // Check URL scheme... + static const OUStringLiteral sScheme( u"vnd.sun.star.extension" ); + if ( !i_rIdentifier->getContentProviderScheme().equalsIgnoreAsciiCase( sScheme ) ) + throw IllegalIdentifierException(); + + // normalize the identifier + const OUString sIdentifier( i_rIdentifier->getContentIdentifier() ); + + // the scheme needs to be lower-case + OUStringBuffer aComposer; + aComposer.append( sIdentifier.copy( 0, sScheme.getLength() ).toAsciiLowerCase() ); + + // one : is required after the scheme + std::u16string_view sRemaining( sIdentifier.subView( sScheme.getLength() ) ); + lcl_ensureAndTransfer( sRemaining, aComposer, ':' ); + + // and at least one / + lcl_ensureAndTransfer( sRemaining, aComposer, '/' ); + + // the normalized form requires one additional /, but we also accept identifiers which don't have it + if ( sRemaining.empty() ) + { + // the root content is a special case, it requires / + aComposer.append( "//" ); + } + else + { + if ( sRemaining[0] != '/' ) + { + aComposer.append( '/' ); + aComposer.append( sRemaining ); + } + else + { + lcl_ensureAndTransfer( sRemaining, aComposer, '/' ); + // by now, we moved "vnd.sun.star.extension://" from the URL to aComposer + if ( sRemaining.empty() ) + { + // again, it's the root content, but one / is missing + aComposer.append( '/' ); + } + else + { + aComposer.append( sRemaining ); + } + } + } + const Reference< XContentIdentifier > xNormalizedIdentifier( new ::ucbhelper::ContentIdentifier( aComposer.makeStringAndClear() ) ); + + ::osl::MutexGuard aGuard( m_aMutex ); + + // check if a content with given id already exists... + Reference< XContent > xContent( queryExistingContent( xNormalizedIdentifier ) ); + if ( xContent.is() ) + return xContent; + + // create a new content + xContent = new Content( m_xContext, this, xNormalizedIdentifier ); + if ( !xContent->getIdentifier().is() ) + throw IllegalIdentifierException(); + + registerNewContent( xContent ); + return xContent; + } + + +} // namespace ucb::ucp::ext + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +ucb_ext_ContentProvider_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) +{ + return cppu::acquire(new ucb::ucp::ext::ContentProvider(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_provider.hxx b/ucb/source/ucp/ext/ucpext_provider.hxx new file mode 100644 index 000000000..e1dae3447 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_provider.hxx @@ -0,0 +1,54 @@ +/* -*- 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 . + */ + +#pragma once + +#include + + +namespace ucb::ucp::ext +{ + + + //= ContentProvider + + typedef ::ucbhelper::ContentProviderImplHelper ContentProvider_Base; + class ContentProvider : public ContentProvider_Base + { + public: + explicit ContentProvider( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + virtual ~ContentProvider() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + // XContentProvider + virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent( const css::uno::Reference< css::ucb::XContentIdentifier >& Identifier ) override; + + public: + static OUString getRootURL(); + static OUString getArtificialNodeContentType(); + }; + + +} // namespace ucb::ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_resultset.cxx b/ucb/source/ucp/ext/ucpext_resultset.cxx new file mode 100644 index 000000000..2ccbded55 --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_resultset.cxx @@ -0,0 +1,75 @@ +/* -*- 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 "ucpext_resultset.hxx" +#include "ucpext_content.hxx" +#include "ucpext_datasupplier.hxx" + +#include + + +namespace ucb::ucp::ext +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::ucb::OpenCommandArgument2; + using ::com::sun::star::ucb::XCommandEnvironment; + + + //= ResultSet + + + ResultSet::ResultSet( const Reference< XComponentContext >& rxContext, const ::rtl::Reference< Content >& i_rContent, + const OpenCommandArgument2& i_rCommand, const Reference< XCommandEnvironment >& i_rEnv ) + :ResultSetImplHelper( rxContext, i_rCommand ) + ,m_xEnvironment( i_rEnv ) + ,m_xContent( i_rContent ) + { + } + + + void ResultSet::initStatic() + { + ::rtl::Reference< DataSupplier > pDataSupplier( new DataSupplier( + m_xContext, + m_xContent + ) ); + m_xResultSet1 = new ::ucbhelper::ResultSet( + m_xContext, + m_aCommand.Properties, + pDataSupplier, + m_xEnvironment + ); + pDataSupplier->fetchData(); + } + + + void ResultSet::initDynamic() + { + initStatic(); + m_xResultSet2 = m_xResultSet1; + } + + +} // namespace ucb::ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/ext/ucpext_resultset.hxx b/ucb/source/ucp/ext/ucpext_resultset.hxx new file mode 100644 index 000000000..abd9fee9a --- /dev/null +++ b/ucb/source/ucp/ext/ucpext_resultset.hxx @@ -0,0 +1,61 @@ +/* -*- 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 . + */ + +#pragma once + +#include "ucpext_content.hxx" + +#include +#include +#include + + +namespace ucb::ucp::ext +{ + + + class Content; + + + //= ResultSet + + class ResultSet : public ::ucbhelper::ResultSetImplHelper + { + public: + ResultSet( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const rtl::Reference< Content >& i_rContent, + const css::ucb::OpenCommandArgument2& i_rCommand, + const css::uno::Reference< css::ucb::XCommandEnvironment >& i_rEnv + ); + + private: + css::uno::Reference< css::ucb::XCommandEnvironment > m_xEnvironment; + ::rtl::Reference< Content > m_xContent; + + private: + virtual void initStatic() override; + virtual void initDynamic() override; + }; + + +} // namespace ucp::ext + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3