git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275346 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -20,20 +20,27 @@ Windows executable and is not aware of Cygwin conventions. | |||
| </p> | |||
| <h4>OpenVMS Users</h4> | |||
| <p>The command specified using <code>executable</code> and | |||
| <code><arg></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> | |||
| inside a temporary DCL script. This has some implications: | |||
| <ul> | |||
| <li>paths have to be written in VMS style</li> | |||
| <li>if your <code>executable</code> points to a DCL script remember to | |||
| prefix it with an <code>@</code>-sign | |||
| (e.g. <code>executable="@[FOO]BAR.COM"</code>), just as you would in a | |||
| DCL script</li> | |||
| </ul> | |||
| For <code><exec></code> to work in an environment with a Java VM | |||
| older than version 1.4.1-2 it is also <i>required</i> that the logical | |||
| <code>JAVA$FORK_SUPPORT_CHDIR</code> is set to <code>TRUE</code> in | |||
| the job table (see the <i>JDK Release Notes</i>).</p> | |||
| <p>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 <code>JAVA.EXE</code>, use a | |||
| <code><java></code> task with the <code>fork</code> attribute | |||
| set ti <code>true</code> instead as this task will follow the VM's | |||
| set to <code>true</code> instead as this task will follow the VM's | |||
| interpretation of exit codes.</p> | |||
| <h3>Parameters</h3> | |||
| @@ -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 = | |||
| @@ -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(); | |||
| @@ -824,6 +824,8 @@ public class FileUtils { | |||
| * <li>DOS style paths that start with a drive letter will have | |||
| * \ as the separator.</li> | |||
| * </ul> | |||
| * Unlike <code>File#getCanonicalPath()</code> 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 <code>File</code> 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 <code>File</code> to get the VMS path for. | |||
| * @return The absolute VMS path to <code>f</code>. | |||
| */ | |||
| 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. | |||
| * | |||