Browse Source

New Execution Framework.

This new framework should ease development of tasks that need to
execute external processes.

<exec> now invokes ExecTask, a reimplementation of Exec that uses the
new framework but has some additional features.

Submitted by:	Thomas Hass <thomas.haas@softwired-inc.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267799 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 25 years ago
parent
commit
3e3008a15b
22 changed files with 2105 additions and 6 deletions
  1. +1
    -1
      bootstrap.bat
  2. +1
    -0
      bootstrap.sh
  3. +1
    -0
      src/main/org/apache/tools/ant/IntrospectionHelper.java
  4. +5
    -0
      src/main/org/apache/tools/ant/Path.java
  5. +218
    -0
      src/main/org/apache/tools/ant/taskdefs/ExecTask.java
  6. +185
    -0
      src/main/org/apache/tools/ant/taskdefs/Execute.java
  7. +100
    -0
      src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java
  8. +100
    -0
      src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java
  9. +145
    -0
      src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java
  10. +134
    -0
      src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java
  11. +82
    -0
      src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java
  12. +136
    -0
      src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java
  13. +107
    -0
      src/main/org/apache/tools/ant/taskdefs/StreamPumper.java
  14. +2
    -1
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  15. +300
    -0
      src/main/org/apache/tools/ant/types/Commandline.java
  16. +135
    -0
      src/main/org/apache/tools/ant/types/CommandlineJava.java
  17. +110
    -0
      src/main/org/apache/tools/ant/types/Environment.java
  18. +1
    -0
      src/testcases/org/apache/tools/ant/AllJUnitTests.java
  19. +4
    -4
      src/testcases/org/apache/tools/ant/IntrospectionHelperTest.java
  20. +77
    -0
      src/testcases/org/apache/tools/ant/types/AllJUnitTests.java
  21. +100
    -0
      src/testcases/org/apache/tools/ant/types/CommandlineJavaTest.java
  22. +161
    -0
      src/testcases/org/apache/tools/ant/types/CommandlineTest.java

+ 1
- 1
bootstrap.bat View File

@@ -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


+ 1
- 0
bootstrap.sh View File

@@ -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


+ 1
- 0
src/main/org/apache/tools/ant/IntrospectionHelper.java View File

@@ -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()) {


+ 5
- 0
src/main/org/apache/tools/ant/Path.java View File

@@ -85,6 +85,7 @@ import java.text.StringCharacterIterator;
* to define a path from an environment variable.
*
* @author Thomas.Haas@softwired-inc.com
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
*/

public class Path {
@@ -221,4 +222,8 @@ public class Path {
}
return false;
}

public int size() {
return definition.size();
}
}

+ 218
- 0
src/main/org/apache/tools/ant/taskdefs/ExecTask.java View File

@@ -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
* <http://www.apache.org/>.
*/

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 <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
*/
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) {}
}

}

+ 185
- 0
src/main/org/apache/tools/ant/taskdefs/Execute.java View File

@@ -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
* <http://www.apache.org/>.
*/

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 <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;
}

/**
* 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 <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();
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;
}
}

+ 100
- 0
src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java View File

@@ -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
* <http://www.apache.org/>.
*/


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);
}
}
}

+ 100
- 0
src/main/org/apache/tools/ant/taskdefs/ExecuteStreamHandler.java View File

@@ -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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.taskdefs;

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 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();
}

+ 145
- 0
src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java View File

@@ -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
* <http://www.apache.org/>.
*/

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);
}
}
}


+ 134
- 0
src/main/org/apache/tools/ant/taskdefs/LogOutputStream.java View File

@@ -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
* <http://www.apache.org/>.
*/

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.<br>
* 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 <code>processLine</code>
*/
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();
}
}

+ 82
- 0
src/main/org/apache/tools/ant/taskdefs/LogStreamHandler.java View File

@@ -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
* <http://www.apache.org/>.
*/

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));
}

}

+ 136
- 0
src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java View File

@@ -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
* <http://www.apache.org/>.
*/

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;
}

}

+ 107
- 0
src/main/org/apache/tools/ant/taskdefs/StreamPumper.java View File

@@ -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
* <http://www.apache.org/>.
*/

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) {}
}
}

+ 2
- 1
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -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


+ 300
- 0
src/main/org/apache/tools/ant/types/Commandline.java View File

@@ -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
* <http://www.apache.org/>.
*/

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.
* <p>
* <code>
* &lt;someelement&gt;<br>
* &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
* &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
* &nbsp;&nbsp;&lt;/acommandline&gt;<br>
* &lt;/someelement&gt;<br>
* </code>
* The element <code>someelement</code> must provide a method
* <code>createAcommandline</code> which returns an instance of this class.
*
* @author thomas.haas@softwired-inc.com
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
*/
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; i<tmp.length; i++) {
addValue(tmp[i]);
}
}
}

public Commandline() {
super();
}

/**
* 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 == 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);
}

}

+ 135
- 0
src/main/org/apache/tools/ant/types/CommandlineJava.java View File

@@ -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
* <http://www.apache.org/>.
*/

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;
}
}

+ 110
- 0
src/main/org/apache/tools/ant/types/Environment.java View File

@@ -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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.types;

import org.apache.tools.ant.BuildException;
import java.util.Vector;

/**
* Wrapper for environment variables.
*
* @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
*/
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<result.length; i++) {
result[i] = ((Variable) variables.elementAt(i)).getContent();
}
return result;
}
}

+ 1
- 0
src/testcases/org/apache/tools/ant/AllJUnitTests.java View File

@@ -73,6 +73,7 @@ public class AllJUnitTests extends TestCase {
TestSuite suite = new TestSuite(IntrospectionHelperTest.class);
suite.addTest(new TestSuite(EnumeratedAttributeTest.class));
suite.addTest(new TestSuite(PathTest.class));
suite.addTest(org.apache.tools.ant.types.AllJUnitTests.suite());
return suite;
}
}

+ 4
- 4
src/testcases/org/apache/tools/ant/IntrospectionHelperTest.java View File

@@ -183,8 +183,8 @@ public class IntrospectionHelperTest extends TestCase {
Hashtable h = new Hashtable();
h.put("six", java.lang.String.class);
h.put("thirteen", java.lang.StringBuffer.class);
h.put("fourteen", java.lang.String.class);
h.put("fifteen", java.lang.String.class);
h.put("fourteen", java.lang.StringBuffer.class);
h.put("fifteen", java.lang.StringBuffer.class);
IntrospectionHelper ih = IntrospectionHelper.getHelper(getClass());
Enumeration enum = ih.getNestedElements();
while (enum.hasMoreElements()) {
@@ -216,7 +216,7 @@ public class IntrospectionHelperTest extends TestCase {
return "test";
}

public String createFifteen() {
public StringBuffer createFifteen() {
throw new NullPointerException();
}

@@ -238,7 +238,7 @@ public class IntrospectionHelperTest extends TestCase {
sb.append("test");
}
public void addFourteen(String s) {
public void addFourteen(StringBuffer s) {
throw new NullPointerException();
}



+ 77
- 0
src/testcases/org/apache/tools/ant/types/AllJUnitTests.java View File

@@ -0,0 +1,77 @@
/*
* 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
* <http://www.apache.org/>.
*/

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 <a href="mailto:stefan.bodewig@megabit.net">stefan.bodewig@megabit.net</a>
*/
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;
}
}

+ 100
- 0
src/testcases/org/apache/tools/ant/types/CommandlineJavaTest.java View File

@@ -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
* <http://www.apache.org/>.
*/

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 <a href="mailto:stefan.bodewig@megabit.net">stefan.bodewig@megabit.net</a>
*/
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]);
}

}

+ 161
- 0
src/testcases/org/apache/tools/ant/types/CommandlineTest.java View File

@@ -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
* <http://www.apache.org/>.
*/

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 <a href="mailto:stefan.bodewig@megabit.net">stefan.bodewig@megabit.net</a>
*/
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"}));
}
}

Loading…
Cancel
Save