This project has retired. For details please refer to its Attic page.
Source code
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}