001    package 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    
022    import org.apache.archiva.admin.model.RepositoryAdminException;
023    import org.apache.archiva.admin.model.beans.ManagedRepository;
024    import org.apache.archiva.configuration.FileTypes;
025    import org.apache.archiva.consumers.InvalidRepositoryContentConsumer;
026    import org.apache.archiva.consumers.KnownRepositoryContentConsumer;
027    import org.apache.archiva.consumers.RepositoryContentConsumer;
028    import org.apache.commons.collections.CollectionUtils;
029    import org.codehaus.plexus.util.DirectoryWalker;
030    import org.springframework.stereotype.Service;
031    
032    import javax.inject.Inject;
033    import java.io.File;
034    import java.util.ArrayList;
035    import java.util.LinkedHashSet;
036    import java.util.List;
037    import java.util.Set;
038    
039    /**
040     * DefaultRepositoryScanner
041     *
042     *
043     */
044    @Service( "repositoryScanner#default" )
045    public class DefaultRepositoryScanner
046        implements RepositoryScanner
047    {
048        /**
049         *
050         */
051        @Inject
052        private FileTypes filetypes;
053    
054        /**
055         *
056         */
057        @Inject
058        private RepositoryContentConsumers consumerUtil;
059    
060        private Set<RepositoryScannerInstance> inProgressScans = new LinkedHashSet<RepositoryScannerInstance>();
061    
062        public RepositoryScanStatistics scan( ManagedRepository repository, long changesSince )
063            throws RepositoryScannerException
064        {
065            try
066            {
067                List<KnownRepositoryContentConsumer> knownContentConsumers = consumerUtil.getSelectedKnownConsumers();
068                List<InvalidRepositoryContentConsumer> invalidContentConsumers = consumerUtil.getSelectedInvalidConsumers();
069                List<String> ignoredPatterns = filetypes.getFileTypePatterns( FileTypes.IGNORED );
070    
071                return scan( repository, knownContentConsumers, invalidContentConsumers, ignoredPatterns, changesSince );
072            }
073            catch ( RepositoryAdminException e )
074            {
075                throw new RepositoryScannerException( e.getMessage(), e );
076            }
077        }
078    
079        public RepositoryScanStatistics scan( ManagedRepository repository,
080                                              List<KnownRepositoryContentConsumer> knownContentConsumers,
081                                              List<InvalidRepositoryContentConsumer> invalidContentConsumers,
082                                              List<String> ignoredContentPatterns, long changesSince )
083            throws RepositoryScannerException
084        {
085            if ( repository == null )
086            {
087                throw new IllegalArgumentException( "Unable to operate on a null repository." );
088            }
089    
090            File repositoryBase = new File( repository.getLocation() );
091    
092            //MRM-1342 Repository statistics report doesn't appear to be working correctly
093            //create the repo if not existing to have an empty stats
094            if ( !repositoryBase.exists() && !repositoryBase.mkdirs() )
095            {
096                throw new UnsupportedOperationException(
097                    "Unable to scan a repository, directory " + repositoryBase.getPath() + " does not exist." );
098            }
099    
100            if ( !repositoryBase.isDirectory() )
101            {
102                throw new UnsupportedOperationException(
103                    "Unable to scan a repository, path " + repositoryBase.getPath() + " is not a directory." );
104            }
105    
106            // Setup Includes / Excludes.
107    
108            List<String> allExcludes = new ArrayList<String>();
109            List<String> allIncludes = new ArrayList<String>();
110    
111            if ( CollectionUtils.isNotEmpty( ignoredContentPatterns ) )
112            {
113                allExcludes.addAll( ignoredContentPatterns );
114            }
115    
116            // Scan All Content. (intentional)
117            allIncludes.add( "**/*" );
118    
119            // Setup Directory Walker
120            DirectoryWalker dirWalker = new DirectoryWalker();
121    
122            dirWalker.setBaseDir( repositoryBase );
123    
124            dirWalker.setIncludes( allIncludes );
125            dirWalker.setExcludes( allExcludes );
126    
127            // Setup the Scan Instance
128            RepositoryScannerInstance scannerInstance =
129                new RepositoryScannerInstance( repository, knownContentConsumers, invalidContentConsumers, changesSince );
130    
131            inProgressScans.add( scannerInstance );
132    
133            RepositoryScanStatistics stats;
134            try
135            {
136                dirWalker.addDirectoryWalkListener( scannerInstance );
137    
138                // Execute scan.
139                dirWalker.scan();
140    
141                stats = scannerInstance.getStatistics();
142    
143                stats.setKnownConsumers( gatherIds( knownContentConsumers ) );
144                stats.setInvalidConsumers( gatherIds( invalidContentConsumers ) );
145            }
146            finally
147            {
148                inProgressScans.remove( scannerInstance );
149            }
150    
151            return stats;
152        }
153    
154        private List<String> gatherIds( List<? extends RepositoryContentConsumer> consumers )
155        {
156            List<String> ids = new ArrayList<String>();
157            for ( RepositoryContentConsumer consumer : consumers )
158            {
159                ids.add( consumer.getId() );
160            }
161            return ids;
162        }
163    
164        public Set<RepositoryScannerInstance> getInProgressScans()
165        {
166            return inProgressScans;
167        }
168    }