001 package 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 023 import org.apache.archiva.admin.model.RepositoryAdminException; 024 import org.apache.archiva.admin.model.beans.ManagedRepository; 025 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin; 026 import org.apache.archiva.common.plexusbridge.PlexusSisuBridge; 027 import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException; 028 import org.apache.archiva.redback.components.taskqueue.Task; 029 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException; 030 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor; 031 import org.apache.lucene.search.BooleanClause; 032 import org.apache.lucene.search.BooleanQuery; 033 import org.apache.maven.index.ArtifactContext; 034 import org.apache.maven.index.ArtifactContextProducer; 035 import org.apache.maven.index.FlatSearchRequest; 036 import org.apache.maven.index.FlatSearchResponse; 037 import org.apache.maven.index.MAVEN; 038 import org.apache.maven.index.NexusIndexer; 039 import org.apache.maven.index.context.IndexingContext; 040 import org.apache.maven.index.expr.SourcedSearchExpression; 041 import org.apache.maven.index.packer.IndexPacker; 042 import org.apache.maven.index.packer.IndexPackingRequest; 043 import org.slf4j.Logger; 044 import org.slf4j.LoggerFactory; 045 import org.springframework.stereotype.Service; 046 047 import javax.annotation.PostConstruct; 048 import javax.inject.Inject; 049 import java.io.File; 050 import 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" ) 058 public class ArchivaIndexingTaskExecutor 059 implements TaskExecutor 060 { 061 private Logger log = LoggerFactory.getLogger( ArchivaIndexingTaskExecutor.class ); 062 063 /** 064 * 065 */ 066 private IndexPacker indexPacker; 067 068 private ArtifactContextProducer artifactContextProducer; 069 070 @Inject 071 private PlexusSisuBridge plexusSisuBridge; 072 073 @Inject 074 private ManagedRepositoryAdmin managedRepositoryAdmin; 075 076 private NexusIndexer nexusIndexer; 077 078 @PostConstruct 079 public void initialize() 080 throws PlexusSisuBridgeException 081 { 082 log.info( "Initialized {}", this.getClass().getName() ); 083 084 artifactContextProducer = plexusSisuBridge.lookup( ArtifactContextProducer.class ); 085 086 indexPacker = plexusSisuBridge.lookup( IndexPacker.class, "default" ); 087 088 nexusIndexer = plexusSisuBridge.lookup( NexusIndexer.class ); 089 090 } 091 092 /** 093 * depending on current {@link Task} you have. 094 * If {@link org.apache.archiva.scheduler.indexing.ArtifactIndexingTask.Action.FINISH} && isExecuteOnEntireRepo: 095 * repository will be scanned. 096 * 097 * @param task 098 * @throws TaskExecutionException 099 */ 100 public void executeTask( Task task ) 101 throws TaskExecutionException 102 { 103 ArtifactIndexingTask indexingTask = (ArtifactIndexingTask) task; 104 105 ManagedRepository repository = indexingTask.getRepository(); 106 IndexingContext context = indexingTask.getContext(); 107 108 if ( ArtifactIndexingTask.Action.FINISH.equals( indexingTask.getAction() ) 109 && indexingTask.isExecuteOnEntireRepo() ) 110 { 111 try 112 { 113 long start = System.currentTimeMillis(); 114 nexusIndexer.scan( context, null, indexingTask.isOnlyUpdate() ); 115 long end = System.currentTimeMillis(); 116 log.info( "indexed maven repository: {}, onlyUpdate: {}, time {} ms", repository.getId(), 117 indexingTask.isOnlyUpdate(), ( end - start ) ); 118 } 119 catch ( IOException e ) 120 { 121 throw new TaskExecutionException( "Error scan repository " + repository, e ); 122 } 123 log.debug( "Finishing indexing task on repo: {}", repository.getId() ); 124 finishIndexingTask( indexingTask, repository, context ); 125 } 126 else 127 { 128 // create context if not a repo scan request 129 if ( !indexingTask.isExecuteOnEntireRepo() ) 130 { 131 try 132 { 133 log.debug( "Creating indexing context on resource: {}", ( indexingTask.getResourceFile() == null 134 ? "none" 135 : indexingTask.getResourceFile().getPath() ) ); 136 context = managedRepositoryAdmin.createIndexContext( repository ); 137 } 138 catch ( RepositoryAdminException e ) 139 { 140 log.error( "Error occurred while creating context: " + e.getMessage() ); 141 throw new TaskExecutionException( "Error occurred while creating context: " + e.getMessage(), e ); 142 } 143 } 144 145 if ( context == null || context.getIndexDirectory() == null ) 146 { 147 throw new TaskExecutionException( "Trying to index an artifact but the context is already closed" ); 148 } 149 150 try 151 { 152 File artifactFile = indexingTask.getResourceFile(); 153 if ( artifactFile == null ) 154 { 155 log.debug( "no artifact pass in indexing task so skip it" ); 156 } 157 else 158 { 159 ArtifactContext ac = artifactContextProducer.getArtifactContext( context, artifactFile ); 160 161 if ( ac != null ) 162 { 163 if ( indexingTask.getAction().equals( ArtifactIndexingTask.Action.ADD ) ) 164 { 165 //IndexSearcher s = context.getIndexSearcher(); 166 //String uinfo = ac.getArtifactInfo().getUinfo(); 167 //TopDocs d = s.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), 1 ); 168 169 BooleanQuery q = new BooleanQuery(); 170 q.add( nexusIndexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( 171 ac.getArtifactInfo().groupId ) ), BooleanClause.Occur.MUST ); 172 q.add( nexusIndexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( 173 ac.getArtifactInfo().artifactId ) ), BooleanClause.Occur.MUST ); 174 q.add( nexusIndexer.constructQuery( MAVEN.VERSION, new SourcedSearchExpression( 175 ac.getArtifactInfo().version ) ), BooleanClause.Occur.MUST ); 176 if ( ac.getArtifactInfo().classifier != null ) 177 { 178 q.add( nexusIndexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( 179 ac.getArtifactInfo().classifier ) ), BooleanClause.Occur.MUST ); 180 } 181 if ( ac.getArtifactInfo().packaging != null ) 182 { 183 q.add( nexusIndexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( 184 ac.getArtifactInfo().packaging ) ), BooleanClause.Occur.MUST ); 185 } 186 FlatSearchRequest flatSearchRequest = new FlatSearchRequest( q, context ); 187 FlatSearchResponse flatSearchResponse = nexusIndexer.searchFlat( flatSearchRequest ); 188 if ( flatSearchResponse.getResults().isEmpty() ) 189 { 190 log.debug( "Adding artifact '{}' to index..", ac.getArtifactInfo() ); 191 nexusIndexer.addArtifactToIndex( ac, context ); 192 } 193 else 194 { 195 log.debug( "Updating artifact '{}' in index..", ac.getArtifactInfo() ); 196 // TODO check if update exists !! 197 nexusIndexer.deleteArtifactFromIndex( ac, context ); 198 nexusIndexer.addArtifactToIndex( ac, context ); 199 } 200 201 context.updateTimestamp(); 202 context.commit(); 203 204 205 } 206 else 207 { 208 log.debug( "Removing artifact '{}' from index..", ac.getArtifactInfo() ); 209 nexusIndexer.deleteArtifactFromIndex( ac, context ); 210 } 211 } 212 } 213 // close the context if not a repo scan request 214 if ( !indexingTask.isExecuteOnEntireRepo() ) 215 { 216 log.debug( "Finishing indexing task on resource file : {}", indexingTask.getResourceFile() != null 217 ? indexingTask.getResourceFile().getPath() 218 : " none " ); 219 finishIndexingTask( indexingTask, repository, context ); 220 } 221 } 222 catch ( IOException e ) 223 { 224 log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage(), 225 e ); 226 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", 227 e ); 228 } 229 } 230 231 } 232 233 private void finishIndexingTask( ArtifactIndexingTask indexingTask, ManagedRepository repository, 234 IndexingContext context ) 235 throws TaskExecutionException 236 { 237 try 238 { 239 240 context.optimize(); 241 242 if ( !repository.isSkipPackedIndexCreation() ) 243 { 244 245 IndexPackingRequest request = new IndexPackingRequest( context, context.getIndexDirectoryFile() ); 246 indexPacker.packIndex( request ); 247 context.updateTimestamp( true ); 248 249 log.debug( "Index file packaged at '{}'.", context.getIndexDirectoryFile() ); 250 } 251 else 252 { 253 log.debug( "skip packed index creation" ); 254 } 255 } 256 catch ( IOException e ) 257 { 258 log.error( "Error occurred while executing indexing task '" + indexingTask + "': " + e.getMessage() ); 259 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'", 260 e ); 261 } 262 } 263 264 public void setIndexPacker( IndexPacker indexPacker ) 265 { 266 this.indexPacker = indexPacker; 267 } 268 269 public PlexusSisuBridge getPlexusSisuBridge() 270 { 271 return plexusSisuBridge; 272 } 273 274 public void setPlexusSisuBridge( PlexusSisuBridge plexusSisuBridge ) 275 { 276 this.plexusSisuBridge = plexusSisuBridge; 277 } 278 }