Hi
I like the discussion started about MatchingTask and Exec. Implementing the JUnit, JavaCC and others I faced similar problems. The problem is that tasks should use functionality instead of inherit. Therefor I did an Execution FrameWork to be used by tasks. If you need executiona and matching, inherit from MatchingTask and use the execution facility from the execution framwork.
I attached some of the classes.
The framework currently provides:
- Easy handling of commandline parameters
- Customizable input and output stream handlers including compatibvility to the old log based output of Exec
- watchdog, killing processes running for too long
- easy evaluation of the return code of the subprocess
- command line definition using nested XML elements
The framework currently does not provide:
- setting of current directory like Exec does (which can be added easily by extending Commandline)
- tom
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */
package org.apache.tools.ant;
import java.io.File;
import java.util.Vector;
import java.util.StringTokenizer;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
/**
* This object represents a path as used by CLASSPATH or PATH
* environment variable.
*
* <code>
* <sometask><br>
* <somepath>
* <element location="/path/to/file.jar" />
* <element
path="/path/to/file2.jar:/path/to/class2;/path/to/class3" />
* <element location="/path/to/file3.jar" />
* <element location="/path/to/file4.jar" />
* </somepath>
* </sometask><br>
* </code>
*
* The object implemention <code>sometask</code> must provide a method called
* <code>createSomepath</code> which returns an instance of <code>Path</code>.
* Nested path definitions are handled by the Path object and must be labeled
* <code>path</code>.<p>
*
* The path element takes a parameter <code>path</code> which will be parsed
* and split into single elements. It will usually be used
* to define a path from an environment variable.
*
* @author [EMAIL PROTECTED]
*/
public class Path {
final static boolean DETECT_DOS = (File.pathSeparatorChar == ';');
private Vector definition = new Vector();
/**
* Adds a element definition to the path.
* @param location the location of the element to add (must not be
* <code>null</code> nor empty.
**/
public void setLocation(String location) {
if (location != null && location.length() > 0) {
definition.addElement(translateFile(location));
}
}
/**
* Parses a path definition and creates single PatheElements.
* @param path the path definition.
*/
public void setPath(String path) {
final Vector elements = translatePath(path);
for (int i=0; i < elements.size(); i++) {
definition.addElement(elements.elementAt(i));
}
}
public Path createElement() {
return this;
}
/**
* Returns all path elements defined by this and netsed path objects.
* @return list of path elements.
*/
public String[] list() {
final String[] result = new String[definition.size()];
definition.copyInto(result);
return result;
}
/**
* Returns a textual representation of the path, which can be used as
* CLASSPATH or PATH environment variable definition.
* @return a textual representation of the path.
*/
public String toString() {
final String[] list = list();
// empty path return empty string
if (list.length == 0) return "";
// path containing one or more elements
final StringBuffer result = new StringBuffer(list[0].toString());
for (int i=1; i < list.length; i++) {
result.append(File.pathSeparatorChar);
result.append(list[i]);
}
return result.toString();
}
public static Vector translatePath(String source) {
final Vector result = new Vector();
if (source == null) return result;
final StringBuffer path = new StringBuffer(source);
int start = 0;
for (int i=0; i < path.length(); i++) {
if (!translateFileSep(path, i)) {
if (endOfElement(path, start, i)) {
// EMPTY ELEMENT DETECTION
if (start < i) {
result.addElement(path.substring(start, i));
}
start = i+1;
}
}
}
if (start < (path.length())) {
result.addElement(path.substring(start));
}
return result;
}
public static String translateFile(String source) {
if (source == null) return "";
final StringBuffer result = new StringBuffer(source);
for (int i=0; i < result.length(); i++) {
translateFileSep(result, i);
}
return result.toString();
}
protected static boolean translateFileSep(StringBuffer buffer, int pos) {
if (buffer.charAt(pos) == '/' || buffer.charAt(pos) == '\\') {
buffer.setCharAt(pos, File.separatorChar);
return true;
}
return false;
}
protected static boolean endOfElement(StringBuffer buffer, int start, int
pos) {
final char c = buffer.charAt(pos);
// DOS PATH DETECTION: SECOND CHARACTER IN ELEMENT IS :
if (DETECT_DOS && c == ':' && (pos - start) == 1) {
return false;
}
// PATH SEPERATOR DETECTION ON ':' AND ';' AND CURRENT PLATFORM
return c == ':' || c == ';' || c == File.pathSeparatorChar;
}
}
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import org.apache.tools.ant.BuildException; import java.util.Vector; import java.util.StringTokenizer; /** * Commandline objects help handling command lines specifying processes to * execute. * * The class can be used to define a command line as nested elements or as a * helper to define a command line by an application. * <p> * <code> * <someelement><br> * <acommandline executable="/executable/to/run"><br> * <argument value="argument 1" /><br> * <argument line="argument_1 argument_2 argument_3" /><br> * <argument value="argument 4" /><br> * </acommandline><br> * </someelement><br> * </code> * The element <code>someelement</code> must provide a method * <code>createAcommandline</code> which returns an instance of this class. * * @author [EMAIL PROTECTED] */ public class Commandline { private Vector definition = new Vector(); private String executable = null; private Argument argument = null; /** * Used for nested xml command line definitions. */ public class Argument { /** * Sets a single commandline argument. * * @param value a single commandline argument. */ public void setValue(String value) { Commandline.this.addValue(value); } /** * Line to split into several commandline arguments. * * @param line line to split into several commandline arguments */ public void setLine(String line) { Commandline.this.addLine(translateCommandline(line)); } } /** * Creates an argument object. * Each commandline object has at most one instance of the argument class. * @return the argument object. */ public Argument createArgument() { if (argument == null) { argument = new Argument(); } return argument; } /** * Sets the executable to run. */ public void setExecutable(String executable) { if (executable == null || executable.length() == 0) return; this.executable = executable; } public String getExecutable() { return executable; } public void addValue(String value) { if (value == null || value.length() == 0) return; definition.addElement(value); } public void addLine(String[] line) { for (int i=0; i < line.length; i++) { createArgument().setValue(line[i]); } } /** * Returns the executable and all defined arguments. */ public String[] getCommandline() { if (executable == null) return getArguments(); final String[] args = getArguments(); final String[] result = new String[args.length+1]; result[0] = executable; System.arraycopy(args, 0, result, 1, args.length); return result; } /** * Returns all arguments defined by <code>addLine</code>, * <code>addValue</code> or the argument object. */ public String[] getArguments() { final String [] result; result = new String[definition.size()]; definition.copyInto(result); return result; } public String toString() { return toString(getCommandline()); } public static String toString(String [] line) { // empty path return empty string if (line.length == 0) return ""; // path containing one or more elements final StringBuffer result = new StringBuffer(line[0]); for (int i=1; i < line.length; i++) { result.append(' '); result.append(line[i]); } return result.toString(); } public static String[] translateCommandline(String to_process) { // Runtime uses the same tokenizer. final StringTokenizer token = new StringTokenizer(to_process); final Commandline result = new Commandline(); while (token.hasMoreTokens()) { result.addValue(token.nextToken()); } return result.getArguments(); } }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Runs an external program. * * @author [EMAIL PROTECTED] */ public class Execute { /** Invalid exit code. **/ public final static int INVALID = Integer.MAX_VALUE; private String[] cmdl = null; private int exitValue = INVALID; private ExecuteStreamHandler streamHandler; private ExecuteWatchdog watchdog; /** * Creates a new execute object using <code>PumpStreamHandler</code> for * stream handling. */ public Execute() { this(new PumpStreamHandler(), null); } /** * Creates a new execute object. * * @param streamHandler the stream handler used to handle the input and * output streams of the subprocess. * @param watchdog a watchdog for the subprocess or <code>null</code> to * to disable a timeout for the subprocess. */ public Execute(ExecuteStreamHandler streamHandler, ExecuteWatchdog watchdog) { this.streamHandler = streamHandler; this.watchdog = watchdog; } /** * Returns the commandline used to create a subprocess. * * @return the commandline used to create a subprocess */ public String[] getCommandline() { return cmdl; } /** * Sets the commandline of the subprocess to launch. * * @param commandline the commandline of the subprocess to launch */ public void setCommandline(String[] commandline) { cmdl = commandline; } /** * Runs a process defined by the command line and returns its exit status. * * @return the exit status of the subprocess or <code>INVALID</code> * @exception java.io.IOExcpetion The exception is thrown, if launching * of the subprocess failed */ public int execute() throws IOException { final Process process = exec(); try { streamHandler.setProcessInputStream(process.getOutputStream()); streamHandler.setProcessOutputStream(process.getInputStream()); streamHandler.setProcessErrorStream(process.getErrorStream()); } catch (IOException e) { process.destroy(); throw e; } streamHandler.start(); if (watchdog != null) watchdog.start(process); waitFor(process); if (watchdog != null) watchdog.stop(); streamHandler.stop(); return getExitValue(); } protected Process exec() throws IOException { return Runtime.getRuntime().exec(getCommandline()); } protected void waitFor(Process process) { try { process.waitFor(); setExitValue(process.exitValue()); } catch (InterruptedException e) {} } protected void setExitValue(int value) { exitValue = value; } protected int getExitValue() { return exitValue; } }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; /** * Used by <code>Execute</code> to handle input and output stream of * subprocesses. * * @author [EMAIL PROTECTED] */ public interface ExecuteStreamHandler { /** * Install a handler for the input stream of the subprocess. * * @param os output stream to write to the standard input stream of the * subprocess */ public void setProcessInputStream(OutputStream os) throws IOException; /** * Install a handler for the error stream of the subprocess. * * @param is input stream to read from the error stream from the subprocess */ public void setProcessErrorStream(InputStream is) throws IOException; /** * Install a handler for the output stream of the subprocess. * * @param is input stream to read from the error stream from the subprocess */ public void setProcessOutputStream(InputStream is) throws IOException; /** * Start handling of the streams. */ public void start() throws IOException; /** * Stop handlin of the streams - will not be restarted. */ public void stop(); }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; /** * Destroys a process running for to long. * * @author [EMAIL PROTECTED] */ public class ExecuteWatchdog implements Runnable { private Process process; private int timeout; private boolean watch = true; /** * Creates a new watchdog. * * @param timeout the timeout for the process. */ public ExecuteWatchdog(int timeout) { if (timeout < 1) { throw new IllegalArgumentException("timeout lesser than 1."); } this.timeout = timeout; } /** * Watches the given process and terminates it, if it runs for to long. * * @param process the process to watch. */ public synchronized void start(Process process) { if (process == null) { throw new NullPointerException("process is null."); } if (this.process != null) { throw new IllegalStateException("Already running."); } watch = true; this.process = process; final Thread thread = new Thread(this, "WATCHDOG"); thread.setDaemon(true); thread.start(); } /** * Stops the watcher. */ public synchronized void stop() { watch = false; notifyAll(); process = null; } /** * Watches the process and terminates it, if it runs for to long. */ public synchronized void run() { try { // This isn't a Task, don't have a Project object to log. // project.log("ExecuteWatchdog: timeout = "+timeout+" msec", Project.MSG_VERBOSE); final long until = System.currentTimeMillis() + timeout; long now; while (watch && until > (now = System.currentTimeMillis())) { try { wait(until - now); } catch (InterruptedException e) {} } if (watch) { process.destroy(); } stop(); } catch(Exception e) { System.err.println("Exception in ExecuteWatchdog.run: "+e); } } }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; /** * Copies standard output and error of subprocesses to standard output and * error of the parent process. * * TODO: standard input of the subprocess is not implemented. * * @author [EMAIL PROTECTED] */ public class PumpStreamHandler implements ExecuteStreamHandler { private Thread inputThread; private Thread errorThread; public void setProcessOutputStream(InputStream is) { createProcessOutputPump(is, System.out); } public void setProcessErrorStream(InputStream is) { createProcessErrorPump(is, System.err); } public void setProcessInputStream(OutputStream os) { } public void start() { inputThread.start(); errorThread.start(); } public void stop() { try { inputThread.join(); } catch(InterruptedException e) {} try { errorThread.join(); } catch(InterruptedException e) {} } protected void createProcessOutputPump(InputStream is, OutputStream os) { inputThread = createPump(is, os); } protected void createProcessErrorPump(InputStream is, OutputStream os) { errorThread = createPump(is, os); } /** * Creates a stream pumper to copy the given input stream to the given output stream. */ protected Thread createPump(InputStream is, OutputStream os) { final Thread result = new Thread(new StreamPumper(is, os)); result.setDaemon(true); return result; } }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Copies all data from an input stream to an output stream. * * @author [EMAIL PROTECTED] */ public class StreamPumper implements Runnable { // TODO: make SIZE and SLEEP instance variables. // TODO: add a status flag to note if an error occured in run. private final static int SLEEP = 5; private final static int SIZE = 128; private InputStream is; private OutputStream os; /** * Create a new stream pumper. * * @param is input stream to read data from * @param os output stream to write data to. */ public StreamPumper(InputStream is, OutputStream os) { this.is = is; this.os = os; } /** * Copies data from the input stream to the output stream. * * Terminates as soon as the input stream is closed or an error occurs. */ public void run() { final byte[] buf = new byte[SIZE]; int length; try { while ((length = is.read(buf)) > 0) { os.write(buf, 0, length); try { Thread.sleep(SLEEP); } catch (InterruptedException e) {} } } catch(IOException e) {} } }
/* * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.tools.ant.taskdefs.optional; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import java.io.IOException; /** * Sample Exec implementation using <code>Execute</code>, <code>Commandline</code>, * <code>ExecuteStramHandler</code> and <code>ExecuteWatchdog</code>. * * @author [EMAIL PROTECTED] */ public class OExec extends Task { private final static String OUTPUT_LOG = "LOG"; private final static String OUTPUT_PIPE = "PIPE"; private Integer timeout = null; private Integer successvalue = new Integer(0); private boolean echo = false; private boolean haltonerror = true; private Commandline cmdl = new Commandline(); private String outputtype = OUTPUT_LOG; public void setTimeout(String value) { timeout = new Integer(value); } public void setEcho(String value) { echo = Project.toBoolean(value); } public void setSuccessvalue(String value) { successvalue = new Integer(value); } public void setHaltonerror(String value) { haltonerror = Project.toBoolean(value); } public void setOutputtype(String value) { outputtype = value; } public void setExecutable(String value) { cmdl.setExecutable(value); } public Commandline createCommandline() { return cmdl; } public void execute() throws BuildException { try { final Execute exe = new Execute(createHandler(), createWatchdog()); exe.setCommandline(cmdl.getCommandline()); if (echo) project.log("Executing "+cmdl); evalExitValue(exe.execute()); } catch (IOException e) { throw new BuildException("Execute failed: " + e); } } protected ExecuteStreamHandler createHandler() throws BuildException { if (OUTPUT_PIPE.equals(outputtype)) { return new LogStreamHandler(project, "exec", Project.MSG_INFO, "error", Project.MSG_INFO); } else if (OUTPUT_LOG.equals(outputtype)) { return new PumpStreamHandler(); } else { throw new BuildException("Unknown outputtype: " + outputtype); } } protected ExecuteWatchdog createWatchdog() throws BuildException { if (timeout == null) return null; return new ExecuteWatchdog(timeout.intValue()); } protected void evalExitValue(int value) throws BuildException { if (successvalue != null && value != successvalue.intValue()) { if (haltonerror) { throw new BuildException("Execute failed with exitValue=" + value); } else { project.log("Execute failed with exitValue=" + value); } } } }
