This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.repository.scanner;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.admin.model.RepositoryAdminException;
023import org.apache.archiva.admin.model.admin.ArchivaAdministration;
024import org.apache.archiva.admin.model.beans.ManagedRepository;
025import org.apache.archiva.common.utils.BaseFile;
026import org.apache.archiva.configuration.ArchivaConfiguration;
027import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
028import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
029import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate;
030import org.apache.archiva.redback.components.registry.RegistryListener;
031import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
032import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
033import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
034import org.apache.commons.collections.Closure;
035import org.apache.commons.collections.CollectionUtils;
036import org.apache.commons.collections.functors.IfClosure;
037import org.springframework.beans.BeansException;
038import org.springframework.context.ApplicationContext;
039import org.springframework.context.ApplicationContextAware;
040import org.springframework.stereotype.Service;
041
042import javax.inject.Inject;
043import java.io.File;
044import java.util.ArrayList;
045import java.util.Date;
046import java.util.HashMap;
047import java.util.List;
048import java.util.Map;
049
050/**
051 * RepositoryContentConsumerUtil
052 */
053@Service("repositoryContentConsumers")
054public class RepositoryContentConsumers
055    implements ApplicationContextAware
056{
057
058    @Inject
059    private ApplicationContext applicationContext;
060
061    private ArchivaAdministration archivaAdministration;
062
063    private List<KnownRepositoryContentConsumer> selectedKnownConsumers;
064
065    private List<InvalidRepositoryContentConsumer> selectedInvalidConsumers;
066
067    @Inject
068    private ArchivaConfiguration archivaConfiguration;
069
070    @Inject
071    public RepositoryContentConsumers( ArchivaAdministration archivaAdministration )
072    {
073        this.archivaAdministration = archivaAdministration;
074    }
075
076    @Override
077    public void setApplicationContext( ApplicationContext applicationContext )
078        throws BeansException
079    {
080        this.applicationContext = applicationContext;
081    }
082
083    /**
084     * <p>
085     * Get the list of Ids associated with those {@link KnownRepositoryContentConsumer} that have
086     * been selected in the configuration to execute.
087     * </p>
088     * <p>
089     * NOTE: This list can be larger and contain entries that might not exist or be available
090     * in the classpath, or as a component.
091     * </p>
092     *
093     * @return the list of consumer ids that have been selected by the configuration.
094     */
095    public List<String> getSelectedKnownConsumerIds()
096        throws RepositoryAdminException
097    {
098        return archivaAdministration.getKnownContentConsumers();
099    }
100
101    /**
102     * <p>
103     * Get the list of Ids associated with those {@link InvalidRepositoryContentConsumer} that have
104     * been selected in the configuration to execute.
105     * </p>
106     * <p>
107     * NOTE: This list can be larger and contain entries that might not exist or be available
108     * in the classpath, or as a component.
109     * </p>
110     *
111     * @return the list of consumer ids that have been selected by the configuration.
112     */
113    public List<String> getSelectedInvalidConsumerIds()
114        throws RepositoryAdminException
115    {
116        return archivaAdministration.getInvalidContentConsumers();
117    }
118
119    /**
120     * Get the map of {@link String} ids to {@link KnownRepositoryContentConsumer} implementations,
121     * for those consumers that have been selected according to the active configuration.
122     *
123     * @return the map of String ids to {@link KnownRepositoryContentConsumer} objects.
124     */
125    public Map<String, KnownRepositoryContentConsumer> getSelectedKnownConsumersMap()
126        throws RepositoryAdminException
127    {
128        Map<String, KnownRepositoryContentConsumer> consumerMap = new HashMap<>();
129
130        for ( KnownRepositoryContentConsumer consumer : getSelectedKnownConsumers() )
131        {
132            consumerMap.put( consumer.getId(), consumer );
133        }
134
135        return consumerMap;
136    }
137
138    /**
139     * Get the map of {@link String} ids to {@link InvalidRepositoryContentConsumer} implementations,
140     * for those consumers that have been selected according to the active configuration.
141     *
142     * @return the map of String ids to {@link InvalidRepositoryContentConsumer} objects.
143     */
144    public Map<String, InvalidRepositoryContentConsumer> getSelectedInvalidConsumersMap()
145        throws RepositoryAdminException
146    {
147        Map<String, InvalidRepositoryContentConsumer> consumerMap = new HashMap<>();
148
149        for ( InvalidRepositoryContentConsumer consumer : getSelectedInvalidConsumers() )
150        {
151            consumerMap.put( consumer.getId(), consumer );
152        }
153
154        return consumerMap;
155    }
156
157    /**
158     * Get the list of {@link KnownRepositoryContentConsumer} objects that are
159     * selected according to the active configuration.
160     *
161     * @return the list of {@link KnownRepositoryContentConsumer} that have been selected
162     * by the active configuration.
163     */
164    public List<KnownRepositoryContentConsumer> getSelectedKnownConsumers()
165        throws RepositoryAdminException
166    {
167        // FIXME only for testing
168        if ( selectedKnownConsumers != null )
169        {
170            return selectedKnownConsumers;
171        }
172        List<KnownRepositoryContentConsumer> ret = new ArrayList<>();
173
174        List<String> knownSelected = getSelectedKnownConsumerIds();
175
176        for ( KnownRepositoryContentConsumer consumer : getAvailableKnownConsumers() )
177        {
178            if ( knownSelected.contains( consumer.getId() ) )
179            {
180                ret.add( consumer );
181            }
182        }
183        return ret;
184    }
185
186    public void releaseSelectedKnownConsumers( List<KnownRepositoryContentConsumer> repositoryContentConsumers )
187    {
188        if ( repositoryContentConsumers == null )
189        {
190            return;
191        }
192        for ( KnownRepositoryContentConsumer knownRepositoryContentConsumer : repositoryContentConsumers )
193        {
194            if ( RegistryListener.class.isAssignableFrom( knownRepositoryContentConsumer.getClass() ) )
195            {
196                archivaConfiguration.removeChangeListener(
197                    RegistryListener.class.cast( knownRepositoryContentConsumer ) );
198            }
199        }
200    }
201
202    /**
203     * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
204     * selected according to the active configuration.
205     *
206     * @return the list of {@link InvalidRepositoryContentConsumer} that have been selected
207     * by the active configuration.
208     */
209    public synchronized List<InvalidRepositoryContentConsumer> getSelectedInvalidConsumers()
210        throws RepositoryAdminException
211    {
212
213        // FIXME only for testing
214        if ( selectedInvalidConsumers != null )
215        {
216            return selectedInvalidConsumers;
217        }
218
219        List<InvalidRepositoryContentConsumer> ret = new ArrayList<>();
220
221        List<String> invalidSelected = getSelectedInvalidConsumerIds();
222
223        for ( InvalidRepositoryContentConsumer consumer : getAvailableInvalidConsumers() )
224        {
225            if ( invalidSelected.contains( consumer.getId() ) )
226            {
227                ret.add( consumer );
228            }
229        }
230        return ret;
231    }
232
233
234    /**
235     * Get the list of {@link KnownRepositoryContentConsumer} objects that are
236     * available and present in the classpath and as components in the IoC.
237     *
238     * @return the list of all available {@link KnownRepositoryContentConsumer} present in the classpath
239     * and as a component in the IoC.
240     */
241    public List<KnownRepositoryContentConsumer> getAvailableKnownConsumers()
242    {
243        return new ArrayList<>( applicationContext.getBeansOfType( KnownRepositoryContentConsumer.class ).values() );
244    }
245
246    /**
247     * Get the list of {@link InvalidRepositoryContentConsumer} objects that are
248     * available and present in the classpath and as components in the IoC.
249     *
250     * @return the list of all available {@link InvalidRepositoryContentConsumer} present in the classpath
251     * and as a component in the IoC.
252     */
253    public List<InvalidRepositoryContentConsumer> getAvailableInvalidConsumers()
254    {
255        return new ArrayList<>( applicationContext.getBeansOfType( InvalidRepositoryContentConsumer.class ).values() );
256    }
257
258    /**
259     * A convienence method to execute all of the active selected consumers for a
260     * particular arbitrary file.
261     * NOTE: Make sure that there is no repository scanning task executing before invoking this so as to prevent
262     * the index writer/reader of the current index-content consumer executing from getting closed. For an example,
263     * see ArchivaDavResource#executeConsumers( File ).
264     *
265     * @param repository             the repository configuration to use.
266     * @param localFile              the local file to execute the consumers against.
267     * @param updateRelatedArtifacts TODO
268     */
269    public void executeConsumers( ManagedRepository repository, File localFile, boolean updateRelatedArtifacts )
270        throws RepositoryAdminException
271    {
272        List<KnownRepositoryContentConsumer> selectedKnownConsumers = null;
273        // Run the repository consumers
274        try
275        {
276            Closure triggerBeginScan = new TriggerBeginScanClosure( repository, getStartTime(), false );
277
278            selectedKnownConsumers = getSelectedKnownConsumers();
279
280            // MRM-1212/MRM-1197 
281            // - do not create missing/fix invalid checksums and update metadata when deploying from webdav since these are uploaded by maven
282            if ( !updateRelatedArtifacts )
283            {
284                List<KnownRepositoryContentConsumer> clone = new ArrayList<>();
285                clone.addAll( selectedKnownConsumers );
286
287                for ( KnownRepositoryContentConsumer consumer : clone )
288                {
289                    if ( consumer.getId().equals( "create-missing-checksums" ) || consumer.getId().equals(
290                        "metadata-updater" ) )
291                    {
292                        selectedKnownConsumers.remove( consumer );
293                    }
294                }
295            }
296
297            List<InvalidRepositoryContentConsumer> selectedInvalidConsumers = getSelectedInvalidConsumers();
298            CollectionUtils.forAllDo( selectedKnownConsumers, triggerBeginScan );
299            CollectionUtils.forAllDo( selectedInvalidConsumers, triggerBeginScan );
300
301            // yuck. In case you can't read this, it says
302            // "process the file if the consumer has it in the includes list, and not in the excludes list"
303            BaseFile baseFile = new BaseFile( repository.getLocation(), localFile );
304            ConsumerWantsFilePredicate predicate = new ConsumerWantsFilePredicate( repository );
305            predicate.setBasefile( baseFile );
306            predicate.setCaseSensitive( false );
307
308            ConsumerProcessFileClosure closure = new ConsumerProcessFileClosure();
309            closure.setBasefile( baseFile );
310            closure.setExecuteOnEntireRepo( false );
311
312            Closure processIfWanted = IfClosure.getInstance( predicate, closure );
313
314            CollectionUtils.forAllDo( selectedKnownConsumers, processIfWanted );
315
316            if ( predicate.getWantedFileCount() <= 0 )
317            {
318                // Nothing known processed this file.  It is invalid!
319                CollectionUtils.forAllDo( selectedInvalidConsumers, closure );
320            }
321
322            TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, false );
323
324            CollectionUtils.forAllDo( selectedKnownConsumers, scanCompletedClosure );
325        }
326        finally
327        {
328            /* TODO: This is never called by the repository scanner instance, so not calling here either - but it probably should be?
329                        CollectionUtils.forAllDo( availableKnownConsumers, triggerCompleteScan );
330                        CollectionUtils.forAllDo( availableInvalidConsumers, triggerCompleteScan );
331            */
332            releaseSelectedKnownConsumers( selectedKnownConsumers );
333        }
334    }
335
336    public void setSelectedKnownConsumers( List<KnownRepositoryContentConsumer> selectedKnownConsumers )
337    {
338        this.selectedKnownConsumers = selectedKnownConsumers;
339    }
340
341    public void setSelectedInvalidConsumers( List<InvalidRepositoryContentConsumer> selectedInvalidConsumers )
342    {
343        this.selectedInvalidConsumers = selectedInvalidConsumers;
344    }
345
346    protected Date getStartTime()
347    {
348        return new Date( System.currentTimeMillis() );
349    }
350
351    public void setArchivaAdministration( ArchivaAdministration archivaAdministration )
352    {
353        this.archivaAdministration = archivaAdministration;
354    }
355}