FileDocCategorySizeDatePackage
Get.javaAPI DocApache Ant 1.7013407Wed Dec 13 06:16:24 GMT 2006org.apache.tools.ant.taskdefs

Get

public 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.
since
Ant 1.1
ant.task
category="network"

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
Constructors Summary
Methods Summary
public booleandoGet(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.

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.

        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 voidexecute()
Does the work.

exception
BuildException Thrown in unrecoverable error.




                  
         

        //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 voidsetDest(java.io.File dest)
Where to copy the source file.

param
dest Path to file.

        this.dest = dest;
    
public voidsetIgnoreErrors(boolean v)
If true, log errors but do not treat as fatal.

param
v if "true" then don't report download errors up to ant

        ignoreErrors = v;
    
public voidsetPassword(java.lang.String p)
password for the basic authentication.

param
p password for authentication

        this.pword = p;
    
public voidsetSrc(java.net.URL u)
Set the URL to get.

param
u URL for the file.

        this.source = u;
    
public voidsetUseTimestamp(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.

param
v "true" to enable file time fetching

        useTimestamp = v;
    
public voidsetUsername(java.lang.String u)
Username for basic auth.

param
u username for authentication

        this.uname = u;
    
public voidsetVerbose(boolean v)
If true, show verbose progress information.

param
v if "true" then be verbose

        verbose = v;