@@ -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 | name will be skipped. If the returned name is a relative path, it | ||||
will be considered relative to the <em>dest</em> attribute.</p> | 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. Cannot be null or empty. Leading and trailing spaces are removed</td> | |||||
<td align="center" valign="top">Yes</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">value</td> | |||||
<td valign="top">The value to assign to the header. Cannot be null or empty. Leading and trailing spaces are removed</td> | |||||
<td align="center" valign="top">Yes</td> | |||||
</tr> | |||||
</table> | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <get src="http://ant.apache.org/" dest="help/index.html"/></pre> | <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> | <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,16 @@ the <a href="input.html">input task</a> to query for a password.</p> | |||||
<url url="http://ant.apache.org/faq.html"/> | <url url="http://ant.apache.org/faq.html"/> | ||||
</get> | </get> | ||||
</pre> | </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 | <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 | them in the directory <code>downloads</code> which will be created if | ||||
necessary.</p> | necessary.</p> | ||||
@@ -98,6 +98,34 @@ | |||||
</fail> | </fail> | ||||
</target> | </target> | ||||
<target name="testTwoHeadersAreAddedOK"> | |||||
<get src="http://www.apache.org/" dest="get.tmp"> | |||||
<header name="header1" value="header1Value"/> | |||||
<header name="header2" value="header2Value"/> | |||||
</get> | |||||
</target> | |||||
<target name="testEmptyHeadersAreNeverAdded"> | |||||
<get src="http://www.apache.org/" dest="get.tmp"> | |||||
<header name="" value="headerValue"/> | |||||
<header name="header2" value=""/> | |||||
</get> | |||||
</target> | |||||
<target name="testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded"> | |||||
<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="testHeaderSpaceTrimmed"> | |||||
<get src="http://www.apache.org/" dest="get.tmp"> | |||||
<header name=" header1 " value=" headerValue1 "/> | |||||
</get> | |||||
</target> | |||||
<target name="cleanup"> | <target name="cleanup"> | ||||
<delete> | <delete> | ||||
<fileset dir="${basedir}" includes="get.tmp" /> | <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.Main; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Task; | 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.Mapper; | ||||
import org.apache.tools.ant.types.Resource; | import org.apache.tools.ant.types.Resource; | ||||
import org.apache.tools.ant.types.ResourceCollection; | import org.apache.tools.ant.types.ResourceCollection; | ||||
@@ -44,6 +45,10 @@ import org.apache.tools.ant.types.resources.URLProvider; | |||||
import org.apache.tools.ant.types.resources.URLResource; | import org.apache.tools.ant.types.resources.URLResource; | ||||
import org.apache.tools.ant.util.FileNameMapper; | import org.apache.tools.ant.util.FileNameMapper; | ||||
import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
import org.apache.tools.ant.util.StringUtils; | |||||
import java.util.LinkedHashMap; | |||||
import java.util.Map; | |||||
/** | /** | ||||
* Gets a particular file from a URL source. | * Gets a particular file from a URL source. | ||||
@@ -90,6 +95,9 @@ public class Get extends Task { | |||||
DEFAULT_AGENT_PREFIX + "/" | DEFAULT_AGENT_PREFIX + "/" | ||||
+ Main.getShortAntVersion()); | + Main.getShortAntVersion()); | ||||
// Store headers as key/value pair without duplicate in keyz | |||||
private Map<String, String> headers = new LinkedHashMap<String, String>(); | |||||
/** | /** | ||||
* Does the work. | * Does the work. | ||||
* | * | ||||
@@ -482,6 +490,21 @@ public class Get extends Task { | |||||
tryGzipEncoding = b; | tryGzipEncoding = b; | ||||
} | } | ||||
/** | |||||
* Add a nested header | |||||
* @param header to be added | |||||
* | |||||
*/ | |||||
public void addConfiguredHeader(Header header) { | |||||
if (header != null) { | |||||
String key = StringUtils.trimToNull(header.getName()); | |||||
String value = StringUtils.trimToNull(header.getValue()); | |||||
if (key != null && value != null) { | |||||
this.headers.put(key, value); | |||||
} | |||||
} | |||||
} | |||||
/** | /** | ||||
* Define the mapper to map source to destination files. | * Define the mapper to map source to destination files. | ||||
* @return a mapper to be configured. | * @return a mapper to be configured. | ||||
@@ -726,6 +749,14 @@ public class Get extends Task { | |||||
connection.setRequestProperty("Accept-Encoding", GZIP_CONTENT_ENCODING); | connection.setRequestProperty("Accept-Encoding", GZIP_CONTENT_ENCODING); | ||||
} | } | ||||
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) { | if (connection instanceof HttpURLConnection) { | ||||
((HttpURLConnection) connection) | ((HttpURLConnection) connection) | ||||
.setInstanceFollowRedirects(false); | .setInstanceFollowRedirects(false); | ||||
@@ -19,7 +19,9 @@ | |||||
package org.apache.tools.ant.taskdefs.email; | 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 | * @since Ant 1.7 | ||||
*/ | */ | ||||
public class Header { | public class Header { | ||||
@@ -306,4 +306,25 @@ public final class StringUtils { | |||||
private static Collector<CharSequence,?,String> joining(CharSequence separator) { | private static Collector<CharSequence,?,String> joining(CharSequence separator) { | ||||
return separator == null ? Collectors.joining() : Collectors.joining(separator); | return separator == null ? Collectors.joining() : Collectors.joining(separator); | ||||
} | } | ||||
/** | |||||
* @param inputString String to trim | |||||
* @return null if the input string is null or empty or contain only empty spaces. | |||||
* It returns the input string without leading and trailing spaces otherwise. | |||||
* | |||||
*/ | |||||
public static String trimToNull(String inputString) { | |||||
if (inputString == null) { | |||||
return null; | |||||
} | |||||
String tmpString = inputString.trim(); | |||||
if ("".equals(tmpString)) { | |||||
return null; | |||||
} | |||||
return tmpString; | |||||
} | |||||
} | } |
@@ -18,6 +18,7 @@ | |||||
package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
import org.apache.tools.ant.AntAssert; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.BuildFileRule; | import org.apache.tools.ant.BuildFileRule; | ||||
import org.junit.After; | import org.junit.After; | ||||
@@ -25,6 +26,7 @@ import org.junit.Before; | |||||
import org.junit.Rule; | import org.junit.Rule; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.fail; | import static org.junit.Assert.fail; | ||||
/** | /** | ||||
@@ -103,6 +105,8 @@ public class GetTest { | |||||
public void test7() { | public void test7() { | ||||
try { | try { | ||||
buildRule.executeTarget("test7"); | buildRule.executeTarget("test7"); | ||||
AntAssert.assertNotContains("Adding header", buildRule.getLog()); | |||||
fail("userAgent may not be null or empty"); | fail("userAgent may not be null or empty"); | ||||
} catch (BuildException ex) { | } catch (BuildException ex) { | ||||
//TODO assert value | //TODO assert value | ||||
@@ -119,4 +123,35 @@ public class GetTest { | |||||
buildRule.executeTarget("testUseTomorrow"); | buildRule.executeTarget("testUseTomorrow"); | ||||
} | } | ||||
@Test | |||||
public void testTwoHeadersAreAddedOK() { | |||||
buildRule.executeTarget("testTwoHeadersAreAddedOK"); | |||||
String log = buildRule.getLog(); | |||||
AntAssert.assertContains("Adding header 'header1'", log); | |||||
AntAssert.assertContains("Adding header 'header2'", log); | |||||
} | |||||
@Test | |||||
public void testEmptyHeadersAreNeverAdded() { | |||||
buildRule.executeTarget("testEmptyHeadersAreNeverAdded"); | |||||
AntAssert.assertNotContains("Adding header", buildRule.getLog()); | |||||
} | |||||
@Test | |||||
public void testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded() { | |||||
buildRule.executeTarget("testThatWhenMoreThanOneHeaderHaveSameNameOnlyLastOneIsAdded"); | |||||
String log = buildRule.getLog(); | |||||
AntAssert.assertContains("Adding header 'header1'", log); | |||||
int actualHeaderCount = log.split("Adding header ").length - 1; | |||||
assertEquals("Only one header has been added", 1, actualHeaderCount); | |||||
} | |||||
@Test | |||||
public void testHeaderSpaceTrimmed() { | |||||
buildRule.executeTarget("testHeaderSpaceTrimmed"); | |||||
AntAssert.assertContains("Adding header 'header1'", buildRule.getLog()); | |||||
} | |||||
} | } |
@@ -17,16 +17,14 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.util; | package org.apache.tools.ant.util; | ||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.assertFalse; | |||||
import static org.junit.Assert.assertTrue; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Vector; | import java.util.Vector; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import static org.junit.Assert.*; | |||||
/** | /** | ||||
* Test for StringUtils | * Test for StringUtils | ||||
*/ | */ | ||||
@@ -195,5 +193,24 @@ public class StringUtilsTest { | |||||
public void testJoinNullSeparator() { | public void testJoinNullSeparator() { | ||||
assertEquals("abc", StringUtils.join(Arrays.asList("a", "b", "c"), null)); | assertEquals("abc", StringUtils.join(Arrays.asList("a", "b", "c"), null)); | ||||
} | } | ||||
@Test | |||||
public void testTrimToNullWithNullInput(){ | |||||
assertNull(StringUtils.trimToNull(null)); | |||||
} | |||||
@Test | |||||
public void testTrimToNullWithEmptyInput(){ | |||||
assertNull(StringUtils.trimToNull("")); | |||||
} | |||||
@Test | |||||
public void testTrimToNullWithBlankSpaceInput(){ | |||||
assertNull(StringUtils.trimToNull(" ")); | |||||
} | |||||
@Test | |||||
public void testTrimToNullWithInputPaddedWithSpace(){ | |||||
assertEquals("aaBcDeF",StringUtils.trimToNull(" aaBcDeF ")); | |||||
} | |||||
} | } |