mbenson 2005/02/25 15:15:16
Modified: src/main/org/apache/tools/ant/taskdefs Tag: ANT_16_BRANCH
Get.java
. Tag: ANT_16_BRANCH WHATSNEW
src/etc/testcases/taskdefs Tag: ANT_16_BRANCH get.xml
src/testcases/org/apache/tools/ant/taskdefs Tag:
ANT_16_BRANCH GetTest.java
Log:
Sync Get to HEAD (hope that's okay Steve);
in particular sync usetimestamp fix on Java 1.2
Revision Changes Path
No revision
No revision
1.38.2.5 +262 -151 ant/src/main/org/apache/tools/ant/taskdefs/Get.java
Index: Get.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Get.java,v
retrieving revision 1.38.2.4
retrieving revision 1.38.2.5
diff -u -r1.38.2.4 -r1.38.2.5
--- Get.java 9 Mar 2004 17:01:33 -0000 1.38.2.4
+++ Get.java 25 Feb 2005 23:15:15 -0000 1.38.2.5
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2004 The Apache Software Foundation
+ * Copyright 2000-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,19 +17,21 @@
package org.apache.tools.ant.taskdefs;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.JavaEnvUtils;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.util.FileUtils;
-import org.apache.tools.ant.util.JavaEnvUtils;
/**
* Gets a particular file from a URL source.
@@ -37,12 +39,14 @@
* actions on failures. NB: access through a firewall only works if the whole
* Java runtime is correctly configured.
*
- *
* @since Ant 1.1
*
* @ant.task category="network"
*/
public class Get extends Task {
+
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
private URL source; // required
private File dest; // required
private boolean verbose = false;
@@ -52,12 +56,47 @@
private String pword = null;
+
/**
* Does the work.
*
* @exception BuildException Thrown in unrecoverable error.
*/
public void execute() throws BuildException {
+
+ //set up logging
+ int logLevel = Project.MSG_INFO;
+ DownloadProgress progress = null;
+ if (verbose) {
+ progress = new VerboseProgress(System.out);
+ }
+
+ //execute the get
+ try {
+ doGet(logLevel, progress);
+ } catch (IOException ioe) {
+ log("Error getting " + source + " to " + dest);
+ if (!ignoreErrors) {
+ throw new BuildException(ioe, getLocation());
+ }
+ }
+ }
+
+ /**
+ * make a get request, with the supplied progress and logging info.
+ * All the other config parameters are set at the task level,
+ * source, dest, ignoreErrors, etc.
+ * @param logLevel level to log at, see [EMAIL PROTECTED]
Project#log(String, int)}
+ * @param progress progress callback; null for no-callbacks
+ * @return true for a successful download, false otherwise.
+ * The return value is only relevant when [EMAIL PROTECTED]
#ignoreErrors} is true, as
+ * when false all failures raise BuildExceptions.
+ * @throws IOException for network trouble
+ * @throws BuildException for argument errors, or other trouble when
ignoreErrors
+ * is false.
+ */
+ public boolean doGet(int logLevel, DownloadProgress progress)
+ throws IOException {
if (source == null) {
throw new BuildException("src attribute is required",
getLocation());
}
@@ -68,172 +107,161 @@
if (dest.exists() && dest.isDirectory()) {
throw new BuildException("The specified destination is a
directory",
- getLocation());
+ getLocation());
}
if (dest.exists() && !dest.canWrite()) {
throw new BuildException("Can't write to " +
dest.getAbsolutePath(),
- getLocation());
+ getLocation());
}
+ //dont do any progress, unless asked
+ if (progress == null) {
+ progress = new NullProgress();
+ }
+ log("Getting: " + source, logLevel);
+ log("To: " + dest.getAbsolutePath(), logLevel);
- try {
-
- log("Getting: " + source);
-
- //set the timestamp to the file date.
- long timestamp = 0;
-
- boolean hasTimestamp = false;
- if (useTimestamp && dest.exists()) {
- timestamp = dest.lastModified();
- if (verbose) {
- Date t = new Date(timestamp);
- log("local file date : " + t.toString());
- }
+ //set the timestamp to the file date.
+ long timestamp = 0;
- hasTimestamp = true;
+ boolean hasTimestamp = false;
+ if (useTimestamp && dest.exists()) {
+ timestamp = dest.lastModified();
+ if (verbose) {
+ Date t = new Date(timestamp);
+ log("local file date : " + t.toString(), logLevel);
}
+ hasTimestamp = true;
+ }
- //set up the URL connection
- URLConnection connection = source.openConnection();
- //modify the headers
- //NB: things like user authentication could go in here too.
- if (useTimestamp && hasTimestamp) {
- connection.setIfModifiedSince(timestamp);
- }
- // prepare Java 1.1 style credentials
- if (uname != null || pword != null) {
- String up = uname + ":" + pword;
- String encoding;
- // check to see if sun's Base64 encoder is available.
- try {
- Object encoder =
-
Class.forName("sun.misc.BASE64Encoder").newInstance();
- encoding = (String)
- encoder.getClass().getMethod("encode", new
Class[] {byte[].class})
- .invoke(encoder, new Object[] {up.getBytes()});
-
- } catch (Exception ex) { // sun's base64 encoder isn't
available
- Base64Converter encoder = new Base64Converter();
- encoding = encoder.encode(up.getBytes());
- }
- connection.setRequestProperty ("Authorization",
- "Basic " + encoding);
- }
+ //set up the URL connection
+ URLConnection connection = source.openConnection();
+ //modify the headers
+ //NB: things like user authentication could go in here too.
+ if (hasTimestamp) {
+ connection.setIfModifiedSince(timestamp);
+ }
+ // prepare Java 1.1 style credentials
+ if (uname != null || pword != null) {
+ String up = uname + ":" + pword;
+ String encoding;
+ //we do not use the sun impl for portability,
+ //and always use our own implementation for consistent
+ //testing
+ Base64Converter encoder = new Base64Converter();
+ encoding = encoder.encode(up.getBytes());
+ connection.setRequestProperty ("Authorization",
+ "Basic " + encoding);
+ }
- //connect to the remote site (may take some time)
- connection.connect();
- //next test for a 304 result (HTTP only)
- if (connection instanceof HttpURLConnection) {
- HttpURLConnection httpConnection
+ //connect to the remote site (may take some time)
+ connection.connect();
+ //next test for a 304 result (HTTP only)
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection httpConnection
= (HttpURLConnection) connection;
- if (httpConnection.getResponseCode()
- == HttpURLConnection.HTTP_NOT_MODIFIED) {
- //not modified so no file download. just return
- //instead and trace out something so the user
- //doesn't think that the download happened when it
- //didn't
- log("Not modified - so not downloaded");
- return;
- }
- // test for 401 result (HTTP only)
- if (httpConnection.getResponseCode()
+ if (httpConnection.getResponseCode()
+ == HttpURLConnection.HTTP_NOT_MODIFIED
+ //workaround: doesn't work on 1.2
+ || (hasTimestamp
+ && JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
+ && timestamp > httpConnection.getLastModified())) {
+ //not modified so no file download. just return
+ //instead and trace out something so the user
+ //doesn't think that the download happened when it
+ //didn't
+ log("Not modified - so not downloaded", logLevel);
+ return false;
+ // also, if timestamp is roughly >= now, HTTP_NOT_MODIFIED
is _not_
+ // returned... We may want to remove the 1.2 qualifier above.
+ }
+ // test for 401 result (HTTP only)
+ if (httpConnection.getResponseCode()
== HttpURLConnection.HTTP_UNAUTHORIZED) {
- String message = "HTTP Authorization failure";
- if (ignoreErrors) {
- log(message, Project.MSG_WARN);
- return;
- } else {
- throw new BuildException(message);
- }
+ String message = "HTTP Authorization failure";
+ if (ignoreErrors) {
+ log(message, logLevel);
+ return false;
+ } else {
+ throw new BuildException(message);
}
-
}
- //REVISIT: at this point even non HTTP connections may
- //support the if-modified-since behaviour -we just check
- //the date of the content and skip the write if it is not
- //newer. Some protocols (FTP) don't include dates, of
- //course.
-
- InputStream is = null;
- for (int i = 0; i < 3; i++) {
- try {
- is = connection.getInputStream();
- break;
- } catch (IOException ex) {
- log("Error opening connection " + ex);
- }
+ }
+
+ //REVISIT: at this point even non HTTP connections may
+ //support the if-modified-since behaviour -we just check
+ //the date of the content and skip the write if it is not
+ //newer. Some protocols (FTP) don't include dates, of
+ //course.
+
+ InputStream is = null;
+ for (int i = 0; i < 3; i++) {
+ //this three attempt trick is to get round quirks in different
+ //Java implementations. Some of them take a few goes to bind
+ //property; we ignore the first couple of such failures.
+ try {
+ is = connection.getInputStream();
+ break;
+ } catch (IOException ex) {
+ log("Error opening connection " + ex, logLevel);
}
- if (is == null) {
- log("Can't get " + source + " to " + dest);
- if (ignoreErrors) {
- return;
- }
- throw new BuildException("Can't get " + source + " to " +
dest,
- getLocation());
+ }
+ if (is == null) {
+ log("Can't get " + source + " to " + dest, logLevel);
+ if (ignoreErrors) {
+ return false;
}
+ throw new BuildException("Can't get " + source + " to " + dest,
+ getLocation());
+ }
- FileOutputStream fos = new FileOutputStream(dest);
- boolean finished = false;
- try {
- byte[] buffer = new byte[100 * 1024];
- int length;
- int dots = 0;
-
- while ((length = is.read(buffer)) >= 0) {
- fos.write(buffer, 0, length);
- if (verbose) {
- System.out.print(".");
- if (dots++ > 50) {
- System.out.flush();
- dots = 0;
- }
- }
- }
- if (verbose) {
- System.out.println();
- }
- finished = true;
- } finally {
- if (fos != null) {
- fos.close();
- }
- is.close();
- // we have started to (over)write dest, but failed.
- // Try to delete the garbage we'd otherwise leave
- // behind.
- if (!finished) {
- dest.delete();
- }
+ FileOutputStream fos = new FileOutputStream(dest);
+ progress.beginDownload();
+ boolean finished = false;
+ try {
+ byte[] buffer = new byte[100 * 1024];
+ int length;
+ while ((length = is.read(buffer)) >= 0) {
+ fos.write(buffer, 0, length);
+ progress.onTick();
+ }
+ finished = true;
+ } finally {
+ FileUtils.close(fos);
+ FileUtils.close(is);
+
+ // we have started to (over)write dest, but failed.
+ // Try to delete the garbage we'd otherwise leave
+ // behind.
+ if (!finished) {
+ dest.delete();
}
+ }
+ progress.endDownload();
- //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 (useTimestamp) {
- long remoteTimestamp = connection.getLastModified();
- if (verbose) {
- Date t = new Date(remoteTimestamp);
- log("last modified = " + t.toString()
+ //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 (useTimestamp) {
+ long remoteTimestamp = connection.getLastModified();
+ if (verbose) {
+ Date t = new Date(remoteTimestamp);
+ log("last modified = " + t.toString()
+ ((remoteTimestamp == 0)
- ? " - using current time instead"
- : ""));
- }
- if (remoteTimestamp != 0) {
- FileUtils.newFileUtils()
- .setFileLastModified(dest, remoteTimestamp);
- }
+ ? " - using current time instead"
+ : ""), logLevel);
}
- } catch (IOException ioe) {
- log("Error getting " + source + " to " + dest);
- if (ignoreErrors) {
- return;
+ if (remoteTimestamp != 0) {
+ FILE_UTILS.setFileLastModified(dest, remoteTimestamp);
}
- throw new BuildException(ioe, getLocation());
}
+
+ //successful download
+ return true;
}
+
/**
* Set the URL to get.
*
@@ -289,9 +317,7 @@
* @param v "true" to enable file time fetching
*/
public void setUseTimestamp(boolean v) {
- if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
- useTimestamp = v;
- }
+ useTimestamp = v;
}
@@ -320,7 +346,7 @@
*
*********************************************************************/
- private static class Base64Converter {
+ protected static class Base64Converter {
public final char [ ] alphabet = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
@@ -391,4 +417,89 @@
return new String(out);
}
}
+
+ public interface DownloadProgress {
+ /**
+ * begin a download
+ */
+ public void beginDownload();
+
+ /**
+ * tick handler
+ *
+ */
+ public void onTick();
+
+ /**
+ * end a download
+ */
+ public void endDownload();
+ }
+
+ /**
+ * do nothing with progress info
+ */
+ public static class NullProgress implements DownloadProgress {
+
+ /**
+ * begin a download
+ */
+ public void beginDownload() {
+
+ }
+
+ /**
+ * tick handler
+ *
+ */
+ public void onTick() {
+ }
+
+ /**
+ * end a download
+ */
+ public void endDownload() {
+
+ }
+ }
+
+ /**
+ * verbose progress system prints to some output stream
+ */
+ public static class VerboseProgress implements DownloadProgress {
+ private int dots = 0;
+ PrintStream out;
+
+ public VerboseProgress(PrintStream out) {
+ this.out = out;
+ }
+
+ /**
+ * begin a download
+ */
+ public void beginDownload() {
+ dots = 0;
+ }
+
+ /**
+ * tick handler
+ *
+ */
+ public void onTick() {
+ out.print(".");
+ if (dots++ > 50) {
+ out.flush();
+ dots = 0;
+ }
+ }
+
+ /**
+ * end a download
+ */
+ public void endDownload() {
+ out.println();
+ out.flush();
+ }
+ }
+
}
No revision
No revision
1.503.2.184 +2 -0 ant/WHATSNEW
Index: WHATSNEW
===================================================================
RCS file: /home/cvs/ant/WHATSNEW,v
retrieving revision 1.503.2.183
retrieving revision 1.503.2.184
diff -u -r1.503.2.183 -r1.503.2.184
--- WHATSNEW 24 Feb 2005 20:25:57 -0000 1.503.2.183
+++ WHATSNEW 25 Feb 2005 23:15:15 -0000 1.503.2.184
@@ -219,6 +219,8 @@
* <javac debug="false"> created an invalid command line when running
the Symantec Java compiler.
+* Get with usetimestamp did not work on Java 1.2.
+
Changes from Ant 1.6.1 to Ant 1.6.2
===================================
No revision
No revision
1.4.6.1 +44 -0 ant/src/etc/testcases/taskdefs/get.xml
Index: get.xml
===================================================================
RCS file: /home/cvs/ant/src/etc/testcases/taskdefs/get.xml,v
retrieving revision 1.4
retrieving revision 1.4.6.1
diff -u -r1.4 -r1.4.6.1
--- get.xml 8 May 2001 09:35:27 -0000 1.4
+++ get.xml 25 Feb 2005 23:15:16 -0000 1.4.6.1
@@ -24,6 +24,50 @@
<target name="test6">
<get src="http://www.apache.org/" dest="get.tmp"/>
+
+ <fileset id="t6" file="get.tmp" />
+ <pathconvert property="t6" refid="t6" setonempty="false" />
+
+ <fail message="get failed">
+ <condition>
+ <not>
+ <isset property="t6" />
+ </not>
+ </condition>
+ </fail>
+ </target>
+
+ <target name="testUseTimestamp">
+ <property name="pat" value="yyyyMMddHHmm" />
+
+ <tstamp>
+ <format property="dt" pattern="${pat}" offset="-90" unit="second" />
+ </tstamp>
+
+ <touch file="get.tmp" datetime="${dt}" pattern="${pat}" />
+
+ <get src="http://www.apache.org/" dest="get.tmp"
+ usetimestamp="true" verbose="true" />
+
+ <fileset id="ts" file="get.tmp">
+ <date when="equal" datetime="${dt}" pattern="${pat}" />
+ </fileset>
+
+ <pathconvert property="ts" refid="ts" setonempty="false" />
+
+ <fail message="get w/ timestamp should have failed.">
+ <condition>
+ <not>
+ <isset property="ts" />
+ </not>
+ </condition>
+ </fail>
+ </target>
+
+ <target name="cleanup">
+ <delete>
+ <fileset dir="${basedir}" includes="get.tmp" />
+ </delete>
</target>
</project>
No revision
No revision
1.7.2.5 +8 -7
ant/src/testcases/org/apache/tools/ant/taskdefs/GetTest.java
Index: GetTest.java
===================================================================
RCS file:
/home/cvs/ant/src/testcases/org/apache/tools/ant/taskdefs/GetTest.java,v
retrieving revision 1.7.2.4
retrieving revision 1.7.2.5
diff -u -r1.7.2.4 -r1.7.2.5
--- GetTest.java 9 Mar 2004 17:02:01 -0000 1.7.2.4
+++ GetTest.java 25 Feb 2005 23:15:16 -0000 1.7.2.5
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2001,2004 The Apache Software Foundation
+ * Copyright 2000-2001, 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,10 @@
configureProject("src/etc/testcases/taskdefs/get.xml");
}
+ public void tearDown() {
+ executeTarget("cleanup");
+ }
+
public void test1() {
expectBuildException("test1", "required argument missing");
}
@@ -54,13 +58,10 @@
public void test6() {
executeTarget("test6");
- java.io.File f = new File(getProjectDir(), "get.tmp");
- if (!f.exists()) {
- fail("get failed");
- } else {
- f.delete();
- }
+ }
+ public void testUseTimestamp() {
+ executeTarget("testUseTimestamp");
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]