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.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.ManagedRepository;
32 import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
33 import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
34 import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
35 import org.apache.commons.collections.Closure;
36 import org.apache.commons.collections.CollectionUtils;
37 import org.apache.commons.collections.functors.IfClosure;
38 import org.springframework.beans.BeansException;
39 import org.springframework.context.ApplicationContext;
40 import org.springframework.context.ApplicationContextAware;
41 import org.springframework.stereotype.Service;
43 import javax.inject.Inject;
44 import java.nio.file.Path;
45 import java.util.ArrayList;
46 import java.util.Date;
47 import java.util.HashMap;
48 import java.util.List;
52 * RepositoryContentConsumerUtil
54 @Service("repositoryContentConsumers")
55 public class RepositoryContentConsumers
56 implements ApplicationContextAware
60 private ApplicationContext applicationContext;
62 private ArchivaAdministration archivaAdministration;
64 private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
66 private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
69 private ArchivaConfiguration archivaConfiguration;
72 public RepositoryContentConsumers( ArchivaAdministration archivaAdministration )
74 this.archivaAdministration = archivaAdministration;
78 public void setApplicationContext( ApplicationContext applicationContext )
81 this.applicationContext = applicationContext;
86 * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have
87 * been selected in the configuration to execute.
90 * NOTE: This list can be larger and contain entries that might not exist or be available
91 * in the classpath, or as a component.
94 * @return the list of consumer ids that have been selected by the configuration.
96 public List<String> getSelectedKnownConsumerIds()
97 throws RepositoryAdminException
99 return archivaAdministration.getKnownContentConsumers();
104 * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have
105 * been selected in the configuration to execute.
108 * NOTE: This list can be larger and contain entries that might not exist or be available
109 * in the classpath, or as a component.
112 * @return the list of consumer ids that have been selected by the configuration.
114 public List<String> getSelectedInvalidConsumerIds()
115 throws RepositoryAdminException
117 return archivaAdministration.getInvalidContentConsumers();
121 * Get the map of {@link String} ids to {@link KnownRepositoryContentConsumer} implementations,
122 * for those consumers that have been selected according to the active configuration.
124 * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.
126 public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
127 throws RepositoryAdminException
129 Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
131 for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
133 consumerMap.put( consumer.getId(), consumer );
140 * Get the map of {@link String} ids to {@link InvalidRepositoryContentConsumer} implementations,
141 * for those consumers that have been selected according to the active configuration.
143 * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.
145 public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
146 throws RepositoryAdminException
148 Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
150 for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
152 consumerMap.put( consumer.getId(), consumer );
159 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
160 * selected according to the active configuration.
162 * @return the list of {@link KnownRepositoryContentConsumer} that have been selected
163 * by the active configuration.
165 public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
166 throws RepositoryAdminException
168 // FIXME only for testing
169 if ( selectedKnownConsumers != null )
171 return selectedKnownConsumers;
173 List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
175 List<String> knownSelected = getSelectedKnownConsumerIds();
177 for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
179 if ( knownSelected.contains( consumer.getId() ) )
187 public void releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
189 if ( repositoryContentConsumers == null )
193 for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
195 if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
197 archivaConfiguration.removeChangeListener(
198 RegistryListener.class.cast( knownRepositoryContentConsumer ) );
204 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
205 * selected according to the active configuration.
207 * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected
208 * by the active configuration.
210 public synchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
211 throws RepositoryAdminException
214 // FIXME only for testing
215 if ( selectedInvalidConsumers != null )
217 return selectedInvalidConsumers;
220 List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
222 List<String> invalidSelected = getSelectedInvalidConsumerIds();
224 for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
226 if ( invalidSelected.contains( consumer.getId() ) )
236 * Get the list of {@link KnownRepositoryContentConsumer} objects that are
237 * available and present in the classpath and as components in the IoC.
239 * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath
240 * and as a component in the IoC.
242 public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
244 return new ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
248 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
249 * available and present in the classpath and as components in the IoC.
251 * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath
252 * and as a component in the IoC.
254 public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
256 return new ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
260 * A convienence method to execute all of the active selected consumers for a
261 * particular arbitrary file.
262 * NOTE: Make sure that there is no repository scanning task executing before invoking this so as to prevent
263 * the index writer/reader of the current index-content consumer executing from getting closed. For an example,
264 * see ArchivaDavResource#executeConsumers( File ).
266 * @param repository the repository configuration to use.
267 * @param localFile the local file to execute the consumers against.
268 * @param updateRelatedArtifacts TODO
270 public void executeConsumers( ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
271 throws RepositoryAdminException
273 List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
274 // Run the repository consumers
277 Closure triggerBeginScan = new TriggerBeginScanClosure( repository, getStartTime(), false );
279 selectedKnownConsumers = getSelectedKnownConsumers();
282 // - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven
283 if ( !updateRelatedArtifacts )
285 List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
286 clone.addAll( selectedKnownConsumers );
288 for ( KnownRepositoryContentConsumer consumer : clone )
290 if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
291 "metadata-updater" ) )
293 selectedKnownConsumers.remove( consumer );
298 List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
299 CollectionUtils.forAllDo( selectedKnownConsumers, triggerBeginScan );
300 CollectionUtils.forAllDo( selectedInvalidConsumers, triggerBeginScan );
302 // yuck. In case you can't read this, it says
303 // "process the file if the consumer has it in the includes list, and not in the excludes list"
304 Path repoPath = PathUtil.getPathFromUri( repository.getLocation() );
305 BaseFile baseFile = new BaseFile( repoPath.toString(), localFile.toFile() );
306 ConsumerWantsFilePredicate predicate = new ConsumerWantsFilePredicate( repository );
307 predicate.setBasefile( baseFile );
308 predicate.setCaseSensitive( false );
310 ConsumerProcessFileClosure closure = new ConsumerProcessFileClosure();
311 closure.setBasefile( baseFile );
312 closure.setExecuteOnEntireRepo( false );
314 Closure processIfWanted = IfClosure.getInstance( predicate, closure );
316 CollectionUtils.forAllDo( selectedKnownConsumers, processIfWanted );
318 if ( predicate.getWantedFileCount() <= 0 )
320 // Nothing known processed this file. It is invalid!
321 CollectionUtils.forAllDo( selectedInvalidConsumers, closure );
324 TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, false );
326 CollectionUtils.forAllDo( selectedKnownConsumers, scanCompletedClosure );
330 /* TODO: This is never called by the repository scanner instance, so not calling here either - but it probably should be?
331 CollectionUtils.forAllDo( availableKnownConsumers, triggerCompleteScan );
332 CollectionUtils.forAllDo( availableInvalidConsumers, triggerCompleteScan );
334 releaseSelectedKnownConsumers( selectedKnownConsumers );
338 public void setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
340 this.selectedKnownConsumers = selectedKnownConsumers;
343 public void setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
345 this.selectedInvalidConsumers = selectedInvalidConsumers;
348 protected Date getStartTime()
350 return new Date( System.currentTimeMillis() );
353 public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
355 this.archivaAdministration = archivaAdministration;