aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java645
1 files changed, 645 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java
new file mode 100644
index 00000000..fc31b1d3
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/SignJar.java
@@ -0,0 +1,645 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant.taskdefs;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.condition.IsSigned;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.resources.FileProvider;
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.IdentityMapper;
+import org.apache.tools.ant.util.ResourceUtils;
+
+/**
+ * Signs JAR or ZIP files with the javasign command line tool. The tool detailed
+ * dependency checking: files are only signed if they are not signed. The
+ * <tt>signjar</tt> attribute can point to the file to generate; if this file
+ * 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 <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/time-of-signing-beta1.html">
+ * beta documentation</a>
+ * @ant.task category="java"
+ * @since Ant 1.1
+ */
+public class SignJar extends AbstractJarSignerTask {
+ // CheckStyle:VisibilityModifier OFF - bc
+
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+
+ /**
+ * name to a signature file
+ */
+ protected String sigfile;
+
+ /**
+ * name of a single jar
+ */
+ protected File signedjar;
+
+ /**
+ * flag for internal sf signing
+ */
+ protected boolean internalsf;
+
+ /**
+ * sign sections only?
+ */
+ protected boolean sectionsonly;
+
+ /**
+ * flag to preserve timestamp on modified files
+ */
+ private boolean preserveLastModified;
+
+ /**
+ * Whether to assume a jar which has an appropriate .SF file in is already
+ * signed.
+ */
+ protected boolean lazy;
+
+ /**
+ * the output directory when using paths.
+ */
+ protected File destDir;
+
+ /**
+ * mapper for todir work
+ */
+ private FileNameMapper mapper;
+
+ /**
+ * URL for a tsa; null implies no tsa support
+ */
+ protected String tsaurl;
+
+ /**
+ * Proxy host to be used when connecting to TSA server
+ */
+ protected String tsaproxyhost;
+
+ /**
+ * Proxy port to be used when connecting to TSA server
+ */
+ protected String tsaproxyport;
+
+ /**
+ * alias for the TSA in the keystore
+ */
+ protected String tsacert;
+
+ /**
+ * force signing even if the jar is already signed.
+ */
+ private boolean force = false;
+
+ /**
+ * signature algorithm
+ */
+ private String sigAlg;
+
+ /**
+ * digest algorithm
+ */
+ private String digestAlg;
+
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_TODIR_AND_SIGNEDJAR
+ = "'destdir' and 'signedjar' cannot both be set";
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_TOO_MANY_MAPPERS = "Too many mappers";
+ /**
+ * error string for unit test verification {@value}
+ */
+ public static final String ERROR_SIGNEDJAR_AND_PATHS
+ = "You cannot specify the signed JAR when using paths or filesets";
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_BAD_MAP = "Cannot map source file to anything sensible: ";
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_MAPPER_WITHOUT_DEST
+ = "The destDir attribute is required if a mapper is set";
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_NO_ALIAS = "alias attribute must be set";
+ /**
+ * error string for unit test verification: {@value}
+ */
+ public static final String ERROR_NO_STOREPASS = "storepass attribute must be set";
+ // CheckStyle:VisibilityModifier ON
+
+ /**
+ * name of .SF/.DSA file; optional
+ *
+ * @param sigfile the name of the .SF/.DSA file
+ */
+ public void setSigfile(final String sigfile) {
+ this.sigfile = sigfile;
+ }
+
+ /**
+ * name of signed JAR file; optional
+ *
+ * @param signedjar the name of the signed jar file
+ */
+ public void setSignedjar(final File signedjar) {
+ this.signedjar = signedjar;
+ }
+
+ /**
+ * Flag to include the .SF file inside the signature; optional; default
+ * false
+ *
+ * @param internalsf if true include the .SF file inside the signature
+ */
+ public void setInternalsf(final boolean internalsf) {
+ this.internalsf = internalsf;
+ }
+
+ /**
+ * flag to compute hash of entire manifest; optional, default false
+ *
+ * @param sectionsonly flag to compute hash of entire manifest
+ */
+ public void setSectionsonly(final boolean sectionsonly) {
+ this.sectionsonly = sectionsonly;
+ }
+
+ /**
+ * flag to control whether the presence of a signature file means a JAR is
+ * signed; optional, default false
+ *
+ * @param lazy flag to control whether the presence of a signature
+ */
+ public void setLazy(final boolean lazy) {
+ this.lazy = lazy;
+ }
+
+ /**
+ * Optionally sets the output directory to be used.
+ *
+ * @param destDir the directory in which to place signed jars
+ * @since Ant 1.7
+ */
+ public void setDestDir(File destDir) {
+ this.destDir = destDir;
+ }
+
+
+ /**
+ * add a mapper to determine file naming policy. Only used with toDir
+ * processing.
+ *
+ * @param newMapper the mapper to add.
+ * @since Ant 1.7
+ */
+ public void add(FileNameMapper newMapper) {
+ if (mapper != null) {
+ throw new BuildException(ERROR_TOO_MANY_MAPPERS);
+ }
+ 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 the tsa url.
+ * @since Ant 1.7
+ */
+ public void setTsaurl(String tsaurl) {
+ this.tsaurl = tsaurl;
+ }
+
+ /**
+ * Get the proxy host to be used when connecting to the TSA url
+ * @return url or null
+ * @since Ant 1.9.5
+ */
+ public String getTsaproxyhost() {
+ return tsaproxyhost;
+ }
+
+ /**
+ *
+ * @param tsaproxyhost the proxy host to be used when connecting to the TSA.
+ * @since Ant 1.9.5
+ */
+ public void setTsaproxyhost(String tsaproxyhost) {
+ this.tsaproxyhost = tsaproxyhost;
+ }
+
+ /**
+ * Get the proxy host to be used when connecting to the TSA url
+ * @return url or null
+ * @since Ant 1.9.5
+ */
+ public String getTsaproxyport() {
+ return tsaproxyport;
+ }
+
+ /**
+ *
+ * @param tsaproxyport the proxy port to be used when connecting to the TSA.
+ * @since Ant 1.9.5
+ */
+ public void setTsaproxyport(String tsaproxyport) {
+ this.tsaproxyport = tsaproxyport;
+ }
+
+ /**
+ * 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 the cert alias.
+ */
+ public void setTsacert(String tsacert) {
+ this.tsacert = tsacert;
+ }
+
+ /**
+ * Whether to force signing of a jar even it is already signed.
+ * @since Ant 1.8.0
+ */
+ public void setForce(boolean b) {
+ force = b;
+ }
+
+ /**
+ * Should the task force signing of a jar even it is already
+ * signed?
+ * @since Ant 1.8.0
+ */
+ public boolean isForce() {
+ return force;
+ }
+
+ /**
+ * Signature Algorithm; optional
+ *
+ * @param sigAlg the signature algorithm
+ */
+ public void setSigAlg(String sigAlg) {
+ this.sigAlg = sigAlg;
+ }
+
+ /**
+ * Signature Algorithm; optional
+ */
+ public String getSigAlg() {
+ return sigAlg;
+ }
+
+ /**
+ * Digest Algorithm; optional
+ *
+ * @param digestAlg the digest algorithm
+ */
+ public void setDigestAlg(String digestAlg) {
+ this.digestAlg = digestAlg;
+ }
+
+ /**
+ * Digest Algorithm; optional
+ */
+ public String getDigestAlg() {
+ return digestAlg;
+ }
+
+ /**
+ * sign the jar(s)
+ *
+ * @throws BuildException on errors
+ */
+ @Override
+ public void execute() throws BuildException {
+ //validation logic
+ final boolean hasJar = jar != null;
+ final boolean hasSignedJar = signedjar != null;
+ final boolean hasDestDir = destDir != null;
+ final boolean hasMapper = mapper != null;
+
+ if (!hasJar && !hasResources()) {
+ throw new BuildException(ERROR_NO_SOURCE);
+ }
+ if (null == alias) {
+ throw new BuildException(ERROR_NO_ALIAS);
+ }
+
+ if (null == storepass) {
+ throw new BuildException(ERROR_NO_STOREPASS);
+ }
+
+ if (hasDestDir && hasSignedJar) {
+ throw new BuildException(ERROR_TODIR_AND_SIGNEDJAR);
+ }
+
+
+ if (hasResources() && hasSignedJar) {
+ throw new BuildException(ERROR_SIGNEDJAR_AND_PATHS);
+ }
+
+ //this isn't strictly needed, but by being fussy now,
+ //we can change implementation details later
+ if (!hasDestDir && hasMapper) {
+ throw new BuildException(ERROR_MAPPER_WITHOUT_DEST);
+ }
+
+ beginExecution();
+
+
+ try {
+ //special case single jar handling with signedjar attribute set
+ if (hasJar && hasSignedJar) {
+ // single jar processing
+ signOneJar(jar, signedjar);
+ //return here.
+ return;
+ }
+
+ //the rest of the method treats single jar like
+ //a nested path with one file
+
+ Path sources = createUnifiedSourcePath();
+ //set up our mapping policy
+ FileNameMapper destMapper;
+ if (hasMapper) {
+ destMapper = mapper;
+ } else {
+ //no mapper? use the identity policy
+ destMapper = new IdentityMapper();
+ }
+
+
+ //at this point the paths are set up with lists of files,
+ //and the mapper is ready to map from source dirs to dest files
+ //now we iterate through every JAR giving source and dest names
+ // deal with the paths
+ for (Resource r : sources) {
+ FileResource fr = ResourceUtils
+ .asFileResource(r.as(FileProvider.class));
+
+ //calculate our destination directory; it is either the destDir
+ //attribute, or the base dir of the fileset (for in situ updates)
+ File toDir = hasDestDir ? destDir : fr.getBaseDir();
+
+ //determine the destination filename via the mapper
+ String[] destFilenames = destMapper.mapFileName(fr.getName());
+ if (destFilenames == null || destFilenames.length != 1) {
+ //we only like simple mappers.
+ throw new BuildException(ERROR_BAD_MAP + fr.getFile());
+ }
+ File destFile = new File(toDir, destFilenames[0]);
+ signOneJar(fr.getFile(), destFile);
+ }
+ } finally {
+ endExecution();
+ }
+ }
+
+ /**
+ * Sign one jar.
+ * <p/>
+ * The signing only takes place if {@link #isUpToDate(File, File)} indicates
+ * that it is needed.
+ *
+ * @param jarSource source to sign
+ * @param jarTarget target; may be null
+ * @throws BuildException
+ */
+ private void signOneJar(File jarSource, File jarTarget)
+ throws BuildException {
+
+
+ File targetFile = jarTarget;
+ if (targetFile == null) {
+ targetFile = jarSource;
+ }
+ if (isUpToDate(jarSource, targetFile)) {
+ return;
+ }
+
+ long lastModified = jarSource.lastModified();
+ final ExecTask cmd = createJarSigner();
+
+ setCommonOptions(cmd);
+
+ bindToKeystore(cmd);
+ if (null != sigfile) {
+ addValue(cmd, "-sigfile");
+ String value = this.sigfile;
+ addValue(cmd, value);
+ }
+
+ try {
+ //DO NOT SET THE -signedjar OPTION if source==dest
+ //unless you like fielding hotspot crash reports
+ if (!FILE_UTILS.areSame(jarSource, targetFile)) {
+ addValue(cmd, "-signedjar");
+ addValue(cmd, targetFile.getPath());
+ }
+ } catch (IOException ioex) {
+ throw new BuildException(ioex);
+ }
+
+ if (internalsf) {
+ addValue(cmd, "-internalsf");
+ }
+
+ if (sectionsonly) {
+ addValue(cmd, "-sectionsonly");
+ }
+
+ if (sigAlg != null) {
+ addValue(cmd, "-sigalg");
+ addValue(cmd, sigAlg);
+ }
+
+ if (digestAlg != null) {
+ addValue(cmd, "-digestalg");
+ addValue(cmd, digestAlg);
+ }
+
+ //add -tsa operations if declared
+ addTimestampAuthorityCommands(cmd);
+
+ //JAR source is required
+ addValue(cmd, jarSource.getPath());
+
+ //alias is required for signing
+ addValue(cmd, alias);
+
+ log("Signing JAR: "
+ + jarSource.getAbsolutePath()
+ + " to "
+ + targetFile.getAbsolutePath()
+ + " as " + alias);
+
+ cmd.execute();
+
+ // restore the lastModified attribute
+ if (preserveLastModified) {
+ FILE_UTILS.setFileLastModified(targetFile, lastModified);
+ }
+ }
+
+ /**
+ * 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 the exec task.
+ */
+ private void addTimestampAuthorityCommands(final ExecTask cmd) {
+ if (tsaurl != null) {
+ addValue(cmd, "-tsa");
+ addValue(cmd, tsaurl);
+ }
+
+ if (tsacert != null) {
+ addValue(cmd, "-tsacert");
+ addValue(cmd, tsacert);
+ }
+
+ if (tsaproxyhost != null) {
+ if (tsaurl == null || tsaurl.startsWith("https")) {
+ addProxyFor(cmd, "https");
+ }
+ if (tsaurl == null || !tsaurl.startsWith("https")) {
+ addProxyFor(cmd, "http");
+ }
+ }
+ }
+
+ /**
+ * <p>Compare a jar file with its corresponding signed jar. The logic for this
+ * is complex, and best explained in the source itself. Essentially if
+ * either file doesn't exist, or the destfile has an out of date timestamp,
+ * then the return value is false.</p>
+ *
+ * <p>If we are signing ourself, the check {@link #isSigned(File)} is used to
+ * trigger the process.</p>
+ *
+ * @param jarFile the unsigned jar file
+ * @param signedjarFile the result signed jar file
+ * @return true if the signedjarFile is considered up to date
+ */
+ protected boolean isUpToDate(File jarFile, File signedjarFile) {
+ if (isForce() || null == jarFile || !jarFile.exists()) {
+ //these are pathological cases, but retained in case somebody
+ //subclassed us.
+ return false;
+ }
+
+ //we normally compare destination with source
+ File destFile = signedjarFile;
+ if (destFile == null) {
+ //but if no dest is specified, compare source to source
+ destFile = jarFile;
+ }
+
+ //if, by any means, the destfile and source match,
+ if (jarFile.equals(destFile)) {
+ if (lazy) {
+ //we check the presence of signatures on lazy signing
+ return isSigned(jarFile);
+ }
+ //unsigned or non-lazy self signings are always false
+ return false;
+ }
+
+ //if they are different, the timestamps are used
+ return FILE_UTILS.isUpToDate(jarFile, destFile);
+ }
+
+ /**
+ * test for a file being signed, by looking for a signature in the META-INF
+ * directory with our alias/sigfile.
+ *
+ * @param file the file to be checked
+ * @return true if the file is signed
+ * @see IsSigned#isSigned(File, String)
+ */
+ protected boolean isSigned(File file) {
+ try {
+ return IsSigned.isSigned(file, sigfile == null ? alias : sigfile);
+ } catch (IOException e) {
+ //just log this
+ log(e.toString(), Project.MSG_VERBOSE);
+ return false;
+ }
+ }
+
+ /**
+ * true to indicate that the signed jar modification date remains the same
+ * as the original. Defaults to false
+ *
+ * @param preserveLastModified if true preserve the last modified time
+ */
+ public void setPreserveLastModified(boolean preserveLastModified) {
+ this.preserveLastModified = preserveLastModified;
+ }
+
+ private void addProxyFor(final ExecTask cmd, final String scheme) {
+ addValue(cmd, "-J-D" + scheme + ".proxyHost=" + tsaproxyhost);
+
+ if (tsaproxyport != null) {
+ addValue(cmd, "-J-D" + scheme + ".proxyPort=" + tsaproxyport);
+ }
+ }
+}