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.admin.model.beans.ManagedRepository;
25 import org.apache.archiva.common.utils.BaseFile;
26 import org.apache.archiva.configuration.ArchivaConfiguration;
27 import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
28 import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
29 import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate;
30 import org.apache.archiva.redback.components.registry.RegistryListener;
31 import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
32 import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
33 import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
34 import org.apache.commons.collections.Closure;
35 import org.apache.commons.collections.CollectionUtils;
36 import org.apache.commons.collections.functors.IfClosure;
37 import org.springframework.beans.BeansException;
38 import org.springframework.context.ApplicationContext;
39 import org.springframework.context.ApplicationContextAware;
40 import org.springframework.stereotype.Service;
42 import javax.inject.Inject;
43 import java.nio.file.Path;
47 * RepositoryContentConsumerUtil
49 @Service("repositoryContentConsumers")
50 public class RepositoryContentConsumers
51 implements ApplicationContextAware
55 private ApplicationContext applicationContext;
57 private ArchivaAdministration archivaAdministration;
59 private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
61 private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
64 private ArchivaConfiguration archivaConfiguration;
67 public RepositoryContentConsumers( ArchivaAdministration archivaAdministration )
69 this.archivaAdministration = archivaAdministration;
73 public void setApplicationContext( ApplicationContext applicationContext )
76 this.applicationContext = applicationContext;
81 * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have
82 * been selected in the configuration to execute.
85 * NOTE: This list can be larger and contain entries that might not exist or be available
86 * in the classpath, or as a component.
89 * @return the list of consumer ids that have been selected by the configuration.
91 public List<String> getSelectedKnownConsumerIds()
92 throws RepositoryAdminException
94 return archivaAdministration.getKnownContentConsumers();
99 * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have
100 * been selected in the configuration to execute.
103 * NOTE: This list can be larger and contain entries that might not exist or be available
104 * in the classpath, or as a component.
107 * @return the list of consumer ids that have been selected by the configuration.
109 public List<String> getSelectedInvalidConsumerIds()
110 throws RepositoryAdminException
112 return archivaAdministration.getInvalidContentConsumers();
116 * Get the map of {@link String} ids to {@link KnownRepositoryContentConsumer} implementations,
117 * for those consumers that have been selected according to the active configuration.
119 * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.
121 public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
122 throws RepositoryAdminException
124 Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
126 for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
128 consumerMap.put( consumer.getId(), consumer );
135 * Get the map of {@link String} ids to {@link InvalidRepositoryContentConsumer} implementations,
136 * for those consumers that have been selected according to the active configuration.
138 * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.
140 public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
141 throws RepositoryAdminException
143 Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
145 for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
147 consumerMap.put( consumer.getId(), consumer );
154 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
155 * selected according to the active configuration.
157 * @return the list of {@link KnownRepositoryContentConsumer} that have been selected
158 * by the active configuration.
160 public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
161 throws RepositoryAdminException
163 // FIXME only for testing
164 if ( selectedKnownConsumers != null )
166 return selectedKnownConsumers;
168 List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
170 List<String> knownSelected = getSelectedKnownConsumerIds();
172 for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
174 if ( knownSelected.contains( consumer.getId() ) )
182 public void releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
184 if ( repositoryContentConsumers == null )
188 for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
190 if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
192 archivaConfiguration.removeChangeListener(
193 RegistryListener.class.cast( knownRepositoryContentConsumer ) );
199 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
200 * selected according to the active configuration.
202 * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected
203 * by the active configuration.
205 public synchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
206 throws RepositoryAdminException
209 // FIXME only for testing
210 if ( selectedInvalidConsumers != null )
212 return selectedInvalidConsumers;
215 List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
217 List<String> invalidSelected = getSelectedInvalidConsumerIds();
219 for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
221 if ( invalidSelected.contains( consumer.getId() ) )
231 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
232 * available and present in the classpath and as components in the IoC.
234 * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath
235 * and as a component in the IoC.
237 public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
239 return new ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
243 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
244 * available and present in the classpath and as components in the IoC.
246 * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath
247 * and as a component in the IoC.
249 public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
251 return new ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
255 * A convienence method to execute all of the active selected consumers for a
256 * particular arbitrary file.
257 * NOTE: Make sure that there is no repository scanning task executing before invoking this so as to prevent
258 * the index writer/reader of the current index-content consumer executing from getting closed. For an example,
259 * see ArchivaDavResource#executeConsumers( File ).
261 * @param repository the repository configuration to use.
262 * @param localFile the local file to execute the consumers against.
263 * @param updateRelatedArtifacts TODO
265 public void executeConsumers(ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
266 throws RepositoryAdminException
268 List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
269 // Run the repository consumers
272 Closure triggerBeginScan = new TriggerBeginScanClosure( repository, getStartTime(), false );
274 selectedKnownConsumers = getSelectedKnownConsumers();
277 // - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven
278 if ( !updateRelatedArtifacts )
280 List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
281 clone.addAll( selectedKnownConsumers );
283 for ( KnownRepositoryContentConsumer consumer : clone )
285 if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
286 "metadata-updater" ) )
288 selectedKnownConsumers.remove( consumer );
293 List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
294 CollectionUtils.forAllDo( selectedKnownConsumers, triggerBeginScan );
295 CollectionUtils.forAllDo( selectedInvalidConsumers, triggerBeginScan );
297 // yuck. In case you can't read this, it says
298 // "process the file if the consumer has it in the includes list, and not in the excludes list"
299 BaseFile baseFile = new BaseFile( repository.getLocation(), localFile.toFile() );
300 ConsumerWantsFilePredicate predicate = new ConsumerWantsFilePredicate( repository );
301 predicate.setBasefile( baseFile );
302 predicate.setCaseSensitive( false );
304 ConsumerProcessFileClosure closure = new ConsumerProcessFileClosure();
305 closure.setBasefile( baseFile );
306 closure.setExecuteOnEntireRepo( false );
308 Closure processIfWanted = IfClosure.getInstance( predicate, closure );
310 CollectionUtils.forAllDo( selectedKnownConsumers, processIfWanted );
312 if ( predicate.getWantedFileCount() <= 0 )
314 // Nothing known processed this file. It is invalid!
315 CollectionUtils.forAllDo( selectedInvalidConsumers, closure );
318 TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, false );
320 CollectionUtils.forAllDo( selectedKnownConsumers, scanCompletedClosure );
324 /* TODO: This is never called by the repository scanner instance, so not calling here either - but it probably should be?
325 CollectionUtils.forAllDo( availableKnownConsumers, triggerCompleteScan );
326 CollectionUtils.forAllDo( availableInvalidConsumers, triggerCompleteScan );
328 releaseSelectedKnownConsumers( selectedKnownConsumers );
332 public void setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
334 this.selectedKnownConsumers = selectedKnownConsumers;
337 public void setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
339 this.selectedInvalidConsumers = selectedInvalidConsumers;
342 protected Date getStartTime()
344 return new Date( System.currentTimeMillis() );
347 public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
349 this.archivaAdministration = archivaAdministration;