blob: 4fd7047054c3fa275f494a06a3c86ed98bd292c8 [file] [log] [blame]
package org.apache.maven.indexer.examples.indexing;
/*
* 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.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Version;
import org.apache.maven.index.ArtifactContext;
import org.apache.maven.index.ArtifactInfo;
import org.apache.maven.index.ArtifactScanningListener;
import org.apache.maven.index.FlatSearchRequest;
import org.apache.maven.index.FlatSearchResponse;
import org.apache.maven.index.Indexer;
import org.apache.maven.index.MAVEN;
import org.apache.maven.index.Scanner;
import org.apache.maven.index.ScanningRequest;
import org.apache.maven.index.ScanningResult;
import org.apache.maven.index.context.IndexCreator;
import org.apache.maven.index.context.IndexingContext;
import org.apache.maven.index.expr.SourcedSearchExpression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.apache.lucene.search.BooleanClause.Occur.MUST;
/**
* This class provides means to index and search for artifacts in a repository on the file system.
*
* @author mtodorov
*/
public class RepositoryIndexer
{
private static final Logger LOGGER = LoggerFactory.getLogger( RepositoryIndexer.class );
private static final String[] luceneFields = new String[]{ "g", "a", "v", "p", "c" };
private static final WhitespaceAnalyzer luceneAnalyzer = new WhitespaceAnalyzer( );
private Indexer indexer;
private Scanner scanner;
private List<IndexCreator> indexers;
private IndexingContext indexingContext;
private String repositoryId;
private File repositoryBasedir;
private File indexDir;
public RepositoryIndexer()
{
// no op
}
public void close()
throws IOException
{
indexer.closeIndexingContext( indexingContext, false );
}
public void close( boolean deleteFiles )
throws IOException
{
indexingContext.close( deleteFiles );
}
public void delete( final Collection<ArtifactInfo> artifacts )
throws IOException
{
final List<ArtifactContext> delete = new ArrayList<>();
for ( final ArtifactInfo artifact : artifacts )
{
LOGGER.debug( "Deleting artifact: {}; ctx id: {}; idx dir: {}",
new String[]{ artifact.toString(), indexingContext.getId(),
indexingContext.getIndexDirectory().toString() } );
delete.add( new ArtifactContext( null, null, null, artifact, null ) );
}
getIndexer().deleteArtifactsFromIndex( delete, indexingContext );
}
public Set<ArtifactInfo> search( final String groupId, final String artifactId, final String version,
final String packaging, final String classifier )
throws IOException
{
final BooleanQuery query = new BooleanQuery();
if ( groupId != null )
{
query.add( getIndexer().constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( groupId ) ), MUST );
}
if ( artifactId != null )
{
query.add( getIndexer().constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( artifactId ) ),
MUST );
}
if ( version != null )
{
query.add( getIndexer().constructQuery( MAVEN.VERSION, new SourcedSearchExpression( version ) ), MUST );
}
if ( packaging != null )
{
query.add( getIndexer().constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( packaging ) ), MUST );
}
else
{
// Fallback to jar
query.add( getIndexer().constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "jar" ) ), MUST );
}
if ( classifier != null )
{
query.add( getIndexer().constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( classifier ) ),
MUST );
}
LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
new String[]{ query.toString(), indexingContext.getId(),
indexingContext.getIndexDirectory().toString() } );
final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
LOGGER.info( "Hit count: {}", response.getReturnedHitsCount() );
final Set<ArtifactInfo> results = response.getResults();
if ( LOGGER.isDebugEnabled() )
{
for ( final ArtifactInfo result : results )
{
LOGGER.debug( "Found artifact: {}", result.toString() );
}
}
return results;
}
public Set<ArtifactInfo> search( final String queryText )
throws ParseException, IOException
{
final Query query = new MultiFieldQueryParser( luceneFields, luceneAnalyzer ).parse( queryText );
LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
new String[]{ query.toString(), indexingContext.getId(),
indexingContext.getIndexDirectory().toString() } );
final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
final Set<ArtifactInfo> results = response.getResults();
if ( LOGGER.isDebugEnabled() )
{
LOGGER.debug( "Hit count: {}", response.getReturnedHitsCount() );
for ( final ArtifactInfo result : results )
{
LOGGER.debug( "Found artifact: {}; uinfo: {}", result.toString(), result.getUinfo() );
}
}
return results;
}
public Set<ArtifactInfo> searchBySHA1( final String checksum )
throws IOException
{
final BooleanQuery query = new BooleanQuery();
query.add( getIndexer().constructQuery( MAVEN.SHA1, new SourcedSearchExpression( checksum ) ), MUST );
LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
new String[]{ query.toString(), indexingContext.getId(),
indexingContext.getIndexDirectory().toString() } );
final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
LOGGER.info( "Hit count: {}", response.getReturnedHitsCount() );
final Set<ArtifactInfo> results = response.getResults();
if ( LOGGER.isDebugEnabled() )
{
for ( final ArtifactInfo result : results )
{
LOGGER.debug( "Found artifact: {}", result.toString() );
}
}
return results;
}
public int index( final File startingPath )
{
final ScanningResult scan = getScanner().scan(
new ScanningRequest( indexingContext, new ReindexArtifactScanningListener(),
startingPath == null ? "." : startingPath.getPath() ) );
return scan.getTotalFiles();
}
public void addArtifactToIndex( final File artifactFile, final ArtifactInfo artifactInfo )
throws IOException
{
getIndexer().addArtifactsToIndex( asList( new ArtifactContext( null, artifactFile, null, artifactInfo, null ) ),
indexingContext );
}
public void addArtifactToIndex( String repository, File artifactFile, String groupId, String artifactId,
String version, String extension, String classifier )
throws IOException
{
ArtifactInfo artifactInfo = new ArtifactInfo( repository, groupId, artifactId, version, classifier, extension );
if ( extension != null )
{
artifactInfo.setFieldValue( MAVEN.EXTENSION, extension );
}
LOGGER.debug( "Adding artifact: {}; repo: {}; type: {}",
new String[]{ artifactInfo.getUinfo(), repository, extension } );
getIndexer().addArtifactsToIndex(
asList( new ArtifactContext( null, artifactFile, null, artifactInfo, artifactInfo.calculateGav() ) ),
indexingContext );
}
private class ReindexArtifactScanningListener
implements ArtifactScanningListener
{
int totalFiles = 0;
private IndexingContext context;
@Override
public void scanningStarted( final IndexingContext context )
{
this.context = context;
}
@Override
public void scanningFinished( final IndexingContext context, final ScanningResult result )
{
result.setTotalFiles( totalFiles );
LOGGER.debug( "Scanning finished; total files: {}; has exception: {}", result.getTotalFiles(),
result.hasExceptions() );
}
@Override
public void artifactError( final ArtifactContext ac, final Exception ex )
{
LOGGER.error( "Artifact error!", ex );
}
@Override
public void artifactDiscovered( final ArtifactContext ac )
{
try
{
LOGGER.debug( "Adding artifact gav: {}; ctx id: {}; idx dir: {}",
new String[]{ ac.getGav().toString(), context.getId(),
context.getIndexDirectory().toString() } );
getIndexer().addArtifactsToIndex( asList( ac ), context );
totalFiles++;
}
catch ( IOException ex )
{
LOGGER.error( "Artifact index error", ex );
}
}
}
public Indexer getIndexer()
{
return indexer;
}
public void setIndexer( Indexer indexer )
{
this.indexer = indexer;
}
public Scanner getScanner()
{
return scanner;
}
public void setScanner( Scanner scanner )
{
this.scanner = scanner;
}
public List<IndexCreator> getIndexers()
{
return indexers;
}
public void setIndexers( List<IndexCreator> indexers )
{
this.indexers = indexers;
}
public IndexingContext getIndexingContext()
{
return indexingContext;
}
public void setIndexingContext( IndexingContext indexingContext )
{
this.indexingContext = indexingContext;
}
public String getRepositoryId()
{
return repositoryId;
}
public void setRepositoryId( String repositoryId )
{
this.repositoryId = repositoryId;
}
public File getRepositoryBasedir()
{
return repositoryBasedir;
}
public void setRepositoryBasedir( File repositoryBasedir )
{
this.repositoryBasedir = repositoryBasedir;
}
public File getIndexDir()
{
return indexDir;
}
public void setIndexDir( File indexDir )
{
this.indexDir = indexDir;
}
}