diff --git a/src/main/org/apache/tools/ant/taskdefs/Java.java b/src/main/org/apache/tools/ant/taskdefs/Java.java index 9f947c03a..f491f9e3d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Java.java +++ b/src/main/org/apache/tools/ant/taskdefs/Java.java @@ -329,6 +329,19 @@ public class Java extends Task { cmdl.createArgument().setLine(s); } + /** + * If set, system properties will be copied to the cloned VM - as + * well as the bootclasspath unless you have explicitly specified + * a bootclaspath. + * + *

Doesn't have any effect unless fork is true.

+ * + * @since Ant 1.7 + */ + public void setCloneVm(boolean cloneVm) { + cmdl.setCloneVm(cloneVm); + } + /** * Adds a command-line argument. * diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java index 4fa47e038..99ba7dd3a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java @@ -587,6 +587,19 @@ public class JUnitTask extends Task { return perm; } + /** + * If set, system properties will be copied to the cloned VM - as + * well as the bootclasspath unless you have explicitly specified + * a bootclaspath. + * + *

Doesn't have any effect unless fork is true.

+ * + * @since Ant 1.7 + */ + public void setCloneVm(boolean cloneVm) { + commandline.setCloneVm(cloneVm); + } + /** * Creates a new JUnitRunner and enables fork of a new Java VM. * diff --git a/src/main/org/apache/tools/ant/types/CommandlineJava.java b/src/main/org/apache/tools/ant/types/CommandlineJava.java index 3bd58fb6b..52bf7d312 100644 --- a/src/main/org/apache/tools/ant/types/CommandlineJava.java +++ b/src/main/org/apache/tools/ant/types/CommandlineJava.java @@ -104,6 +104,12 @@ public class CommandlineJava implements Cloneable { */ private boolean executeJar = false; + /** + * Whether system properties and bootclasspath shall be cloned. + * @since Ant 1.7 + */ + private boolean cloneVm = false; + /** * Specialized Environment class for System properties */ @@ -294,6 +300,15 @@ public class CommandlineJava implements Cloneable { vmVersion = value; } + /** + * If set, system properties will be copied to the cloned VM - as + * well as the bootclasspath unless you have explicitly specified + * a bootclaspath. + * @since Ant 1.7 + */ + public void setCloneVm(boolean cloneVm) { + this.cloneVm = cloneVm; + } /** * get the current assertions @@ -397,10 +412,26 @@ public class CommandlineJava implements Cloneable { getActualVMCommand().addCommandToList(listIterator); // properties are part of the vm options... sysProperties.addDefinitionsToList(listIterator); + + if (isCloneVm()) { + SysProperties clonedSysProperties = new SysProperties(); + PropertySet ps = new PropertySet(); + PropertySet.BuiltinPropertySetName sys = + new PropertySet.BuiltinPropertySetName(); + sys.setValue("system"); + ps.appendBuiltin(sys); + clonedSysProperties.addSyspropertyset(ps); + clonedSysProperties.addDefinitionsToList(listIterator); + } + //boot classpath if (haveBootclasspath(true)) { listIterator.add("-Xbootclasspath:" + bootclasspath.toString()); + } else if (cloneBootclasspath()) { + listIterator.add("-Xbootclasspath:" + + Path.systemBootClasspath.toString()); } + //main classpath if (haveClasspath()) { listIterator.add("-classpath"); @@ -489,13 +520,19 @@ public class CommandlineJava implements Cloneable { * @deprecated please dont use this -it effectively creates the entire command. */ public int size() { - int size = getActualVMCommand().size() + javaCommand.size() + sysProperties.size(); + int size = getActualVMCommand().size() + javaCommand.size() + + sysProperties.size(); + // cloned system properties + if (isCloneVm()) { + size += System.getProperties().size(); + } + // classpath is "-classpath " -> 2 args if (haveClasspath()) { size += 2; } // bootclasspath is "-Xbootclasspath:" -> 1 arg - if (haveBootclasspath(true)) { + if (haveBootclasspath(true) || cloneBootclasspath()) { size++; } // jar execution requires an additional -jar option @@ -648,4 +685,23 @@ public class CommandlineJava implements Cloneable { return false; } + /** + * Should a bootclasspath argument be created to clone the current + * VM settings? + * + * @since Ant 1.7 + */ + private boolean cloneBootclasspath() { + return isCloneVm() && !vmVersion.startsWith("1.1") + && Path.systemBootClasspath.size() > 0; + } + + /** + * Has the cloneVm attribute or the magic property build.clonevm been set? + * + * @since 1.7 + */ + private boolean isCloneVm() { + return cloneVm || "true".equals(System.getProperty("build.clonevm")); + } } diff --git a/src/main/org/apache/tools/ant/types/Path.java b/src/main/org/apache/tools/ant/types/Path.java index c922651b5..60c67761d 100644 --- a/src/main/org/apache/tools/ant/types/Path.java +++ b/src/main/org/apache/tools/ant/types/Path.java @@ -104,6 +104,15 @@ public class Path extends DataType implements Cloneable { new Path(null, System.getProperty("java.class.path")); + /** + * The system bootclassspath as a Path object. + * + * @since Ant 1.7 + */ + public static Path systemBootClasspath = + new Path(null, System.getProperty("sun.boot.class.path")); + + /** * Helper class, holds the nested <pathelement> values. */ @@ -404,7 +413,7 @@ public class Path extends DataType implements Cloneable { public static String[] translatePath(Project project, String source) { final Vector result = new Vector(); if (source == null) { - return new String[0]; + return new String[0]; } PathTokenizer tok = new PathTokenizer(source); diff --git a/src/main/org/apache/tools/ant/types/PropertySet.java b/src/main/org/apache/tools/ant/types/PropertySet.java index 485be383c..c50906dfb 100644 --- a/src/main/org/apache/tools/ant/types/PropertySet.java +++ b/src/main/org/apache/tools/ant/types/PropertySet.java @@ -194,13 +194,15 @@ public class PropertySet extends DataType { public Properties getProperties() { Vector names = null; Project prj = getProject(); + Hashtable props = + prj == null ? System.getProperties() : prj.getProperties(); if (getDynamic() || cachedNames == null) { names = new Vector(); // :TODO: should be a Set! if (isReference()) { - getRef().addPropertyNames(names, prj.getProperties()); + getRef().addPropertyNames(names, props); } else { - addPropertyNames(names, prj.getProperties()); + addPropertyNames(names, props); } if (!getDynamic()) { @@ -218,7 +220,7 @@ public class PropertySet extends DataType { Properties properties = new Properties(); for (Enumeration e = names.elements(); e.hasMoreElements();) { String name = (String) e.nextElement(); - String value = prj.getProperty(name); + String value = (String) props.get(name); if (mapper != null) { String[] newname = mapper.mapFileName(name); if (newname != null) { @@ -243,7 +245,7 @@ public class PropertySet extends DataType { for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) { PropertyRef ref = (PropertyRef) e.nextElement(); if (ref.name != null) { - if (prj.getProperty(ref.name) != null) { + if (prj != null && prj.getProperty(ref.name) != null) { names.addElement(ref.name); } } else if (ref.prefix != null) {