diff --git a/src/main/org/apache/tools/ant/taskdefs/Java.java b/src/main/org/apache/tools/ant/taskdefs/Java.java index 0bba65b9d..431255ba2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Java.java +++ b/src/main/org/apache/tools/ant/taskdefs/Java.java @@ -67,6 +67,7 @@ import org.apache.tools.ant.types.Environment; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.Assertions; /** * Launcher for Java applications. Allows use of @@ -94,6 +95,7 @@ public class Java extends Task { private Long timeout = null; private Redirector redirector = new Redirector(this); private String resultProperty; + private boolean spawn = false; private boolean incompatibleWithSpawn = false; /** @@ -329,7 +331,7 @@ public class Java extends Task { protected void maybeSetResultPropertyValue(int result) { String res = Integer.toString(result); if (resultProperty != null) { - project.setNewProperty(resultProperty, res); + getProject().setNewProperty(resultProperty, res); } } @@ -560,6 +562,15 @@ public class Java extends Task { incompatibleWithSpawn = true; } + /** + * assertions to enable in this program (if fork=true) + * @since Ant 1.6 + * @param asserts assertion set + */ + public void setAssertions(Assertions asserts) { + cmdl.setAssertions(asserts); + } + /** * Pass output sent to System.out to specified output file. * diff --git a/src/main/org/apache/tools/ant/types/Assertions.java b/src/main/org/apache/tools/ant/types/Assertions.java index 44575dd8c..75a46f72c 100644 --- a/src/main/org/apache/tools/ant/types/Assertions.java +++ b/src/main/org/apache/tools/ant/types/Assertions.java @@ -111,7 +111,7 @@ public class Assertions extends DataType { /** * list of type BaseAssertion */ - private List assertionList = new ArrayList(); + private ArrayList assertionList = new ArrayList(); /** @@ -172,6 +172,47 @@ public class Assertions extends DataType { } } + /** + * how many assertions are made...will resolve references before returning + * @return total # of commands to make + */ + public int size() { + Assertions clause = getFinalReference(); + return clause.getFinalSize(); + } + + + /** + * what is the final size of this object + * @return + */ + private int getFinalSize() { + return assertionList.size()+ (enableSystemAssertions!=null?1:0); + } + + /** + * add the assertions to a list in a format suitable + * for adding to a command line + * @param commandList + */ + public void applyAssertions(List commandList) { + Assertions clause = getFinalReference(); + //do the system assertions + if (Boolean.TRUE.equals(clause.enableSystemAssertions)) { + commandList.add("-enablesystemassertions"); + } else if (Boolean.FALSE.equals(clause.enableSystemAssertions)) { + commandList.add("-disablesystemassertions"); + } + + //now any inner assertions + Iterator it = clause.assertionList.iterator(); + while (it.hasNext()) { + BaseAssertion assertion = (BaseAssertion) it.next(); + String arg = assertion.toCommand(); + commandList.add(arg); + } + } + /** * apply all the assertions to the command. * @param command @@ -205,6 +246,19 @@ public class Assertions extends DataType { argument.setValue(arg); } + /** + * clone the objects. + * This is not a full depth clone; the list of assertions is cloned, + * but it does not clone the underlying assertions. + * @return a cli + * @throws CloneNotSupportedException + */ + protected Object clone() throws CloneNotSupportedException { + Assertions that=(Assertions) super.clone(); + that.assertionList=(ArrayList) assertionList.clone(); + return that; + } + /** * base class for our assertion elements. */ diff --git a/src/main/org/apache/tools/ant/types/Commandline.java b/src/main/org/apache/tools/ant/types/Commandline.java index c334a25a4..9133be8de 100644 --- a/src/main/org/apache/tools/ant/types/Commandline.java +++ b/src/main/org/apache/tools/ant/types/Commandline.java @@ -57,6 +57,11 @@ package org.apache.tools.ant.types; import java.io.File; import java.util.StringTokenizer; import java.util.Vector; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.LinkedList; + import org.apache.tools.ant.BuildException; import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.util.StringUtils; @@ -86,7 +91,14 @@ import org.apache.tools.ant.util.StringUtils; */ public class Commandline implements Cloneable { + /** + * The arguments of the command + */ private Vector arguments = new Vector(); + + /** + * the program to execute + */ private String executable = null; protected static final String DISCLAIMER = @@ -96,9 +108,14 @@ public class Commandline implements Cloneable { + "not part of the command." + StringUtils.LINE_SEP; - public Commandline(String to_process) { + /** + * create a command line from a string + * @param toProcess the line: the first element becomes the executable, the rest + * the arguments + */ + public Commandline(String toProcess) { super(); - String[] tmp = translateCommandline(to_process); + String[] tmp = translateCommandline(toProcess); if (tmp != null && tmp.length > 0) { setExecutable(tmp[0]); for (int i = 1; i < tmp.length; i++) { @@ -107,6 +124,9 @@ public class Commandline implements Cloneable { } } + /** + * Create an empty command line + */ public Commandline() { super(); } @@ -183,10 +203,10 @@ public class Commandline implements Cloneable { /** * Class to keep track of the position of an Argument. +
This class is there to support the srcfile and targetfile + elements of <execon> and <transform> - don't know + whether there might be additional use cases.
--SB */ - //This class is there to support the srcfile and targetfile - // elements of <execon> and <transform> - don't know - // whether there might be additional use cases.
--SB public class Marker { private int position; @@ -248,7 +268,8 @@ public class Commandline implements Cloneable { } /** - * Sets the executable to run. + * Sets the executable to run. All file separators in the string + * are converted to the platform specific value */ public void setExecutable(String executable) { if (executable == null || executable.length() == 0) { @@ -259,11 +280,19 @@ public class Commandline implements Cloneable { } + /** + * get the executable + * @return the program to run -null if not yet set + */ public String getExecutable() { return executable; } + /** + * append the arguments to the existing command + * @param line an array of arguments to append + */ public void addArguments(String[] line) { for (int i = 0; i < line.length; i++) { createArgument().setValue(line[i]); @@ -274,14 +303,23 @@ public class Commandline implements Cloneable { * Returns the executable and all defined arguments. */ public String[] getCommandline() { - final String[] args = getArguments(); - if (executable == null) { - return args; + List commands=new LinkedList(); + ListIterator list = commands.listIterator(); + addCommandToList(list); + final String[] result = new String[commands.size()]; + return (String[])commands.toArray(result); + } + + /** + * add the entire command, including (optional) executable to a list + * @param list + * @since Ant 1.6 + */ + public void addCommandToList(ListIterator list) { + if(executable!=null) { + list.add(executable); } - final String[] result = new String[args.length + 1]; - result[0] = executable; - System.arraycopy(args, 0, result, 1, args.length); - return result; + addArgumentsToList(list); } @@ -290,23 +328,34 @@ public class Commandline implements Cloneable { *addValue
or the argument object.
*/
public String[] getArguments() {
- Vector result = new Vector(arguments.size() * 2);
+ List result = new ArrayList(arguments.size() * 2);
+ addArgumentsToList(result.listIterator());
+ String [] res = new String[result.size()];
+ return (String[])result.toArray(res);
+ }
+
+ /**
+ * append all the arguments to the tail of a supplied list
+ * @param list
+ * @since Ant 1.6
+ */
+ public void addArgumentsToList(ListIterator list) {
for (int i = 0; i < arguments.size(); i++) {
Argument arg = (Argument) arguments.elementAt(i);
String[] s = arg.getParts();
if (s != null) {
for (int j = 0; j < s.length; j++) {
- result.addElement(s[j]);
+ list.add(s[j]);
}
}
}
-
- String [] res = new String[result.size()];
- result.copyInto(res);
- return res;
}
+ /**
+ * stringify operator returns the command line as a string
+ * @return the command line
+ */
public String toString() {
return toString(getCommandline());
}
@@ -324,7 +373,8 @@ public class Commandline implements Cloneable {
public static String quoteArgument(String argument) {
if (argument.indexOf("\"") > -1) {
if (argument.indexOf("\'") > -1) {
- throw new BuildException("Can\'t handle single and double quotes in same argument");
+ throw new BuildException("Can\'t handle single and double"
+ +" quotes in same argument");
} else {
return '\'' + argument + '\'';
}
@@ -338,6 +388,8 @@ public class Commandline implements Cloneable {
/**
* Quotes the parts of the given array in way that makes them
* usable as command line arguments.
+ * @return empty string for null or no command, else every argument split
+ * by spaces and quoted by quoting rules
*/
public static String toString(String [] line) {
// empty path return empty string
@@ -356,8 +408,15 @@ public class Commandline implements Cloneable {
return result.toString();
}
- public static String[] translateCommandline(String to_process) {
- if (to_process == null || to_process.length() == 0) {
+ /**
+ * crack a command line
+ * @param toProcess the command line to process
+ * @return the command line broken into strings.
+ * An empty or null toProcess parameter results in a zero sized array
+ */
+ public static String[] translateCommandline(String toProcess) {
+ if (toProcess == null || toProcess.length() == 0) {
+ //no command? no string
return new String[0];
}
@@ -367,7 +426,7 @@ public class Commandline implements Cloneable {
final int inQuote = 1;
final int inDoubleQuote = 2;
int state = normal;
- StringTokenizer tok = new StringTokenizer(to_process, "\"\' ", true);
+ StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
Vector v = new Vector();
StringBuffer current = new StringBuffer();
boolean lastTokenHasBeenQuoted = false;
@@ -414,7 +473,7 @@ public class Commandline implements Cloneable {
}
if (state == inQuote || state == inDoubleQuote) {
- throw new BuildException("unbalanced quotes in " + to_process);
+ throw new BuildException("unbalanced quotes in " + toProcess);
}
String[] args = new String[v.size()];
@@ -422,10 +481,19 @@ public class Commandline implements Cloneable {
return args;
}
+ /**
+ * size operator. This actually creates the command line, so it is not
+ * a zero cost operation.
+ * @return number of elements in the command, including the executable
+ */
public int size() {
return getCommandline().length;
}
+ /**
+ * a deep clone of the contained object.
+ * @return
+ */
public Object clone() {
try {
Commandline c = (Commandline) super.clone();
diff --git a/src/main/org/apache/tools/ant/types/CommandlineJava.java b/src/main/org/apache/tools/ant/types/CommandlineJava.java
index d05675af7..0d0276d3f 100644
--- a/src/main/org/apache/tools/ant/types/CommandlineJava.java
+++ b/src/main/org/apache/tools/ant/types/CommandlineJava.java
@@ -57,18 +57,24 @@ package org.apache.tools.ant.types;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.JavaEnvUtils;
/**
- * A representation of a Java command line that is nothing more
- * than a composite of 2 Commandline. One is used for the
+ * A representation of a Java command line that is
+ * a composite of 2 Commandline. One is used for the
* vm/options and one for the classname/arguments. It provides
* specific methods for a java command line.
*
* @author thomas.haas@softwired-inc.com
* @author Stephane Bailliez
+ * @author steve loughran
*/
public class CommandlineJava implements Cloneable {
@@ -88,6 +94,10 @@ public class CommandlineJava implements Cloneable {
private Path bootclasspath = null;
private String vmVersion;
private String maxMemory = null;
+ /**
+ * any assertions to make? Currently only supported in forked JVMs
+ */
+ private Assertions assertions=null;
/**
* Indicate whether it will execute a jar file or not, in this case
@@ -102,37 +112,58 @@ public class CommandlineJava implements Cloneable {
Properties sys = null;
private Vector propertySets = new Vector();
+ /**
+ * get the properties as an array; this is an override of the
+ * superclass, as it evaluates all the properties
+ * @return the array of definitions; may be null
+ * @throws BuildException
+ */
public String[] getVariables() throws BuildException {
- String[] props = super.getVariables();
- Properties p = mergePropertySets();
- if (props == null) {
- if (p.size() == 0) {
- return null;
- } else {
- props = new String[0];
- }
+ List definitions=new LinkedList();
+ ListIterator list=definitions.listIterator();
+ addDefinitionsToList(list);
+ if(definitions.size()==0) {
+ return null;
+ } else {
+ return (String[])definitions.toArray(new String[0]);
}
+ }
- String[] result = new String[props.length + p.size()];
- int i = 0;
- for (; i < props.length; i++) {
- result[i] = "-D" + props[i];
+ /**
+ * add all definitions (including property sets) to a list
+ * @param listIt list iterator supporting add method
+ */
+ public void addDefinitionsToList(ListIterator listIt) {
+ String[] props = super.getVariables();
+ if(props!=null) {
+ for (int i=0; i < props.length; i++) {
+ listIt.add("-D" + props[i]);
+ }
}
- for (Enumeration enum = p.keys(); enum.hasMoreElements();) {
+ Properties propertySets = mergePropertySets();
+ for (Enumeration enum = propertySets.keys(); enum.hasMoreElements();) {
String key = (String) enum.nextElement();
- String value = p.getProperty(key);
- result[i++] = "-D" + key + "=" + value;
+ String value = propertySets.getProperty(key);
+ listIt.add("-D" + key + "=" + value);
}
-
- return result;
}
+ /**
+ * get the size of the sysproperties instance. This merges all
+ * property sets, so is not an O(1) operation.
+ * @return
+ */
public int size() {
Properties p = mergePropertySets();
return variables.size() + p.size();
}
+ /**
+ * cache the system properties and set the system properties to the
+ * new values
+ * @throws BuildException if Security prevented this operation
+ */
public void setSystem() throws BuildException {
try {
sys = System.getProperties();
@@ -152,6 +183,11 @@ public class CommandlineJava implements Cloneable {
}
}
+ /**
+ * restore the system properties to the cached value
+ * @throws BuildException if Security prevented this operation, or
+ * there was no system properties to restore
+ */
public void restoreSystem() throws BuildException {
if (sys == null) {
throw new BuildException("Unbalanced nesting of SysProperties");
@@ -165,6 +201,10 @@ public class CommandlineJava implements Cloneable {
}
}
+ /**
+ * deep clone
+ * @return a cloned instance of SysProperties
+ */
public Object clone() {
try {
SysProperties c = (SysProperties) super.clone();
@@ -176,10 +216,18 @@ public class CommandlineJava implements Cloneable {
}
}
+ /**
+ * add a propertyset to the total set
+ * @param ps the new property set
+ */
public void addSyspropertyset(PropertySet ps) {
propertySets.addElement(ps);
}
+ /**
+ * merge all property sets into a single Properties object
+ * @return the merged object
+ */
private Properties mergePropertySets() {
Properties p = new Properties();
for (Enumeration e = propertySets.elements();
@@ -199,30 +247,71 @@ public class CommandlineJava implements Cloneable {
setVmversion(JavaEnvUtils.getJavaVersion());
}
+ /**
+ * create a new argument to the java program
+ * @return an argument to be configured
+ */
public Commandline.Argument createArgument() {
return javaCommand.createArgument();
}
+ /**
+ * create a new JVM argument
+ * @return an argument to be configured
+ */
public Commandline.Argument createVmArgument() {
return vmCommand.createArgument();
}
+ /**
+ * add a system property
+ * @param sysp a property to be set in the JVM
+ */
public void addSysproperty(Environment.Variable sysp) {
sysProperties.addVariable(sysp);
}
+ /**
+ * add a set of system properties
+ * @param sysp a set of properties
+ */
public void addSyspropertyset(PropertySet sysp) {
sysProperties.addSyspropertyset(sysp);
}
+ /**
+ * set the executable used to start the new JVM
+ * @param vm
+ */
public void setVm(String vm) {
vmCommand.setExecutable(vm);
}
+ /**
+ * set the JVM version required
+ * @param value
+ */
public void setVmversion(String value) {
vmVersion = value;
}
+
+ /**
+ * get the current assertions
+ * @return assertions or null
+ */
+ public Assertions getAssertions() {
+ return assertions;
+ }
+
+ /**
+ * add an assertion set to the command
+ * @param assertions assertions to make
+ */
+ public void setAssertions(Assertions assertions) {
+ this.assertions = assertions;
+ }
+
/**
* set a jar file to execute via the -jar option.
* @param jarpathname the pathname of the jar to execute
@@ -290,27 +379,39 @@ public class CommandlineJava implements Cloneable {
* @return the list of all arguments necessary to run the vm.
*/
public String[] getCommandline() {
- String[] result = new String[size()];
- int pos = 0;
- String[] vmArgs = getActualVMCommand().getCommandline();
- System.arraycopy(vmArgs, 0, result, pos, vmArgs.length);
- pos += vmArgs.length;
+ //create the list
+ List commands=new LinkedList();
+ final ListIterator listIterator = commands.listIterator();
+ //fill it
+ addCommandsToList(listIterator);
+ //convert to an array
+ return (String[])commands.toArray(new String[0]);
+ }
+
+ /**
+ * add all the commands to a list identified by the iterator passed in
+ * @param listIterator an iterator that supports the add method
+ * @since Ant1.6
+ */
+ private void addCommandsToList(final ListIterator listIterator) {
+ //create the command to run Java, including user specified options
+ getActualVMCommand().addCommandToList(listIterator);
// properties are part of the vm options...
- if (sysProperties.size() > 0) {
- System.arraycopy(sysProperties.getVariables(), 0,
- result, pos, sysProperties.size());
- pos += sysProperties.size();
+ sysProperties.addDefinitionsToList(listIterator);
+ //boot classpath
+ if (haveBootclasspath(true)) {
+ listIterator.add("-Xbootclasspath:" + bootclasspath.toString());
}
-
- // classpath and bootclasspath are vm options too..
- if (haveBootclasspath(false)) {
- result[pos++] = "-Xbootclasspath:" + bootclasspath.toString();
+ //main classpath
+ if (haveClasspath()) {
+ listIterator.add("-classpath");
+ listIterator.add(
+ classpath.concatSystemClasspath("ignore").toString());
}
- if (haveClasspath()) {
- result[pos++] = "-classpath";
- result[pos++] =
- classpath.concatSystemClasspath("ignore").toString();
+ //now any assertions are added
+ if (getAssertions() != null) {
+ getAssertions().applyAssertions(this);
}
// JDK usage command line says that -jar must be the first option, as there is
@@ -318,15 +419,11 @@ public class CommandlineJava implements Cloneable {
// option, it is appended here as specified in the docs even though there is
// in fact no order.
if (executeJar) {
- result[pos++] = "-jar";
+ listIterator.add("-jar");
}
-
// this is the classname to run as well as its arguments.
// in case of 'executeJar', the executable is a jar file.
- System.arraycopy(javaCommand.getCommandline(), 0,
- result, pos, javaCommand.size());
-
- return result;
+ javaCommand.addCommandToList(listIterator);
}
/**
@@ -339,7 +436,7 @@ public class CommandlineJava implements Cloneable {
/**
- * get a string description
+ * get a string description.
* @return the command line as a string
*/
public String toString() {
@@ -369,6 +466,10 @@ public class CommandlineJava implements Cloneable {
return Commandline.describeCommand(getJavaCommand());
}
+ /**
+ * Get the VM command parameters, including memory settings
+ * @return
+ */
private Commandline getActualVMCommand() {
Commandline actualVMCommand = (Commandline) vmCommand.clone();
if (maxMemory != null) {
@@ -382,9 +483,11 @@ public class CommandlineJava implements Cloneable {
}
/**
- * The size of the java command line.
+ * The size of the java command line. This is a fairly intensive
+ * operation, as it has to evaluate the size of many components.
* @return the total number of arguments in the java command line.
* @see #getCommandline()
+ * @deprecated please dont use this -it effectively creates the entire command.
*/
public int size() {
int size = getActualVMCommand().size() + javaCommand.size() + sysProperties.size();
@@ -400,39 +503,72 @@ public class CommandlineJava implements Cloneable {
if (executeJar) {
size++;
}
+ //assertions take up space too
+ if(getAssertions()!=null) {
+ size+=getAssertions().size();
+ }
return size;
}
+ /**
+ * get the Java command to be used.
+ * @return the java command -not a clone.
+ */
public Commandline getJavaCommand() {
return javaCommand;
}
+ /**
+ * Get the VM command, including memory.
+ * @return A deep clone of the instance's VM command, with memory settings added
+ */
public Commandline getVmCommand() {
return getActualVMCommand();
}
+ /**
+ * get the classpath for the command
+ * @return the classpath or null
+ */
public Path getClasspath() {
return classpath;
}
+ /**
+ * get the boot classpath
+ * @return boot classpath or null
+ */
public Path getBootclasspath() {
return bootclasspath;
}
+ /**
+ * cache current system properties and set them to those in this
+ * java command
+ * @throws BuildException if Security prevented this operation
+ */
public void setSystemProperties() throws BuildException {
sysProperties.setSystem();
}
+ /**
+ * @throws BuildException if Security prevented this operation, or
+ * there was no system properties to restore
+ */
public void restoreSystemProperties() throws BuildException {
sysProperties.restoreSystem();
}
+ /**
+ * get the system properties object
+ * @return
+ */
public SysProperties getSystemProperties() {
return sysProperties;
}
/**
- * clone the object; do a deep clone of all fields in the class
+ * clone the object; clone of all fields in the class
* @return a CommandlineJava object
*/
public Object clone() {
@@ -447,6 +583,9 @@ public class CommandlineJava implements Cloneable {
if (bootclasspath != null) {
c.bootclasspath = (Path) bootclasspath.clone();
}
+ if( assertions != null ) {
+ c.assertions = (Assertions) assertions.clone();
+ }
return c;
} catch (CloneNotSupportedException e) {
throw new BuildException(e);