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. | |||
* | |||