Getpublic class Get extends org.apache.tools.ant.Task Gets a particular file from a URL source.
Options include verbose reporting, timestamp based fetches and controlling
actions on failures. NB: access through a firewall only works if the whole
Java runtime is correctly configured. |
Fields Summary |
---|
private static final org.apache.tools.ant.util.FileUtils | FILE_UTILS | private URL | source | private File | dest | private boolean | verbose | private boolean | useTimestamp | private boolean | ignoreErrors | private String | uname | private String | pword |
Methods Summary |
---|
public boolean | doGet(int logLevel, org.apache.tools.ant.taskdefs.Get$DownloadProgress progress)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.
if (source == null) {
throw new BuildException("src attribute is required", getLocation());
}
if (dest == null) {
throw new BuildException("dest attribute is required", getLocation());
}
if (dest.exists() && dest.isDirectory()) {
throw new BuildException("The specified destination is a directory",
getLocation());
}
if (dest.exists() && !dest.canWrite()) {
throw new BuildException("Can't write to " + dest.getAbsolutePath(),
getLocation());
}
//dont do any progress, unless asked
if (progress == null) {
progress = new NullProgress();
}
log("Getting: " + source, logLevel);
log("To: " + dest.getAbsolutePath(), logLevel);
//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(), 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 (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
= (HttpURLConnection) connection;
long lastModified = httpConnection.getLastModified();
if (httpConnection.getResponseCode()
== HttpURLConnection.HTTP_NOT_MODIFIED
|| (lastModified != 0 && hasTimestamp
&& timestamp >= lastModified)) {
//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;
}
// test for 401 result (HTTP only)
if (httpConnection.getResponseCode()
== HttpURLConnection.HTTP_UNAUTHORIZED) {
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++) {
//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, logLevel);
if (ignoreErrors) {
return false;
}
throw new BuildException("Can't get " + source + " to " + dest,
getLocation());
}
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()
+ ((remoteTimestamp == 0)
? " - using current time instead"
: ""), logLevel);
}
if (remoteTimestamp != 0) {
FILE_UTILS.setFileLastModified(dest, remoteTimestamp);
}
}
//successful download
return true;
| public void | execute()Does the work.
//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());
}
}
| public void | setDest(java.io.File dest)Where to copy the source file.
this.dest = dest;
| public void | setIgnoreErrors(boolean v)If true, log errors but do not treat as fatal.
ignoreErrors = v;
| public void | setPassword(java.lang.String p)password for the basic authentication.
this.pword = p;
| public void | setSrc(java.net.URL u)Set the URL to get.
this.source = u;
| public void | setUseTimestamp(boolean v)If true, conditionally download a file based on the timestamp
of the local copy.
In this situation, the if-modified-since header is set so
that the file is only fetched if it is newer than the local
file (or there is no local file) This flag is only valid on
HTTP connections, it is ignored in other cases. When the flag
is set, the local copy of the downloaded file will also have
its timestamp set to the remote file time.
Note that remote files of date 1/1/1970 (GMT) are treated as
'no timestamp', and web servers often serve files with a
timestamp in the future by replacing their timestamp with that
of the current time. Also, inter-computer clock differences can
cause no end of grief.
useTimestamp = v;
| public void | setUsername(java.lang.String u)Username for basic auth.
this.uname = u;
| public void | setVerbose(boolean v)If true, show verbose progress information.
verbose = v;
|
|