]> source.dussan.org Git - archiva.git/commitdiff
* Adding CachedFailuresPolicy.
authorJoakim Erdfelt <joakime@apache.org>
Fri, 13 Apr 2007 15:48:27 +0000 (15:48 +0000)
committerJoakim Erdfelt <joakime@apache.org>
Fri, 13 Apr 2007 15:48:27 +0000 (15:48 +0000)
* Adding UrlFailureCache component.
* Adding unit tests for cache-failures and checksum policies.

git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches@528532 13f79535-47bb-0310-9956-ffa450edef68

17 files changed:
archiva-jpox-database-refactor/archiva-base/archiva-policies/pom.xml
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good [new file with mode: 0644]
archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/log4j.xml [new file with mode: 0644]

index 0681489501edc5b5ffe3b55a67669ab1d3c0a84b..a08bd09db3cd8f80f71e18498672e1952bd6f485 100644 (file)
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-digest</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus.cache</groupId>
+      <artifactId>plexus-cache-ehcache</artifactId>
+      <version>1.0-alpha-2-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>easymock</groupId>
       <artifactId>easymock</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>merge</id>
+            <goals>
+              <goal>merge-descriptors</goal>
+            </goals>
+            <configuration>
+              <descriptors>
+                <descriptor>${basedir}/src/main/resources/META-INF/plexus/components.xml</descriptor>
+                <descriptor>${project.build.directory}/generated-resources/plexus/META-INF/plexus/components.xml</descriptor>
+              </descriptors>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
 </project>
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java
new file mode 100644 (file)
index 0000000..5bd7e78
--- /dev/null
@@ -0,0 +1,96 @@
+package org.apache.maven.archiva.policies;
+
+/*
+ * 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.lang.StringUtils;
+import org.apache.maven.archiva.policies.urlcache.UrlFailureCache;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * {@link PreDownloadPolicy} to check if the requested url has failed before. 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ * 
+ * @plexus.component role="org.apache.maven.archiva.policies.PreDownloadPolicy"
+ *                   role-hint="cache-failures"
+ */
+public class CachedFailuresPolicy
+    extends AbstractLogEnabled
+    implements PreDownloadPolicy
+{
+    /**
+     * The CACHED policy indicates that if the URL provided exists in the
+     * cached failures pool, then the policy fails, and the download isn't even 
+     * attempted.
+     */
+    public static final String CACHED = "cached";
+
+    /**
+     * @plexus.requirement role-hint="default"
+     */
+    private UrlFailureCache urlFailureCache;
+
+    private Set validPolicyCodes = new HashSet();
+
+    public CachedFailuresPolicy()
+    {
+        validPolicyCodes.add( IGNORED );
+        validPolicyCodes.add( CACHED );
+    }
+
+    public boolean applyPolicy( String policySetting, Properties request, File localFile )
+    {
+        if ( !validPolicyCodes.contains( policySetting ) )
+        {
+            // No valid code? false it is then.
+            getLogger().error( "Unknown checksum policyCode [" + policySetting + "]" );
+            return false;
+        }
+
+        if ( IGNORED.equals( policySetting ) )
+        {
+            // Ignore.
+            return true;
+        }
+
+        String url = request.getProperty( "url" );
+
+        if ( StringUtils.isNotBlank( url ) )
+        {
+            if ( urlFailureCache.hasFailedBefore( url ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public String getDefaultPolicySetting()
+    {
+        return IGNORED;
+    }
+}
index f297aa7004db6e2eb6b7700537c24510b233e1ac..864ba13589a0c5cdbf1206d3c35e8bd5fe3bf58a 100644 (file)
@@ -1,5 +1,24 @@
 package org.apache.maven.archiva.policies;
 
+/*
+ * 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.codehaus.plexus.digest.ChecksumFile;
 import org.codehaus.plexus.digest.Digester;
 import org.codehaus.plexus.digest.DigesterException;
@@ -12,6 +31,15 @@ import java.util.HashSet;
 import java.util.Properties;
 import java.util.Set;
 
+/**
+ * ChecksumPolicy 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ * 
+ * @plexus.component role="org.apache.maven.archiva.policies.PostDownloadPolicy"
+ *                   role-hint="checksum"
+ */
 public class ChecksumPolicy
     extends AbstractLogEnabled
     implements PostDownloadPolicy
@@ -30,13 +58,6 @@ public class ChecksumPolicy
      */
     public static final String FIX = "fix";
 
-    /**
-     * The IGNORE policy indicates that the checksum is never tested
-     * and even bad downloads and checksum files are left in place
-     * on the local repository.
-     */
-    public static final String IGNORED = "ignored";
-
     /**
      * @plexus.requirement role-hint="sha1"
      */
@@ -88,147 +109,170 @@ public class ChecksumPolicy
 
         if ( FAIL.equals( policySetting ) )
         {
+            boolean checksPass = true;
+
+            // Both files missing is a failure.
             if ( !sha1File.exists() && !md5File.exists() )
             {
-                getLogger().error( "File " + localFile.getAbsolutePath() + " has no checksum files (sha1 or md5)." );
-                localFile.delete();
-                return false;
+                getLogger().error( "File " + localFile.getPath() + " has no checksum files (sha1 or md5)." );
+                checksPass = false;
             }
 
-            // Test for sha1 first, then md5
-
             if ( sha1File.exists() )
             {
-                try
+                // Bad sha1 checksum is a failure.
+                if ( !validateChecksum( sha1File, "sha1" ) )
                 {
-                    return checksumFile.isValidChecksum( sha1File );
-                }
-                catch ( FileNotFoundException e )
-                {
-                    getLogger().warn( "Unable to find sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( DigesterException e )
-                {
-                    getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( IOException e )
-                {
-                    getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
+                    getLogger().warn( "SHA1 is incorrect for " + localFile.getPath() );
+                    checksPass = false;
                 }
             }
 
             if ( md5File.exists() )
             {
-                try
-                {
-                    return checksumFile.isValidChecksum( md5File );
-                }
-                catch ( FileNotFoundException e )
+                // Bad md5 checksum is a failure.
+                if ( !validateChecksum( md5File, "md5" ) )
                 {
-                    getLogger().warn( "Unable to find md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
+                    getLogger().warn( "MD5 is incorrect for " + localFile.getPath() );
+                    checksPass = false;
                 }
-                catch ( DigesterException e )
+            }
+
+            if ( !checksPass )
+            {
+                // On failure. delete files.
+                if ( sha1File.exists() )
                 {
-                    getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
+                    sha1File.delete();
                 }
-                catch ( IOException e )
+
+                if ( md5File.exists() )
                 {
-                    getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
+                    md5File.delete();
                 }
+
+                localFile.delete();
             }
+
+            return checksPass;
         }
 
         if ( FIX.equals( policySetting ) )
         {
-            if ( !sha1File.exists() )
+            boolean checksPass = true;
+
+            if ( !fixChecksum( localFile, sha1File, digestSha1 ) )
             {
-                try
-                {
-                    checksumFile.createChecksum( localFile, digestSha1 );
-                }
-                catch ( DigesterException e )
-                {
-                    getLogger().warn( "Unable to create sha1 file: " + e.getMessage(), e );
-                    return false;
-                }
-                catch ( IOException e )
-                {
-                    getLogger().warn( "Unable to create sha1 file: " + e.getMessage(), e );
-                    return false;
-                }
+                checksPass = false;
             }
-            else
+
+            if ( !fixChecksum( localFile, md5File, digestMd5 ) )
             {
-                try
-                {
-                    checksumFile.isValidChecksum( sha1File );
-                }
-                catch ( FileNotFoundException e )
-                {
-                    getLogger().warn( "Unable to find sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( DigesterException e )
-                {
-                    getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( IOException e )
-                {
-                    getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
-                    return false;
-                }
+                checksPass = false;
             }
 
-            if ( !md5File.exists() )
+            return checksPass;
+        }
+
+        getLogger().error( "Unhandled policyCode [" + policySetting + "]" );
+        return false;
+    }
+
+    private boolean createChecksum( File localFile, Digester digester )
+    {
+        try
+        {
+            checksumFile.createChecksum( localFile, digester );
+            return true;
+        }
+        catch ( DigesterException e )
+        {
+            getLogger().warn( "Unable to create " + digester.getFilenameExtension() + " file: " + e.getMessage(), e );
+            return false;
+        }
+        catch ( IOException e )
+        {
+            getLogger().warn( "Unable to create " + digester.getFilenameExtension() + " file: " + e.getMessage(), e );
+            return false;
+        }
+    }
+
+    private boolean fixChecksum( File localFile, File hashFile, Digester digester )
+    {
+        String ext = digester.getFilenameExtension();
+
+        if ( !hashFile.getPath().endsWith( ext ) )
+        {
+            throw new IllegalArgumentException( "Cannot fix " + hashFile.getPath() + " using " + ext + " digester." );
+        }
+
+        // If hashfile doesn't exist, create it.
+        if ( !hashFile.exists() )
+        {
+            return createChecksum( localFile, digester );
+        }
+
+        // Validate checksum, if bad, recreate it.
+        try
+        {
+            if ( checksumFile.isValidChecksum( hashFile ) )
             {
-                try
-                {
-                    checksumFile.createChecksum( localFile, digestMd5 );
-                }
-                catch ( DigesterException e )
-                {
-                    getLogger().warn( "Unable to create md5 file: " + e.getMessage(), e );
-                    return false;
-                }
-                catch ( IOException e )
-                {
-                    getLogger().warn( "Unable to create md5 file: " + e.getMessage(), e );
-                    return false;
-                }
+                getLogger().debug( "Valid checksum: " + hashFile.getPath() );
+                return true;
             }
             else
             {
-                try
-                {
-                    return checksumFile.isValidChecksum( md5File );
-                }
-                catch ( FileNotFoundException e )
-                {
-                    getLogger().warn( "Unable to find md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( DigesterException e )
-                {
-                    getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
-                }
-                catch ( IOException e )
-                {
-                    getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
-                    return false;
-                }
+                getLogger().debug( "Not valid checksum: " + hashFile.getPath() );
+                return createChecksum( localFile, digester );
             }
         }
+        catch ( FileNotFoundException e )
+        {
+            getLogger().warn( "Unable to find " + ext + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
+        catch ( DigesterException e )
+        {
+            getLogger().warn( "Unable to process " + ext + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
+        catch ( IOException e )
+        {
+            getLogger().warn( "Unable to process " + ext + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
+    }
 
-        getLogger().error( "Unhandled policyCode [" + policySetting + "]" );
-        return false;
+    private boolean validateChecksum( File hashFile, String type )
+    {
+        try
+        {
+            boolean validity = checksumFile.isValidChecksum( hashFile );
+            if ( validity )
+            {
+                getLogger().debug( "Valid checksum: " + hashFile.getPath() );
+            }
+            else
+            {
+                getLogger().debug( "Not valid checksum: " + hashFile.getPath() );
+            }
+            return validity;
+        }
+        catch ( FileNotFoundException e )
+        {
+            getLogger().warn( "Unable to find " + type + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
+        catch ( DigesterException e )
+        {
+            getLogger().warn( "Unable to process " + type + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
+        catch ( IOException e )
+        {
+            getLogger().warn( "Unable to process " + type + " file: " + hashFile.getAbsolutePath(), e );
+            return false;
+        }
     }
 
     public String getDefaultPolicySetting()
index 36f283705a2373b26b9145acb2fff6d6bfe212bf..e556c4b28476b7bd8b18e4e1e384a022afd2aed8 100644 (file)
@@ -35,6 +35,9 @@ public interface DownloadPolicy
      */
     public static final String IGNORED = "ignored";
     
+    public static final boolean PASS = true;
+    public static final boolean FAIL = false;
+    
     /**
      * Get the default policy setting.
      * 
index 9c9bc2daa1239193532c5750db3cc00bac281edb..4d08d1a689016ed26c943483ea9219eee693f25d 100644 (file)
@@ -26,7 +26,7 @@ package org.apache.maven.archiva.policies;
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  * @version $Id$
  * 
- * @plexus.component role="org.apache.maven.archiva.policies.download.PreDownloadPolicy"
+ * @plexus.component role="org.apache.maven.archiva.policies.PreDownloadPolicy"
  *                   role-hint="releases"
  */
 public class ReleasesPolicy
index d786275ed592e57e5fcf60c4e006127e5a4ee357..d78847a80e00e598c856610ef0d1f8895efb70e9 100644 (file)
@@ -26,8 +26,8 @@ package org.apache.maven.archiva.policies;
  * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
  * @version $Id$
  * 
- * @plexus.component role="org.apache.maven.archiva.policies.download.PreDownloadPolicy"
- *                   role-hint="releases"
+ * @plexus.component role="org.apache.maven.archiva.policies.PreDownloadPolicy"
+ *                   role-hint="snapshots"
  */
 public class SnapshotsPolicy
     extends AbstractUpdatePolicy
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java
new file mode 100644 (file)
index 0000000..0c251ae
--- /dev/null
@@ -0,0 +1,58 @@
+package org.apache.maven.archiva.policies.urlcache;
+
+/*
+ * 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.codehaus.plexus.cache.Cache;
+
+import java.util.Date;
+
+/**
+ * DefaultUrlFailureCache 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ * 
+ * @plexus.component role="org.apache.maven.archiva.policies.urlcache.UrlFailureCache"
+ *                   role-hint="default"
+ */
+public class DefaultUrlFailureCache
+    implements UrlFailureCache
+{
+    /**
+     * @plexus.requirement role-hint="url-failures-cache"
+     */
+    private Cache urlCache;
+
+    public void cacheFailure( String url )
+    {
+        urlCache.register( url, new Date() );
+    }
+
+    public boolean hasFailedBefore( String url )
+    {
+        if ( urlCache.hasKey( url ) )
+        {
+            urlCache.register( url, new Date() );
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java
new file mode 100644 (file)
index 0000000..fc08e6c
--- /dev/null
@@ -0,0 +1,48 @@
+package org.apache.maven.archiva.policies.urlcache;
+
+/*
+ * 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.
+ */
+
+
+/**
+ * Cache for requested URLs that cannot be fetched. 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public interface UrlFailureCache
+{
+    /**
+     * Store a URL in the cache as failed.
+     * 
+     * @param url the url to store. 
+     */
+    public void cacheFailure( String url );
+    
+    /**
+     * Test if a specified URL has failed before.
+     * 
+     * NOTE: If the provided URL has failed, then making this call 
+     * should refresh the expiration time on that URL entry.
+     * 
+     * @param url the URL to test.
+     * @return true if it has failed before, false if not.
+     */
+    public boolean hasFailedBefore( String url );
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml
new file mode 100644 (file)
index 0000000..66d543f
--- /dev/null
@@ -0,0 +1,24 @@
+<component-set>
+  <components>
+    <component>
+      <role>org.codehaus.plexus.cache.Cache</role>
+      <role-hint>url-failures-cache</role-hint>
+      <implementation>org.codehaus.plexus.cache.ehcache.EhcacheCache</implementation>
+      <description>URL Failure Cache</description>
+      <configuration>
+        <disk-expiry-thread-interval-seconds>600</disk-expiry-thread-interval-seconds>
+        <disk-persistent>true</disk-persistent>
+        <disk-store-path>${java.io.tmpdir}/archiva/urlcache</disk-store-path>
+        <eternal>false</eternal>
+        <max-elements-in-memory>1000</max-elements-in-memory>
+        <memory-eviction-policy>LRU</memory-eviction-policy>
+        <name>cache</name>
+        <overflow-to-disk>false</overflow-to-disk>
+        <!-- 45 minutes = 2700 seconds -->
+        <time-to-idle-seconds>2700</time-to-idle-seconds>
+        <!-- 30 minutes = 1800 seconds  -->
+        <time-to-live-seconds>1800</time-to-live-seconds>
+      </configuration>
+    </component>
+  </components>
+</component-set>
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java
new file mode 100644 (file)
index 0000000..dd65f7a
--- /dev/null
@@ -0,0 +1,102 @@
+package org.apache.maven.archiva.policies;
+
+/*
+ * 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.policies.urlcache.UrlFailureCache;
+import org.codehaus.plexus.PlexusTestCase;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * CachedFailuresPolicyTest 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class CachedFailuresPolicyTest
+    extends PlexusTestCase
+{
+    private DownloadPolicy lookupPolicy()
+        throws Exception
+    {
+        return (DownloadPolicy) lookup( PreDownloadPolicy.class.getName(), "cache-failures" );
+    }
+
+    private UrlFailureCache lookupUrlFailureCache()
+        throws Exception
+    {
+        return (UrlFailureCache) lookup( UrlFailureCache.class.getName(), "default" );
+    }
+
+    private File getFile()
+    {
+        return new File( "target/cache-failures/" + getName() + ".txt" );
+    }
+
+    private Properties createRequest()
+    {
+        Properties request = new Properties();
+
+        return request;
+    }
+
+    public void testIgnored()
+        throws Exception
+    {
+        DownloadPolicy policy = lookupPolicy();
+        File localFile = getFile();
+        Properties request = createRequest();
+
+        request.setProperty( "url", "http://a.bad.hostname.maven.org/path/to/resource.txt" );
+
+        assertTrue( policy.applyPolicy( CachedFailuresPolicy.IGNORED, request, localFile ) );
+    }
+
+    public void testCachedNotInCache()
+        throws Exception
+    {
+        DownloadPolicy policy = lookupPolicy();
+        File localFile = getFile();
+        Properties request = createRequest();
+
+        request.setProperty( "url", "http://a.bad.hostname.maven.org/path/to/resource.txt" );
+
+        assertTrue( policy.applyPolicy( CachedFailuresPolicy.CACHED, request, localFile ) );
+    }
+
+    public void testCachedInCache()
+        throws Exception
+    {
+        UrlFailureCache urlFailureCache = lookupUrlFailureCache();
+
+        DownloadPolicy policy = lookupPolicy();
+        File localFile = getFile();
+        Properties request = createRequest();
+
+        String url = "http://a.bad.hostname.maven.org/path/to/resource.txt";
+
+        urlFailureCache.cacheFailure( url );
+
+        request.setProperty( "url", url );
+
+        assertFalse( policy.applyPolicy( CachedFailuresPolicy.CACHED, request, localFile ) );
+    }
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java
new file mode 100644 (file)
index 0000000..d37b42d
--- /dev/null
@@ -0,0 +1,314 @@
+package org.apache.maven.archiva.policies;
+
+/*
+ * 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.codehaus.plexus.PlexusTestCase;
+import org.codehaus.plexus.util.FileUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.Properties;
+
+/**
+ * ChecksumPolicyTest 
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ * @version $Id$
+ */
+public class ChecksumPolicyTest
+    extends PlexusTestCase
+{
+    private static final String GOOD = "good";
+
+    private static final String BAD = "bad";
+
+    public void testFailOnFileOnly()
+        throws Exception
+    {
+        assertFailSetting( false, null, null );
+    }
+
+    public void testFailOnFileWithBadMd5AndBadSha1()
+        throws Exception
+    {
+        assertFailSetting( false, BAD, BAD );
+    }
+
+    public void testFailOnFileWithBadMd5AndGoodSha1()
+        throws Exception
+    {
+        assertFailSetting( false, BAD, GOOD );
+    }
+
+    public void testFailOnFileWithBadMd5Only()
+        throws Exception
+    {
+        assertFailSetting( false, BAD, null );
+    }
+
+    public void testFailOnFileWithBadSha1Only()
+        throws Exception
+    {
+        assertFailSetting( false, null, BAD );
+    }
+
+    public void testFailOnFileWithGoodMd5AndBadSha1()
+        throws Exception
+    {
+        assertFailSetting( false, GOOD, BAD );
+    }
+
+    public void testFailOnFileWithGoodMd5AndGoodSha1()
+        throws Exception
+    {
+        assertFailSetting( true, GOOD, GOOD );
+    }
+
+    public void testFailOnFileWithGoodMd5Only()
+        throws Exception
+    {
+        assertFailSetting( true, GOOD, null );
+    }
+
+    public void testFailOnFileWithGoodSha1Only()
+        throws Exception
+    {
+        assertFailSetting( true, null, GOOD );
+    }
+
+    public void testFixOnFileOnly()
+        throws Exception
+    {
+        assertFixSetting( true, null, null );
+    }
+
+    public void testFixOnFileWithBadMd5AndBadSha1()
+        throws Exception
+    {
+        assertFixSetting( true, BAD, BAD );
+    }
+
+    public void testFixOnFileWithBadMd5AndGoodSha1()
+        throws Exception
+    {
+        assertFixSetting( true, BAD, GOOD );
+    }
+
+    public void testFixOnFileWithBadMd5Only()
+        throws Exception
+    {
+        assertFixSetting( true, BAD, null );
+    }
+
+    public void testFixOnFileWithBadSha1Only()
+        throws Exception
+    {
+        assertFixSetting( true, null, BAD );
+    }
+
+    public void testFixOnFileWithGoodMd5AndBadSha1()
+        throws Exception
+    {
+        assertFixSetting( true, GOOD, BAD );
+    }
+
+    public void testFixOnFileWithGoodMd5AndGoodSha1()
+        throws Exception
+    {
+        assertFixSetting( true, GOOD, GOOD );
+    }
+
+    public void testFixOnFileWithGoodMd5Only()
+        throws Exception
+    {
+        assertFixSetting( true, GOOD, null );
+    }
+
+    public void testFixOnFileWithGoodSha1Only()
+        throws Exception
+    {
+        assertFixSetting( true, null, GOOD );
+    }
+
+    public void testIgnored()
+        throws Exception
+    {
+        PostDownloadPolicy policy = lookupPolicy();
+        File localFile = createTestableFiles( null, null );
+        Properties request = createRequest();
+
+        assertTrue( policy.applyPolicy( ChecksumPolicy.IGNORED, request, localFile ) );
+    }
+
+    private void assertFailSetting( boolean expectedResult, String md5State, String sha1State )
+        throws Exception
+    {
+        PostDownloadPolicy policy = lookupPolicy();
+        File localFile = createTestableFiles( md5State, sha1State );
+        Properties request = createRequest();
+
+        boolean actualResult = policy.applyPolicy( ChecksumPolicy.FAIL, request, localFile );
+        String msg = createMessage( ChecksumPolicy.FAIL, md5State, sha1State );
+
+        if ( actualResult == false )
+        {
+            assertFalse( msg + " local file should not exist:", localFile.exists() );
+            File md5File = new File( localFile.getAbsolutePath() + ".sha1" );
+            File sha1File = new File( localFile.getAbsolutePath() + ".md5" );
+            assertFalse( msg + " local md5 file should not exist:", md5File.exists() );
+            assertFalse( msg + " local sha1 file should not exist:", sha1File.exists() );
+        }
+
+        assertEquals( createMessage( ChecksumPolicy.FAIL, md5State, sha1State ), expectedResult, actualResult );
+    }
+
+    private void assertFixSetting( boolean expectedResult, String md5State, String sha1State )
+        throws Exception
+    {
+        PostDownloadPolicy policy = lookupPolicy();
+        File localFile = createTestableFiles( md5State, sha1State );
+        Properties request = createRequest();
+
+        boolean actualResult = policy.applyPolicy( ChecksumPolicy.FIX, request, localFile );
+        assertEquals( createMessage( ChecksumPolicy.FIX, md5State, sha1State ), expectedResult, actualResult );
+
+        // End result should be legitimate SHA1 and MD5 files.
+        File md5File = new File( localFile.getAbsolutePath() + ".md5" );
+        File sha1File = new File( localFile.getAbsolutePath() + ".sha1" );
+
+        assertTrue( "ChecksumPolicy.apply(FIX) md5 should exist.", md5File.exists() && md5File.isFile() );
+        assertTrue( "ChecksumPolicy.apply(FIX) sha1 should exist.", sha1File.exists() && sha1File.isFile() );
+
+        String actualMd5Contents = readChecksumFile( md5File );
+        String actualSha1Contents = readChecksumFile( sha1File );
+
+        String expectedMd5Contents = "360ccd01d8a0a2d94b86f9802c2fc548  artifact.jar";
+        String expectedSha1Contents = "7dd8929150664f182db60ad15f20359d875f059f  artifact.jar";
+
+        assertEquals( "ChecksumPolicy.apply(FIX) md5 contents:", expectedMd5Contents, actualMd5Contents );
+        assertEquals( "ChecksumPolicy.apply(FIX) sha1 contents:", expectedSha1Contents, actualSha1Contents );
+    }
+
+    /**
+     * Read the first line from the checksum file, and return it (trimmed).
+     */
+    private String readChecksumFile( File checksumFile )
+        throws Exception
+    {
+        FileReader freader = null;
+        BufferedReader buf = null;
+
+        try
+        {
+            freader = new FileReader( checksumFile );
+            buf = new BufferedReader( freader );
+            return buf.readLine();
+        }
+        finally
+        {
+            if ( buf != null )
+            {
+                buf.close();
+            }
+
+            if ( freader != null )
+            {
+                freader.close();
+            }
+        }
+    }
+
+    private String createMessage( String settingType, String md5State, String sha1State )
+    {
+        StringBuffer msg = new StringBuffer();
+        msg.append( "Expected result of ChecksumPolicy.apply(" );
+        msg.append( settingType.toUpperCase() );
+        msg.append( ") when working with " );
+        if ( md5State == null )
+        {
+            msg.append( "NO" );
+        }
+        else
+        {
+            msg.append( "a " ).append( md5State.toUpperCase() );
+        }
+
+        msg.append( " MD5 and " );
+
+        if ( sha1State == null )
+        {
+            msg.append( "NO" );
+        }
+        else
+        {
+            msg.append( "a " ).append( sha1State.toUpperCase() );
+        }
+        msg.append( " SHA1:" );
+
+        return msg.toString();
+    }
+
+    private Properties createRequest()
+    {
+        Properties request = new Properties();
+
+        request.setProperty( "url", "http://a.bad.hostname.maven.org/path/to/resource.txt" );
+
+        return request;
+    }
+
+    private File createTestableFiles( String md5State, String sha1State )
+        throws Exception
+    {
+        File sourceDir = new File( "src/test/resources/checksums/" );
+        File destDir = new File( "target/checksum-tests/" + getName() + "/" );
+
+        FileUtils.copyFileToDirectory( new File( sourceDir, "artifact.jar" ), destDir );
+
+        if ( md5State != null )
+        {
+            File md5File = new File( sourceDir, "artifact.jar.md5-" + md5State );
+            assertTrue( "Testable file exists: " + md5File.getName() + ":", md5File.exists() && md5File.isFile() );
+            File destFile = new File( destDir, "artifact.jar.md5" );
+            FileUtils.copyFile( md5File, destFile );
+        }
+
+        if ( sha1State != null )
+        {
+            File sha1File = new File( sourceDir, "artifact.jar.sha1-" + sha1State );
+            assertTrue( "Testable file exists: " + sha1File.getName() + ":", sha1File.exists() && sha1File.isFile() );
+            File destFile = new File( destDir, "artifact.jar.sha1" );
+            FileUtils.copyFile( sha1File, destFile );
+        }
+
+        File localFile = new File( destDir, "artifact.jar" );
+        return localFile;
+    }
+
+    private PostDownloadPolicy lookupPolicy()
+        throws Exception
+    {
+        PostDownloadPolicy policy = (PostDownloadPolicy) lookup( PostDownloadPolicy.class.getName(), "checksum" );
+        assertNotNull( policy );
+        return policy;
+    }
+
+}
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar
new file mode 100644 (file)
index 0000000..d1b610e
Binary files /dev/null and b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar differ
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad
new file mode 100644 (file)
index 0000000..aafbb1c
--- /dev/null
@@ -0,0 +1 @@
+444ccc111aaa222999888eee222fff00  artifact.jar
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good
new file mode 100644 (file)
index 0000000..1c84652
--- /dev/null
@@ -0,0 +1 @@
+360ccd01d8a0a2d94b86f9802c2fc548  artifact.jar
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad
new file mode 100644 (file)
index 0000000..2d809c2
--- /dev/null
@@ -0,0 +1 @@
+ddd888999000444888bbbaaa555333999777eee0  artifact.jar
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good
new file mode 100644 (file)
index 0000000..0f10d25
--- /dev/null
@@ -0,0 +1 @@
+7dd8929150664f182db60ad15f20359d875f059f  artifact.jar
diff --git a/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/log4j.xml b/archiva-jpox-database-refactor/archiva-base/archiva-policies/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..3c782b1
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+  <appender name="console" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.out"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%5p|%t|%5r|%-30c{1} - %m%n"/>
+    </layout>
+  </appender>
+
+  <!-- Help identify bugs during testing -->
+  <logger name="org.apache.maven.archiva">
+    <level value="debug"/>
+  </logger>
+
+  <logger name="org.codehaus.plexus.security">
+    <level value="info"/>
+  </logger>
+
+  <logger name="org.codehaus.plexus.PlexusContainer">
+    <level value="info"/>
+  </logger>
+
+  <logger name="JPOX">
+    <level value="warn"/>
+  </logger>
+
+  <logger name="JPOX.MetaData">
+    <level value="error"/>
+  </logger>
+
+  <logger name="JPOX.RDBMS.SQL">
+    <level value="error"/>
+  </logger>
+
+  <logger name="SQL">
+    <level value="error"/>
+  </logger>
+
+  <root>
+    <priority value ="debug" />
+    <appender-ref ref="console" />
+  </root>
+
+</log4j:configuration>