org.apache.archiva.rest.services.DefaultSearchService Maven / Gradle / Ivy
package org.apache.archiva.rest.services;
/*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.indexer.search.RepositorySearch;
import org.apache.archiva.indexer.search.RepositorySearchException;
import org.apache.archiva.indexer.search.SearchFields;
import org.apache.archiva.indexer.search.SearchResultHit;
import org.apache.archiva.indexer.search.SearchResultLimits;
import org.apache.archiva.indexer.search.SearchResults;
import org.apache.archiva.maven2.model.Artifact;
import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.archiva.metadata.repository.MetadataRepositoryException;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.metadata.repository.RepositorySessionFactory;
import org.apache.archiva.rest.api.model.ChecksumSearch;
import org.apache.archiva.rest.api.model.GroupIdList;
import org.apache.archiva.rest.api.model.SearchRequest;
import org.apache.archiva.rest.api.model.StringList;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.rest.api.services.SearchService;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
/**
* @author Olivier Lamy
*/
@Service( "searchService#rest" )
public class DefaultSearchService
extends AbstractRestService
implements SearchService
{
private static final String LATEST_KEYWORD = "LATEST";
@Inject
private RepositorySearch repositorySearch;
@Inject
private RepositorySessionFactory repositorySessionFactory;
@Override
public List quickSearch( String queryString )
throws ArchivaRestServiceException
{
if ( StringUtils.isBlank( queryString ) )
{
return Collections.emptyList( );
}
SearchResultLimits limits = new SearchResultLimits( 0 );
try
{
SearchResults searchResults =
repositorySearch.search( getPrincipal( ), getObservableRepos( ), queryString, limits,
Collections.emptyList( ) );
return getArtifacts( searchResults );
}
catch ( RepositorySearchException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
@Override
public List quickSearchWithRepositories( SearchRequest searchRequest )
throws ArchivaRestServiceException
{
String queryString = searchRequest.getQueryTerms( );
if ( StringUtils.isBlank( queryString ) )
{
return Collections.emptyList( );
}
List repositories = searchRequest.getRepositories( );
if ( repositories == null || repositories.isEmpty( ) )
{
repositories = getObservableRepos( );
}
SearchResultLimits limits =
new SearchResultLimits( searchRequest.getPageSize( ), searchRequest.getSelectedPage( ) );
try
{
SearchResults searchResults = repositorySearch.search( getPrincipal( ), repositories, queryString, limits,
Collections.emptyList( ) );
return getArtifacts( searchResults );
}
catch ( RepositorySearchException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
@Override
public List getArtifactVersions( String groupId, String artifactId, String packaging )
throws ArchivaRestServiceException
{
if ( StringUtils.isBlank( groupId ) || StringUtils.isBlank( artifactId ) )
{
return Collections.emptyList( );
}
SearchFields searchField = new SearchFields( );
searchField.setGroupId( groupId );
searchField.setArtifactId( artifactId );
searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
searchField.setRepositories( getObservableRepos( ) );
try
{
SearchResults searchResults = repositorySearch.search( getPrincipal( ), searchField, null );
return getArtifacts( searchResults );
}
catch ( RepositorySearchException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
@Override
public List searchArtifacts( SearchRequest searchRequest )
throws ArchivaRestServiceException
{
if ( searchRequest == null )
{
return Collections.emptyList( );
}
SearchFields searchField = getModelMapper( ).map( searchRequest, SearchFields.class );
SearchResultLimits limits = new SearchResultLimits( 0 );
limits.setPageSize( searchRequest.getPageSize( ) );
// if no repos set we use ones available for the user
if ( searchField.getRepositories( ) == null || searchField.getRepositories( ).isEmpty( ) )
{
searchField.setRepositories( getObservableRepos( ) );
}
try
{
SearchResults searchResults = repositorySearch.search( getPrincipal( ), searchField, limits );
return getArtifacts( searchResults );
}
catch ( RepositorySearchException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
@Override
public GroupIdList getAllGroupIds( List selectedRepos )
throws ArchivaRestServiceException
{
List observableRepos = getObservableRepos( );
List repos = ListUtils.intersection( observableRepos, selectedRepos );
if ( repos == null || repos.isEmpty( ) )
{
return new GroupIdList( Collections.emptyList( ) );
}
try
{
return new GroupIdList( new ArrayList<>( repositorySearch.getAllGroupIds( getPrincipal( ), repos ) ) );
}
catch ( RepositorySearchException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
public List getArtifactByChecksum( ChecksumSearch checksumSearch )
throws ArchivaRestServiceException
{
// if no repos set we use ones available for the user
if ( checksumSearch.getRepositories( ) == null || checksumSearch.getRepositories( ).isEmpty( ) )
{
checksumSearch.setRepositories( getObservableRepos( ) );
}
RepositorySession repositorySession = repositorySessionFactory.createSession( );
MetadataRepository metadataRepository = repositorySession.getRepository( );
Set artifactSet = new HashSet<>( );
try
{
for ( String repoId : checksumSearch.getRepositories( ) )
{
Collection artifactMetadatas =
metadataRepository.getArtifactsByChecksum( repoId, checksumSearch.getChecksum( ) );
artifactSet.addAll( buildArtifacts( artifactMetadatas, repoId ) );
}
return new ArrayList<>( artifactSet );
}
catch ( MetadataRepositoryException e )
{
log.error( e.getMessage( ), e );
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
finally
{
repositorySession.closeQuietly( );
}
}
@Override
public StringList getObservablesRepoIds( )
throws ArchivaRestServiceException
{
return new StringList( getObservableRepos( ) );
}
@Override
public Response redirectToArtifactFile( String repositoryId, String groupId, String artifactId, String version,
String packaging, String classifier, Boolean literalVersion )
throws ArchivaRestServiceException
{
try
{
// validate query
if ( StringUtils.isEmpty( groupId ) )
{
return Response.status( new Response.StatusType( )
{
@Override
public int getStatusCode( )
{
return Response.Status.BAD_REQUEST.getStatusCode( );
}
@Override
public Response.Status.Family getFamily( )
{
return Response.Status.BAD_REQUEST.getFamily( );
}
@Override
public String getReasonPhrase( )
{
return "groupId mandatory";
}
} ).build( );
}
if ( StringUtils.isEmpty( version ) )
{
return Response.status( new Response.StatusType( )
{
@Override
public int getStatusCode( )
{
return Response.Status.BAD_REQUEST.getStatusCode( );
}
@Override
public Response.Status.Family getFamily( )
{
return Response.Status.BAD_REQUEST.getFamily( );
}
@Override
public String getReasonPhrase( )
{
return "version mandatory";
}
} ).build( );
}
if ( StringUtils.isEmpty( artifactId ) )
{
return Response.status( new Response.StatusType( )
{
@Override
public int getStatusCode( )
{
return Response.Status.BAD_REQUEST.getStatusCode( );
}
@Override
public Response.Status.Family getFamily( )
{
return Response.Status.BAD_REQUEST.getFamily( );
}
@Override
public String getReasonPhrase( )
{
return "artifactId mandatory";
}
} ).build( );
}
SearchFields searchField = new SearchFields( );
searchField.setGroupId( groupId );
searchField.setArtifactId( artifactId );
searchField.setPackaging( StringUtils.isBlank( packaging ) ? "jar" : packaging );
if ( literalVersion.booleanValue( ) || !StringUtils.equals( version, LATEST_KEYWORD ) )
{
searchField.setVersion( version );
}
searchField.setClassifier( classifier );
List userRepos = getObservablesRepoIds( ).getStrings( );
searchField.setRepositories(
StringUtils.isEmpty( repositoryId ) ? userRepos : Arrays.asList( repositoryId ) );
log.debug( "Searching repository {}", repositoryId );
searchField.setExactSearch( true );
SearchResults searchResults = repositorySearch.search( getPrincipal( ), searchField, null );
List artifacts = getArtifacts( searchResults, repositoryId );
if ( artifacts.isEmpty( ) )
{
return Response.status( new Response.StatusType( )
{
@Override
public int getStatusCode( )
{
return Response.Status.NO_CONTENT.getStatusCode( );
}
@Override
public Response.Status.Family getFamily( )
{
return Response.Status.NO_CONTENT.getFamily( );
}
@Override
public String getReasonPhrase( )
{
return "your query doesn't return any artifact";
}
} ).build( );
}
// TODO improve that with querying lucene with null value for classifier
// so simple loop and retain only artifact with null classifier
if ( classifier == null )
{
List filteredArtifacts = new ArrayList<>( artifacts.size( ) );
for ( Artifact artifact : artifacts )
{
if ( artifact.getClassifier( ) == null )
{
filteredArtifacts.add( artifact );
}
}
artifacts = filteredArtifacts;
}
// TODO return json result of the query ?
if ( artifacts.size( ) > 1 && ( literalVersion || !StringUtils.equals( version, LATEST_KEYWORD ) ) )
{
return Response.status( new Response.StatusType( )
{
@Override
public int getStatusCode( )
{
return Response.Status.BAD_REQUEST.getStatusCode( );
}
@Override
public Response.Status.Family getFamily( )
{
return Response.Status.BAD_REQUEST.getFamily( );
}
@Override
public String getReasonPhrase( )
{
return "your query return more than one artifact";
}
} ).build( );
}
// version is LATEST so we have to find the latest one from the result
if ( !literalVersion && ( artifacts.size( ) > 1 && StringUtils.equals( version, LATEST_KEYWORD ) ) )
{
TreeMap artifactPerVersion = new TreeMap<>( VersionComparator.getInstance( ) );
for ( Artifact artifact : artifacts )
{
artifactPerVersion.put( artifact.getVersion( ), artifact );
}
return Response.temporaryRedirect(
new URI( artifactPerVersion.lastEntry( ).getValue( ).getUrl( ) ) ).build( );
}
Artifact artifact = artifacts.get( 0 );
log.debug( "Returning artifact {}, {}", artifact.getUrl( ), artifact.getRepositoryId( ) );
return Response.temporaryRedirect( new URI( artifact.getUrl( ) ) ).build( );
}
catch ( Exception e )
{
throw new ArchivaRestServiceException( e.getMessage( ), e );
}
}
protected List getArtifacts( SearchResults searchResults )
throws ArchivaRestServiceException
{
return getArtifacts( searchResults, null );
}
//-------------------------------------
// internal
//-------------------------------------
protected List getArtifacts( SearchResults searchResults, String repositoryId )
throws ArchivaRestServiceException
{
if ( searchResults == null || searchResults.isEmpty() )
{
return Collections.emptyList();
}
List artifacts = new ArrayList<>( searchResults.getReturnedHitsCount() );
for ( SearchResultHit hit : searchResults.getHits() )
{
// duplicate Artifact one per available version
if ( hit.getVersions().size() > 0 )
{
for ( String version : hit.getVersions() )
{
Artifact versionned = getModelMapper().map( hit, Artifact.class );
if ( StringUtils.isNotBlank( version ) )
{
versionned.setVersion( version );
versionned.setUrl( getArtifactUrl( versionned, repositoryId ) );
artifacts.add( versionned );
}
}
}
}
return artifacts;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy