diff --git a/docs/manual/CoreTasks/exec.html b/docs/manual/CoreTasks/exec.html index 385b5aec5..50f97f8eb 100644 --- a/docs/manual/CoreTasks/exec.html +++ b/docs/manual/CoreTasks/exec.html @@ -20,20 +20,27 @@ Windows executable and is not aware of Cygwin conventions.

OpenVMS Users

-

The command specified using executable and <arg> 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 -JAVA$FORK_SUPPORT_CHDIR is set to TRUE (see -the JDK Release Notes).

- +inside a temporary DCL script. This has some implications: + +For <exec> to work in an environment with a Java VM +older than version 1.4.1-2 it is also required that the logical +JAVA$FORK_SUPPORT_CHDIR is set to TRUE in +the job table (see the JDK Release Notes).

+

Please note that the Java VM provided by HP doesn't follow OpenVMS' conventions of exit codes. If you run a Java VM with this task, the task may falsely claim that an error occured (or silently ignore an error). Don't use this task to run JAVA.EXE, use a <java> task with the fork attribute -set ti true instead as this task will follow the VM's +set to true instead as this task will follow the VM's interpretation of exit codes.

Parameters

diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 9b7b1b6e1..d26ffe1f6 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -65,6 +65,7 @@ import java.util.Map; import java.util.Set; import java.util.Vector; +import org.apache.tools.ant.taskdefs.condition.Os; import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.selectors.FileSelector; @@ -163,6 +164,8 @@ import org.apache.tools.ant.util.FileUtils; public class DirectoryScanner implements FileScanner, SelectorScanner, ResourceFactory { + /** Is OpenVMS the operating system we're running on? */ + private static final boolean ON_VMS = Os.isFamily("openvms"); /** * Patterns which should be excluded by default. @@ -725,7 +728,7 @@ public class DirectoryScanner File canonFile = myfile.getCanonicalFile(); String path = fileUtils.removeLeadingPath(canonBase, canonFile); - if (!path.equals(currentelement)) { + if (!path.equals(currentelement) || ON_VMS) { myfile = findFile(basedir, currentelement); if (myfile != null) { currentelement = diff --git a/src/main/org/apache/tools/ant/taskdefs/Execute.java b/src/main/org/apache/tools/ant/taskdefs/Execute.java index 44f6e4012..55f7d6a37 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Execute.java +++ b/src/main/org/apache/tools/ant/taskdefs/Execute.java @@ -621,6 +621,13 @@ public class Execute { * @return the patched environment */ private String[] patchEnvironment() { + // On OpenVMS Runtime#exec() doesn't support the environment array, + // so we only return the new values which then will be set in + // the generated DCL script, inheriting the parent process environment + if (Os.isFamily("openvms")) { + return env; + } + Vector osEnv = (Vector) getProcEnvironment().clone(); for (int i = 0; i < env.length; i++) { int pos = env[i].indexOf('='); @@ -1119,7 +1126,7 @@ public class Execute { */ public Process exec(Project project, String[] cmd, String[] env) throws IOException { - String[] vmsCmd = {createCommandFile(cmd).getPath()}; + String[] vmsCmd = {createCommandFile(cmd, env).getPath()}; return super.exec(project, vmsCmd, env); } @@ -1131,7 +1138,7 @@ public class Execute { */ public Process exec(Project project, String[] cmd, String[] env, File workingDir) throws IOException { - String[] vmsCmd = {createCommandFile(cmd).getPath()}; + String[] vmsCmd = {createCommandFile(cmd, env).getPath()}; return super.exec(project, vmsCmd, env, workingDir); } @@ -1139,17 +1146,34 @@ public class Execute { * 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 { + private File createCommandFile(String[] cmd, String[] env) + 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]); + + // add the environment as logicals to the DCL script + if (env != null) { + int eqIndex; + for (int i = 1; i < env.length ; i++) { + eqIndex = env[i].indexOf('='); + if (eqIndex != -1) { + out.print("$ DEFINE/NOLOG "); + out.print(env[i].substring(0, eqIndex)); + out.print(" \""); + out.print(env[i].substring(eqIndex + 1)); + out.println('\"'); + } + } + } + + out.print("$ " + cmd[0]); + for (int i = 1; i < cmd.length ; i++) { + out.println(" -"); + out.print(cmd[i]); } - out.println(dclCmd.toString()); } finally { if (out != null) { out.close(); diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index eada52f11..cc6ae3a06 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -824,6 +824,8 @@ public class FileUtils { *
  • DOS style paths that start with a drive letter will have * \ as the separator.
  • * + * Unlike File#getCanonicalPath() it specifically doesn't + * resolve symbolic links. * * @param path the path to be normalized * @return the normalized version of the path. @@ -937,6 +939,65 @@ public class FileUtils { return new File(path); } + /** + * Returns a VMS String representation of a File object. + * This is useful since the JVM by default internally converts VMS paths + * to Unix style. + * The returned String is always an absolute path. + * + * @param f The File to get the VMS path for. + * @return The absolute VMS path to f. + */ + public String toVMSPath(File f) { + // format: "DEVICE:[DIR.SUBDIR]FILE" + String osPath; + String path = normalize(f.getAbsolutePath()).getPath(); + String name = f.getName(); + boolean isAbsolute = path.charAt(0) == File.separatorChar; + // treat directories specified using .DIR syntax as files + boolean isDirectory = f.isDirectory() && + !name.regionMatches(true, name.length() - 4, ".DIR", 0, 4); + + String device = null; + StringBuffer directory = null; + String file = null; + + int index = 0; + + if (isAbsolute) { + index = path.indexOf(File.separatorChar, 1); + if (index == -1) { + return path.substring(1) + ":[000000]"; + } else { + device = path.substring(1, index++); + } + } + if (isDirectory) { + directory = new StringBuffer(path.substring(index). + replace(File.separatorChar, '.')); + } else { + int dirEnd = + path.lastIndexOf(File.separatorChar, path.length()); + if (dirEnd == -1 || dirEnd < index) { + file = path.substring(index); + } else { + directory = new StringBuffer(path.substring(index, dirEnd). + replace(File.separatorChar, '.')); + index = dirEnd + 1; + if (path.length() > index) { + file = path.substring(index); + } + } + } + if (!isAbsolute && directory != null) { + directory.insert(0, '.'); + } + osPath = ((device != null) ? device + ":" : "") + + ((directory != null) ? "[" + directory + "]" : "") + + ((file != null) ? file : ""); + return osPath; + } + /** * Create a temporary file in a given directory. *