From: Joakim Erdfelt Date: Fri, 13 Apr 2007 15:48:27 +0000 (+0000) Subject: * Adding CachedFailuresPolicy. X-Git-Tag: archiva-1.0-alpha-1~113^2~49 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b02cdf39a14af419375fe8f6f6bddd6d8aafec14;p=archiva.git * Adding CachedFailuresPolicy. * Adding UrlFailureCache component. * Adding unit tests for cache-failures and checksum policies. git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-jpox-database-refactor@528532 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/archiva-base/archiva-policies/pom.xml b/archiva-base/archiva-policies/pom.xml index 068148950..a08bd09db 100644 --- a/archiva-base/archiva-policies/pom.xml +++ b/archiva-base/archiva-policies/pom.xml @@ -41,6 +41,11 @@ org.codehaus.plexus plexus-digest + + org.codehaus.plexus.cache + plexus-cache-ehcache + 1.0-alpha-2-SNAPSHOT + easymock easymock @@ -60,4 +65,26 @@ test + + + + org.codehaus.plexus + plexus-maven-plugin + + + merge + + merge-descriptors + + + + ${basedir}/src/main/resources/META-INF/plexus/components.xml + ${project.build.directory}/generated-resources/plexus/META-INF/plexus/components.xml + + + + + + + diff --git a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java new file mode 100644 index 000000000..5bd7e78a8 --- /dev/null +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java @@ -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 Joakim Erdfelt + * @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; + } +} diff --git a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java index f297aa700..864ba1358 100644 --- a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java @@ -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 Joakim Erdfelt + * @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() diff --git a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java index 36f283705..e556c4b28 100644 --- a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java @@ -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. * diff --git a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java index 9c9bc2daa..4d08d1a68 100644 --- a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java @@ -26,7 +26,7 @@ package org.apache.maven.archiva.policies; * @author Joakim Erdfelt * @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 diff --git a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java index d786275ed..d78847a80 100644 --- a/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java @@ -26,8 +26,8 @@ package org.apache.maven.archiva.policies; * @author Joakim Erdfelt * @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-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java new file mode 100644 index 000000000..0c251aee4 --- /dev/null +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/DefaultUrlFailureCache.java @@ -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 Joakim Erdfelt + * @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-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java new file mode 100644 index 000000000..fc08e6c33 --- /dev/null +++ b/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/urlcache/UrlFailureCache.java @@ -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 Joakim Erdfelt + * @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-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml b/archiva-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000..66d543fb6 --- /dev/null +++ b/archiva-base/archiva-policies/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,24 @@ + + + + org.codehaus.plexus.cache.Cache + url-failures-cache + org.codehaus.plexus.cache.ehcache.EhcacheCache + URL Failure Cache + + 600 + true + ${java.io.tmpdir}/archiva/urlcache + false + 1000 + LRU + cache + false + + 2700 + + 1800 + + + + diff --git a/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java b/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java new file mode 100644 index 000000000..dd65f7a90 --- /dev/null +++ b/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/CachedFailuresPolicyTest.java @@ -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 Joakim Erdfelt + * @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-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java b/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java new file mode 100644 index 000000000..d37b42d24 --- /dev/null +++ b/archiva-base/archiva-policies/src/test/java/org/apache/maven/archiva/policies/ChecksumPolicyTest.java @@ -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 Joakim Erdfelt + * @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-base/archiva-policies/src/test/resources/checksums/artifact.jar b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar new file mode 100644 index 000000000..d1b610e5e Binary files /dev/null and b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar differ diff --git a/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad new file mode 100644 index 000000000..aafbb1c77 --- /dev/null +++ b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-bad @@ -0,0 +1 @@ +444ccc111aaa222999888eee222fff00 artifact.jar diff --git a/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good new file mode 100644 index 000000000..1c8465238 --- /dev/null +++ b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.md5-good @@ -0,0 +1 @@ +360ccd01d8a0a2d94b86f9802c2fc548 artifact.jar diff --git a/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad new file mode 100644 index 000000000..2d809c29b --- /dev/null +++ b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-bad @@ -0,0 +1 @@ +ddd888999000444888bbbaaa555333999777eee0 artifact.jar diff --git a/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good new file mode 100644 index 000000000..0f10d257e --- /dev/null +++ b/archiva-base/archiva-policies/src/test/resources/checksums/artifact.jar.sha1-good @@ -0,0 +1 @@ +7dd8929150664f182db60ad15f20359d875f059f artifact.jar diff --git a/archiva-base/archiva-policies/src/test/resources/log4j.xml b/archiva-base/archiva-policies/src/test/resources/log4j.xml new file mode 100644 index 000000000..3c782b138 --- /dev/null +++ b/archiva-base/archiva-policies/src/test/resources/log4j.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +