1package org.apache.archiva.repository.scanner;
23/*4 * Licensed to the Apache Software Foundation (ASF) under one5 * or more contributor license agreements. See the NOTICE file6 * distributed with this work for additional information7 * regarding copyright ownership. The ASF licenses this file8 * to you under the Apache License, Version 2.0 (the9 * "License"); you may not use this file except in compliance10 * with the License. You may obtain a copy of the License at11 *12 * http://www.apache.org/licenses/LICENSE-2.013 *14 * Unless required by applicable law or agreed to in writing,15 * software distributed under the License is distributed on an16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 * KIND, either express or implied. See the License for the18 * specific language governing permissions and limitations19 * under the License.20 */2122import org.apache.archiva.admin.model.RepositoryAdminException;
23import org.apache.archiva.admin.model.admin.ArchivaAdministration;
24import org.apache.archiva.common.utils.BaseFile;
25import org.apache.archiva.common.utils.PathUtil;
26import org.apache.archiva.configuration.ArchivaConfiguration;
27import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
28import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
29import org.apache.archiva.consumers.RepositoryContentConsumer;
30import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate;
31import org.apache.archiva.components.registry.RegistryListener;
32import org.apache.archiva.repository.ManagedRepository;
33import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
34import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
35import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
36import org.apache.commons.collections4.Closure;
37import org.apache.commons.collections4.CollectionUtils;
38import org.apache.commons.collections4.IterableUtils;
39import org.apache.commons.collections4.functors.IfClosure;
40import org.springframework.beans.BeansException;
41import org.springframework.context.ApplicationContext;
42import org.springframework.context.ApplicationContextAware;
43import org.springframework.stereotype.Service;
4445import javax.inject.Inject;
46import java.nio.file.Path;
47import java.util.ArrayList;
48import java.util.Date;
49import java.util.HashMap;
50import java.util.List;
51import java.util.Map;
5253/**54 * RepositoryContentConsumerUtil55 */56 @Service("repositoryContentConsumers")
57publicclassRepositoryContentConsumers58implements ApplicationContextAware
59 {
6061 @Inject
62private ApplicationContext applicationContext;
6364privateArchivaAdministration archivaAdministration;
6566private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
6768private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
6970 @Inject
71privateArchivaConfiguration archivaConfiguration;
7273 @Inject
74publicRepositoryContentConsumers( ArchivaAdministration archivaAdministration )
75 {
76this.archivaAdministration = archivaAdministration;
77 }
7879 @Override
80publicvoid setApplicationContext( ApplicationContext applicationContext )
81throws BeansException
82 {
83this.applicationContext = applicationContext;
84 }
8586/**87 * <p>88 * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have89 * been selected in the configuration to execute.90 * </p>91 * <p>92 * NOTE: This list can be larger and contain entries that might not exist or be available93 * in the classpath, or as a component.94 * </p>95 *96 * @return the list of consumer ids that have been selected by the configuration.97 */98public List<String> getSelectedKnownConsumerIds()
99throwsRepositoryAdminException100 {
101return archivaAdministration.getKnownContentConsumers();
102 }
103104/**105 * <p>106 * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have107 * been selected in the configuration to execute.108 * </p>109 * <p>110 * NOTE: This list can be larger and contain entries that might not exist or be available111 * in the classpath, or as a component.112 * </p>113 *114 * @return the list of consumer ids that have been selected by the configuration.115 */116public List<String> getSelectedInvalidConsumerIds()
117throwsRepositoryAdminException118 {
119return archivaAdministration.getInvalidContentConsumers();
120 }
121122/**123 * Get the map of {@link String} ids to {@link KnownRepositoryContentConsumer} implementations,124 * for those consumers that have been selected according to the active configuration.125 *126 * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.127 */128public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
129throwsRepositoryAdminException130 {
131 Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
132133for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
134 {
135 consumerMap.put( consumer.getId(), consumer );
136 }
137138return consumerMap;
139 }
140141/**142 * Get the map of {@link String} ids to {@link InvalidRepositoryContentConsumer} implementations,143 * for those consumers that have been selected according to the active configuration.144 *145 * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.146 */147public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
148throwsRepositoryAdminException149 {
150 Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
151152for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
153 {
154 consumerMap.put( consumer.getId(), consumer );
155 }
156157return consumerMap;
158 }
159160/**161 * Get the list of {@link KnownRepositoryContentConsumer} objects that are162 * selected according to the active configuration.163 *164 * @return the list of {@link KnownRepositoryContentConsumer} that have been selected165 * by the active configuration.166 */167public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
168throwsRepositoryAdminException169 {
170// FIXME only for testing171if ( selectedKnownConsumers != null )
172 {
173return selectedKnownConsumers;
174 }
175 List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
176177 List<String> knownSelected = getSelectedKnownConsumerIds();
178179for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
180 {
181if ( knownSelected.contains( consumer.getId() ) )
182 {
183 ret.add( consumer );
184 }
185 }
186return ret;
187 }
188189publicvoid releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
190 {
191if ( repositoryContentConsumers == null )
192 {
193return;
194 }
195for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
196 {
197if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
198 {
199 archivaConfiguration.removeChangeListener(
200 RegistryListener.class.cast( knownRepositoryContentConsumer ) );
201 }
202 }
203 }
204205/**206 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are207 * selected according to the active configuration.208 *209 * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected210 * by the active configuration.211 */212publicsynchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
213throwsRepositoryAdminException214 {
215216// FIXME only for testing217if ( selectedInvalidConsumers != null )
218 {
219return selectedInvalidConsumers;
220 }
221222 List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
223224 List<String> invalidSelected = getSelectedInvalidConsumerIds();
225226for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
227 {
228if ( invalidSelected.contains( consumer.getId() ) )
229 {
230 ret.add( consumer );
231 }
232 }
233return ret;
234 }
235236237/**238 * Get the list of {@link KnownRepositoryContentConsumer} objects that are239 * available and present in the classpath and as components in the IoC.240 *241 * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath242 * and as a component in the IoC.243 */244public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
245 {
246returnnew ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
247 }
248249/**250 * Get the list of {@link InvalidRepositoryContentConsumer} objects that are251 * available and present in the classpath and as components in the IoC.252 *253 * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath254 * and as a component in the IoC.255 */256public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
257 {
258returnnew ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
259 }
260261/**262 * A convienence method to execute all of the active selected consumers for a263 * particular arbitrary file.264 * NOTE: Make sure that there is no repository scanning task executing before invoking this so as to prevent265 * the index writer/reader of the current index-content consumer executing from getting closed. For an example,266 * see ArchivaDavResource#executeConsumers( File ).267 *268 * @param repository the repository configuration to use.269 * @param localFile the local file to execute the consumers against.270 * @param updateRelatedArtifacts TODO271 */272publicvoid executeConsumers( ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
273throwsRepositoryAdminException274 {
275 List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
276// Run the repository consumers277try278 {
279 Closure<RepositoryContentConsumer> triggerBeginScan = newTriggerBeginScanClosure( repository, getStartTime(), false );
280281 selectedKnownConsumers = getSelectedKnownConsumers();
282283// MRM-1212/MRM-1197 284// - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven285if ( !updateRelatedArtifacts )
286 {
287 List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
288 clone.addAll( selectedKnownConsumers );
289290for ( KnownRepositoryContentConsumer consumer : clone )
291 {
292if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
293"metadata-updater" ) )
294 {
295 selectedKnownConsumers.remove( consumer );
296 }
297 }
298 }
299300 List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
301 IterableUtils.forEach( selectedKnownConsumers, triggerBeginScan );
302 IterableUtils.forEach( selectedInvalidConsumers, triggerBeginScan );
303304// yuck. In case you can't read this, it says305// "process the file if the consumer has it in the includes list, and not in the excludes list"306 Path repoPath = PathUtil.getPathFromUri( repository.getLocation() );
307BaseFilels/BaseFile.html#BaseFile">BaseFile baseFile = newBaseFile( repoPath.toString(), localFile.toFile() );
308ConsumerWantsFilePredicatentsFilePredicate.html#ConsumerWantsFilePredicate">ConsumerWantsFilePredicate predicate = newConsumerWantsFilePredicate( repository );
309 predicate.setBasefile( baseFile );
310 predicate.setCaseSensitive( false );
311312ConsumerProcessFileClosure/ConsumerProcessFileClosure.html#ConsumerProcessFileClosure">ConsumerProcessFileClosure closure = newConsumerProcessFileClosure();
313 closure.setBasefile( baseFile );
314 closure.setExecuteOnEntireRepo( false );
315316 Closure<RepositoryContentConsumer> processIfWanted = IfClosure.ifClosure( predicate, closure );
317318 IterableUtils.forEach( selectedKnownConsumers, processIfWanted );
319320if ( predicate.getWantedFileCount() <= 0 )
321 {
322// Nothing known processed this file. It is invalid!323 IterableUtils.forEach( selectedInvalidConsumers, closure );
324 }
325326TriggerScanCompletedClosurempletedClosure.html#TriggerScanCompletedClosure">TriggerScanCompletedClosure scanCompletedClosure = newTriggerScanCompletedClosure( repository, false );
327328 IterableUtils.forEach( selectedKnownConsumers, scanCompletedClosure );
329 }
330finally331 {
332/* TODO: This is never called by the repository scanner instance, so not calling here either - but it probably should be?333 IterableUtils.forEach( availableKnownConsumers, triggerCompleteScan );334 IterableUtils.forEach( availableInvalidConsumers, triggerCompleteScan );335 */336 releaseSelectedKnownConsumers( selectedKnownConsumers );
337 }
338 }
339340publicvoid setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
341 {
342this.selectedKnownConsumers = selectedKnownConsumers;
343 }
344345publicvoid setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
346 {
347this.selectedInvalidConsumers = selectedInvalidConsumers;
348 }
349350protected Date getStartTime()
351 {
352returnnew Date( System.currentTimeMillis() );
353 }
354355publicvoid setArchivaAdministration( ArchivaAdministration archivaAdministration )
356 {
357this.archivaAdministration = archivaAdministration;
358 }
359 }