1 package org.apache.archiva.maven.scheduler.indexing;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
21 import org.apache.archiva.indexer.ArchivaIndexingContext;
22 import org.apache.archiva.indexer.UnsupportedBaseContextException;
23 import org.apache.archiva.components.taskqueue.Task;
24 import org.apache.archiva.components.taskqueue.execution.TaskExecutionException;
25 import org.apache.archiva.components.taskqueue.execution.TaskExecutor;
26 import org.apache.archiva.repository.ManagedRepository;
27 import org.apache.archiva.repository.features.IndexCreationFeature;
28 import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
29 import org.apache.maven.index.ArtifactContext;
30 import org.apache.maven.index.ArtifactContextProducer;
31 import org.apache.maven.index.DefaultScannerListener;
32 import org.apache.maven.index.FlatSearchRequest;
33 import org.apache.maven.index.FlatSearchResponse;
34 import org.apache.maven.index.Indexer;
35 import org.apache.maven.index.IndexerEngine;
36 import org.apache.maven.index.MAVEN;
37 import org.apache.maven.index.Scanner;
38 import org.apache.maven.index.ScanningRequest;
39 import org.apache.maven.index.ScanningResult;
40 import org.apache.maven.index.context.IndexingContext;
41 import org.apache.maven.index.expr.SourcedSearchExpression;
42 import org.apache.maven.index.packer.IndexPacker;
43 import org.apache.maven.index.packer.IndexPackingRequest;
44 import org.apache.maven.index_shaded.lucene.search.BooleanClause;
45 import org.apache.maven.index_shaded.lucene.search.BooleanQuery;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.stereotype.Service;
50 import javax.inject.Inject;
51 import java.io.IOException;
52 import java.nio.file.Path;
55 * ArchivaIndexingTaskExecutor Executes all indexing tasks. Adding, updating and removing artifacts from the index are
56 * all performed by this executor. Add and update artifact in index tasks are added in the indexing task queue by the
57 * NexusIndexerConsumer while remove artifact from index tasks are added by the LuceneCleanupRemoveIndexedConsumer.
59 @Service( "taskExecutor#indexing" )
60 public class ArchivaIndexingTaskExecutor
61 implements TaskExecutor
63 private Logger log = LoggerFactory.getLogger( ArchivaIndexingTaskExecutor.class );
66 private IndexPacker indexPacker;
69 private ArtifactContextProducer artifactContextProducer;
72 private Indexer indexer;
75 private Scanner scanner;
78 IndexerEngine indexerEngine;
81 * depending on current {@link Task} you have.
82 * If {@link org.apache.archiva.scheduler.indexing.ArtifactIndexingTask.Action#FINISH} && isExecuteOnEntireRepo:
83 * repository will be scanned.
86 * @throws TaskExecutionException
89 public void executeTask( Task task )
90 throws TaskExecutionException
92 ArtifactIndexingTask indexingTask = (ArtifactIndexingTask) task;
94 ManagedRepository repository = indexingTask.getRepository( );
95 ArchivaIndexingContext archivaContext = indexingTask.getContext( );
96 IndexingContext context = null;
99 context = archivaContext.getBaseContext( IndexingContext.class );
101 catch ( UnsupportedBaseContextException e )
103 throw new TaskExecutionException( "Bad repository type.", e );
106 if ( ArtifactIndexingTask.Action.FINISH.equals( indexingTask.getAction( ) )
107 && indexingTask.isExecuteOnEntireRepo( ) )
109 long start = System.currentTimeMillis( );
112 context.updateTimestamp( );
113 DefaultScannerListener listener = new DefaultScannerListener( context, indexerEngine, true, null );
114 ScanningRequest request = new ScanningRequest( context, listener );
115 ScanningResult result = scanner.scan( request );
116 if ( result.hasExceptions( ) )
118 log.error( "Exceptions occured during index scan of " + context.getId( ) );
119 result.getExceptions( ).stream( ).map( e -> e.getMessage( ) ).distinct( ).limit( 5 ).forEach(
120 s -> log.error( "Message: " + s )
124 catch ( IOException e )
126 log.error( "Error during context scan {}: {}", context.getId( ), context.getIndexDirectory( ) );
128 long end = System.currentTimeMillis( );
129 log.info( "indexed maven repository: {}, onlyUpdate: {}, time {} ms", repository.getId( ),
130 indexingTask.isOnlyUpdate( ), ( end - start ) );
131 log.debug( "Finishing indexing task on repo: {}", repository.getId( ) );
132 finishIndexingTask( indexingTask, repository, context );
136 // create context if not a repo scan request
137 if ( !indexingTask.isExecuteOnEntireRepo( ) )
141 log.debug( "Creating indexing context on resource: {}", //
142 ( indexingTask.getResourceFile( ) == null
144 : indexingTask.getResourceFile( ) ) );
145 archivaContext = repository.getIndexingContext( );
146 context = archivaContext.getBaseContext( IndexingContext.class );
148 catch ( UnsupportedBaseContextException e )
150 log.error( "Error occurred while creating context: {}", e.getMessage( ) );
151 throw new TaskExecutionException( "Error occurred while creating context: " + e.getMessage( ), e );
155 if ( context == null || context.getIndexDirectory( ) == null )
157 throw new TaskExecutionException( "Trying to index an artifact but the context is already closed" );
162 Path artifactFile = indexingTask.getResourceFile( );
163 if ( artifactFile == null )
165 log.debug( "no artifact pass in indexing task so skip it" );
169 ArtifactContext ac = artifactContextProducer.getArtifactContext( context, artifactFile.toFile( ) );
173 // MRM-1779 pom must be indexed too
174 // TODO make that configurable?
175 if ( artifactFile.getFileName( ).toString( ).endsWith( ".pom" ) )
177 ac.getArtifactInfo( ).setFileExtension( "pom" );
178 ac.getArtifactInfo( ).setPackaging( "pom" );
179 ac.getArtifactInfo( ).setClassifier( "pom" );
181 if ( indexingTask.getAction( ).equals( ArtifactIndexingTask.Action.ADD ) )
183 //IndexSearcher s = context.getIndexSearcher();
184 //String uinfo = ac.getArtifactInfo().getUinfo();
185 //TopDocs d = s.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), 1 );
187 BooleanQuery.Builder qb = new BooleanQuery.Builder();
188 qb.add( indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression(
189 ac.getArtifactInfo( ).getGroupId( ) ) ), BooleanClause.Occur.MUST );
190 qb.add( indexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression(
191 ac.getArtifactInfo( ).getArtifactId( ) ) ), BooleanClause.Occur.MUST );
192 qb.add( indexer.constructQuery( MAVEN.VERSION, new SourcedSearchExpression(
193 ac.getArtifactInfo( ).getVersion( ) ) ), BooleanClause.Occur.MUST );
194 if ( ac.getArtifactInfo( ).getClassifier( ) != null )
196 qb.add( indexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression(
197 ac.getArtifactInfo( ).getClassifier( ) ) ), BooleanClause.Occur.MUST );
199 if ( ac.getArtifactInfo( ).getPackaging( ) != null )
201 qb.add( indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression(
202 ac.getArtifactInfo( ).getPackaging( ) ) ), BooleanClause.Occur.MUST );
204 FlatSearchRequest flatSearchRequest = new FlatSearchRequest( qb.build(), context );
205 FlatSearchResponse flatSearchResponse = indexer.searchFlat( flatSearchRequest );
206 if ( flatSearchResponse.getResults( ).isEmpty( ) )
208 log.debug( "Adding artifact '{}' to index..", ac.getArtifactInfo( ) );
209 indexerEngine.index( context, ac );
213 log.debug( "Updating artifact '{}' in index..", ac.getArtifactInfo( ) );
214 // TODO check if update exists !!
215 indexerEngine.update( context, ac );
218 context.updateTimestamp( );
225 log.debug( "Removing artifact '{}' from index..", ac.getArtifactInfo( ) );
226 indexerEngine.remove( context, ac );
230 // close the context if not a repo scan request
231 if ( !indexingTask.isExecuteOnEntireRepo( ) )
233 log.debug( "Finishing indexing task on resource file : {}", indexingTask.getResourceFile( ) != null
234 ? indexingTask.getResourceFile( )
236 finishIndexingTask( indexingTask, repository, context );
239 catch ( IOException e )
241 log.error( "Error occurred while executing indexing task '{}': {}", indexingTask, e.getMessage( ),
243 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'",
250 private void finishIndexingTask( ArtifactIndexingTask indexingTask, ManagedRepository repository,
251 IndexingContext context )
252 throws TaskExecutionException
257 log.debug( "Finishing indexing" );
260 if ( repository.supportsFeature( IndexCreationFeature.class ) )
262 IndexCreationFeature icf = repository.getFeature( IndexCreationFeature.class ).get( );
263 if ( !icf.isSkipPackedIndexCreation( ) && icf.getLocalPackedIndexPath( ) != null && icf.getLocalIndexPath().getFilePath()!=null )
266 log.debug( "Creating packed index from {} on {}", context.getIndexDirectoryFile( ), icf.getLocalPackedIndexPath( ) );
267 IndexPackingRequest request = new IndexPackingRequest( context, //
268 context.acquireIndexSearcher( ).getIndexReader( ),
270 icf.getLocalPackedIndexPath( ).getFilePath().toFile( ) );
272 indexPacker.packIndex( request );
273 context.updateTimestamp( true );
275 log.debug( "Index file packed at '{}'.", icf.getLocalPackedIndexPath( ) );
279 log.debug( "skip packed index creation" );
284 log.debug( "skip packed index creation" );
287 catch ( IOException e )
289 log.error( "Error occurred while executing indexing task '{}': {}", indexingTask, e.getMessage( ) );
290 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'",
295 public void setIndexPacker( IndexPacker indexPacker )
297 this.indexPacker = indexPacker;