001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.taskdefs;
019:
020: import java.util.Enumeration;
021: import java.util.Vector;
022: import org.apache.tools.ant.BuildException;
023: import org.apache.tools.ant.Task;
024: import org.apache.tools.ant.types.Commandline;
025: import org.apache.tools.ant.util.JavaEnvUtils;
026:
027: /**
028: * Generates a key in a keystore.
029: *
030: * @since Ant 1.2
031: *
032: * @ant.task name="genkey" category="java"
033: */
034: public class GenerateKey extends Task {
035:
036: /**
037: * A DistinguishedName parameter.
038: * This is a nested element in a dname nested element.
039: */
040: public static class DnameParam {
041: private String name;
042: private String value;
043:
044: /**
045: * Set the name attribute.
046: * @param name a <code>String</code> value
047: */
048: public void setName(String name) {
049: this .name = name;
050: }
051:
052: /**
053: * Get the name attribute.
054: * @return the name.
055: */
056: public String getName() {
057: return name;
058: }
059:
060: /**
061: * Set the value attribute.
062: * @param value a <code>String</code> value
063: */
064: public void setValue(String value) {
065: this .value = value;
066: }
067:
068: /**
069: * Get the value attribute.
070: * @return the value.
071: */
072: public String getValue() {
073: return value;
074: }
075: }
076:
077: /**
078: * A class corresponding to the dname nested element.
079: */
080: public static class DistinguishedName {
081: private Vector params = new Vector();
082:
083: /**
084: * Create a param nested element.
085: * @return a DnameParam object to be configured.
086: */
087: public Object createParam() {
088: DnameParam param = new DnameParam();
089: params.addElement(param);
090:
091: return param;
092: }
093:
094: /**
095: * Get the nested parameters.
096: * @return an enumeration of the nested parameters.
097: */
098: public Enumeration getParams() {
099: return params.elements();
100: }
101:
102: /**
103: * Generate a string rep of this distinguished name.
104: * The format is each of the parameters (name = value)
105: * separated by ','.
106: * This is used on the command line.
107: * @return a string rep of this name
108: */
109: public String toString() {
110: final int size = params.size();
111: final StringBuffer sb = new StringBuffer();
112: boolean firstPass = true;
113:
114: for (int i = 0; i < size; i++) {
115: if (!firstPass) {
116: sb.append(" ,");
117: }
118: firstPass = false;
119:
120: final DnameParam param = (DnameParam) params
121: .elementAt(i);
122: sb.append(encode(param.getName()));
123: sb.append('=');
124: sb.append(encode(param.getValue()));
125: }
126:
127: return sb.toString();
128: }
129:
130: /**
131: * Encode a name or value.
132: * The encoded result is the same as the input string
133: * except that each ',' is replaced by a '\,'.
134: * @param string the value to be encoded
135: * @return the encoded value.
136: */
137: public String encode(final String string) {
138: int end = string.indexOf(',');
139:
140: if (-1 == end) {
141: return string;
142: }
143:
144: final StringBuffer sb = new StringBuffer();
145:
146: int start = 0;
147:
148: while (-1 != end) {
149: sb.append(string.substring(start, end));
150: sb.append("\\,");
151: start = end + 1;
152: end = string.indexOf(',', start);
153: }
154:
155: sb.append(string.substring(start));
156:
157: return sb.toString();
158: }
159: }
160:
161: // CheckStyle:VisibilityModifier OFF - bc
162:
163: /**
164: * The alias of signer.
165: */
166: protected String alias;
167:
168: /**
169: * The name of keystore file.
170: */
171: protected String keystore;
172: protected String storepass;
173: protected String storetype;
174: protected String keypass;
175:
176: protected String sigalg;
177: protected String keyalg;
178: protected String dname;
179: protected DistinguishedName expandedDname;
180: protected int keysize;
181: protected int validity;
182: protected boolean verbose;
183:
184: // CheckStyle:VisibilityModifier ON
185:
186: /**
187: * Distinguished name list.
188: *
189: * @return Distinguished name container.
190: * @throws BuildException If specified more than once or dname
191: * attribute is used.
192: */
193: public DistinguishedName createDname() throws BuildException {
194: if (null != expandedDname) {
195: throw new BuildException("DName sub-element can only be "
196: + "specified once.");
197: }
198: if (null != dname) {
199: throw new BuildException(
200: "It is not possible to specify dname "
201: + " both as attribute and element.");
202: }
203: expandedDname = new DistinguishedName();
204: return expandedDname;
205: }
206:
207: /**
208: * The distinguished name for entity.
209: *
210: * @param dname distinguished name
211: */
212: public void setDname(final String dname) {
213: if (null != expandedDname) {
214: throw new BuildException(
215: "It is not possible to specify dname "
216: + " both as attribute and element.");
217: }
218: this .dname = dname;
219: }
220:
221: /**
222: * The alias to add under.
223: *
224: * @param alias alias to add under
225: */
226: public void setAlias(final String alias) {
227: this .alias = alias;
228: }
229:
230: /**
231: * Keystore location.
232: *
233: * @param keystore location
234: */
235: public void setKeystore(final String keystore) {
236: this .keystore = keystore;
237: }
238:
239: /**
240: * Password for keystore integrity.
241: * Must be at least 6 characters long.
242: * @param storepass password
243: */
244: public void setStorepass(final String storepass) {
245: this .storepass = storepass;
246: }
247:
248: /**
249: * Keystore type.
250: *
251: * @param storetype type
252: */
253: public void setStoretype(final String storetype) {
254: this .storetype = storetype;
255: }
256:
257: /**
258: * Password for private key (if different).
259: *
260: * @param keypass password
261: */
262: public void setKeypass(final String keypass) {
263: this .keypass = keypass;
264: }
265:
266: /**
267: * The algorithm to use in signing.
268: *
269: * @param sigalg algorithm
270: */
271: public void setSigalg(final String sigalg) {
272: this .sigalg = sigalg;
273: }
274:
275: /**
276: * The method to use when generating name-value pair.
277: * @param keyalg algorithm
278: */
279: public void setKeyalg(final String keyalg) {
280: this .keyalg = keyalg;
281: }
282:
283: /**
284: * Indicates the size of key generated.
285: *
286: * @param keysize size of key
287: * @throws BuildException If not an Integer
288: * @todo Could convert this to a plain Integer setter.
289: */
290: public void setKeysize(final String keysize) throws BuildException {
291: try {
292: this .keysize = Integer.parseInt(keysize);
293: } catch (final NumberFormatException nfe) {
294: throw new BuildException(
295: "KeySize attribute should be a integer");
296: }
297: }
298:
299: /**
300: * Indicates how many days certificate is valid.
301: *
302: * @param validity days valid
303: * @throws BuildException If not an Integer
304: */
305: public void setValidity(final String validity)
306: throws BuildException {
307: try {
308: this .validity = Integer.parseInt(validity);
309: } catch (final NumberFormatException nfe) {
310: throw new BuildException(
311: "Validity attribute should be a integer");
312: }
313: }
314:
315: /**
316: * If true, verbose output when signing.
317: * @param verbose verbose or not
318: */
319: public void setVerbose(final boolean verbose) {
320: this .verbose = verbose;
321: }
322:
323: /**
324: * Execute the task.
325: * @throws BuildException on error
326: */
327: public void execute() throws BuildException {
328:
329: if (null == alias) {
330: throw new BuildException("alias attribute must be set");
331: }
332:
333: if (null == storepass) {
334: throw new BuildException("storepass attribute must be set");
335: }
336:
337: if (null == dname && null == expandedDname) {
338: throw new BuildException("dname must be set");
339: }
340:
341: final StringBuffer sb = new StringBuffer();
342:
343: sb.append("-genkey ");
344:
345: if (verbose) {
346: sb.append("-v ");
347: }
348:
349: sb.append("-alias \"");
350: sb.append(alias);
351: sb.append("\" ");
352:
353: if (null != dname) {
354: sb.append("-dname \"");
355: sb.append(dname);
356: sb.append("\" ");
357: }
358:
359: if (null != expandedDname) {
360: sb.append("-dname \"");
361: sb.append(expandedDname);
362: sb.append("\" ");
363: }
364:
365: if (null != keystore) {
366: sb.append("-keystore \"");
367: sb.append(keystore);
368: sb.append("\" ");
369: }
370:
371: if (null != storepass) {
372: sb.append("-storepass \"");
373: sb.append(storepass);
374: sb.append("\" ");
375: }
376:
377: if (null != storetype) {
378: sb.append("-storetype \"");
379: sb.append(storetype);
380: sb.append("\" ");
381: }
382:
383: sb.append("-keypass \"");
384: if (null != keypass) {
385: sb.append(keypass);
386: } else {
387: sb.append(storepass);
388: }
389: sb.append("\" ");
390:
391: if (null != sigalg) {
392: sb.append("-sigalg \"");
393: sb.append(sigalg);
394: sb.append("\" ");
395: }
396:
397: if (null != keyalg) {
398: sb.append("-keyalg \"");
399: sb.append(keyalg);
400: sb.append("\" ");
401: }
402:
403: if (0 < keysize) {
404: sb.append("-keysize \"");
405: sb.append(keysize);
406: sb.append("\" ");
407: }
408:
409: if (0 < validity) {
410: sb.append("-validity \"");
411: sb.append(validity);
412: sb.append("\" ");
413: }
414:
415: log("Generating Key for " + alias);
416: final ExecTask cmd = new ExecTask(this );
417: cmd.setExecutable(JavaEnvUtils.getJdkExecutable("keytool"));
418: Commandline.Argument arg = cmd.createArg();
419: arg.setLine(sb.toString());
420: cmd.setFailonerror(true);
421: cmd.setTaskName(getTaskName());
422: cmd.execute();
423: }
424: }
|