(1) it wouldn't use the basedir (2) all diagnostic messages have been swallowed Submitted by: Ilya A. Kriveshko <ilya@kaon.com> Note that this patch needs the magic of Execute but also access to the processes' standard input - this has been solved by adding a new static method launch to Execute which hands out the Process instance, the proper fix would be to handle input for the spawned processes as well. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271431 13f79535-47bb-0310-9956-ffa450edef68master
@@ -382,6 +382,28 @@ public class Execute { | |||
this.useVMLauncher = useVMLauncher; | |||
} | |||
/** | |||
* Creates a process that runs a command. | |||
* | |||
* @param project the Project, only used for logging purposes, may be null. | |||
* @param command the command to run | |||
* @param env the environment for the command | |||
* @param the working directory for the command | |||
* @param useVM use the built-in exec command for JDK 1.3 if available. | |||
* | |||
* @since 1.35, Ant 1.5 | |||
*/ | |||
public static Process launch(Project project, String[] command, | |||
String[] env, File dir, boolean useVM) | |||
throws IOException { | |||
CommandLauncher launcher = vmLauncher != null ? vmLauncher : shellLauncher; | |||
if (!useVM) { | |||
launcher = shellLauncher; | |||
} | |||
return launcher.exec(project, command, env, dir); | |||
} | |||
/** | |||
* Runs a process defined by the command line and returns its exit status. | |||
* | |||
@@ -390,12 +412,10 @@ public class Execute { | |||
* of the subprocess failed | |||
*/ | |||
public int execute() throws IOException { | |||
CommandLauncher launcher = vmLauncher != null ? vmLauncher : shellLauncher; | |||
if (!useVMLauncher) { | |||
launcher = shellLauncher; | |||
} | |||
final Process process = launch(project, getCommandline(), | |||
getEnvironment(), workingDirectory, | |||
useVMLauncher); | |||
final Process process = launcher.exec(project, getCommandline(), getEnvironment(), workingDirectory); | |||
try { | |||
streamHandler.setProcessInputStream(process.getOutputStream()); | |||
streamHandler.setProcessOutputStream(process.getInputStream()); | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2000 The Apache Software Foundation. All rights | |||
* Copyright (c) 2000,2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
@@ -72,7 +72,7 @@ public class StreamPumper implements Runnable { | |||
private final static int SIZE = 128; | |||
private InputStream is; | |||
private OutputStream os; | |||
private boolean finished; | |||
/** | |||
* Create a new stream pumper. | |||
@@ -92,6 +92,11 @@ public class StreamPumper implements Runnable { | |||
* Terminates as soon as the input stream is closed or an error occurs. | |||
*/ | |||
public void run() { | |||
synchronized(this) { | |||
// Just in case this object is reused in the future | |||
finished = false; | |||
} | |||
final byte[] buf = new byte[SIZE]; | |||
int length; | |||
@@ -102,6 +107,32 @@ public class StreamPumper implements Runnable { | |||
Thread.sleep(SLEEP); | |||
} catch (InterruptedException e) {} | |||
} | |||
} catch(IOException e) {} | |||
} catch(IOException e) { | |||
} finally { | |||
synchronized(this) { | |||
finished = true; | |||
notify(); | |||
} | |||
} | |||
} | |||
/** | |||
* Tells whether the end of the stream has been reached. | |||
* @return true is the stream has been exhausted. | |||
**/ | |||
public synchronized boolean isFinished() { | |||
return finished; | |||
} | |||
/** | |||
* This method blocks until the stream pumper finishes. | |||
* @see #isFinished() | |||
**/ | |||
public synchronized void waitFor() | |||
throws InterruptedException | |||
{ | |||
while(!isFinished()) { | |||
wait(); | |||
} | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights | |||
* Copyright (c) 2000-2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
@@ -65,8 +65,11 @@ import java.util.Vector; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.taskdefs.Execute; | |||
import org.apache.tools.ant.taskdefs.ExecTask; | |||
import org.apache.tools.ant.taskdefs.LogOutputStream; | |||
import org.apache.tools.ant.taskdefs.MatchingTask; | |||
import org.apache.tools.ant.taskdefs.StreamPumper; | |||
import org.apache.tools.ant.taskdefs.condition.Os; | |||
import org.apache.tools.ant.types.Commandline; | |||
import org.apache.tools.ant.types.FileSet; | |||
@@ -175,7 +178,7 @@ public class Cab extends MatchingTask { | |||
for (int i = 0; i < files.size() && upToDate; i++) { | |||
String file = files.elementAt(i).toString(); | |||
if (new File(baseDir, file).lastModified() > | |||
cabFile.lastModified()) { | |||
cabFile.lastModified()) { | |||
upToDate = false; | |||
} | |||
} | |||
@@ -212,7 +215,7 @@ public class Cab extends MatchingTask { | |||
* to be included in the cab, one file per line. | |||
*/ | |||
protected File createListFile(Vector files) | |||
throws IOException { | |||
throws IOException { | |||
File listFile = fileUtils.createTempFile("ant", "", null); | |||
PrintWriter writer = new PrintWriter(new FileOutputStream(listFile)); | |||
@@ -286,11 +289,45 @@ public class Cab extends MatchingTask { | |||
sb.append("\n").append(cabFile.getAbsolutePath()).append("\n"); | |||
try { | |||
Process p = Runtime.getRuntime().exec("listcab"); | |||
Process p = Execute.launch(getProject(), | |||
new String[] {"listcab"}, null, | |||
baseDir, true); | |||
OutputStream out = p.getOutputStream(); | |||
out.write(sb.toString().getBytes()); | |||
out.flush(); | |||
out.close(); | |||
// Create the stream pumpers to forward listcab's stdout and stderr to the log | |||
// note: listcab is an interactive program, and issues prompts for every new line. | |||
// Therefore, make it show only with verbose logging turned on. | |||
LogOutputStream outLog = new LogOutputStream(this, Project.MSG_VERBOSE); | |||
LogOutputStream errLog = new LogOutputStream(this, Project.MSG_ERR); | |||
StreamPumper outPump = new StreamPumper(p.getInputStream(), outLog); | |||
StreamPumper errPump = new StreamPumper(p.getErrorStream(), errLog); | |||
// Pump streams asynchronously | |||
(new Thread(outPump)).start(); | |||
(new Thread(errPump)).start(); | |||
int result = -99; // A wild default for when the thread is interrupted | |||
try { | |||
// Wait for the process to finish | |||
result = p.waitFor(); | |||
// Wait for the end of output and error streams | |||
outPump.waitFor(); | |||
outLog.close(); | |||
errPump.waitFor(); | |||
errLog.close(); | |||
} catch(InterruptedException ie) { | |||
log("Thread interrupted: " + ie); | |||
} | |||
// Informative summary message in case of errors | |||
if(result != 0) { | |||
log("Error executing listcab; error code: " + result); | |||
} | |||
} catch (IOException ex) { | |||
String msg = "Problem creating " + cabFile + " " + ex.getMessage(); | |||
throw new BuildException(msg); | |||