brett 2004/07/01 05:55:49
Modified: src/java/org/apache/maven/util Tag: MAVEN-1_0-BRANCH
HttpUtils.java
src/java/org/apache/maven/verifier Tag: MAVEN-1_0-BRANCH
DependencyVerifier.java
xdocs Tag: MAVEN-1_0-BRANCH changes.xml
Log:
fixes to httpclient code
Revision Changes Path
No revision
No revision
1.28.4.11 +156 -96 maven/src/java/org/apache/maven/util/HttpUtils.java
Index: HttpUtils.java
===================================================================
RCS file: /home/cvs/maven/src/java/org/apache/maven/util/HttpUtils.java,v
retrieving revision 1.28.4.10
retrieving revision 1.28.4.11
diff -u -r1.28.4.10 -r1.28.4.11
--- HttpUtils.java 27 Jun 2004 07:57:48 -0000 1.28.4.10
+++ HttpUtils.java 1 Jul 2004 12:55:46 -0000 1.28.4.11
@@ -31,7 +31,9 @@
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.TimeZone;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.Credentials;
@@ -61,6 +63,11 @@
{
private static final Log LOG = LogFactory.getLog(HttpUtils.class);
+ private static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");
+
+ /** @todo make it a property. */
+ private static final int REDIRECT_LIMIT = 5;
+
/**
* Use a proxy to bypass the firewall with or without authentication
*
@@ -262,6 +269,8 @@
String loginDomain )
throws IOException
{
+ LOG.debug( "Getting URL: " + url );
+
//set the timestamp to the file date.
long timestamp = -1;
if ( useTimestamp && destinationFile.exists() )
@@ -360,90 +369,22 @@
client.getState().setCredentials(null, null, creds);
}
- int statusCode = -1;
- InputStream is = null;
- GetMethod get = new GetMethod(source.getPath());
- try {
- if ( timestamp >= 0 )
- {
- SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd-MMM-yy
HH:mm:ss zzz");
- get.addRequestHeader(new Header("If-Modified-Since",
fmt.format(new Date(timestamp))));
- }
-
- // We will retry up to 3 times.
- for (int i = 0; i < 3; i++)
- {
- try
- {
- statusCode = client.executeMethod(get);
- if (statusCode != -1) {
- break;
- }
- }
- catch (HttpRecoverableException e)
- {
- if (i < 2) {
- throw e;
- }
- LOG.warn( "A recoverable exception occurred." +
e.getMessage());
- }
- catch (IOException e)
- {
- throw e;
- }
- if (i < 2) {
- LOG.warn("retrying " + (i + 1) + " of 3");
- }
+ for (int i = 0; i < REDIRECT_LIMIT; i++ )
+ {
+ String redirect = retrieveArtifact(client, source, destinationFile,
timestamp, silent);
+ if (redirect == null) {
+ break;
}
-
- boolean use = statusCode < 300 && statusCode !=
HttpURLConnection.HTTP_NOT_MODIFIED;
-
- // Must read content regardless
- is = get.getResponseBodyAsStream();
- if (is == null) {
- if (!silent) LOG.info("Not modified");
- return;
+ if (i >= REDIRECT_LIMIT - 1) {
+ throw new IOException("Redirection limit of " + REDIRECT_LIMIT
+ " exceeded");
}
- int projected = 0;
- Header header = get.getResponseHeader("Content-Length");
- if (header != null) {
- projected = Integer.valueOf(header.getValue()).intValue()/1024;
- }
+ redirect = StringUtils.replace( redirect, ":/", "://" );
+ redirect = StringUtils.replace( redirect, "//", "/" );
- long remoteTimestamp = 0;
- header = get.getResponseHeader("Last-Modified");
- if (header != null) {
- try {
- remoteTimestamp =
DateParser.parseDate(header.getValue()).getTime();
- }
- catch (DateParseException e) {
- LOG.warn("Unable to parse last modified header", e );
- }
- }
- else {
- if (!silent) LOG.warn("warning: last-modified not specified");
- }
- process( use, is, destinationFile, projected, timestamp,
remoteTimestamp, silent );
- }
- finally {
- if (is != null) try { is.close(); } catch (Exception e) {
LOG.error("error closing stream", e); }
- get.releaseConnection();
- }
-
- if ( statusCode == HttpURLConnection.HTTP_NOT_FOUND)
- {
- throw new FileNotFoundException(url.toString());
- }
- // test for 401 result (HTTP only)
- if ( statusCode == HttpURLConnection.HTTP_UNAUTHORIZED )
- {
- throw new IOException( "Not authorized." );
- }
- // test for 407 result (HTTP only)
- if ( statusCode == HttpURLConnection.HTTP_PROXY_AUTH )
- {
- throw new IOException( "Not authorized by proxy." );
+ source = new URL( redirect );
+ hc.setHost(source.getHost(), source.getPort(),
source.getProtocol());
+ client.setHostConfiguration(hc);
}
}
else
@@ -474,7 +415,7 @@
if ( connection.getLastModified() <= timestamp &&
connection.getLastModified() != 0 )
{
- if (!silent) LOG.info("Not modified");
+ if (!silent) LOG.debug("Not modified");
return;
}
@@ -489,6 +430,121 @@
}
}
+ private static String retrieveArtifact(HttpClient client, URL source, File
destinationFile, long timestamp, boolean silent) throws FileNotFoundException,
IOException, HttpRecoverableException {
+ int statusCode = -1;
+ String redirectUrl = null;
+ InputStream is = null;
+ GetMethod get = new GetMethod(source.getPath());
+ // Handle these ourselves until httpclient deals with cross host redirects
+ get.setFollowRedirects(false);
+ try {
+ if ( timestamp >= 0 )
+ {
+ SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd-MMM-yy
HH:mm:ss zzz");
+ fmt.setTimeZone(GMT_TIME_ZONE);
+ Header hdr = new Header("If-Modified-Since", fmt.format(new
Date(timestamp)));
+ LOG.debug("sending ==> " + hdr + "(" + timestamp + ")");
+ get.addRequestHeader(hdr);
+ }
+
+ // We will retry up to 3 times.
+ for (int i = 0; i < 3; i++)
+ {
+ try
+ {
+ statusCode = client.executeMethod(get);
+ if (statusCode != -1) {
+ LOG.debug("Received status code: " + statusCode);
+ break;
+ }
+ }
+ catch (HttpRecoverableException e)
+ {
+ if (i >= 2) {
+ throw e;
+ }
+ LOG.warn( "A recoverable exception occurred." + e.getMessage());
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ LOG.warn("retrying (" + (i + 1) + ")");
+ }
+
+ boolean use = statusCode < 300;
+
+ if (statusCode == HttpURLConnection.HTTP_NOT_MODIFIED) {
+ if (!silent) LOG.debug("Not modified");
+ }
+ else if (statusCode >= 300 && statusCode < 400) {
+ Header header = get.getResponseHeader("Location");
+ if (header != null) {
+ redirectUrl = header.getValue();
+ LOG.debug("Location: " + redirectUrl);
+ }
+ else {
+ LOG.warn("Location header not specified");
+ }
+ }
+
+ // Must read content regardless
+ is = get.getResponseBodyAsStream();
+ if (is == null) {
+ return redirectUrl;
+ }
+
+ int projected = 0;
+ Header header = get.getResponseHeader("Content-Length");
+ if (header != null) {
+ try {
+ projected = Integer.valueOf(header.getValue()).intValue();
+ }
+ catch (NumberFormatException e) {
+ LOG.warn( "error parsing content length header '" +
header.getValue() + "' " + e );
+ }
+ }
+
+ long remoteTimestamp = 0;
+ if ( use ) {
+ header = get.getResponseHeader("Last-Modified");
+ if (header != null) {
+ try {
+ remoteTimestamp =
DateParser.parseDate(header.getValue()).getTime();
+ }
+ catch (DateParseException e) {
+ LOG.warn("Unable to parse last modified header", e );
+ }
+ LOG.debug("last-modified = " + header.getValue() + " (" +
remoteTimestamp + ")");
+ }
+ else {
+ if (!silent) LOG.warn("warning: last-modified not specified");
+ }
+ }
+ process( use, is, destinationFile, projected, timestamp,
remoteTimestamp, silent );
+ }
+ finally {
+ if (is != null) try { is.close(); } catch (Exception e) {
LOG.error("error closing stream", e); }
+ get.releaseConnection();
+ }
+
+ if ( statusCode == HttpURLConnection.HTTP_NOT_FOUND)
+ {
+ throw new FileNotFoundException(source.toString());
+ }
+ // test for 401 result (HTTP only)
+ if ( statusCode == HttpURLConnection.HTTP_UNAUTHORIZED )
+ {
+ throw new IOException( "Not authorized." );
+ }
+ // test for 407 result (HTTP only)
+ if ( statusCode == HttpURLConnection.HTTP_PROXY_AUTH )
+ {
+ throw new IOException( "Not authorized by proxy." );
+ }
+ return redirectUrl;
+ }
+
private static void process( boolean use, InputStream is, File destinationFile,
long projected, long timestamp, long remoteTimestamp, boolean silent )
throws IOException {
byte[] buffer = new byte[100 * 1024];
@@ -509,27 +565,30 @@
}
}
}
+ }
+ finally {
+ if (os != null) try { os.close(); } catch (Exception e) {
LOG.error("error closing stream", e); }
+ }
- if ( use ) {
- if ( !silent ) {
- System.out.println( (total/1024) + "K downloaded");
- }
+ if ( use ) {
+ if ( !silent ) {
+ System.out.println( (total/1024) + "K downloaded");
+ }
+
+ LOG.debug("Local timestamp: " + timestamp);
+ LOG.debug("Remote timestamp: " + remoteTimestamp);
- // if (and only if) the use file time option is set, then the
- // saved file now has its timestamp set to that of the downloaded
- // file
- if ( timestamp >= 0 )
+ // if (and only if) the use file time option is set, then the
+ // saved file now has its timestamp set to that of the downloaded
+ // file
+ if ( timestamp >= 0 )
+ {
+ if ( remoteTimestamp != 0 )
{
- if ( remoteTimestamp != 0 )
- {
- touchFile( destinationFile, remoteTimestamp );
- }
+ touchFile( destinationFile, remoteTimestamp );
}
}
}
- finally {
- if (os != null) try { os.close(); } catch (Exception e) {
LOG.error("error closing stream", e); }
- }
}
/**
@@ -590,6 +649,7 @@
modifiedTime = timemillis;
}
+ LOG.debug("touching " + file + " with " + modifiedTime);
file.setLastModified( modifiedTime );
return true;
}
No revision
No revision
1.34.4.8 +17 -6 maven/src/java/org/apache/maven/verifier/DependencyVerifier.java
Index: DependencyVerifier.java
===================================================================
RCS file:
/home/cvs/maven/src/java/org/apache/maven/verifier/DependencyVerifier.java,v
retrieving revision 1.34.4.7
retrieving revision 1.34.4.8
diff -u -r1.34.4.7 -r1.34.4.8
--- DependencyVerifier.java 27 Jun 2004 07:57:48 -0000 1.34.4.7
+++ DependencyVerifier.java 1 Jul 2004 12:55:46 -0000 1.34.4.8
@@ -141,7 +141,7 @@
{
failedDependencies.add( artifact );
}
- else
+ else if ( artifact.isSnapshot() )
{
// The artifact exists but we need to take into account the user
// being online and whether the artifact is a snapshot. If the user
@@ -151,11 +151,11 @@
// take their chances with a strong warning that they could possibly
// be using an out-of-date artifact. We don't want to cripple users
// when working offline.
- if ( online && artifact.isSnapshot() )
+ if ( online )
{
failedDependencies.add( artifact );
}
- else if ( !online && artifact.isSnapshot() )
+ else
{
log.warn( getMessage( "offline.snapshot.warning",
artifact.getName() ) );
}
@@ -235,6 +235,7 @@
*/
private void getDependencies()
{
+ log.debug("Getting failed dependencies: " + failedDependencies);
for ( Iterator i = failedDependencies.iterator(); i.hasNext();)
{
Artifact artifact = (Artifact) i.next();
@@ -263,7 +264,7 @@
{
// The snapshot jar locally exists and not in remote repository
// FIXME: localize this message
- log.debug("Artifact " + artifact.getUrlPath()
+ log.info("Artifact " + artifact.getUrlPath()
+ " doesn't exists in remote repository, but it exists
locally");
i.remove();
}
@@ -285,11 +286,16 @@
private boolean getRemoteArtifact( Artifact artifact )
{
boolean artifactFound = false;
+ boolean errorsFound = false;
for ( Iterator i =
getProject().getContext().getMavenRepoRemote().iterator(); i.hasNext();)
{
String remoteRepo = (String) i.next();
+ if (remoteRepo.endsWith("/")) {
+ remoteRepo = remoteRepo.substring(0, remoteRepo.length() - 1);
+ }
+
// The username and password parameters are not being
// used here. Those are the "" parameters you see below.
String url = remoteRepo + "/" + artifact.getUrlPath();
@@ -311,7 +317,6 @@
// of the checksum file was successful.
try
{
- log.debug( "Getting URL: " + url );
String loginHost = (String) getProject().getContext().getVariable(
MavenConstants.PROXY_LOGINHOST );
String loginDomain = (String)
getProject().getContext().getVariable( MavenConstants.PROXY_LOGINDOMAIN );
HttpUtils.getFile( url,
@@ -329,6 +334,11 @@
// 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;
+ }
}
catch (FileNotFoundException e)
{
@@ -361,6 +371,7 @@
// FIXME: localize this message
log.warn("Error retrieving artifact from [" + url + "]: " + e);
log.debug("Error details", e);
+ errorsFound = true;
}
}
No revision
No revision
1.14.4.27 +7 -0 maven/xdocs/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/maven/xdocs/changes.xml,v
retrieving revision 1.14.4.26
retrieving revision 1.14.4.27
diff -u -r1.14.4.26 -r1.14.4.27
--- changes.xml 28 Jun 2004 12:22:07 -0000 1.14.4.26
+++ changes.xml 1 Jul 2004 12:55:49 -0000 1.14.4.27
@@ -24,6 +24,13 @@
<author email="[EMAIL PROTECTED]">Vincent Massol</author>
</properties>
<body>
+ <release version="1.0-final-SNAPSHOT" date="in CVS">
+ <action dev="brett" type="fix" issue="MAVEN-1343">Bugfixes for new httpclient
based downloading (incorrect timestamps)</action>
+ <action dev="brett" type="fix" issue="MAVEN-1353">Handle cross site
redirects</action>
+ <action dev="brett" type="fix" issue="MAVEN-1290">Correct absolute paths with
no drive designator on windows</action>
+ <action dev="brett" type="fix" issue="MAVEN-1341">Amend bootstrap to create
directories that might not exist</action>
+ <action dev="brett" type="fix" issue="MAVEN-1344">If artifact is not a
snapshot, don't continue checking for newer downloads once one is successful</action>
+ </release>
<release version="1.0-rc4" date="2004-06-28">
<action dev="brett" type="update">Set maven.plugin.user.dir to
${maven.home.local}/plugins by default, move maven.plugin.unpacked.dir to
${maven.home.local}/cache.</action>
<action dev="brett" type="update">Read local plugin jars from
maven.plugin.user.dir instead of maven.plugin.unpacked.dir.</action>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]