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



By default, Archiva comes with the following policies: 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 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

import org.apache.maven.archiva.policies.AbstractUpdatePolicy; import org.apache.maven.archiva.policies.AbstractUpdatePolicy;
import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.CachedFailuresPolicy;
import org.apache.maven.archiva.policies.ChecksumPolicy; 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.PostDownloadPolicy;
import org.apache.maven.archiva.policies.PreDownloadPolicy; import org.apache.maven.archiva.policies.PreDownloadPolicy;
import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator; import org.codehaus.plexus.evaluator.DefaultExpressionEvaluator;
// Validate existance of policy key. // Validate existance of policy key.
if ( policyExists( policyId ) ) if ( policyExists( policyId ) )
{ {
DownloadPolicy policy = findPolicy( policyId );
Policy policy = findPolicy( policyId );
// Does option exist? // Does option exist?
if ( !policy.getOptions().contains( setting ) ) if ( !policy.getOptions().contains( setting ) )
{ {
return config; return config;
} }


private DownloadPolicy findPolicy( String policyId )
private Policy findPolicy( String policyId )
{ {
if ( MapUtils.isEmpty( prePolicies ) ) if ( MapUtils.isEmpty( prePolicies ) )
{ {
return null; return null;
} }


DownloadPolicy policy;
Policy policy;


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

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

*/ */
public static final int UNORDERED = 0; 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. * The policy key {@link #getPolicies()} for snapshot handling.
* See {@link org.apache.maven.archiva.policies.SnapshotsPolicy} * 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

return "cache-failures"; return "cache-failures";
} }


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

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

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

return "checksum"; return "checksum";
} }


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

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

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

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

*/ */


import java.io.File; import java.io.File;
import java.util.List;
import java.util.Properties; import java.util.Properties;


/** /**
* @version $Id$ * @version $Id$
*/ */
public interface DownloadPolicy 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. * Apply the download policy.

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

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

* under the License. * under the License.
*/ */


import java.io.File;
import java.util.Properties;

/** /**
* Policy to apply after the download has completed, but before the * Policy to apply after the download has completed, but before the
* resource is made available to the calling client. * resource is made available to the calling client.
public interface PostDownloadPolicy public interface PostDownloadPolicy
extends DownloadPolicy 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

*/ */




import java.io.File;
import java.util.Properties;

/** /**
* Policy to apply before the download is attempted. * Policy to apply before the download is attempted.
* *
*/ */
public interface PreDownloadPolicy extends DownloadPolicy 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

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

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

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

{ {
return "releases"; 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

{ {
return "snapshots"; 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

* under the License. * 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.collections.CollectionUtils;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.model.RepositoryURL; import org.apache.maven.archiva.model.RepositoryURL;
import org.apache.maven.archiva.model.VersionedReference; 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.DownloadPolicy;
import org.apache.maven.archiva.policies.PolicyConfigurationException; import org.apache.maven.archiva.policies.PolicyConfigurationException;
import org.apache.maven.archiva.policies.PolicyViolationException; import org.apache.maven.archiva.policies.PolicyViolationException;
import org.apache.maven.archiva.policies.PostDownloadPolicy; import org.apache.maven.archiva.policies.PostDownloadPolicy;
import org.apache.maven.archiva.policies.PreDownloadPolicy; 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.policies.urlcache.UrlFailureCache;
import org.apache.maven.archiva.repository.ContentNotFoundException; import org.apache.maven.archiva.repository.ContentNotFoundException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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 * DefaultRepositoryProxyConnectors
* *
* @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a> * @author <a href="mailto:joakime@apache.org">Joakim Erdfelt</a>
* @version $Id$ * @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" * @plexus.component role-hint="default"
*/ */
public class DefaultRepositoryProxyConnectors public class DefaultRepositoryProxyConnectors
private Map<String, PostDownloadPolicy> postDownloadPolicies; 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; private UrlFailureCache urlFailureCache;


* @param artifact the artifact reference to fetch. * @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 * @return the local file in the managed repository that was fetched, or null if the artifact was not (or
* could not be) fetched. * 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 ) public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
throws ProxyDownloadException
{ {
File localFile = toLocalFile( repository, artifact ); File localFile = toLocalFile( repository, artifact );


Properties requestProperties = new Properties(); Properties requestProperties = new Properties();
requestProperties.setProperty( "filetype", "artifact" ); requestProperties.setProperty( "filetype", "artifact" );
requestProperties.setProperty( "version", artifact.getVersion() ); requestProperties.setProperty( "version", artifact.getVersion() );
requestProperties.setProperty( "managedRepositoryId", repository.getId() );


List<ProxyConnector> connectors = getProxyConnectors( repository ); List<ProxyConnector> connectors = getProxyConnectors( repository );
Map<String, Exception> previousExceptions = new LinkedHashMap<String, Exception>();
for ( ProxyConnector connector : connectors ) for ( ProxyConnector connector : connectors )
{ {
RemoteRepositoryContent targetRepository = connector.getTargetRepository(); RemoteRepositoryContent targetRepository = connector.getTargetRepository();
requestProperties.setProperty( "remoteRepositoryId", targetRepository.getId() );

String targetPath = targetRepository.toPath( artifact ); String targetPath = targetRepository.toPath( artifact );


try try
{ {
File downloadedFile = transferFile( connector, targetRepository, targetPath, localFile,
requestProperties );
File downloadedFile =
transferFile( connector, targetRepository, targetPath, localFile, requestProperties );


if ( fileExists( downloadedFile ) ) if ( fileExists( downloadedFile ) )
{ {
} }
catch ( ProxyException e ) 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." ); log.debug( "Exhausted all target repositories, artifact " + Keys.toKey( artifact ) + " not found." );


return null; return null;
* @param localFile the local file to place the downloaded resource into * @param localFile the local file to place the downloaded resource into
* @param requestProperties the request properties to utilize for policy handling. * @param requestProperties the request properties to utilize for policy handling.
* @return the local file that was downloaded, or null if not downloaded. * @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, * @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. * 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, private File transferFile( ProxyConnector connector, RemoteRepositoryContent remoteRepository, String remotePath,
File localFile, Properties requestProperties ) File localFile, Properties requestProperties )
success = wagon.getIfNewer( remotePath, temp, localFile.lastModified() ); success = wagon.getIfNewer( remotePath, temp, localFile.lastModified() );
if ( !success ) 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() ) if ( temp.exists() )
} }
catch ( ResourceDoesNotExistException e ) 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 ) 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 finally
{ {
{ {
for ( Entry<String, ? extends DownloadPolicy> entry : policies.entrySet() ) for ( Entry<String, ? extends DownloadPolicy> entry : policies.entrySet() )
{ {
String key = (String) entry.getKey();
String key = entry.getKey();
DownloadPolicy policy = entry.getValue(); DownloadPolicy policy = entry.getValue();
String defaultSetting = policy.getDefaultOption(); 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 + "]" ); log.debug( "Applying [" + key + "] policy with [" + setting + "]" );
try try
} }
} }


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 * Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles
* its downloaded files. * its downloaded files.
* @param remoteRepository the remote repository to connect to. * @param remoteRepository the remote repository to connect to.
* @return true if the connection was successful. false if not connected. * @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; boolean connected = false;


catch ( ConnectionException e ) catch ( ConnectionException e )
{ {
log.warn( log.warn(
"Could not connect to " + remoteRepository.getRepository().getName() + ": "
+ e.getMessage() );
"Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() );
connected = false; connected = false;
} }
catch ( AuthenticationException e ) catch ( AuthenticationException e )
{ {
log.warn( log.warn(
"Could not connect to " + remoteRepository.getRepository().getName() + ": "
+ e.getMessage() );
"Could not connect to " + remoteRepository.getRepository().getName() + ": " + e.getMessage() );
connected = false; connected = false;
} }




public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) 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(); initConnectorsAndNetworkProxies();
} }

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

import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.model.VersionedReference; import org.apache.maven.archiva.model.VersionedReference;
import org.apache.maven.archiva.policies.ProxyDownloadException;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;


import java.io.File; import java.io.File;
* @param repository the source repository to use. (must be a managed repository) * @param repository the source repository to use. (must be a managed repository)
* @param artifact the artifact to fetch. * @param artifact the artifact to fetch.
* @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. * @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 ) public File fetchFromProxies( ManagedRepositoryContent repository, ArtifactReference artifact )
throws ProxyException;
throws ProxyDownloadException;
/** /**
* Performs the metadata fetch operation against the target repositories * Performs the metadata fetch operation against the target repositories
* of the provided source repository. * of the provided source repository.
* @param repository the source repository to use. (must be a managed repository) * @param repository the source repository to use. (must be a managed repository)
* @param metadata the metadata to fetch. * @param metadata the metadata to fetch.
* @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. * @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 * Performs the metadata fetch operation against the target repositories
* of the provided source repository. * of the provided source repository.
* @param repository the source repository to use. (must be a managed repository) * @param repository the source repository to use. (must be a managed repository)
* @param metadata the metadata to fetch. * @param metadata the metadata to fetch.
* @return true if the fetch operation succeeded in obtaining content, false if no content was obtained. * @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. * 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

import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.CachedFailuresPolicy;
import org.apache.maven.archiva.policies.ChecksumPolicy; 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.ReleasesPolicy;
import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
SnapshotsPolicy.ALWAYS, CachedFailuresPolicy.NO ); 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(); ProxyConnectorConfiguration connectorConfig = new ProxyConnectorConfiguration();
connectorConfig.setSourceRepoId( sourceRepoId ); connectorConfig.setSourceRepoId( sourceRepoId );
connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_RELEASES, releasePolicy ); connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_RELEASES, releasePolicy );
connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_SNAPSHOTS, snapshotPolicy ); connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_SNAPSHOTS, snapshotPolicy );
connectorConfig.addPolicy( ProxyConnectorConfiguration.POLICY_CACHE_FAILURES, cacheFailuresPolicy ); 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(); int count = config.getConfiguration().getProxyConnectors().size();
config.getConfiguration().addProxyConnector( connectorConfig ); config.getConfiguration().addProxyConnector( connectorConfig );
config.triggerChange( prefix + ".policies.checksum", connectorConfig.getPolicy( "checksum", "" ) ); config.triggerChange( prefix + ".policies.checksum", connectorConfig.getPolicy( "checksum", "" ) );
config.triggerChange( prefix + ".policies.snapshots", connectorConfig.getPolicy( "snapshots", "" ) ); config.triggerChange( prefix + ".policies.snapshots", connectorConfig.getPolicy( "snapshots", "" ) );
config.triggerChange( prefix + ".policies.cache-failures", connectorConfig.getPolicy( "cache-failures", "" ) ); 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 ) 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

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

<!--
~ 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

import com.opensymphony.xwork.Preparable; import com.opensymphony.xwork.Preparable;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.configuration.ProxyConnectorConfiguration; 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.PostDownloadPolicy;
import org.apache.maven.archiva.policies.PreDownloadPolicy; import org.apache.maven.archiva.policies.PreDownloadPolicy;


*/ */
private Map<String, PostDownloadPolicy> postDownloadPolicyMap; 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. * The list of network proxy ids that are available.
*/ */
/** /**
* The map of policies that are available to be set. * 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. * The property key to add or remove.
return pattern; return pattern;
} }


public Map<String, DownloadPolicy> getPolicyMap()
public Map<String, Policy> getPolicyMap()
{ {
return policyMap; return policyMap;
} }
this.pattern = pattern; this.pattern = pattern;
} }


public void setPolicyMap( Map<String, DownloadPolicy> policyMap )
public void setPolicyMap( Map<String, Policy> policyMap )
{ {
this.policyMap = policyMap; this.policyMap = policyMap;
} }
return options; 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( preDownloadPolicyMap );
policyMap.putAll( postDownloadPolicyMap ); policyMap.putAll( postDownloadPolicyMap );
policyMap.putAll( downloadErrorPolicyMap );


return policyMap; return policyMap;
} }
else else
{ {
// Validate / Fix policy settings arriving from browser. // 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(); List<String> options = policy.getOptions();


if ( !connector.getPolicies().containsKey( policyId ) ) 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

import org.apache.maven.archiva.model.ArtifactReference; import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference; import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.model.VersionedReference; 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.proxy.RepositoryProxyConnectors;
import org.apache.maven.archiva.repository.ManagedRepositoryContent; import org.apache.maven.archiva.repository.ManagedRepositoryContent;
import org.apache.maven.archiva.repository.RepositoryContentFactory; import org.apache.maven.archiva.repository.RepositoryContentFactory;
{ {
/* eat it */ /* eat it */
} }
catch ( ProxyException e )
catch ( ProxyDownloadException e )
{ {
throw new ServletException( "Unable to fetch artifact resource.", e ); throw new ServletException( "Unable to fetch artifact resource.", e );
} }
{ {
/* eat it */ /* eat it */
} }
catch ( ProxyException e )
{
throw new ServletException( "Unable to fetch versioned metadata resource.", e );
}


try try
{ {
{ {
/* eat it */ /* eat it */
} }
catch ( ProxyException e )
{
throw new ServletException( "Unable to fetch project metadata resource.", e );
}


return false; return false;
} }
* artifact. * artifact.
*/ */
protected void applyServerSideRelocation( ArtifactReference artifact ) protected void applyServerSideRelocation( ArtifactReference artifact )
throws ProxyException
throws ProxyDownloadException
{ {
if ( "pom".equals( artifact.getType() ) ) 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

<tr> <tr>
<td> <td>
<ww:label for="policy_${policy.key}" required="true" <ww:label for="policy_${policy.key}" required="true"
theme="simple">${policy.key}:
theme="simple">${policy.value.name}:
</ww:label> </ww:label>
</td> </td>
<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

import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.CachedFailuresPolicy;
import org.apache.maven.archiva.policies.ChecksumPolicy; 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.ReleasesPolicy;
import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy;
import org.apache.maven.archiva.web.action.AbstractWebworkTestCase; import org.apache.maven.archiva.web.action.AbstractWebworkTestCase;
import org.easymock.MockControl; import org.easymock.MockControl;


import java.util.List; import java.util.List;
import java.util.Map;


/** /**
* AddProxyConnectorActionTest * AddProxyConnectorActionTest
connector.setTargetRepoId( "central" ); connector.setTargetRepoId( "central" );


// TODO: Set these options programatically via list of available policies. // 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 @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

import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration; import org.apache.maven.archiva.configuration.RemoteRepositoryConfiguration;
import org.apache.maven.archiva.policies.CachedFailuresPolicy; import org.apache.maven.archiva.policies.CachedFailuresPolicy;
import org.apache.maven.archiva.policies.ChecksumPolicy; 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.ReleasesPolicy;
import org.apache.maven.archiva.policies.SnapshotsPolicy; import org.apache.maven.archiva.policies.SnapshotsPolicy;
import org.apache.maven.archiva.web.action.AbstractWebworkTestCase; import org.apache.maven.archiva.web.action.AbstractWebworkTestCase;
import org.easymock.MockControl; import org.easymock.MockControl;


import java.util.List; import java.util.List;
import java.util.Map;


/** /**
* EditProxyConnectorActionTest * EditProxyConnectorActionTest
connector.setTargetRepoId( TEST_TARGET_ID ); connector.setTargetRepoId( TEST_TARGET_ID );
// TODO: Set these options programatically via list of available policies. // 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 ); config.addProxyConnector( connector );



Loading…
Cancel
Save