source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/types/CommandlineJava.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 20.4 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.types;
19
20import org.apache.tools.ant.BuildException;
21import org.apache.tools.ant.Project;
22import org.apache.tools.ant.util.JavaEnvUtils;
23
24import java.util.Enumeration;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.ListIterator;
28import java.util.Properties;
29import java.util.Vector;
30
31/**
32 * A representation of a Java command line that is
33 * a composite of 2 <tt>Commandline</tt>. One is used for the
34 * vm/options and one for the classname/arguments. It provides
35 * specific methods for a java command line.
36 *
37 */
38public class CommandlineJava implements Cloneable {
39
40 /**
41 * commands to the JVM
42 */
43 private Commandline vmCommand = new Commandline();
44 /**
45 * actual java commands
46 */
47 private Commandline javaCommand = new Commandline();
48 /**
49 * properties to add using -D
50 */
51 private SysProperties sysProperties = new SysProperties();
52 private Path classpath = null;
53 private Path bootclasspath = null;
54 private String vmVersion;
55 private String maxMemory = null;
56 /**
57 * any assertions to make? Currently only supported in forked JVMs
58 */
59 private Assertions assertions = null;
60
61 /**
62 * Indicate whether it will execute a jar file or not, in this case
63 * the first vm option must be a -jar and the 'executable' is a jar file.
64 */
65 private boolean executeJar = false;
66
67 /**
68 * Specialized Environment class for System properties
69 */
70 public static class SysProperties extends Environment implements Cloneable {
71 Properties sys = null;
72 private Vector propertySets = new Vector();
73
74 /**
75 * get the properties as an array; this is an override of the
76 * superclass, as it evaluates all the properties
77 * @return the array of definitions; may be null
78 * @throws BuildException on error
79 */
80 public String[] getVariables() throws BuildException {
81
82 List definitions = new LinkedList();
83 ListIterator list = definitions.listIterator();
84 addDefinitionsToList(list);
85 if (definitions.size() == 0) {
86 return null;
87 } else {
88 return (String[]) definitions.toArray(new String[0]);
89 }
90 }
91
92 /**
93 * add all definitions (including property sets) to a list
94 * @param listIt list iterator supporting add method
95 */
96 public void addDefinitionsToList(ListIterator listIt) {
97 String[] props = super.getVariables();
98 if (props != null) {
99 for (int i = 0; i < props.length; i++) {
100 listIt.add("-D" + props[i]);
101 }
102 }
103 Properties propertySetProperties = mergePropertySets();
104 for (Enumeration e = propertySetProperties.keys();
105 e.hasMoreElements();) {
106 String key = (String) e.nextElement();
107 String value = propertySetProperties.getProperty(key);
108 listIt.add("-D" + key + "=" + value);
109 }
110 }
111
112 /**
113 * This method gets the size of the sysproperties instance. This merges all
114 * property sets, so is not an O(1) operation.
115 * @return the size of the sysproperties instance
116 */
117 public int size() {
118 Properties p = mergePropertySets();
119 return variables.size() + p.size();
120 }
121
122 /**
123 * cache the system properties and set the system properties to the
124 * new values
125 * @throws BuildException if Security prevented this operation
126 */
127 public void setSystem() throws BuildException {
128 try {
129 sys = System.getProperties();
130 Properties p = new Properties();
131 for (Enumeration e = sys.propertyNames(); e.hasMoreElements();) {
132 String name = (String) e.nextElement();
133 p.put(name, sys.getProperty(name));
134 }
135 p.putAll(mergePropertySets());
136 for (Enumeration e = variables.elements(); e.hasMoreElements();) {
137 Environment.Variable v = (Environment.Variable) e.nextElement();
138 v.validate();
139 p.put(v.getKey(), v.getValue());
140 }
141 System.setProperties(p);
142 } catch (SecurityException e) {
143 throw new BuildException("Cannot modify system properties", e);
144 }
145 }
146
147 /**
148 * restore the system properties to the cached value
149 * @throws BuildException if Security prevented this operation, or
150 * there was no system properties to restore
151 */
152 public void restoreSystem() throws BuildException {
153 if (sys == null) {
154 throw new BuildException("Unbalanced nesting of SysProperties");
155 }
156
157 try {
158 System.setProperties(sys);
159 sys = null;
160 } catch (SecurityException e) {
161 throw new BuildException("Cannot modify system properties", e);
162 }
163 }
164
165 /**
166 * deep clone
167 * @return a cloned instance of SysProperties
168 * @exception CloneNotSupportedException for signature
169 */
170 public Object clone() throws CloneNotSupportedException {
171 try {
172 SysProperties c = (SysProperties) super.clone();
173 c.variables = (Vector) variables.clone();
174 c.propertySets = (Vector) propertySets.clone();
175 return c;
176 } catch (CloneNotSupportedException e) {
177 return null;
178 }
179 }
180
181 /**
182 * add a propertyset to the total set
183 * @param ps the new property set
184 */
185 public void addSyspropertyset(PropertySet ps) {
186 propertySets.addElement(ps);
187 }
188
189 /**
190 * add a propertyset to the total set
191 * @param ps the new property set
192 * @since Ant 1.6.3
193 */
194 public void addSysproperties(SysProperties ps) {
195 variables.addAll(ps.variables);
196 propertySets.addAll(ps.propertySets);
197 }
198
199 /**
200 * merge all property sets into a single Properties object
201 * @return the merged object
202 */
203 private Properties mergePropertySets() {
204 Properties p = new Properties();
205 for (Enumeration e = propertySets.elements();
206 e.hasMoreElements();) {
207 PropertySet ps = (PropertySet) e.nextElement();
208 p.putAll(ps.getProperties());
209 }
210 return p;
211 }
212
213 }
214
215 /**
216 * constructor uses the VM we are running on now.
217 */
218 public CommandlineJava() {
219 setVm(JavaEnvUtils.getJreExecutable("java"));
220 setVmversion(JavaEnvUtils.getJavaVersion());
221 }
222
223 /**
224 * create a new argument to the java program
225 * @return an argument to be configured
226 */
227 public Commandline.Argument createArgument() {
228 return javaCommand.createArgument();
229 }
230
231 /**
232 * create a new JVM argument
233 * @return an argument to be configured
234 */
235 public Commandline.Argument createVmArgument() {
236 return vmCommand.createArgument();
237 }
238
239 /**
240 * add a system property
241 * @param sysp a property to be set in the JVM
242 */
243 public void addSysproperty(Environment.Variable sysp) {
244 sysProperties.addVariable(sysp);
245 }
246
247 /**
248 * add a set of system properties
249 * @param sysp a set of properties
250 */
251 public void addSyspropertyset(PropertySet sysp) {
252 sysProperties.addSyspropertyset(sysp);
253 }
254
255 /**
256 * add a set of system properties
257 * @param sysp a set of properties
258 * @since Ant 1.6.3
259 */
260 public void addSysproperties(SysProperties sysp) {
261 sysProperties.addSysproperties(sysp);
262 }
263
264 /**
265 * Set the executable used to start the new JVM.
266 * @param vm the executable to use
267 */
268 public void setVm(String vm) {
269 vmCommand.setExecutable(vm);
270 }
271
272 /**
273 * Set the JVM version required.
274 * @param value the version required
275 */
276 public void setVmversion(String value) {
277 vmVersion = value;
278 }
279
280
281 /**
282 * get the current assertions
283 * @return assertions or null
284 */
285 public Assertions getAssertions() {
286 return assertions;
287 }
288
289 /**
290 * add an assertion set to the command
291 * @param assertions assertions to make
292 */
293 public void setAssertions(Assertions assertions) {
294 this.assertions = assertions;
295 }
296
297 /**
298 * set a jar file to execute via the -jar option.
299 * @param jarpathname the pathname of the jar to execute
300 */
301 public void setJar(String jarpathname) {
302 javaCommand.setExecutable(jarpathname);
303 executeJar = true;
304 }
305
306 /**
307 * @return the pathname of the jar file to run via -jar option
308 * or <tt>null</tt> if there is no jar to run.
309 * @see #getClassname()
310 */
311 public String getJar() {
312 if (executeJar) {
313 return javaCommand.getExecutable();
314 }
315 return null;
316 }
317
318 /**
319 * set the classname to execute
320 * @param classname the fully qualified classname.
321 */
322 public void setClassname(String classname) {
323 javaCommand.setExecutable(classname);
324 executeJar = false;
325 }
326
327 /**
328 * @return the name of the class to run or <tt>null</tt> if there is no class.
329 * @see #getJar()
330 */
331 public String getClassname() {
332 if (!executeJar) {
333 return javaCommand.getExecutable();
334 }
335 return null;
336 }
337
338 /**
339 * Create a classpath.
340 * @param p the project to use to create the path in
341 * @return a path to be configured
342 */
343 public Path createClasspath(Project p) {
344 if (classpath == null) {
345 classpath = new Path(p);
346 }
347 return classpath;
348 }
349
350 /**
351 * Create a boot classpath.
352 * @param p the project to use to create the path in
353 * @return a path to be configured
354 * @since Ant 1.6
355 */
356 public Path createBootclasspath(Project p) {
357 if (bootclasspath == null) {
358 bootclasspath = new Path(p);
359 }
360 return bootclasspath;
361 }
362
363 /**
364 * Get the vm version.
365 * @return the vm version
366 */
367 public String getVmversion() {
368 return vmVersion;
369 }
370
371 /**
372 * get the command line to run a java vm.
373 * @return the list of all arguments necessary to run the vm.
374 */
375 public String[] getCommandline() {
376 //create the list
377 List commands = new LinkedList();
378 final ListIterator listIterator = commands.listIterator();
379 //fill it
380 addCommandsToList(listIterator);
381 //convert to an array
382 return (String[]) commands.toArray(new String[0]);
383 }
384
385 /**
386 * add all the commands to a list identified by the iterator passed in
387 * @param listIterator an iterator that supports the add method
388 * @since Ant1.6
389 */
390 private void addCommandsToList(final ListIterator listIterator) {
391 //create the command to run Java, including user specified options
392 getActualVMCommand().addCommandToList(listIterator);
393 // properties are part of the vm options...
394 sysProperties.addDefinitionsToList(listIterator);
395 //boot classpath
396 if (haveBootclasspath(true)) {
397 listIterator.add("-Xbootclasspath:" + bootclasspath.toString());
398 }
399
400 //main classpath
401 if (haveClasspath()) {
402 listIterator.add("-classpath");
403 listIterator.add(
404 classpath.concatSystemClasspath("ignore").toString());
405 }
406
407 //now any assertions are added
408 if (getAssertions() != null) {
409 getAssertions().applyAssertions(listIterator);
410 }
411
412 // JDK usage command line says that -jar must be the first option, as there is
413 // a bug in JDK < 1.4 that forces the jvm type to be specified as the first
414 // option, it is appended here as specified in the docs even though there is
415 // in fact no order.
416 if (executeJar) {
417 listIterator.add("-jar");
418 }
419 // this is the classname to run as well as its arguments.
420 // in case of 'executeJar', the executable is a jar file.
421 javaCommand.addCommandToList(listIterator);
422 }
423
424 /**
425 * Specify max memory of the JVM
426 * -mx or -Xmx depending on VM version
427 * @param max the string to pass to the jvm to specifiy the max memory
428 */
429 public void setMaxmemory(String max) {
430 this.maxMemory = max;
431 }
432
433
434 /**
435 * get a string description.
436 * @return the command line as a string
437 */
438 public String toString() {
439 return Commandline.toString(getCommandline());
440 }
441
442 /**
443 * Returns a String that describes the command and arguments
444 * suitable for verbose output before a call to
445 * <code>Runtime.exec(String[])<code>
446 * @return the description string
447 * @since Ant 1.5
448 */
449 public String describeCommand() {
450 return Commandline.describeCommand(getCommandline());
451 }
452
453 /**
454 * Returns a String that describes the java command and arguments
455 * for in VM executions.
456 *
457 * <p>The class name is the executable in this context.</p>
458 * @return the description string
459 * @since Ant 1.5
460 */
461 public String describeJavaCommand() {
462 return Commandline.describeCommand(getJavaCommand());
463 }
464
465 /**
466 * Get the VM command parameters, including memory settings
467 * @return the VM command parameters
468 */
469 protected Commandline getActualVMCommand() {
470 Commandline actualVMCommand = (Commandline) vmCommand.clone();
471 if (maxMemory != null) {
472 if (vmVersion.startsWith("1.1")) {
473 actualVMCommand.createArgument().setValue("-mx" + maxMemory);
474 } else {
475 actualVMCommand.createArgument().setValue("-Xmx" + maxMemory);
476 }
477 }
478 return actualVMCommand;
479 }
480
481 /**
482 * The size of the java command line. This is a fairly intensive
483 * operation, as it has to evaluate the size of many components.
484 * @return the total number of arguments in the java command line.
485 * @see #getCommandline()
486 * @deprecated please dont use this -it effectively creates the entire command.
487 */
488 public int size() {
489 int size = getActualVMCommand().size() + javaCommand.size()
490 + sysProperties.size();
491 // classpath is "-classpath <classpath>" -> 2 args
492 if (haveClasspath()) {
493 size += 2;
494 }
495 // bootclasspath is "-Xbootclasspath:<classpath>" -> 1 arg
496 if (haveBootclasspath(true)) {
497 size++;
498 }
499 // jar execution requires an additional -jar option
500 if (executeJar) {
501 size++;
502 }
503 //assertions take up space too
504 if (getAssertions() != null) {
505 size += getAssertions().size();
506 }
507 return size;
508 }
509
510 /**
511 * get the Java command to be used.
512 * @return the java command -not a clone.
513 */
514 public Commandline getJavaCommand() {
515 return javaCommand;
516 }
517
518 /**
519 * Get the VM command, including memory.
520 * @return A deep clone of the instance's VM command, with memory settings added
521 */
522 public Commandline getVmCommand() {
523 return getActualVMCommand();
524 }
525
526 /**
527 * get the classpath for the command
528 * @return the classpath or null
529 */
530 public Path getClasspath() {
531 return classpath;
532 }
533
534 /**
535 * get the boot classpath
536 * @return boot classpath or null
537 */
538 public Path getBootclasspath() {
539 return bootclasspath;
540 }
541
542 /**
543 * cache current system properties and set them to those in this
544 * java command
545 * @throws BuildException if Security prevented this operation
546 */
547 public void setSystemProperties() throws BuildException {
548 sysProperties.setSystem();
549 }
550
551 /**
552 * @throws BuildException if Security prevented this operation, or
553 * there was no system properties to restore
554 */
555 public void restoreSystemProperties() throws BuildException {
556 sysProperties.restoreSystem();
557 }
558
559 /**
560 * get the system properties object
561 * @return The system properties object
562 */
563 public SysProperties getSystemProperties() {
564 return sysProperties;
565 }
566
567 /**
568 * clone the object; clone of all fields in the class
569 * @return a CommandlineJava object
570 * @throws BuildException if anything went wrong.
571 * @throws CloneNotSupportedException never
572 */
573 public Object clone() throws CloneNotSupportedException {
574 try {
575 CommandlineJava c = (CommandlineJava) super.clone();
576 c.vmCommand = (Commandline) vmCommand.clone();
577 c.javaCommand = (Commandline) javaCommand.clone();
578 c.sysProperties = (SysProperties) sysProperties.clone();
579 if (classpath != null) {
580 c.classpath = (Path) classpath.clone();
581 }
582 if (bootclasspath != null) {
583 c.bootclasspath = (Path) bootclasspath.clone();
584 }
585 if (assertions != null) {
586 c.assertions = (Assertions) assertions.clone();
587 }
588 return c;
589 } catch (CloneNotSupportedException e) {
590 throw new BuildException(e);
591 }
592 }
593
594 /**
595 * Clear out the java arguments.
596 */
597 public void clearJavaArgs() {
598 javaCommand.clearArgs();
599 }
600
601 /**
602 * Has the classpath been specified and shall it really be used or
603 * will build.sysclasspath null it?
604 * @return true if the classpath is to be used
605 * @since Ant 1.6
606 */
607 protected boolean haveClasspath() {
608 Path fullClasspath = classpath != null
609 ? classpath.concatSystemClasspath("ignore") : null;
610 return fullClasspath != null
611 && fullClasspath.toString().trim().length() > 0;
612 }
613
614 /**
615 * Has the bootclasspath been specified and shall it really be
616 * used (build.sysclasspath could be set or the VM may not support
617 * it)?
618 *
619 * @param log whether to log a warning if a bootclasspath has been
620 * specified but will be ignored.
621 * @return true if the bootclasspath is to be used
622 * @since Ant 1.6
623 */
624 protected boolean haveBootclasspath(boolean log) {
625 if (bootclasspath != null
626 && bootclasspath.toString().trim().length() > 0) {
627
628 if (!bootclasspath.toString()
629 .equals(bootclasspath.concatSystemClasspath("ignore")
630 .toString())) {
631 if (log) {
632 bootclasspath.log("Ignoring bootclasspath as "
633 + "build.sysclasspath has been set.");
634 }
635 } else if (vmVersion.startsWith("1.1")) {
636 if (log) {
637 bootclasspath.log("Ignoring bootclasspath as "
638 + "the target VM doesn't support it.");
639 }
640 } else {
641 return true;
642 }
643 }
644 return false;
645 }
646
647}
Note: See TracBrowser for help on using the repository browser.