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.beans.ManagedRepository;
023import org.apache.archiva.common.utils.BaseFile;
024import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
025import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
026import org.apache.archiva.consumers.functors.ConsumerWantsFilePredicate;
027import org.apache.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
028import org.apache.archiva.repository.scanner.functors.TriggerBeginScanClosure;
029import org.apache.archiva.repository.scanner.functors.TriggerScanCompletedClosure;
030import org.apache.commons.collections.Closure;
031import org.apache.commons.collections.CollectionUtils;
032import org.apache.commons.collections.functors.IfClosure;
033import org.apache.commons.lang.SystemUtils;
034import org.codehaus.plexus.util.DirectoryWalkListener;
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038import java.io.File;
039import java.util.Date;
040import java.util.HashMap;
041import java.util.List;
042import java.util.Map;
043
044/**
045 * RepositoryScannerInstance
046 */
047public class RepositoryScannerInstance
048    implements DirectoryWalkListener
049{
050    private Logger log = LoggerFactory.getLogger( RepositoryScannerInstance.class );
051
052    /**
053     * Consumers that process known content.
054     */
055    private List<KnownRepositoryContentConsumer> knownConsumers;
056
057    /**
058     * Consumers that process unknown/invalid content.
059     */
060    private List<InvalidRepositoryContentConsumer> invalidConsumers;
061
062    private ManagedRepository repository;
063
064    private RepositoryScanStatistics stats;
065
066    private long changesSince = 0;
067
068    private ConsumerProcessFileClosure consumerProcessFile;
069
070    private ConsumerWantsFilePredicate consumerWantsFile;
071
072    private Map<String, Long> consumerTimings;
073
074    private Map<String, Long> consumerCounts;
075
076    public RepositoryScannerInstance( ManagedRepository repository,
077                                      List<KnownRepositoryContentConsumer> knownConsumerList,
078                                      List<InvalidRepositoryContentConsumer> invalidConsumerList )
079    {
080        this.repository = repository;
081        this.knownConsumers = knownConsumerList;
082        this.invalidConsumers = invalidConsumerList;
083
084        consumerTimings = new HashMap<>();
085        consumerCounts = new HashMap<>();
086
087        this.consumerProcessFile = new ConsumerProcessFileClosure();
088        consumerProcessFile.setExecuteOnEntireRepo( true );
089        consumerProcessFile.setConsumerTimings( consumerTimings );
090        consumerProcessFile.setConsumerCounts( consumerCounts );
091
092        this.consumerWantsFile = new ConsumerWantsFilePredicate( repository );
093
094        stats = new RepositoryScanStatistics();
095        stats.setRepositoryId( repository.getId() );
096
097        Closure triggerBeginScan =
098            new TriggerBeginScanClosure( repository, new Date( System.currentTimeMillis() ), true );
099
100        CollectionUtils.forAllDo( knownConsumerList, triggerBeginScan );
101        CollectionUtils.forAllDo( invalidConsumerList, triggerBeginScan );
102
103        if ( SystemUtils.IS_OS_WINDOWS )
104        {
105            consumerWantsFile.setCaseSensitive( false );
106        }
107    }
108
109    public RepositoryScannerInstance( ManagedRepository repository,
110                                      List<KnownRepositoryContentConsumer> knownContentConsumers,
111                                      List<InvalidRepositoryContentConsumer> invalidContentConsumers,
112                                      long changesSince )
113    {
114        this( repository, knownContentConsumers, invalidContentConsumers );
115
116        consumerWantsFile.setChangesSince( changesSince );
117
118        this.changesSince = changesSince;
119    }
120
121    public RepositoryScanStatistics getStatistics()
122    {
123        return stats;
124    }
125
126    public Map<String, Long> getConsumerTimings()
127    {
128        return consumerTimings;
129    }
130
131    public Map<String, Long> getConsumerCounts()
132    {
133        return consumerCounts;
134    }
135
136    @Override
137    public void directoryWalkStarting( File basedir )
138    {
139        log.info( "Walk Started: [{}] {}", this.repository.getId(), this.repository.getLocation() );
140        stats.triggerStart();
141    }
142
143    @Override
144    public void directoryWalkStep( int percentage, File file )
145    {
146        log.debug( "Walk Step: {}, {}", percentage, file );
147
148        stats.increaseFileCount();
149
150        // consume files regardless - the predicate will check the timestamp
151        BaseFile basefile = new BaseFile( repository.getLocation(), file );
152
153        // Safety check, if a parallel process removes the file
154        if (basefile.exists())
155        {
156
157            // Timestamp finished points to the last successful scan, not this current one.
158            if ( file.lastModified( ) >= changesSince )
159            {
160                stats.increaseNewFileCount( );
161            }
162
163            consumerProcessFile.setBasefile( basefile );
164            consumerWantsFile.setBasefile( basefile );
165
166            Closure processIfWanted = IfClosure.getInstance( consumerWantsFile, consumerProcessFile );
167            CollectionUtils.forAllDo( this.knownConsumers, processIfWanted );
168
169            if ( consumerWantsFile.getWantedFileCount( ) <= 0 )
170            {
171                // Nothing known processed this file.  It is invalid!
172                CollectionUtils.forAllDo( this.invalidConsumers, consumerProcessFile );
173            }
174        }
175    }
176
177    @Override
178    public void directoryWalkFinished()
179    {
180        TriggerScanCompletedClosure scanCompletedClosure = new TriggerScanCompletedClosure( repository, true );
181        CollectionUtils.forAllDo( knownConsumers, scanCompletedClosure );
182        CollectionUtils.forAllDo( invalidConsumers, scanCompletedClosure );
183
184        stats.setConsumerTimings( consumerTimings );
185        stats.setConsumerCounts( consumerCounts );
186
187        log.info( "Walk Finished: [{}] {}", this.repository.getId(), this.repository.getLocation() );
188        stats.triggerFinished();
189    }
190
191    /**
192     * Debug method from DirectoryWalker.
193     */
194    @Override
195    public void debug( String message )
196    {
197        log.debug( "Repository Scanner: {}", message );
198    }
199
200    public ManagedRepository getRepository()
201    {
202        return repository;
203    }
204
205    public RepositoryScanStatistics getStats()
206    {
207        return stats;
208    }
209
210    public long getChangesSince()
211    {
212        return changesSince;
213    }
214}