| @@ -170,6 +170,29 @@ plain text' authentication is used. This is only secure over an HTTPS link. | |||
| name will be skipped. If the returned name is a relative path, it | |||
| will be considered relative to the <em>dest</em> attribute.</p> | |||
| <h4>header</h4> | |||
| <p>Any arbitrary number of HTTP headers can be added to a request.<br/> | |||
| The attributes of a nested <pre><header/> </pre> node are as follow: | |||
| <p></p> | |||
| <table width="60%" border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name or key of this header.</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">value</td> | |||
| <td valign="top">The value to assign to the.</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h3>Examples</h3> | |||
| <pre> <get src="http://ant.apache.org/" dest="help/index.html"/></pre> | |||
| <p>Gets the index page of http://ant.apache.org/, and stores it in the file <code>help/index.html</code>.</p> | |||
| @@ -234,6 +257,17 @@ the <a href="input.html">input task</a> to query for a password.</p> | |||
| <url url="http://ant.apache.org/faq.html"/> | |||
| </get> | |||
| </pre> | |||
| <p>With custom HTTP headers</p> | |||
| <pre> | |||
| <get src="http://ant.apache.org/index.html" dest="downloads"> | |||
| <header name="header1" value=="headerValue1" /> | |||
| <header name="header2" value=="headerValue2" /> | |||
| <header name="header3" value=="headerValue3" /> | |||
| </get> | |||
| </pre> | |||
| <p>Gets the index and FAQ pages of http://ant.apache.org/, and stores | |||
| them in the directory <code>downloads</code> which will be created if | |||
| necessary.</p> | |||
| @@ -98,6 +98,34 @@ | |||
| </fail> | |||
| </target> | |||
| <target name="testTwoHeaders"> | |||
| <get src="http://www.apache.org/" dest="get.tmp"> | |||
| <header name="header1" value="header1Value"/> | |||
| <header name="header2" value="header2Value"/> | |||
| </get> | |||
| </target> | |||
| <target name="testEmptyHeaders"> | |||
| <get src="http://www.apache.org/" dest="get.tmp"> | |||
| <header name="" value="headerValue"/> | |||
| <header name="header2" value=""/> | |||
| </get> | |||
| </target> | |||
| <target name="testDuplicateHeaderNames"> | |||
| <get src="http://www.apache.org/" dest="get.tmp"> | |||
| <header name="header1" value="headerValue1"/> | |||
| <header name="header1" value="headerValue2"/> | |||
| <header name="header1" value="headerValue3"/> | |||
| </get> | |||
| </target> | |||
| <target name="testHeaderSpacesTrimmed"> | |||
| <get src="http://www.apache.org/" dest="get.tmp"> | |||
| <header name=" header1 " value=" headerValue1 "/> | |||
| </get> | |||
| </target> | |||
| <target name="cleanup"> | |||
| <delete> | |||
| <fileset dir="${basedir}" includes="get.tmp" /> | |||
| @@ -36,6 +36,7 @@ import org.apache.tools.ant.MagicNames; | |||
| import org.apache.tools.ant.Main; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.taskdefs.email.Header; | |||
| import org.apache.tools.ant.types.Mapper; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| @@ -44,6 +45,8 @@ import org.apache.tools.ant.types.resources.URLProvider; | |||
| import org.apache.tools.ant.types.resources.URLResource; | |||
| import org.apache.tools.ant.util.FileNameMapper; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import java.util.LinkedHashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * Gets a particular file from a URL source. | |||
| @@ -90,6 +93,9 @@ public class Get extends Task { | |||
| DEFAULT_AGENT_PREFIX + "/" | |||
| + Main.getShortAntVersion()); | |||
| // Store headers as key/value pair without duplicate in keyz | |||
| private Map<String, String> headers = new LinkedHashMap<String, String>(); | |||
| /** | |||
| * Does the work. | |||
| * | |||
| @@ -482,6 +488,35 @@ public class Get extends Task { | |||
| tryGzipEncoding = b; | |||
| } | |||
| /** | |||
| * Add a nested header | |||
| * @param header to be added | |||
| * | |||
| */ | |||
| public void addConfiguredHeader(Header header) { | |||
| if (header != null) { | |||
| String key = trimToNull(header.getName()); | |||
| String value = trimToNull(header.getValue()); | |||
| if (key != null && value != null) { | |||
| this.headers.put(key, value); | |||
| } | |||
| } | |||
| } | |||
| private String trimToNull(String inputString) { | |||
| if (inputString == null) { | |||
| return null; | |||
| } | |||
| inputString = inputString.trim(); | |||
| if ("".equals(inputString)) { | |||
| return null; | |||
| } | |||
| return inputString; | |||
| } | |||
| /** | |||
| * Define the mapper to map source to destination files. | |||
| * @return a mapper to be configured. | |||
| @@ -726,6 +761,14 @@ public class Get extends Task { | |||
| connection.setRequestProperty("Accept-Encoding", GZIP_CONTENT_ENCODING); | |||
| } | |||
| if (!headers.isEmpty()) { | |||
| for (final Map.Entry<String, String> header : headers.entrySet()) { | |||
| //we do not log the header value as it may contain sensitive data like passwords | |||
| log(String.format("Adding header '%s' ", header.getKey())); | |||
| connection.setRequestProperty(header.getKey(), header.getValue()); | |||
| } | |||
| } | |||
| if (connection instanceof HttpURLConnection) { | |||
| ((HttpURLConnection) connection) | |||
| .setInstanceFollowRedirects(false); | |||
| @@ -19,7 +19,9 @@ | |||
| package org.apache.tools.ant.taskdefs.email; | |||
| /** | |||
| * Class representing a generic e-mail header. | |||
| * Class representing a generic key-value header. | |||
| * TODO: This should be moved out of the email package | |||
| * | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Header { | |||
| @@ -18,6 +18,7 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.AntAssert; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.BuildFileRule; | |||
| import org.junit.After; | |||
| @@ -25,6 +26,7 @@ import org.junit.Before; | |||
| import org.junit.Rule; | |||
| import org.junit.Test; | |||
| import static org.junit.Assert.assertEquals; | |||
| import static org.junit.Assert.fail; | |||
| /** | |||
| @@ -103,6 +105,8 @@ public class GetTest { | |||
| public void test7() { | |||
| try { | |||
| buildRule.executeTarget("test7"); | |||
| AntAssert.assertNotContains("Adding header", buildRule.getLog()); | |||
| fail("userAgent may not be null or empty"); | |||
| } catch (BuildException ex) { | |||
| //TODO assert value | |||
| @@ -119,4 +123,36 @@ public class GetTest { | |||
| buildRule.executeTarget("testUseTomorrow"); | |||
| } | |||
| @Test | |||
| public void testTwoHeaders() { | |||
| buildRule.executeTarget("testTwoHeaders"); | |||
| String log = buildRule.getLog(); | |||
| AntAssert.assertContains("Adding header 'header1'", log); | |||
| AntAssert.assertContains("Adding header 'header2'", log); | |||
| } | |||
| @Test | |||
| public void testEmptyHeadersAreNeverAdded() { | |||
| buildRule.executeTarget("testEmptyHeaders"); | |||
| AntAssert.assertNotContains("Adding header", buildRule.getLog()); | |||
| } | |||
| @Test | |||
| public void testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded() { | |||
| buildRule.executeTarget("testDuplicateHeaderNames"); | |||
| String log = buildRule.getLog(); | |||
| AntAssert.assertContains("Adding header 'header1'", log); | |||
| String firstHeaderLogTrimmed = log.replaceFirst("Adding header ", ""); | |||
| String allHeaderLogsTrimmed = log.replaceAll("Adding header ", ""); | |||
| assertEquals("Only one header has been added", firstHeaderLogTrimmed, allHeaderLogsTrimmed); | |||
| } | |||
| @Test | |||
| public void testHeaderSpaceTrimmed() { | |||
| buildRule.executeTarget("testHeaderSpacesTrimmed"); | |||
| AntAssert.assertContains("Adding header 'header1'", buildRule.getLog()); | |||
| } | |||
| } | |||