/* -*- 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 <com/sun/star/deployment/PackageInformationProvider.hpp>
#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
#include <o3tl/string_view.hxx>
#include <ucbhelper/contentidentifier.hxx>
#include <ucbhelper/providerhelper.hxx>
#include <ucbhelper/content.hxx>
#include <ucbhelper/propertyvalueset.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <memory>
#include <string_view>
#include <utility>
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,
::rtl::Reference< Content > i_xContent )
:m_xContent(std::move( i_xContent ))
,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 { u"Title"_ustr };
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( std::unique_lock<std::mutex>& /*rResultSetGuard*/, sal_uInt32 i_nIndex )
{
std::unique_lock 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( std::unique_lock<std::mutex>& rResultSetGuard, sal_uInt32 i_nIndex )
{
std::unique_lock 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( rResultSetGuard, 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( std::unique_lock<std::mutex>& rResultSetGuard, sal_uInt32 i_nIndex )
{
std::unique_lock 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( rResultSetGuard, 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( std::unique_lock<std::mutex>& /*rResultSetGuard*/, sal_uInt32 i_nIndex )
{
std::unique_lock aGuard( m_aMutex );
// true if result already present.
return m_aResults.size() > i_nIndex;
}
sal_uInt32 DataSupplier::totalCount(std::unique_lock<std::mutex>& /*rResultSetGuard*/)
{
std::unique_lock aGuard( m_aMutex );
return m_aResults.size();
}
sal_uInt32 DataSupplier::currentCount()
{
return m_aResults.size();
}
bool DataSupplier::isCountFinal()
{
return true;
}
Reference< XRow > DataSupplier::queryPropertyValues( std::unique_lock<std::mutex>& rResultSetGuard, sal_uInt32 i_nIndex )
{
std::unique_lock 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( rResultSetGuard, 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 )
{
std::unique_lock 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: */
↑ V530 The return value of function 'append' is required to be utilized.
↑ V547 Expression '!i_rBaseURL.empty()' is always false.