This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.consumers.lucene;
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 License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.common.utils.PathUtil;
023import org.apache.archiva.configuration.ArchivaConfiguration;
024import org.apache.archiva.configuration.ConfigurationNames;
025import org.apache.archiva.configuration.FileTypes;
026import org.apache.archiva.consumers.AbstractMonitoredConsumer;
027import org.apache.archiva.consumers.ConsumerException;
028import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
029import org.apache.archiva.indexer.UnsupportedBaseContextException;
030import org.apache.archiva.components.registry.Registry;
031import org.apache.archiva.components.registry.RegistryListener;
032import org.apache.archiva.components.taskqueue.TaskQueueException;
033import org.apache.archiva.repository.ManagedRepository;
034import org.apache.archiva.repository.RepositoryType;
035import org.apache.archiva.scheduler.ArchivaTaskScheduler;
036import org.apache.archiva.scheduler.indexing.ArtifactIndexingTask;
037import org.apache.maven.index.context.IndexingContext;
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040import org.springframework.context.annotation.Scope;
041import org.springframework.stereotype.Service;
042
043import javax.annotation.PostConstruct;
044import javax.inject.Inject;
045import javax.inject.Named;
046import java.nio.file.Path;
047import java.nio.file.Paths;
048import java.util.ArrayList;
049import java.util.Collections;
050import java.util.Date;
051import java.util.List;
052
053/**
054 * Consumer for indexing the repository to provide search and IDE integration features.
055 */
056@Service( "knownRepositoryContentConsumer#index-content" )
057@Scope( "prototype" )
058public class NexusIndexerConsumer
059    extends AbstractMonitoredConsumer
060    implements KnownRepositoryContentConsumer, RegistryListener
061{
062
063
064    private Logger log = LoggerFactory.getLogger( getClass() );
065
066    private ArchivaConfiguration configuration;
067
068    private FileTypes filetypes;
069
070    private Path managedRepository;
071
072    private ArchivaTaskScheduler<ArtifactIndexingTask> scheduler;
073
074    private IndexingContext indexingContext;
075
076    private List<String> includes = new ArrayList<>( 0 );
077
078    private ManagedRepository repository;
079
080    @Inject
081    public NexusIndexerConsumer(
082        @Named( value = "archivaTaskScheduler#indexing" ) ArchivaTaskScheduler<ArtifactIndexingTask> scheduler,
083        @Named( value = "archivaConfiguration" ) ArchivaConfiguration configuration, FileTypes filetypes)
084    {
085        this.configuration = configuration;
086        this.filetypes = filetypes;
087        this.scheduler = scheduler;
088    }
089
090    @Override
091    public String getDescription()
092    {
093        return "Indexes the repository to provide search and IDE integration features";
094    }
095
096    @Override
097    public String getId()
098    {
099        return "index-content";
100    }
101
102    @Override
103    public void beginScan( ManagedRepository repository, Date whenGathered )
104        throws ConsumerException
105    {
106        this.repository = repository;
107        managedRepository = PathUtil.getPathFromUri( repository.getLocation() );
108
109        try
110        {
111            log.info( "Creating indexing context for repo : {}", repository.getId() );
112            if (repository.getType()== RepositoryType.MAVEN) {
113                indexingContext = repository.getIndexingContext().getBaseContext(IndexingContext.class);
114            } else  {
115                indexingContext= null;
116            }
117        } catch (UnsupportedBaseContextException e) {
118            log.error("Bad repository type. Not nexus indexer compatible.");
119            throw new ConsumerException("Bad repository type "+repository.getType());
120        }
121    }
122
123    @Override
124    public void beginScan( ManagedRepository repository, Date whenGathered, boolean executeOnEntireRepo )
125        throws ConsumerException
126    {
127        if ( executeOnEntireRepo )
128        {
129            beginScan( repository, whenGathered );
130        }
131        else
132        {
133            this.repository = repository;
134            managedRepository = Paths.get( repository.getLocation() );
135        }
136    }
137
138    @Override
139    public void processFile( String path )
140        throws ConsumerException
141    {
142        Path artifactFile = managedRepository.resolve(path);
143
144        ArtifactIndexingTask task =
145            new ArtifactIndexingTask( repository, artifactFile, ArtifactIndexingTask.Action.ADD, repository.getIndexingContext() );
146        try
147        {
148            log.debug( "Queueing indexing task '{}' to add or update the artifact in the index.", task );
149            scheduler.queueTask( task );
150        }
151        catch ( TaskQueueException e )
152        {
153            throw new ConsumerException( e.getMessage(), e );
154        }
155    }
156
157    @Override
158    public void processFile( String path, boolean executeOnEntireRepo )
159        throws Exception
160    {
161        if ( executeOnEntireRepo )
162        {
163            processFile( path );
164        }
165        else
166        {
167            Path artifactFile = managedRepository.resolve(path);
168
169            // specify in indexing task that this is not a repo scan request!
170            ArtifactIndexingTask task =
171                new ArtifactIndexingTask( repository, artifactFile, ArtifactIndexingTask.Action.ADD,
172                                          repository.getIndexingContext(), false );
173            // only update index we don't need to scan the full repo here
174            task.setOnlyUpdate( true );
175            try
176            {
177                log.debug( "Queueing indexing task '{}' to add or update the artifact in the index.", task );
178                scheduler.queueTask( task );
179            }
180            catch ( TaskQueueException e )
181            {
182                throw new ConsumerException( e.getMessage(), e );
183            }
184        }
185    }
186
187    @Override
188    public void completeScan()
189    {
190        ArtifactIndexingTask task =
191            new ArtifactIndexingTask( repository, null, ArtifactIndexingTask.Action.FINISH, repository.getIndexingContext());
192        try
193        {
194            log.debug( "Queueing indexing task '{}' to finish indexing.", task );
195            scheduler.queueTask( task );
196        }
197        catch ( TaskQueueException e )
198        {
199            log.error( "Error queueing task: {}: {}", task, e.getMessage(), e );
200        }
201    }
202
203    @Override
204    public void completeScan( boolean executeOnEntireRepo )
205    {
206        if ( executeOnEntireRepo )
207        {
208            completeScan();
209        }
210
211        // else, do nothing as the context will be closed when indexing task is executed if not a repo scan request!
212    }
213
214    @Override
215    public List<String> getExcludes()
216    {
217        return Collections.emptyList();
218    }
219
220    @Override
221    public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
222    {
223        if ( ConfigurationNames.isRepositoryScanning( propertyName ) )
224        {
225            initIncludes();
226        }
227    }
228
229    @Override
230    public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
231    {
232        /* do nothing */
233    }
234
235    private void initIncludes()
236    {
237        List<String> indexable = filetypes.getFileTypePatterns( FileTypes.INDEXABLE_CONTENT );
238        List<String> artifacts = filetypes.getFileTypePatterns( FileTypes.ARTIFACTS );
239
240        includes = new ArrayList<>( indexable.size() + artifacts.size() );
241
242        includes.addAll( indexable );
243
244        includes.addAll( artifacts );
245    }
246
247    @PostConstruct
248    public void initialize()
249    {
250        configuration.addChangeListener( this );
251
252        initIncludes();
253    }
254
255    @Override
256    public List<String> getIncludes()
257    {
258        return includes;
259    }
260
261
262    private IndexingContext getIndexingContext()
263        throws ConsumerException
264    {
265
266        if ( this.indexingContext == null )
267        {
268            try
269            {
270                indexingContext = repository.getIndexingContext().getBaseContext(IndexingContext.class);
271            } catch (UnsupportedBaseContextException e) {
272                log.error("Bad repository type. Not nexus indexer compatible. "+repository.getType());
273                throw new ConsumerException("Bad repository type "+repository.getType());
274            }
275        }
276        return indexingContext;
277    }
278}