diff --git a/WHATSNEW b/WHATSNEW
index 3891ac06f..44ba59253 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -151,6 +151,7 @@ Other changes:
-a destDir attribute with the appropriate dependency logic, which
can be used with the jar attribute or nested filesets
-a mapper to permit filename remapping on signing
+ -tsaurl and tsacert attributes for timestamped JAR signing
Changes from Ant 1.6.2 to current Ant 1.6 CVS version
=====================================================
diff --git a/docs/manual/CoreTasks/signjar.html b/docs/manual/CoreTasks/signjar.html
index 900ea96d2..9d098c66a 100644
--- a/docs/manual/CoreTasks/signjar.html
+++ b/docs/manual/CoreTasks/signjar.html
@@ -113,6 +113,19 @@ block
time as the original jar files.
No; default false. |
+
+ tsaurl |
+ URL for a timestamp authority for timestamped
+ JAR files in Java1.5+ |
+ No |
+
+
+ tsacert |
+ alias in the keystore for a timestamp authority for
+ timestamped JAR files in Java1.5+ |
+ No |
+
+
Parameters as nested elements
@@ -141,6 +154,20 @@ alias="apache-group" storepass="secret"/>
signs the ant.jar with alias "apache-group" accessing the
keystore and private key via "secret" password.
+
+About timestamp signing
+
+
+Timestamped JAR files are a new feature in Java1.5; a feature supported in Ant since
+Ant 1.7. Ant does not yet support proxy setup for this singing process, and
+the whole TSA feature is not tested yet. Furthermore, the
+
+official TSA documentation
+warns that the API is subject to change. If a future version of Java changes the
+API, Ant will break. It may be possible to hide changes if and when they occur,
+but this can not be guaranteed.
+
+
Copyright © 2000-2005 The Apache Software Foundation. All rights
Reserved.
diff --git a/src/etc/testcases/taskdefs/signjar.xml b/src/etc/testcases/taskdefs/signjar.xml
index 17f0da224..fd703476a 100644
--- a/src/etc/testcases/taskdefs/signjar.xml
+++ b/src/etc/testcases/taskdefs/signjar.xml
@@ -5,6 +5,7 @@
+
@@ -168,6 +169,10 @@
alias="testonly"
jar="${test.jar}"/>
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/SignJar.java b/src/main/org/apache/tools/ant/taskdefs/SignJar.java
index 908a2e430..8869c6593 100644
--- a/src/main/org/apache/tools/ant/taskdefs/SignJar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/SignJar.java
@@ -41,6 +41,10 @@ import org.apache.tools.ant.util.FileNameMapper;
* exists then its modification date is used as a cue as to whether to resign
* any JAR file.
*
+ * Timestamp driven signing is based on the unstable and inadequately documented
+ * information in the Java1.5 docs
+ * @see
+ * beta documentation
* @ant.task category="java"
* @since Ant 1.1
*/
@@ -94,11 +98,23 @@ public class SignJar extends Task {
protected boolean verbose;
/**
- * flag for
+ * flag for internal sf signing
*/
protected boolean internalsf;
+
+ /**
+ * sign sections only?
+ */
protected boolean sectionsonly;
+
+ /**
+ * flag to preserve timestamp on modified files
+ */
private boolean preserveLastModified;
+
+ /**
+ * redirector used to talk to the jarsigner program
+ */
private RedirectorElement redirector;
/**
@@ -127,6 +143,16 @@ public class SignJar extends Task {
*/
private FileNameMapper mapper;
+ /**
+ * URL for a tsa; null implies no tsa support
+ */
+ protected String tsaurl;
+
+ /**
+ * alias for the TSA in the keystore
+ */
+ protected String tsacert;
+
/**
* error string for unit test verification: {@value}
*/
@@ -327,10 +353,50 @@ public class SignJar extends Task {
mapper = newMapper;
}
+ /**
+ * get the active mapper; may be null
+ * @return mapper or null
+ * @since Ant 1.7
+ */
public FileNameMapper getMapper() {
return mapper;
}
+ /**
+ * get the -tsaurl url
+ * @return url or null
+ * @since Ant 1.7
+ */
+ public String getTsaurl() {
+ return tsaurl;
+ }
+
+ /**
+ *
+ * @param tsaurl
+ * @since Ant 1.7
+ */
+ public void setTsaurl(String tsaurl) {
+ this.tsaurl = tsaurl;
+ }
+
+ /**
+ * get the -tsacert option
+ * @since Ant 1.7
+ * @return a certificate alias or null
+ */
+ public String getTsacert() {
+ return tsacert;
+ }
+
+ /**
+ * set the alias in the keystore of the TSA to use;
+ * @param tsacert
+ */
+ public void setTsacert(String tsacert) {
+ this.tsacert = tsacert;
+ }
+
/**
* sign the jar(s)
*
@@ -523,6 +589,9 @@ public class SignJar extends Task {
cmd.createArg().setValue("-sectionsonly");
}
+ //add -tsa operations if declared
+ addTimestampAuthorityCommands(cmd);
+
//JAR source is required
cmd.createArg().setValue(jarSource.getPath());
@@ -544,6 +613,23 @@ public class SignJar extends Task {
}
}
+ /**
+ * If the tsa parameters are set, this passes them to the command.
+ * There is no validation of java version, as third party JDKs
+ * may implement this on earlier/later jarsigner implementations.
+ * @param cmd
+ */
+ private void addTimestampAuthorityCommands(final ExecTask cmd) {
+ if(tsaurl!=null) {
+ cmd.createArg().setValue("-tsa");
+ cmd.createArg().setValue(tsaurl);
+ }
+ if (tsacert != null) {
+ cmd.createArg().setValue("-tsacert");
+ cmd.createArg().setValue(tsacert);
+ }
+ }
+
/**
* Compare a jar file with its corresponding signed jar. The logic for this
* is complex, and best explained in the source itself. Essentially if
@@ -559,7 +645,7 @@ public class SignJar extends Task {
*/
protected boolean isUpToDate(File jarFile, File signedjarFile) {
if (null == jarFile && !jarFile.exists()) {
- //these are pathological case, but retained in case somebody
+ //these are pathological cases, but retained in case somebody
//subclassed us.
return false;
}
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java b/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java
index bd716c521..db9e94211 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/SignJarTest.java
@@ -143,7 +143,13 @@ public class SignJarTest extends BuildFileTest {
public void testNoStorePass() {
expectBuildExceptionContaining("testNoStorePass",
- "no files",
+ "no password",
SignJar.ERROR_NO_STOREPASS);
}
- }
+
+ public void testTsaLocalhost() {
+ expectBuildException("testTsaLocalhost",
+ "no TSA at localhost:0");
+ assertLogContaining("java.net.ConnectException");
+ }
+}