If set, the forked VM will be configured to match the currently running VM closely. This involves: * copying of all system properties. * copying of the bootclasspath - only if no bootclasspath has been specified explicitly or build.sysclasspath has been set to "only". This is accompanied by a magic system property build.clonevm that can be used to force the attribute to be set. It has to be a system property as CommandlineJava doesn't know about project instances. PR: 25327 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275775 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -329,6 +329,19 @@ public class Java extends Task { | |||||
| cmdl.createArgument().setLine(s); | 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. | |||||
| * | |||||
| * <p>Doesn't have any effect unless fork is true.</p> | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public void setCloneVm(boolean cloneVm) { | |||||
| cmdl.setCloneVm(cloneVm); | |||||
| } | |||||
| /** | /** | ||||
| * Adds a command-line argument. | * Adds a command-line argument. | ||||
| * | * | ||||
| @@ -587,6 +587,19 @@ public class JUnitTask extends Task { | |||||
| return perm; | 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. | |||||
| * | |||||
| * <p>Doesn't have any effect unless fork is true.</p> | |||||
| * | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public void setCloneVm(boolean cloneVm) { | |||||
| commandline.setCloneVm(cloneVm); | |||||
| } | |||||
| /** | /** | ||||
| * Creates a new JUnitRunner and enables fork of a new Java VM. | * Creates a new JUnitRunner and enables fork of a new Java VM. | ||||
| * | * | ||||
| @@ -104,6 +104,12 @@ public class CommandlineJava implements Cloneable { | |||||
| */ | */ | ||||
| private boolean executeJar = false; | 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 | * Specialized Environment class for System properties | ||||
| */ | */ | ||||
| @@ -294,6 +300,15 @@ public class CommandlineJava implements Cloneable { | |||||
| vmVersion = value; | 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 | * get the current assertions | ||||
| @@ -397,10 +412,26 @@ public class CommandlineJava implements Cloneable { | |||||
| getActualVMCommand().addCommandToList(listIterator); | getActualVMCommand().addCommandToList(listIterator); | ||||
| // properties are part of the vm options... | // properties are part of the vm options... | ||||
| sysProperties.addDefinitionsToList(listIterator); | 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 | //boot classpath | ||||
| if (haveBootclasspath(true)) { | if (haveBootclasspath(true)) { | ||||
| listIterator.add("-Xbootclasspath:" + bootclasspath.toString()); | listIterator.add("-Xbootclasspath:" + bootclasspath.toString()); | ||||
| } else if (cloneBootclasspath()) { | |||||
| listIterator.add("-Xbootclasspath:" + | |||||
| Path.systemBootClasspath.toString()); | |||||
| } | } | ||||
| //main classpath | //main classpath | ||||
| if (haveClasspath()) { | if (haveClasspath()) { | ||||
| listIterator.add("-classpath"); | listIterator.add("-classpath"); | ||||
| @@ -489,13 +520,19 @@ public class CommandlineJava implements Cloneable { | |||||
| * @deprecated please dont use this -it effectively creates the entire command. | * @deprecated please dont use this -it effectively creates the entire command. | ||||
| */ | */ | ||||
| public int size() { | 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 <classpath>" -> 2 args | // classpath is "-classpath <classpath>" -> 2 args | ||||
| if (haveClasspath()) { | if (haveClasspath()) { | ||||
| size += 2; | size += 2; | ||||
| } | } | ||||
| // bootclasspath is "-Xbootclasspath:<classpath>" -> 1 arg | // bootclasspath is "-Xbootclasspath:<classpath>" -> 1 arg | ||||
| if (haveBootclasspath(true)) { | |||||
| if (haveBootclasspath(true) || cloneBootclasspath()) { | |||||
| size++; | size++; | ||||
| } | } | ||||
| // jar execution requires an additional -jar option | // jar execution requires an additional -jar option | ||||
| @@ -648,4 +685,23 @@ public class CommandlineJava implements Cloneable { | |||||
| return false; | 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")); | |||||
| } | |||||
| } | } | ||||
| @@ -104,6 +104,15 @@ public class Path extends DataType implements Cloneable { | |||||
| new Path(null, System.getProperty("java.class.path")); | 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 <code><pathelement></code> values. | * Helper class, holds the nested <code><pathelement></code> values. | ||||
| */ | */ | ||||
| @@ -404,7 +413,7 @@ public class Path extends DataType implements Cloneable { | |||||
| public static String[] translatePath(Project project, String source) { | public static String[] translatePath(Project project, String source) { | ||||
| final Vector result = new Vector(); | final Vector result = new Vector(); | ||||
| if (source == null) { | if (source == null) { | ||||
| return new String[0]; | |||||
| return new String[0]; | |||||
| } | } | ||||
| PathTokenizer tok = new PathTokenizer(source); | PathTokenizer tok = new PathTokenizer(source); | ||||
| @@ -194,13 +194,15 @@ public class PropertySet extends DataType { | |||||
| public Properties getProperties() { | public Properties getProperties() { | ||||
| Vector names = null; | Vector names = null; | ||||
| Project prj = getProject(); | Project prj = getProject(); | ||||
| Hashtable props = | |||||
| prj == null ? System.getProperties() : prj.getProperties(); | |||||
| if (getDynamic() || cachedNames == null) { | if (getDynamic() || cachedNames == null) { | ||||
| names = new Vector(); // :TODO: should be a Set! | names = new Vector(); // :TODO: should be a Set! | ||||
| if (isReference()) { | if (isReference()) { | ||||
| getRef().addPropertyNames(names, prj.getProperties()); | |||||
| getRef().addPropertyNames(names, props); | |||||
| } else { | } else { | ||||
| addPropertyNames(names, prj.getProperties()); | |||||
| addPropertyNames(names, props); | |||||
| } | } | ||||
| if (!getDynamic()) { | if (!getDynamic()) { | ||||
| @@ -218,7 +220,7 @@ public class PropertySet extends DataType { | |||||
| Properties properties = new Properties(); | Properties properties = new Properties(); | ||||
| for (Enumeration e = names.elements(); e.hasMoreElements();) { | for (Enumeration e = names.elements(); e.hasMoreElements();) { | ||||
| String name = (String) e.nextElement(); | String name = (String) e.nextElement(); | ||||
| String value = prj.getProperty(name); | |||||
| String value = (String) props.get(name); | |||||
| if (mapper != null) { | if (mapper != null) { | ||||
| String[] newname = mapper.mapFileName(name); | String[] newname = mapper.mapFileName(name); | ||||
| if (newname != null) { | if (newname != null) { | ||||
| @@ -243,7 +245,7 @@ public class PropertySet extends DataType { | |||||
| for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) { | for (Enumeration e = ptyRefs.elements(); e.hasMoreElements();) { | ||||
| PropertyRef ref = (PropertyRef) e.nextElement(); | PropertyRef ref = (PropertyRef) e.nextElement(); | ||||
| if (ref.name != null) { | if (ref.name != null) { | ||||
| if (prj.getProperty(ref.name) != null) { | |||||
| if (prj != null && prj.getProperty(ref.name) != null) { | |||||
| names.addElement(ref.name); | names.addElement(ref.name); | ||||
| } | } | ||||
| } else if (ref.prefix != null) { | } else if (ref.prefix != null) { | ||||