From 9b4609e4bafb5cbd2e882546dc718ad2970dd307 Mon Sep 17 00:00:00 2001 From: Steve Loughran Date: Tue, 27 Nov 2001 22:43:44 +0000 Subject: [PATCH] Stuck the http task set (get, head, post, setproxy) into the sandbox. All need to move to httpclient for a better user experience, except maybe setproxy which is ready to roll as is. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270035 13f79535-47bb-0310-9956-ffa450edef68 --- .../docs/manual/OptionalTasks/httptasks.html | 429 ++++++ .../taskdefs/optional/http/Base64Encode.java | 115 ++ .../optional/http/ContentGuesser.java | 100 ++ .../http/HttpAuthenticationStrategy.java | 88 ++ .../taskdefs/optional/http/HttpBasicAuth.java | 109 ++ .../optional/http/HttpDigestAuth.java | 100 ++ .../ant/taskdefs/optional/http/HttpGet.java | 93 ++ .../ant/taskdefs/optional/http/HttpHead.java | 112 ++ .../ant/taskdefs/optional/http/HttpPost.java | 224 ++++ .../optional/http/HttpRequestParameter.java | 141 ++ .../ant/taskdefs/optional/http/HttpTask.java | 1145 +++++++++++++++++ .../optional/http/NullOutputStream.java | 106 ++ .../ant/taskdefs/optional/http/SetProxy.java | 240 ++++ 13 files changed, 3002 insertions(+) create mode 100644 proposal/sandbox/httptasks/docs/manual/OptionalTasks/httptasks.html create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/Base64Encode.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/ContentGuesser.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpAuthenticationStrategy.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpBasicAuth.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpDigestAuth.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpGet.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpHead.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpPost.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpRequestParameter.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/HttpTask.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/NullOutputStream.java create mode 100644 proposal/sandbox/httptasks/src/main/org/apache/tools/ant/taskdefs/optional/http/SetProxy.java 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 +

    +
  1. The core ant file doesn't get so big +
  2. 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

+ +
    + +
  1. Ability to name the remote url which the target of the request.
  2. + +
  3. Ability to name a local file as the local store of any returned +content.
  4. + +
  5. Ability to name a property as the local store of any returned +content.
  6. + +
  7. Ability to name a property to be set to "true" when a +request succeeds.
  8. + +
  9. 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.
  10. + +
  11. 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
  12. + +
  13. A 'verbose' option which provides extra information and progess +information during a download.
  14. + +
  15. 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.
  16. + +
+ +

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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
authtypethe HTTP authentication protocol to use, none or basic.No
blocksizesize (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
destthe file where to store the retrieved file.No
destinationPropertythe name of a property to fill with the returned content. + Ignored if dest is setNo
failonerrorstop the build if the request failed. default: trueNo
passwordthe password for authentication.No
successPropertythe name of a property to set to "true" if the + request succeeds.
+ Set failonerror to false for this to be of use.
No
urlthe URL from which to retrieve a file.Yes
usecachesboolean to enable 'caching' of content during the fetch process. + default:falseNo
useresponsecodeboolean to enable success/failure to be determined by result + of the received response code. HTTP only. default=true. 
usernamethe user name for authentication.No
usetimestampboolean flag to conditionally download a file based on the + timestamp of the local copy. HTTP onlyNo
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.

+ + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
namethe name of the request property to set.Yes
valuethe 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.

+ + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
namethe name of the HTTP request headerYes
valuethe 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. + + + +

HttpGet

+

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)

+

HttpHead

+

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.

+

HttpPost

+ +

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.

+ + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
uploadFilea 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 +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
proxyHosthostname of a web/ftp proxy server +
no
+
proxyPort integer; the port of the proxy server +
no
+
socksProxyHosthostname of a SOCKS4 proxy server +
no
+
socksProxyPortinteger; 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(); + } + +} +