Browse Source

Add OpenVMS support to <exec>.

PR: 21877
Submitted by:	Knut Wannheden <knut at paranor dot ch>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274949 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 22 years ago
parent
commit
f30f3d21cb
4 changed files with 106 additions and 12 deletions
  1. +3
    -0
      WHATSNEW
  2. +16
    -8
      docs/manual/CoreTasks/exec.html
  3. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/ExecTask.java
  4. +86
    -3
      src/main/org/apache/tools/ant/taskdefs/Execute.java

+ 3
- 0
WHATSNEW View File

@@ -513,6 +513,9 @@ Other changes:
mappings per source path. This behaviour is enabled by using
an enablemultiplemapping attribute. Bugzilla Report 21320.

* <exec> will now work on OpenVMS (please read the notes in
<exec>'s manual page). Bugzilla Report 21877.

Changes from Ant 1.5.2 to Ant 1.5.3
===================================



+ 16
- 8
docs/manual/CoreTasks/exec.html View File

@@ -19,6 +19,14 @@ the executable parameter. This is because the Java VM in which Ant is running is
Windows executable and is not aware of Cygwin conventions.
</p>
<h4>OpenVMS Users</h4>
<p>The command specified using <code>executable</code> and <code>&lt;arg&gt;</code>
elements is executed exactly as specified inside a temporary DCL script. This means
that paths have to be written in VMS style. It is also required that the logical
<code>JAVA$FORK_SUPPORT_CHDIR</code> is set to <code>TRUE</code> (see the <i>JDK Release
Notes</i>).
</p>
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -108,7 +116,7 @@ Windows executable and is not aware of Cygwin conventions.
<tr>
<td valign="top">resultproperty</td>
<td valign="top">the name of a property in which the return code of the
command should be stored. Only of interest if failonerror=false</td>
command should be stored. Only of interest if failonerror=false.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
@@ -120,7 +128,7 @@ Windows executable and is not aware of Cygwin conventions.
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the buildprocess if the command exits with a
returncode other than 0. Defaults to false</td>
return code signaling failure. Defaults to false.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
@@ -204,15 +212,15 @@ system command via nested <code>&lt;env&gt;</code> elements.</p>

<h3>Errors and return codes</h3>
By default the return code of a &lt;exec&gt; is ignored; when you set
<code>failonerror="true"</code> then any non zero response is treated as an
error. Alternatively, you can set <code>resultproperty</code> to the name
of a property and have it assigned to the result code (barring immutability,
of course).
<code>failonerror="true"</code> then any return code signaling failure
(OS specific) causes the build to fail. Alternatively, you can set
<code>resultproperty</code> to the name of a property and have it assigned to
the result code (barring immutability, of course).
<p>
If the attempt to start the program fails with an OS dependent error code,
then &lt;exec&gt; halts the build unless <code>failifexecutionfails</code>
is set. You can use that to run a program if it exists, but otherwise
do nothing.
is set to <code>false</code>. You can use that to run a program if it exists, but
otherwise do nothing.
<p>
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;


+ 1
- 1
src/main/org/apache/tools/ant/taskdefs/ExecTask.java View File

@@ -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());


+ 86
- 3
src/main/org/apache/tools/ant/taskdefs/Execute.java View File

@@ -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 <code>exitValue</code> signals a failure on the current
* system (OS specific).
* @param exitValue the exit value (return code) to be checked
* @return <code>true</code> if <code>exitValue</code> 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 <code>workingDir</code> 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;
}

}
}

Loading…
Cancel
Save