package org.apache.archiva.scheduler.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 Li * cense 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.admin.model.RepositoryAdminException; import org.apache.archiva.admin.model.beans.ManagedRepository; import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; import org.apache.archiva.common.plexusbridge.PlexusSisuBridge; import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException; import org.apache.archiva.redback.components.taskqueue.Task; import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException; import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.maven.index.ArtifactContext; import org.apache.maven.index.ArtifactContextProducer; import org.apache.maven.index.FlatSearchRequest; import org.apache.maven.index.FlatSearchResponse; import org.apache.maven.index.MAVEN; import org.apache.maven.index.NexusIndexer; import org.apache.maven.index.context.IndexingContext; import org.apache.maven.index.expr.SourcedSearchExpression; import org.apache.maven.index.packer.IndexPacker; import org.apache.maven.index.packer.IndexPackingRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.inject.Inject; import java.io.File; import java.io.IOException; /** * ArchivaIndexingTaskExecutor Executes all indexing tasks. Adding, updating and removing artifacts from the index are * all performed by this executor. Add and update artifact in index tasks are added in the indexing task queue by the * NexusIndexerConsumer while remove artifact from index tasks are added by the LuceneCleanupRemoveIndexedConsumer. */ @Service ( "taskExecutor#indexing" ) public class ArchivaIndexingTaskExecutor implements TaskExecutor { private Logger log = LoggerFactory.getLogger( ArchivaIndexingTaskExecutor.class ); private IndexPacker indexPacker; private ArtifactContextProducer artifactContextProducer; @Inject private PlexusSisuBridge plexusSisuBridge; @Inject private ManagedRepositoryAdmin managedRepositoryAdmin; private NexusIndexer nexusIndexer; @PostConstruct public void initialize() throws PlexusSisuBridgeException { log.info( "Initialized {}", this.getClass().getName() ); artifactContextProducer = plexusSisuBridge.lookup( ArtifactContextProducer.class ); indexPacker = plexusSisuBridge.lookup( IndexPacker.class, "default" ); nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class ); } /** * depending on current {@link Task} you have. * If {@link org.apache.archiva.scheduler.indexing.ArtifactIndexingTask.Action#FINISH} && isExecuteOnEntireRepo: * repository will be scanned. * * @param task * @throws TaskExecutionException */ @Override public void executeTask( Task task ) throws TaskExecutionException { ArtifactIndexingTask indexingTask = (ArtifactIndexingTask) task; ManagedRepository repository = indexingTask.getRepository(); IndexingContext context = indexingTask.getContext(); if ( ArtifactIndexingTask.Action.FINISH.equals( indexingTask.getAction() ) && indexingTask.isExecuteOnEntireRepo() ) { try { long start = System.currentTimeMillis(); nexusIndexer.scan( context, null, indexingTask.isOnlyUpdate() ); long end = System.currentTimeMillis(); log.info( "indexed maven repository: {}, onlyUpdate: {}, time {} ms", repository.getId(), indexingTask.isOnlyUpdate(), ( end - start ) ); } catch ( IOException e ) { throw new TaskExecutionException( "Error scan repository " + repository, e ); } log.debug( "Finishing indexing task on repo: {}", repository.getId() ); finishIndexingTask( indexingTask, repository, context ); } else { // create context if not a repo scan request if ( !indexingTask.isExecuteOnEntireRepo() ) { try { log.debug( "Creating indexing context on resource: {}", ( indexingTask.getResourceFile() == null ? "none" : indexingTask.getResourceFile().getPath() ) ); context = managedRepositoryAdmin.createIndexContext( repository ); } catch ( RepositoryAdminException e ) { log.error( "Error occurred while creating context: " + e.getMessage() ); throw new TaskExecutionException( "Error occurred while creating context: " + e.getMessage(), e ); } } if ( context == null || context.getIndexDirectory() == null ) { throw new TaskExecutionException( "Trying to index an artifact but the context is already closed" ); } try { File artifactFile = indexingTask.getResourceFile(); if ( artifactFile == null ) { log.debug( "no artifact pass in indexing task so skip it" ); } else { ArtifactContext ac = artifactContextProducer.getArtifactContext( context, artifactFile ); if ( ac != null ) { // MRM-1779 pom must be indexed too // TODO make that configurable? if ( artifactFile.getPath().endsWith( ".pom" ) ) { ac.getArtifactInfo().fextension = "pom"; ac.getArtifactInfo().packaging = "pom"; ac.getArtifactInfo().classifier = "pom"; } if ( indexingTask.getAction().equals( ArtifactIndexingTask.Action.ADD ) ) { //IndexSearcher s = context.getIndexSearcher(); //String uinfo = ac.getArtifactInfo().getUinfo(); //TopDocs d = s.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), 1 ); BooleanQuery q = new BooleanQuery(); q.add( nexusIndexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( ac.getArtifactInfo().groupId ) ), BooleanClause.Occur.MUST ); q.add( nexusIndexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( ac.getArtifactInfo().artifactId ) ), BooleanClause.Occur.MUST ); q.add( nexusIndexer.constructQuery( MAVEN.VERSION, new SourcedSearchExpression( ac.getArtifactInfo().version ) ), BooleanClause.Occur.MUST ); if ( ac.getArtifactInfo().classifier != null ) { q.add( nexusIndexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( ac.getArtifactInfo().classifier ) ), BooleanClause.Occur.MUST ); } if ( ac.getArtifactInfo().packaging != null ) { q.add( nexusIndexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( ac.getArtifactInfo().packaging ) ), BooleanClause.Occur.MUST ); } FlatSearchRequest flatSearchRequest = new FlatSearchRequest( q, context ); FlatSearchResponse flatSearchResponse = nexusIndexer.searchFlat( flatSearchRequest ); if ( flatSearchResponse.getResults().isEmpty() ) { log.debug( "Adding artifact '{}' to index..", ac.getArtifactInfo() ); nexusIndexer.addArtifactToIndex( ac, context ); } else { log.debug( "Updating artifact '{}' in index..", ac.getArtifactInfo() ); // TODO check if update exists !! nexusIndexer.deleteArtifactFromIndex( ac, context ); nexusIndexer.addArtifactToIndex( ac, context ); } context.updateTimestamp(); context.commit(); } else { log.debug( "Removing artifact '{}' from index..", ac.getArtifactInfo() ); nexusIndexer.deleteArtifactFromIndex( ac, context ); } } } // close the context if not a repo scan request if ( !indexingTask.isExecuteOnEntireRepo() ) { log.debug( "Finishing indexing task on resource file : {}", indexingTask.getResourceFile() != null ? indexingTask.getResourceFile().getPath() : " none " ); finishIndexingTask( indexingTask, repository, context ); } } catch ( IOException e ) { log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage(), e ); throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", e ); } } } private void finishIndexingTask( ArtifactIndexingTask indexingTask, ManagedRepository repository, IndexingContext context ) throws TaskExecutionException { try { context.optimize(); if ( !repository.isSkipPackedIndexCreation() ) { IndexPackingRequest request = new IndexPackingRequest( context, context.getIndexDirectoryFile() ); indexPacker.packIndex( request ); context.updateTimestamp( true ); log.debug( "Index file packaged at '{}'.", context.getIndexDirectoryFile() ); } else { log.debug( "skip packed index creation" ); } } catch ( IOException e ) { log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage() ); throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", e ); } } public void setIndexPacker( IndexPacker indexPacker ) { this.indexPacker = indexPacker; } public PlexusSisuBridge getPlexusSisuBridge() { return plexusSisuBridge; } public void setPlexusSisuBridge( PlexusSisuBridge plexusSisuBridge ) { this.plexusSisuBridge = plexusSisuBridge; } }