| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.tools.ant.types; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Properties; |
| import java.util.Vector; |
| |
| 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 |
| * a composite of 2 <code>Commandline</code>s. One is used for the |
| * vm/options and one for the classname/arguments. It provides |
| * specific methods for a Java command line. |
| * |
| */ |
| public class CommandlineJava implements Cloneable { |
| |
| /** |
| * commands to the JVM |
| */ |
| private Commandline vmCommand = new Commandline(); |
| /** |
| * actual java commands |
| */ |
| private Commandline javaCommand = new Commandline(); |
| /** |
| * properties to add using -D |
| */ |
| private SysProperties sysProperties = new SysProperties(); |
| private Path classpath = null; |
| private Path bootclasspath = null; |
| private Path modulepath = null; |
| private Path upgrademodulepath = 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, module or main class. |
| * In this case of jar the first vm option must be a -jar and the 'executable' is a jar file. |
| * In case of module the first vm option is -m and the 'executable' is 'module/mainClass'. |
| */ |
| private ExecutableType executableType; |
| |
| /** |
| * Whether system properties and bootclasspath shall be cloned. |
| * @since Ant 1.7 |
| */ |
| private boolean cloneVm = false; |
| |
| /** |
| * Specialized Environment class for System properties. |
| */ |
| public static class SysProperties extends Environment implements Cloneable { |
| // CheckStyle:VisibilityModifier OFF - bc |
| /** the system properties. */ |
| Properties sys = null; |
| // CheckStyle:VisibilityModifier ON |
| private Vector<PropertySet> 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 on error. |
| */ |
| @Override |
| public String[] getVariables() throws BuildException { |
| |
| List<String> definitions = new LinkedList<>(); |
| addDefinitionsToList(definitions.listIterator()); |
| if (definitions.isEmpty()) { |
| return null; |
| } |
| return definitions.toArray(new String[definitions.size()]); |
| } |
| |
| /** |
| * Add all definitions (including property sets) to a list. |
| * @param listIt list iterator supporting add method. |
| */ |
| public void addDefinitionsToList(ListIterator<String> listIt) { |
| String[] props = super.getVariables(); |
| if (props != null) { |
| for (String prop : props) { |
| listIt.add("-D" + prop); |
| } |
| } |
| Properties propertySetProperties = mergePropertySets(); |
| for (String key : propertySetProperties.stringPropertyNames()) { |
| listIt.add("-D" + key + "=" + propertySetProperties.getProperty(key)); |
| } |
| } |
| |
| /** |
| * Get the size of the sysproperties instance. This merges all |
| * property sets, so is not an O(1) operation. |
| * @return the size of the sysproperties instance. |
| */ |
| 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(); |
| Properties p = new Properties(); |
| for (String name : sys.stringPropertyNames()) { |
| String value = sys.getProperty(name); |
| if (value != null) { |
| p.put(name, value); |
| } |
| } |
| p.putAll(mergePropertySets()); |
| for (Environment.Variable v : variables) { |
| v.validate(); |
| p.put(v.getKey(), v.getValue()); |
| } |
| System.setProperties(p); |
| } catch (SecurityException e) { |
| throw new BuildException("Cannot modify system properties", e); |
| } |
| } |
| |
| /** |
| * Restore the system properties to the cached value. |
| * @throws BuildException if Security prevented this operation, or |
| * there were no system properties to restore. |
| */ |
| public void restoreSystem() throws BuildException { |
| if (sys == null) { |
| throw new BuildException("Unbalanced nesting of SysProperties"); |
| } |
| |
| try { |
| System.setProperties(sys); |
| sys = null; |
| } catch (SecurityException e) { |
| throw new BuildException("Cannot modify system properties", e); |
| } |
| } |
| |
| /** |
| * Create a deep clone. |
| * @return a cloned instance of SysProperties. |
| * @exception CloneNotSupportedException for signature. |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public Object clone() throws CloneNotSupportedException { |
| try { |
| SysProperties c = (SysProperties) super.clone(); |
| c.variables = (Vector<Environment.Variable>) variables.clone(); |
| c.propertySets = (Vector<PropertySet>) propertySets.clone(); |
| return c; |
| } catch (CloneNotSupportedException e) { |
| return null; |
| } |
| } |
| |
| /** |
| * Add a propertyset to the total set. |
| * @param ps the new property set. |
| */ |
| public void addSyspropertyset(PropertySet ps) { |
| propertySets.addElement(ps); |
| } |
| |
| /** |
| * Add a propertyset to the total set. |
| * @param ps the new property set. |
| * @since Ant 1.6.3 |
| */ |
| public void addSysproperties(SysProperties ps) { |
| variables.addAll(ps.variables); |
| propertySets.addAll(ps.propertySets); |
| } |
| |
| /** |
| * Merge all property sets into a single Properties object. |
| * @return the merged object. |
| */ |
| private Properties mergePropertySets() { |
| Properties p = new Properties(); |
| for (PropertySet ps : propertySets) { |
| p.putAll(ps.getProperties()); |
| } |
| return p; |
| } |
| |
| } |
| |
| /** |
| * Constructor uses the VM we are running on now. |
| */ |
| public CommandlineJava() { |
| setVm(JavaEnvUtils.getJreExecutable("java")); |
| 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); |
| } |
| |
| /** |
| * Add a set of system properties. |
| * @param sysp a set of properties. |
| * @since Ant 1.6.3 |
| */ |
| public void addSysproperties(SysProperties sysp) { |
| sysProperties.addSysproperties(sysp); |
| } |
| |
| /** |
| * Set the executable used to start the new JVM. |
| * @param vm the executable to use. |
| */ |
| public void setVm(String vm) { |
| vmCommand.setExecutable(vm); |
| } |
| |
| /** |
| * Set the JVM version required. |
| * @param value the version required. |
| */ |
| public void setVmversion(String value) { |
| vmVersion = value; |
| } |
| |
| /** |
| * Set whether system properties will be copied to the cloned VM--as |
| * well as the bootclasspath unless you have explicitly specified |
| * a bootclasspath. |
| * @param cloneVm if true copy the system properties. |
| * @since Ant 1.7 |
| */ |
| public void setCloneVm(boolean cloneVm) { |
| this.cloneVm = cloneVm; |
| } |
| |
| /** |
| * 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. |
| */ |
| public void setJar(String jarpathname) { |
| javaCommand.setExecutable(jarpathname); |
| executableType = ExecutableType.JAR; |
| } |
| |
| /** |
| * Get the name of the jar to be run. |
| * @return the pathname of the jar file to run via -jar option |
| * or <code>null</code> if there is no jar to run. |
| * @see #getClassname() |
| */ |
| public String getJar() { |
| if (executableType == ExecutableType.JAR) { |
| return javaCommand.getExecutable(); |
| } |
| return null; |
| } |
| |
| /** |
| * Set the classname to execute. |
| * @param classname the fully qualified classname. |
| */ |
| public void setClassname(String classname) { |
| if (executableType == ExecutableType.MODULE) { |
| javaCommand.setExecutable(createModuleClassPair( |
| parseModuleFromModuleClassPair(javaCommand.getExecutable()), |
| classname), false); |
| } else { |
| javaCommand.setExecutable(classname); |
| executableType = ExecutableType.CLASS; |
| } |
| } |
| |
| /** |
| * Get the name of the class to be run. |
| * @return the name of the class to run or <code>null</code> if there is no class. |
| * @see #getJar() |
| */ |
| public String getClassname() { |
| if (executableType != null) { |
| switch (executableType) { |
| case CLASS: |
| return javaCommand.getExecutable(); |
| case MODULE: |
| return parseClassFromModuleClassPair(javaCommand.getExecutable()); |
| default: |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Set the source-file, to execute as single file source programs, a feature, available |
| * since Java 11. |
| * |
| * @param sourceFile The path to the source file |
| * @since Ant 1.10.5 |
| */ |
| public void setSourceFile(final String sourceFile) { |
| this.executableType = ExecutableType.SOURCE_FILE; |
| javaCommand.setExecutable(sourceFile); |
| } |
| |
| /** |
| * @return Returns the source-file to execute, if this command line has |
| * been {@link #setSourceFile(String) configured for single file source program |
| * execution}. Else returns null. |
| * @since Ant 1.10.5 |
| */ |
| public String getSourceFile() { |
| return this.executableType == ExecutableType.SOURCE_FILE ? this.javaCommand.getExecutable() : null; |
| } |
| |
| /** |
| * Set the module to execute. |
| * @param module the module name. |
| * @since 1.9.7 |
| */ |
| public void setModule(final String module) { |
| if (executableType == null) { |
| javaCommand.setExecutable(module); |
| } else { |
| switch (executableType) { |
| case JAR: |
| javaCommand.setExecutable(module, false); |
| break; |
| case CLASS: |
| javaCommand.setExecutable(createModuleClassPair(module, |
| javaCommand.getExecutable()), false); |
| break; |
| case MODULE: |
| javaCommand.setExecutable(createModuleClassPair(module, |
| parseClassFromModuleClassPair(javaCommand.getExecutable())), false); |
| break; |
| default: |
| } |
| } |
| executableType = ExecutableType.MODULE; |
| } |
| |
| /** |
| * Get the name of the module to be run. |
| * @return the name of the module to run or <code>null</code> if there is no module. |
| * @see #getJar() |
| * @see #getClassname() |
| * @since 1.9.7 |
| */ |
| public String getModule() { |
| if (executableType == ExecutableType.MODULE) { |
| return parseModuleFromModuleClassPair(javaCommand.getExecutable()); |
| } |
| return null; |
| } |
| |
| /** |
| * Create a classpath. |
| * @param p the project to use to create the path. |
| * @return a path to be configured. |
| */ |
| public Path createClasspath(Project p) { |
| if (classpath == null) { |
| classpath = new Path(p); |
| } |
| return classpath; |
| } |
| |
| /** |
| * Create a boot classpath. |
| * @param p the project to use to create the path. |
| * @return a path to be configured. |
| * @since Ant 1.6 |
| */ |
| public Path createBootclasspath(Project p) { |
| if (bootclasspath == null) { |
| bootclasspath = new Path(p); |
| } |
| return bootclasspath; |
| } |
| |
| /** |
| * Create a modulepath. |
| * @param p the project to use to create the path. |
| * @return a path to be configured. |
| * @since 1.9.7 |
| */ |
| public Path createModulepath(Project p) { |
| if (modulepath == null) { |
| modulepath = new Path(p); |
| } |
| return modulepath; |
| } |
| |
| /** |
| * Create an upgrademodulepath. |
| * @param p the project to use to create the path. |
| * @return a path to be configured. |
| * @since 1.9.7 |
| */ |
| public Path createUpgrademodulepath(Project p) { |
| if (upgrademodulepath == null) { |
| upgrademodulepath = new Path(p); |
| } |
| return upgrademodulepath; |
| } |
| |
| /** |
| * Get the vm version. |
| * @return the vm version. |
| */ |
| public String getVmversion() { |
| return vmVersion; |
| } |
| |
| /** |
| * Get the command line to run a Java vm. |
| * @return the list of all arguments necessary to run the vm. |
| */ |
| public String[] getCommandline() { |
| //create the list |
| List<String> commands = new LinkedList<>(); |
| //fill it |
| addCommandsToList(commands.listIterator()); |
| //convert to an array |
| return commands.toArray(new String[commands.size()]); |
| } |
| |
| /** |
| * Add all the commands to a list identified by the iterator passed in. |
| * @param listIterator an iterator that supports the add method. |
| * @since Ant 1.6 |
| */ |
| private void addCommandsToList(final ListIterator<String> listIterator) { |
| //create the command to run Java, including user specified options |
| 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 |
| Path bcp = calculateBootclasspath(true); |
| if (bcp.size() > 0) { |
| listIterator.add("-Xbootclasspath:" + bcp.toString()); |
| } |
| //main classpath |
| if (haveClasspath()) { |
| listIterator.add("-classpath"); |
| listIterator.add(classpath.concatSystemClasspath("ignore").toString()); |
| } |
| //module path |
| if (haveModulepath()) { |
| listIterator.add("--module-path"); |
| listIterator.add(modulepath.concatSystemClasspath("ignore").toString()); |
| } |
| //upgrade module path |
| if (haveUpgrademodulepath()) { |
| listIterator.add("--upgrade-module-path"); |
| listIterator.add(upgrademodulepath.concatSystemClasspath("ignore").toString()); |
| } |
| //now any assertions are added |
| if (getAssertions() != null) { |
| getAssertions().applyAssertions(listIterator); |
| } |
| // JDK usage command line says that -jar must be the first option, as there is |
| // a bug in JDK < 1.4 that forces the jvm type to be specified as the first |
| // option, it is appended here as specified in the docs even though there is |
| // in fact no order. |
| if (executableType == ExecutableType.JAR) { |
| listIterator.add("-jar"); |
| } else if (executableType == ExecutableType.MODULE) { |
| listIterator.add("-m"); |
| } |
| // this is the classname/source-file to run as well as its arguments. |
| // in case of ExecutableType.JAR, the executable is a jar file, |
| // in case of ExecutableType.MODULE, the executable is a module name, potentially including a class name. |
| // in case of ExecutableType.SOURCE_FILE, the executable is a Java source file (ending in .java) or a shebang |
| // file containing Java source |
| javaCommand.addCommandToList(listIterator); |
| } |
| |
| /** |
| * Specify max memory of the JVM. |
| * -mx or -Xmx depending on VM version. |
| * @param max the string to pass to the jvm to specify the max memory. |
| */ |
| public void setMaxmemory(String max) { |
| this.maxMemory = max; |
| } |
| |
| /** |
| * Get a string description. |
| * @return the command line as a string. |
| */ |
| @Override |
| public String toString() { |
| return Commandline.toString(getCommandline()); |
| } |
| |
| /** |
| * Return a String that describes the command and arguments suitable for |
| * verbose output before a call to <code>Runtime.exec(String[])</code>. |
| * @return the description string. |
| * @since Ant 1.5 |
| */ |
| public String describeCommand() { |
| return Commandline.describeCommand(getCommandline()); |
| } |
| |
| /** |
| * Return a String that describes the java command and arguments |
| * for in-VM executions. |
| * |
| * <p>The class name is the executable in this context.</p> |
| * @return the description string. |
| * @since Ant 1.5 |
| */ |
| public String describeJavaCommand() { |
| return Commandline.describeCommand(getJavaCommand()); |
| } |
| |
| /** |
| * Get the VM command parameters, including memory settings. |
| * @return the VM command parameters. |
| */ |
| protected Commandline getActualVMCommand() { |
| Commandline actualVMCommand = (Commandline) vmCommand.clone(); |
| if (maxMemory != null) { |
| if (vmVersion.startsWith("1.1")) { |
| actualVMCommand.createArgument().setValue("-mx" + maxMemory); |
| } else { |
| actualVMCommand.createArgument().setValue("-Xmx" + maxMemory); |
| } |
| } |
| return actualVMCommand; |
| } |
| |
| /** |
| * Get 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 since 1.7. |
| * Please don't use this, it effectively creates the |
| * entire command. |
| */ |
| @Deprecated |
| public int size() { |
| int size = getActualVMCommand().size() + javaCommand.size() |
| + sysProperties.size(); |
| // cloned system properties |
| if (isCloneVm()) { |
| size += System.getProperties().size(); |
| } |
| // classpath is "-classpath <classpath>" -> 2 args |
| if (haveClasspath()) { |
| size += 2; |
| } |
| // bootclasspath is "-Xbootclasspath:<classpath>" -> 1 arg |
| if (calculateBootclasspath(true).size() > 0) { |
| size++; |
| } |
| // jar execution requires an additional -jar option |
| if (executableType == ExecutableType.JAR || executableType == ExecutableType.MODULE) { |
| 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; |
| } |
| |
| /** |
| * Get the modulepath. |
| * @return modulepath or null. |
| * @since 1.9.7 |
| */ |
| public Path getModulepath() { |
| return modulepath; |
| } |
| |
| /** |
| * Get the upgrademodulepath. |
| * @return upgrademodulepath or null. |
| * @since 1.9.7 |
| */ |
| public Path getUpgrademodulepath() { |
| return upgrademodulepath; |
| } |
| |
| /** |
| * 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(); |
| } |
| |
| /** |
| * Restore the cached system properties. |
| * @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 The system properties object. |
| */ |
| public SysProperties getSystemProperties() { |
| return sysProperties; |
| } |
| |
| /** |
| * Deep clone the object. |
| * @return a CommandlineJava object. |
| * @throws BuildException if anything went wrong. |
| * @throws CloneNotSupportedException never. |
| */ |
| @Override |
| public Object clone() throws CloneNotSupportedException { |
| try { |
| CommandlineJava c = (CommandlineJava) super.clone(); |
| c.vmCommand = (Commandline) vmCommand.clone(); |
| c.javaCommand = (Commandline) javaCommand.clone(); |
| c.sysProperties = (SysProperties) sysProperties.clone(); |
| if (classpath != null) { |
| c.classpath = (Path) classpath.clone(); |
| } |
| if (bootclasspath != null) { |
| c.bootclasspath = (Path) bootclasspath.clone(); |
| } |
| if (modulepath != null) { |
| c.modulepath = (Path) modulepath.clone(); |
| } |
| if (upgrademodulepath != null) { |
| c.upgrademodulepath = (Path) upgrademodulepath.clone(); |
| } |
| if (assertions != null) { |
| c.assertions = (Assertions) assertions.clone(); |
| } |
| return c; |
| } catch (CloneNotSupportedException e) { |
| throw new BuildException(e); |
| } |
| } |
| |
| /** |
| * Clear out the java arguments. |
| */ |
| public void clearJavaArgs() { |
| javaCommand.clearArgs(); |
| } |
| |
| /** |
| * Determine whether the classpath has been specified, and whether it shall |
| * really be used or be nulled by build.sysclasspath. |
| * @return true if the classpath is to be used. |
| * @since Ant 1.6 |
| */ |
| public boolean haveClasspath() { |
| Path fullClasspath = classpath == null ? null : classpath.concatSystemClasspath("ignore"); |
| return fullClasspath != null && !fullClasspath.toString().trim().isEmpty(); |
| } |
| |
| /** |
| * Determine whether the bootclasspath has been specified, and whether it |
| * shall really be used (build.sysclasspath could be set or the VM may not |
| * support it). |
| * |
| * @param log whether to log a warning if a bootclasspath has been |
| * specified but will be ignored. |
| * @return true if the bootclasspath is to be used. |
| * @since Ant 1.6 |
| */ |
| protected boolean haveBootclasspath(boolean log) { |
| return calculateBootclasspath(log).size() > 0; |
| } |
| |
| /** |
| * Determine whether the modulepath has been specified. |
| * @return true if the modulepath is to be used. |
| * @since 1.9.7 |
| */ |
| public boolean haveModulepath() { |
| Path fullClasspath = modulepath != null |
| ? modulepath.concatSystemClasspath("ignore") : null; |
| return fullClasspath != null |
| && !fullClasspath.toString().trim().isEmpty(); |
| } |
| |
| /** |
| * Determine whether the upgrademodulepath has been specified. |
| * @return true if the upgrademodulepath is to be used. |
| * @since 1.9.7 |
| */ |
| public boolean haveUpgrademodulepath() { |
| Path fullClasspath = upgrademodulepath != null |
| ? upgrademodulepath.concatSystemClasspath("ignore") : null; |
| return fullClasspath != null && !fullClasspath.toString().trim().isEmpty(); |
| } |
| |
| /** |
| * Calculate the bootclasspath based on the bootclasspath |
| * specified, the build.sysclasspath and ant.build.clonevm magic |
| * properties as well as the cloneVm attribute. |
| * @param log whether to write messages to the log. |
| * @since Ant 1.7 |
| */ |
| private Path calculateBootclasspath(boolean log) { |
| if (vmVersion.startsWith("1.1")) { |
| if (bootclasspath != null && log) { |
| bootclasspath.log("Ignoring bootclasspath as the target VM doesn't support it."); |
| } |
| } else { |
| Path b = bootclasspath; |
| if (b == null) { |
| b = new Path(null); |
| } |
| // even with no user-supplied bootclasspath |
| // build.sysclasspath could be set to something other than |
| // "ignore" and thus create one |
| return b.concatSystemBootClasspath(isCloneVm() ? "last" : "ignore"); |
| } |
| return new Path(null); |
| } |
| |
| /** |
| * Find out whether either of the cloneVm attribute or the magic property |
| * ant.build.clonevm has been set. |
| * @return <code>boolean</code>. |
| * @since 1.7 |
| */ |
| private boolean isCloneVm() { |
| return cloneVm || Boolean.parseBoolean(System.getProperty("ant.build.clonevm")); |
| } |
| |
| /** |
| * Creates JDK 9 main module command line argument. |
| * @param module the module name. |
| * @param classname the classname or <code>null</code>. |
| * @return the main module with optional classname command line argument. |
| * @since 1.9.7 |
| */ |
| private static String createModuleClassPair(final String module, final String classname) { |
| return classname == null ? module : String.format("%s/%s", module, classname); //NOI18N |
| } |
| |
| /** |
| * Parses a module name from JDK 9 main module command line argument. |
| * @param moduleClassPair a module with optional classname or <code>null</code>. |
| * @return the module name or <code>null</code>. |
| * @since 1.9.7 |
| */ |
| private static String parseModuleFromModuleClassPair(final String moduleClassPair) { |
| if (moduleClassPair == null) { |
| return null; |
| } |
| final String[] moduleAndClass = moduleClassPair.split("/"); //NOI18N |
| return moduleAndClass[0]; |
| } |
| |
| /** |
| * Parses a classname from JDK 9 main module command line argument. |
| * @param moduleClassPair a module with optional classname or <code>null</code>. |
| * @return the classname or <code>null</code>. |
| * @since 1.9.7 |
| */ |
| private static String parseClassFromModuleClassPair(final String moduleClassPair) { |
| if (moduleClassPair == null) { |
| return null; |
| } |
| final String[] moduleAndClass = moduleClassPair.split("/"); //NOI18N |
| return moduleAndClass.length == 2 ? moduleAndClass[1] : null; |
| } |
| |
| /** |
| * Type of execution. |
| * @since 1.9.7 |
| */ |
| private enum ExecutableType { |
| /** |
| * Main class execution. |
| */ |
| CLASS, |
| /** |
| * Jar file execution. |
| */ |
| JAR, |
| /** |
| * Module execution. |
| */ |
| MODULE, |
| |
| /** |
| * Source file (introduced in Java 11) |
| */ |
| SOURCE_FILE, |
| } |
| } |