From: Brett Porter Date: Thu, 3 Apr 2008 07:58:24 +0000 (+0000) Subject: [MRM-159] should not respond with a 404 if proxying a file results in a remote error X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=86de241b7345098d50cf1f8fd6f76f31f1c3e6b8;p=archiva.git [MRM-159] should not respond with a 404 if proxying a file results in a remote error git-svn-id: https://svn.apache.org/repos/asf/archiva/branches@644205 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/archiva-1.0.x/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java b/archiva-1.0.x/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java index 6fd182987..d83f44042 100644 --- a/archiva-1.0.x/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java +++ b/archiva-1.0.x/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java @@ -29,7 +29,7 @@ import org.apache.maven.archiva.configuration.io.registry.ConfigurationRegistryW import org.apache.maven.archiva.policies.AbstractUpdatePolicy; import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.ChecksumPolicy; -import org.apache.maven.archiva.policies.DownloadPolicy; +import org.apache.maven.archiva.policies.Policy; import org.apache.maven.archiva.policies.PostDownloadPolicy; import org.apache.maven.archiva.policies.PreDownloadPolicy; import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator; @@ -276,7 +276,7 @@ public class DefaultArchivaConfiguration // Validate existance of policy key. if ( policyExists( policyId ) ) { - DownloadPolicy policy = findPolicy( policyId ); + Policy policy = findPolicy( policyId ); // Does option exist? if ( !policy.getOptions().contains( setting ) ) { @@ -319,7 +319,7 @@ public class DefaultArchivaConfiguration return config; } - private DownloadPolicy findPolicy( String policyId ) + private Policy findPolicy( String policyId ) { if ( MapUtils.isEmpty( prePolicies ) ) { @@ -333,7 +333,7 @@ public class DefaultArchivaConfiguration return null; } - DownloadPolicy policy; + Policy policy; policy = prePolicies.get( policyId ); if ( policy != null ) diff --git a/archiva-1.0.x/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo b/archiva-1.0.x/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo index 611adff86..5d3f1b87f 100644 --- a/archiva-1.0.x/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo +++ b/archiva-1.0.x/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo @@ -642,6 +642,20 @@ */ public static final int UNORDERED = 0; + /** + * The policy key {@link #getPolicies()} for error handling. + * See {@link org.apache.maven.archiva.policies.DownloadErrorPolicy} + * for details on potential values to this policy key. + */ + public static final String POLICY_PROPAGATE_ERRORS = "propagate-errors"; + + /** + * The policy key {@link #getPolicies()} for error handling when an artifact is present. + * See {@link org.apache.maven.archiva.policies.DownloadErrorPolicy} + * for details on potential values to this policy key. + */ + public static final String POLICY_PROPAGATE_ERRORS_ON_UPDATE = "propagate-errors-on-update"; + /** * The policy key {@link #getPolicies()} for snapshot handling. * See {@link org.apache.maven.archiva.policies.SnapshotsPolicy} diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java index c7d44258c..28f2d3e6b 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java @@ -105,6 +105,11 @@ public class CachedFailuresPolicy return "cache-failures"; } + public String getName() + { + return "Cache failures"; + } + public List getOptions() { return options; diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java index c86bbaaec..2c96e8317 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java @@ -155,6 +155,11 @@ public class ChecksumPolicy return "checksum"; } + public String getName() + { + return "Checksum"; + } + public List getOptions() { return options; diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadErrorPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadErrorPolicy.java new file mode 100644 index 000000000..b5c209c6c --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadErrorPolicy.java @@ -0,0 +1,50 @@ +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 java.io.File; +import java.util.Map; +import java.util.Properties; + +/** + * Policy to apply after the download has completed, but before the + * resource is made available to the calling client. + * + * @author Brett Porter + * @version $Id$ + */ +public interface DownloadErrorPolicy + extends Policy +{ + /** + * Apply the download error policy. + * + * @param policySetting the policy setting. + * @param request the list of request properties that the policy might use. + * @param localFile + * @param exception the exception that triggered the error + * @param previousExceptions any previously triggered exceptions + * @return whether to process the exception or not + * @throws PolicyConfigurationException if the policy is improperly configured + */ + public boolean applyPolicy( String policySetting, Properties request, File localFile, Exception exception, + Map previousExceptions ) + throws PolicyConfigurationException; +} \ No newline at end of file diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java index 6d506308d..68036d9e8 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java @@ -20,7 +20,6 @@ package org.apache.maven.archiva.policies; */ import java.io.File; -import java.util.List; import java.util.Properties; /** @@ -30,27 +29,8 @@ import java.util.Properties; * @version $Id$ */ public interface DownloadPolicy + extends Policy { - /** - * Get the list of options for this policy. - * - * @return the list of options for this policy. - */ - public List getOptions(); - - /** - * Get the default option for this policy. - * - * @return the default policy for this policy. - */ - public String getDefaultOption(); - - /** - * Get the id for this policy. - * - * @return the id for this policy. - */ - public String getId(); /** * Apply the download policy. diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/Policy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/Policy.java new file mode 100644 index 000000000..f7add1b73 --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/Policy.java @@ -0,0 +1,55 @@ +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 java.util.List; + +public interface Policy +{ + /** + * Get the list of options for this policy. + * + * @return the list of options for this policy. + */ + List getOptions(); + + /** + * Get the default option for this policy. + * + * @return the default policy for this policy. + */ + String getDefaultOption(); + + /** + * Get the id for this policy. + * + * @return the id for this policy. + */ + String getId(); + + /** + * Get the display name for this policy. + * + * @todo i18n + * + * @return the name for this policy + */ + String getName(); +} diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java index d1f6d216e..12bb6b416 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java @@ -19,9 +19,6 @@ package org.apache.maven.archiva.policies; * under the License. */ -import java.io.File; -import java.util.Properties; - /** * Policy to apply after the download has completed, but before the * resource is made available to the calling client. @@ -32,18 +29,4 @@ import java.util.Properties; public interface PostDownloadPolicy extends DownloadPolicy { - /** - * Apply the download policy. - * - * A true result allows the download to succeed. false indicates that the - * download is a failure. - * - * @param policySetting the policy setting. - * @param request the list of request properties that the policy might use. - * @param localFile the local file that this policy affects - * - * @throws PolicyViolationException if the policy has been violated. - */ - public void applyPolicy( String policySetting, Properties request, File localFile ) - throws PolicyViolationException, PolicyConfigurationException; } diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java index f88eb938f..1faf52025 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java @@ -20,9 +20,6 @@ package org.apache.maven.archiva.policies; */ -import java.io.File; -import java.util.Properties; - /** * Policy to apply before the download is attempted. * @@ -31,18 +28,4 @@ import java.util.Properties; */ public interface PreDownloadPolicy extends DownloadPolicy { - /** - * Apply the download policy. - * - * A true result lets the download occur. A false result prevents the download - * from occuring. - * - * @param policySetting the policy setting. - * @param request the list of request properties that the policy might use. - * @param localFile the local file that this policy affects - * - * @throws PolicyViolationException if the policy has been violated. - */ - public void applyPolicy( String policySetting, Properties request, File localFile ) - throws PolicyViolationException, PolicyConfigurationException; } diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsDownloadPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsDownloadPolicy.java new file mode 100644 index 000000000..cca1c6750 --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsDownloadPolicy.java @@ -0,0 +1,118 @@ +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.codehaus.plexus.logging.AbstractLogEnabled; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * PropagateErrorsPolicy - a policy applied on error to determine how to treat the error. + * + * @plexus.component role="org.apache.maven.archiva.policies.DownloadErrorPolicy" + * role-hint="propagate-errors" + */ +public class PropagateErrorsDownloadPolicy + extends AbstractLogEnabled + implements DownloadErrorPolicy +{ + /** + * Signifies any error should stop searching for other proxies. + */ + public static final String STOP = "stop"; + + /** + * Propagate errors at the end after all are gathered, if there was no successful download from other proxies. + */ + public static final String QUEUE = "queue error"; + + /** + * Ignore errors and treat as if it were not found. + */ + public static final String IGNORE = "ignore"; + + private List options = new ArrayList(); + + public PropagateErrorsDownloadPolicy() + { + options.add( STOP ); + options.add( QUEUE ); + options.add( IGNORE ); + } + + public boolean applyPolicy( String policySetting, Properties request, File localFile, Exception exception, + Map previousExceptions ) + throws PolicyConfigurationException + { + if ( !options.contains( policySetting ) ) + { + // Not a valid code. + throw new PolicyConfigurationException( "Unknown error policy setting [" + policySetting + + "], valid settings are [" + StringUtils.join( options.iterator(), "," ) + "]" ); + } + + if ( IGNORE.equals( policySetting ) ) + { + // Ignore. + getLogger().debug( "Error policy set to IGNORE." ); + return false; + } + + String repositoryId = request.getProperty( "remoteRepositoryId" ); + if ( STOP.equals( policySetting ) ) + { + return true; + } + + if ( QUEUE.equals( policySetting ) ) + { + previousExceptions.put( repositoryId, exception ); + return true; + } + + throw new PolicyConfigurationException( + "Unable to process checksum policy of [" + policySetting + "], please file a bug report." ); + } + + public String getDefaultOption() + { + return QUEUE; + } + + public String getId() + { + return "propagate-errors"; + } + + public String getName() + { + return "On remote error"; + } + + public List getOptions() + { + return options; + } +} \ No newline at end of file diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java new file mode 100644 index 000000000..d2b471af3 --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java @@ -0,0 +1,105 @@ +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.codehaus.plexus.logging.AbstractLogEnabled; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * PropagateErrorsPolicy - a policy applied on error to determine how to treat the error. + * + * @plexus.component role="org.apache.maven.archiva.policies.DownloadErrorPolicy" + * role-hint="propagate-errors-on-update" + */ +public class PropagateErrorsOnUpdateDownloadPolicy + extends AbstractLogEnabled + implements DownloadErrorPolicy +{ + /** + * Signifies any error should cause a failure whether the artifact is already present or not. + */ + public static final String ALWAYS = "always"; + + /** + * Signifies any error should cause a failure only if the artifact is not already present. + */ + public static final String NOT_PRESENT = "artifact not already present"; + + private List options = new ArrayList(); + + public PropagateErrorsOnUpdateDownloadPolicy() + { + options.add( ALWAYS ); + options.add( NOT_PRESENT ); + } + + public boolean applyPolicy( String policySetting, Properties request, File localFile, Exception exception, + Map previousExceptions ) + throws PolicyConfigurationException + { + if ( !options.contains( policySetting ) ) + { + // Not a valid code. + throw new PolicyConfigurationException( "Unknown error policy setting [" + policySetting + + "], valid settings are [" + StringUtils.join( options.iterator(), "," ) + "]" ); + } + + if ( ALWAYS.equals( policySetting ) ) + { + // throw ther exception regardless + return true; + } + + if ( NOT_PRESENT.equals( policySetting ) ) + { + // cancel the exception if the file exists + return !localFile.exists(); + } + + throw new PolicyConfigurationException( "Unable to process checksum policy of [" + policySetting + + "], please file a bug report." ); + } + + public String getDefaultOption() + { + return NOT_PRESENT; + } + + public String getId() + { + return "propagate-errors-on-update"; + } + + public String getName() + { + return "Return error when"; + } + + public List getOptions() + { + return options; + } +} \ No newline at end of file diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ProxyDownloadException.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ProxyDownloadException.java new file mode 100644 index 000000000..9d328c6b7 --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ProxyDownloadException.java @@ -0,0 +1,66 @@ +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.common.ArchivaException; + +import java.util.Collections; +import java.util.Map; + +/** + * One or more exceptions occurred downloading from a remote repository during the proxy phase. + */ +public class ProxyDownloadException + extends ArchivaException +{ + /** + * A list of failures keyed by repository ID. + */ + private final Map failures; + + public ProxyDownloadException( String message, String repositoryId, Exception cause ) + { + super( constructMessage( message, Collections.singletonMap( repositoryId, cause ) ), cause ); + + failures = Collections.singletonMap( repositoryId, cause ); + } + + public ProxyDownloadException( String message, Map failures ) + { + super( constructMessage( message, failures ) ); + + this.failures = failures; + } + + private static String constructMessage( String message, Map failures ) + { + String msg = message + ":"; + for ( Map.Entry entry : failures.entrySet() ) + { + msg += "\n\t" + entry.getKey() + ": " + entry.getValue().getMessage(); + } + return msg; + } + + public Map getFailures() + { + return failures; + } +} diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java index 8b53461a8..86ad7c3fc 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java @@ -55,4 +55,9 @@ public class ReleasesPolicy { return "releases"; } + + public String getName() + { + return "Releases"; + } } diff --git a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java index ffa903262..ea10023c3 100644 --- a/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java +++ b/archiva-1.0.x/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java @@ -55,4 +55,9 @@ public class SnapshotsPolicy { return "snapshots"; } + + public String getName() + { + return "Snapshots"; + } } diff --git a/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java b/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java index 5b3d1a515..0252ac7c7 100644 --- a/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java +++ b/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java @@ -31,11 +31,13 @@ import org.apache.maven.archiva.model.Keys; import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.RepositoryURL; import org.apache.maven.archiva.model.VersionedReference; +import org.apache.maven.archiva.policies.DownloadErrorPolicy; import org.apache.maven.archiva.policies.DownloadPolicy; import org.apache.maven.archiva.policies.PolicyConfigurationException; import org.apache.maven.archiva.policies.PolicyViolationException; import org.apache.maven.archiva.policies.PostDownloadPolicy; import org.apache.maven.archiva.policies.PreDownloadPolicy; +import org.apache.maven.archiva.policies.ProxyDownloadException; import org.apache.maven.archiva.policies.urlcache.UrlFailureCache; import org.apache.maven.archiva.repository.ContentNotFoundException; import org.apache.maven.archiva.repository.ManagedRepositoryContent; @@ -67,6 +69,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -77,6 +80,7 @@ import java.util.Properties; * * @author Joakim Erdfelt * @version $Id$ + * @todo exception handling needs work - "not modified" is not really an exceptional case, and it has more layers than your average brown onion * @plexus.component role-hint="default" */ public class DefaultRepositoryProxyConnectors @@ -113,6 +117,11 @@ public class DefaultRepositoryProxyConnectors */ private Map postDownloadPolicies; + /** + * @plexus.requirement role="org.apache.maven.archiva.policies.DownloadErrorPolicy" + */ + private Map downloadErrorPolicies; + /** * @plexus.requirement role-hint="default" */ @@ -134,26 +143,31 @@ public class DefaultRepositoryProxyConnectors * @param artifact the artifact reference to fetch. * @return the local file in the managed repository that was fetched, or null if the artifact was not (or * could not be) fetched. - * @throws ProxyException if there was a problem fetching the artifact. + * @throws PolicyViolationException if there was a problem fetching the artifact. */ public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact ) + throws ProxyDownloadException { File localFile = toLocalFile( repository, artifact ); Properties requestProperties = new Properties(); requestProperties.setProperty( "filetype", "artifact" ); requestProperties.setProperty( "version", artifact.getVersion() ); + requestProperties.setProperty( "managedRepositoryId", repository.getId() ); List connectors = getProxyConnectors( repository ); + Map previousExceptions = new LinkedHashMap(); for ( ProxyConnector connector : connectors ) { RemoteRepositoryContent targetRepository = connector.getTargetRepository(); + requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() ); + String targetPath = targetRepository.toPath( artifact ); try { - File downloadedFile = transferFile( connector, targetRepository, targetPath, localFile, - requestProperties ); + File downloadedFile = + transferFile( connector, targetRepository, targetPath, localFile, requestProperties ); if ( fileExists( downloadedFile ) ) { @@ -163,22 +177,27 @@ public class DefaultRepositoryProxyConnectors } catch ( NotFoundException e ) { - getLogger().debug( "Artifact " + Keys.toKey( artifact ) + " not found on repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Artifact " + Keys.toKey( artifact ) + " not found on repository \"" + + targetRepository.getRepository().getId() + "\"." ); } catch ( NotModifiedException e ) { - getLogger().debug( "Artifact " + Keys.toKey( artifact ) + " not updated on repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Artifact " + Keys.toKey( artifact ) + " not updated on repository \"" + + targetRepository.getRepository().getId() + "\"." ); } catch ( ProxyException e ) { - getLogger().warn( "Transfer error from repository \"" + targetRepository.getRepository().getId() + - "\" for artifact " + Keys.toKey( artifact ) + ", continuing to next repository. Error message: " + - e.getMessage() ); - getLogger().debug( "Full stack trace", e ); + validatePolicies( this.downloadErrorPolicies, connector.getPolicies(), requestProperties, artifact, + targetRepository, localFile, e, previousExceptions ); } } + + if ( !previousExceptions.isEmpty() ) + { + throw new ProxyDownloadException( "Failures occurred downloading from some remote repositories", + previousExceptions ); + } + getLogger().debug( "Exhausted all target repositories, artifact " + Keys.toKey( artifact ) + " not found." ); return null; @@ -218,15 +237,13 @@ public class DefaultRepositoryProxyConnectors } catch ( NotFoundException e ) { - getLogger().debug( "Versioned Metadata " + Keys.toKey( metadata ) - + " not found on remote repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Versioned Metadata " + Keys.toKey( metadata ) + + " not found on remote repository \"" + targetRepository.getRepository().getId() + "\"." ); } catch ( NotModifiedException e ) { - getLogger().debug( "Versioned Metadata " + Keys.toKey( metadata ) - + " not updated on remote repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Versioned Metadata " + Keys.toKey( metadata ) + + " not updated on remote repository \"" + targetRepository.getRepository().getId() + "\"." ); } catch ( ProxyException e ) { @@ -336,14 +353,13 @@ public class DefaultRepositoryProxyConnectors } catch ( NotFoundException e ) { - getLogger().debug( "Project Metadata " + Keys.toKey( metadata ) + " not found on remote repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Project Metadata " + Keys.toKey( metadata ) + " not found on remote repository \"" + + targetRepository.getRepository().getId() + "\"." ); } catch ( NotModifiedException e ) { - getLogger().debug( "Project Metadata " + Keys.toKey( metadata ) - + " not updated on remote repository \"" - + targetRepository.getRepository().getId() + "\"." ); + getLogger().debug( "Project Metadata " + Keys.toKey( metadata ) + + " not updated on remote repository \"" + targetRepository.getRepository().getId() + "\"." ); } catch ( ProxyException e ) { @@ -469,10 +485,10 @@ public class DefaultRepositoryProxyConnectors * @param localFile the local file to place the downloaded resource into * @param requestProperties the request properties to utilize for policy handling. * @return the local file that was downloaded, or null if not downloaded. - * @throws NotFoundException if the file was not found on the remote repository. + * @throws NotFoundException if the file was not found on the remote repository. * @throws NotModifiedException if the localFile was present, and the resource was present on remote repository, * but the remote resource is not newer than the local File. - * @throws ProxyException if transfer was unsuccessful. + * @throws ProxyException if transfer was unsuccessful. */ private File transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath, File localFile, Properties requestProperties ) @@ -524,10 +540,10 @@ public class DefaultRepositoryProxyConnectors getLogger().info( emsg ); return null; } - + Wagon wagon = null; try - { + { RepositoryURL repoUrl = remoteRepository.getURL(); String protocol = repoUrl.getProtocol(); wagon = (Wagon) wagons.get( protocol ); @@ -689,13 +705,13 @@ public class DefaultRepositoryProxyConnectors } else { - getLogger().debug( "Retrieving " + remotePath + " from " + remoteRepository.getRepository().getName() - + " if updated" ); + getLogger().debug( "Retrieving " + remotePath + " from " + remoteRepository.getRepository().getName() + + " if updated" ); success = wagon.getIfNewer( remotePath, temp, localFile.lastModified() ); if ( !success ) { - throw new NotModifiedException( "Not downloaded, as local file is newer than remote side: " - + localFile.getAbsolutePath() ); + throw new NotModifiedException( + "Not downloaded, as local file is newer than remote side: " + localFile.getAbsolutePath() ); } if ( temp.exists() ) @@ -709,13 +725,15 @@ public class DefaultRepositoryProxyConnectors } catch ( ResourceDoesNotExistException e ) { - throw new NotFoundException( "Resource [" + remoteRepository.getURL() + "/" + remotePath - + "] does not exist: " + e.getMessage(), e ); + throw new NotFoundException( + "Resource [" + remoteRepository.getURL() + "/" + remotePath + "] does not exist: " + e.getMessage(), + e ); } catch ( WagonException e ) { - throw new ProxyException( "Download failure on resource [" + remoteRepository.getURL() + "/" + remotePath + "]:" - + e.getMessage(), e ); + throw new ProxyException( + "Download failure on resource [" + remoteRepository.getURL() + "/" + remotePath + "]:" + e.getMessage(), + e ); } finally { @@ -740,10 +758,10 @@ public class DefaultRepositoryProxyConnectors { for ( Entry entry : policies.entrySet() ) { - String key = (String) entry.getKey(); + String key = entry.getKey(); DownloadPolicy policy = entry.getValue(); String defaultSetting = policy.getDefaultOption(); - String setting = StringUtils.defaultString( (String) settings.get( key ), defaultSetting ); + String setting = StringUtils.defaultString( settings.get( key ), defaultSetting ); getLogger().debug( "Applying [" + key + "] policy with [" + setting + "]" ); try @@ -757,6 +775,56 @@ public class DefaultRepositoryProxyConnectors } } + private void validatePolicies( Map policies, Map settings, + Properties request, ArtifactReference artifact, RemoteRepositoryContent content, + File localFile, ProxyException exception, Map previousExceptions ) + throws ProxyDownloadException + { + boolean process = true; + for ( Entry entry : policies.entrySet() ) + { + String key = entry.getKey(); + DownloadErrorPolicy policy = entry.getValue(); + String defaultSetting = policy.getDefaultOption(); + String setting = StringUtils.defaultString( settings.get( key ), defaultSetting ); + + getLogger().debug( "Applying [" + key + "] policy with [" + setting + "]" ); + try + { + // all policies must approve the exception, any can cancel + process = policy.applyPolicy( setting, request, localFile, exception, previousExceptions ); + if ( !process ) + { + break; + } + } + catch ( PolicyConfigurationException e ) + { + getLogger().error( e.getMessage(), e ); + } + } + + if ( process ) + { + // if the exception was queued, don't throw it + if ( !previousExceptions.containsKey( content.getId() ) ) + { + throw new ProxyDownloadException( + "An error occurred in downloading from the remote repository, and the policy is to fail immediately", + content.getId(), exception ); + } + } + else + { + // if the exception was queued, but cancelled, remove it + previousExceptions.remove( content.getId() ); + } + + getLogger().warn( "Transfer error from repository \"" + content.getRepository().getId() + "\" for artifact " + + Keys.toKey( artifact ) + ", continuing to next repository. Error message: " + exception.getMessage() ); + getLogger().debug( "Full stack trace", exception ); + } + /** * Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles * its downloaded files. @@ -800,7 +868,8 @@ public class DefaultRepositoryProxyConnectors * @param remoteRepository the remote repository to connect to. * @return true if the connection was successful. false if not connected. */ - private boolean connectToRepository( ProxyConnector connector, Wagon wagon, RemoteRepositoryContent remoteRepository ) + private boolean connectToRepository( ProxyConnector connector, Wagon wagon, + RemoteRepositoryContent remoteRepository ) { boolean connected = false; @@ -818,8 +887,8 @@ public class DefaultRepositoryProxyConnectors if ( StringUtils.isNotBlank( username ) && StringUtils.isNotBlank( password ) ) { - getLogger().debug( "Using username " + username + " to connect to remote repository " - + remoteRepository.getURL() ); + getLogger().debug( + "Using username " + username + " to connect to remote repository " + remoteRepository.getURL() ); authInfo = new AuthenticationInfo(); authInfo.setUserName( username ); authInfo.setPassword( password ); @@ -829,7 +898,8 @@ public class DefaultRepositoryProxyConnectors getLogger().debug( "No authentication for remote repository needed" ); } - Repository wagonRepository = new Repository( remoteRepository.getId(), remoteRepository.getURL().toString() ); + Repository wagonRepository = + new Repository( remoteRepository.getId(), remoteRepository.getURL().toString() ); if ( networkProxy != null ) { wagon.connect( wagonRepository, authInfo, networkProxy ); @@ -843,15 +913,13 @@ public class DefaultRepositoryProxyConnectors catch ( ConnectionException e ) { getLogger().warn( - "Could not connect to " + remoteRepository.getRepository().getName() + ": " - + e.getMessage() ); + "Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() ); connected = false; } catch ( AuthenticationException e ) { getLogger().warn( - "Could not connect to " + remoteRepository.getRepository().getName() + ": " - + e.getMessage() ); + "Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() ); connected = false; } @@ -903,10 +971,10 @@ public class DefaultRepositoryProxyConnectors public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) { - if ( ConfigurationNames.isNetworkProxy( propertyName ) - || ConfigurationNames.isManagedRepositories( propertyName ) - || ConfigurationNames.isRemoteRepositories( propertyName ) - || ConfigurationNames.isProxyConnector( propertyName ) ) + if ( ConfigurationNames.isNetworkProxy( propertyName ) || + ConfigurationNames.isManagedRepositories( propertyName ) || + ConfigurationNames.isRemoteRepositories( propertyName ) || + ConfigurationNames.isProxyConnector( propertyName ) ) { initConnectorsAndNetworkProxies(); } diff --git a/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java b/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java index 6d832bfbb..c27c5b8ab 100644 --- a/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java +++ b/archiva-1.0.x/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java @@ -22,6 +22,7 @@ package org.apache.maven.archiva.proxy; import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.VersionedReference; +import org.apache.maven.archiva.policies.ProxyDownloadException; import org.apache.maven.archiva.repository.ManagedRepositoryContent; import java.io.File; @@ -45,11 +46,11 @@ public interface RepositoryProxyConnectors * @param repository the source repository to use. (must be a managed repository) * @param artifact the artifact to fetch. * @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. - * @throws ProxyException if there was a problem fetching the content from the target repositories. + * @throws ProxyDownloadException if there was a problem fetching the content from the target repositories. */ public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact ) - throws ProxyException; - + throws ProxyDownloadException; + /** * Performs the metadata fetch operation against the target repositories * of the provided source repository. @@ -60,11 +61,9 @@ public interface RepositoryProxyConnectors * @param repository the source repository to use. (must be a managed repository) * @param metadata the metadata to fetch. * @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. - * @throws ProxyException if there was a problem fetching the content from the target repositories. */ - public File fetchFromProxies( ManagedRepositoryContent repository, VersionedReference metadata ) - throws ProxyException; - + public File fetchFromProxies( ManagedRepositoryContent repository, VersionedReference metadata ); + /** * Performs the metadata fetch operation against the target repositories * of the provided source repository. @@ -75,10 +74,8 @@ public interface RepositoryProxyConnectors * @param repository the source repository to use. (must be a managed repository) * @param metadata the metadata to fetch. * @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. - * @throws ProxyException if there was a problem fetching the content from the target repositories. */ - public File fetchFromProxies( ManagedRepositoryContent repository, ProjectReference metadata ) - throws ProxyException; + public File fetchFromProxies( ManagedRepositoryContent repository, ProjectReference metadata ); /** * Get the List of {@link ProxyConnector} objects of the source repository. diff --git a/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java index 8527ade4f..cf660af49 100644 --- a/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java +++ b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java @@ -26,6 +26,8 @@ import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.ChecksumPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsDownloadPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy; import org.apache.maven.archiva.policies.ReleasesPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.policies.urlcache.UrlFailureCache; @@ -302,8 +304,23 @@ public abstract class AbstractProxyTestCase SnapshotsPolicy.ALWAYS, CachedFailuresPolicy.NO ); } - protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, - String releasePolicy, String snapshotPolicy, String cacheFailuresPolicy ) + protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy, + String snapshotPolicy, String cacheFailuresPolicy ) + { + saveConnector( sourceRepoId, targetRepoId, checksumPolicy, releasePolicy, snapshotPolicy, cacheFailuresPolicy, + PropagateErrorsDownloadPolicy.QUEUE ); + } + + protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy, + String snapshotPolicy, String cacheFailuresPolicy, String errorPolicy ) + { + saveConnector( sourceRepoId, targetRepoId, checksumPolicy, releasePolicy, snapshotPolicy, cacheFailuresPolicy, + errorPolicy, PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + } + + protected void saveConnector( String sourceRepoId, String targetRepoId, String checksumPolicy, String releasePolicy, + String snapshotPolicy, String cacheFailuresPolicy, String errorPolicy, + String errorOnUpdatePolicy ) { ProxyConnectorConfiguration connectorConfig = new ProxyConnectorConfiguration(); connectorConfig.setSourceRepoId( sourceRepoId ); @@ -312,6 +329,8 @@ public abstract class AbstractProxyTestCase connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_RELEASES, releasePolicy ); connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_SNAPSHOTS, snapshotPolicy ); connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CACHE_FAILURES, cacheFailuresPolicy ); + connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS, errorPolicy ); + connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_PROPAGATE_ERRORS_ON_UPDATE, errorOnUpdatePolicy ); int count = config.getConfiguration().getProxyConnectors().size(); config.getConfiguration().addProxyConnector( connectorConfig ); @@ -325,6 +344,10 @@ public abstract class AbstractProxyTestCase config.triggerChange( prefix + ".policies.checksum", connectorConfig.getPolicy( "checksum", "" ) ); config.triggerChange( prefix + ".policies.snapshots", connectorConfig.getPolicy( "snapshots", "" ) ); config.triggerChange( prefix + ".policies.cache-failures", connectorConfig.getPolicy( "cache-failures", "" ) ); + config.triggerChange( prefix + ".policies.propagate-errors", + connectorConfig.getPolicy( "propagate-errors", "" ) ); + config.triggerChange( prefix + ".policies.propagate-errors-on-update", + connectorConfig.getPolicy( "propagate-errors-on-update", "" ) ); } protected void saveManagedRepositoryConfig( String id, String name, String path, String layout ) diff --git a/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java new file mode 100644 index 000000000..0e62f8273 --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java @@ -0,0 +1,627 @@ +package org.apache.maven.archiva.proxy; + +/* + * 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.CachedFailuresPolicy; +import org.apache.maven.archiva.policies.ChecksumPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsDownloadPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy; +import org.apache.maven.archiva.policies.ProxyDownloadException; +import org.apache.maven.archiva.policies.ReleasesPolicy; +import org.apache.maven.archiva.policies.SnapshotsPolicy; +import org.apache.maven.archiva.repository.layout.LayoutException; +import org.apache.maven.wagon.ResourceDoesNotExistException; +import org.apache.maven.wagon.TransferFailedException; +import org.apache.maven.wagon.authorization.AuthorizationException; + +import java.io.File; + +/** + * ErrorHandlingTest + * + * @author Brett Porter + * @version $Id$ + */ +public class ErrorHandlingTest + extends AbstractProxyTestCase +{ + private static final String PATH_IN_BOTH_REMOTES_NOT_LOCAL = + "org/apache/maven/test/get-in-both-proxies/1.0/get-in-both-proxies-1.0.jar"; + + private static final String PATH_IN_BOTH_REMOTES_AND_LOCAL = + "org/apache/maven/test/get-on-multiple-repos/1.0/get-on-multiple-repos-1.0.pom"; + + private static final String ID_MOCKED_PROXIED1 = "badproxied1"; + + private static final String NAME_MOCKED_PROXIED1 = "Bad Proxied 1"; + + private static final String ID_MOCKED_PROXIED2 = "badproxied2"; + + private static final String NAME_MOCKED_PROXIED2 = "Bad Proxied 2"; + + public void testPropagateErrorImmediatelyWithErrorThenSuccess() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP ); + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED2 ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateErrorImmediatelyWithNotFoundThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED2 ); + } + + public void testPropagateErrorImmediatelyWithSuccessThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED1 ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED1 ); + } + + public void testPropagateErrorImmediatelyWithNotFoundThenSuccess() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED2 ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED2 ); + } + + public void testPropagateErrorAtEndWithErrorThenSuccess() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED2 ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateErrorAtEndWithSuccessThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED1 ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED1 ); + } + + public void testPropagateErrorAtEndWithNotFoundThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED2 ); + } + + public void testPropagateErrorAtEndWithErrorThenNotFound() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE ); + + simulateGetError( path, expectedFile, createTransferException() ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateErrorAtEndWithErrorThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE ); + + simulateGetError( path, expectedFile, createTransferException() ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmFailures( path, new String[]{ID_MOCKED_PROXIED1, ID_MOCKED_PROXIED2} ); + } + + public void testPropagateErrorAtEndWithNotFoundThenSuccess() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED2 ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED2 ); + } + + public void testIgnoreErrorWithErrorThenSuccess() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED2 ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED2 ); + } + + public void testIgnoreErrorWithSuccessThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + saveConnector( ID_DEFAULT_MANAGED, ID_PROXIED1 ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE ); + + confirmSuccess( path, expectedFile, REPOPATH_PROXIED1 ); + } + + public void testIgnoreErrorWithNotFoundThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + } + + public void testIgnoreErrorWithErrorThenNotFound() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE ); + + simulateGetError( path, expectedFile, createTransferException() ); + + simulateGetError( path, expectedFile, createResourceNotFoundException() ); + + confirmNotDownloadedNoError( path ); + } + + public void testIgnoreErrorWithErrorThenError() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE ); + + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE ); + + simulateGetError( path, expectedFile, createTransferException() ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + } + + public void testPropagateOnUpdateAlwaysArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateOnUpdateAlwaysArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateOnUpdateAlwaysQueueArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetError( path, expectedFile, createTransferException() ); + simulateGetError( path, expectedFile, createTransferException() ); + + confirmFailures( path, new String[] { ID_MOCKED_PROXIED1, ID_MOCKED_PROXIED2 } ); + } + + public void testPropagateOnUpdateAlwaysQueueArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmFailures( path, new String[] { ID_MOCKED_PROXIED1, ID_MOCKED_PROXIED2 } ); + } + + public void testPropagateOnUpdateAlwaysIgnoreArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetError( path, expectedFile, createTransferException() ); + simulateGetError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + } + + public void testPropagateOnUpdateAlwaysIgnoreArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.ALWAYS ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + assertTrue( expectedFile.exists() ); + } + + public void testPropagateOnUpdateNotPresentArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetError( path, expectedFile, createTransferException() ); + + confirmSingleFailure( path, ID_MOCKED_PROXIED1 ); + } + + public void testPropagateOnUpdateNotPresentArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.STOP, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + assertTrue( expectedFile.exists() ); + } + + public void testPropagateOnUpdateNotPresentQueueArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetError( path, expectedFile, createTransferException() ); + simulateGetError( path, expectedFile, createTransferException() ); + + confirmFailures( path, new String[] { ID_MOCKED_PROXIED1, ID_MOCKED_PROXIED2 } ); + } + + public void testPropagateOnUpdateNotPresentQueueArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.QUEUE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + assertTrue( expectedFile.exists() ); + } + + public void testPropagateOnUpdateNotPresentIgnoreArtifactNotPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_NOT_LOCAL; + File expectedFile = setupRepositoriesWithLocalFileNotPresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetError( path, expectedFile, createTransferException() ); + simulateGetError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + } + + public void testPropagateOnUpdateNotPresentIgnoreArtifactPresent() + throws Exception + { + String path = PATH_IN_BOTH_REMOTES_AND_LOCAL; + File expectedFile = setupRepositoriesWithLocalFilePresent( path ); + + createMockedProxyConnector( ID_MOCKED_PROXIED1, NAME_MOCKED_PROXIED1, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + createMockedProxyConnector( ID_MOCKED_PROXIED2, NAME_MOCKED_PROXIED2, PropagateErrorsDownloadPolicy.IGNORE, + PropagateErrorsOnUpdateDownloadPolicy.NOT_PRESENT ); + + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + simulateGetIfNewerError( path, expectedFile, createTransferException() ); + + confirmNotDownloadedNoError( path ); + assertTrue( expectedFile.exists() ); + } + + // ------------------------------------------ + // HELPER METHODS + // ------------------------------------------ + + private void createMockedProxyConnector( String id, String name, String errorPolicy ) + { + saveRemoteRepositoryConfig( id, name, "test://bad.machine.com/repo/", "default" ); + saveConnector( ID_DEFAULT_MANAGED, id, ChecksumPolicy.FIX, ReleasesPolicy.ALWAYS, SnapshotsPolicy.ALWAYS, + CachedFailuresPolicy.NO, errorPolicy ); + } + + private void createMockedProxyConnector( String id, String name, String errorPolicy, String errorOnUpdatePolicy ) + { + saveRemoteRepositoryConfig( id, name, "test://bad.machine.com/repo/", "default" ); + saveConnector( ID_DEFAULT_MANAGED, id, ChecksumPolicy.FIX, ReleasesPolicy.ALWAYS, SnapshotsPolicy.ALWAYS, + CachedFailuresPolicy.NO, errorPolicy, errorOnUpdatePolicy ); + } + + private File setupRepositoriesWithLocalFileNotPresent( String path ) + throws Exception + { + setupTestableManagedRepository( path ); + + File file = new File( managedDefaultDir, path ); + + assertNotExistsInManagedDefaultRepo( file ); + + return file; + } + + private File setupRepositoriesWithLocalFilePresent( String path ) + throws Exception + { + setupTestableManagedRepository( path ); + + File file = new File( managedDefaultDir, path ); + + assertTrue( file.exists() ); + + return file; + } + + private void simulateGetError( String path, File expectedFile, Exception throwable ) + throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException + { + wagonMock.get( path, createExpectedTempFile( expectedFile ) ); + wagonMockControl.setThrowable( throwable, 1 ); + } + + private void simulateGetIfNewerError( String path, File expectedFile, TransferFailedException exception ) + throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException + { + wagonMock.getIfNewer( path, createExpectedTempFile( expectedFile ), expectedFile.lastModified() ); + wagonMockControl.setThrowable( exception, 1 ); + } + + private File createExpectedTempFile( File expectedFile ) + { + return new File( expectedFile.getParentFile(), expectedFile.getName() + ".tmp" ).getAbsoluteFile(); + } + + private void confirmSingleFailure( String path, String id ) + throws LayoutException + { + confirmFailures( path, new String[]{id} ); + } + + private void confirmFailures( String path, String[] ids ) + throws LayoutException + { + wagonMockControl.replay(); + + // Attempt the proxy fetch. + File downloadedFile = null; + try + { + downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, + managedDefaultRepository.toArtifactReference( path ) ); + fail( "Proxy should not have succeeded" ); + } + catch ( ProxyDownloadException e ) + { + assertEquals( ids.length, e.getFailures().size() ); + for ( String id : ids ) + { + assertTrue( e.getFailures().keySet().contains( id ) ); + } + } + + wagonMockControl.verify(); + + assertNotDownloaded( downloadedFile ); + } + + private void confirmSuccess( String path, File expectedFile, String basedir ) + throws Exception + { + File downloadedFile = performDownload( path ); + + File proxied1File = new File( basedir, path ); + assertFileEquals( expectedFile, downloadedFile, proxied1File ); + } + + private void confirmNotDownloadedNoError( String path ) + throws Exception + { + File downloadedFile = performDownload( path ); + + assertNotDownloaded( downloadedFile ); + } + + private File performDownload( String path ) + throws ProxyDownloadException, LayoutException + { + wagonMockControl.replay(); + + // Attempt the proxy fetch. + File downloadedFile = proxyHandler.fetchFromProxies( managedDefaultRepository, + managedDefaultRepository.toArtifactReference( path ) ); + + wagonMockControl.verify(); + return downloadedFile; + } + + private static TransferFailedException createTransferException() + { + return new TransferFailedException( "test download exception" ); + } + + private static ResourceDoesNotExistException createResourceNotFoundException() + { + return new ResourceDoesNotExistException( "test download not found" ); + } +} \ No newline at end of file diff --git a/archiva-1.0.x/archiva-base/archiva-proxy/src/test/resources/org/apache/maven/archiva/proxy/ErrorHandlingTest.xml b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/resources/org/apache/maven/archiva/proxy/ErrorHandlingTest.xml new file mode 100644 index 000000000..508b58bfc --- /dev/null +++ b/archiva-1.0.x/archiva-base/archiva-proxy/src/test/resources/org/apache/maven/archiva/proxy/ErrorHandlingTest.xml @@ -0,0 +1,118 @@ + + + + + + org.apache.maven.wagon.Wagon + test + org.apache.maven.archiva.proxy.WagonDelegate + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + mock + org.apache.maven.archiva.proxy.MockConfiguration + + + org.apache.maven.archiva.repository.RepositoryContentFactory + mocked + org.apache.maven.archiva.repository.RepositoryContentFactory + RepositoryContentRequest + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + mock + archivaConfiguration + + + + + org.apache.maven.archiva.proxy.RepositoryProxyConnectors + default + org.apache.maven.archiva.proxy.DefaultRepositoryProxyConnectors + DefaultRepositoryProxyConnectors + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + mock + archivaConfiguration + + + org.apache.maven.wagon.Wagon + wagons + + + org.apache.maven.archiva.repository.RepositoryContentFactory + mocked + + + org.apache.maven.archiva.repository.metadata.MetadataTools + + + org.apache.maven.archiva.policies.PreDownloadPolicy + preDownloadPolicies + + + org.apache.maven.archiva.policies.PostDownloadPolicy + postDownloadPolicies + + + org.apache.maven.archiva.policies.DownloadErrorPolicy + downloadErrorPolicies + + + org.apache.maven.archiva.policies.urlcache.UrlFailureCache + default + urlFailureCache + + + org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers + consumers + + + + + + org.codehaus.plexus.cache.Cache + url-failures-cache + org.codehaus.plexus.cache.ehcache.EhcacheCache + URL Failure Cache + + 600 + false + ${java.io.tmpdir}/archiva/urlcache + false + 1000 + LRU + url-failures-cache + false + + 2700 + + 1800 + + + + + org.codehaus.plexus.logging.LoggerManager + org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager + basic + + + \ No newline at end of file diff --git a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java index 68adb6c57..1318f5765 100644 --- a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java +++ b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java @@ -22,7 +22,8 @@ package org.apache.maven.archiva.web.action.admin.connectors.proxy; import com.opensymphony.xwork.Preparable; import org.apache.commons.lang.StringUtils; import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; -import org.apache.maven.archiva.policies.DownloadPolicy; +import org.apache.maven.archiva.policies.DownloadErrorPolicy; +import org.apache.maven.archiva.policies.Policy; import org.apache.maven.archiva.policies.PostDownloadPolicy; import org.apache.maven.archiva.policies.PreDownloadPolicy; @@ -54,6 +55,11 @@ public abstract class AbstractProxyConnectorFormAction */ private Map postDownloadPolicyMap; + /** + * @plexus.requirement role="org.apache.maven.archiva.policies.DownloadErrorPolicy" + */ + private Map downloadErrorPolicyMap; + /** * The list of network proxy ids that are available. */ @@ -72,7 +78,7 @@ public abstract class AbstractProxyConnectorFormAction /** * The map of policies that are available to be set. */ - private Map policyMap; + private Map policyMap; /** * The property key to add or remove. @@ -185,7 +191,7 @@ public abstract class AbstractProxyConnectorFormAction return pattern; } - public Map getPolicyMap() + public Map getPolicyMap() { return policyMap; } @@ -318,7 +324,7 @@ public abstract class AbstractProxyConnectorFormAction this.pattern = pattern; } - public void setPolicyMap( Map policyMap ) + public void setPolicyMap( Map policyMap ) { this.policyMap = policyMap; } @@ -363,12 +369,13 @@ public abstract class AbstractProxyConnectorFormAction return options; } - protected Map createPolicyMap() + protected Map createPolicyMap() { - Map policyMap = new HashMap(); + Map policyMap = new HashMap(); policyMap.putAll( preDownloadPolicyMap ); policyMap.putAll( postDownloadPolicyMap ); + policyMap.putAll( downloadErrorPolicyMap ); return policyMap; } @@ -387,10 +394,10 @@ public abstract class AbstractProxyConnectorFormAction else { // Validate / Fix policy settings arriving from browser. - for ( Map.Entry entry : getPolicyMap().entrySet() ) + for ( Map.Entry entry : getPolicyMap().entrySet() ) { - String policyId = (String) entry.getKey(); - DownloadPolicy policy = (DownloadPolicy) entry.getValue(); + String policyId = entry.getKey(); + Policy policy = entry.getValue(); List options = policy.getOptions(); if ( !connector.getPolicies().containsKey( policyId ) ) diff --git a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java index 027f58f54..34ccbbf78 100644 --- a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java +++ b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java @@ -19,23 +19,11 @@ package org.apache.maven.archiva.web.repository; * under the License. */ -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; - import org.apache.maven.archiva.common.utils.PathUtil; import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.VersionedReference; -import org.apache.maven.archiva.proxy.ProxyException; +import org.apache.maven.archiva.policies.ProxyDownloadException; import org.apache.maven.archiva.proxy.RepositoryProxyConnectors; import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.RepositoryContentFactory; @@ -61,6 +49,17 @@ import org.codehaus.plexus.webdav.DavServerListener; import org.codehaus.plexus.webdav.servlet.DavServerRequest; import org.codehaus.plexus.webdav.util.WebdavMethodUtil; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + /** * ProxiedDavServer * @@ -365,7 +364,7 @@ public class ProxiedDavServer { /* eat it */ } - catch ( ProxyException e ) + catch ( ProxyDownloadException e ) { throw new ServletException( "Unable to fetch artifact resource.", e ); } @@ -392,10 +391,6 @@ public class ProxiedDavServer { /* eat it */ } - catch ( ProxyException e ) - { - throw new ServletException( "Unable to fetch versioned metadata resource.", e ); - } try { @@ -410,10 +405,6 @@ public class ProxiedDavServer { /* eat it */ } - catch ( ProxyException e ) - { - throw new ServletException( "Unable to fetch project metadata resource.", e ); - } return false; } @@ -429,7 +420,7 @@ public class ProxiedDavServer * artifact. */ protected void applyServerSideRelocation( ArtifactReference artifact ) - throws ProxyException + throws ProxyDownloadException { if ( "pom".equals( artifact.getType() ) ) { diff --git a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf index 52acf5881..6e04cee2d 100644 --- a/archiva-1.0.x/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf +++ b/archiva-1.0.x/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf @@ -42,7 +42,7 @@ ${policy.key}: + theme="simple">${policy.value.name}: diff --git a/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java b/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java index b4747e393..213ce9fbb 100644 --- a/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java +++ b/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java @@ -28,6 +28,8 @@ import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.ChecksumPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsDownloadPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy; import org.apache.maven.archiva.policies.ReleasesPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.web.action.AbstractWebworkTestCase; @@ -36,6 +38,7 @@ import org.codehaus.plexus.registry.RegistryException; import org.easymock.MockControl; import java.util.List; +import java.util.Map; /** * AddProxyConnectorActionTest @@ -390,10 +393,13 @@ public class AddProxyConnectorActionTest connector.setTargetRepoId( "central" ); // TODO: Set these options programatically via list of available policies. - connector.getPolicies().put( "releases", new ReleasesPolicy().getDefaultOption() ); - connector.getPolicies().put( "snapshots", new SnapshotsPolicy().getDefaultOption() ); - connector.getPolicies().put( "checksum", new ChecksumPolicy().getDefaultOption() ); - connector.getPolicies().put( "cache-failures", new CachedFailuresPolicy().getDefaultOption() ); + Map policies = connector.getPolicies(); + policies.put( "releases", new ReleasesPolicy().getDefaultOption() ); + policies.put( "snapshots", new SnapshotsPolicy().getDefaultOption() ); + policies.put( "checksum", new ChecksumPolicy().getDefaultOption() ); + policies.put( "cache-failures", new CachedFailuresPolicy().getDefaultOption() ); + policies.put( "propagate-errors", new PropagateErrorsDownloadPolicy().getDefaultOption() ); + policies.put( "propagate-errors-on-update", new PropagateErrorsOnUpdateDownloadPolicy().getDefaultOption() ); } @Override diff --git a/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java b/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java index 626cf5654..31364f4b8 100644 --- a/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java +++ b/archiva-1.0.x/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java @@ -28,6 +28,8 @@ import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.ChecksumPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsDownloadPolicy; +import org.apache.maven.archiva.policies.PropagateErrorsOnUpdateDownloadPolicy; import org.apache.maven.archiva.policies.ReleasesPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.web.action.AbstractWebworkTestCase; @@ -36,6 +38,7 @@ import org.codehaus.plexus.registry.RegistryException; import org.easymock.MockControl; import java.util.List; +import java.util.Map; /** * EditProxyConnectorActionTest @@ -395,10 +398,13 @@ public class EditProxyConnectorActionTest connector.setTargetRepoId( TEST_TARGET_ID ); // TODO: Set these options programatically via list of available policies. - connector.getPolicies().put( "releases", new ReleasesPolicy().getDefaultOption() ); - connector.getPolicies().put( "snapshots", new SnapshotsPolicy().getDefaultOption() ); - connector.getPolicies().put( "checksum", new ChecksumPolicy().getDefaultOption() ); - connector.getPolicies().put( "cache-failures", new CachedFailuresPolicy().getDefaultOption() ); + Map policies = connector.getPolicies(); + policies.put( "releases", new ReleasesPolicy().getDefaultOption() ); + policies.put( "snapshots", new SnapshotsPolicy().getDefaultOption() ); + policies.put( "checksum", new ChecksumPolicy().getDefaultOption() ); + policies.put( "cache-failures", new CachedFailuresPolicy().getDefaultOption() ); + policies.put( "propagate-errors", new PropagateErrorsDownloadPolicy().getDefaultOption() ); + policies.put( "propagate-errors-on-update", new PropagateErrorsOnUpdateDownloadPolicy().getDefaultOption() ); config.addProxyConnector( connector );