diff --git a/proposal/sandbox/httptasks/docs/manual/OptionalTasks/httptasks.html b/proposal/sandbox/httptasks/docs/manual/OptionalTasks/httptasks.html
new file mode 100644
index 000000000..2c089d6b2
--- /dev/null
+++ b/proposal/sandbox/httptasks/docs/manual/OptionalTasks/httptasks.html
@@ -0,0 +1,429 @@
+
+
+Http Tasks
+
+
+Http Tasks
+
+Tasks do to make the basic HTTP requests: get, post, head, put, with authentication.
+There is also a task to configure the proxy settings of the http tasks.
+
+These tasks significantly extend the basic get task, but are split off into the optional section
+so that
+
+- The core ant file doesn't get so big
+
- this implementation can move to using an optional jar (HttpClient) to work around
+limitations of the HTTP support built in to the Java platform.
+
+
+Core Functionality and Parameters
+
+Common functionality to the core tasks tasks is
+
+
+
+- Ability to name the remote url which the target of the request.
+
+- Ability to name a local file as the local store of any returned
+content.
+
+- Ability to name a property as the local store of any returned
+content.
+
+- Ability to name a property to be set to "true" when a
+request succeeds.
+
+- The option to list a number of parameters, each with a name and a
+value. Some methods (HttpGet, HttpHead) attach these parameters to the
+stated url to generate the url to actually fetch. Others (HttpPost) send
+the parameters up in the standard representation of form data.
+
+- The option to state the authentication policy and then the username
+and password. Currently only basic authentication is used, which is
+utterly insecure except over an https link
+
+- A 'verbose' option which provides extra information and progess
+information during a download.
+
+- Timestamp control, using the usetimestamp flag. When set the
+timestamp of downloaded content is set to match that of the remote file
+(Java 1.2 or later only), and the local timestamp of the destination
+file (if it exists) used to set the if-modified-since header in the
+request, which will trigger optional download only.
+
+
+
+Parameters
+
+ The url parameter specifies the URL to access. The optional
+dest parameter specifies a destination to which the retrieved
+page will be written. The optional destinationproperty parameter
+specifies a name of a property to save the content to, instead of a
+property. If neither dest nor destinationproperty
+specified, the contents of the specified URL are discarded (this is
+useful when accessing the URL for the purpose of causing some action on
+the remote server).
+
+ When the verbose option is enabled, the task displays a '.' for every
+ 64 KB retrieved. If the blocksize parameter is adjusted then files are
+ uploaded or downloaded in a different size block from this, and progress markers
+ appear appropriately.
+
+The usetimestamp option enables you to control downloads so that
+the remote file is only fetched if newer than the local copy. If there
+is no local copy, the download always takes place. When a file is
+downloaded, the timestamp of the downloaded file is set to the remote
+timestamp, if the JVM is Java1.2 or later. NB: This timestamp facility
+only works on downloads using the HTTP protocol.
+
+The authtype, username, and password options enable support
+ for password protected pages. Currently only 'Basic' authentication is used,
+ which is notoriously insecure except over an encrypted https channel.
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ authtype |
+ the HTTP authentication protocol to use, none or basic. |
+ No |
+
+
+ blocksize |
+ size (in kilobytes) of the data block used for upload and
+ download. Default: 64.
+ Keep this to a multiple of the hard disk sector size for file IO performance. |
+ No |
+
+
+ dest |
+ the file where to store the retrieved file. |
+ No |
+
+
+ destinationProperty |
+ the name of a property to fill with the returned content.
+ Ignored if dest is set |
+ No |
+
+
+ failonerror |
+ stop the build if the request failed. default: true |
+ No |
+
+
+ password |
+ the password for authentication. |
+ No |
+
+
+ successProperty |
+ the name of a property to set to "true" if the
+ request succeeds.
+ Set failonerror to false for this to be of use. |
+ No |
+
+
+ url |
+ the URL from which to retrieve a file. |
+ Yes |
+
+
+ usecaches |
+ boolean to enable 'caching' of content during the fetch process.
+ default:false |
+ No |
+
+
+ useresponsecode |
+ boolean to enable success/failure to be determined by result
+ of the received response code. HTTP only. default=true. |
+ |
+
+
+ username |
+ the user name for authentication. |
+ No |
+
+
+ usetimestamp |
+ boolean flag to conditionally download a file based on the
+ timestamp of the local copy. HTTP only |
+ No |
+
+
+ verbose |
+ boolean flag to control progress information display. |
+ No |
+
+
+ The successProperty names a property which will be set to "true" if
+ the request was deemed successful. For any non-http protocol, success is defined
+ as the request completing. For http and https, success is defined as the request
+ completing, and the response code from the serving being one of the 'success'
+ values -any number between 200 and 299 inclusive. The usual HTTP_OK (200) is
+ therefore a success, as is HTTP_ACCEPTED (202). But failures such as BAD_REQUEST
+ (400) and the ubiquitous HTTP_NOT_FOUND (404) are most definately errors. So
+ an attempt to access a missing url may result 'failure',even though some content
+ was download (such as, perhaps, the 'file not found' text). If this is not what
+ you desire, then set useresponsecode="false" for the system
+ to interpret any data back as a success.
+
Parameters specified as nested elements
+
+param
+
+Specifies an HTTP request parameter to send as part of the request.
+For get and head request methods the parameters are
+encoded as part of the URL. For post request methods, the
+parameters are sent as the POST request data.
+
+
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ name |
+ the name of the request property to set. |
+ Yes |
+
+
+ value |
+ the value of the request property. You may alternatively
+ specify the value as text between the beginning and ending param tags. |
+ Yes |
+
+
+
+
+header
+
+Specifies an arbitrary HTTP request header that will be sent with the
+request.
+
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ name |
+ the name of the HTTP request header |
+ Yes |
+
+
+ value |
+ the value of the HTTP request header. You may alternatively
+ specify the value as text between the beginning and ending header tags. |
+ Yes |
+
+
+Quirky Limitations of java.net classes
+Multiple HTTP headers can with the same name can not be set, even
+though the protocol permits it. Java1.1 and Java 1.2 may permit multiple
+cookies to be set, but this behaviour is explicitly not supported on Java1.3,
+as someone went and change the code to stop this (Java bug ID #4242254).
+You need to set multiple cookies in one go and hope the far end can handle it
+
+Bug ID #4160499 covers another issue, to wit: some versions of Java throw
+exceptions when an error code is greater than 400 and the dest file isn't
+one of a few simple file types, but Java 1.2 and 1.3 do not. So there
+is no way to get the error text when a jsp page throws some exception.
+
+Also, although this isnt going to be filed until we have a short
+test case, but if you recieve a short response with less content than
+the content-length header promises, the library seems to silently
+reduce the content length header to match, which seems the wrong action.
+
+
+
+
+Description
+
+Accesses a URL to retrieve a file or to cause some action on the server.
+
+ This task should be preferred above the CVS task when doing
+ automated builds. CVS is significantly slower than loading a compressed archive
+ with http/ftp. This task will also retrieve content using other supported protocols,
+ such as ftp: and file:
+
All the attributes of httptask may be used. Note that a quirk of the implementation
+ of the http client in java makes it impossible to reliably fetch the response
+ details from any unsuccessful request against a URL which doesn't end in '.htm,.html
+ or .txt'. This means that if the task is used to compile jsp pages by issuing
+ request against them, the text details of any errors will not be picked up.
+
Examples
+
+ <httpget url="http://jakarta.apache.org/" dest="help/index.html"/>
+Fetches the index page of http://jakarta.apache.org/, and stores it in the
+ file help/index.html
.
+
+ <httpget src="http://jakarta.apache.org/builds/tomcat/nightly/ant.zip"
+ dest="optional.jar"
+ verbose="true"
+ usetimestamp="true"
+ >
+ <header name="Cookie" value="someid=43ff2b"/>
+ </httpget>
+ Retrieves the nightly ant build from the tomcat distribution, if the local
+ copy is missing or out of date. Uses the verbose option for progress information.
+ A cookie is supplied for the server's benefit.
+ <httpget url="https://www.pizzaservices.com/prices.jsp"
+ dest="pizza-prices.xml">
+ <param name="zipcode">57340</param>
+ <param name="pizza">pepperoni</param>
+ </httpget>
+Builds a URL by adding parameters ("?zipcode=57340&pizza=pepperoni")
+ to the base URL and then fetches the contents (fictional example)
+
+The http HEAD request is similar to the normal GET request , except it, by
+ definition, returns no content, just a success code and http headers. Accordingly,
+ the destination properties of the base class -dest and -, destinationpropertyname)
+ are not supported -any attempt to use them will result in a build failure. Note
+ also that the http and https protocols are the only protocols supported.
+
+HttpHead is useful for triggering server side actions, but note that many servers
+interpret a HEAD very differently from a GET. An HttpGet request with the
+return data discarded is often a more reliable approach.
+
+
+ Where head can be useful is in testing for the availability and reachability
+ of servers, such as in the following test for apache being reachable, which
+ sets a variable on success:-
+
+ <httphead url="http://www.apache.org/"
+ failonerror="false"
+ successproperty="reachable.apache"
+ />
+
+
+Note that sometimes a missing file on a mis-configured server still generates
+ a successful '200' response to a GET request -and returns a 'missing' file page,
+ but a HEAD request will reliably pick up the 'missing file' error.
+
+
+This implements the POST request. Supplied parameter data is turned into form
+ data and sent as the body of the request, rather than appended to the URL. If
+ a file to upload is specified instead, using uploadFile, the parameter
+ values are ignored. Instead the content type of the file is sent in the header
+ -based on the contentType attribute or what the java runtime thinks the
+ content type is based on the file extension. The file is uploaded.
+
+Like HttpGet, this command can return a content which can downloaded to a file,
+ to a property, or just ignored.
+
+This task adds two new attributes to the base set.
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ uploadFile |
+ a file to upload. when specified, all parameters
+ are ignored. |
+
+ no
+ |
+
+
+ contentType |
+ the type of the content (text/html, text/xml,
+ application/binary, etc). Only of relevance when a file is being uploaded,
+ and still optional in that case. |
+
+ no
+ |
+
+
+
+
+ <httppost url="http://www.example.com/servlet/docserver"
+ authtype="basic" username="joe" password="silly">
+ <param name="action" value="getdoc"/>
+ <param name="ISBN">038550120X</param>
+ <param name="pages">19-20</param>
+ <header name="Accept-Language" value="en-us"/>
+ </httppost>
+Accesses a server at www.foo.com, passing a request to some servlet asking it
+to retrieve several pages from a stored book. An HTTP header specifying
+acceptable languages for the returned contents is also sent. Basic
+authentication is used with a user name of "joe" and a password of
+"silly".
+
+
<httppost url="https://www.pizzaservices.com"
+ uploadFile="pizza-order.xml"
+ contentType="text/xml">
+
+Sends a pre-prepared order for a pizza to a pizza vendor accepting orders using
+ xml-rpc requests. (NB: fictional example)
+SetProxy
+This task configures the proxy settings for all http tasks which follow it
+ in the build. That includes the original Get task, but not the telnet and FTP
+ tasks. The proxy settings remain in place until changed or the build finishes,
+ and will also hold for other ant build files invoked and even non-forked java
+ invocations, and even URL resolutions of XML parsers running in the same JVM
+
+
+
+ Attribute |
+ Description |
+ Required |
+
+
+ proxyHost |
+ hostname of a web/ftp proxy server |
+
+ no
+ |
+
+
+ proxyPort |
+ integer; the port of the proxy server |
+
+ no
+ |
+
+
+ socksProxyHost |
+ hostname of a SOCKS4 proxy server |
+
+ no
+ |
+
+
+ socksProxyPort |
+ integer; port number of a SOCKS4 server (default=1080) |
+
+ no
+ |
+
+
+
+Turn off all proxies
+ <setproxy proxyhost="" socksProxyHost="" />
+Set web proxy to 'web-proxy:80'; do not make any changes to existing socks
+ settings (if any)
+ <setproxy proxyHost="web-proxy" proxyPort="80"/>
+Turn on socks
+ <setproxy socksProxyHost="socks-server" socksProxyPort="1080"/>
+Do nothing
+ <setproxy/>
+
+Copyright © 2000,2001 Apache Software Foundation. All rights
+Reserved.
+
+
+
+
+
+
+
+
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/Base64Encode.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/Base64Encode.java
new file mode 100644
index 000000000..40763e472
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/Base64Encode.java
@@ -0,0 +1,115 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+/**
+ * This code handles Base64 encoding for basic authentication
+ * and the like
+ *
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created 02 April 2001
+ */
+class Base64Encode {
+
+ /**
+ * the encode alphabet
+ */
+ private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
+
+
+ /**
+ * Encode a block of binary data as base64 as specified in RFC1521.
+ *
+ * @param data the binary data to encode.
+ * @return An array of characters that represent the data encoded
+ * as Base64
+ */
+ public char[] encodeBase64(byte[] data) {
+ char[] out = new char[((data.length + 2) / 3) * 4];
+
+ //
+ // 3 bytes encode to 4 chars. Output is always an even
+ // multiple of 4 characters.
+ //
+ for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
+ boolean quad = false;
+ boolean triple = false;
+ //convert to unsigned byte
+ int val = (0xFF & (int) data[i]);
+ val <<= 8;
+ if ((i + 1) < data.length) {
+ val |= (0xFF & (int) data[i + 1]);
+ triple = true;
+ }
+ val <<= 8;
+ if ((i + 2) < data.length) {
+ val |= (0xFF & (int) data[i + 2]);
+ quad = true;
+ }
+ out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
+ val >>= 6;
+ out[index + 2] = alphabet[(triple ? (val & 0x3F) : 64)];
+ val >>= 6;
+ out[index + 1] = alphabet[val & 0x3F];
+ val >>= 6;
+ out[index + 0] = alphabet[val & 0x3F];
+ }
+ return out;
+ }
+
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/ContentGuesser.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/ContentGuesser.java
new file mode 100644
index 000000000..a9a6bd3bd
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/ContentGuesser.java
@@ -0,0 +1,100 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.IOException;
+import java.net.*;
+
+/**
+ * this is a class to work around the fact a function I want (guessContentTypeFromName)
+ * is protected.
+ *
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+class ContentGuesser extends URLConnection {
+
+ /**
+ * stub Constructor for the ContentGuesser object
+ *
+ * @param url Description of Parameter
+ */
+ ContentGuesser(URL url) {
+ super(url);
+ }
+
+
+ /**
+ * this stub is needed for the build
+ *
+ * @exception IOException Description of Exception
+ */
+ public void connect()
+ throws IOException {
+ }
+
+
+ /**
+ * make a protected method public.
+ * This guesses file type from extension. It's ok for very
+ * well known types...
+ * @param filename file to guess type of
+ * @return what the system guessed
+ */
+ public static String guessContentType(String filename) {
+ return guessContentTypeFromName(filename);
+ }
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpAuthenticationStrategy.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpAuthenticationStrategy.java
new file mode 100644
index 000000000..d15852be7
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpAuthenticationStrategy.java
@@ -0,0 +1,88 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import org.apache.tools.ant.BuildException;
+import java.net.URLConnection;
+
+/**
+ * this interface is for use by classes which authenticate connections.
+ *
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created 20 March 2001
+ */
+
+public interface HttpAuthenticationStrategy {
+
+
+ /**
+ * Sets the AuthenticationHeader attribute of the HttpAuthStrategy
+ * object
+ *
+ * @param requestConnection The current request
+ * @param responseConnection any previous request, which can contain a
+ * challenge for the next round. Will often be null
+ * @param user the current user name
+ * @param password the current password
+ */
+ public void setAuthenticationHeader(URLConnection requestConnection,
+ URLConnection responseConnection,
+ String user, String password)
+ throws BuildException ;
+
+
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpBasicAuth.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpBasicAuth.java
new file mode 100644
index 000000000..553720e70
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpBasicAuth.java
@@ -0,0 +1,109 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.Get;
+
+
+/**
+ * this class implements basic auth, the one that shouldn't be used
+ * except over an encrypted link or trusted network.
+ *
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created 20 March 2001
+ */
+
+public class HttpBasicAuth implements HttpAuthenticationStrategy {
+
+
+ /**
+ * Sets the AuthenticationHeader attribute of the HttpAuthStrategy
+ * object
+ *
+ * @param requestConnection The current request
+ * @param responseConnection any previous request, which can contain a
+ * challenge for the next round. Will often be null
+ * @param user the current user name
+ * @param password the current password
+ */
+ public void setAuthenticationHeader(URLConnection requestConnection,
+ URLConnection responseConnection,
+ String username, String password)
+ throws BuildException {
+
+ if (username != null) {
+ password = username == null ? "" : password;
+ String encodeStr = username + ":" + password;
+ char[] encodedPass;
+ String encodedPassStr;
+
+ Base64Encode encoder = new Base64Encode();
+ encodedPass = encoder.encodeBase64(encodeStr.getBytes());
+ encodedPassStr= new String(encodedPass);
+ /* this uses the get task
+ Get.Base64Converter converter= new Get.Base64Converter();
+ encodedPassStr = converter.encode(encodeStr);
+ */
+ String authStr = "BASIC " +encodedPassStr;
+ requestConnection.setRequestProperty("Authorization", authStr);
+ }
+ }
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpDigestAuth.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpDigestAuth.java
new file mode 100644
index 000000000..eb597e859
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpDigestAuth.java
@@ -0,0 +1,100 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+
+
+/**
+ * this class implements basic auth, the one that shouldn't be used
+ * except over an encrypted link or trusted network.
+ *
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created 20 March 2001
+ */
+
+public class HttpDigestAuth implements HttpAuthenticationStrategy {
+
+
+ /**
+ * Sets the AuthenticationHeader attribute of the HttpAuthStrategy
+ * object
+ *
+ * @param requestConnection The current request
+ * @param responseConnection any previous request, which can contain a
+ * challenge for the next round. Will often be null
+ * @param user the current user name
+ * @param password the current password
+ */
+ public void setAuthenticationHeader(URLConnection requestConnection,
+ URLConnection responseConnection,
+ String username, String password)
+ throws BuildException {
+
+ if (username != null) {
+ password = username == null ? "" : password;
+ String encodeStr = username + ":" + password;
+ Base64Encode encoder = new Base64Encode();
+ char[] encodedPass = encoder.encodeBase64(encodeStr.getBytes());
+ String authStr = "BASIC " + new String(encodedPass);
+ requestConnection.setRequestProperty("Authorization", authStr);
+ }
+ }
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpGet.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpGet.java
new file mode 100644
index 000000000..a29c88a93
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpGet.java
@@ -0,0 +1,93 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+
+/**
+ * This class implements boring old HTTP1.0 get. It represents
+ * a refactoring of Get to HttpTask and then into a specific
+ * subclass. because almost everything is done by the parent,
+ * this class is almost completely empty
+ * @since ant1.5
+ * @author costin@dnt.ro
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+
+public class HttpGet extends HttpTask {
+
+ /**
+ * override of test
+ * @return true always
+ */
+
+ protected boolean areParamsAddedToUrl() {
+ return true;
+ }
+
+ /**
+ * this must be overridden by implementations
+ * to set the request method to GET, POST, whatever
+ * @return GET, obviously
+ */
+ public String getRequestMethod() {
+ return "GET";
+ }
+}
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpHead.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpHead.java
new file mode 100644
index 000000000..a87aad9cb
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpHead.java
@@ -0,0 +1,112 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+
+/**
+ * Head is a get with a different method and the notion of
+ * destination file missing. Why would anyone want to make a HEAD
+ * request? a) side effects on the server and b) polling for stuff
+ * @since ant1.5
+ * @author costin@dnt.ro
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+
+public class HttpHead extends HttpTask {
+
+ /**
+ * this must be overridden by implementations
+ * to set the request method to GET, POST, whatever
+ * @return HEAD always
+ */
+ public String getRequestMethod() {
+ return "HEAD";
+ }
+
+ /**
+ * override of test
+ * @return true always
+ */
+
+ protected boolean areParamsAddedToUrl() {
+ return true;
+ }
+
+ /**
+ * add a check for all the destination settings being
+ * null; nothing else makes sense for a HEAD.
+ *
+ * @return true if everything is fine. false if we have encountered
+ * problems but arent allowed to fail on an error,
+ * @exception BuildException only throw this when the failonerror
+ * flag is true
+ */
+
+ protected void verifyArguments()
+ throws BuildException {
+ BuildException trouble = null;
+ if(getDest() != null || getDestinationProperty() !=null) {
+ throw new BuildException("destination properties must not be defined for a HEAD request");
+ }
+ super.verifyArguments();
+ }
+
+}
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpPost.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpPost.java
new file mode 100644
index 000000000..959a25f84
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpPost.java
@@ -0,0 +1,224 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+
+/**
+ * this class does post of form content or raw files. you can have one
+ * or the other -as soon as a file is specified all the other properties
+ * are dropped on the floor.
+ * a file post will have content type determined from the extension, you can
+ * override it
+ * @since ant1.5
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+
+public class HttpPost extends HttpTask {
+
+ /**
+ * file to upload. Null is ok
+ */
+
+ protected File postFile=null;
+
+ /**
+ * set the file to post
+ */
+ public void setUploadFile(File postFile) {
+ this.postFile=postFile;
+ }
+
+ /**
+ * query the post file
+ * @return the file or null for 'not defined'
+ */
+ public File getUploadFile() {
+ return postFile;
+ }
+
+ /**
+ * content type. ignored when the file is null,
+ * and even then we guess it if aint specified
+ */
+
+ private String contentType;
+
+ /**
+ * set the content type. Recommended if a file is being uploaded
+ */
+ public void setContentType(String contentType) {
+ this.contentType=contentType;
+ }
+
+ /**
+ * query the content type
+ * @return the content type or null for 'not defined'
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * override of test
+ * @return false always
+ */
+
+ protected boolean areParamsAddedToUrl() {
+ return false;
+ }
+
+ /**
+ * this override of the base connect pumps
+ * up the parameter vector as form data
+ *
+ * @param connection where to connect to
+ * @exception BuildException build trouble
+ * @exception IOException IO trouble
+ */
+ protected URLConnection doConnect(URLConnection connection)
+ throws BuildException, IOException {
+
+ if(postFile==null) {
+ return doConnectFormPost(connection);
+ }
+ else {
+ return doConnectFilePost(connection);
+ }
+ }
+
+ /**
+ * feed up the parameter vector as form data
+ *
+ * @param connection where to connect to
+ * @exception BuildException build trouble
+ * @exception IOException IO trouble
+ */
+ protected URLConnection doConnectFormPost(URLConnection connection)
+ throws BuildException, IOException {
+
+ log("Posting data as a form",Project.MSG_VERBOSE);
+ // Create the output payload
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream(256);
+ PrintWriter out = new PrintWriter(byteStream);
+ writePostData(out);
+ out.flush();
+ out.close();
+ byte[] data=byteStream.toByteArray();
+ //send it
+
+ return doConnectWithUpload(connection,
+ "application/x-www-form-urlencoded",
+ byteStream.size(),
+ new ByteArrayInputStream(data));
+ }
+
+ /**
+ * feed up the data file
+ *
+ * @param connection where to connect to
+ * @exception BuildException build trouble
+ * @exception IOException IO trouble
+ */
+ protected URLConnection doConnectFilePost(URLConnection connection)
+ throws BuildException, IOException {
+ int size=(int)postFile.length();
+ log("Posting file "+postFile,Project.MSG_VERBOSE);
+ InputStream instream=new FileInputStream(postFile);
+ String type=contentType;
+ if(type==null) {
+ type=ContentGuesser.guessContentType(postFile.getName());
+ }
+ return doConnectWithUpload(connection,
+ type,
+ size,
+ instream);
+ }
+
+
+ /**
+ * write out post data in form mode
+ *
+ * @param out Description of Parameter
+ */
+ protected void writePostData(PrintWriter out) {
+ HttpRequestParameter param;
+ Vector params=getRequestParameters();
+ for (int i = 0; i < params.size(); i++) {
+ if (i > 0) {
+ out.print('&');
+ }
+ param = (HttpRequestParameter) params.get(i);
+ out.print(param.toString());
+ log("parameter : "+param.toString(),Project.MSG_DEBUG);
+ }
+ }
+
+ /**
+ * this must be overridden by implementations
+ * to set the request method to GET, POST, whatever
+ * @return the method string
+ */
+ public String getRequestMethod() {
+ return "POST";
+ }
+
+
+}
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpRequestParameter.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpRequestParameter.java
new file mode 100644
index 000000000..566a236ce
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpRequestParameter.java
@@ -0,0 +1,141 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+import java.net.URLEncoder;
+
+/**
+ * This class is used to store name-value pairs for request parameters
+ * and headers
+ *
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+
+public class HttpRequestParameter {
+
+ /**
+ * request name
+ */
+ private String name;
+
+ /**
+ * request value
+ */
+ private String value;
+
+
+ /**
+ * Sets the Name attribute of the request parameter
+ *
+ * @param name The new Name value
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ /**
+ * Sets the Value attribute of the request parameter
+ *
+ * @param value The new Value value
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+
+ /**
+ * Gets the Name attribute of the request parameter
+ *
+ * @return The Name value
+ */
+ public String getName() {
+ return name;
+ }
+
+
+ /**
+ * Gets the Value attribute of the request parameter
+ *
+ * @return The Value
+ */
+ public String getValue() {
+ return value;
+ }
+
+
+ /**
+ * Adds a feature to the Text attribute of the request parameter
+ *
+ * @param text The feature to be added to the Text attribute
+ */
+ public void addText(String text) {
+ this.value = text;
+ }
+
+
+ /**
+ * simple stringifier returning name and value encoded for use in HTTP requests
+ *
+ * @return a string for informational purposes
+ */
+ public String toString() {
+ return URLEncoder.encode(getName())+
+ '='+URLEncoder.encode(getValue());
+ }
+
+}
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpTask.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpTask.java
new file mode 100644
index 000000000..faf229777
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpTask.java
@@ -0,0 +1,1145 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+/**
+ * This class is a foundational class for all the tasks which implement
+ * http methods. To implement a subclass you *must* provide
+ * an implementation of getRequestMethod(). Consider also
+ * stating the parameter policy (areParamsAddedToUrl()) and
+ * then, if needed, overriding doConnect, and the onConnected(),
+ * OnDownloadFinished() methods.
+ * @since ant1.5
+ * @author costin@dnt.ro
+ * @author matth@pobox.com Matt Humphrey
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+public abstract class HttpTask extends Task {
+
+ /**
+ * flag to control action on execution trouble
+ */
+ protected boolean failOnError=true;
+
+ /**
+ * this sets the size of the buffer and the hash for download
+ */
+
+ protected int blockSize = 64;
+
+ /**
+ * property to set on success
+ */
+
+ protected String successProperty;
+
+ /**
+ * source URL. required
+ */
+ private String source;
+
+ /**
+ * destination for download
+ */
+ private File dest;
+ /**
+ * verbose flag gives extra information
+ */
+ private boolean verbose = false;
+
+ /**
+ * timestamp based download flag. off by default
+ */
+ private boolean useTimestamp = false;
+
+ /**
+ * authorization mechanism in use.
+ */
+ private int authType = AUTH_NONE;
+
+ /**
+ * username for authentication
+ */
+ private String username;
+
+ /**
+ * password for authentication
+ */
+ private String password;
+
+ /**
+ * parameters to send on a request
+ */
+ private Vector params = new Vector();
+
+ /**
+ * headers to send on a request
+ */
+ private Vector headers = new Vector();
+
+ /**
+ * cache policy
+ */
+ private boolean usecaches = false;
+
+ /**
+ * the name of a destination property
+ */
+
+ private String destinationPropname = null;
+
+ /***
+ * a flag to control whether or not response codes
+ * are acted on
+ */
+ private boolean useResponseCode=true;
+
+ /**
+ * No authentication specified
+ */
+ public final static int AUTH_NONE = 0;
+
+ /**
+ * basic 'cleartext' authentication
+ */
+ public final static int AUTH_BASIC = 1;
+
+ /**
+ * digest auth. not actually supported but present for completeness
+ */
+ public final static int AUTH_DIGEST = 2;
+
+
+ /**
+ * turn caching on or off. only relevant for protocols and methods
+ * which are cacheable (HEAD, GET) on http
+ *
+ * @param usecaches The new UseCaches value
+ */
+ public void setUseCaches(boolean usecaches) {
+ this.usecaches = usecaches;
+ }
+
+ /**
+ * turn caching on or off. only relevant for protocols and methods
+ * which are cacheable (HEAD, GET) on http
+ *
+ * @param usecaches The new UseCaches value
+ */
+ public void setUseResponseCode(boolean useResponseCodes ) {
+ this.useResponseCode = useResponseCode ;
+ }
+
+
+ /**
+ * Set the URL.
+ *
+ * @param u URL for the file.
+ */
+ public void setURL(String u) {
+ this.source = u;
+ }
+
+
+ /**
+ * the local destination for any response. this can be null for 'dont
+ * download'
+ *
+ * @param dest Path to file.
+ */
+ public void setDest(File dest) {
+ this.dest = dest;
+ }
+
+/**
+ * the local destination for any response. this can be null for 'dont
+ * download'
+ *
+ * @param dest Path to file.
+ */
+ public void setDestinationProperty(String name) {
+ this.destinationPropname = name;
+ }
+
+
+ /**
+ * Be verbose, if set to " true
".
+ *
+ * @param verbose The new Verbose value
+ */
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+
+ /**
+ * set fail on error flag
+ *
+ * @param b The new FailOnError value
+ */
+ public void setFailOnError(boolean b) {
+ failOnError = b;
+ }
+
+
+ /**
+ * Use timestamps, if set to " true
".
+ *
+ * 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 usetimestamp The new UseTimestamp value
+ */
+ public void setUseTimestamp(boolean usetimestamp) {
+ if (project.getJavaVersion() != Project.JAVA_1_1) {
+ this.useTimestamp = usetimestamp;
+ }
+ else {
+ log("usetimestamp is not supported on java 1.1", Project.MSG_WARN);
+ }
+ }
+
+
+ /**
+ * Sets the Authtype attribute of the HttpTask object REVISIT/REFACTOR
+ *
+ * @param type The new Authtype value
+ */
+ public void setAuthtype(AuthMethodType type) {
+ this.authType=type.mapValueToNumber();
+ }
+
+
+ /**
+ * Sets the Username used for authentication. setting the username
+ * implicitly turns authentication on.
+ *
+ * @param username The new Username value
+ */
+ public void setUsername(String username) {
+ this.username = username;
+ if (authType == AUTH_NONE) {
+ authType = AUTH_BASIC;
+ }
+ }
+
+
+ /**
+ * Sets the Password attribute of the HttpTask object
+ *
+ * @param password The new Password value
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+
+ /**
+ * set a variable to be set in the event of success
+ *
+ * @param successProperty The new SuccessProperty value
+ */
+ public void setSuccessProperty(String successProperty) {
+ this.successProperty = successProperty;
+ }
+
+ /**
+ * get block size (kb)
+ */
+
+ public int getBlockSize() {
+ return blockSize;
+ }
+
+ /**
+ * set the new block size for download
+ * @param the new value (in kilobytes)
+ */
+ public void setBlockSize(int blocksize) {
+ this.blockSize=blockSize;
+ }
+
+
+ /**
+ * query cache policy
+ *
+ * @return The UseCaches value
+ */
+ public boolean getUseCaches() {
+ return usecaches;
+ }
+
+
+ /**
+ * query fail on error flag
+ *
+ * @return The FailFailOnError value
+ */
+ public boolean getFailOnError() {
+ return failOnError;
+ }
+
+
+ /**
+ * get the username
+ *
+ * @return current username or null for 'none'
+ */
+ public String getUsername() {
+ return username;
+ }
+
+
+ /**
+ * get the password
+ *
+ * @return current password or null for 'none'
+ */
+ public String getPassword() {
+ return password;
+ }
+
+
+ /**
+ * @return The RemoteURL value
+ */
+ public String getURL() {
+ return source;
+ }
+
+
+ /**
+ * access parameters
+ *
+ * @return The RequestParameters value
+ */
+ public Vector getRequestParameters() {
+ return params;
+ }
+
+
+ /**
+ * accessor of success property name
+ *
+ * @return The SuccessProperty value
+ */
+ public String getSuccessProperty() {
+ return successProperty;
+ }
+
+ /**
+ * accessor of destination property name
+ *
+ * @return The destination value
+ */
+ public String getDestinationProperty() {
+ return destinationPropname;
+ }
+
+ /**
+ * accessor of destination
+ *
+ * @return Thedestination
+ */
+ public File getDest() {
+ return dest;
+ }
+
+
+ /**
+ * if the user wanted a success property, this is it. of course, it
+ * is only relevant if failonerror=false
+ *
+ * @return Description of the Returned Value
+ */
+
+ public void noteSuccess() {
+ if (successProperty != null && successProperty.length() > 0) {
+ getProject().setProperty(successProperty, "true");
+ }
+ }
+
+
+ /**
+ * Does the work.
+ * @todo extract content length header and use it to verify
+ * completeness of download
+ * @exception BuildException Thrown in unrecoverable error.
+ */
+ public void execute()
+ throws BuildException {
+
+ //check arguments, will bail out if there
+ //was trouble
+ verifyArguments();
+
+ //set up the URL connection
+ URL url = buildURL();
+
+ try {
+
+ //now create a connection
+ URLConnection connection = url.openConnection();
+
+ //set caching option to whatever
+ connection.setUseCaches(getUseCaches());
+
+ //set the timestamp option if flag is set and
+ //the local file actually exists.
+ long localTimestamp = getTimestamp();
+ if (localTimestamp != 0) {
+ if (verbose) {
+ Date t = new Date(localTimestamp);
+ log("local file date : " + t.toString());
+ }
+ connection.setIfModifiedSince(localTimestamp);
+ }
+
+ // Set auth header, if specified
+ //NB: verifyArguments will already have checked that you can't
+ //have a null username with a non-null strategy.
+ HttpAuthenticationStrategy authStrategy=getAuthStrategy();
+ if (authStrategy != null) {
+ authStrategy.setAuthenticationHeader(connection,null,username,password);
+ }
+
+ // Set explicitly specified request headers
+ HttpRequestParameter header;
+ for (int i = 0; i < headers.size(); i++) {
+ header = (HttpRequestParameter) headers.get(i);
+ connection.setRequestProperty(header.getName(), header.getValue());
+ }
+
+ //cast to an http connection if we can,
+ //then set the request method pulled from the subclass
+ String method=getRequestMethod();
+ HttpURLConnection httpConnection = null;
+ if (connection instanceof HttpURLConnection) {
+ httpConnection = (HttpURLConnection) connection;
+ httpConnection.setRequestMethod(method);
+ }
+ log("making "+method+" to "+url);
+
+ //call self or subclass for the connect.
+ //the connection object may change identity at this point.
+ connection=doConnect(connection);
+
+ //then provide a bit of overridable post processing for the fun of it
+ if (!onConnected(connection)) {
+ return;
+ }
+
+ //repeat the cast.
+ if (connection instanceof HttpURLConnection) {
+ httpConnection = (HttpURLConnection) connection;
+ }
+ if(httpConnection != null) {
+ // check for a 304 result (HTTP only) when we set the timestamp
+ // earlier on (A fractional performance tweak)
+ if (localTimestamp != 0) {
+ if (getResponseCode(httpConnection) == 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("Local file is up to date - so nothing was downloaded");
+ noteSuccess();
+ return;
+ }
+ }
+
+ }
+
+
+ //get the input stream
+ InputStream is = getInputStream(connection);
+
+ //bail out if the input stream isn't valid at this point
+ //again, though we should have got to this point earlier.
+
+ if (is == null) {
+ log("Can't get " + url, Project.MSG_ERR);
+ if (getFailOnError()) {
+ return;
+ }
+ throw new BuildException("Can't reach URL");
+ }
+
+ //pick a file or null stream for saving content
+ OutputStream out = null;
+ if (dest != null) {
+ log("Saving output to "+dest,Project.MSG_DEBUG);
+ out = new FileOutputStream(dest);
+ }
+ else {
+ if(destinationPropname!=null) {
+ //save contents to a property
+ log("Saving output to property "+destinationPropname,
+ Project.MSG_DEBUG);
+ out=new ByteArrayOutputStream(blockSize * 1024);
+ }
+ else {
+ //discard everything
+ out = new NullOutputStream();
+ }
+ }
+
+ //get content length
+ //do it this way instead of calling getContentLength() because
+ //that way is sporadically unreliable (length is downgraded to
+ //size of small packets)
+ int contentLength=connection.getHeaderFieldInt("Content-Length",-1);
+ int bytesRead=0;
+
+ //now start download.
+ byte[] buffer = new byte[blockSize * 1024];
+ int length;
+
+ while ((length = is.read(buffer)) >= 0 &&
+ (contentLength==-1 || bytesRead-1 && bytesRead!=contentLength) {
+ failureString="Incomplete download -Expected "+contentLength
+ +"received "+bytesRead+" bytes";
+ }
+ else {
+
+ //finally clean anything up.
+ //http requests have their response code checked, and only
+ //those in the success range are deemed successful.
+ if (httpConnection != null && useResponseCode) {
+ int statusCode=httpConnection.getResponseCode();
+ if(statusCode <200 || statusCode >299) {
+ failureString="Server error code "+statusCode+" received";
+ }
+ }
+ }
+
+ //check for an error message
+ if(failureString==null) {
+ noteSuccess();
+ }
+ else {
+ if(failOnError)
+ throw new BuildException(failureString);
+ else
+ log(failureString,Project.MSG_ERR);
+ }
+
+ }
+ catch (IOException ioe) {
+ log("Error performing "+getRequestMethod() +" on " + url +
+ " : "+ioe.toString(), Project.MSG_ERR);
+ if (failOnError) {
+ throw new BuildException(ioe);
+ }
+ }
+ }
+
+ /**
+ * show a progress character
+ * @todo this doesn't work in shell wrappers
+ */
+
+ protected void showProgressChar(char c) {
+ System.out.write(c);
+ }
+
+
+ /**
+ * Adds a form / request parameter.
+ *
+ * @param param The feature to be added to the HttpRequestParameter
+ * attribute
+ */
+ public void addParam(HttpRequestParameter param) {
+ params.add(param);
+ }
+
+
+ /**
+ * Adds an HTTP request header.
+ *
+ * @param header The feature to be added to the Header attribute
+ */
+ public void addHeader(HttpRequestParameter header) {
+ headers.add(header);
+ }
+
+
+ /**
+ * this must be overridden by implementations to set the request method
+ * to GET, POST, whatever NB: this method only gets called for an
+ * http request
+ *
+ * @return the method string
+ */
+ protected abstract String getRequestMethod();
+
+
+ /**
+ * determine the timestamp to use if the flag is set and the local
+ * file actually exists.
+ *
+ * @return 0 for 'no timestamp', a number otherwhise
+ */
+
+ protected long getTimestamp() {
+ long timestamp = 0;
+ if (useTimestamp && dest != null && dest.exists()) {
+ timestamp = dest.lastModified();
+ }
+ else {
+ timestamp = 0;
+ }
+ return timestamp;
+ }
+
+
+ /**
+ * ask for authentication details. An empty string means 'no auth'
+ *
+ * @return an RFC2617 auth string
+ */
+
+ protected String getAuthenticationString() {
+ // Set authorization eader, if specified
+ if (authType == AUTH_BASIC && username != null) {
+ password = password == null ? "" : password;
+ String encodeStr = username + ":" + password;
+ Base64Encode encoder = new Base64Encode();
+ char[] encodedPass = encoder.encodeBase64(encodeStr.getBytes());
+ String authStr = "BASIC " + new String(encodedPass);
+ return authStr;
+ }
+ else {
+ return null;
+ }
+ }
+
+
+ /**
+ * this overridable method verifies that all the params are valid
+ * the base implementation checks for remote url validity and if the
+ * destination is not null, write access to what mustnt be a directory.
+ * sublcasses can call the base class as well as check their own data
+ *
+ * @return true if everything is fine. false if we have encountered
+ * problems but arent allowed to fail on an error,
+ * @exception BuildException only throw this when the failonerror
+ * flag is true
+ */
+
+ protected void verifyArguments()
+ throws BuildException {
+ BuildException trouble = null;
+ //check remote params -but only create an exception, not throw it
+ if (getURL() == null) {
+ throw new BuildException("target URL missing");
+ }
+ //check destination parameters -but only create an exception, not throw it
+ if (dest != null && dest.exists()) {
+ if (dest.isDirectory()) {
+ throw new BuildException("The specified destination is a directory");
+ }
+ else if (!dest.canWrite()) {
+ throw new BuildException("Can't write to " + dest.getAbsolutePath());
+ }
+ }
+ //check auth policy
+ if(authType!=AUTH_NONE && username==null) {
+ throw new BuildException("no username defined to use with authorisation");
+ }
+ }
+
+
+ /**
+ * set the timestamp of a named file to a specified time. prints a
+ * warning on java1.1
+ *
+ * @param file Description of Parameter
+ * @param timemillis Description of Parameter
+ * @exception BuildException Thrown in unrecoverable error. Likely
+ * this comes from file access failures.
+ */
+ protected void touchFile(File file, long timemillis)
+ throws BuildException {
+ getProject().setFileLastModified(file, timemillis);
+ }
+
+
+ /**
+ * build a URL from the source url, maybe with parameters attached
+ *
+ * @return Description of the Returned Value
+ * @exception BuildException Description of Exception
+ */
+ protected URL buildURL()
+ throws BuildException {
+ String urlbase = getURL();
+ try {
+ if (areParamsAddedToUrl()) {
+ urlbase = parameterizeURL();
+ }
+ return new URL(urlbase);
+ }
+ catch (MalformedURLException e) {
+ throw new BuildException("Invalid URL");
+ }
+ }
+
+
+ /**
+ * take a url and add parameters to it. if there are no parameters
+ * the base url string is returned
+ *
+ * @return a string to be used for URL creation
+ * @exception BuildException Description of Exception
+ */
+ protected String parameterizeURL()
+ throws BuildException {
+ //return immediately if there are no parameters
+ if (params.size() == 0) {
+ return getURL();
+ }
+
+ StringBuffer buf = new StringBuffer(getURL());
+ //this devious little line code recognises a parameter string already
+ //in the source url, and if so doesnt add a new one
+ buf.append(source.indexOf('?') == -1 ? '?' : '&');
+ HttpRequestParameter param;
+
+ //run through the parameter list, encode the name/value pairs and
+ //append them to the list
+ for (int i = 0; i < params.size(); i++) {
+ if (i > 0) {
+ buf.append('&');
+ }
+ param = (HttpRequestParameter) params.get(i);
+ buf.append(param.toString());
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * query for the request wanting parameters on the url default is
+ * true, subclasses may want to change
+ *
+ * @return true if a url should have params attached.
+ */
+
+ protected boolean areParamsAddedToUrl() {
+ return true;
+ }
+
+ /**
+ * get the auth policy
+ * a null return value means 'no policy chosen'
+ * @return current authorisation strategy or null
+ */
+
+ protected HttpAuthenticationStrategy getAuthStrategy() {
+ HttpAuthenticationStrategy strategy=null;
+ switch(authType) {
+ case AUTH_BASIC:
+ strategy=new HttpBasicAuth();
+ break;
+
+ case AUTH_DIGEST:
+ //TODO
+ break;
+
+ case AUTH_NONE:
+ default:
+ break;
+ }
+ return strategy;
+
+ }
+
+ /**
+ * this method opens the connection. It can recognise a 401 error code
+ * and in digest auth will then open a new connection with the
+ * supplied nonce encoded. That is why it can return a new
+ * connection object.
+ * @todo handle digest auth
+ * @param connection where to connect to
+ * @exception BuildException build trouble
+ * @exception IOException IO trouble
+ * @return a new connection. This may be different than the old one
+ */
+
+ protected URLConnection makeConnectionWithAuthHandling(URLConnection connection)
+ throws BuildException, IOException {
+ log("Connecting to "+connection.toString(),Project.MSG_DEBUG);
+ connection.connect();
+ URLConnection returnConnection=connection;
+ log("connected",Project.MSG_DEBUG);
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection httpConnection = (HttpURLConnection) connection;
+ if(getResponseCode(httpConnection)==HttpURLConnection.HTTP_UNAUTHORIZED
+ && authType==AUTH_DIGEST) {
+ //TODO auth failure. in digest mode we can make a new auth
+ //duplicating all the settings then reconnect
+ //and return it
+ log("Digest authentication needed but not yet supported",Project.MSG_DEBUG);
+ }
+ }
+
+ return returnConnection;
+ }
+
+
+ /**
+ * by making a query for a value from the connection, we force the
+ * client code to actually do the http request and go into input mode.
+ * so next we can check for trouble.
+ */
+ void probeConnection (HttpURLConnection connection) {
+ String probe=connection.getHeaderFieldKey(0);
+ }
+
+
+ /**
+ * get a response from a connection request.
+ * This code fixes a problem found in HttpURLConnection, that
+ * any attempt to get the response code would trigger a FileNotFound
+ * @see
+ * BugParade details
+ * "If the requested file does not exist, and ends in .html, .htm, .txt or /, you
+ * will get the error stream with no exception thrown. If the file does not end
+ * like any of these you can catch the exception and immediately request it again
+ * to get the error stream. The response code can be obtained with
+ * getResponseCode()."
+ * which means, to really get the response code you need to ask twice.
+ * @param connection the current http link
+ * @return whatever we get back
+ * @throws IOException if anything other than file not found gets thrown,
+ * and even a FileNotFound exception if that gets thrown too many times.
+ */
+ protected int getResponseCode(HttpURLConnection connection)
+ throws IOException {
+ //force the creation of the input stream
+ //(which is what HttpURLConnection.getResponseCode() does internally
+ //that way the bug handler code is only needed once.
+
+ //probeConnection(connection);
+ IOException swallowed=null;
+ boolean caught=false;
+ int response=0;
+ for (int attempts = 0; attempts < 5; attempts++) {
+ try {
+ response = connection.getResponseCode();
+ caught=true;
+ break;
+ }
+ catch (FileNotFoundException ex) {
+ log("Swallowed FileNotFoundException in getResponseCode",
+ Project.MSG_VERBOSE);
+ log(ex.toString(),Project.MSG_DEBUG);
+ swallowed=ex;
+ }
+ }
+ if(!caught && swallowed!=null) {
+ throw swallowed;
+ }
+ return response;
+ }
+
+ /**
+ * get an input stream from a connection
+ * This code tries to fix a problem found in HttpURLConnection, that
+ * any attempt to get the response code would trigger a FileNotFound
+ * BugParade ID 4160499 :
+ *
+ * "If the requested file does not exist, and ends in .html, .htm, .txt or /, you
+ * will get the error stream with no exception thrown. If the file does not end
+ * like any of these you can catch the exception and immediately request it again
+ * to get the error stream. The response code can be obtained with
+ * getResponseCode()."
+ *
+ * which means, to really get the response code you need to ask twice. More to the point
+ * this handling is not consistent across JVMs: on java 1.3 you can ask as often as you like
+ * but you are not going to get the input stream on a JSP page when it has some 500 class error.
+ * @param connection the current link
+ * @return the input stream.
+ * @throws IOException if anything other than file not found gets thrown,
+ * and even a FileNotFound exception if that gets thrown too many times.
+ */
+
+ protected InputStream getInputStream(URLConnection connection)
+ throws IOException {
+ IOException swallowed=null;
+ InputStream instream=null;
+ for (int attempts = 0; attempts < 5; attempts++) {
+ try {
+ instream = connection.getInputStream();
+ break;
+ }
+ catch (FileNotFoundException ex) {
+ log("Swallowed IO exception in getInputStream",
+ Project.MSG_VERBOSE);
+ log(ex.toString(),Project.MSG_DEBUG);
+ swallowed=ex;
+ }
+ }
+ if(instream==null && swallowed!=null) {
+ throw swallowed;
+ }
+ return instream;
+ }
+
+
+
+ /**
+ * this method is inteded for overriding. it is called when connecting
+ * to a URL, and the base implementation just calls connect() on the
+ * parameter. any subclass that wants to pump its own datastream up
+ * (like post) must override this
+ *
+ * @param connection where to connect to
+ * @exception BuildException build trouble
+ * @exception IOException IO trouble
+ */
+
+ protected URLConnection doConnect(URLConnection connection)
+ throws BuildException, IOException {
+ return makeConnectionWithAuthHandling(connection);
+ }
+
+
+ /**
+ * this is a method for upload centric post-like requests
+ *
+ * @param connection who we talk to
+ * @param contentType Description of Parameter
+ * @param contentLength Description of Parameter
+ * @param content Description of Parameter
+ * @exception IOException something went wrong with the IO
+ */
+ protected URLConnection doConnectWithUpload(URLConnection connection,
+ String contentType, int contentLength,
+ InputStream content)
+ throws IOException {
+
+ log("uploading " + contentLength + " bytes of type " + contentType,
+ Project.MSG_VERBOSE);
+ //tell the connection we are in output mode
+ connection.setDoOutput(true);
+
+
+ // Set content length and type headers
+ connection.setRequestProperty("Content-Length", String.valueOf(contentLength));
+ connection.setRequestProperty("Content-Type", contentType);
+ //todo: add auth handling
+ //connection=makeConnectionWithAuthHandling(connection);
+ connection.connect();
+ OutputStream toServer = connection.getOutputStream();
+
+ //create a buffer which is the smaller of
+ //the content length and the block size (in KB)
+ int buffersize=blockSize*1024;
+ if(contentLength 0) {
+ int read = content.read(buffer);
+ log("block of "+read,Project.MSG_DEBUG);
+ toServer.write(buffer, 0, read);
+ remaining -= read;
+ if (verbose) {
+ showProgressChar('^');
+ }
+ }
+ if (verbose) {
+ showProgressChar('\n');
+ }
+ log("upload completed",Project.MSG_DEBUG);
+ return connection;
+ }
+
+ /**
+ * internal event handler called after a connect can throw an exception
+ * or return false for an immediate exit from the process
+ *
+ * @param connection the now open connection
+ * @return true if the execution is to continue
+ * @exception BuildException Description of Exception
+ */
+ protected boolean onConnected(URLConnection connection)
+ throws BuildException {
+ return true;
+ }
+
+
+ /**
+ * internal event handler called after the download is complete the
+ * code can still bail out at this point, and the connection may contain
+ * headers of interest. can throw an exception or return false for
+ * an immediate exit from the process
+ *
+ * @param connection the now open connection
+ * @return true if the execution is to continue
+ * @exception BuildException Description of Exception
+ */
+ protected boolean onDownloadFinished(URLConnection connection)
+ throws BuildException {
+ return true;
+ }
+
+
+ /**
+ * Enumerated attribute for "authType" with the value "basic" (note,
+ * eventually we can add "digest" authentication)
+ *
+ * @author matt_h@pobox.com;
+ * @created March 17, 2001
+ */
+ public static class AuthMethodType extends EnumeratedAttribute {
+ /**
+ * Gets the possible values of authorisation supported
+ *
+ * @return The Values value
+ */
+ public String[] getValues() {
+ return new String[]{"none", "basic","digest"};
+ }
+
+ /**
+ * lookup from value to a numeric value. defaults to 0, basic-auth
+ * @param choice string selection
+ * @return selected value
+ */
+ public int mapValueToNumber() {
+ String choice=getValue();
+ int value=0;
+ String[] values=getValues();
+ for(int i=0;i.
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * simple output stream which discards all write requests this should
+ * really be part of java.io, as it is sporadically invaluable
+ *
+ * @author slo
+ * @created March 17, 2001
+ */
+public class NullOutputStream extends OutputStream {
+
+ /**
+ * discard all incoming bytes
+ *
+ * @param b byte to write
+ * @exception IOException never throwable in this subclass
+ */
+ public void write(int b)
+ throws IOException {
+ }
+
+
+ /**
+ * discard all incoming bytes
+ *
+ * @param b byte array
+ * @exception IOException never throwable in this subclass
+ */
+ public void write(byte[] b)
+ throws IOException {
+ }
+
+
+ /**
+ * discard all incoming bytes
+ *
+ * @param b byte array
+ * @param off starting offset
+ * @param len length to write
+ * @exception IOException never throwable in this subclass
+ */
+ public void write(byte[] b,
+ int off,
+ int len)
+ throws IOException {
+ }
+
+}
+
+
diff --git a/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/SetProxy.java b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/SetProxy.java
new file mode 100644
index 000000000..933dddaeb
--- /dev/null
+++ b/proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/SetProxy.java
@@ -0,0 +1,240 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2001 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
+ * .
+ */
+
+package org.apache.tools.ant.taskdefs.optional.http;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.lang.reflect.*;
+import org.apache.tools.ant.*;
+
+/**
+ * proxy definition task. This allows all web tasks in the build file
+ * executed after this task to access the web through a proxy server
+ *
+ * @author steve_l@iseran.com Steve Loughran
+ * @created March 17, 2001
+ */
+
+public class SetProxy extends Task {
+
+ /**
+ * proxy details
+ */
+ protected String proxyHost = null;
+
+ /**
+ * name of proxy port
+ */
+ protected int proxyPort = 80;
+
+ /**
+ * socks host.
+ */
+ private String socksProxyHost = null;
+ /**
+ * socks proxy port. 1080 is the default
+ */
+ private int socksProxyPort = 1080;
+
+
+
+ /**
+ * set a proxy host. the port should be defined too
+ *
+ * @param hostname the new proxy hostname
+ */
+ public void setProxyHost(String hostname) {
+ proxyHost = hostname;
+ }
+
+
+ /**
+ * set the proxy port number.
+ *
+ * @param port port number of the proxy
+ */
+ public void setProxyPort(int port) {
+ proxyPort = port;
+ }
+
+
+ /**
+ * accessor to proxy hostname
+ *
+ * @return the hostname or null
+ */
+
+ public String getProxyHost() {
+ return proxyHost;
+ }
+
+
+ /**
+ * accessor to proxy hostname
+ *
+ * @return the port number
+ */
+
+ public int getProxyPort() {
+ return proxyPort;
+ }
+
+
+ /**
+ * Set the SocksProxyHost attribute
+ *
+ * @param host The new SocksProxyHost value
+ */
+ public void setSocksProxyHost(String host) {
+ this.socksProxyHost = host;
+ }
+
+
+ /**
+ * Set the SocksProxyPort attribute
+ *
+ * @param port The new SocksProxyPort value
+ */
+ public void setSocksProxyPort(int port) {
+ this.socksProxyPort = port;
+ }
+
+
+
+ /**
+ * if the proxy port and host settings are not null, then the settings
+ * get applied these settings last beyond the life of the object and
+ * apply to all network connections
+ *
+ * @return true if the settings were applied
+ */
+
+ public void applyWebProxySettings() {
+ boolean settingsChanged=false;
+ Properties prop = System.getProperties();
+ if (getProxyHost() != null) {
+ log("Setting proxy to " + getProxyHost() + ":" + getProxyPort(),
+ Project.MSG_VERBOSE);
+ prop.put("http.proxyHost", getProxyHost());
+ prop.put("http.proxyPort", String.valueOf(getProxyPort()));
+ prop.put("https.proxyHost", getProxyHost());
+ prop.put("https.proxyPort", String.valueOf(getProxyPort()));
+ prop.put("ftp.proxyHost", getProxyHost());
+ prop.put("ftp.proxyPort", String.valueOf(getProxyPort()));
+ settingsChanged=true;
+ }
+
+ //socks
+ if (socksProxyHost != null) {
+ log("Setting proxy to " + getProxyHost() + ":" + getProxyPort(),
+ Project.MSG_VERBOSE);
+ prop.put("socksProxyHost", socksProxyHost);
+ prop.put("socksProxyPort", Integer.toString(socksProxyPort));
+ settingsChanged=true;
+ }
+
+ //for Java1.1 we need to tell the system that the settings are new
+ if(settingsChanged && project.getJavaVersion() == Project.JAVA_1_1) {
+ prop.put("http.proxySet", "true");
+ sun.net.www.http.HttpClient.resetProperties();
+ }
+ legacyResetProxySettingsCall();
+ }
+
+
+ /**
+ * make a call to sun.net.www.http.HttpClient.resetProperties();
+ * this is only needed for java 1.1; reflection is used to stop the compiler
+ * whining, and in case cleanroom JVMs dont have the class.
+ * @return Description of the Returned Value
+ * @returns
+ */
+
+ protected boolean legacyResetProxySettingsCall() {
+ try {
+ Class c = Class.forName("sun.net.www.http.HttpClient");
+ Method reset = c.getMethod("resetProperties", null);
+ reset.invoke(null, null);
+ return true;
+ }
+ catch (ClassNotFoundException cnfe) {
+ return false;
+ }
+ catch (NoSuchMethodException e) {
+ return false;
+ }
+ catch (IllegalAccessException e) {
+ return false;
+ }
+ catch (InvocationTargetException e) {
+ return false;
+ }
+
+ }
+
+
+ /**
+ * Does the work.
+ *
+ * @exception BuildException Thrown in unrecoverable error.
+ */
+ public void execute()
+ throws BuildException {
+ applyWebProxySettings();
+ }
+
+}
+