The attached patch (only lightly tested and only on Linux, please note)
should make ExecTask/Execute (<exec>) take advantage of JDK 1.3's new
Runtime.exec accepting a working directory, thus avoiding the need to
use antRun. It should also correct a bug in ExecTask that antRun was
used even when no 'dir' attribute was given (the working directory did
not need to be set at all). And hopefully the code should be a little
clearer (all the alternative strategies are listed in order in one
method).
Previous code had this:
private static String antWorkingDirectory =
(new File((new File(".")).getAbsolutePath())).getParent();
(Written by Mariusz.) I've replaced that with
System.getProperty("user.dir") which is defined from JDK 1.1 to give the
intended result, so hopefully the older code was not a workaround for an
obscure broken JDK.
Two other thoughts about using antRun (not antRun.bat, only the POSIX
version):
1. At least on Bash and I thought other Bourne shells, $@ should be "$@"
to preserve spaces correctly, I think. (But why <<echo $CMD $@ | sh>>
instead of simply <<exec $CMD $@>> or better <<exec "$CMD" "$@">>?)
2. If /bin/sh is found to exist at runtime, why not use it rather than
rely on some shell script? Take the command array cmdl, then construct a
new one of three strings: "/bin/sh", "-c", and then: "cd
${workingDirectory}; " plus each element of cmdl, separated by spaces,
surrounded by ticks ('), and properly escaped (' -> '"'"'). Is there
something special antRun does beyond this?
-Jesse
--
Jesse Glick <mailto:[EMAIL PROTECTED]>
NetBeans, Open APIs <http://www.netbeans.org/>
tel (+4202) 3300-9161 Sun Micro x49161 Praha CRIndex: docs/index.html
===================================================================
RCS file: /home/cvspublic/jakarta-ant/docs/index.html,v
retrieving revision 1.67
diff -c -r1.67 index.html
*** docs/index.html 2000/08/07 11:47:11 1.67
--- docs/index.html 2000/08/08 19:54:17
***************
*** 1134,1140 ****
<tr>
<td valign="top">dir</td>
<td valign="top">the directory in which the command should be
executed.</td>
! <td align="center" valign="top">Yes</td>
</tr>
<tr>
<td valign="top">os</td>
--- 1134,1140 ----
<tr>
<td valign="top">dir</td>
<td valign="top">the directory in which the command should be
executed.</td>
! <td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">os</td>
***************
*** 1146,1152 ****
<td valign="top">output</td>
<td valign="top">the file to which the output of the command should be
redirected.</td>
! <td align="center" valign="top">Yes</td>
</tr>
<tr>
<td valign="top">failonerror</td>
--- 1146,1152 ----
<td valign="top">output</td>
<td valign="top">the file to which the output of the command should be
redirected.</td>
! <td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">failonerror</td>
Index: src/main/org/apache/tools/ant/taskdefs/ExecTask.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java,v
retrieving revision 1.5
diff -c -r1.5 ExecTask.java
*** src/main/org/apache/tools/ant/taskdefs/ExecTask.java 2000/08/01
09:18:39 1.5
--- src/main/org/apache/tools/ant/taskdefs/ExecTask.java 2000/08/08
19:54:18
***************
*** 180,187 ****
* Create an Execute instance with the correct working directory set.
*/
protected Execute prepareExec() throws BuildException {
- // default directory to the project's base directory
- if (dir == null) dir = project.getBaseDir();
// show the command
log(cmdl.toString(), Project.MSG_VERBOSE);
--- 180,185 ----
Index: src/main/org/apache/tools/ant/taskdefs/Execute.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Execute.java,v
retrieving revision 1.5
diff -c -r1.5 Execute.java
*** src/main/org/apache/tools/ant/taskdefs/Execute.java 2000/08/03 10:29:20
1.5
--- src/main/org/apache/tools/ant/taskdefs/Execute.java 2000/08/08 19:54:18
***************
*** 61,66 ****
--- 61,68 ----
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+ import java.lang.reflect.InvocationTargetException;
+ import java.lang.reflect.Method;
/**
***************
*** 78,90 ****
private int exitValue = INVALID;
private ExecuteStreamHandler streamHandler;
private ExecuteWatchdog watchdog;
! private File workingDirectory;
private String antRun;
! private static String antWorkingDirectory =
! (new File((new File(".")).getAbsolutePath())).getParent();
private static String myos = System.getProperty("os.name");
/**
* Creates a new execute object using <code>PumpStreamHandler</code> for
* stream handling.
--- 80,102 ----
private int exitValue = INVALID;
private ExecuteStreamHandler streamHandler;
private ExecuteWatchdog watchdog;
! private File workingDirectory = null;
private String antRun;
! private static String antWorkingDirectory =
System.getProperty("user.dir");
private static String myos = System.getProperty("os.name");
+ private static Method execWithCWD = null;
+ static {
+ try {
+ // JDK 1.3 API extension:
+ // Runtime.exec(String[] cmdarray, String[] envp, File dir)
+ execWithCWD = Runtime.class.getMethod("exec", new Class[]
{String[].class, String[].class, File.class});
+ } catch (NoSuchMethodException nsme) {
+ // OK.
+ }
+ }
+
/**
* Creates a new execute object using <code>PumpStreamHandler</code> for
* stream handling.
***************
*** 124,156 ****
* @return the commandline used to create a subprocess
*/
public String[] getCommandline() {
! String[] commandLine = cmdl;
!
! if (workingDirectory != null &&
! !antWorkingDirectory.equals(workingDirectory.getAbsolutePath()) &&
! !myos.equals("Mac OS")) {
!
! if (myos.toLowerCase().indexOf("windows") >= 0 &&
! (myos.toLowerCase().indexOf("nt") >= 0 ||
! myos.indexOf("2000") >= 0)) {
!
! commandLine = new String[cmdl.length+5];
! commandLine[0] = "cmd";
! commandLine[1] = "/c";
! commandLine[2] = "cd";
! commandLine[3] = workingDirectory.getAbsolutePath();
! commandLine[4] = "&&";
! System.arraycopy(cmdl, 0, commandLine, 5, cmdl.length);
!
! } else {
! commandLine = new String[cmdl.length+2];
! commandLine[0] = antRun;
! commandLine[1] = workingDirectory.getAbsolutePath();
! System.arraycopy(cmdl, 0, commandLine, 2, cmdl.length);
! }
! }
!
! return commandLine;
}
--- 136,142 ----
* @return the commandline used to create a subprocess
*/
public String[] getCommandline() {
! return cmdl;
}
***************
*** 187,198 ****
* Sets the working directory of the process to execute.
*
* <p>This is emulated using the antRun scripts unless the OS is
! * Windows NT in which case a cmd.exe is spawned.
*
* @param wd the working directory of the process.
*/
public void setWorkingDirectory(File wd) {
! workingDirectory = wd;
}
/**
--- 173,189 ----
* Sets the working directory of the process to execute.
*
* <p>This is emulated using the antRun scripts unless the OS is
! * Windows NT in which case a cmd.exe is spawned,
! * or MRJ and setting user.dir works, or JDK 1.3 and there is
! * official support in java.lang.Runtime.
*
* @param wd the working directory of the process.
*/
public void setWorkingDirectory(File wd) {
! if (wd == null || wd.getAbsolutePath().equals(antWorkingDirectory))
! workingDirectory = null;
! else
! workingDirectory = wd;
}
/**
***************
*** 201,207 ****
* @param project the current project.
*/
public void setAntRun(Project project) throws BuildException {
! if (myos.equals("Mac OS"))
return;
String ant = project.getProperty("ant.home");
--- 192,198 ----
* @param project the current project.
*/
public void setAntRun(Project project) throws BuildException {
! if (myos.equals("Mac OS") || execWithCWD != null)
return;
String ant = project.getProperty("ant.home");
***************
*** 244,262 ****
protected Process exec() throws IOException {
! String userDir = System.getProperty("user.dir");
! try {
! if (myos.equals("Mac OS") && workingDirectory != null) {
! System.getProperties().put("user.dir",
!
workingDirectory.getAbsolutePath());
! }
!
! return Runtime.getRuntime().exec(getCommandline(),
getEnvironment());
! } finally {
! if (myos.equals("Mac OS") && workingDirectory != null) {
! System.getProperties().put("user.dir", userDir);
! }
! }
}
protected void waitFor(Process process) {
--- 235,290 ----
protected Process exec() throws IOException {
! if (workingDirectory == null) {
! // Easy.
! return Runtime.getRuntime().exec(cmdl, getEnvironment());
! } else if (execWithCWD != null) {
! // The best way to set cwd, if you have JDK 1.3.
! try {
! Object[] arguments = new Object[] {getCommandline(),
getEnvironment(), workingDirectory};
! return (Process)execWithCWD.invoke(Runtime.getRuntime(),
arguments);
! } catch (InvocationTargetException ite) {
! Throwable t = ite.getTargetException();
! if (t instanceof ThreadDeath) {
! throw (ThreadDeath)t;
! } else if (t instanceof IOException) {
! throw (IOException)t;
! } else {
! throw new IOException(t.toString());
! }
! } catch (Exception e) {
! // IllegalAccess, IllegalArgument, ClassCast
! throw new IOException(e.toString());
! }
! } else if (myos.equals("Mac OS")) {
! // Dubious Mac hack.
! System.getProperties().put("user.dir",
! workingDirectory.getAbsolutePath());
! try {
! return Runtime.getRuntime().exec(cmdl, getEnvironment());
! } finally {
! System.getProperties().put("user.dir", antWorkingDirectory);
! }
! } else if (myos.toLowerCase().indexOf("windows") >= 0 &&
! (myos.toLowerCase().indexOf("nt") >= 0 ||
! myos.indexOf("2000") >= 0)) {
! // cmd /c cd works OK on Windows NT & friends.
! String[] commandLine = new String[cmdl.length+5];
! commandLine[0] = "cmd";
! commandLine[1] = "/c";
! commandLine[2] = "cd";
! commandLine[3] = workingDirectory.getAbsolutePath();
! commandLine[4] = "&&";
! System.arraycopy(cmdl, 0, commandLine, 5, cmdl.length);
! return Runtime.getRuntime().exec(commandLine, getEnvironment());
! } else {
! // Fallback to the antRun wrapper script (POSIX, Win95/98, etc.):
! String[] commandLine = new String[cmdl.length+2];
! commandLine[0] = antRun;
! commandLine[1] = workingDirectory.getAbsolutePath();
! System.arraycopy(cmdl, 0, commandLine, 2, cmdl.length);
! return Runtime.getRuntime().exec(commandLine, getEnvironment());
! }
}
protected void waitFor(Process process) {