@@ -30,11 +30,19 @@ import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Resources;
import org.apache.tools.ant.types.resources.URLProvider;
import org.apache.tools.ant.types.resources.URLResource;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.FileUtils;
/**
@@ -53,12 +61,12 @@ public class Get extends Task {
private static final int BIG_BUFFER_SIZE = 100 * 1024;
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
private static final int REDIRECT_LIMIT = 25;
private static final String HTTP = "http";
private static final String HTTPS = "https";
private URL source; // required
private File dest; // required
private Resources sources = new Resources();
private File destination ; // required
private boolean verbose = false;
private boolean useTimestamp = false; //off by default
private boolean ignoreErrors = false;
@@ -68,6 +76,7 @@ public class Get extends Task {
private int numberRetries = NUMBER_RETRIES;
private boolean skipExisting = false;
private boolean httpUseCaches = true; // on by default
private Mapper mapperElement = null;
/**
* Does the work.
@@ -75,6 +84,36 @@ public class Get extends Task {
* @exception BuildException Thrown in unrecoverable error.
*/
public void execute() throws BuildException {
checkAttributes();
for (Iterator iter = sources.iterator(); iter.hasNext(); ) {
Resource r = (Resource) iter.next();
URLProvider up = (URLProvider) r.as(URLProvider.class);
URL source = up.getURL();
File dest = destination;
if (destination.isDirectory()) {
if (mapperElement != null) {
String path = source.getPath();
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
int slash = path.lastIndexOf("/");
if (slash > -1) {
path = path.substring(slash + 1);
}
dest = new File(destination, path);
} else {
FileNameMapper mapper = mapperElement.getImplementation();
String[] d = mapper.mapFileName(r.getName());
if (d == null || d.length != 1) {
log("skipping " + r + " - mapper can't handle it",
Project.MSG_WARN);
continue;
}
dest = new File(destination, d[0]);
}
}
//set up logging
int logLevel = Project.MSG_INFO;
@@ -85,13 +124,14 @@ public class Get extends Task {
//execute the get
try {
doGet(logLevel, progress);
doGet(source, dest, logLevel, progress);
} catch (IOException ioe) {
log("Error getting " + source + " to " + dest);
if (!ignoreErrors) {
throw new BuildException(ioe, getLocation());
}
}
}
}
/**
@@ -106,10 +146,41 @@ public class Get extends Task {
* @throws IOException for network trouble
* @throws BuildException for argument errors, or other trouble when ignoreErrors
* is false.
* @deprecated only gets the first configured resource
*/
public boolean doGet(int logLevel, DownloadProgress progress)
throws IOException {
checkAttributes();
for (Iterator iter = sources.iterator(); iter.hasNext(); ) {
Resource r = (Resource) iter.next();
URLProvider up = (URLProvider) r.as(URLProvider.class);
URL source = up.getURL();
return doGet(source, destination, logLevel, progress);
}
/*NOTREACHED*/
return false;
}
/**
* make a get request, with the supplied progress and logging info.
*
* All the other config parameters like ignoreErrors are set at
* the task level.
* @param source the URL to get
* @param dest the target file
* @param logLevel level to log at, see {@link 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 {@link #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.
* @since Ant 1.8.0
*/
public boolean doGet(URL source, File dest, int logLevel,
DownloadProgress progress)
throws IOException {
if (dest.exists() && skipExisting) {
log("Destination already exists (skipping): "
@@ -137,7 +208,8 @@ public class Get extends Task {
hasTimestamp = true;
}
GetThread getThread = new GetThread(hasTimestamp, timestamp, progress,
GetThread getThread = new GetThread(source, dest,
hasTimestamp, timestamp, progress,
logLevel);
getThread.setDaemon(true);
getProject().registerThreadTask(getThread, this);
@@ -169,32 +241,55 @@ public class Get extends Task {
* Check the attributes.
*/
private void checkAttributes() {
if (source == null) {
throw new BuildException("src attribute is required", getLocation());
if (sources.size() == 0) {
throw new BuildException("at least one source is required",
getLocation());
}
for (Iterator iter = sources.iterator(); iter.hasNext(); ) {
Object up = ((Resource) iter.next()).as(URLProvider.class);
if (up == null) {
throw new BuildException("Only URLProvider resources are"
+ " supported", getLocation());
}
}
if (dest == null) {
if (destination == 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 (destination.exists() && sources.size() > 1
&& !destination.isDirectory()) {
throw new BuildException("The specified destination is not a"
+ " directory",
getLocation());
}
if (dest.exists() && !dest.canWrite()) {
throw new BuildException("Can't write to " + dest.getAbsolutePath(),
getLocation());
if (destination.exists() && !destination.canWrite()) {
throw new BuildException("Can't write to "
+ destination.getAbsolutePath(),
getLocation());
}
if (sources.size() > 1 && !destination.exists()) {
destination.mkdirs();
}
}
/**
* Set the URL to get.
* Set an URL to get.
*
* @param u URL for the file.
*/
public void setSrc(URL u) {
this.source = u;
add(new URLResource(u));
}
/**
* Adds URLs to get.
* @since Ant 1.8.0
*/
public void add(ResourceCollection rc) {
sources.add(rc);
}
/**
@@ -203,7 +298,7 @@ public class Get extends Task {
* @param dest Path to file.
*/
public void setDest(File dest) {
this.dest = dest;
this.destination = dest;
}
/**
@@ -265,13 +360,6 @@ public class Get extends Task {
this.pword = p;
}
/**
* Provide this for Backward Compatibility.
*/
protected static class Base64Converter
extends org.apache.tools.ant.util.Base64Converter {
}
/**
* The time in seconds the download is allowed to take before
* being terminated.
@@ -318,6 +406,37 @@ public class Get extends Task {
this.httpUseCaches = httpUseCache;
}
/**
* Define the mapper to map source to destination files.
* @return a mapper to be configured.
* @exception BuildException if more than one mapper is defined.
* @since Ant 1.8.0
*/
public Mapper createMapper() throws BuildException {
if (mapperElement != null) {
throw new BuildException("Cannot define more than one mapper",
getLocation());
}
mapperElement = new Mapper(getProject());
return mapperElement;
}
/**
* Add a nested filenamemapper.
* @param fileNameMapper the mapper to add.
* @since Ant 1.8.0
*/
public void add(FileNameMapper fileNameMapper) {
createMapper().add(fileNameMapper);
}
/**
* Provide this for Backward Compatibility.
*/
protected static class Base64Converter
extends org.apache.tools.ant.util.Base64Converter {
}
/**
* Interface implemented for reporting
* progess of downloading.
@@ -414,6 +533,8 @@ public class Get extends Task {
private class GetThread extends Thread {
private final URL source;
private final File dest;
private final boolean hasTimestamp;
private final long timestamp;
private final DownloadProgress progress;
@@ -427,7 +548,10 @@ public class Get extends Task {
private URLConnection connection;
private int redirections = 0;
GetThread(boolean h, long t, DownloadProgress p, int l) {
GetThread(URL source, File dest,
boolean h, long t, DownloadProgress p, int l) {
this.source = source;
this.dest = dest;
hasTimestamp = h;
timestamp = t;
progress = p;
@@ -445,7 +569,7 @@ public class Get extends Task {
}
private boolean get() throws IOException, BuildException {
connection = openConnection(source);
if (connection == null)
@@ -461,7 +585,7 @@ public class Get extends Task {
if (downloadSucceeded && useTimestamp) {
updateTimeStamp();
}
return downloadSucceeded;
}
@@ -493,7 +617,7 @@ public class Get extends Task {
}
}
return true;
}
@@ -640,7 +764,7 @@ public class Get extends Task {
FILE_UTILS.setFileLastModified(dest, remoteTimestamp);
}
}
/**
* Has the download completed successfully?
*