You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by Richard Beton <ri...@roke.co.uk> on 2002/10/16 23:19:40 UTC

Get task - new proxy support

According to open-source mantra, if you have an itch, scratch it! I am 
new to this list so forgive me if I've posted to the wrong place.

Here's my enhanced version of the Get task with new support for proxy 
servers. I based my changes on the the CVS HEAD which I got via the HTTP 
server.

I have enhanced the documentation page also.

Enjoy!
Rick :-)


Re: Get task - new proxy support

Posted by Richard Beton <ri...@roke.co.uk>.
Steve Loughran wrote:

>rich,
>
>while we value itch scratching, what is so wrong with <setproxy> that it
>doesnt work for you?
>  
>
...Ahem! Didn't spot that. Oops...

What's wrong? ... possibly the fact that it's not mentioned in the Get 
documentation?

I had a quick look at the Setproxy.java source code. It always sets the 
same HTTP and FTP proxy, although I guess that's not really a problem.

May I suggest the following improvement to the documentation: add 
mention and a hyperlink to the setproxy page from the following tasks:

    Get
    Javadoc
    Splash (needs hyperlink)

and the following conditions:

    Http
    Socket

and possibly also:

    DescriptorHandler in EjbJar
    VAJRemoteUtil

I note that the Splash task already mentions Setproxy (without a 
hyperlink though) with regard to its own (deprecated) proxy parameters.

Rick :-)





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Get task - new proxy support

Posted by Steve Loughran <st...@iseran.com>.
rich,

while we value itch scratching, what is so wrong with <setproxy> that it
doesnt work for you?

----- Original Message -----
From: "Richard Beton" <ri...@roke.co.uk>
To: <an...@jakarta.apache.org>
Sent: Wednesday, October 16, 2002 2:19 PM
Subject: Get task - new proxy support


> According to open-source mantra, if you have an itch, scratch it! I am
> new to this list so forgive me if I've posted to the wrong place.
>
> Here's my enhanced version of the Get task with new support for proxy
> servers. I based my changes on the the CVS HEAD which I got via the HTTP
> server.
>
> I have enhanced the documentation page also.
>
> Enjoy!
> Rick :-)
>
>


----------------------------------------------------------------------------
----


> /*
>  * The Apache Software License, Version 1.1
>  *
>  * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
>  * reserved.
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  *
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  *
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in
>  *    the documentation and/or other materials provided with the
>  *    distribution.
>  *
>  * 3. The end-user documentation included with the redistribution, if
>  *    any, must include the following acknowlegement:
>  *       "This product includes software developed by the
>  *        Apache Software Foundation (http://www.apache.org/)."
>  *    Alternately, this acknowlegement may appear in the software itself,
>  *    if and wherever such third-party acknowlegements normally appear.
>  *
>  * 4. The names "The Jakarta Project", "Ant", and "Apache Software
>  *    Foundation" must not be used to endorse or promote products derived
>  *    from this software without prior written permission. For written
>  *    permission, please contact apache@apache.org.
>  *
>  * 5. Products derived from this software may not be called "Apache"
>  *    nor may "Apache" appear in their names without prior written
>  *    permission of the Apache Group.
>  *
>  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>  * SUCH DAMAGE.
>  * ====================================================================
>  *
>  * This software consists of voluntary contributions made by many
>  * individuals on behalf of the Apache Software Foundation.  For more
>  * information on the Apache Software Foundation, please see
>  * <http://www.apache.org/>.
>  */
>
> package org.apache.tools.ant.taskdefs;
>
> import java.io.File;
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.net.HttpURLConnection;
> import java.net.URL;
> import java.net.URLConnection;
> import java.net.Socket;
> import java.net.SocketAddress;
> import java.net.UnknownHostException;
> 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.
>  * 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.
>  *
>  * @author costin@dnt.ro
>  * @author gg@grtmail.com (Added Java 1.1 style HTTP basic auth)
>  * @author rdb@roke.co.uk (Added proxy configuration options)
>  *
>  * @since Ant 1.1
>  *
>  * @ant.task category="network"
>  */
> public class Get extends Task {
>
>     private static final String HTTP_PROXY_HOST      = "http.proxyHost";
>     private static final String HTTP_PROXY_PORT      = "http.proxyPort";
>     private static final String HTTP_NON_PROXY_HOSTS =
"http.nonProxyHosts";
>     private static final String FTP_PROXY_HOST       = "ftp.proxyHost";
>     private static final String FTP_PROXY_PORT       = "ftp.proxyPort";
>     private static final String FTP_NON_PROXY_HOSTS  =
"ftp.nonProxyHosts";
>
>     private URL source; // required
>     private File dest; // required
>     private boolean verbose = false;
>     private boolean useTimestamp = false; //off by default
>     private boolean ignoreErrors = false;
>     private String uname = null;
>     private String pword = null;
>     private String proxyHost = null;
>     private String proxyPort = null;
>     private String nonProxyHosts = null;
>
>
>     /**
>      * Does the work.
>      *
>      * @exception BuildException Thrown in unrecoverable error.
>      */
>     public void execute() throws BuildException {
>         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());
>         }
>
>         if (source.getProtocol().equals("http")) {
>             if (proxyPort != null) {
>                 System.setProperty( HTTP_PROXY_PORT, proxyPort );
>             }
>             if (nonProxyHosts != null) {
>                 System.setProperty( HTTP_NON_PROXY_HOSTS, nonProxyHosts );
>             }
>             if (proxyHost != null) {
>                 testProxyServer (proxyHost,
>                     System.getProperty(HTTP_PROXY_PORT),
>                     source.getDefaultPort(), "http");
>                 System.setProperty( HTTP_PROXY_HOST, proxyHost );
>             }
>         }
>         else if (source.getProtocol().equals("ftp")) {
>             if (proxyPort != null) {
>                 System.setProperty( FTP_PROXY_PORT, proxyPort );
>             }
>             if (nonProxyHosts != null) {
>                 System.setProperty( FTP_NON_PROXY_HOSTS, nonProxyHosts );
>             }
>             if (proxyHost != null) {
>                 testProxyServer (proxyHost,
>                     System.getProperty(FTP_PROXY_PORT),
>                     source.getDefaultPort(), "ftp");
>                 System.setProperty( FTP_PROXY_HOST, proxyHost );
>             }
>         }
>
>         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());
>                 }
>
>                 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 {
>                     sun.misc.BASE64Encoder encoder =
>                         (sun.misc.BASE64Encoder)
>
Class.forName("sun.misc.BASE64Encoder").newInstance();
>                     encoding = encoder.encode (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);
>             }
>
>             //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
>                     //didnt
>                     log("Not modified - so not downloaded");
>                     return;
>                 }
>                 // 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);
>                     }
>                 }
>
>             }
>
>             //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) dont 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);
>                 }
>             }
>             if (is == null) {
>                 log("Can't get " + source + " to " + dest);
>                 if (ignoreErrors) {
>                     return;
>                 }
>                 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;
>
>                 while ((length = is.read(buffer)) >= 0) {
>                     fos.write(buffer, 0, length);
>                     if (verbose) {
>                         System.out.print(".");
>                     }
>                 }
>                 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();
>                 }
>             }
>
>             //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);
>                 }
>             }
>         } catch (IOException ioe) {
>             log("Error getting " + source + " to " + dest);
>             if (ignoreErrors) {
>                 return;
>             }
>             throw new BuildException(ioe, getLocation());
>         }
>     }
>
>     /**
>      * Validates the existence of the proxy server by attempting
>      * to connect to it.
>      * @param host the host name
>      * @param port the port number, or null if not defined
>      * @param defaultPort the default number
>      */
>     private void testProxyServer (String host, String port,
>                                   int defaultPort, String protocol)
>     throws BuildException {
>         int portNo = defaultPort;
>         if (port != null) {
>             try {
>                 portNo = Integer.parseInt( port );
>             } catch (NumberFormatException e) {
>                 throw new BuildException("Expected an integer port
number",
>                     e, getLocation());
>             }
>         }
>         try {
>             // just open and close the socket
>             new Socket (host, portNo).close();
>         }
>         catch (UnknownHostException uhe) {
>             throw new BuildException(
>                 "Cannot connect via unknown proxy "+host+".",
>                 uhe, getLocation());
>         }
>         catch (IOException ioe) {
>             throw new BuildException(
>                 "Connection via proxy "+protocol+"://"+host+":"+portNo+"
failed.",
>                 ioe, getLocation());
>         }
>     }
>
>     /**
>      * Set the URL to get.
>      *
>      * @param u URL for the file.
>      */
>     public void setSrc(URL u) {
>         this.source = u;
>     }
>
>     /**
>      * Where to copy the source file.
>      *
>      * @param dest Path to file.
>      */
>     public void setDest(File dest) {
>         this.dest = dest;
>     }
>
>     /**
>      * If true, show verbose progress information.
>      *
>      * @param v if "true" then be verbose
>      */
>     public void setVerbose(boolean v) {
>         verbose = v;
>     }
>
>     /**
>      * If true, log errors but do not treat as fatal.
>      *
>      * @param v if "true" then don't report download errors up to ant
>      */
>     public void setIgnoreErrors(boolean v) {
>         ignoreErrors = v;
>     }
>
>     /**
>      * If true, conditionally download a file based on the timestamp
>      * of the local copy.
>      *
>      * <p>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.</p>
>      *
>      * <p>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.</p>
>      * @param v "true" to enable file time fetching
>      */
>     public void setUseTimestamp(boolean v) {
>         if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
>             useTimestamp = v;
>         }
>     }
>
>
>     /**
>      * Username for basic auth.
>      *
>      * @param u username for authentication
>      */
>     public void setUsername(String u) {
>         this.uname = u;
>     }
>
>     /**
>      * password for the basic authentication.
>      *
>      * @param p password for authentication
>      */
>     public void setPassword(String p) {
>         this.pword = p;
>     }
>
>     /**
>      * Proxy server name
>      *
>      * @param h proxy host
>      * @see http://java.sun.com/j2se/1.4.1/docs/guide/net/properties.html
>      */
>     public void setProxyHost(String h) {
>         this.proxyHost = h;
>     }
>
>     /**
>      * Proxy server port
>      *
>      * @param p proxy port
>      * @see http://java.sun.com/j2se/1.4.1/docs/guide/net/properties.html
>      */
>     public void setProxyPort(String p) {
>         this.proxyPort = p;
>     }
>
>     /**
>      * Non proxy host list, separated by vertical bars.
>      *
>      * @param h HTTP non proxy hosts
>      * @see http://java.sun.com/j2se/1.4.1/docs/guide/net/properties.html
>      */
>     public void setNonProxyHosts(String h) {
>         this.nonProxyHosts = h;
>     }
>
>
>     /*********************************************************************
>     * BASE 64 encoding of a String or an array of bytes.
>     *
>     * Based on RFC 1421.
>     *
>     * @author
>     *    Unknown
>     * @author
>     *    <a HREF="gg@grtmail.com">Gautam Guliani</a>
>     *********************************************************************/
>
>     class  Base64Converter {
>
>         public final char [ ]  alphabet = {
>             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',   //  0 to  7
>             'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',   //  8 to 15
>             'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',   // 16 to 23
>             'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',   // 24 to 31
>             'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',   // 32 to 39
>             'o', 'p', 'q', 'r', 's', 't', 'u', 'v',   // 40 to 47
>             'w', 'x', 'y', 'z', '0', '1', '2', '3',   // 48 to 55
>             '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
>
>
>         public String  encode(String  s) {
>             return encode (s.getBytes());
>         }
>
>         public String  encode(byte[ ] octetString) {
>             int  bits24;
>             int  bits6;
>
>             char [ ]  out
>               = new char[((octetString.length - 1) / 3 + 1) * 4];
>
>             int outIndex = 0;
>             int i = 0;
>
>             while ((i + 3) <= octetString.length) {
>                 // store the octets
>                 bits24 = (octetString[i++] & 0xFF) << 16;
>                 bits24 |= (octetString[i++] & 0xFF) << 8;
>
>                 bits6 = (bits24 & 0x00FC0000) >> 18;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6 = (bits24 & 0x0003F000) >> 12;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6  = (bits24 & 0x00000FC0) >> 6;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6 = (bits24 & 0x0000003F);
>                 out[outIndex++] = alphabet[bits6];
>             }
>
>             if (octetString.length - i == 2) {
>                 // store the octets
>                 bits24 = (octetString[i] & 0xFF) << 16;
>                 bits24 |= (octetString[i + 1] & 0xFF) << 8;
>                 bits6 = (bits24 & 0x00FC0000) >> 18;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6 = (bits24 & 0x0003F000) >> 12;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6 = (bits24 & 0x00000FC0) >> 6;
>                 out[outIndex++] = alphabet[bits6];
>
>                 // padding
>                 out[outIndex++] = '=';
>             } else if (octetString.length - i == 1) {
>                 // store the octets
>                 bits24 = (octetString[i] & 0xFF) << 16;
>                 bits6 = (bits24 & 0x00FC0000) >> 18;
>                 out[outIndex++] = alphabet[bits6];
>                 bits6 = (bits24 & 0x0003F000) >> 12;
>                 out[outIndex++] = alphabet[ bits6 ];
>
>                 // padding
>                 out[outIndex++] = '=';
>                 out[outIndex++] = '=';
>             }
>
>             return new String(out);
>         }
>      }
> }
>
>


----------------------------------------------------------------------------
----


> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>