Browse Source

Added module, modulepath attributes and modulepath, moduleupgradepath elements into Java task.

master
Tomas Zezula 9 years ago
parent
commit
dd8b5f45dd
4 changed files with 381 additions and 15 deletions
  1. +23
    -0
      src/etc/testcases/taskdefs/java.xml
  2. +54
    -3
      src/main/org/apache/tools/ant/taskdefs/Java.java
  3. +217
    -11
      src/main/org/apache/tools/ant/types/CommandlineJava.java
  4. +87
    -1
      src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java

+ 23
- 0
src/etc/testcases/taskdefs/java.xml View File

@@ -44,6 +44,9 @@
<property name="pipeapp"
value="org.apache.tools.ant.taskdefs.JavaTest$$PipeEntryPoint" />

<property name="module"
value="TestModule" />

<target name="testNoJarNoClassname">
<java/>
</target>
@@ -61,6 +64,26 @@
<java classname="${app}" jar="test.jar" />
</target>

<target name="testModuleAndJar">
<java module="${module}" jar="test.jar" />
</target>

<target name="testJarAndModule">
<java jar="test.jar" module="${module}" />
</target>

<target name="testClassnameAndModule">
<java classname="${app}" module="${module}" fork="true"/>
</target>

<target name="testModuleAndClassname">
<java module="${module}" classname="${app}" fork="true"/>
</target>

<target name="testModule">
<java module="${module}" fork="true"/>
</target>

<target name="testRun">
<fail unless="tests-classpath.value" />
<java classname="${app}"


+ 54
- 3
src/main/org/apache/tools/ant/taskdefs/Java.java View File

@@ -142,13 +142,18 @@ public class Java extends Task {
*/
protected void checkConfiguration() throws BuildException {
String classname = getCommandLine().getClassname();
if (classname == null && getCommandLine().getJar() == null) {
String module = getCommandLine().getModule();
if (classname == null && getCommandLine().getJar() == null && module == null) {
throw new BuildException("Classname must not be null.");
}
if (!fork && getCommandLine().getJar() != null) {
throw new BuildException("Cannot execute a jar in non-forked mode."
+ " Please set fork='true'. ");
}
if (!fork && getCommandLine().getModule() != null) {
throw new BuildException("Cannot execute a module in non-forked mode."
+ " Please set fork='true'. ");
}
if (spawn && !fork) {
throw new BuildException("Cannot spawn a java process in non-forked mode."
+ " Please set fork='true'. ");
@@ -289,6 +294,36 @@ public class Java extends Task {
return getCommandLine().createBootclasspath(getProject()).createPath();
}

/**
* Set the modulepath to be used when running the Java class.
*
* @param mp an Ant Path object containing the modulepath.
* @since ???
*/
public void setModulepath(Path mp) {
createModulepath().append(mp);
}

/**
* Add a path to the modulepath.
*
* @return created modulepath.
* @since ???
*/
public Path createModulepath() {
return getCommandLine().createModulepath(getProject()).createPath();
}

/**
* Add a path to the upgrademodulepath.
*
* @return created upgrademodulepath.
* @since ???
*/
public Path createUpgrademodulepath() {
return getCommandLine().createUpgrademodulepath(getProject()).createPath();
}

/**
* Set the permissions for the application run inside the same JVM.
* @since Ant 1.6
@@ -316,8 +351,8 @@ public class Java extends Task {
* @throws BuildException if there is also a main class specified.
*/
public void setJar(File jarfile) throws BuildException {
if (getCommandLine().getClassname() != null) {
throw new BuildException("Cannot use 'jar' and 'classname' "
if (getCommandLine().getClassname() != null || getCommandLine().getModule() != null) {
throw new BuildException("Cannot use 'jar' with 'classname' or 'module' "
+ "attributes in same command.");
}
getCommandLine().setJar(jarfile.getAbsolutePath());
@@ -338,6 +373,22 @@ public class Java extends Task {
getCommandLine().setClassname(s);
}

/**
* Set the Java module to execute.
*
* @param module the name of the module.
*
* @throws BuildException if the jar attribute has been set.
* @since ???
*/
public void setModule(String module) throws BuildException {
if (getCommandLine().getJar() != null) {
throw new BuildException("Cannot use 'jar' and 'module' "
+ "attributes in same command");
}
getCommandLine().setModule(module);
}

/**
* Deprecated: use nested arg instead.
* Set the command line arguments for the class.


+ 217
- 11
src/main/org/apache/tools/ant/types/CommandlineJava.java View File

@@ -52,6 +52,8 @@ public class CommandlineJava implements Cloneable {
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;
/**
@@ -60,10 +62,11 @@ public class CommandlineJava implements Cloneable {
private Assertions assertions = null;

/**
* Indicate whether it will execute a jar file or not, in this case
* the first vm option must be a -jar and the 'executable' is a jar file.
* 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 boolean executeJar = false;
private ExecutableType executableType;

/**
* Whether system properties and bootclasspath shall be cloned.
@@ -320,7 +323,7 @@ public class CommandlineJava implements Cloneable {
*/
public void setJar(String jarpathname) {
javaCommand.setExecutable(jarpathname);
executeJar = true;
executableType = ExecutableType.JAR;
}

/**
@@ -330,7 +333,7 @@ public class CommandlineJava implements Cloneable {
* @see #getClassname()
*/
public String getJar() {
if (executeJar) {
if (executableType == ExecutableType.JAR) {
return javaCommand.getExecutable();
}
return null;
@@ -341,8 +344,14 @@ public class CommandlineJava implements Cloneable {
* @param classname the fully qualified classname.
*/
public void setClassname(String classname) {
javaCommand.setExecutable(classname);
executeJar = false;
if (executableType == ExecutableType.MODULE) {
javaCommand.setExecutable(createModuleClassPair(
parseModuleFromModuleClassPair(javaCommand.getExecutable()),
classname));
} else {
javaCommand.setExecutable(classname);
executableType = ExecutableType.CLASS;
}
}

/**
@@ -351,8 +360,55 @@ public class CommandlineJava implements Cloneable {
* @see #getJar()
*/
public String getClassname() {
if (!executeJar) {
return javaCommand.getExecutable();
if (executableType != null) {
switch (executableType) {
case CLASS:
return javaCommand.getExecutable();
case MODULE:
return parseClassFromModuleClassPair(javaCommand.getExecutable());
}
}
return null;
}

/**
* Set the module to execute.
* @param module the module name.
* @since ???
*/
public void setModule(final String module) {
if (executableType == null) {
javaCommand.setExecutable(module);
} else {
switch (executableType) {
case JAR:
javaCommand.setExecutable(module);
break;
case CLASS:
javaCommand.setExecutable(createModuleClassPair(
module,
javaCommand.getExecutable()));
break;
case MODULE:
javaCommand.setExecutable(createModuleClassPair(
module,
parseClassFromModuleClassPair(javaCommand.getExecutable())));
break;
}
}
executableType = ExecutableType.MODULE;
}

/**
* Get the name of the module to be run.
* @return the name of the module to run or <tt>null</tt> if there is no module.
* @see #getJar()
* @see #getClassname()
* @since ???
*/
public String getModule() {
if(executableType == ExecutableType.MODULE) {
return parseModuleFromModuleClassPair(javaCommand.getExecutable());
}
return null;
}
@@ -382,6 +438,32 @@ public class CommandlineJava implements Cloneable {
return bootclasspath;
}

/**
* Create a modulepath.
* @param p the project to use to create the path.
* @return a path to be configured.
* @since ???
*/
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 ???
*/
public Path createUpgrademodulepath(Project p) {
if (upgrademodulepath == null) {
upgrademodulepath = new Path(p);
}
return upgrademodulepath;
}

/**
* Get the vm version.
* @return the vm version.
@@ -435,6 +517,18 @@ public class CommandlineJava implements Cloneable {
listIterator.add(
classpath.concatSystemClasspath("ignore").toString());
}
//module path
if (haveModulepath()) {
listIterator.add("-modulepath");
listIterator.add(
modulepath.concatSystemClasspath("ignore").toString());
}
//upgrade module path
if (haveUpgrademodulepath()) {
listIterator.add("-upgrademodulepath");
listIterator.add(
upgrademodulepath.concatSystemClasspath("ignore").toString());
}
//now any assertions are added
if (getAssertions() != null) {
getAssertions().applyAssertions(listIterator);
@@ -443,8 +537,10 @@ public class CommandlineJava implements Cloneable {
// 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 (executeJar) {
if (executableType == ExecutableType.JAR) {
listIterator.add("-jar");
} else if (executableType == ExecutableType.MODULE) {
listIterator.add("-m");
}
// this is the classname to run as well as its arguments.
// in case of 'executeJar', the executable is a jar file.
@@ -531,7 +627,7 @@ public class CommandlineJava implements Cloneable {
size++;
}
// jar execution requires an additional -jar option
if (executeJar) {
if (executableType == ExecutableType.JAR || executableType == ExecutableType.MODULE) {
size++;
}
//assertions take up space too
@@ -573,6 +669,24 @@ public class CommandlineJava implements Cloneable {
return bootclasspath;
}

/**
* Get the modulepath.
* @return modulepath or null.
* @since ???
*/
public Path getModulepath() {
return modulepath;
}

/**
* Get the upgrademodulepath.
* @return upgrademodulepath or null.
* @since ???
*/
public Path getUpgrademodulepath() {
return upgrademodulepath;
}

/**
* Cache current system properties and set them to those in this
* Java command.
@@ -617,6 +731,12 @@ public class CommandlineJava implements Cloneable {
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();
}
@@ -660,6 +780,30 @@ public class CommandlineJava implements Cloneable {
return calculateBootclasspath(log).size() > 0;
}

/**
* Determine whether the modulepath has been specified.
* @return true if the modulepath is to be used.
* @since ???
*/
public boolean haveModulepath() {
Path fullClasspath = modulepath != null
? modulepath.concatSystemClasspath("ignore") : null;
return fullClasspath != null
&& fullClasspath.toString().trim().length() > 0;
}

/**
* Determine whether the upgrademodulepath has been specified.
* @return true if the upgrademodulepath is to be used.
* @since ???
*/
public boolean haveUpgrademodulepath() {
Path fullClasspath = upgrademodulepath != null
? upgrademodulepath.concatSystemClasspath("ignore") : null;
return fullClasspath != null
&& fullClasspath.toString().trim().length() > 0;
}

/**
* Calculate the bootclasspath based on the bootclasspath
* specified, the build.sysclasspath and ant.build.clonevm magic
@@ -696,4 +840,66 @@ public class CommandlineJava implements Cloneable {
return cloneVm
|| "true".equals(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 ???
*/
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 ???
*/
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 ???
*/
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 ???
*/
private enum ExecutableType {
/**
* Main class execution.
*/
CLASS,
/**
* Jar file execution.
*/
JAR,
/**
* Module execution.
*/
MODULE
}
}

+ 87
- 1
src/tests/junit/org/apache/tools/ant/taskdefs/JavaTest.java View File

@@ -41,6 +41,8 @@ import org.junit.Test;
import org.junit.internal.AssumptionViolatedException;

import static org.apache.tools.ant.AntAssert.assertContains;
import org.apache.tools.ant.types.Path;
import org.junit.Assert;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -118,10 +120,94 @@ public class JavaTest {
buildRule.executeTarget("testClassnameAndJar");
fail("Build exception should have been thrown - both classname and JAR are not allowed");
} catch (BuildException ex) {
assertEquals("Cannot use 'jar' and 'classname' attributes in same command.", ex.getMessage());
assertEquals("Cannot use 'jar' with 'classname' or 'module' attributes in same command.", ex.getMessage());
}
}

@Test
public void testJarAndModule() {
try {
buildRule.executeTarget("testJarAndModule");
fail("Build exception should have been thrown - both module and JAR are not allowed");
} catch (BuildException ex) {
assertEquals("Cannot use 'jar' and 'module' attributes in same command", ex.getMessage());
}
}

@Test
public void testModuleAndJar() {
try {
buildRule.executeTarget("testModuleAndJar");
fail("Build exception should have been thrown - both module and JAR are not allowed");
} catch (BuildException ex) {
assertEquals("Cannot use 'jar' with 'classname' or 'module' attributes in same command.", ex.getMessage());
}
}

@Test
public void testClassnameAndModule() {
buildRule.executeTarget("testClassnameAndModule");
}

@Test
public void testModuleAndClassname() {
buildRule.executeTarget("testModuleAndClassname");
}

@Test
public void testModule() {
buildRule.executeTarget("testModule");
}

@Test
public void testModuleCommandLine() {
final String moduleName = "TestModule"; //NOI18N
final String arg = "appArg"; //NOI18N
final Java java = new Java();
java.setFork(true);
java.setModule(moduleName);
java.setJvmargs("-Xmx128M");
java.setArgs(arg);
final String[] cmdLine = java.getCommandLine().getCommandline();
Assert.assertNotNull("Has command line.", cmdLine);
assertEquals("Command line should have 5 elements", 5, cmdLine.length);
assertEquals("Last command line element should be java argument: " + arg,
arg,
cmdLine[cmdLine.length-1]);
assertEquals("The command line element at index 3 should be module name: " + moduleName,
moduleName,
cmdLine[cmdLine.length-2]);
assertEquals("The command line element at index 2 should be -m",
"-m",
cmdLine[cmdLine.length-3]);
}

@Test
public void testModuleAndClassnameCommandLine() {
final String moduleName = "TestModule"; //NOI18N
final String className = "org.apache.Test"; //NOI18N
final String moduleClassPair= String.format("%s/%s", moduleName, className);
final String arg = "appArg"; //NOI18N
final Java java = new Java();
java.setFork(true);
java.setModule(moduleName);
java.setClassname(className);
java.setJvmargs("-Xmx128M"); //NOI18N
java.setArgs(arg);
final String[] cmdLine = java.getCommandLine().getCommandline();
Assert.assertNotNull("Has command line.", cmdLine);
assertEquals("Command line should have 5 elements", 5, cmdLine.length);
assertEquals("Last command line element should be java argument: " + arg,
arg,
cmdLine[cmdLine.length-1]);
assertEquals("The command line element at index 3 should be module class pair: " + moduleClassPair,
moduleClassPair,
cmdLine[cmdLine.length-2]);
assertEquals("The command line element at index 2 should be -m",
"-m",
cmdLine[cmdLine.length-3]);
}

@Test
public void testRun() {
buildRule.executeTarget("testRun");


Loading…
Cancel
Save