diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManager.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManager.java index 9fecd1f045..7105bccadb 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManager.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManager.java @@ -36,6 +36,7 @@ import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; import org.apache.maven.artifact.repository.Authentication; import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; +import org.apache.maven.repository.Proxy; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.Logger; @@ -45,6 +46,9 @@ public class DefaultUpdateCheckManager extends AbstractLogEnabled implements UpdateCheckManager { + + private static final String ERROR_KEY_SUFFIX = ".error"; + public DefaultUpdateCheckManager() { @@ -154,7 +158,13 @@ public class DefaultUpdateCheckManager return readLastUpdated( touchfile, key ); } - public void touch( Artifact artifact, ArtifactRepository repository ) + public String getError( Artifact artifact, ArtifactRepository repository ) + { + File touchFile = getTouchfile( artifact ); + return getError( touchFile, getRepositoryKey( repository ) ); + } + + public void touch( Artifact artifact, ArtifactRepository repository, String error ) { File file = artifact.getFile(); @@ -166,7 +176,7 @@ public class DefaultUpdateCheckManager } else { - writeLastUpdated( touchfile, getRepositoryKey( repository ) ); + writeLastUpdated( touchfile, getRepositoryKey( repository ), error ); } } @@ -176,7 +186,7 @@ public class DefaultUpdateCheckManager String key = getMetadataKey( repository, file ); - writeLastUpdated( touchfile, key ); + writeLastUpdated( touchfile, key, null ); } String getMetadataKey( ArtifactRepository repository, File file ) @@ -188,6 +198,17 @@ public class DefaultUpdateCheckManager { StringBuilder buffer = new StringBuilder( 256 ); + Proxy proxy = repository.getProxy(); + if ( proxy != null ) + { + if ( proxy.getUserName() != null ) + { + int hash = ( proxy.getUserName() + proxy.getPassword() ).hashCode(); + buffer.append( hash ).append( '@' ); + } + buffer.append( proxy.getHost() ).append( ':' ).append( proxy.getPort() ).append( '>' ); + } + // consider the username&password because a repo manager might block artifacts depending on authorization Authentication auth = repository.getAuthentication(); if ( auth != null ) @@ -202,7 +223,7 @@ public class DefaultUpdateCheckManager return buffer.toString(); } - private void writeLastUpdated( File touchfile, String key ) + private void writeLastUpdated( File touchfile, String key, String error ) { synchronized ( touchfile.getAbsolutePath().intern() ) { @@ -236,6 +257,15 @@ public class DefaultUpdateCheckManager props.setProperty( key, Long.toString( System.currentTimeMillis() ) ); + if ( error != null ) + { + props.setProperty( key + ERROR_KEY_SUFFIX, error ); + } + else + { + props.remove( key + ERROR_KEY_SUFFIX ); + } + ByteArrayOutputStream stream = new ByteArrayOutputStream(); getLogger().debug( "Writing resolution-state to: " + touchfile ); @@ -285,19 +315,49 @@ public class DefaultUpdateCheckManager } } - public Date readLastUpdated( File touchfile, String key ) + Date readLastUpdated( File touchfile, String key ) + { + getLogger().debug( "Searching for " + key + " in resolution tracking file." ); + + Properties props = read( touchfile ); + if ( props != null ) + { + String rawVal = props.getProperty( key ); + if ( rawVal != null ) + { + try + { + return new Date( Long.parseLong( rawVal ) ); + } + catch ( NumberFormatException e ) + { + getLogger().debug( "Cannot parse lastUpdated date: \'" + rawVal + "\'. Ignoring.", e ); + } + } + } + return null; + } + + private String getError( File touchFile, String key ) + { + Properties props = read( touchFile ); + if ( props != null ) + { + return props.getProperty( key + ERROR_KEY_SUFFIX ); + } + return null; + } + + private Properties read( File touchfile ) { if ( !touchfile.canRead() ) { - getLogger().debug( "Skipped unreadable touchfile " + touchfile + " for key " + key ); + getLogger().debug( "Skipped unreadable resolution tracking file " + touchfile ); return null; } synchronized ( touchfile.getAbsolutePath().intern() ) { - getLogger().debug( "Searching for: " + key + " in touchfile." ); - - Date result = null; FileInputStream stream = null; FileLock lock = null; FileChannel channel = null; @@ -312,24 +372,13 @@ public class DefaultUpdateCheckManager getLogger().debug( "Reading resolution-state from: " + touchfile ); props.load( stream ); - String rawVal = props.getProperty( key ); - if ( rawVal != null ) - { - try - { - result = new Date( Long.parseLong( rawVal ) ); - } - catch ( NumberFormatException e ) - { - getLogger().debug( "Cannot parse lastUpdated date: \'" + rawVal + "\'. Ignoring.", e ); - result = null; - } - } + return props; } catch ( IOException e ) { - getLogger().debug( "Failed to read lastUpdated information.\nFile: " - + touchfile.toString() + "; key: " + key, e ); + getLogger().debug( "Failed to read resolution tracking file " + touchfile, e ); + + return null; } finally { @@ -341,8 +390,7 @@ public class DefaultUpdateCheckManager } catch ( IOException e ) { - getLogger().debug( "Error releasing shared lock for resolution tracking file: " - + touchfile, e ); + getLogger().debug( "Error releasing shared lock for resolution tracking file: " + touchfile, e ); } } @@ -354,13 +402,10 @@ public class DefaultUpdateCheckManager } catch ( IOException e ) { - getLogger().debug( "Error closing FileChannel for resolution tracking file: " - + touchfile, e ); + getLogger().debug( "Error closing FileChannel for resolution tracking file: " + touchfile, e ); } } } - - return result; } } diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java index 3bd49a69e8..0672131851 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/DefaultWagonManager.java @@ -98,10 +98,19 @@ public class DefaultWagonManager { getRemoteFile( repository, artifact.getFile(), remotePath, downloadMonitor, policy.getChecksumPolicy(), false ); + + updateCheckManager.touch( artifact, repository, null ); } - finally + catch ( ResourceDoesNotExistException e ) { - updateCheckManager.touch( artifact, repository ); + updateCheckManager.touch( artifact, repository, null ); + throw e; + } + catch ( TransferFailedException e ) + { + String error = ( e.getMessage() != null ) ? e.getMessage() : e.getClass().getSimpleName(); + updateCheckManager.touch( artifact, repository, error ); + throw e; } logger.debug( " Artifact " + artifact.getId() + " resolved to " + artifact.getFile() ); @@ -110,10 +119,21 @@ public class DefaultWagonManager } else if ( !artifact.getFile().exists() ) { - throw new ResourceDoesNotExistException( "Failure to resolve " + remotePath + " from " - + repository.getUrl() + " was cached in the local repository. " - + "Resolution will not be reattempted until the update interval of " + repository.getId() - + " has elapsed or updates are forced." ); + String error = updateCheckManager.getError( artifact, repository ); + if ( error != null ) + { + throw new TransferFailedException( "Failure to resolve " + remotePath + " from " + + repository.getUrl() + " was cached in the local repository. " + + "Resolution will not be reattempted until the update interval of " + repository.getId() + + " has elapsed or updates are forced. Original error: " + error ); + } + else + { + throw new ResourceDoesNotExistException( "Failure to resolve " + remotePath + " from " + + repository.getUrl() + " was cached in the local repository. " + + "Resolution will not be reattempted until the update interval of " + repository.getId() + + " has elapsed or updates are forced." ); + } } } } diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/UpdateCheckManager.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/UpdateCheckManager.java index 6ac49a27e7..f4e969b693 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/UpdateCheckManager.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/UpdateCheckManager.java @@ -30,7 +30,9 @@ public interface UpdateCheckManager boolean isUpdateRequired( Artifact artifact, ArtifactRepository repository ); - void touch( Artifact artifact, ArtifactRepository repository ); + void touch( Artifact artifact, ArtifactRepository repository, String error ); + + String getError( Artifact artifact, ArtifactRepository repository ); boolean isUpdateRequired( RepositoryMetadata metadata, ArtifactRepository repository, File file ); diff --git a/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java b/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java index 9b8376ef16..c5ec6f6426 100644 --- a/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java +++ b/maven-compat/src/test/java/org/apache/maven/repository/legacy/DefaultUpdateCheckManagerTest.java @@ -71,7 +71,7 @@ public class DefaultUpdateCheckManagerTest file.getParentFile().mkdirs(); file.createNewFile(); - updateCheckManager.touch( a, remoteRepository ); + updateCheckManager.touch( a, remoteRepository, null ); assertFalse( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); @@ -99,7 +99,7 @@ public class DefaultUpdateCheckManagerTest assertTrue( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); - updateCheckManager.touch( a, remoteRepository ); + updateCheckManager.touch( a, remoteRepository, null ); assertFalse( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); @@ -127,7 +127,7 @@ public class DefaultUpdateCheckManagerTest file.getParentFile().mkdirs(); file.createNewFile(); - updateCheckManager.touch( a, remoteRepository ); + updateCheckManager.touch( a, remoteRepository, null ); assertFalse( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); @@ -155,7 +155,7 @@ public class DefaultUpdateCheckManagerTest assertTrue( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); - updateCheckManager.touch( a, remoteRepository ); + updateCheckManager.touch( a, remoteRepository, null ); assertFalse( updateCheckManager.isUpdateRequired( a, remoteRepository ) ); diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java index ffb2d0e1af..7f862b7b4f 100644 --- a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java +++ b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java @@ -41,6 +41,7 @@ import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException; import org.apache.maven.artifact.resolver.filter.AndArtifactFilter; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; @@ -587,11 +588,16 @@ public class MavenMetadataSource String message; - // missing/incompatible POM (e.g. a Maven 1 POM) - if ( isMissingPom( e ) ) + if ( e.getCause() instanceof MultipleArtifactsNotFoundException ) { message = "Missing POM for " + relocatedArtifact.getId(); } + else if ( e.getCause() instanceof ArtifactResolutionException ) + { + throw new ArtifactMetadataRetrievalException( "Failed to retrieve POM for " + + relocatedArtifact.getId() + ": " + e.getCause().getMessage(), e.getCause(), + relocatedArtifact ); + } else { message = @@ -705,11 +711,6 @@ public class MavenMetadataSource return rel; } - private boolean isMissingPom( ProjectBuildingException e ) - { - return e.getCause() instanceof ArtifactResolutionException; - } - private ModelProblem hasMissingParentPom( ProjectBuildingException e ) { if ( e.getCause() instanceof ModelBuildingException )