001package org.apache.archiva.scheduler.indexing; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the Li 016 * cense is distributed on an 017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 018 * KIND, either express or implied. See the License for the 019 * specific language governing permissions and limitations 020 * under the License. 021 */ 022 023import org.apache.archiva.admin.model.RepositoryAdminException; 024import org.apache.archiva.admin.model.beans.ManagedRepository; 025import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 026import org.apache.archiva.common.plexusbridge.PlexusSisuBridge; 027import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException; 028import org.apache.archiva.redback.components.taskqueue.Task; 029import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException; 030import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor; 031import org.apache.lucene.search.BooleanClause; 032import org.apache.lucene.search.BooleanQuery; 033import org.apache.maven.index.ArtifactContext; 034import org.apache.maven.index.ArtifactContextProducer; 035import org.apache.maven.index.FlatSearchRequest; 036import org.apache.maven.index.FlatSearchResponse; 037import org.apache.maven.index.MAVEN; 038import org.apache.maven.index.NexusIndexer; 039import org.apache.maven.index.context.IndexingContext; 040import org.apache.maven.index.expr.SourcedSearchExpression; 041import org.apache.maven.index.packer.IndexPacker; 042import org.apache.maven.index.packer.IndexPackingRequest; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045import org.springframework.stereotype.Service; 046 047import javax.annotation.PostConstruct; 048import javax.inject.Inject; 049import java.io.File; 050import java.io.IOException; 051 052/** 053 * ArchivaIndexingTaskExecutor Executes all indexing tasks. Adding, updating and removing artifacts from the index are 054 * all performed by this executor. Add and update artifact in index tasks are added in the indexing task queue by the 055 * NexusIndexerConsumer while remove artifact from index tasks are added by the LuceneCleanupRemoveIndexedConsumer. 056 */ 057@Service ( "taskExecutor#indexing" ) 058public class ArchivaIndexingTaskExecutor 059 implements TaskExecutor 060{ 061 private Logger log = LoggerFactory.getLogger( ArchivaIndexingTaskExecutor.class ); 062 063 private IndexPacker indexPacker; 064 065 private ArtifactContextProducer artifactContextProducer; 066 067 @Inject 068 private PlexusSisuBridge plexusSisuBridge; 069 070 @Inject 071 private ManagedRepositoryAdmin managedRepositoryAdmin; 072 073 private NexusIndexer nexusIndexer; 074 075 @PostConstruct 076 public void initialize() 077 throws PlexusSisuBridgeException 078 { 079 log.info( "Initialized {}", this.getClass().getName() ); 080 081 artifactContextProducer = plexusSisuBridge.lookup( ArtifactContextProducer.class ); 082 083 indexPacker = plexusSisuBridge.lookup( IndexPacker.class, "default" ); 084 085 nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class ); 086 087 } 088 089 /** 090 * depending on current {@link Task} you have. 091 * If {@link org.apache.archiva.scheduler.indexing.ArtifactIndexingTask.Action#FINISH} && isExecuteOnEntireRepo: 092 * repository will be scanned. 093 * 094 * @param task 095 * @throws TaskExecutionException 096 */ 097 @Override 098 public void executeTask( Task task ) 099 throws TaskExecutionException 100 { 101 ArtifactIndexingTask indexingTask = (ArtifactIndexingTask) task; 102 103 ManagedRepository repository = indexingTask.getRepository(); 104 IndexingContext context = indexingTask.getContext(); 105 106 if ( ArtifactIndexingTask.Action.FINISH.equals( indexingTask.getAction() ) 107 && indexingTask.isExecuteOnEntireRepo() ) 108 { 109 try 110 { 111 long start = System.currentTimeMillis(); 112 nexusIndexer.scan( context, null, indexingTask.isOnlyUpdate() ); 113 long end = System.currentTimeMillis(); 114 log.info( "indexed maven repository: {}, onlyUpdate: {}, time {} ms", repository.getId(), 115 indexingTask.isOnlyUpdate(), ( end - start ) ); 116 } 117 catch ( IOException e ) 118 { 119 throw new TaskExecutionException( "Error scan repository " + repository, e ); 120 } 121 log.debug( "Finishing indexing task on repo: {}", repository.getId() ); 122 finishIndexingTask( indexingTask, repository, context ); 123 } 124 else 125 { 126 // create context if not a repo scan request 127 if ( !indexingTask.isExecuteOnEntireRepo() ) 128 { 129 try 130 { 131 log.debug( "Creating indexing context on resource: {}", ( indexingTask.getResourceFile() == null 132 ? "none" 133 : indexingTask.getResourceFile().getPath() ) ); 134 context = managedRepositoryAdmin.createIndexContext( repository ); 135 } 136 catch ( RepositoryAdminException e ) 137 { 138 log.error( "Error occurred while creating context: " + e.getMessage() ); 139 throw new TaskExecutionException( "Error occurred while creating context: " + e.getMessage(), e ); 140 } 141 } 142 143 if ( context == null || context.getIndexDirectory() == null ) 144 { 145 throw new TaskExecutionException( "Trying to index an artifact but the context is already closed" ); 146 } 147 148 try 149 { 150 File artifactFile = indexingTask.getResourceFile(); 151 if ( artifactFile == null ) 152 { 153 log.debug( "no artifact pass in indexing task so skip it" ); 154 } 155 else 156 { 157 ArtifactContext ac = artifactContextProducer.getArtifactContext( context, artifactFile ); 158 159 if ( ac != null ) 160 { 161 // MRM-1779 pom must be indexed too 162 // TODO make that configurable? 163 if ( artifactFile.getPath().endsWith( ".pom" ) ) 164 { 165 ac.getArtifactInfo().fextension = "pom"; 166 ac.getArtifactInfo().packaging = "pom"; 167 ac.getArtifactInfo().classifier = "pom"; 168 } 169 if ( indexingTask.getAction().equals( ArtifactIndexingTask.Action.ADD ) ) 170 { 171 //IndexSearcher s = context.getIndexSearcher(); 172 //String uinfo = ac.getArtifactInfo().getUinfo(); 173 //TopDocs d = s.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), 1 ); 174 175 BooleanQuery q = new BooleanQuery(); 176 q.add( nexusIndexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( 177 ac.getArtifactInfo().groupId ) ), BooleanClause.Occur.MUST ); 178 q.add( nexusIndexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( 179 ac.getArtifactInfo().artifactId ) ), BooleanClause.Occur.MUST ); 180 q.add( nexusIndexer.constructQuery( MAVEN.VERSION, new SourcedSearchExpression( 181 ac.getArtifactInfo().version ) ), BooleanClause.Occur.MUST ); 182 if ( ac.getArtifactInfo().classifier != null ) 183 { 184 q.add( nexusIndexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( 185 ac.getArtifactInfo().classifier ) ), BooleanClause.Occur.MUST ); 186 } 187 if ( ac.getArtifactInfo().packaging != null ) 188 { 189 q.add( nexusIndexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( 190 ac.getArtifactInfo().packaging ) ), BooleanClause.Occur.MUST ); 191 } 192 FlatSearchRequest flatSearchRequest = new FlatSearchRequest( q, context ); 193 FlatSearchResponse flatSearchResponse = nexusIndexer.searchFlat( flatSearchRequest ); 194 if ( flatSearchResponse.getResults().isEmpty() ) 195 { 196 log.debug( "Adding artifact '{}' to index..", ac.getArtifactInfo() ); 197 nexusIndexer.addArtifactToIndex( ac, context ); 198 } 199 else 200 { 201 log.debug( "Updating artifact '{}' in index..", ac.getArtifactInfo() ); 202 // TODO check if update exists !! 203 nexusIndexer.deleteArtifactFromIndex( ac, context ); 204 nexusIndexer.addArtifactToIndex( ac, context ); 205 } 206 207 context.updateTimestamp(); 208 context.commit(); 209 210 211 } 212 else 213 { 214 log.debug( "Removing artifact '{}' from index..", ac.getArtifactInfo() ); 215 nexusIndexer.deleteArtifactFromIndex( ac, context ); 216 } 217 } 218 } 219 // close the context if not a repo scan request 220 if ( !indexingTask.isExecuteOnEntireRepo() ) 221 { 222 log.debug( "Finishing indexing task on resource file : {}", indexingTask.getResourceFile() != null 223 ? indexingTask.getResourceFile().getPath() 224 : " none " ); 225 finishIndexingTask( indexingTask, repository, context ); 226 } 227 } 228 catch ( IOException e ) 229 { 230 log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage(), 231 e ); 232 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", 233 e ); 234 } 235 } 236 237 } 238 239 private void finishIndexingTask( ArtifactIndexingTask indexingTask, ManagedRepository repository, 240 IndexingContext context ) 241 throws TaskExecutionException 242 { 243 try 244 { 245 246 context.optimize(); 247 248 if ( !repository.isSkipPackedIndexCreation() ) 249 { 250 251 IndexPackingRequest request = new IndexPackingRequest( context, context.getIndexDirectoryFile() ); 252 indexPacker.packIndex( request ); 253 context.updateTimestamp( true ); 254 255 log.debug( "Index file packaged at '{}'.", context.getIndexDirectoryFile() ); 256 } 257 else 258 { 259 log.debug( "skip packed index creation" ); 260 } 261 } 262 catch ( IOException e ) 263 { 264 log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage() ); 265 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", 266 e ); 267 } 268 } 269 270 public void setIndexPacker( IndexPacker indexPacker ) 271 { 272 this.indexPacker = indexPacker; 273 } 274 275 public PlexusSisuBridge getPlexusSisuBridge() 276 { 277 return plexusSisuBridge; 278 } 279 280 public void setPlexusSisuBridge( PlexusSisuBridge plexusSisuBridge ) 281 { 282 this.plexusSisuBridge = plexusSisuBridge; 283 } 284}