]> source.dussan.org Git - archiva.git/blob
0795fa557767db6ee791a9b1d615fb1ee15de433
[archiva.git] /
1 package org.apache.archiva.repository.scanner;
2
3 /*
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
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
21
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;
44
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;
51 import java.util.Map;
52
53 /**
54  * RepositoryContentConsumerUtil
55  */
56 @Service("repositoryContentConsumers")
57 public class RepositoryContentConsumers
58     implements ApplicationContextAware
59 {
60
61     @Inject
62     private ApplicationContext applicationContext;
63
64     private ArchivaAdministration archivaAdministration;
65
66     private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
67
68     private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
69
70     @Inject
71     private ArchivaConfiguration archivaConfiguration;
72
73     @Inject
74     public RepositoryContentConsumers( ArchivaAdministration archivaAdministration )
75     {
76         this.archivaAdministration = archivaAdministration;
77     }
78
79     @Override
80     public void setApplicationContext( ApplicationContext applicationContext )
81         throws BeansException
82     {
83         this.applicationContext = applicationContext;
84     }
85
86     /**
87      * <p>
88      * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have
89      * 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 available
93      * 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      */
98     public List<String> getSelectedKnownConsumerIds()
99         throws ConsumerException
100     {
101         try
102         {
103             return archivaAdministration.getKnownContentConsumers();
104         }
105         catch ( RepositoryAdminException e )
106         {
107             throw new ConsumerException( e.getMessage( ), e );
108         }
109     }
110
111     /**
112      * <p>
113      * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have
114      * been selected in the configuration to execute.
115      * </p>
116      * <p>
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.
119      * </p>
120      *
121      * @return the list of consumer ids that have been selected by the configuration.
122      */
123     public List<String> getSelectedInvalidConsumerIds()
124         throws ConsumerException
125     {
126         try
127         {
128             return archivaAdministration.getInvalidContentConsumers();
129         }
130         catch ( RepositoryAdminException e )
131         {
132             throw new ConsumerException( e.getMessage( ), e );
133         }
134     }
135
136     /**
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.
139      *
140      * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.
141      */
142     public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
143         throws ConsumerException
144     {
145         Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
146
147         for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
148         {
149             consumerMap.put( consumer.getId(), consumer );
150         }
151
152         return consumerMap;
153     }
154
155     /**
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.
158      *
159      * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.
160      */
161     public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
162         throws ConsumerException
163     {
164         Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
165
166         for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
167         {
168             consumerMap.put( consumer.getId(), consumer );
169         }
170
171         return consumerMap;
172     }
173
174     /**
175      * Get the list of {@link KnownRepositoryContentConsumer} objects that are
176      * selected according to the active configuration.
177      *
178      * @return the list of {@link KnownRepositoryContentConsumer} that have been selected
179      * by the active configuration.
180      */
181     public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
182         throws ConsumerException
183     {
184         // FIXME only for testing
185         if ( selectedKnownConsumers != null )
186         {
187             return selectedKnownConsumers;
188         }
189         List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
190
191         List<String> knownSelected = getSelectedKnownConsumerIds();
192
193         for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
194         {
195             if ( knownSelected.contains( consumer.getId() ) )
196             {
197                 ret.add( consumer );
198             }
199         }
200         return ret;
201     }
202
203     public void releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
204     {
205         if ( repositoryContentConsumers == null )
206         {
207             return;
208         }
209         for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
210         {
211             if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
212             {
213                 archivaConfiguration.removeChangeListener(
214                     RegistryListener.class.cast( knownRepositoryContentConsumer ) );
215             }
216         }
217     }
218
219     /**
220      * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
221      * selected according to the active configuration.
222      *
223      * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected
224      * by the active configuration.
225      */
226     public synchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
227         throws ConsumerException
228     {
229
230         // FIXME only for testing
231         if ( selectedInvalidConsumers != null )
232         {
233             return selectedInvalidConsumers;
234         }
235
236         List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
237
238         List<String> invalidSelected = null;
239         try
240         {
241             invalidSelected = getSelectedInvalidConsumerIds();
242         }
243         catch ( ConsumerException e )
244         {
245             e.printStackTrace( );
246         }
247
248         for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
249         {
250             if ( invalidSelected.contains( consumer.getId() ) )
251             {
252                 ret.add( consumer );
253             }
254         }
255         return ret;
256     }
257
258
259     /**
260      * Get the list of {@link KnownRepositoryContentConsumer} objects that are
261      * available and present in the classpath and as components in the IoC.
262      *
263      * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath
264      * and as a component in the IoC.
265      */
266     public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
267     {
268         return new ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
269     }
270
271     /**
272      * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
273      * available and present in the classpath and as components in the IoC.
274      *
275      * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath
276      * and as a component in the IoC.
277      */
278     public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
279     {
280         return new ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
281     }
282
283     /**
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
292      */
293     public void executeConsumers( ManagedRepository repository, Path localFile, boolean updateRelatedArtifacts )
294         throws ConsumerException
295     {
296         List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
297         // Run the repository consumers
298         try
299         {
300             Closure<RepositoryContentConsumer> triggerBeginScan = new TriggerBeginScanClosure( repository, getStartTime(), false );
301
302             selectedKnownConsumers = getSelectedKnownConsumers();
303
304             // MRM-1212/MRM-1197 
305             // - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven
306             if ( !updateRelatedArtifacts )
307             {
308                 List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
309                 clone.addAll( selectedKnownConsumers );
310
311                 for ( KnownRepositoryContentConsumer consumer : clone )
312                 {
313                     if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
314                         "metadata-updater" ) )
315                     {
316                         selectedKnownConsumers.remove( consumer );
317                     }
318                 }
319             }
320
321             List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
322             IterableUtils.forEach( selectedKnownConsumers, triggerBeginScan );
323             IterableUtils.forEach( selectedInvalidConsumers, triggerBeginScan );
324
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 );
332
333             ConsumerProcessFileClosure closure = new ConsumerProcessFileClosure();
334             closure.setBasefile( baseFile );
335             closure.setExecuteOnEntireRepo( false );
336
337             Closure<RepositoryContentConsumer> processIfWanted = IfClosure.ifClosure( predicate, closure );
338
339             IterableUtils.forEach( selectedKnownConsumers, processIfWanted );
340
341             if ( predicate.getWantedFileCount() <= 0 )
342             {
343                 // Nothing known processed this file.  It is invalid!
344                 IterableUtils.forEach( selectedInvalidConsumers, closure );
345             }
346
347             TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, false );
348
349             IterableUtils.forEach( selectedKnownConsumers, scanCompletedClosure );
350         }
351         finally
352         {
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 );
356             */
357             releaseSelectedKnownConsumers( selectedKnownConsumers );
358         }
359     }
360
361     public void setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
362     {
363         this.selectedKnownConsumers = selectedKnownConsumers;
364     }
365
366     public void setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
367     {
368         this.selectedInvalidConsumers = selectedInvalidConsumers;
369     }
370
371     protected Date getStartTime()
372     {
373         return new Date( System.currentTimeMillis() );
374     }
375
376     public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
377     {
378         this.archivaAdministration = archivaAdministration;
379     }
380 }