@@ -204,15 +212,15 @@ system command via nested <env>
elements.
Errors and return codes
By default the return code of a <exec> is ignored; when you set
-failonerror="true"
then any non zero response is treated as an
-error. Alternatively, you can set resultproperty
to the name
-of a property and have it assigned to the result code (barring immutability,
-of course).
+failonerror="true"
then any return code signaling failure
+(OS specific) causes the build to fail. Alternatively, you can set
+resultproperty
to the name of a property and have it assigned to
+the result code (barring immutability, of course).
If the attempt to start the program fails with an OS dependent error code,
then <exec> halts the build unless failifexecutionfails
-is set. You can use that to run a program if it exists, but otherwise
-do nothing.
+is set to false
. You can use that to run a program if it exists, but
+otherwise do nothing.
What do those error codes mean? Well, they are OS dependent. On Windows
boxes you have to look in include\error.h in your windows compiler or wine files;
diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecTask.java b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
index 9e4bcabf7..dbd95f357 100644
--- a/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java
@@ -413,7 +413,7 @@ public class ExecTask extends Task {
log("Timeout: killed the sub-process", Project.MSG_WARN);
}
maybeSetResultPropertyValue(returnCode);
- if (returnCode != 0) {
+ if (Execute.isFailure(returnCode)) {
if (failOnError) {
throw new BuildException(getTaskType() + " returned: "
+ returnCode, getLocation());
diff --git a/src/main/org/apache/tools/ant/taskdefs/Execute.java b/src/main/org/apache/tools/ant/taskdefs/Execute.java
index 8fba313d2..88e4eee00 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Execute.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Execute.java
@@ -57,7 +57,9 @@ package org.apache.tools.ant.taskdefs;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
+import java.io.PrintWriter;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -109,7 +111,9 @@ public class Execute {
static {
// Try using a JDK 1.3 launcher
try {
- if (!Os.isFamily("os/2")) {
+ if (Os.isFamily("openvms")) {
+ vmLauncher = new VmsCommandLauncher();
+ } else if (!Os.isFamily("os/2")) {
vmLauncher = new Java13CommandLauncher();
}
} catch (NoSuchMethodException exc) {
@@ -155,6 +159,9 @@ public class Execute {
shellLauncher
= new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher);
+ } else if (Os.isFamily("openvms")) {
+ // the vmLauncher already uses the shell
+ shellLauncher = vmLauncher;
} else {
// Generic
shellLauncher = new ScriptCommandLauncher("bin/antRun",
@@ -249,6 +256,9 @@ public class Execute {
// rely on PATH
String[] cmd = {"env"};
return cmd;
+ } else if (Os.isFamily("openvms")) {
+ String[] cmd = {"show", "logical"};
+ return cmd;
} else {
// MAC OS 9 and previous
// TODO: I have no idea how to get it, someone must fix it
@@ -490,14 +500,30 @@ public class Execute {
}
/**
- * query the exit value of the process.
+ * Query the exit value of the process.
* @return the exit value, 1 if the process was killed,
- * or Project.INVALID if no exit value has been received
+ * or Execute.INVALID if no exit value has been received
*/
public int getExitValue() {
return exitValue;
}
+ /**
+ * Checks whether exitValue
signals a failure on the current
+ * system (OS specific).
+ * @param exitValue the exit value (return code) to be checked
+ * @return true
if exitValue
signals a failure
+ */
+ public static boolean isFailure(int exitValue) {
+ if (Os.isFamily("openvms")) {
+ // odd exit value signals failure
+ return (exitValue % 2) == 0;
+ } else {
+ // non zero exit value signals failure
+ return exitValue != 0;
+ }
+ }
+
/**
* test for an untimely death of the process
* @return true iff a watchdog had to kill the process
@@ -912,4 +938,61 @@ public class Execute {
private String _script;
}
+
+ /**
+ * A command launcher for VMS that writes the command to a temporary DCL
+ * script before launching commands. This is due to limitations of both
+ * the DCL interpreter and the Java VM implementation.
+ */
+ private static class VmsCommandLauncher extends Java13CommandLauncher {
+
+ public VmsCommandLauncher() throws NoSuchMethodException {
+ super();
+ }
+
+ /**
+ * Launches the given command in a new process.
+ */
+ public Process exec(Project project, String[] cmd, String[] env)
+ throws IOException {
+ String[] vmsCmd = { createCommandFile(cmd).getPath() };
+ return super.exec(project, vmsCmd, env);
+ }
+
+ /**
+ * Launches the given command in a new process, in the given working
+ * directory. Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this
+ * method only works if workingDir
is null or the logical
+ * JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
+ */
+ public Process exec(Project project, String[] cmd, String[] env,
+ File workingDir) throws IOException {
+ String[] vmsCmd = { createCommandFile(cmd).getPath() };
+ return super.exec(project, vmsCmd, env, workingDir);
+ }
+
+ /*
+ * Writes the command into a temporary DCL script and returns the
+ * corresponding File object. The script will be deleted on exit.
+ */
+ private File createCommandFile(String[] cmd) throws IOException {
+ File script = File.createTempFile("ANT", ".COM");
+ script.deleteOnExit();
+ PrintWriter out = null;
+ try {
+ out = new PrintWriter(new FileWriter(script));
+ StringBuffer dclCmd = new StringBuffer("$");
+ for (int i = 0; i < cmd.length; i++) {
+ dclCmd.append(' ').append(cmd[i]);
+ }
+ out.println(dclCmd.toString());
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ return script;
+ }
+
+ }
}