You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

SignJar.java 9.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 1999 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Ant", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant.taskdefs;
  55. import java.io.File;
  56. import java.io.IOException;
  57. import java.util.Enumeration;
  58. import java.util.Vector;
  59. import java.util.zip.ZipEntry;
  60. import java.util.zip.ZipFile;
  61. import org.apache.tools.ant.Task;
  62. import org.apache.tools.ant.BuildException;
  63. import org.apache.tools.ant.DirectoryScanner;
  64. import org.apache.tools.ant.Project;
  65. import org.apache.tools.ant.types.FileSet;
  66. /**
  67. * Sign a archive.
  68. *
  69. * @author Peter Donald <a href="mailto:donaldp@apache.org">donaldp@apache.org</a>
  70. * @author Nick Fortescue <a href="mailto:nick@ox.compsoc.net">nick@ox.compsoc.net</a>
  71. */
  72. public class SignJar extends Task {
  73. /**
  74. * The name of the jar file.
  75. */
  76. protected File jar;
  77. /**
  78. * The alias of signer.
  79. */
  80. protected String alias;
  81. /**
  82. * The name of keystore file.
  83. */
  84. protected File keystore;
  85. protected String storepass;
  86. protected String storetype;
  87. protected String keypass;
  88. protected File sigfile;
  89. protected File signedjar;
  90. protected boolean verbose;
  91. protected boolean internalsf;
  92. protected boolean sectionsonly;
  93. /**
  94. * the filesets of the jars to sign
  95. */
  96. protected Vector filesets = new Vector();
  97. /**
  98. * Whether to assume a jar which has an appropriate .SF file in is already
  99. * signed.
  100. */
  101. protected boolean lazy;
  102. public void setJar(final File jar) {
  103. this.jar = jar;
  104. }
  105. public void setAlias(final String alias) {
  106. this.alias = alias;
  107. }
  108. public void setKeystore(final File keystore) {
  109. this.keystore = keystore;
  110. }
  111. public void setStorepass(final String storepass) {
  112. this.storepass = storepass;
  113. }
  114. public void setStoretype(final String storetype) {
  115. this.storetype = storetype;
  116. }
  117. public void setKeypass(final String keypass) {
  118. this.keypass = keypass;
  119. }
  120. public void setSigfile(final File sigfile) {
  121. this.sigfile = sigfile;
  122. }
  123. public void setSignedjar(final File signedjar) {
  124. this.signedjar = signedjar;
  125. }
  126. public void setVerbose(final boolean verbose) {
  127. this.verbose = verbose;
  128. }
  129. public void setInternalsf(final boolean internalsf) {
  130. this.internalsf = internalsf;
  131. }
  132. public void setSectionsonly(final boolean sectionsonly) {
  133. this.sectionsonly = sectionsonly;
  134. }
  135. public void setLazy(final boolean lazy) {
  136. this.lazy = lazy;
  137. }
  138. /**
  139. * Adds a set of files (nested fileset attribute).
  140. */
  141. public void addFileset(final FileSet set) {
  142. filesets.addElement(set);
  143. }
  144. public void execute() throws BuildException {
  145. if (null == jar && null == filesets) {
  146. throw new BuildException("jar must be set through jar attribute or nested filesets");
  147. }
  148. if( null != jar ) {
  149. doOneJar(jar, signedjar);
  150. return;
  151. } else {
  152. //Assume null != filesets
  153. // deal with the filesets
  154. for (int i=0; i<filesets.size(); i++) {
  155. FileSet fs = (FileSet) filesets.elementAt(i);
  156. DirectoryScanner ds = fs.getDirectoryScanner(project);
  157. String[] jarFiles = ds.getIncludedFiles();
  158. for(int j=0; j<jarFiles.length; j++) {
  159. doOneJar( new File( jarFiles[j] ), null);
  160. }
  161. }
  162. }
  163. }
  164. private void doOneJar(File jarSource, File jarTarget) throws BuildException {
  165. if (project.getJavaVersion().equals(Project.JAVA_1_1)) {
  166. throw new BuildException("The signjar task is only available on JDK versions 1.2 or greater");
  167. }
  168. if (null == alias) {
  169. throw new BuildException("alias attribute must be set");
  170. }
  171. if (null == storepass) {
  172. throw new BuildException("storepass attribute must be set");
  173. }
  174. if(isUpToDate(jarSource, jarTarget)) return;
  175. final StringBuffer sb = new StringBuffer();
  176. final ExecTask cmd = (ExecTask) project.createTask("exec");
  177. cmd.setExecutable("jarsigner");
  178. if (null != keystore) {
  179. cmd.createArg().setValue("-keystore");
  180. cmd.createArg().setValue( keystore.toString() );
  181. }
  182. if (null != storepass) {
  183. cmd.createArg().setValue("-storepass");
  184. cmd.createArg().setValue(storepass);
  185. }
  186. if (null != storetype) {
  187. cmd.createArg().setValue("-storetype");
  188. cmd.createArg().setValue(storetype);
  189. }
  190. if (null != keypass) {
  191. cmd.createArg().setValue("-keypass");
  192. cmd.createArg().setValue(keypass);
  193. }
  194. if (null != sigfile) {
  195. cmd.createArg().setValue("-sigfile");
  196. cmd.createArg().setValue( sigfile.toString() );
  197. }
  198. if (null != jarTarget) {
  199. cmd.createArg().setValue("-signedjar");
  200. cmd.createArg().setValue( jarTarget.toString() );
  201. }
  202. if (verbose) {
  203. cmd.createArg().setValue("-verbose");
  204. }
  205. if (internalsf) {
  206. cmd.createArg().setValue("-internalsf");
  207. }
  208. if (sectionsonly) {
  209. cmd.createArg().setValue("-sectionsonly");
  210. }
  211. cmd.createArg().setValue( jarSource.toString() );
  212. cmd.createArg().setValue(alias);
  213. log("Signing Jar : " + jarSource.getAbsolutePath());
  214. cmd.setFailonerror(true);
  215. cmd.setTaskName( getTaskName() );
  216. cmd.execute();
  217. }
  218. protected boolean isUpToDate(File jarFile, File signedjarFile) {
  219. if( null == jarFile ) {
  220. return false;
  221. }
  222. if( null != signedjarFile ) {
  223. if(!jarFile.exists()) return false;
  224. if(!signedjarFile.exists()) return false;
  225. if(jarFile.equals(signedjarFile)) return false;
  226. if(signedjarFile.lastModified() > jarFile.lastModified())
  227. return true;
  228. } else {
  229. if( lazy ) {
  230. return isSigned(jarFile);
  231. }
  232. }
  233. return false;
  234. }
  235. protected boolean isSigned(File file) {
  236. final String SIG_START = "META-INF/";
  237. final String SIG_END = ".SF";
  238. if( !file.exists() ) {
  239. return false;
  240. }
  241. ZipFile jarFile = null;
  242. try {
  243. jarFile = new ZipFile(file);
  244. if(null == alias) {
  245. Enumeration entries = jarFile.entries();
  246. while(entries.hasMoreElements()) {
  247. String name = ((ZipEntry)entries.nextElement()).getName();
  248. if(name.startsWith(SIG_START) && name.endsWith(SIG_END)) {
  249. return true;
  250. }
  251. }
  252. return false;
  253. } else {
  254. return jarFile.getEntry(SIG_START+alias.toUpperCase()+
  255. SIG_END) != null;
  256. }
  257. } catch(IOException e) {
  258. return false;
  259. } finally {
  260. if(jarFile != null) {
  261. try {jarFile.close();} catch(IOException e) {}
  262. }
  263. }
  264. }
  265. }