diff --git a/bootstrap.bat b/bootstrap.bat index c435657d3..9b6758d33 100755 --- a/bootstrap.bat +++ b/bootstrap.bat @@ -44,7 +44,7 @@ mkdir %CLASSDIR% echo. echo ... Compiling Ant Classes -%JAVAC% -d %CLASSDIR% %TOOLS%\tar\*.java %TOOLS%\ant\*.java %TOOLS%\ant\taskdefs\*.java +%JAVAC% -d %CLASSDIR% %TOOLS%\tar\*.java %TOOLS%\ant\*.java %TOOLS%\ant\types\*.java %TOOLS%\ant\taskdefs\*.java echo. echo ... Copying Required Files diff --git a/bootstrap.sh b/bootstrap.sh index 3c171f3c7..00fd4a360 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -39,6 +39,7 @@ echo ... Compiling Ant Classes javac -d ${CLASSDIR} ${TOOLS}/tar/*.java javac -d ${CLASSDIR} ${TOOLS}/ant/*.java +javac -d ${CLASSDIR} ${TOOLS}/ant/types/*.java javac -d ${CLASSDIR} ${TOOLS}/ant/taskdefs/*.java echo ... Copying Required Files diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java index 3b1efc12f..bc0af59f9 100644 --- a/src/main/org/apache/tools/ant/IntrospectionHelper.java +++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java @@ -171,6 +171,7 @@ public class IntrospectionHelper { } else if (name.startsWith("add") && java.lang.Void.TYPE.equals(returnType) && args.length == 1 + && !java.lang.String.class.equals(args[0]) && !args[0].isArray() && !args[0].isPrimitive()) { diff --git a/src/main/org/apache/tools/ant/Path.java b/src/main/org/apache/tools/ant/Path.java index 0f8a96e1c..fc90fdadd 100644 --- a/src/main/org/apache/tools/ant/Path.java +++ b/src/main/org/apache/tools/ant/Path.java @@ -85,6 +85,7 @@ import java.text.StringCharacterIterator; * to define a path from an environment variable. * * @author Thomas.Haas@softwired-inc.com + * @author Stefan Bodewig */ public class Path { @@ -221,4 +222,8 @@ public class Path { } return false; } + + public int size() { + return definition.size(); + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecTask.java b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java new file mode 100644 index 000000000..278d786ad --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/ExecTask.java @@ -0,0 +1,218 @@ +/* + * 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.*; + +import java.io.*; + +/** + * Executes a given command if the os platform is appropriate. + * + * @author duncan@x180.com + * @author rubys@us.ibm.com + * @author thomas.haas@softwired-inc.com + * @author Stefan Bodewig + */ +public class ExecTask extends Task { + + private String os; + private File out; + private File dir; + private boolean failOnError = false; + private Integer timeout = null; + private Environment env = new Environment(); + private Commandline cmdl = new Commandline(); + private FileOutputStream fos = null; + + public void setTimeout(Integer value) { + timeout = value; + } + + public void setExecutable(String value) { + cmdl.setExecutable(value); + } + + public void setDir(File d) { + this.dir = d; + } + + public void setOs(String os) { + this.os = os; + } + + public void setCommand(Commandline cmdl) { + this.cmdl = cmdl; + } + + public void setOutput(File out) { + this.out = out; + } + + public void setFailonerror(boolean fail) { + failOnError = fail; + } + + public void addEnv(Environment.Variable var) { + env.addVariable(var); + } + + public void execute() throws BuildException { + if (cmdl.getExecutable() == null) { + throw new BuildException("no executable specified", location); + } + + String[] orig = cmdl.getCommandline(); + + int err = -1; // assume the worst + + // test if os match + String myos = System.getProperty("os.name"); + log("Myos = " + myos, Project.MSG_VERBOSE); + if ((os != null) && (os.indexOf(myos) < 0)){ + // this command will be executed only on the specified OS + log("Not found in " + os, Project.MSG_VERBOSE); + return; + } + + // default directory to the project's base directory + if (dir == null) dir = project.getBaseDir(); + + if (myos.toLowerCase().indexOf("windows") >= 0) { + if (!dir.equals(project.resolveFile("."))) { + if (myos.toLowerCase().indexOf("nt") >= 0) { + cmdl = new Commandline(); + cmdl.setExecutable("cmd"); + cmdl.addValue("/c"); + cmdl.addValue("cd"); + cmdl.addValue(dir.getAbsolutePath()); + cmdl.addValue("&&"); + cmdl.addLine(orig); + } else { + String ant = project.getProperty("ant.home"); + if (ant == null) { + throw new BuildException("Property 'ant.home' not found", location); + } + + String antRun = project.resolveFile(ant + "/bin/antRun.bat").toString(); + cmdl = new Commandline(); + cmdl.setExecutable(antRun); + cmdl.addValue(dir.getAbsolutePath()); + cmdl.addLine(orig); + } + } + } else { + String ant = project.getProperty("ant.home"); + if (ant == null) throw new BuildException("Property 'ant.home' not found", location); + String antRun = project.resolveFile(ant + "/bin/antRun").toString(); + + cmdl = new Commandline(); + cmdl.setExecutable(antRun); + cmdl.addValue(dir.getAbsolutePath()); + cmdl.addLine(orig); + } + + try { + // show the command + log(cmdl.toString(), Project.MSG_VERBOSE); + + final Execute exe = new Execute(createHandler(), createWatchdog()); + exe.setCommandline(cmdl.getCommandline()); + exe.setEnvironment(env.getVariables()); + err = exe.execute(); + if (err != 0) { + if (failOnError) { + throw new BuildException("Exec returned: "+err, location); + } else { + log("Result: " + err, Project.MSG_ERR); + } + } + } catch (IOException e) { + throw new BuildException("Execute failed: " + e, e, location); + } finally { + // close the output file if required + logFlush(); + } + } + + + protected ExecuteStreamHandler createHandler() throws BuildException { + if(out!=null) { + try { + fos = new FileOutputStream(out); + log("Output redirected to " + out, Project.MSG_VERBOSE); + return new PumpStreamHandler(fos); + } catch (FileNotFoundException fne) { + throw new BuildException("Cannot write to "+out, fne, location); + } + } else { + return new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + } + } + + protected ExecuteWatchdog createWatchdog() throws BuildException { + if (timeout == null) return null; + return new ExecuteWatchdog(timeout.intValue()); + } + + protected void logFlush() { + try { + if (fos != null) fos.close(); + } catch (IOException io) {} + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/Execute.java b/src/main/org/apache/tools/ant/taskdefs/Execute.java new file mode 100644 index 000000000..e11e092a6 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/Execute.java @@ -0,0 +1,185 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +/** + * Runs an external program. + * + * @author thomas.haas@softwired-inc.com + */ +public class Execute { + + /** Invalid exit code. **/ + public final static int INVALID = Integer.MAX_VALUE; + + private String[] cmdl = null; + private String[] env = null; + private int exitValue = INVALID; + private ExecuteStreamHandler streamHandler; + private ExecuteWatchdog watchdog; + + /** + * Creates a new execute object using PumpStreamHandler 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 null 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; + } + + /** + * Returns the commandline used to create a subprocess. + * + * @return the commandline used to create a subprocess + */ + public String[] getEnvironment() { + return env; + } + + + /** + * Sets the commandline of the subprocess to launch. + * + * @param commandline the commandline of the subprocess to launch + */ + public void setEnvironment(String[] env) { + this.env = env; + } + + + /** + * Runs a process defined by the command line and returns its exit status. + * + * @return the exit status of the subprocess or INVALID + * @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(); + if (watchdog != null) watchdog.checkException(); + return getExitValue(); + } + + + protected Process exec() throws IOException { + return Runtime.getRuntime().exec(getCommandline(), getEnvironment()); + } + + 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; + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java new file mode 100644 index 000000000..219c172ca --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java @@ -0,0 +1,100 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Path; +import org.apache.tools.ant.types.Commandline; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/* + * + * @author thomas.haas@softwired-inc.com + */ +public class ExecuteJava { + + private Commandline javaCommand = null; + + public void setJavaCommand(Commandline javaCommand) { + this.javaCommand = javaCommand; + } + + public void execute() throws BuildException{ + final String classname = javaCommand.getExecutable(); + final Object[] argument = { javaCommand.getArguments() }; + final Class[] param = { argument[0].getClass() }; + try { + final Class target = Class.forName(classname); + final Method main = target.getMethod("main", param); + main.invoke(null, argument); + } catch (NullPointerException e) { + throw new BuildException("Could not find main() method in " + classname); + } catch (ClassNotFoundException e) { + throw new BuildException("Could not find " + classname + ". Make sure you have it in your classpath"); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (!(t instanceof SecurityException)) { + throw new BuildException(t.toString()); + } + // else ignore because the security exception is thrown + // if the invoked application tried to call System.exit() + } catch (Exception e) { + throw new BuildException(e); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java new file mode 100644 index 000000000..80bfae0f7 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java @@ -0,0 +1,100 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Used by Execute to handle input and output stream of + * subprocesses. + * + * @author thomas.haas@softwired-inc.com + */ +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 handling of the streams - will not be restarted. + */ + public void stop(); +} diff --git a/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java b/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java new file mode 100644 index 000000000..f50359d98 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java @@ -0,0 +1,145 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.BuildException; + +/** + * Destroys a process running for too long. + * + * @author thomas.haas@softwired-inc.com + */ +public class ExecuteWatchdog implements Runnable { + + private Process process; + private int timeout; + private boolean watch = true; + private Exception caught = null; + + + /** + * 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) { + caught = e; + } + } + + public void checkException() throws BuildException { + if (caught != null) { + throw new BuildException("Exception in ExecuteWatchdog.run: " + + caught.getMessage(), caught); + } + } +} + diff --git a/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java b/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java new file mode 100644 index 000000000..d75c5f140 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java @@ -0,0 +1,134 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; + + +/** + * Logs each line written to this stream to the log system of ant. + * + * Tries to be smart about line separators.
+ * TODO: This class can be split to implement other line based processing + * of data written to the stream. + * + * @author thomas.haas@softwired-inc.com + */ +public class LogOutputStream extends OutputStream { + + private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + private boolean skip = false; + + private Task task; + private int level = Project.MSG_INFO; + + /** + * Creates a new instance of this class. + * + * @param task the task for whom to log + * @param level loglevel used to log data written to this stream. + */ + public LogOutputStream(Task task, int level) { + this.task = task; + this.level = level; + } + + + /** + * Write the data to the buffer and flush the buffer, if a line + * separator is detected. + * + * @param cc data to log (byte). + */ + public void write(int cc) throws IOException { + final byte c = (byte)cc; + if ((c == '\n') || (c == '\r')) { + if (!skip) processBuffer(); + } else buffer.write(cc); + skip = (c == '\r'); + } + + + /** + * Converts the buffer to a string and sends it to processLine + */ + protected void processBuffer() { + processLine(buffer.toString()); + buffer.reset(); + } + + /** + * Logs a line to the log system of ant. + * + * @param line the line to log. + */ + protected void processLine(String line) { + task.log(line, level); + } + + + /** + * Writes all remaining + */ + public void close() throws IOException { + if (buffer.size() > 0) processBuffer(); + super.close(); + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java new file mode 100644 index 000000000..57513bcad --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java @@ -0,0 +1,82 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +import java.io.OutputStream; +import java.io.InputStream; + +/** + * Logs standard output and error of a subprocess to the log system of ant. + * + * @author thomas.haas@softwired-inc.com + */ +public class LogStreamHandler extends PumpStreamHandler { + + /** + * Creates a new instance of this class. + * + * @param task the task for whom to log + * @param outlevel the loglevel used to log standard output + * @param errlevel the loglevel used to log standard error + */ + public LogStreamHandler(Task task, int outlevel, int errlevel) { + super(new LogOutputStream(task, outlevel), + new LogOutputStream(task, errlevel)); + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java new file mode 100644 index 000000000..c8902ae35 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java @@ -0,0 +1,136 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +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 thomas.haas@softwired-inc.com + */ +public class PumpStreamHandler implements ExecuteStreamHandler { + + private Thread inputThread; + private Thread errorThread; + + private OutputStream out, err; + + public PumpStreamHandler(OutputStream out, OutputStream err) { + this.out = out; + this.err = err; + } + + public PumpStreamHandler(OutputStream outAndErr) { + this(outAndErr, outAndErr); + } + + public PumpStreamHandler() { + this(System.out, System.err); + } + + public void setProcessOutputStream(InputStream is) { + createProcessOutputPump(is, out); + } + + + public void setProcessErrorStream(InputStream is) { + createProcessErrorPump(is, 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; + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java new file mode 100644 index 000000000..5ccc08361 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java @@ -0,0 +1,107 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Copies all data from an input stream to an output stream. + * + * @author thomas.haas@softwired-inc.com + */ +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) {} + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties index 11adacb8d..98642bac7 100644 --- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties +++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties @@ -23,7 +23,7 @@ tstamp=org.apache.tools.ant.taskdefs.Tstamp property=org.apache.tools.ant.taskdefs.Property taskdef=org.apache.tools.ant.taskdefs.Taskdef ant=org.apache.tools.ant.taskdefs.Ant -exec=org.apache.tools.ant.taskdefs.Exec +exec=org.apache.tools.ant.taskdefs.ExecTask tar=org.apache.tools.ant.taskdefs.Tar untar=org.apache.tools.ant.taskdefs.Untar available=org.apache.tools.ant.taskdefs.Available @@ -47,6 +47,7 @@ wlrun=org.apache.tools.ant.taskdefs.optional.ejb.WLRun wlstop=org.apache.tools.ant.taskdefs.optional.ejb.WLStop vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar +javacc=org.apache.tools.ant.taskdefs.optional.javacc.JavaCC # deprecated ant tasks (kept for back compatibility) javadoc2=org.apache.tools.ant.taskdefs.Javadoc diff --git a/src/main/org/apache/tools/ant/types/Commandline.java b/src/main/org/apache/tools/ant/types/Commandline.java new file mode 100644 index 000000000..029cf35dd --- /dev/null +++ b/src/main/org/apache/tools/ant/types/Commandline.java @@ -0,0 +1,300 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.types; + +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. + *

+ * + * <someelement>
+ *   <acommandline executable="/executable/to/run">
+ *     <argument value="argument 1" />
+ *     <argument line="argument_1 argument_2 argument_3" />
+ *     <argument value="argument 4" />
+ *   </acommandline>
+ * </someelement>
+ *
+ * The element someelement must provide a method + * createAcommandline which returns an instance of this class. + * + * @author thomas.haas@softwired-inc.com + * @author Stefan Bodewig + */ +public class Commandline { + + private Vector definition = new Vector(); + private String executable = null; + private Argument argument = null; + + public Commandline(String to_process) { + super(); + String[] tmp = translateCommandline(to_process); + if (tmp != null && tmp.length > 0) { + setExecutable(tmp[0]); + for (int i=1; iaddLine, + * addValue 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 == null || line.length == 0) return ""; + + // path containing one or more elements + final StringBuffer result = new StringBuffer(); + for (int i=0; i < line.length; i++) { + if (i > 0) { + result.append(' '); + } + + // try to place quotes around arguments that need them + if (line[i].indexOf("\"") > -1) { + if (line[i].indexOf("\'") > -1) { + throw new BuildException("Can\'t handle single and double quotes in same argument"); + } else { + result.append('\'').append(line[i]).append('\''); + } + } else if (line[i].indexOf("\'") > -1 + || line[i].indexOf(" ") > -1) { + result.append('\"').append(line[i]).append('\"'); + } else { + result.append(line[i]); + } + } + return result.toString(); + } + + public static String[] translateCommandline(String to_process) { + if (to_process == null || to_process.length() == 0) { + return new String[0]; + } + + // parse with a simple finite state machine + + final int normal = 0; + final int inQuote = 1; + final int inDoubleQuote = 2; + int state = normal; + StringTokenizer tok = new StringTokenizer(to_process, "\\\"\' ", true); + Vector v = new Vector(); + StringBuffer current = new StringBuffer(); + + while (tok.hasMoreTokens()) { + String nextTok = tok.nextToken(); + switch (state) { + case inQuote: + if ("\'".equals(nextTok)) { + state = normal; + } else { + current.append(nextTok); + } + break; + case inDoubleQuote: + if ("\"".equals(nextTok)) { + state = normal; + } else { + current.append(nextTok); + } + break; + default: + if ("\'".equals(nextTok)) { + state = inQuote; + } else if ("\"".equals(nextTok)) { + state = inDoubleQuote; + } else if (" ".equals(nextTok)) { + if (current.length() != 0) { + v.addElement(current.toString()); + current.setLength(0); + } + } else if ("\\".equals(nextTok)) { + if (tok.hasMoreTokens()) { + current.append(tok.nextToken()); + } else { + throw new BuildException("stray backslash in " + + to_process); + } + } else { + current.append(nextTok); + } + break; + } + } + + if (current.length() != 0) { + v.addElement(current.toString()); + } + + if (state == inQuote || state == inDoubleQuote) { + throw new BuildException("unbalanced quotes in " + to_process); + } + + String[] args = new String[v.size()]; + v.copyInto(args); + return args; + } + + public int size() { + return definition.size() + (executable == null ? 0 : 1); + } + +} diff --git a/src/main/org/apache/tools/ant/types/CommandlineJava.java b/src/main/org/apache/tools/ant/types/CommandlineJava.java new file mode 100644 index 000000000..110496ec0 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/CommandlineJava.java @@ -0,0 +1,135 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.Path; + +/* + * + * @author thomas.haas@softwired-inc.com + */ +public class CommandlineJava { + + private Commandline vmCommand = new Commandline(); + private Commandline javaCommand = new Commandline(); + private Path classpath = new Path(); + private String vmVersion; + + + public CommandlineJava() { + setVm("java"); + setVmversion(org.apache.tools.ant.Project.getJavaVersion()); + } + + public Commandline.Argument createArgument() { + return javaCommand.createArgument(); + } + + public Commandline.Argument createVmArgument() { + return vmCommand.createArgument(); + } + + public void setVm(String vm) { + vmCommand.setExecutable(vm); + } + + public void setVmversion(String value) { + vmVersion = value; + } + + public void setClassname(String classname) { + javaCommand.setExecutable(classname); + } + + public Path createClasspath() { + return classpath; + } + + public String getVmversion() { + return vmVersion; + } + + public String[] getCommandline() { + int size = vmCommand.size() + javaCommand.size(); + if (classpath.size() > 0) { + size += 2; + } + + String[] result = new String[size]; + System.arraycopy(vmCommand.getCommandline(), 0, + result, 0, vmCommand.size()); + if (classpath.size() > 0) { + result[vmCommand.size()] = "-classpath"; + result[vmCommand.size()+1] = classpath.toString(); + } + System.arraycopy(javaCommand.getCommandline(), 0, + result, result.length-javaCommand.size(), + javaCommand.size()); + return result; + } + + + public String toString() { + return Commandline.toString(getCommandline()); + } + + public int size() { + int size = vmCommand.size() + javaCommand.size(); + if (classpath.size() > 0) { + size += 2; + } + return size; + } +} diff --git a/src/main/org/apache/tools/ant/types/Environment.java b/src/main/org/apache/tools/ant/types/Environment.java new file mode 100644 index 000000000..a13d5e51c --- /dev/null +++ b/src/main/org/apache/tools/ant/types/Environment.java @@ -0,0 +1,110 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.BuildException; +import java.util.Vector; + +/** + * Wrapper for environment variables. + * + * @author Stefan Bodewig + */ +public class Environment { + + private Vector variables; + + public static class Variable { + private String key, value; + + public Variable() { + super(); + } + + public void setKey(String key) { + this.key = key; + } + public void setValue(String value) { + this.value = value; + } + public String getContent() throws BuildException { + if (key == null || value == null) { + throw new BuildException("key and value must be specified for environment variables."); + } + StringBuffer sb = new StringBuffer(key.trim()); + sb.append("=").append(value.trim()); + return sb.toString(); + } + } + + public Environment() { + variables = new Vector(); + } + + public void addVariable(Variable var) { + variables.addElement(var); + } + + public String[] getVariables() throws BuildException { + if (variables.size() == 0) { + return null; + } + String[] result = new String[variables.size()]; + for (int i=0; i. + */ + +package org.apache.tools.ant.types; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Simple class to build a TestSuite out of the individual test classes. + * + * @author Stefan Bodewig stefan.bodewig@megabit.net + */ +public class AllJUnitTests extends TestCase { + + public AllJUnitTests(String name) { + super(name); + } + + public static Test suite() { + TestSuite suite = new TestSuite(CommandlineTest.class); + suite.addTest(new TestSuite(CommandlineJavaTest.class)); + return suite; + } +} diff --git a/src/testcases/org/apache/tools/ant/types/CommandlineJavaTest.java b/src/testcases/org/apache/tools/ant/types/CommandlineJavaTest.java new file mode 100644 index 000000000..1264276d4 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/types/CommandlineJavaTest.java @@ -0,0 +1,100 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.types; + +import junit.framework.TestCase; +import junit.framework.AssertionFailedError; + +import java.io.File; + +/** + * JUnit 3 testcases for org.apache.tools.ant.CommandlineJava + * + * @author Stefan Bodewig stefan.bodewig@megabit.net + */ +public class CommandlineJavaTest extends TestCase { + + public CommandlineJavaTest(String name) { + super(name); + } + + public void testGetCommandline() { + CommandlineJava c = new CommandlineJava(); + c.createArgument().setValue("org.apache.tools.ant.CommandlineJavaTest"); + c.setClassname("junit.textui.TestRunner"); + c.createVmArgument().setValue("-Djava.compiler=NONE"); + String[] s = c.getCommandline(); + assertEquals("no classpath", 4, s.length); + assertEquals("no classpath", "java", s[0]); + assertEquals("no classpath", "-Djava.compiler=NONE", s[1]); + assertEquals("no classpath", "junit.textui.TestRunner", s[2]); + assertEquals("no classpath", + "org.apache.tools.ant.CommandlineJavaTest", s[3]); + + c.createClasspath().setLocation("junit.jar"); + c.createClasspath().setLocation("ant.jar"); + s = c.getCommandline(); + assertEquals("with classpath", 6, s.length); + assertEquals("with classpath", "java", s[0]); + assertEquals("with classpath", "-Djava.compiler=NONE", s[1]); + assertEquals("with classpath", "-classpath", s[2]); + assertEquals("with classpath", + "junit.jar"+java.io.File.pathSeparator+"ant.jar", s[3]); + assertEquals("with classpath", "junit.textui.TestRunner", s[4]); + assertEquals("with classpath", + "org.apache.tools.ant.CommandlineJavaTest", s[5]); + } + +} diff --git a/src/testcases/org/apache/tools/ant/types/CommandlineTest.java b/src/testcases/org/apache/tools/ant/types/CommandlineTest.java new file mode 100644 index 000000000..9a068d407 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/types/CommandlineTest.java @@ -0,0 +1,161 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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 apache@apache.org. + * + * 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 + * . + */ + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.BuildException; + +import junit.framework.TestCase; +import junit.framework.AssertionFailedError; + +import java.io.File; + +/** + * JUnit 3 testcases for org.apache.tools.ant.CommandLine + * + * @author Stefan Bodewig stefan.bodewig@megabit.net + */ +public class CommandlineTest extends TestCase { + + public CommandlineTest(String name) { + super(name); + } + + public void testTokenizer() { + String[] s = Commandline.translateCommandline("1 2 3"); + assertEquals("Simple case", 3, s.length); + for (int i=0; i<3; i++) { + assertEquals(""+(i+1), s[i]); + } + + s = Commandline.translateCommandline(""); + assertEquals("empty string", 0, s.length); + + s = Commandline.translateCommandline(null); + assertEquals("null", 0, s.length); + + s = Commandline.translateCommandline("1 \'2\' 3"); + assertEquals("Simple case with single quotes", 3, s.length); + assertEquals("Single quotes have been stripped", "2", s[1]); + + s = Commandline.translateCommandline("1 \"2\" 3"); + assertEquals("Simple case with double quotes", 3, s.length); + assertEquals("Double quotes have been stripped", "2", s[1]); + + s = Commandline.translateCommandline("1 \"2 3\" 4"); + assertEquals("Case with double quotes and whitespace", 3, s.length); + assertEquals("Double quotes stripped, space included", "2 3", s[1]); + + s = Commandline.translateCommandline("1 \"2\'3\" 4"); + assertEquals("Case with double quotes around single quote", 3, s.length); + assertEquals("Double quotes stripped, single quote included", "2\'3", + s[1]); + + s = Commandline.translateCommandline("1 \'2 3\' 4"); + assertEquals("Case with single quotes and whitespace", 3, s.length); + assertEquals("Single quotes stripped, space included", "2 3", s[1]); + + s = Commandline.translateCommandline("1 \'2\"3\' 4"); + assertEquals("Case with single quotes around double quote", 3, s.length); + assertEquals("Single quotes stripped, double quote included", "2\"3", + s[1]); + + s = Commandline.translateCommandline("1 2\\ 3 4"); + assertEquals("Case with quoted whitespace", 3, s.length); + assertEquals("space included", "2 3", s[1]); + + s = Commandline.translateCommandline("1 2\\\'3 4"); + assertEquals("Case with quoted single quote", 3, s.length); + assertEquals("single quote included", "2\'3", s[1]); + + s = Commandline.translateCommandline("1 2\\\"3 4"); + assertEquals("Case with quoted double quote", 3, s.length); + assertEquals("double quote included", "2\"3", s[1]); + + s = Commandline.translateCommandline("1 2\\\\3 4"); + assertEquals("Case with quoted backslash", 3, s.length); + assertEquals("backslash included", "2\\3", s[1]); + + // now to the expected failures + try { + s = Commandline.translateCommandline("a \\"); + fail("stray \\ undetected"); + } catch (BuildException be) { + assertEquals("stray backslash in a \\", be.getMessage()); + } + + try { + s = Commandline.translateCommandline("a \'b c"); + fail("unbalanced single quotes undetected"); + } catch (BuildException be) { + assertEquals("unbalanced quotes in a \'b c", be.getMessage()); + } + + try { + s = Commandline.translateCommandline("a \"b c"); + fail("unbalanced double quotes undetected"); + } catch (BuildException be) { + assertEquals("unbalanced quotes in a \"b c", be.getMessage()); + } + } + + public void testToString() { + assertEquals("", Commandline.toString(new String[0])); + assertEquals("", Commandline.toString(null)); + assertEquals("1 2 3", Commandline.toString(new String[] {"1", "2", "3"})); + assertEquals("1 \"2 3\"", Commandline.toString(new String[] {"1", "2 3"})); + assertEquals("1 \"2\'3\"", Commandline.toString(new String[] {"1", "2\'3"})); + assertEquals("1 \'2\"3\'", Commandline.toString(new String[] {"1", "2\"3"})); + } +}