1 package org.apache.archiva.repository.scanner;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.admin.model.RepositoryAdminException;
23 import org.apache.archiva.admin.model.admin.ArchivaAdministration;
24 import org.apache.archiva.common.utils.BaseFile;
25 import org.apache.archiva.common.utils.PathUtil;
26 import org.apache.archiva.configuration.ArchivaConfiguration;
27 import org.apache.archiva.consumers.ConsumerException;
28 import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
29 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
30 import org.apache.archiva.consumers.RepositoryContentConsumer;
31 import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate;
32 import org.apache.archiva.components.registry.RegistryListener;
33 import org.apache.archiva.repository.ManagedRepository;
34 import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
35 import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
36 import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
37 import org.apache.commons.collections4.Closure;
38 import org.apache.commons.collections4.IterableUtils;
39 import org.apache.commons.collections4.functors.IfClosure;
40 import org.springframework.beans.BeansException;
41 import org.springframework.context.ApplicationContext;
42 import org.springframework.context.ApplicationContextAware;
43 import org.springframework.stereotype.Service;
45 import javax.inject.Inject;
46 import java.nio.file.Path;
47 import java.util.ArrayList;
48 import java.util.Date;
49 import java.util.HashMap;
50 import java.util.List;
54 * RepositoryContentConsumerUtil
56 @Service("repositoryContentConsumers")
57 public class RepositoryContentConsumers
58 implements ApplicationContextAware
62 private ApplicationContext applicationContext;
64 private ArchivaAdministration archivaAdministration;
66 private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
68 private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
71 private ArchivaConfiguration archivaConfiguration;
74 public RepositoryContentConsumers( ArchivaAdministration archivaAdministration )
76 this.archivaAdministration = archivaAdministration;
80 public void setApplicationContext( ApplicationContext applicationContext )
83 this.applicationContext = applicationContext;
88 * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have
89 * been selected in the configuration to execute.
92 * NOTE: This list can be larger and contain entries that might not exist or be available
93 * in the classpath, or as a component.
96 * @return the list of consumer ids that have been selected by the configuration.
98 public List<String> getSelectedKnownConsumerIds()
99 throws ConsumerException
103 return archivaAdministration.getKnownContentConsumers();
105 catch ( RepositoryAdminException e )
107 throw new ConsumerException( e.getMessage( ), e );
113 * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have
114 * been selected in the configuration to execute.
117 * NOTE: This list can be larger and contain entries that might not exist or be available
118 * in the classpath, or as a component.
121 * @return the list of consumer ids that have been selected by the configuration.
123 public List<String> getSelectedInvalidConsumerIds()
124 throws ConsumerException
128 return archivaAdministration.getInvalidContentConsumers();
130 catch ( RepositoryAdminException e )
132 throw new ConsumerException( e.getMessage( ), e );
137 * Get the map of {@link String} ids to {@link KnownRepositoryContentConsumer} implementations,
138 * for those consumers that have been selected according to the active configuration.
140 * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.
142 public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
143 throws ConsumerException
145 Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
147 for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
149 consumerMap.put( consumer.getId(), consumer );
156 * Get the map of {@link String} ids to {@link InvalidRepositoryContentConsumer} implementations,
157 * for those consumers that have been selected according to the active configuration.
159 * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.
161 public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
162 throws ConsumerException
164 Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
166 for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
168 consumerMap.put( consumer.getId(), consumer );
175 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
176 * selected according to the active configuration.
178 * @return the list of {@link KnownRepositoryContentConsumer} that have been selected
179 * by the active configuration.
181 public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
182 throws ConsumerException
184 // FIXME only for testing
185 if ( selectedKnownConsumers != null )
187 return selectedKnownConsumers;
189 List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
191 List<String> knownSelected = getSelectedKnownConsumerIds();
193 for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
195 if ( knownSelected.contains( consumer.getId() ) )
203 public void releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
205 if ( repositoryContentConsumers == null )
209 for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
211 if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
213 archivaConfiguration.removeChangeListener(
214 RegistryListener.class.cast( knownRepositoryContentConsumer ) );
220 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
221 * selected according to the active configuration.
223 * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected
224 * by the active configuration.
226 public synchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
227 throws ConsumerException
230 // FIXME only for testing
231 if ( selectedInvalidConsumers != null )
233 return selectedInvalidConsumers;
236 List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
238 List<String> invalidSelected = null;
241 invalidSelected = getSelectedInvalidConsumerIds();
243 catch ( ConsumerException e )
245 e.printStackTrace( );
248 for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
250 if ( invalidSelected.contains( consumer.getId() ) )
260 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
261 * available and present in the classpath and as components in the IoC.
263 * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath
264 * and as a component in the IoC.
266 public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
268 return new ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
272 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
273 * available and present in the classpath and as components in the IoC.
275 * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath
276 * and as a component in the IoC.
278 public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
280 return new ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
284 * A convienence method to execute all of the active selected consumers for a
285 * particular arbitrary file.
286 * NOTE: Make sure that there is no repository scanning task executing before invoking this so as to prevent
287 * the index writer/reader of the current index-content consumer executing from getting closed. For an example,
288 * see ArchivaDavResource#executeConsumers( File ).
289 * @param repository the repository configuration to use.
290 * @param localFile the local file to execute the consumers against.
291 * @param updateRelatedArtifacts TODO
293 public void executeConsumers( ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
294 throws ConsumerException
296 List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
297 // Run the repository consumers
300 Closure<RepositoryContentConsumer> triggerBeginScan = new TriggerBeginScanClosure( repository, getStartTime(), false );
302 selectedKnownConsumers = getSelectedKnownConsumers();
305 // - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven
306 if ( !updateRelatedArtifacts )
308 List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
309 clone.addAll( selectedKnownConsumers );
311 for ( KnownRepositoryContentConsumer consumer : clone )
313 if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
314 "metadata-updater" ) )
316 selectedKnownConsumers.remove( consumer );
321 List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
322 IterableUtils.forEach( selectedKnownConsumers, triggerBeginScan );
323 IterableUtils.forEach( selectedInvalidConsumers, triggerBeginScan );
325 // yuck. In case you can't read this, it says
326 // "process the file if the consumer has it in the includes list, and not in the excludes list"
327 Path repoPath = PathUtil.getPathFromUri( repository.getLocation() );
328 BaseFile baseFile = new BaseFile( repoPath.toString(), localFile.toFile() );
329 ConsumerWantsFilePredicate predicate = new ConsumerWantsFilePredicate( repository );
330 predicate.setBasefile( baseFile );
331 predicate.setCaseSensitive( false );
333 ConsumerProcessFileClosure closure = new ConsumerProcessFileClosure();
334 closure.setBasefile( baseFile );
335 closure.setExecuteOnEntireRepo( false );
337 Closure<RepositoryContentConsumer> processIfWanted = IfClosure.ifClosure( predicate, closure );
339 IterableUtils.forEach( selectedKnownConsumers, processIfWanted );
341 if ( predicate.getWantedFileCount() <= 0 )
343 // Nothing known processed this file. It is invalid!
344 IterableUtils.forEach( selectedInvalidConsumers, closure );
347 TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, false );
349 IterableUtils.forEach( selectedKnownConsumers, scanCompletedClosure );
353 /* TODO: This is never called by the repository scanner instance, so not calling here either - but it probably should be?
354 IterableUtils.forEach( availableKnownConsumers, triggerCompleteScan );
355 IterableUtils.forEach( availableInvalidConsumers, triggerCompleteScan );
357 releaseSelectedKnownConsumers( selectedKnownConsumers );
361 public void setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
363 this.selectedKnownConsumers = selectedKnownConsumers;
366 public void setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
368 this.selectedInvalidConsumers = selectedInvalidConsumers;
371 protected Date getStartTime()
373 return new Date( System.currentTimeMillis() );
376 public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
378 this.archivaAdministration = archivaAdministration;