summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/FileTypes.java11
-rw-r--r--archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java6
-rw-r--r--archiva-base/archiva-converter/pom.xml4
-rw-r--r--archiva-base/archiva-converter/src/main/java/org/apache/maven/archiva/converter/legacy/DefaultLegacyRepositoryConverter.java21
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/DefaultRepositoryScanner.java128
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryContentConsumerUtil.java25
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScanner.java178
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerInstance.java157
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerProcessFileClosure.java89
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerWantsFilePredicate.java122
-rw-r--r--archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/TriggerBeginScanClosure.java63
-rw-r--r--archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/InvalidScanConsumer.java92
-rw-r--r--archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/KnownScanConsumer.java (renamed from archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/ScanConsumer.java)11
-rw-r--r--archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerTest.java124
-rw-r--r--archiva-cli/src/main/java/org/apache/maven/archiva/cli/ArchivaCli.java37
-rw-r--r--archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaScheduledTaskExecutor.java59
-rw-r--r--archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/scanning/RepositoryScanningAction.java63
-rw-r--r--archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryScanning.jsp223
-rw-r--r--archiva-web/archiva-webapp/src/main/webapp/css/site.css20
19 files changed, 986 insertions, 447 deletions
diff --git a/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/FileTypes.java b/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/FileTypes.java
index 783b35885..262b61468 100644
--- a/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/FileTypes.java
+++ b/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/FileTypes.java
@@ -49,11 +49,13 @@ public class FileTypes
implements Initializable
{
public static final String ARTIFACTS = "artifacts";
-
+
public static final String AUTO_REMOVE = "auto-remove";
-
+
public static final String INDEXABLE_CONTENT = "indexable-content";
-
+
+ public static final String IGNORED = "ignored";
+
/**
* @plexus.requirement
*/
@@ -110,7 +112,8 @@ public class FileTypes
try
{
- URL defaultArchivaXml = this.getClass().getResource( "" );
+ URL defaultArchivaXml = this.getClass()
+ .getResource( "/org/apache/maven/archiva/configuration/default-archiva.xml" );
XMLReader reader = new XMLReader( "configuration", defaultArchivaXml );
List resp = reader.getElementList( "//configuration/repositoryScanning/fileTypes/fileType" );
diff --git a/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java b/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java
index 0ce132e36..180bc1f8f 100644
--- a/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java
+++ b/archiva-base/archiva-configuration/src/test/java/org/apache/maven/archiva/configuration/ArchivaConfigurationTest.java
@@ -32,15 +32,11 @@ import java.util.List;
*/
public class ArchivaConfigurationTest extends PlexusTestCase
{
- private FileTypes filetypes;
-
public void testDefaults() throws Exception
{
ArchivaConfiguration archivaConfiguration =
(ArchivaConfiguration) lookup( ArchivaConfiguration.class, "test-defaults" );
- filetypes = (FileTypes) lookup( FileTypes.class );
-
Configuration configuration = archivaConfiguration.getConfiguration();
// check default configuration
@@ -53,6 +49,8 @@ public class ArchivaConfigurationTest extends PlexusTestCase
ArchivaConfiguration archivaConfiguration =
(ArchivaConfiguration) lookup( ArchivaConfiguration.class.getName(), "test-configuration" );
+ FileTypes filetypes = (FileTypes) lookup( FileTypes.class.getName() );
+
Configuration configuration = archivaConfiguration.getConfiguration();
assertEquals( "check repositories", 4, configuration.getRepositories().size() );
diff --git a/archiva-base/archiva-converter/pom.xml b/archiva-base/archiva-converter/pom.xml
index dbfeca6cd..6ae0fe21a 100644
--- a/archiva-base/archiva-converter/pom.xml
+++ b/archiva-base/archiva-converter/pom.xml
@@ -71,6 +71,10 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus.registry</groupId>
+ <artifactId>plexus-registry-commons</artifactId>
+ </dependency>
<!-- TEST DEPS -->
<dependency>
<groupId>hsqldb</groupId>
diff --git a/archiva-base/archiva-converter/src/main/java/org/apache/maven/archiva/converter/legacy/DefaultLegacyRepositoryConverter.java b/archiva-base/archiva-converter/src/main/java/org/apache/maven/archiva/converter/legacy/DefaultLegacyRepositoryConverter.java
index 4926f5aa8..bdabf5a1b 100644
--- a/archiva-base/archiva-converter/src/main/java/org/apache/maven/archiva/converter/legacy/DefaultLegacyRepositoryConverter.java
+++ b/archiva-base/archiva-converter/src/main/java/org/apache/maven/archiva/converter/legacy/DefaultLegacyRepositoryConverter.java
@@ -31,6 +31,8 @@ import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -54,11 +56,16 @@ public class DefaultLegacyRepositoryConverter
private ArtifactRepositoryLayout defaultLayout;
/**
- * @plexus.requirement role="org.apache.maven.archiva.consumers.RepositoryContentConsumer"
+ * @plexus.requirement role="org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer"
* role-hint="artifact-legacy-to-default-converter"
*/
private LegacyConverterArtifactConsumer legacyConverterConsumer;
+ /**
+ * @plexus.requirement
+ */
+ private RepositoryScanner repoScanner;
+
public void convertLegacyRepository( File legacyRepositoryDirectory, File repositoryDirectory,
List fileExclusionPatterns )
throws RepositoryConversionException
@@ -90,11 +97,15 @@ public class DefaultLegacyRepositoryConverter
legacyConverterConsumer.setExcludes( fileExclusionPatterns );
legacyConverterConsumer.setDestinationRepository( repository );
- List consumers = new ArrayList();
- consumers.add( legacyConverterConsumer );
+ List knownConsumers = new ArrayList();
+ knownConsumers.add( legacyConverterConsumer );
+
+ List invalidConsumers = Collections.EMPTY_LIST;
+ List ignoredContent = new ArrayList();
+ ignoredContent.addAll( Arrays.asList( RepositoryScanner.IGNORABLE_CONTENT ) );
- RepositoryScanner scanner = new RepositoryScanner();
- scanner.scan( legacyRepository, consumers, true );
+ repoScanner.scan( legacyRepository, knownConsumers, invalidConsumers, ignoredContent,
+ RepositoryScanner.FRESH_SCAN );
}
catch ( RepositoryException e )
{
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/DefaultRepositoryScanner.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/DefaultRepositoryScanner.java
new file mode 100644
index 000000000..45dab28e0
--- /dev/null
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/DefaultRepositoryScanner.java
@@ -0,0 +1,128 @@
+package org.apache.maven.archiva.repository.scanner;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.maven.archiva.configuration.FileTypes;
+import org.apache.maven.archiva.model.ArchivaRepository;
+import org.apache.maven.archiva.model.RepositoryContentStatistics;
+import org.apache.maven.archiva.repository.RepositoryException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.util.DirectoryWalker;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * DefaultRepositoryScanner
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ *
+ * @plexus.component role="org.apache.maven.archiva.repository.scanner.RepositoryScanner"
+ */
+public class DefaultRepositoryScanner
+ extends AbstractLogEnabled
+ implements RepositoryScanner
+{
+ /**
+ * @plexus.requirement
+ */
+ private FileTypes filetypes;
+
+ /**
+ * @plexus.requirement
+ */
+ private RepositoryContentConsumerUtil consumerUtil;
+
+ public RepositoryContentStatistics scan( ArchivaRepository repository, long changesSince )
+ throws RepositoryException
+ {
+ List knownContentConsumers = consumerUtil.getSelectedKnownConsumers();
+ List invalidContentConsumers = consumerUtil.getSelectedInvalidConsumers();
+ List ignoredPatterns = filetypes.getFileTypePatterns( FileTypes.IGNORED );
+
+ return scan( repository, knownContentConsumers, invalidContentConsumers, ignoredPatterns, changesSince );
+ }
+
+ public RepositoryContentStatistics scan( ArchivaRepository repository, List knownContentConsumers,
+ List invalidContentConsumers, List ignoredContentPatterns,
+ long changesSince )
+ throws RepositoryException
+ {
+ if ( repository == null )
+ {
+ throw new IllegalArgumentException( "Unable to operate on a null repository." );
+ }
+
+ if ( !repository.isManaged() )
+ {
+ throw new UnsupportedOperationException( "Only filesystem repositories are supported." );
+ }
+
+ File repositoryBase = new File( repository.getUrl().getPath() );
+
+ if ( !repositoryBase.exists() )
+ {
+ throw new UnsupportedOperationException( "Unable to scan a repository, directory "
+ + repositoryBase.getAbsolutePath() + " does not exist." );
+ }
+
+ if ( !repositoryBase.isDirectory() )
+ {
+ throw new UnsupportedOperationException( "Unable to scan a repository, path "
+ + repositoryBase.getAbsolutePath() + " is not a directory." );
+ }
+
+ // Setup Includes / Excludes.
+
+ List allExcludes = new ArrayList();
+ List allIncludes = new ArrayList();
+
+ if ( CollectionUtils.isNotEmpty( ignoredContentPatterns ) )
+ {
+ allExcludes.addAll( ignoredContentPatterns );
+ }
+
+ // Scan All Content. (intentional)
+ allIncludes.add( "**/*" );
+
+ // Setup Directory Walker
+ DirectoryWalker dirWalker = new DirectoryWalker();
+
+ dirWalker.setBaseDir( repositoryBase );
+
+ dirWalker.setIncludes( allIncludes );
+ dirWalker.setExcludes( allExcludes );
+
+ // Setup the Scan Instance
+ RepositoryScannerInstance scannerInstance = new RepositoryScannerInstance( repository, knownContentConsumers,
+ invalidContentConsumers, getLogger() );
+ scannerInstance.setOnlyModifiedAfterTimestamp( changesSince );
+
+ dirWalker.addDirectoryWalkListener( scannerInstance );
+
+ // Execute scan.
+ dirWalker.scan();
+
+ return scannerInstance.getStatistics();
+ }
+}
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryContentConsumerUtil.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryContentConsumerUtil.java
index ec03a3437..135db420d 100644
--- a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryContentConsumerUtil.java
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryContentConsumerUtil.java
@@ -30,6 +30,7 @@ import org.apache.maven.archiva.consumers.InvalidRepositoryContentConsumer;
import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -128,7 +129,7 @@ public class RepositoryContentConsumerUtil
return new SelectedInvalidRepoConsumersPredicate();
}
- public Map getSelectedKnownConsumers()
+ public Map getSelectedKnownConsumersMap()
{
RepositoryScanningConfiguration scanning = archivaConfiguration.getConfiguration().getRepositoryScanning();
@@ -139,7 +140,7 @@ public class RepositoryContentConsumerUtil
return consumerMapClosure.getMap();
}
- public Map getSelectedInvalidConsumers()
+ public Map getSelectedInvalidConsumersMap()
{
RepositoryScanningConfiguration scanning = archivaConfiguration.getConfiguration().getRepositoryScanning();
@@ -149,6 +150,26 @@ public class RepositoryContentConsumerUtil
return consumerMapClosure.getMap();
}
+
+ public List getSelectedKnownConsumers()
+ {
+ RepositoryScanningConfiguration scanning = archivaConfiguration.getConfiguration().getRepositoryScanning();
+
+ List ret = new ArrayList();
+ ret.addAll( CollectionUtils.select( scanning.getGoodConsumers(), getKnownSelectionPredicate() ));
+
+ return ret;
+ }
+
+ public List getSelectedInvalidConsumers()
+ {
+ RepositoryScanningConfiguration scanning = archivaConfiguration.getConfiguration().getRepositoryScanning();
+
+ List ret = new ArrayList();
+ ret.addAll( CollectionUtils.select( scanning.getBadConsumers(), getInvalidSelectionPredicate() ));
+
+ return ret;
+ }
public List getAvailableKnownConsumers()
{
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScanner.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScanner.java
index e2ed6768e..12f00244a 100644
--- a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScanner.java
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScanner.java
@@ -19,17 +19,12 @@ package org.apache.maven.archiva.repository.scanner;
* under the License.
*/
-import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
+import org.apache.maven.archiva.consumers.InvalidRepositoryContentConsumer;
+import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.RepositoryContentStatistics;
import org.apache.maven.archiva.repository.RepositoryException;
-import org.codehaus.plexus.util.DirectoryWalker;
-import org.codehaus.plexus.util.FileUtils;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
import java.util.List;
/**
@@ -38,17 +33,34 @@ import java.util.List;
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
-public class RepositoryScanner
+public interface RepositoryScanner
{
/**
- * Standard patterns to exclude from discovery as they are usually noise.
+ * The value to pass to {@link #scan(ArchivaRepository, long)} to have the scan
+ * operate in a fresh fashion, with no check on changes based on timestamp.
*/
- private static final String[] STANDARD_SCANNER_EXCLUDES = {
+ public static final long FRESH_SCAN = 0;
+
+ /**
+ * <p>
+ * Typical Ignorable Content patterns.
+ * </p>
+ *
+ * <p><strong>
+ * NOTE: Do not use for normal webapp or task driven repository scanning.
+ * </strong></p>
+ *
+ * <p>
+ * These patterns are only valid for archiva-cli and archiva-converter use.
+ * </p>
+ */
+ public static final String[] IGNORABLE_CONTENT = {
"bin/**",
"reports/**",
".index",
".reports/**",
".maven/**",
+ "**/.svn/**",
"**/*snapshot-version",
"*/website/**",
"*/licences/**",
@@ -58,140 +70,42 @@ public class RepositoryScanner
"**/README*",
"**/CHANGELOG*",
"**/KEYS*" };
-
+
/**
- * Walk the repository, and report to the consumers the files found.
- *
- * Report changes to the appropriate Consumer.
+ * Scan the repository for content changes.
*
- * This is just a convenience method to {@link #scan(ArtifactRepository, List, boolean, long, List, List)}
- * equivalent to calling <code>scan( repository, consumers, includeSnapshots, 0, null, null );</code>
+ * Internally, this will use the as-configured known and invalid consumer lists.
*
* @param repository the repository to change.
- * @param consumers use the provided list of consumers.
- * @param includeSnapshots true to include snapshots in the walking of this repository.
+ * @param changesSince the timestamp to use as a threshold on what is considered new or changed.
+ * (To have all content be taken into consideration regardless of timestamp,
+ * use the {@link #FRESH_SCAN} constant)
* @return the statistics for this scan.
* @throws RepositoryException if there was a fundamental problem with getting the discoverer started.
*/
- public RepositoryContentStatistics scan( ArchivaRepository repository, List consumers, boolean includeSnapshots )
- throws RepositoryException
- {
- return scan( repository, consumers, includeSnapshots, 0, null, null );
- }
-
+ public RepositoryContentStatistics scan( ArchivaRepository repository, long changesSince )
+ throws RepositoryException;
+
/**
- * Walk the repository, and report to the consumers the files found.
+ * Scan the repository for content changes.
*
- * Report changes to the appropriate Consumer.
+ * Internally, this will use the as-configured known and invalid consumer lists.
*
* @param repository the repository to change.
- * @param consumers use the provided list of consumers.
- * @param includeSnapshots true to include snapshots in the scanning of this repository.
- * @param onlyModifiedAfterTimestamp Only report to the consumers, files that have a {@link File#lastModified()})
- * after the provided timestamp.
- * @param extraFileExclusions an optional list of file exclusions on the walk.
- * @param extraFileInclusions an optional list of file inclusions on the walk.
+ * @param knownContentConsumers the list of consumers that follow the {@link KnownRepositoryContentConsumer}
+ * interface that should be used for this scan.
+ * @param invalidContentConsumers the list of consumers that follow the {@link InvalidRepositoryContentConsumer}
+ * interface that should be used for this scan.
+ * @param ignoredContentPatterns list of patterns that should be ignored and not sent to any consumer.
+ * @param changesSince the timestamp to use as a threshold on what is considered new or changed.
+ * (To have all content be taken into consideration regardless of timestamp,
+ * use the {@link #FRESH_SCAN} constant)
* @return the statistics for this scan.
- * @throws RepositoryException if there was a fundamental problem with getting the discoverer started.
+ * @throws RepositoryException if there was a fundamental problem with getting the discoverer started.
*/
- public RepositoryContentStatistics scan( ArchivaRepository repository, List consumers, boolean includeSnapshots,
- long onlyModifiedAfterTimestamp, List extraFileExclusions, List extraFileInclusions )
- throws RepositoryException
- {
- if ( repository == null )
- {
- throw new IllegalArgumentException( "Unable to operate on a null repository." );
- }
-
- if ( !"file".equals( repository.getUrl().getProtocol() ) )
- {
- throw new UnsupportedOperationException( "Only filesystem repositories are supported." );
- }
-
- File repositoryBase = new File( repository.getUrl().getPath() );
-
- if ( !repositoryBase.exists() )
- {
- throw new UnsupportedOperationException( "Unable to scan a repository, directory "
- + repositoryBase.getAbsolutePath() + " does not exist." );
- }
-
- if ( !repositoryBase.isDirectory() )
- {
- throw new UnsupportedOperationException( "Unable to scan a repository, path "
- + repositoryBase.getAbsolutePath() + " is not a directory." );
- }
-
- // Setup Includes / Excludes.
-
- List allExcludes = new ArrayList();
- List allIncludes = new ArrayList();
-
- // Exclude all of the SCM patterns.
- allExcludes.addAll( FileUtils.getDefaultExcludesAsList() );
-
- // Exclude all of the archiva noise patterns.
- allExcludes.addAll( Arrays.asList( STANDARD_SCANNER_EXCLUDES ) );
-
- if ( !includeSnapshots )
- {
- allExcludes.add( "**/*-SNAPSHOT*" );
- }
-
- if ( extraFileExclusions != null )
- {
- allExcludes.addAll( extraFileExclusions );
- }
-
- Iterator it = consumers.iterator();
- while ( it.hasNext() )
- {
- RepositoryContentConsumer consumer = (RepositoryContentConsumer) it.next();
-
- /* NOTE: Do not insert the consumer exclusion patterns here.
- * Exclusion patterns are handled by RepositoryScanner.wantsFile(Consumer, String)
- *
- * addUniqueElements( consumer.getExcludePatterns(), allExcludes );
- */
- addUniqueElements( consumer.getIncludes(), allIncludes );
- }
-
- if ( extraFileInclusions != null )
- {
- allIncludes.addAll( extraFileInclusions );
- }
-
- // Setup Directory Walker
-
- DirectoryWalker dirWalker = new DirectoryWalker();
-
- dirWalker.setBaseDir( repositoryBase );
-
- dirWalker.setIncludes( allIncludes );
- dirWalker.setExcludes( allExcludes );
-
- // Setup the Scan Instance
- RepositoryScannerInstance scannerInstance = new RepositoryScannerInstance( repository, consumers );
- scannerInstance.setOnlyModifiedAfterTimestamp( onlyModifiedAfterTimestamp );
-
- dirWalker.addDirectoryWalkListener( scannerInstance );
-
- // Execute scan.
- dirWalker.scan();
-
- return scannerInstance.getStatistics();
- }
+ public RepositoryContentStatistics scan( ArchivaRepository repository, List knownContentConsumers,
+ List invalidContentConsumers, List ignoredContentPatterns,
+ long changesSince )
+ throws RepositoryException;
- private void addUniqueElements( List fromList, List toList )
- {
- Iterator itFrom = fromList.iterator();
- while ( itFrom.hasNext() )
- {
- Object o = itFrom.next();
- if ( !toList.contains( o ) )
- {
- toList.add( o );
- }
- }
- }
}
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerInstance.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerInstance.java
index c5e498b8e..2c0637cb4 100644
--- a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerInstance.java
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerInstance.java
@@ -19,20 +19,20 @@ package org.apache.maven.archiva.repository.scanner;
* under the License.
*/
+import org.apache.commons.collections.Closure;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.functors.IfClosure;
import org.apache.commons.lang.SystemUtils;
import org.apache.maven.archiva.common.utils.BaseFile;
-import org.apache.maven.archiva.consumers.ConsumerException;
-import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.RepositoryContentStatistics;
+import org.apache.maven.archiva.repository.scanner.functors.ConsumerProcessFileClosure;
+import org.apache.maven.archiva.repository.scanner.functors.ConsumerWantsFilePredicate;
+import org.apache.maven.archiva.repository.scanner.functors.TriggerBeginScanClosure;
+import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.DirectoryWalkListener;
-import org.codehaus.plexus.util.SelectorUtils;
-import org.codehaus.plexus.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.File;
-import java.util.Iterator;
import java.util.List;
/**
@@ -41,45 +41,53 @@ import java.util.List;
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
-public class RepositoryScannerInstance implements DirectoryWalkListener
+public class RepositoryScannerInstance
+ implements DirectoryWalkListener
{
- private static Logger log = LoggerFactory.getLogger( RepositoryScannerInstance.class );
-
- private List consumers;
+ /**
+ * Consumers that process known content.
+ */
+ private List knownConsumers;
- private ArchivaRepository repository;
+ /**
+ * Consumers that process unknown/invalid content.
+ */
+ private List invalidConsumers;
- private boolean isCaseSensitive = true;
+ ArchivaRepository repository;
private RepositoryContentStatistics stats;
private long onlyModifiedAfterTimestamp = 0;
- public RepositoryScannerInstance( ArchivaRepository repository, List consumerList )
+ private ConsumerProcessFileClosure consumerProcessFile;
+
+ private ConsumerWantsFilePredicate consumerWantsFile;
+
+ private Logger logger;
+
+ public RepositoryScannerInstance( ArchivaRepository repository, List knownConsumerList, List invalidConsumerList,
+ Logger logger )
{
this.repository = repository;
- this.consumers = consumerList;
+ this.knownConsumers = knownConsumerList;
+ this.invalidConsumers = invalidConsumerList;
+ this.logger = logger;
+
+ this.consumerProcessFile = new ConsumerProcessFileClosure( logger );
+ this.consumerWantsFile = new ConsumerWantsFilePredicate();
+
stats = new RepositoryContentStatistics();
stats.setRepositoryId( repository.getId() );
- Iterator it = this.consumers.iterator();
- while ( it.hasNext() )
- {
- RepositoryContentConsumer consumer = (RepositoryContentConsumer) it.next();
- try
- {
- consumer.beginScan( repository );
- }
- catch ( ConsumerException e )
- {
- // TODO: remove bad consumers from list
- log.warn( "Consumer [" + consumer.getId() + "] cannot begin: " + e.getMessage(), e );
- }
- }
+ Closure triggerBeginScan = new TriggerBeginScanClosure( repository, logger );
+
+ CollectionUtils.forAllDo( knownConsumerList, triggerBeginScan );
+ CollectionUtils.forAllDo( invalidConsumerList, triggerBeginScan );
if ( SystemUtils.IS_OS_WINDOWS )
{
- isCaseSensitive = false;
+ consumerWantsFile.setCaseSensitive( false );
}
}
@@ -90,13 +98,13 @@ public class RepositoryScannerInstance implements DirectoryWalkListener
public void directoryWalkStarting( File basedir )
{
- log.info( "Walk Started: [" + this.repository.getId() + "] " + this.repository.getUrl() );
+ logger.info( "Walk Started: [" + this.repository.getId() + "] " + this.repository.getUrl() );
stats.triggerStart();
}
public void directoryWalkStep( int percentage, File file )
{
- log.debug( "Walk Step: " + percentage + ", " + file );
+ logger.debug( "Walk Step: " + percentage + ", " + file );
stats.increaseFileCount();
@@ -104,86 +112,33 @@ public class RepositoryScannerInstance implements DirectoryWalkListener
if ( file.lastModified() < onlyModifiedAfterTimestamp )
{
// Skip file as no change has occured.
- log.debug( "Skipping, No Change: " + file.getAbsolutePath() );
+ logger.debug( "Skipping, No Change: " + file.getAbsolutePath() );
return;
}
- synchronized ( consumers )
+ stats.increaseNewFileCount();
+
+ BaseFile basefile = new BaseFile( repository.getUrl().getPath(), file );
+
+ consumerProcessFile.setBasefile( basefile );
+ consumerWantsFile.setBasefile( basefile );
+
+ Closure processIfWanted = IfClosure.getInstance( consumerWantsFile, consumerProcessFile );
+ CollectionUtils.forAllDo( this.knownConsumers, processIfWanted );
+
+ if ( consumerWantsFile.getWantedFileCount() <= 0 )
{
- stats.increaseNewFileCount();
-
- BaseFile basefile = new BaseFile( repository.getUrl().getPath(), file );
-
- Iterator itConsumers = this.consumers.iterator();
- while ( itConsumers.hasNext() )
- {
- RepositoryContentConsumer consumer = (RepositoryContentConsumer) itConsumers.next();
-
- if ( wantsFile( consumer, StringUtils.replace( basefile.getRelativePath(), "\\", "/" ) ) )
- {
- try
- {
- log.debug( "Sending to consumer: " + consumer.getId() );
- consumer.processFile( basefile.getRelativePath() );
- }
- catch ( Exception e )
- {
- /* Intentionally Catch all exceptions.
- * So that the discoverer processing can continue.
- */
- log.error( "Consumer [" + consumer.getId() + "] had an error when processing file ["
- + basefile.getAbsolutePath() + "]: " + e.getMessage(), e );
- }
- }
- else
- {
- log.debug( "Skipping consumer " + consumer.getId() + " for file " + basefile.getRelativePath() );
- }
- }
+ // Nothing known processed this file. It is invalid!
+ CollectionUtils.forAllDo( this.invalidConsumers, consumerProcessFile );
}
}
public void directoryWalkFinished()
{
- log.info( "Walk Finished: [" + this.repository.getId() + "] " + this.repository.getUrl() );
+ logger.info( "Walk Finished: [" + this.repository.getId() + "] " + this.repository.getUrl() );
stats.triggerFinished();
}
- private boolean wantsFile( RepositoryContentConsumer consumer, String relativePath )
- {
- Iterator it;
-
- // Test excludes first.
- if ( consumer.getExcludes() != null )
- {
- it = consumer.getExcludes().iterator();
- while ( it.hasNext() )
- {
- String pattern = (String) it.next();
- if ( SelectorUtils.matchPath( pattern, relativePath, isCaseSensitive ) )
- {
- // Definately does NOT WANT FILE.
- return false;
- }
- }
- }
-
- // Now test includes.
- it = consumer.getIncludes().iterator();
- while ( it.hasNext() )
- {
- String pattern = (String) it.next();
- if ( SelectorUtils.matchPath( pattern, relativePath, isCaseSensitive ) )
- {
- // Specifically WANTS FILE.
- return true;
- }
- }
-
- // Not included, and Not excluded? Default to EXCLUDE.
- return false;
- }
-
public long getOnlyModifiedAfterTimestamp()
{
return onlyModifiedAfterTimestamp;
@@ -199,6 +154,6 @@ public class RepositoryScannerInstance implements DirectoryWalkListener
*/
public void debug( String message )
{
- log.debug( "Repository Scanner: " + message );
+ logger.debug( "Repository Scanner: " + message );
}
}
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerProcessFileClosure.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerProcessFileClosure.java
new file mode 100644
index 000000000..d79be78cf
--- /dev/null
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerProcessFileClosure.java
@@ -0,0 +1,89 @@
+package org.apache.maven.archiva.repository.scanner.functors;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.collections.Closure;
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * ConsumerProcessFileClosure
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ConsumerProcessFileClosure
+ implements Closure
+{
+ private BaseFile basefile;
+
+ private Logger logger;
+
+ public ConsumerProcessFileClosure( Logger logger )
+ {
+ // Lame. I know, but seeing as plexus doesn't like to cleanup after
+ // application loaded/lookup'd components, this is the best I can do.
+ this.logger = logger;
+ }
+
+ public void execute( Object input )
+ {
+ if ( input instanceof RepositoryContentConsumer )
+ {
+ RepositoryContentConsumer consumer = (RepositoryContentConsumer) input;
+
+ try
+ {
+ logger.debug( "Sending to consumer: " + consumer.getId() );
+
+ consumer.processFile( basefile.getRelativePath() );
+ }
+ catch ( Exception e )
+ {
+ /* Intentionally Catch all exceptions.
+ * So that the discoverer processing can continue.
+ */
+ logger.error( "Consumer [" + consumer.getId() + "] had an error when processing file ["
+ + basefile.getAbsolutePath() + "]: " + e.getMessage(), e );
+ }
+ }
+ }
+
+ public BaseFile getBasefile()
+ {
+ return basefile;
+ }
+
+ public void setBasefile( BaseFile basefile )
+ {
+ this.basefile = basefile;
+ }
+
+ public Logger getLogger()
+ {
+ return logger;
+ }
+
+ public void setLogger( Logger logger )
+ {
+ this.logger = logger;
+ }
+}
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerWantsFilePredicate.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerWantsFilePredicate.java
new file mode 100644
index 000000000..0d2bc5719
--- /dev/null
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/ConsumerWantsFilePredicate.java
@@ -0,0 +1,122 @@
+package org.apache.maven.archiva.repository.scanner.functors;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.collections.Predicate;
+import org.apache.maven.archiva.common.utils.BaseFile;
+import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
+import org.codehaus.plexus.util.SelectorUtils;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.util.Iterator;
+
+/**
+ * ConsumerWantsFilePredicate
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ConsumerWantsFilePredicate
+ implements Predicate
+{
+ private BaseFile basefile;
+
+ private boolean isCaseSensitive = true;
+
+ private int wantedFileCount = 0;
+
+ public boolean evaluate( Object object )
+ {
+ boolean satisfies = false;
+
+ if ( object instanceof RepositoryContentConsumer )
+ {
+ RepositoryContentConsumer consumer = (RepositoryContentConsumer) object;
+ if ( wantsFile( consumer, StringUtils.replace( basefile.getRelativePath(), "\\", "/" ) ) )
+ {
+ satisfies = true;
+ wantedFileCount++;
+ }
+ }
+
+ return satisfies;
+ }
+
+ public BaseFile getBasefile()
+ {
+ return basefile;
+ }
+
+ public int getWantedFileCount()
+ {
+ return wantedFileCount;
+ }
+
+ public boolean isCaseSensitive()
+ {
+ return isCaseSensitive;
+ }
+
+ public void setBasefile( BaseFile basefile )
+ {
+ this.basefile = basefile;
+ this.wantedFileCount = 0;
+ }
+
+ public void setCaseSensitive( boolean isCaseSensitive )
+ {
+ this.isCaseSensitive = isCaseSensitive;
+ }
+
+ private boolean wantsFile( RepositoryContentConsumer consumer, String relativePath )
+ {
+ Iterator it;
+
+ // Test excludes first.
+ if ( consumer.getExcludes() != null )
+ {
+ it = consumer.getExcludes().iterator();
+ while ( it.hasNext() )
+ {
+ String pattern = (String) it.next();
+ if ( SelectorUtils.matchPath( pattern, relativePath, isCaseSensitive ) )
+ {
+ // Definately does NOT WANT FILE.
+ return false;
+ }
+ }
+ }
+
+ // Now test includes.
+ it = consumer.getIncludes().iterator();
+ while ( it.hasNext() )
+ {
+ String pattern = (String) it.next();
+ if ( SelectorUtils.matchPath( pattern, relativePath, isCaseSensitive ) )
+ {
+ // Specifically WANTS FILE.
+ return true;
+ }
+ }
+
+ // Not included, and Not excluded? Default to EXCLUDE.
+ return false;
+ }
+}
diff --git a/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/TriggerBeginScanClosure.java b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/TriggerBeginScanClosure.java
new file mode 100644
index 000000000..1b546bdf4
--- /dev/null
+++ b/archiva-base/archiva-repository-layer/src/main/java/org/apache/maven/archiva/repository/scanner/functors/TriggerBeginScanClosure.java
@@ -0,0 +1,63 @@
+package org.apache.maven.archiva.repository.scanner.functors;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.commons.collections.Closure;
+import org.apache.maven.archiva.consumers.ConsumerException;
+import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
+import org.apache.maven.archiva.model.ArchivaRepository;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * TriggerBeginScanClosure
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class TriggerBeginScanClosure
+ implements Closure
+{
+ private ArchivaRepository repository;
+
+ private Logger logger;
+
+ public TriggerBeginScanClosure( ArchivaRepository repository, Logger logger )
+ {
+ this.repository = repository;
+ this.logger = logger;
+ }
+
+ public void execute( Object input )
+ {
+ if ( input instanceof RepositoryContentConsumer )
+ {
+ RepositoryContentConsumer consumer = (RepositoryContentConsumer) input;
+
+ try
+ {
+ consumer.beginScan( repository );
+ }
+ catch ( ConsumerException e )
+ {
+ logger.warn( "Consumer [" + consumer.getId() + "] cannot begin: " + e.getMessage(), e );
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/InvalidScanConsumer.java b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/InvalidScanConsumer.java
new file mode 100644
index 000000000..68bc9db95
--- /dev/null
+++ b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/InvalidScanConsumer.java
@@ -0,0 +1,92 @@
+package org.apache.maven.archiva.repository.scanner;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
+import org.apache.maven.archiva.consumers.ConsumerException;
+import org.apache.maven.archiva.consumers.InvalidRepositoryContentConsumer;
+import org.apache.maven.archiva.model.ArchivaRepository;
+
+import java.util.List;
+
+/**
+ * InvalidScanConsumer
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class InvalidScanConsumer
+ extends AbstractMonitoredConsumer
+ implements InvalidRepositoryContentConsumer
+{
+ private int processCount = 0;
+
+ public void beginScan( ArchivaRepository repository )
+ throws ConsumerException
+ {
+ /* do nothing */
+ }
+
+ public void completeScan()
+ {
+ /* do nothing */
+ }
+
+ public List getExcludes()
+ {
+ return null;
+ }
+
+ public List getIncludes()
+ {
+ return null;
+ }
+
+ public void processFile( String path )
+ throws ConsumerException
+ {
+ processCount++;
+ }
+
+ public String getDescription()
+ {
+ return "Bad Content Scan Consumer (for testing)";
+ }
+
+ public String getId()
+ {
+ return "test-invalid-consumer";
+ }
+
+ public boolean isPermanent()
+ {
+ return false;
+ }
+
+ public int getProcessCount()
+ {
+ return processCount;
+ }
+
+ public void setProcessCount( int processCount )
+ {
+ this.processCount = processCount;
+ }
+}
diff --git a/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/ScanConsumer.java b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/KnownScanConsumer.java
index 8ab2012f7..d16b6aa61 100644
--- a/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/ScanConsumer.java
+++ b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/KnownScanConsumer.java
@@ -22,7 +22,6 @@ package org.apache.maven.archiva.repository.scanner;
import org.apache.maven.archiva.consumers.AbstractMonitoredConsumer;
import org.apache.maven.archiva.consumers.ConsumerException;
import org.apache.maven.archiva.consumers.KnownRepositoryContentConsumer;
-import org.apache.maven.archiva.consumers.RepositoryContentConsumer;
import org.apache.maven.archiva.model.ArchivaRepository;
import java.util.ArrayList;
@@ -35,7 +34,9 @@ import java.util.List;
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
-public class ScanConsumer extends AbstractMonitoredConsumer implements KnownRepositoryContentConsumer
+public class KnownScanConsumer
+ extends AbstractMonitoredConsumer
+ implements KnownRepositoryContentConsumer
{
private int processCount = 0;
@@ -67,12 +68,14 @@ public class ScanConsumer extends AbstractMonitoredConsumer implements KnownRepo
return "Scan Consumer (for testing)";
}
- public void beginScan( ArchivaRepository repository ) throws ConsumerException
+ public void beginScan( ArchivaRepository repository )
+ throws ConsumerException
{
/* do nothing */
}
- public void processFile( String path ) throws ConsumerException
+ public void processFile( String path )
+ throws ConsumerException
{
this.processCount++;
}
diff --git a/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerTest.java b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerTest.java
index c85c39758..305096163 100644
--- a/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerTest.java
+++ b/archiva-base/archiva-repository-layer/src/test/java/org/apache/maven/archiva/repository/scanner/RepositoryScannerTest.java
@@ -27,6 +27,7 @@ import org.codehaus.plexus.PlexusTestCase;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -72,7 +73,7 @@ public class RepositoryScannerTest
return repo;
}
-
+
private void assertMinimumHits( String msg, int minimumHitCount, long actualCount )
{
if ( actualCount < minimumHitCount )
@@ -82,27 +83,54 @@ public class RepositoryScannerTest
}
}
+ private RepositoryScanner lookupRepositoryScanner()
+ throws Exception
+ {
+ return (RepositoryScanner) lookup( RepositoryScanner.class );
+ }
+
+ private List getIgnoreList()
+ {
+ List ignores = new ArrayList();
+ ignores.addAll( Arrays.asList( RepositoryScanner.IGNORABLE_CONTENT ) );
+ return ignores;
+ }
+
public void testDefaultRepositoryScanner()
- throws RepositoryException
+ throws Exception
{
ArchivaRepository repository = createDefaultRepository();
- List consumers = new ArrayList();
- ScanConsumer consumer = new ScanConsumer();
- consumer.setIncludes( new String[] { "**/*.jar" } );
- consumers.add( consumer );
-
- RepositoryScanner scanner = new RepositoryScanner();
- boolean includeSnapshots = true;
- RepositoryContentStatistics stats = scanner.scan( repository, consumers, includeSnapshots );
+ List knownConsumers = new ArrayList();
+ KnownScanConsumer consumer = new KnownScanConsumer();
+ consumer.setIncludes( new String[] {
+ "**/*.jar",
+ "**/*.war",
+ "**/*.pom",
+ "**/maven-metadata.xml",
+ "**/*-site.xml",
+ "**/*.zip",
+ "**/*.tar.gz",
+ "**/*.sha1",
+ "**/*.md5" } );
+ knownConsumers.add( consumer );
+
+ List invalidConsumers = new ArrayList();
+ InvalidScanConsumer badconsumer = new InvalidScanConsumer();
+ invalidConsumers.add( badconsumer );
+
+ RepositoryScanner scanner = lookupRepositoryScanner();
+ RepositoryContentStatistics stats = scanner.scan( repository, knownConsumers, invalidConsumers,
+ getIgnoreList(), RepositoryScanner.FRESH_SCAN );
assertNotNull( "Stats should not be null.", stats );
assertMinimumHits( "Stats.totalFileCount", 17, stats.getTotalFileCount() );
assertMinimumHits( "Processed Count", 17, consumer.getProcessCount() );
+ assertEquals( "Processed Count (of invalid items)", 6, badconsumer.getProcessCount() );
}
public void testDefaultRepositoryArtifactScanner()
- throws RepositoryException
+ throws Exception
{
List actualArtifactPaths = new ArrayList();
@@ -140,14 +168,18 @@ public class RepositoryScannerTest
ArchivaRepository repository = createDefaultRepository();
- List consumers = new ArrayList();
- ScanConsumer consumer = new ScanConsumer();
+ List knownConsumers = new ArrayList();
+ KnownScanConsumer consumer = new KnownScanConsumer();
consumer.setIncludes( ARTIFACT_PATTERNS );
- consumers.add( consumer );
+ knownConsumers.add( consumer );
+
+ List invalidConsumers = new ArrayList();
+ InvalidScanConsumer badconsumer = new InvalidScanConsumer();
+ invalidConsumers.add( badconsumer );
- RepositoryScanner scanner = new RepositoryScanner();
- boolean includeSnapshots = true;
- RepositoryContentStatistics stats = scanner.scan( repository, consumers, includeSnapshots );
+ RepositoryScanner scanner = lookupRepositoryScanner();
+ RepositoryContentStatistics stats = scanner.scan( repository, knownConsumers, invalidConsumers,
+ getIgnoreList(), RepositoryScanner.FRESH_SCAN );
assertNotNull( "Stats should not be null.", stats );
assertMinimumHits( "Stats.totalFileCount", actualArtifactPaths.size(), stats.getTotalFileCount() );
@@ -155,7 +187,7 @@ public class RepositoryScannerTest
}
public void testDefaultRepositoryMetadataScanner()
- throws RepositoryException
+ throws Exception
{
List actualMetadataPaths = new ArrayList();
@@ -172,22 +204,26 @@ public class RepositoryScannerTest
ArchivaRepository repository = createDefaultRepository();
- List consumers = new ArrayList();
- ScanConsumer consumer = new ScanConsumer();
- consumer.setIncludes( new String[] { "**/maven-metadata*.xml" } );
- consumers.add( consumer );
+ List knownConsumers = new ArrayList();
+ KnownScanConsumer knownConsumer = new KnownScanConsumer();
+ knownConsumer.setIncludes( new String[] { "**/maven-metadata*.xml" } );
+ knownConsumers.add( knownConsumer );
- RepositoryScanner scanner = new RepositoryScanner();
- boolean includeSnapshots = true;
- RepositoryContentStatistics stats = scanner.scan( repository, consumers, includeSnapshots );
+ List invalidConsumers = new ArrayList();
+ InvalidScanConsumer badconsumer = new InvalidScanConsumer();
+ invalidConsumers.add( badconsumer );
+
+ RepositoryScanner scanner = lookupRepositoryScanner();
+ RepositoryContentStatistics stats = scanner.scan( repository, knownConsumers, invalidConsumers,
+ getIgnoreList(), RepositoryScanner.FRESH_SCAN );
assertNotNull( "Stats should not be null.", stats );
assertMinimumHits( "Stats.totalFileCount", actualMetadataPaths.size(), stats.getTotalFileCount() );
- assertMinimumHits( "Processed Count", actualMetadataPaths.size(), consumer.getProcessCount() );
+ assertMinimumHits( "Processed Count", actualMetadataPaths.size(), knownConsumer.getProcessCount() );
}
public void testDefaultRepositoryProjectScanner()
- throws RepositoryException
+ throws Exception
{
List actualProjectPaths = new ArrayList();
@@ -204,14 +240,18 @@ public class RepositoryScannerTest
ArchivaRepository repository = createDefaultRepository();
- List consumers = new ArrayList();
- ScanConsumer consumer = new ScanConsumer();
+ List knownConsumers = new ArrayList();
+ KnownScanConsumer consumer = new KnownScanConsumer();
consumer.setIncludes( new String[] { "**/*.pom" } );
- consumers.add( consumer );
+ knownConsumers.add( consumer );
+
+ List invalidConsumers = new ArrayList();
+ InvalidScanConsumer badconsumer = new InvalidScanConsumer();
+ invalidConsumers.add( badconsumer );
- RepositoryScanner scanner = new RepositoryScanner();
- boolean includeSnapshots = true;
- RepositoryContentStatistics stats = scanner.scan( repository, consumers, includeSnapshots );
+ RepositoryScanner scanner = lookupRepositoryScanner();
+ RepositoryContentStatistics stats = scanner.scan( repository, knownConsumers, invalidConsumers,
+ getIgnoreList(), RepositoryScanner.FRESH_SCAN );
assertNotNull( "Stats should not be null.", stats );
assertMinimumHits( "Stats.totalFileCount", actualProjectPaths.size(), stats.getTotalFileCount() );
@@ -219,7 +259,7 @@ public class RepositoryScannerTest
}
public void testLegacyRepositoryArtifactScanner()
- throws RepositoryException
+ throws Exception
{
List actualArtifactPaths = new ArrayList();
@@ -240,14 +280,18 @@ public class RepositoryScannerTest
ArchivaRepository repository = createLegacyRepository();
- List consumers = new ArrayList();
- ScanConsumer consumer = new ScanConsumer();
+ List knownConsumers = new ArrayList();
+ KnownScanConsumer consumer = new KnownScanConsumer();
consumer.setIncludes( ARTIFACT_PATTERNS );
- consumers.add( consumer );
+ knownConsumers.add( consumer );
+
+ List invalidConsumers = new ArrayList();
+ InvalidScanConsumer badconsumer = new InvalidScanConsumer();
+ invalidConsumers.add( badconsumer );
- RepositoryScanner scanner = new RepositoryScanner();
- boolean includeSnapshots = true;
- RepositoryContentStatistics stats = scanner.scan( repository, consumers, includeSnapshots );
+ RepositoryScanner scanner = lookupRepositoryScanner();
+ RepositoryContentStatistics stats = scanner.scan( repository, knownConsumers, invalidConsumers,
+ getIgnoreList(), RepositoryScanner.FRESH_SCAN );
assertNotNull( "Stats should not be null.", stats );
assertMinimumHits( "Stats.totalFileCount", actualArtifactPaths.size(), stats.getTotalFileCount() );
diff --git a/archiva-cli/src/main/java/org/apache/maven/archiva/cli/ArchivaCli.java b/archiva-cli/src/main/java/org/apache/maven/archiva/cli/ArchivaCli.java
index e5237d264..3f5b03872 100644
--- a/archiva-cli/src/main/java/org/apache/maven/archiva/cli/ArchivaCli.java
+++ b/archiva-cli/src/main/java/org/apache/maven/archiva/cli/ArchivaCli.java
@@ -44,6 +44,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -70,7 +71,7 @@ public class ArchivaCli
public static final char CONSUMERS = 'u';
public static final char LIST_CONSUMERS = 'l';
-
+
public static final char DUMP_CONFIGURATION = 'd';
// ----------------------------------------------------------------------------
@@ -89,7 +90,7 @@ public class ArchivaCli
* @plexus.requirement
*/
private ArchivaConfiguration archivaConfiguration;
-
+
public static void main( String[] args )
throws Exception
{
@@ -134,7 +135,7 @@ public class ArchivaCli
Option dumpConfig = createOption( DUMP_CONFIGURATION, "dumpconfig", 0, "Dump Current Configuration." );
options.addOption( dumpConfig );
-
+
return options;
}
@@ -170,15 +171,21 @@ public class ArchivaCli
ArchivaRepository repo = new ArchivaRepository( "cliRepo", "Archiva CLI Provided Repo", "file://" + path );
- List consumerList = new ArrayList();
+ List knownConsumerList = new ArrayList();
+
+ knownConsumerList.addAll( getConsumerList( cli, plexus ) );
- consumerList.addAll( getConsumerList( cli, plexus ) );
+ List invalidConsumerList = Collections.EMPTY_LIST;
- RepositoryScanner scanner = new RepositoryScanner();
+ List ignoredContent = new ArrayList();
+ ignoredContent.addAll( Arrays.asList( RepositoryScanner.IGNORABLE_CONTENT ) );
+
+ RepositoryScanner scanner = (RepositoryScanner) plexus.lookup( RepositoryScanner.class );
try
{
- RepositoryContentStatistics stats = scanner.scan( repo, consumerList, true );
+ RepositoryContentStatistics stats = scanner.scan( repo, knownConsumerList, invalidConsumerList,
+ ignoredContent, RepositoryScanner.FRESH_SCAN );
SimpleDateFormat df = new SimpleDateFormat();
System.out.println( "" );
@@ -186,8 +193,8 @@ public class ArchivaCli
System.out.println( " Repository URL : " + repo.getUrl() );
System.out.println( " Repository Name : " + repo.getModel().getName() );
System.out.println( " Repository Layout : " + repo.getModel().getLayoutName() );
- System.out.println( " Consumers : (" + consumerList.size() + " active)" );
- for ( Iterator iter = consumerList.iterator(); iter.hasNext(); )
+ System.out.println( " Consumers : (" + knownConsumerList.size() + " active)" );
+ for ( Iterator iter = knownConsumerList.iterator(); iter.hasNext(); )
{
RepositoryContentConsumer consumer = (RepositoryContentConsumer) iter.next();
System.out.println( " " + consumer.getId() + " - " + consumer.getDescription() );
@@ -296,11 +303,13 @@ public class ArchivaCli
showFatalError( "Error converting repository.", e, true );
}
}
-
- private void dumpConfiguration( PlexusContainer plexus ) throws ComponentLookupException
- {
+
+ private void dumpConfiguration( PlexusContainer plexus )
+ throws ComponentLookupException
+ {
archivaConfiguration = (ArchivaConfiguration) plexus.lookup( ArchivaConfiguration.ROLE, "cli" );
-
- System.out.println( "File Type Count: " + archivaConfiguration.getConfiguration().getRepositoryScanning().getFileTypes().size() );
+
+ System.out.println( "File Type Count: "
+ + archivaConfiguration.getConfiguration().getRepositoryScanning().getFileTypes().size() );
}
}
diff --git a/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaScheduledTaskExecutor.java b/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaScheduledTaskExecutor.java
index 3caadfc48..cf931977d 100644
--- a/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaScheduledTaskExecutor.java
+++ b/archiva-scheduled/src/main/java/org/apache/maven/archiva/scheduled/executors/ArchivaScheduledTaskExecutor.java
@@ -20,16 +20,15 @@ package org.apache.maven.archiva.scheduled.executors;
*/
import org.apache.commons.collections.CollectionUtils;
-import org.apache.maven.archiva.configuration.ArchivaConfiguration;
-import org.apache.maven.archiva.configuration.RepositoryScanningConfiguration;
+import org.apache.maven.archiva.common.utils.DateUtil;
import org.apache.maven.archiva.database.ArchivaDAO;
import org.apache.maven.archiva.database.ArchivaDatabaseException;
import org.apache.maven.archiva.database.RepositoryDAO;
+import org.apache.maven.archiva.database.constraints.MostRecentRepositoryScanStatistics;
import org.apache.maven.archiva.database.updater.DatabaseUpdater;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.RepositoryContentStatistics;
import org.apache.maven.archiva.repository.RepositoryException;
-import org.apache.maven.archiva.repository.scanner.RepositoryContentConsumerUtil;
import org.apache.maven.archiva.repository.scanner.RepositoryScanner;
import org.apache.maven.archiva.scheduled.tasks.DatabaseTask;
import org.apache.maven.archiva.scheduled.tasks.RepositoryTask;
@@ -38,9 +37,7 @@ import org.codehaus.plexus.taskqueue.Task;
import org.codehaus.plexus.taskqueue.execution.TaskExecutionException;
import org.codehaus.plexus.taskqueue.execution.TaskExecutor;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
*
@@ -55,13 +52,6 @@ public class ArchivaScheduledTaskExecutor
implements TaskExecutor
{
/**
- * Configuration store.
- *
- * @plexus.requirement
- */
- private ArchivaConfiguration archivaConfiguration;
-
- /**
* @plexus.requirement role-hint="jdo"
*/
private ArchivaDAO dao;
@@ -77,17 +67,11 @@ public class ArchivaScheduledTaskExecutor
private RepositoryDAO repositoryDAO;
/**
- * The collection of available database consumers.
- * @plexus.requirement role="org.apache.maven.archiva.consumers.ArchivaArtifactConsumer"
- */
- private Map availableDBConsumers;
-
- /**
- * The collection of available repository consumers.
+ * The repository scanner component.
*
* @plexus.requirement
*/
- private RepositoryContentConsumerUtil repositoryContentConsumerUtil;
+ private RepositoryScanner repoScanner;
public void executeTask( Task task )
throws TaskExecutionException
@@ -149,13 +133,21 @@ public class ArchivaScheduledTaskExecutor
{
ArchivaRepository arepo = repositoryDAO.getRepository( task.getRepositoryId() );
- RepositoryScanner scanner = new RepositoryScanner();
+ long sinceWhen = RepositoryScanner.FRESH_SCAN;
+
+ List results = dao.query( new MostRecentRepositoryScanStatistics( arepo.getId() ) );
+
+ if ( CollectionUtils.isNotEmpty( results ) )
+ {
+ RepositoryContentStatistics lastStats = (RepositoryContentStatistics) results.get( 0 );
+ sinceWhen = lastStats.getWhenGathered().getTime() + lastStats.getDuration();
+ }
- RepositoryContentStatistics stats = scanner.scan( arepo, getActiveConsumerList(), true );
+ RepositoryContentStatistics stats = repoScanner.scan( arepo, sinceWhen );
dao.save( stats );
- getLogger().info( "Finished repository task: " + stats.getDuration() + " ms." );
+ getLogger().info( "Finished repository task: " + DateUtil.getDuration( stats.getDuration() ) + "." );
}
catch ( ArchivaDatabaseException e )
{
@@ -166,25 +158,4 @@ public class ArchivaScheduledTaskExecutor
throw new TaskExecutionException( "Repository error when executing repository job.", e );
}
}
-
- private List getActiveConsumerList()
- {
- List activeConsumers = new ArrayList();
-
- RepositoryScanningConfiguration repoScanningConfig = archivaConfiguration.getConfiguration()
- .getRepositoryScanning();
-
- List configuredGoodConsumers = new ArrayList();
- List configuredBadConsumers = new ArrayList();
-
- configuredGoodConsumers.addAll( CollectionUtils.select( repoScanningConfig.getGoodConsumers(),
- repositoryContentConsumerUtil
- .getKnownSelectionPredicate() ) );
-
- configuredBadConsumers.addAll( CollectionUtils.select( repoScanningConfig.getBadConsumers(),
- repositoryContentConsumerUtil
- .getInvalidSelectionPredicate() ) );
-
- return activeConsumers;
- }
}
diff --git a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/scanning/RepositoryScanningAction.java b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/scanning/RepositoryScanningAction.java
index c326b5355..b8035c7a5 100644
--- a/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/scanning/RepositoryScanningAction.java
+++ b/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/scanning/RepositoryScanningAction.java
@@ -34,6 +34,7 @@ import org.codehaus.plexus.security.ui.web.interceptor.SecureActionException;
import org.codehaus.plexus.xwork.action.PlexusActionSupport;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -55,10 +56,16 @@ public class RepositoryScanningAction
private ArchivaConfiguration archivaConfiguration;
private Map fileTypeMap;
+
+ private List fileTypeIds;
private List goodConsumers = new ArrayList();
private List badConsumers = new ArrayList();
+
+ private String pattern;
+
+ private String fileTypeId;
public void prepare()
throws Exception
@@ -74,6 +81,32 @@ public class RepositoryScanningAction
badConsumers.clear();
badConsumers.addAll( config.getRepositoryScanning().getBadConsumers() );
+
+ fileTypeIds = new ArrayList();
+ fileTypeIds.addAll( fileTypeMap.keySet() );
+ Collections.sort( fileTypeIds );
+ }
+
+ public String removeFiletypePattern()
+ {
+ getLogger().info( "Remove File Type Pattern [" + getFileTypeId() + ":" + getPattern() + "]" );
+
+ // TODO: remove the filetype
+ // TODO: save configuration
+
+ return INPUT;
+ }
+
+ public String addFiletypePattern()
+ {
+ getLogger().info( "Add New File Type Pattern [" + getFileTypeId() + ":" + getPattern() + "]" );
+
+ // TODO: add the filetype.
+ // TODO: report error if filetype pattern already exists.
+ // TODO: report success (message) if added successfully.
+ // TODO: save configuration each time.
+
+ return INPUT;
}
public SecureActionBundle getSecureActionBundle()
@@ -92,28 +125,38 @@ public class RepositoryScanningAction
return badConsumers;
}
- public void setBadConsumers( List badConsumers )
+ public Map getFileTypeMap()
{
- this.badConsumers = badConsumers;
+ return fileTypeMap;
}
- public Map getFileTypeMap()
+ public List getGoodConsumers()
{
- return fileTypeMap;
+ return goodConsumers;
}
- public void setFileTypeMap( Map fileTypeMap )
+ public String getFileTypeId()
{
- this.fileTypeMap = fileTypeMap;
+ return fileTypeId;
}
- public List getGoodConsumers()
+ public void setFileTypeId( String fileTypeId )
{
- return goodConsumers;
+ this.fileTypeId = fileTypeId;
+ }
+
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ public void setPattern( String pattern )
+ {
+ this.pattern = pattern;
}
- public void setGoodConsumers( List goodConsumers )
+ public List getFileTypeIds()
{
- this.goodConsumers = goodConsumers;
+ return fileTypeIds;
}
}
diff --git a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryScanning.jsp b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryScanning.jsp
index 3814dc94e..039ac84f2 100644
--- a/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryScanning.jsp
+++ b/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/repositoryScanning.jsp
@@ -17,15 +17,16 @@
~ under the License.
--%>
-<%@ taglib prefix="ww" uri="/webwork" %>
-<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-<%@ taglib prefix="pss" uri="/plexusSecuritySystem" %>
-<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
+<%@ taglib prefix="ww" uri="/webwork"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%@ taglib prefix="pss" uri="/plexusSecuritySystem"%>
+<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva"%>
<html>
<head>
- <title>Administration - Repository Scanning</title>
- <ww:head/>
+<title>Administration - Repository Scanning</title>
+<ww:head />
</head>
<body>
@@ -34,11 +35,40 @@
<div id="contentArea">
-<ww:actionerror />
-<ww:actionmessage />
+<ww:actionerror />
+<ww:actionmessage />
+
+<c:url var="iconDeleteUrl" value="/images/icons/delete.gif" />
+<c:url var="iconCreateUrl" value="/images/icons/create.png" />
+<ww:url id="removeFiletypePatternUrl" action="repositoryScanning" method="removeFiletypePattern" />
+<ww:url id="addFiletypePatternUrl" action="repositoryScanning" method="addFiletypePattern" />
+
+<script type="text/javascript">
+<!--
+ function removeFiletypePattern(filetypeId, pattern)
+ {
+ var f = document.getElementById('filetypeForm');
+
+ f.action = "${removeFiletypePatternUrl}";
+ f['pattern'].value = pattern;
+ f['fileTypeId'].value = filetypeId;
+ f.submit();
+ }
+
+ function addFiletypePattern(filetypeId, newPatternId)
+ {
+ var f = document.getElementById('filetypeForm');
+
+ f.action = "${addFiletypePatternUrl}";
+ f['pattern'].value = document.getElementById(newPatternId).value;
+ f['fileTypeId'].value = filetypeId;
+ f.submit();
+ }
+//-->
+</script>
<div class="admin">
- <h2>Repository Scanning - File Types</h2>
+<h2>Repository Scanning - File Types</h2>
<c:choose>
<c:when test="${empty(fileTypeMap)}">
@@ -47,46 +77,75 @@
</c:when>
<c:otherwise>
<%-- Display the filetypes. --%>
-
- <c:forEach items="${fileTypeMap}" var="filetype" varStatus="i">
- <c:choose>
- <c:when test='${(i.index)%2 eq 0}'>
- <c:set var="rowColor" value="dark" scope="page" />
- </c:when>
- <c:otherwise>
- <c:set var="rowColor" value="lite" scope="page" />
- </c:otherwise>
- </c:choose>
-
- <div class="filetype ${rowColor}">
-
- <div class="controls">
- <%-- Does this even make sense for file types? --%>
- </div>
-
- <h3 class="filetype">${filetype.key}</h3>
+
+ <ww:form method="post" action="repositoryScanning"
+ namespace="/admin" validate="false"
+ id="filetypeForm" theme="simple">
+ <input type="hidden" name="pattern" />
+ <input type="hidden" name="fileTypeId" />
+ </ww:form>
+
+ <ww:url id="addFiletypePatternUrl" action="repositoryScanning" method="addFiletypePattern" />
+
+ <c:forEach items="${fileTypeIds}" var="filetypeId">
+
+ <div class="filetype">
+
+ <div class="controls"><%-- Does this even make sense for file types? --%></div>
+
+ <h3 class="filetype">${filetypeId}</h3>
<table>
- <c:forEach items="${filetype.value.patterns}" var="pattern" varStatus="i">
+ <c:forEach items="${fileTypeMap[filetypeId].patterns}" var="pattern" varStatus="i">
+ <c:choose>
+ <c:when test='${(i.index)%2 eq 0}'>
+ <c:set var="bgcolor" value="even" scope="page" />
+ </c:when>
+ <c:otherwise>
+ <c:set var="bgcolor" value="odd" scope="page" />
+ </c:otherwise>
+ </c:choose>
+
+ <c:set var="escapedPattern" value="${fn:escapeXml(pattern)}" scope="page" />
+
+ <tr>
+ <td class="pattern ${bgcolor}">
+ <code>${escapedPattern}</code>
+ </td>
+ <td class="controls ${bgcolor}">
+ <ww:a href="#" title="Remove [${escapedPattern}] Pattern from [${filetypeId}]"
+ onclick="removeFiletypePattern( '${filetypeId}', '${escapedPattern}' )"
+ theme="simple">
+ <img src="${iconDeleteUrl}" />
+ </ww:a>
+ </td>
+ </tr>
+ </c:forEach>
<tr>
<td>
- <code>${pattern}</code>
+ <ww:textfield size="40"
+ id="newpattern_${i.index}"
+ theme="simple" />
</td>
<td>
- <img src="<c:url value="/images/icons/delete.gif" />" />
+ <ww:a href="#"
+ title="Add Pattern to [${filetypeId}]"
+ onclick="addFiletypePattern( '${filetypeId}', 'newpattern_${i.index}' )"
+ theme="simple">
+ <img src="${iconCreateUrl}" />
+ </ww:a>
</td>
</tr>
- </c:forEach>
</table>
-
- </div>
- </c:forEach>
-
+
+ </div>
+ </c:forEach>
+
</c:otherwise>
</c:choose>
- <h2>Repository Scanning - Consumers of Good Content</h2>
-
+<h2>Repository Scanning - Consumers of Good Content</h2>
+
<c:choose>
<c:when test="${empty(goodConsumers)}">
<%-- No Good Consumers. Eeek! --%>
@@ -94,33 +153,31 @@
</c:when>
<c:otherwise>
<%-- Display the consumers. --%>
-
- <table>
- <c:forEach items="${goodConsumers}" var="consumer" varStatus="i">
- <c:choose>
- <c:when test='${(i.index)%2 eq 0}'>
- <c:set var="rowColor" value="dark" scope="page" />
- </c:when>
- <c:otherwise>
- <c:set var="rowColor" value="lite" scope="page" />
- </c:otherwise>
- </c:choose>
-
- <tr>
- <td><code>${consumer}</code></td>
- <td>
- <img src="<c:url value="/images/icons/delete.gif" />" />
- </td>
- </tr>
- </c:forEach>
- </table>
-
+
+ <table>
+ <c:forEach items="${goodConsumers}" var="consumer" varStatus="i">
+ <c:choose>
+ <c:when test='${(i.index)%2 eq 0}'>
+ <c:set var="rowColor" value="dark" scope="page" />
+ </c:when>
+ <c:otherwise>
+ <c:set var="rowColor" value="lite" scope="page" />
+ </c:otherwise>
+ </c:choose>
+
+ <tr>
+ <td><code>${consumer}</code></td>
+ <td><img src="<c:url value="/images/icons/delete.gif" />" /></td>
+ </tr>
+ </c:forEach>
+ </table>
+
</c:otherwise>
</c:choose>
-
- <h2>Repository Scanning - Consumers of Bad Content</h2>
-
+
+<h2>Repository Scanning - Consumers of Bad Content</h2>
+
<c:choose>
<c:when test="${empty(badConsumers)}">
<%-- No Bad Consumers. Eeek! --%>
@@ -128,32 +185,26 @@
</c:when>
<c:otherwise>
<%-- Display the consumers. --%>
-
- <table>
- <c:forEach items="${badConsumers}" var="consumer" varStatus="i">
- <c:choose>
- <c:when test='${(i.index)%2 eq 0}'>
- <c:set var="rowColor" value="dark" scope="page" />
- </c:when>
- <c:otherwise>
- <c:set var="rowColor" value="lite" scope="page" />
- </c:otherwise>
- </c:choose>
-
- <tr>
- <td><code>${consumer}</code></td>
- <td>
- <img src="<c:url value="/images/icons/delete.gif" />" />
- </td>
- </tr>
- </c:forEach>
- </table>
-
- </c:otherwise>
-</c:choose>
-
-</div>
+ <table>
+ <c:forEach items="${badConsumers}" var="consumer" varStatus="i">
+ <c:choose>
+ <c:when test='${(i.index)%2 eq 0}'>
+ <c:set var="rowColor" value="dark" scope="page" />
+ </c:when>
+ <c:otherwise>
+ <c:set var="rowColor" value="lite" scope="page" />
+ </c:otherwise>
+ </c:choose>
+ <tr>
+ <td><code>${consumer}</code></td>
+ <td><img src="<c:url value="/images/icons/delete.gif" />" /></td>
+ </tr>
+ </c:forEach>
+ </table>
+
+ </c:otherwise>
+</c:choose></div>
</body>
</html>
diff --git a/archiva-web/archiva-webapp/src/main/webapp/css/site.css b/archiva-web/archiva-webapp/src/main/webapp/css/site.css
index 5091385f1..587dd7161 100644
--- a/archiva-web/archiva-webapp/src/main/webapp/css/site.css
+++ b/archiva-web/archiva-webapp/src/main/webapp/css/site.css
@@ -307,4 +307,22 @@ div.admin div.dark {
div.admin div.controls {
float: right;
font-size: 8pt !important;
-} \ No newline at end of file
+}
+
+div.admin div.filetype table {
+ margin-left: 25px;
+ border: 1px solid gray;
+}
+
+div.filetype table td.controls {
+ width: 5%;
+}
+
+div.filetype table td.odd {
+ background-color: #dddddd;
+}
+
+div.filetype table td.event {
+ background-color: white;
+}
+