{
String remoteRepo = (String) i.next();
Repository repository = new Repository( "repo" + count, remoteRepo.trim() );
final Wagon wagon = new DefaultWagonFactory().getWagon( repository.getProtocol() );
if ( listener != null )
{
wagon.addTransferListener( listener );
}
ChecksumObserver md5ChecksumObserver = null;
ChecksumObserver sha1ChecksumObserver = null;
try
{
md5ChecksumObserver = new ChecksumObserver( "MD5" );
wagon.addTransferListener( md5ChecksumObserver );
sha1ChecksumObserver = new ChecksumObserver( "SHA-1" );
wagon.addTransferListener( sha1ChecksumObserver );
}
catch ( NoSuchAlgorithmException e )
{
throw new ChecksumVerificationException( "Unable to add checksum methods: " + e.getMessage(), e );
}
File destination = artifact.getFile();
String remotePath = artifact.getUrlPath();
File temp = new File( destination + ".tmp" );
temp.deleteOnExit();
boolean downloaded = false;
try
{
wagon.connect( repository, proxyInfo );
boolean firstRun = true;
boolean retry = true;
// this will run at most twice. The first time, the firstRun flag is turned off, and if the retry flag
// is set on the first run, it will be turned off and not re-set on the second try. This is because the
// only way the retry flag can be set is if ( firstRun == true ).
while ( firstRun || retry )
{
// reset the retry flag.
retry = false;
downloaded = wagon.getIfNewer( remotePath, temp, destination.lastModified() );
if ( !downloaded && firstRun )
{
log.info( getMessage( "skip.download.message" ) );
}
if ( downloaded )
{
// keep the checksum files from showing up on the download monitor...
if ( listener != null )
{
wagon.removeTransferListener( listener );
}
// try to verify the MD5 checksum for this file.
try
{
verifyChecksum( md5ChecksumObserver, destination, temp, remotePath, ".md5", wagon );
}
catch ( ChecksumVerificationException e )
{
// if we catch a ChecksumVerificationException, it means the transfer/read succeeded, but the checksum
// doesn't match. This could be a problem with the server (ibiblio HTTP-200 error page), so we'll
// try this up to two times. On the second try, we'll handle it as a bona-fide error, based on the
// repository's checksum checking policy.
if ( firstRun )
{
log.warn( "*** CHECKSUM FAILED - " + e.getMessage() + " - RETRYING" );
retry = true;
}
else
{
throw new ChecksumVerificationException( e.getMessage(), e.getCause() );
}
}
catch ( ResourceDoesNotExistException md5TryException )
{
log.debug( "MD5 not found, trying SHA1", md5TryException );
// if this IS NOT a ChecksumVerificationException, it was a problem with transfer/read of the checksum
// file...we'll try again with the SHA-1 checksum.
try
{
verifyChecksum( sha1ChecksumObserver, destination, temp, remotePath, ".sha1", wagon );
}
catch ( ChecksumVerificationException e )
{
// if we also fail to verify based on the SHA-1 checksum, and the checksum transfer/read
// succeeded, then we need to determine whether to retry or handle it as a failure.
if ( firstRun )
{
retry = true;
}
else
{
throw new ChecksumVerificationException( e.getMessage(), e.getCause() );
}
}
catch ( ResourceDoesNotExistException sha1TryException )
{
// this was a failed transfer, and we don't want to retry.
throw new ChecksumVerificationException( "Error retrieving checksum file for "
+ remotePath, sha1TryException );
}
}
}
// Artifact was found, continue checking additional remote repos (if any)
// in case there is a newer version (i.e. snapshots) in another repo
artifactFound = true;
if ( !artifact.isSnapshot() )
{
break;
}
// reinstate the download monitor...
if ( listener != null )
{
wagon.addTransferListener( listener );
}
// unset the firstRun flag, so we don't get caught in an infinite loop...
firstRun = false;
}
}
catch ( ResourceDoesNotExistException e )
{
// Multiple repositories may exist, and if the file is not found
// in just one of them, it's no problem, and we don't want to
// even print out an error.
// if it's not found at all, artifactFound will be false, and the
// build _will_ break, and the user will get an error message
log.debug( "File not found on one of the repos", e );
}
catch ( Exception e )
{
// If there are additional remote repos, then ignore exception
// as artifact may be found in another remote repo. If there
// are no more remote repos to check and the artifact wasn't found in
// a previous remote repo, then artifactFound is false indicating
// that the artifact could not be found in any of the remote repos
//
// arguably, we need to give the user better control (another command-
// line switch perhaps) of what to do in this case? Maven already has
// a command-line switch to work in offline mode, but what about when
// one of two or more remote repos is unavailable? There may be multiple
// remote repos for redundancy, in which case you probably want the build
// to continue. There may however be multiple remote repos because some
// artifacts are on one, and some are on another. In this case, you may
// want the build to break.
//
// print a warning, in any case, so user catches on to mistyped
// hostnames, or other snafus
// FIXME: localize this message
log.warn( "Error retrieving artifact from [" + repository.getUrl() + "]: " + e );
log.debug( "Error details", e );
}
finally
{
try
{
wagon.disconnect();
}
catch ( ConnectionException e )
{
log.debug( "Error disconnecting wagon", e );
}