]> source.dussan.org Git - archiva.git/blob
03a95be75db1c8c982d98351c0e7c38e29b137a0
[archiva.git] /
1 package org.apache.archiva.scheduler.indexing;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the Li
16  * cense is distributed on an
17  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  * KIND, either express or implied.  See the License for the
19  * specific language governing permissions and limitations
20  * under the License.
21  */
22
23 import org.apache.archiva.admin.model.RepositoryAdminException;
24 import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
25 import org.apache.archiva.indexer.ArchivaIndexingContext;
26 import org.apache.archiva.indexer.UnsupportedBaseContextException;
27 import org.apache.archiva.redback.components.taskqueue.Task;
28 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutionException;
29 import org.apache.archiva.redback.components.taskqueue.execution.TaskExecutor;
30 import org.apache.archiva.repository.ManagedRepository;
31 import org.apache.archiva.repository.features.IndexCreationFeature;
32 import org.apache.maven.index.ArtifactContext;
33 import org.apache.maven.index.ArtifactContextProducer;
34 import org.apache.maven.index.FlatSearchRequest;
35 import org.apache.maven.index.FlatSearchResponse;
36 import org.apache.maven.index.MAVEN;
37 import org.apache.maven.index.NexusIndexer;
38 import org.apache.maven.index.context.IndexingContext;
39 import org.apache.maven.index.expr.SourcedSearchExpression;
40 import org.apache.maven.index.packer.IndexPacker;
41 import org.apache.maven.index.packer.IndexPackingRequest;
42 import org.apache.maven.index_shaded.lucene.search.BooleanClause;
43 import org.apache.maven.index_shaded.lucene.search.BooleanQuery;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.springframework.stereotype.Service;
47
48 import javax.inject.Inject;
49 import java.io.IOException;
50 import java.nio.file.Path;
51
52 /**
53  * ArchivaIndexingTaskExecutor Executes all indexing tasks. Adding, updating and removing artifacts from the index are
54  * all performed by this executor. Add and update artifact in index tasks are added in the indexing task queue by the
55  * NexusIndexerConsumer while remove artifact from index tasks are added by the LuceneCleanupRemoveIndexedConsumer.
56  */
57 @Service( "taskExecutor#indexing" )
58 public class ArchivaIndexingTaskExecutor
59     implements TaskExecutor
60 {
61     private Logger log = LoggerFactory.getLogger( ArchivaIndexingTaskExecutor.class );
62
63     @Inject
64     private IndexPacker indexPacker;
65
66     @Inject
67     private ArtifactContextProducer artifactContextProducer;
68
69     @Inject
70     private NexusIndexer nexusIndexer;
71
72
73     /**
74      * depending on current {@link Task} you have.
75      * If {@link org.apache.archiva.scheduler.indexing.ArtifactIndexingTask.Action#FINISH} && isExecuteOnEntireRepo:
76      * repository will be scanned.
77      *
78      * @param task
79      * @throws TaskExecutionException
80      */
81     @Override
82     public void executeTask( Task task )
83         throws TaskExecutionException
84     {
85         ArtifactIndexingTask indexingTask = (ArtifactIndexingTask) task;
86
87         ManagedRepository repository = indexingTask.getRepository( );
88         ArchivaIndexingContext archivaContext = indexingTask.getContext( );
89         IndexingContext context = null;
90         try {
91             context = archivaContext.getBaseContext(IndexingContext.class);
92         } catch (UnsupportedBaseContextException e) {
93             throw new TaskExecutionException("Bad repository type.", e);
94         }
95         if (!nexusIndexer.getIndexingContexts().containsKey(context.getId())) {
96             nexusIndexer.addIndexingContext(context);
97         }
98
99         if ( ArtifactIndexingTask.Action.FINISH.equals( indexingTask.getAction( ) )
100             && indexingTask.isExecuteOnEntireRepo( ) )
101         {
102             try
103             {
104                 long start = System.currentTimeMillis( );
105                 nexusIndexer.scan( context, null, indexingTask.isOnlyUpdate( ) );
106                 long end = System.currentTimeMillis( );
107                 log.info( "indexed maven repository: {}, onlyUpdate: {}, time {} ms", repository.getId( ),
108                     indexingTask.isOnlyUpdate( ), ( end - start ) );
109             }
110             catch ( IOException e )
111             {
112                 throw new TaskExecutionException( "Error scan repository " + repository, e );
113             }
114             log.debug( "Finishing indexing task on repo: {}", repository.getId( ) );
115             finishIndexingTask( indexingTask, repository, context );
116         }
117         else
118         {
119             // create context if not a repo scan request
120             if ( !indexingTask.isExecuteOnEntireRepo( ) )
121             {
122                 try
123                 {
124                     log.debug( "Creating indexing context on resource: {}", //
125                         ( indexingTask.getResourceFile( ) == null
126                             ? "none"
127                             : indexingTask.getResourceFile( ) ) );
128                     archivaContext = repository.getIndexingContext();
129                     context = archivaContext.getBaseContext(IndexingContext.class);
130                 }
131                 catch ( UnsupportedBaseContextException e )
132                 {
133                     log.error( "Error occurred while creating context: {}", e.getMessage( ) );
134                     throw new TaskExecutionException( "Error occurred while creating context: " + e.getMessage( ), e );
135                 }
136             }
137
138             if ( context == null || context.getIndexDirectory( ) == null )
139             {
140                 throw new TaskExecutionException( "Trying to index an artifact but the context is already closed" );
141             }
142
143             try
144             {
145                 Path artifactFile = indexingTask.getResourceFile( );
146                 if ( artifactFile == null )
147                 {
148                     log.debug( "no artifact pass in indexing task so skip it" );
149                 }
150                 else
151                 {
152                     ArtifactContext ac = artifactContextProducer.getArtifactContext( context, artifactFile.toFile( ) );
153
154                     if ( ac != null )
155                     {
156                         // MRM-1779 pom must be indexed too
157                         // TODO make that configurable?
158                         if ( artifactFile.getFileName( ).toString( ).endsWith( ".pom" ) )
159                         {
160                             ac.getArtifactInfo( ).setFileExtension( "pom" );
161                             ac.getArtifactInfo( ).setPackaging( "pom" );
162                             ac.getArtifactInfo( ).setClassifier( "pom" );
163                         }
164                         if ( indexingTask.getAction( ).equals( ArtifactIndexingTask.Action.ADD ) )
165                         {
166                             //IndexSearcher s = context.getIndexSearcher();
167                             //String uinfo = ac.getArtifactInfo().getUinfo();
168                             //TopDocs d = s.search( new TermQuery( new Term( ArtifactInfo.UINFO, uinfo ) ), 1 );
169
170                             BooleanQuery q = new BooleanQuery( );
171                             q.add( nexusIndexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression(
172                                 ac.getArtifactInfo( ).getGroupId( ) ) ), BooleanClause.Occur.MUST );
173                             q.add( nexusIndexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression(
174                                 ac.getArtifactInfo( ).getArtifactId( ) ) ), BooleanClause.Occur.MUST );
175                             q.add( nexusIndexer.constructQuery( MAVEN.VERSION, new SourcedSearchExpression(
176                                 ac.getArtifactInfo( ).getVersion( ) ) ), BooleanClause.Occur.MUST );
177                             if ( ac.getArtifactInfo( ).getClassifier( ) != null )
178                             {
179                                 q.add( nexusIndexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression(
180                                     ac.getArtifactInfo( ).getClassifier( ) ) ), BooleanClause.Occur.MUST );
181                             }
182                             if ( ac.getArtifactInfo( ).getPackaging( ) != null )
183                             {
184                                 q.add( nexusIndexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression(
185                                     ac.getArtifactInfo( ).getPackaging( ) ) ), BooleanClause.Occur.MUST );
186                             }
187                             FlatSearchRequest flatSearchRequest = new FlatSearchRequest( q, context );
188                             FlatSearchResponse flatSearchResponse = nexusIndexer.searchFlat( flatSearchRequest );
189                             if ( flatSearchResponse.getResults( ).isEmpty( ) )
190                             {
191                                 log.debug( "Adding artifact '{}' to index..", ac.getArtifactInfo( ) );
192                                 nexusIndexer.addArtifactToIndex( ac, context );
193                             }
194                             else
195                             {
196                                 log.debug( "Updating artifact '{}' in index..", ac.getArtifactInfo( ) );
197                                 // TODO check if update exists !!
198                                 nexusIndexer.deleteArtifactFromIndex( ac, context );
199                                 nexusIndexer.addArtifactToIndex( ac, context );
200                             }
201
202                             context.updateTimestamp( );
203                             context.commit( );
204
205
206                         }
207                         else
208                         {
209                             log.debug( "Removing artifact '{}' from index..", ac.getArtifactInfo( ) );
210                             nexusIndexer.deleteArtifactFromIndex( ac, context );
211                         }
212                     }
213                 }
214                 // close the context if not a repo scan request
215                 if ( !indexingTask.isExecuteOnEntireRepo( ) )
216                 {
217                     log.debug( "Finishing indexing task on resource file : {}", indexingTask.getResourceFile( ) != null
218                         ? indexingTask.getResourceFile( )
219                         : " none " );
220                     finishIndexingTask( indexingTask, repository, context );
221                 }
222             }
223             catch ( IOException e )
224             {
225                 log.error( "Error occurred while executing indexing task '{}': {}", indexingTask, e.getMessage( ),
226                     e );
227                 throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'",
228                     e );
229             }
230         }
231
232     }
233
234     private void finishIndexingTask( ArtifactIndexingTask indexingTask, ManagedRepository repository,
235                                      IndexingContext context )
236         throws TaskExecutionException
237     {
238         try
239         {
240
241             log.debug("Finishing indexing");
242             context.optimize( );
243
244             if ( repository.supportsFeature( IndexCreationFeature.class ) )
245             {
246                 IndexCreationFeature icf = repository.getFeature( IndexCreationFeature.class ).get( );
247                 if ( !icf.isSkipPackedIndexCreation( ) && icf.getLocalPackedIndexPath()!=null)
248                 {
249
250                     log.debug("Creating packed index from {} on {}", context.getIndexDirectoryFile(), icf.getLocalPackedIndexPath());
251                     IndexPackingRequest request = new IndexPackingRequest( context, //
252                         context.acquireIndexSearcher( ).getIndexReader( ),
253                         //
254                         icf.getLocalPackedIndexPath().toFile() );
255
256                     indexPacker.packIndex( request );
257                     context.updateTimestamp( true );
258
259                     log.debug( "Index file packed at '{}'.", icf.getLocalPackedIndexPath() );
260                 } else {
261                     log.debug( "skip packed index creation" );
262                 }
263             }
264             else
265             {
266                 log.debug( "skip packed index creation" );
267             }
268         }
269         catch ( IOException e )
270         {
271             log.error( "Error occurred while executing indexing task '{}': {}", indexingTask, e.getMessage( ) );
272             throw new TaskExecutionException( "Error occurred while executing indexing task '" + indexingTask + "'",
273                 e );
274         }
275     }
276
277     public void setIndexPacker( IndexPacker indexPacker )
278     {
279         this.indexPacker = indexPacker;
280     }
281
282 }