git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1350460 13f79535-47bb-0310-9956-ffa450edef68master
@@ -10,6 +10,10 @@ Changes that could break older environments: | |||||
EOL ASIS will not insert a newline even if fixlast is set to true. | EOL ASIS will not insert a newline even if fixlast is set to true. | ||||
Bugzilla report 53036 | Bugzilla report 53036 | ||||
* The CommandLauncher hierarchy that used to be a set of inner | |||||
classes of Execute has been extracted to the | |||||
org.apache.tools.ant.taskdefs.launcher package. | |||||
Fixed bugs: | Fixed bugs: | ||||
----------- | ----------- | ||||
@@ -36,9 +40,14 @@ Fixed bugs: | |||||
Other changes: | Other changes: | ||||
-------------- | -------------- | ||||
* merged the ZIP package from Commons Compress, it can now read | |||||
archives using Zip64 extensions (files and archives bigger that 4GB | |||||
and with more that 64k entries). | |||||
* merged the ZIP package from Commons Compress, it can now read | |||||
archives using Zip64 extensions (files and archives bigger that 4GB | |||||
and with more that 64k entries). | |||||
* a new task <commandlaucher> can be used to configure the | |||||
CommandLauncher used by Ant when forking external programs or new | |||||
Java VMs. | |||||
Bugzilla Report 52706. | |||||
Changes from Ant 1.8.3 TO Ant 1.8.4 | Changes from Ant 1.8.3 TO Ant 1.8.4 | ||||
=================================== | =================================== | ||||
@@ -0,0 +1,33 @@ | |||||
package org.apache.tools.ant.taskdefs; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Task; | |||||
import org.apache.tools.ant.taskdefs.launcher.CommandLauncher; | |||||
public class CommandLauncherTask extends Task { | |||||
private boolean vmLauncher; | |||||
private CommandLauncher commandLauncher; | |||||
public synchronized void addConfigured(CommandLauncher commandLauncher) { | |||||
if (this.commandLauncher != null) { | |||||
throw new BuildException("Only one CommandLauncher can be installed"); | |||||
} | |||||
this.commandLauncher = commandLauncher; | |||||
} | |||||
@Override | |||||
public void execute() { | |||||
if (commandLauncher != null) { | |||||
if (vmLauncher) { | |||||
CommandLauncher.setVMLauncher(getProject(), commandLauncher); | |||||
} else { | |||||
CommandLauncher.setShellLauncher(getProject(), commandLauncher); | |||||
} | |||||
} | |||||
} | |||||
public void setVmLauncher(boolean vmLauncher) { | |||||
this.vmLauncher = vmLauncher; | |||||
} | |||||
} |
@@ -30,6 +30,7 @@ bzip2=org.apache.tools.ant.taskdefs.BZip2 | |||||
checksum=org.apache.tools.ant.taskdefs.Checksum | checksum=org.apache.tools.ant.taskdefs.Checksum | ||||
chmod=org.apache.tools.ant.taskdefs.Chmod | chmod=org.apache.tools.ant.taskdefs.Chmod | ||||
classloader=org.apache.tools.ant.taskdefs.Classloader | classloader=org.apache.tools.ant.taskdefs.Classloader | ||||
commandlaucher=org.apache.tools.ant.taskdefs.CommandLauncherTask | |||||
componentdef=org.apache.tools.ant.taskdefs.Componentdef | componentdef=org.apache.tools.ant.taskdefs.Componentdef | ||||
concat=org.apache.tools.ant.taskdefs.Concat | concat=org.apache.tools.ant.taskdefs.Concat | ||||
condition=org.apache.tools.ant.taskdefs.ConditionTask | condition=org.apache.tools.ant.taskdefs.ConditionTask | ||||
@@ -0,0 +1,184 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.taskdefs.condition.Os; | |||||
import org.apache.tools.ant.types.Commandline; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
/** | |||||
* A command launcher for a particular JVM/OS platform. This class is | |||||
* a general purpose command launcher which can only launch commands | |||||
* in the current working directory. | |||||
*/ | |||||
public class CommandLauncher { | |||||
private static final String ANT_SHELL_LAUNCHER_REF_ID = "ant.shellLauncher"; | |||||
private static final String ANT_VM_LAUNCHER_REF_ID = "ant.vmLauncher"; | |||||
protected static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
private static CommandLauncher vmLauncher = null; | |||||
private static CommandLauncher shellLauncher = null; | |||||
static { | |||||
// Try using a JDK 1.3 launcher | |||||
try { | |||||
if(!Os.isFamily("os/2")) { | |||||
vmLauncher = new Java13CommandLauncher(); | |||||
} | |||||
} catch(NoSuchMethodException exc) { | |||||
// Ignore and keep trying | |||||
} | |||||
if (Os.isFamily("mac") && !Os.isFamily("unix")) { | |||||
// Mac | |||||
shellLauncher = new MacCommandLauncher(new CommandLauncher()); | |||||
} else if (Os.isFamily("os/2")) { | |||||
// OS/2 | |||||
shellLauncher = new OS2CommandLauncher(new CommandLauncher()); | |||||
} else if (Os.isFamily("windows")) { | |||||
CommandLauncher baseLauncher = new CommandLauncher(); | |||||
if (!Os.isFamily("win9x")) { | |||||
// Windows XP/2000/NT | |||||
shellLauncher = new WinNTCommandLauncher(baseLauncher); | |||||
} else { | |||||
// Windows 98/95 - need to use an auxiliary script | |||||
shellLauncher = new ScriptCommandLauncher("bin/antRun.bat", baseLauncher); | |||||
} | |||||
} else if (Os.isFamily("netware")) { | |||||
CommandLauncher baseLauncher = new CommandLauncher(); | |||||
shellLauncher = new PerlScriptCommandLauncher("bin/antRun.pl", baseLauncher); | |||||
} else if (Os.isFamily("openvms")) { | |||||
// OpenVMS | |||||
try { | |||||
shellLauncher = new VmsCommandLauncher(); | |||||
} catch(NoSuchMethodException exc) { | |||||
// Ignore and keep trying | |||||
} | |||||
} else { | |||||
// Generic | |||||
shellLauncher = new ScriptCommandLauncher("bin/antRun", new CommandLauncher()); | |||||
} | |||||
} | |||||
/** | |||||
* Launches the given command in a new process. | |||||
* | |||||
* @param project | |||||
* The project that the command is part of. | |||||
* @param cmd | |||||
* The command to execute. | |||||
* @param env | |||||
* The environment for the new process. If null, the | |||||
* environment of the current process is used. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* if attempting to run a command in a specific directory. | |||||
*/ | |||||
public Process exec(Project project, String[] cmd, String[] env) throws IOException { | |||||
if(project != null) { | |||||
project.log("Execute:CommandLauncher: " + Commandline.describeCommand(cmd), Project.MSG_DEBUG); | |||||
} | |||||
return Runtime.getRuntime().exec(cmd, env); | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* The project that the command is part of. | |||||
* @param cmd | |||||
* The command to execute. | |||||
* @param env | |||||
* The environment for the new process. If null, the | |||||
* environment of the current process is used. | |||||
* @param workingDir | |||||
* The directory to start the command in. If null, the | |||||
* current directory is used. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* if trying to change directory. | |||||
*/ | |||||
public Process exec(Project project, String[] cmd, String[] env, File workingDir) throws IOException { | |||||
if(workingDir == null) { | |||||
return exec(project, cmd, env); | |||||
} | |||||
throw new IOException("Cannot execute a process in different " | |||||
+ "directory under this JVM"); | |||||
} | |||||
public static CommandLauncher getShellLauncher(Project project) { | |||||
CommandLauncher launcher = null; | |||||
if(project != null) { | |||||
launcher = (CommandLauncher) project | |||||
.getReference(ANT_SHELL_LAUNCHER_REF_ID); | |||||
} | |||||
if (launcher == null) { | |||||
launcher = getSystemLauncher(ANT_SHELL_LAUNCHER_REF_ID); | |||||
} | |||||
if (launcher == null) { | |||||
launcher = shellLauncher; | |||||
} | |||||
return launcher; | |||||
} | |||||
public static CommandLauncher getVMLauncher(Project project) { | |||||
CommandLauncher launcher = null; | |||||
if (project != null) { | |||||
launcher = (CommandLauncher)project.getReference(ANT_VM_LAUNCHER_REF_ID); | |||||
} | |||||
if (launcher == null) { | |||||
launcher = getSystemLauncher(ANT_VM_LAUNCHER_REF_ID); | |||||
} | |||||
if (launcher == null) { | |||||
launcher = vmLauncher; | |||||
} | |||||
return launcher; | |||||
} | |||||
private static CommandLauncher getSystemLauncher(String launcherRefId) { | |||||
CommandLauncher launcher = null; | |||||
String launcherClass = System.getProperty(launcherRefId); | |||||
if (launcherClass != null) { | |||||
try { | |||||
launcher = (CommandLauncher) Class.forName(launcherClass) | |||||
.newInstance(); | |||||
} | |||||
catch(InstantiationException e) { | |||||
System.err.println("Could not instantiate launcher class " | |||||
+ launcherClass + ": " + e.getMessage()); | |||||
} | |||||
catch(IllegalAccessException e) { | |||||
System.err.println("Could not instantiate launcher class " | |||||
+ launcherClass + ": " + e.getMessage()); | |||||
} | |||||
catch(ClassNotFoundException e) { | |||||
System.err.println("Could not instantiate launcher class " | |||||
+ launcherClass + ": " + e.getMessage()); | |||||
} | |||||
} | |||||
return launcher; | |||||
} | |||||
public static void setVMLauncher(Project project, CommandLauncher launcher) { | |||||
if (project != null) { | |||||
project.addReference(ANT_VM_LAUNCHER_REF_ID, launcher); | |||||
} | |||||
} | |||||
public static void setShellLauncher(Project project, CommandLauncher launcher) { | |||||
if (project != null) { | |||||
project.addReference(ANT_SHELL_LAUNCHER_REF_ID, launcher); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,37 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher that proxies another command | |||||
* launcher. Sub-classes override exec(args, env, workdir). | |||||
*/ | |||||
public class CommandLauncherProxy extends CommandLauncher { | |||||
private final CommandLauncher myLauncher; | |||||
protected CommandLauncherProxy(CommandLauncher launcher) { | |||||
myLauncher = launcher; | |||||
} | |||||
/** | |||||
* Launches the given command in a new process. Delegates this | |||||
* method to the proxied launcher. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env) | |||||
throws IOException { | |||||
return myLauncher.exec(project, cmd, env); | |||||
} | |||||
} |
@@ -0,0 +1,53 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.types.Commandline; | |||||
/** | |||||
* A command launcher for JDK/JRE 1.3 (and higher). Uses the built-in | |||||
* Runtime.exec() command. | |||||
*/ | |||||
public class Java13CommandLauncher extends CommandLauncher { | |||||
public Java13CommandLauncher() throws NoSuchMethodException { | |||||
// Used to verify if Java13 is available, is prerequisite in ant 1.8 | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* the working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* probably forwarded from Runtime#exec. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
try { | |||||
if (project != null) { | |||||
project.log("Execute:Java13CommandLauncher: " | |||||
+ Commandline.describeCommand(cmd), | |||||
Project.MSG_DEBUG); | |||||
} | |||||
return Runtime.getRuntime().exec(cmd, env, workingDir); | |||||
} catch(IOException ioex) { | |||||
throw ioex; | |||||
} catch(Exception exc) { | |||||
// IllegalAccess, IllegalArgument, ClassCast | |||||
throw new BuildException("Unable to execute command", exc); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,47 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher for Mac that uses a dodgy mechanism to change | |||||
* working directory before launching commands. | |||||
*/ | |||||
public class MacCommandLauncher extends CommandLauncherProxy { | |||||
public MacCommandLauncher(CommandLauncher launcher) { | |||||
super(launcher); | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
if (workingDir == null) { | |||||
return exec(project, cmd, env); | |||||
} | |||||
System.getProperties().put("user.dir", workingDir.getAbsolutePath()); | |||||
try { | |||||
return exec(project, cmd, env); | |||||
} | |||||
finally { | |||||
System.getProperties().put("user.dir", System.getProperty("user.dir")); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,65 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher for OS/2 that uses 'cmd.exe' when launching | |||||
* commands in directories other than the current working directory. | |||||
* | |||||
* <p>Unlike Windows NT and friends, OS/2's cd doesn't support the /d | |||||
* switch to change drives and directories in one go.</p> | |||||
*/ | |||||
public class OS2CommandLauncher extends CommandLauncherProxy { | |||||
public OS2CommandLauncher(CommandLauncher launcher) { | |||||
super(launcher); | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
File commandDir = workingDir; | |||||
if (workingDir == null) { | |||||
if (project != null) { | |||||
commandDir = project.getBaseDir(); | |||||
} else { | |||||
return exec(project, cmd, env); | |||||
} | |||||
} | |||||
// Use cmd.exe to change to the specified drive and | |||||
// directory before running the command | |||||
final int preCmdLength = 7; | |||||
final String cmdDir = commandDir.getAbsolutePath(); | |||||
String[] newcmd = new String[cmd.length + preCmdLength]; | |||||
// CheckStyle:MagicNumber OFF - do not bother | |||||
newcmd[0] = "cmd"; | |||||
newcmd[1] = "/c"; | |||||
newcmd[2] = cmdDir.substring(0, 2); | |||||
newcmd[3] = "&&"; | |||||
newcmd[4] = "cd"; | |||||
newcmd[5] = cmdDir.substring(2); | |||||
newcmd[6] = "&&"; | |||||
// CheckStyle:MagicNumber ON | |||||
System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length); | |||||
return exec(project, newcmd, env); | |||||
} | |||||
} |
@@ -0,0 +1,73 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.MagicNames; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher that uses an auxiliary perl script to launch | |||||
* commands in directories other than the current working directory. | |||||
*/ | |||||
public class PerlScriptCommandLauncher extends CommandLauncherProxy { | |||||
private final String myScript; | |||||
public PerlScriptCommandLauncher(String script, CommandLauncher launcher) { | |||||
super(launcher); | |||||
myScript = script; | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
if (project == null) { | |||||
if(workingDir == null) { | |||||
return exec(project, cmd, env); | |||||
} | |||||
throw new IOException("Cannot locate antRun script: " | |||||
+ "No project provided"); | |||||
} | |||||
// Locate the auxiliary script | |||||
String antHome = project.getProperty(MagicNames.ANT_HOME); | |||||
if (antHome == null) { | |||||
throw new IOException("Cannot locate antRun script: " | |||||
+ "Property '" + MagicNames.ANT_HOME | |||||
+ "' not found"); | |||||
} | |||||
String antRun = FILE_UTILS.resolveFile(project.getBaseDir(), | |||||
antHome + File.separator | |||||
+ myScript).toString(); | |||||
// Build the command | |||||
File commandDir = workingDir; | |||||
if (workingDir == null) { | |||||
commandDir = project.getBaseDir(); | |||||
} | |||||
// CheckStyle:MagicNumber OFF | |||||
String[] newcmd = new String[cmd.length + 3]; | |||||
newcmd[0] = "perl"; | |||||
newcmd[1] = antRun; | |||||
newcmd[2] = commandDir.getAbsolutePath(); | |||||
System.arraycopy(cmd, 0, newcmd, 3, cmd.length); | |||||
// CheckStyle:MagicNumber ON | |||||
return exec(project, newcmd, env); | |||||
} | |||||
} |
@@ -0,0 +1,71 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.MagicNames; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher that uses an auxiliary script to launch commands | |||||
* in directories other than the current working directory. | |||||
*/ | |||||
public class ScriptCommandLauncher extends CommandLauncherProxy { | |||||
private final String myScript; | |||||
public ScriptCommandLauncher(String script, CommandLauncher launcher) { | |||||
super(launcher); | |||||
myScript = script; | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
if (project == null) { | |||||
if (workingDir == null) { | |||||
return exec(project, cmd, env); | |||||
} | |||||
throw new IOException("Cannot locate antRun script: " | |||||
+ "No project provided"); | |||||
} | |||||
// Locate the auxiliary script | |||||
String antHome = project.getProperty(MagicNames.ANT_HOME); | |||||
if(antHome == null) { | |||||
throw new IOException("Cannot locate antRun script: " | |||||
+ "Property '" + MagicNames.ANT_HOME | |||||
+ "' not found"); | |||||
} | |||||
String antRun = FILE_UTILS.resolveFile(project.getBaseDir(), | |||||
antHome + File.separator | |||||
+ myScript).toString(); | |||||
// Build the command | |||||
File commandDir = workingDir; | |||||
if(workingDir == null) { | |||||
commandDir = project.getBaseDir(); | |||||
} | |||||
String[] newcmd = new String[cmd.length + 2]; | |||||
newcmd[0] = antRun; | |||||
newcmd[1] = commandDir.getAbsolutePath(); | |||||
System.arraycopy(cmd, 0, newcmd, 2, cmd.length); | |||||
return exec(project, newcmd, env); | |||||
} | |||||
} |
@@ -0,0 +1,128 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.BufferedWriter; | |||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
/** | |||||
* 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. | |||||
*/ | |||||
public class VmsCommandLauncher extends Java13CommandLauncher { | |||||
public VmsCommandLauncher() throws NoSuchMethodException { | |||||
super(); | |||||
} | |||||
/** | |||||
* Launches the given command in a new process. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env) | |||||
throws IOException { | |||||
File cmdFile = createCommandFile(cmd, env); | |||||
Process p = super.exec(project, new String[] {cmdFile.getPath()}, env); | |||||
deleteAfter(cmdFile, p); | |||||
return p; | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. Note that under Java 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. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
File cmdFile = createCommandFile(cmd, env); | |||||
Process p = super.exec(project, new String[] { | |||||
cmdFile.getPath() | |||||
}, env, workingDir); | |||||
deleteAfter(cmdFile, p); | |||||
return p; | |||||
} | |||||
/* | |||||
* Writes the command into a temporary DCL script and returns the | |||||
* corresponding File object. The script will be deleted on exit. | |||||
* @param cmd the command line to execute as an array of strings. | |||||
* @param env the environment to set as an array of strings. | |||||
* @return the command File. | |||||
* @throws IOException if errors are encountered creating the file. | |||||
*/ | |||||
private File createCommandFile(String[] cmd, String[] env) | |||||
throws IOException { | |||||
File script = FILE_UTILS.createTempFile("ANT", ".COM", null, true, true); | |||||
BufferedWriter out = null; | |||||
try { | |||||
out = new BufferedWriter(new FileWriter(script)); | |||||
// add the environment as logicals to the DCL script | |||||
if (env != null) { | |||||
int eqIndex; | |||||
for (int i = 0; i < env.length; i++) { | |||||
eqIndex = env[i].indexOf('='); | |||||
if (eqIndex != -1) { | |||||
out.write("$ DEFINE/NOLOG "); | |||||
out.write(env[i].substring(0, eqIndex)); | |||||
out.write(" \""); | |||||
out.write(env[i].substring(eqIndex + 1)); | |||||
out.write('\"'); | |||||
out.newLine(); | |||||
} | |||||
} | |||||
} | |||||
out.write("$ " + cmd[0]); | |||||
for (int i = 1; i < cmd.length; i++) { | |||||
out.write(" -"); | |||||
out.newLine(); | |||||
out.write(cmd[i]); | |||||
} | |||||
} finally { | |||||
FileUtils.close(out); | |||||
} | |||||
return script; | |||||
} | |||||
private void deleteAfter(final File f, final Process p) { | |||||
new Thread() { | |||||
@Override | |||||
public void run() { | |||||
try { | |||||
p.waitFor(); | |||||
} catch(InterruptedException e) { | |||||
// ignore | |||||
} | |||||
FileUtils.delete(f); | |||||
} | |||||
}.start(); | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
package org.apache.tools.ant.taskdefs.launcher; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when | |||||
* launching commands in directories other than the current working | |||||
* directory. | |||||
*/ | |||||
public class WinNTCommandLauncher extends CommandLauncherProxy { | |||||
public WinNTCommandLauncher(CommandLauncher launcher) { | |||||
super(launcher); | |||||
} | |||||
/** | |||||
* Launches the given command in a new process, in the given | |||||
* working directory. | |||||
* | |||||
* @param project | |||||
* the Ant project. | |||||
* @param cmd | |||||
* the command line to execute as an array of strings. | |||||
* @param env | |||||
* the environment to set as an array of strings. | |||||
* @param workingDir | |||||
* working directory where the command should run. | |||||
* @return the created Process. | |||||
* @throws IOException | |||||
* forwarded from the exec method of the command launcher. | |||||
*/ | |||||
@Override | |||||
public Process exec(Project project, String[] cmd, String[] env, | |||||
File workingDir) throws IOException { | |||||
File commandDir = workingDir; | |||||
if (workingDir == null) { | |||||
if (project != null) { | |||||
commandDir = project.getBaseDir(); | |||||
} else { | |||||
return exec(project, cmd, env); | |||||
} | |||||
} | |||||
// Use cmd.exe to change to the specified directory before running | |||||
// the command | |||||
final int preCmdLength = 6; | |||||
String[] newcmd = new String[cmd.length + preCmdLength]; | |||||
// CheckStyle:MagicNumber OFF - do not bother | |||||
newcmd[0] = "cmd"; | |||||
newcmd[1] = "/c"; | |||||
newcmd[2] = "cd"; | |||||
newcmd[3] = "/d"; | |||||
newcmd[4] = commandDir.getAbsolutePath(); | |||||
newcmd[5] = "&&"; | |||||
// CheckStyle:MagicNumber ON | |||||
System.arraycopy(cmd, 0, newcmd, preCmdLength, cmd.length); | |||||
return exec(project, newcmd, env); | |||||
} | |||||
} |