Browse Source

[MRM-159] should not respond with a 404 if proxying a file results in a remote error

Merged from: r644205, 644275


git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@644276 13f79535-47bb-0310-9956-ffa450edef68
tags/archiva-r676265
Brett Porter 16 years ago
parent
commit
28e54029c0
25 changed files with 1365 additions and 141 deletions
  1. 8
    4
      archiva-docs/src/site/apt/adminguide/proxy-connectors.apt
  2. 4
    4
      archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java
  3. 14
    0
      archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo
  4. 5
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java
  5. 5
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java
  6. 50
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadErrorPolicy.java
  7. 1
    21
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java
  8. 55
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/Policy.java
  9. 0
    17
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java
  10. 0
    17
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java
  11. 118
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsDownloadPolicy.java
  12. 105
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java
  13. 66
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ProxyDownloadException.java
  14. 5
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java
  15. 5
    0
      archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java
  16. 107
    37
      archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java
  17. 7
    10
      archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java
  18. 25
    2
      archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java
  19. 627
    0
      archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java
  20. 118
    0
      archiva-modules/archiva-base/archiva-proxy/src/test/resources/org/apache/maven/archiva/proxy/ErrorHandlingTest.xml
  21. 16
    9
      archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java
  22. 3
    11
      archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java
  23. 1
    1
      archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf
  24. 10
    4
      archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java
  25. 10
    4
      archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java

+ 8
- 4
archiva-docs/src/site/apt/adminguide/proxy-connectors.apt View File

@@ -29,14 +29,18 @@ Understanding Proxy Connector Configuration of Apache Archiva

By default, Archiva comes with the following policies:

* <<<releases>>> - how to behave for released artifact metadata (those not carrying a <<<SNAPSHOT>>> version). This can be set to <<<always>>> (default), <<<hourly>>>, <<<daily>>>, <<<once>>> and <<<never>>>.
* <<<Releases>>> - how to behave for released artifact metadata (those not carrying a <<<SNAPSHOT>>> version). This can be set to <<<always>>> (default), <<<hourly>>>, <<<daily>>>, <<<once>>> and <<<never>>>.

* <<<snapshots>>> - how to behave for snapshot artifact metadata (those carrying a <<<SNAPSHOT>>> version). This can be set to <<<always>>> (default), <<<hourly>>>, <<<daily>>>, <<<once>>> and <<<never>>>.
* <<<Snapshots>>> - how to behave for snapshot artifact metadata (those carrying a <<<SNAPSHOT>>> version). This can be set to <<<always>>> (default), <<<hourly>>>, <<<daily>>>, <<<once>>> and <<<never>>>.

* <<<checksum>>> - how to handle incorrect checksums when downloading an artifact from the remote repository (ie, the checksum of the artifact does not match the corresponding detached checksum file).
* <<<Checksum>>> - how to handle incorrect checksums when downloading an artifact from the remote repository (ie, the checksum of the artifact does not match the corresponding detached checksum file).
The options are to fail the request for the remote artifact, fix the checksum on the fly (default), or simply ignore the incorrect checksum

* <<<cache-failures>>> - whether failures retrieving the remote artifact should be cached (to save network bandwidth for missing or bad artifacts), or uncached (default).
* <<<Cache failures>>> - whether failures retrieving the remote artifact should be cached (to save network bandwidth for missing or bad artifacts), or uncached (default).

* <<<Return error when>>> - if a remote proxy causes an error, this option determines whether an existing artifact should be returned (error when <<<artifact not already present>>>), or the error passed on regardless (<<<always>>>).

* <<<On remote error>>> - if a remote error is encountered, <<<stop>>> causes the error to be returned immediately, <<<queue error>>> will return all errors after checking for other successful remote repositories first, and <<<ignore>>> will disregard ay errors.

[]


+ 4
- 4
archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/maven/archiva/configuration/DefaultArchivaConfiguration.java View File

@@ -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;
@@ -280,7 +280,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 ) )
{
@@ -323,7 +323,7 @@ public class DefaultArchivaConfiguration
return config;
}

private DownloadPolicy findPolicy( String policyId )
private Policy findPolicy( String policyId )
{
if ( MapUtils.isEmpty( prePolicies ) )
{
@@ -337,7 +337,7 @@ public class DefaultArchivaConfiguration
return null;
}

DownloadPolicy policy;
Policy policy;

policy = prePolicies.get( policyId );
if ( policy != null )

+ 14
- 0
archiva-modules/archiva-base/archiva-configuration/src/main/mdo/configuration.mdo View File

@@ -651,6 +651,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}

+ 5
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/CachedFailuresPolicy.java View File

@@ -108,6 +108,11 @@ public class CachedFailuresPolicy
return "cache-failures";
}

public String getName()
{
return "Cache failures";
}

public List<String> getOptions()
{
return options;

+ 5
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ChecksumPolicy.java View File

@@ -157,6 +157,11 @@ public class ChecksumPolicy
return "checksum";
}

public String getName()
{
return "Checksum";
}

public List<String> getOptions()
{
return options;

+ 50
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadErrorPolicy.java View File

@@ -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 <a href="mailto:brett@apache.org">Brett Porter</a>
* @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<String, Exception> previousExceptions )
throws PolicyConfigurationException;
}

+ 1
- 21
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/DownloadPolicy.java View File

@@ -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<String> 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.

+ 55
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/Policy.java View File

@@ -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<String> 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();
}

+ 0
- 17
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PostDownloadPolicy.java View File

@@ -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;
}

+ 0
- 17
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PreDownloadPolicy.java View File

@@ -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;
}

+ 118
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsDownloadPolicy.java View File

@@ -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<String> options = new ArrayList<String>();

public PropagateErrorsDownloadPolicy()
{
options.add( STOP );
options.add( QUEUE );
options.add( IGNORE );
}

public boolean applyPolicy( String policySetting, Properties request, File localFile, Exception exception,
Map<String, Exception> 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<String> getOptions()
{
return options;
}
}

+ 105
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/PropagateErrorsOnUpdateDownloadPolicy.java View File

@@ -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<String> options = new ArrayList<String>();

public PropagateErrorsOnUpdateDownloadPolicy()
{
options.add( ALWAYS );
options.add( NOT_PRESENT );
}

public boolean applyPolicy( String policySetting, Properties request, File localFile, Exception exception,
Map<String,Exception> 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<String> getOptions()
{
return options;
}
}

+ 66
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ProxyDownloadException.java View File

@@ -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<String, Exception> 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<String, Exception> failures )
{
super( constructMessage( message, failures ) );

this.failures = failures;
}

private static String constructMessage( String message, Map<String, Exception> failures )
{
String msg = message + ":";
for ( Map.Entry<String, Exception> entry : failures.entrySet() )
{
msg += "\n\t" + entry.getKey() + ": " + entry.getValue().getMessage();
}
return msg;
}

public Map<String,Exception> getFailures()
{
return failures;
}
}

+ 5
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/ReleasesPolicy.java View File

@@ -55,4 +55,9 @@ public class ReleasesPolicy
{
return "releases";
}

public String getName()
{
return "Releases";
}
}

+ 5
- 0
archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/maven/archiva/policies/SnapshotsPolicy.java View File

@@ -55,4 +55,9 @@ public class SnapshotsPolicy
{
return "snapshots";
}

public String getName()
{
return "Snapshots";
}
}

+ 107
- 37
archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/DefaultRepositoryProxyConnectors.java View File

@@ -19,16 +19,6 @@ package org.apache.maven.archiva.proxy;
* under the License.
*/

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
@@ -41,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;
@@ -73,11 +65,23 @@ import org.codehaus.plexus.util.SelectorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
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;
import java.util.Properties;

/**
* DefaultRepositoryProxyConnectors
*
* @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
* @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
@@ -116,7 +120,12 @@ public class DefaultRepositoryProxyConnectors
private Map<String, PostDownloadPolicy> postDownloadPolicies;

/**
* @plexus.requirement
* @plexus.requirement role="org.apache.maven.archiva.policies.DownloadErrorPolicy"
*/
private Map<String, DownloadErrorPolicy> downloadErrorPolicies;

/**
* @plexus.requirement role-hint="default"
*/
private UrlFailureCache urlFailureCache;

@@ -136,26 +145,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<ProxyConnector> connectors = getProxyConnectors( repository );
Map<String, Exception> previousExceptions = new LinkedHashMap<String, Exception>();
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 ) )
{
@@ -175,12 +189,17 @@ public class DefaultRepositoryProxyConnectors
}
catch ( ProxyException e )
{
log.warn( "Transfer error from repository \"" + targetRepository.getRepository().getId() +
"\" for artifact " + Keys.toKey( artifact ) + ", continuing to next repository. Error message: " +
e.getMessage() );
log.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 );
}

log.debug( "Exhausted all target repositories, artifact " + Keys.toKey( artifact ) + " not found." );

return null;
@@ -471,10 +490,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 )
@@ -696,8 +715,8 @@ public class DefaultRepositoryProxyConnectors
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() )
@@ -711,13 +730,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
{
@@ -742,10 +763,10 @@ public class DefaultRepositoryProxyConnectors
{
for ( Entry<String, ? extends DownloadPolicy> 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 );

log.debug( "Applying [" + key + "] policy with [" + setting + "]" );
try
@@ -759,6 +780,56 @@ public class DefaultRepositoryProxyConnectors
}
}

private void validatePolicies( Map<String, DownloadErrorPolicy> policies, Map<String, String> settings,
Properties request, ArtifactReference artifact, RemoteRepositoryContent content,
File localFile, ProxyException exception, Map<String, Exception> previousExceptions )
throws ProxyDownloadException
{
boolean process = true;
for ( Entry<String, ? extends DownloadErrorPolicy> entry : policies.entrySet() )
{
String key = entry.getKey();
DownloadErrorPolicy policy = entry.getValue();
String defaultSetting = policy.getDefaultOption();
String setting = StringUtils.defaultString( settings.get( key ), defaultSetting );

log.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 )
{
log.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() );
}

log.warn( "Transfer error from repository \"" + content.getRepository().getId() + "\" for artifact " +
Keys.toKey( artifact ) + ", continuing to next repository. Error message: " + exception.getMessage() );
log.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.
@@ -802,7 +873,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;

@@ -851,15 +923,13 @@ public class DefaultRepositoryProxyConnectors
catch ( ConnectionException e )
{
log.warn(
"Could not connect to " + remoteRepository.getRepository().getName() + ": "
+ e.getMessage() );
"Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() );
connected = false;
}
catch ( AuthenticationException e )
{
log.warn(
"Could not connect to " + remoteRepository.getRepository().getName() + ": "
+ e.getMessage() );
"Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() );
connected = false;
}

@@ -911,10 +981,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();
}

+ 7
- 10
archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/maven/archiva/proxy/RepositoryProxyConnectors.java View File

@@ -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.

+ 25
- 2
archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/AbstractProxyTestCase.java View File

@@ -37,6 +37,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.repository.ManagedRepositoryContent;
@@ -295,8 +297,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 );
@@ -305,6 +322,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 );
@@ -318,6 +337,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 )

+ 627
- 0
archiva-modules/archiva-base/archiva-proxy/src/test/java/org/apache/maven/archiva/proxy/ErrorHandlingTest.java View File

@@ -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" );
}
}

+ 118
- 0
archiva-modules/archiva-base/archiva-proxy/src/test/resources/org/apache/maven/archiva/proxy/ErrorHandlingTest.xml View File

@@ -0,0 +1,118 @@
<!--
~ 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.
-->

<component-set>
<components>
<component>
<role>org.apache.maven.wagon.Wagon</role>
<role-hint>test</role-hint>
<implementation>org.apache.maven.archiva.proxy.WagonDelegate</implementation>
</component>
<component>
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
<role-hint>mock</role-hint>
<implementation>org.apache.maven.archiva.proxy.MockConfiguration</implementation>
</component>
<component>
<role>org.apache.maven.archiva.repository.RepositoryContentFactory</role>
<role-hint>mocked</role-hint>
<implementation>org.apache.maven.archiva.repository.RepositoryContentFactory</implementation>
<description>RepositoryContentRequest</description>
<requirements>
<requirement>
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
<role-hint>mock</role-hint>
<field-name>archivaConfiguration</field-name>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.archiva.proxy.RepositoryProxyConnectors</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.archiva.proxy.DefaultRepositoryProxyConnectors</implementation>
<description>DefaultRepositoryProxyConnectors</description>
<requirements>
<requirement>
<role>org.apache.maven.archiva.configuration.ArchivaConfiguration</role>
<role-hint>mock</role-hint>
<field-name>archivaConfiguration</field-name>
</requirement>
<requirement>
<role>org.apache.maven.wagon.Wagon</role>
<field-name>wagons</field-name>
</requirement>
<requirement>
<role>org.apache.maven.archiva.repository.RepositoryContentFactory</role>
<role-hint>mocked</role-hint>
</requirement>
<requirement>
<role>org.apache.maven.archiva.repository.metadata.MetadataTools</role>
</requirement>
<requirement>
<role>org.apache.maven.archiva.policies.PreDownloadPolicy</role>
<field-name>preDownloadPolicies</field-name>
</requirement>
<requirement>
<role>org.apache.maven.archiva.policies.PostDownloadPolicy</role>
<field-name>postDownloadPolicies</field-name>
</requirement>
<requirement>
<role>org.apache.maven.archiva.policies.DownloadErrorPolicy</role>
<field-name>downloadErrorPolicies</field-name>
</requirement>
<requirement>
<role>org.apache.maven.archiva.policies.urlcache.UrlFailureCache</role>
<role-hint>default</role-hint>
<field-name>urlFailureCache</field-name>
</requirement>
<requirement>
<role>org.apache.maven.archiva.repository.scanner.RepositoryContentConsumers</role>
<field-name>consumers</field-name>
</requirement>
</requirements>
</component>
<component>
<role>org.codehaus.plexus.cache.Cache</role>
<role-hint>url-failures-cache</role-hint>
<implementation>org.codehaus.plexus.cache.ehcache.EhcacheCache</implementation>
<description>URL Failure Cache</description>
<configuration>
<disk-expiry-thread-interval-seconds>600</disk-expiry-thread-interval-seconds>
<disk-persistent>false</disk-persistent> <!--disabling disk persistence for unit testing. -->
<disk-store-path>${java.io.tmpdir}/archiva/urlcache</disk-store-path>
<eternal>false</eternal>
<max-elements-in-memory>1000</max-elements-in-memory>
<memory-eviction-policy>LRU</memory-eviction-policy>
<name>url-failures-cache</name>
<overflow-to-disk>false</overflow-to-disk>
<!-- 45 minutes = 2700 seconds -->
<time-to-idle-seconds>2700</time-to-idle-seconds>
<!-- 30 minutes = 1800 seconds -->
<time-to-live-seconds>1800</time-to-live-seconds>
</configuration>
</component>
<component>
<role>org.codehaus.plexus.logging.LoggerManager</role>
<implementation>org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager</implementation>
<lifecycle-handler>basic</lifecycle-handler>
</component>
</components>
</component-set>

+ 16
- 9
archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AbstractProxyConnectorFormAction.java View File

@@ -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<String, PostDownloadPolicy> postDownloadPolicyMap;

/**
* @plexus.requirement role="org.apache.maven.archiva.policies.DownloadErrorPolicy"
*/
private Map<String, DownloadErrorPolicy> 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<String, DownloadPolicy> policyMap;
private Map<String, Policy> policyMap;

/**
* The property key to add or remove.
@@ -185,7 +191,7 @@ public abstract class AbstractProxyConnectorFormAction
return pattern;
}

public Map<String, DownloadPolicy> getPolicyMap()
public Map<String, Policy> getPolicyMap()
{
return policyMap;
}
@@ -318,7 +324,7 @@ public abstract class AbstractProxyConnectorFormAction
this.pattern = pattern;
}

public void setPolicyMap( Map<String, DownloadPolicy> policyMap )
public void setPolicyMap( Map<String, Policy> policyMap )
{
this.policyMap = policyMap;
}
@@ -363,12 +369,13 @@ public abstract class AbstractProxyConnectorFormAction
return options;
}

protected Map<String, DownloadPolicy> createPolicyMap()
protected Map<String, Policy> createPolicyMap()
{
Map<String, DownloadPolicy> policyMap = new HashMap<String, DownloadPolicy>();
Map<String, Policy> policyMap = new HashMap<String, Policy>();

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<String, DownloadPolicy> entry : getPolicyMap().entrySet() )
for ( Map.Entry<String, Policy> entry : getPolicyMap().entrySet() )
{
String policyId = (String) entry.getKey();
DownloadPolicy policy = (DownloadPolicy) entry.getValue();
String policyId = entry.getKey();
Policy policy = entry.getValue();
List<String> options = policy.getOptions();

if ( !connector.getPolicies().containsKey( policyId ) )

+ 3
- 11
archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/repository/ProxiedDavServer.java View File

@@ -23,7 +23,7 @@ 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;
@@ -364,7 +364,7 @@ public class ProxiedDavServer
{
/* eat it */
}
catch ( ProxyException e )
catch ( ProxyDownloadException e )
{
throw new ServletException( "Unable to fetch artifact resource.", e );
}
@@ -391,10 +391,6 @@ public class ProxiedDavServer
{
/* eat it */
}
catch ( ProxyException e )
{
throw new ServletException( "Unable to fetch versioned metadata resource.", e );
}

try
{
@@ -409,10 +405,6 @@ public class ProxiedDavServer
{
/* eat it */
}
catch ( ProxyException e )
{
throw new ServletException( "Unable to fetch project metadata resource.", e );
}

return false;
}
@@ -428,7 +420,7 @@ public class ProxiedDavServer
* artifact.
*/
protected void applyServerSideRelocation( ArtifactReference artifact )
throws ProxyException
throws ProxyDownloadException
{
if ( "pom".equals( artifact.getType() ) )
{

+ 1
- 1
archiva-modules/archiva-web/archiva-webapp/src/main/webapp/WEB-INF/jsp/admin/include/proxyConnectorForm.jspf View File

@@ -42,7 +42,7 @@
<tr>
<td>
<ww:label for="policy_${policy.key}" required="true"
theme="simple">${policy.key}:
theme="simple">${policy.value.name}:
</ww:label>
</td>
<td>

+ 10
- 4
archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/AddProxyConnectorActionTest.java View File

@@ -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<String, String> 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

+ 10
- 4
archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/action/admin/connectors/proxy/EditProxyConnectorActionTest.java View File

@@ -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<String, String> 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 );


Loading…
Cancel
Save