package org.pyant.tasks;
import java.io.File;
import java.io.IOException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
import org.apache.tools.ant.taskdefs.LogStreamHandler;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Path;
/**
* @author Ron Smith
*
* Base class for Python Ant tasks.
* Tasks inheriting from this task support the following attributes:
* <ul>
* <li>python - Use to set the Python executable to be used. Defaults to "python".
* <li>pythonpath - The PYTHONPATH to be used
* <li>failonerror - If true, fail if any errors occurred
* <li>optimize - The Python optimize level to use. 0 (no optimization), 1, or 2.
* </ul>
*/
public class PythonBaseTask extends Task
{
// PYTHONPATH to be used
protected Path pythonpath = null;
// Python executable
protected String python = "python";
// If true, fail on errors as a result of this task executing
protected boolean failonerror=true;
// Python optimize level to be used
// 0: no optimization
// 1: -O
// 2: -OO
protected int optimize = 0;
private Commandline cmdline = null;
/**
* Set the PYTHONPATH as an environment variable into the given Execute task
*/
protected void setPythonPathInExecute(Execute runner)
{
if(pythonpath != null)
{
Project project = getProject();
project.log("pythonpath: " + pythonpath);//, Project.MSG_DEBUG);
String envSetting = "PYTHONPATH=" + pythonpath;
String[] environment = new String[] {envSetting};
runner.setEnvironment(environment);
}
}
/**
* Set the PYTHONPATH as a string
* @param pythonpath The pythonpath to set.
*/
public void setPythonpath(Path pythonpath)
{
this.pythonpath = pythonpath;
}
/**
* Set the PYTHONPATH as an Ant path reference.
* @param pathref
*/
public void setPythonpathref(String pathref)
{
Project project = getProject();
this.pythonpath = (Path)project.getReference(pathref);
}
public String getPython()
{
return python;
}
public void setPython(String python)
{
this.python = python;
}
/**
* Convert file paths to be forward slashes for Python.
* Windows: Why oh why would you choose the universal
* escape character as your file delimeter?
*/
protected String fixFilePath(String path)
{
return(path.replace('\\', '/'));
}
public void setFailonerror(boolean failonerror)
{
this.failonerror = failonerror;
}
/**
* Execute the python script.
* This function will construct the command line, set up the environment,
* and execute the Python script. The particulars are expected to be set
* up by derived classes.
* @param project - Ant project
* @param workingDirectory - Working directory to execute from
* @param failMsg - Message to be reported upon execution failure
*/
protected void executeScript(Project project,
File workingDirectory, String failMsg)
{
Commandline cmdline = getCommandline();
prepCommandline();
Execute runner = createExecute(project, cmdline,
workingDirectory);
execExecuteTask(failMsg, runner);
}
/**
* Execute the given Execute task.
* @param failMsg
* @param runner
*/
protected void execExecuteTask(String failMsg, Execute runner)
{
try
{
int res = runner.execute();
if(res != 0)
{
failureOcurred(failMsg);
}
}
catch(IOException ie)
{
throw new BuildException("Error executing task", ie, getLocation());
}
}
/**
* Create the Execute task to be run.
* @param project - Ant project
* @param cmdline - Commandline to be executed
* @param workingDirectory - Working directory to execute from
* @return Execute task
*/
protected Execute createExecute(Project project, Commandline cmdline,
File workingDirectory)
{
ExecuteStreamHandler streamHandler = createStreamHandler();
Execute runner = new Execute(streamHandler, null);
if(workingDirectory != null)
{
runner.setWorkingDirectory(workingDirectory);
}
setPythonPathInExecute(runner);
runner.setAntRun(project);
runner.setCommandline(cmdline.getCommandline());
return runner;
}
protected ExecuteStreamHandler createStreamHandler()
{
LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO,
Project.MSG_WARN);
return streamHandler;
}
protected Commandline getCommandline()
{
if(this.cmdline == null)
{
this.cmdline = createCommandline();
}
return this.cmdline;
}
protected Commandline createCommandline()
{
Commandline cmdline = new Commandline();
return cmdline;
}
protected void prepCommandline()
{
cmdline.setExecutable(this.python);
addCommandlineArgs(cmdline);
}
protected void addCommandlineArgs(Commandline cmdline)
{
setOptimizeArgument(cmdline);
}
protected void failureOcurred(String msg)
{
log("failureOcurred", Project.MSG_DEBUG);
if(failonerror == true)
{
throw new BuildException(msg, getLocation());
}
else
{
log(msg, Project.MSG_ERR);
}
}
public void setOptimize(int optimize)
{
this.optimize = optimize;
}
protected void setOptimizeArgument(Commandline cmdline)
{
String optimizeString = null;
if(optimize == 1)
optimizeString = "-O";
else if(optimize == 2)
optimizeString = "-OO";
if(optimizeString != null)
cmdline.createArgument(true).setValue(optimizeString);
}
}