/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.runners;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.python.pydev.core.IInterpreterManager;
import org.python.pydev.core.IPythonNature;
import com.aptana.shared_core.structure.Tuple;
/**
* This class provides a factory for creating a suitable runner for any project and running
* some code or script.
*
* @author Leo Soto
*/
public class UniversalRunner {
/**
* This is the interface users will be using.
*
* @return the appropriate runner based on the nature type.
*/
public static AbstractRunner getRunner(IPythonNature nature) {
try {
int interpreterType = nature.getInterpreterType();
switch (interpreterType) {
case IInterpreterManager.INTERPRETER_TYPE_PYTHON:
return new PythonRunner(nature);
case IInterpreterManager.INTERPRETER_TYPE_JYTHON:
return new JythonRunner(nature);
case IInterpreterManager.INTERPRETER_TYPE_IRONPYTHON:
return new IronPythonRunner(nature);
default:
throw new RuntimeException("Interpreter type " + interpreterType + "not recognized");
}
} catch (CoreException e) {
throw new RuntimeException(e);
}
}
/**
* Abstract runner. Clients must override the way to provide the command line to be run.
*/
public static abstract class AbstractRunner {
protected IPythonNature nature;
public AbstractRunner(IPythonNature nature) {
this.nature = nature;
}
/**
* Subclasses must override to provide the appropriate command line.
*/
public abstract String[] getCommandLine(List<String> argumentsAfterPython);
/**
* Runs the code and returns its output.
*
* @return a tuple with stdout and stderr
*/
public Tuple<String, String> runCodeAndGetOutput(String code, String[] args, File workingDir,
IProgressMonitor monitor) {
if (args == null) {
args = new String[0];
}
List<String> cmd = new ArrayList<String>();
cmd.add("-c");
cmd.add(code);
cmd.addAll(Arrays.asList(args));
// We just hope this sets the right env. But looks like it ignores
// the interpreter env variables (IInterpreterInfo#getEnvVariables)
return new SimpleRunner().runAndGetOutput(getCommandLine(cmd), workingDir, nature, monitor, null);
}
/**
* Runs the script and returns its output.
*
* @return a tuple with stdout and stderr
*/
public Tuple<String, String> runScriptAndGetOutput(String script, String[] args, File workingDir,
IProgressMonitor monitor) {
if (args == null) {
args = new String[0];
}
List<String> cmd = new ArrayList<String>();
cmd.add(script);
cmd.addAll(Arrays.asList(args));
// We just hope this sets the right env. But looks like it ignores
// the interpreter env variables (IInterpreterInfo#getEnvVariables)
return new SimpleRunner().runAndGetOutput(getCommandLine(cmd), workingDir, nature, monitor, null);
}
public Tuple<Process, String> createProcess(String script, String[] args, File workingDir,
IProgressMonitor monitor) {
File file = new File(script);
if (!file.exists()) {
throw new RuntimeException("The script passed for execution (" + script + ") does not exist.");
}
if (args == null) {
args = new String[0];
}
List<String> cmd = new ArrayList<String>();
cmd.add(script);
cmd.addAll(Arrays.asList(args));
return new SimpleRunner().run(getCommandLine(cmd), workingDir, nature, monitor);
}
}
/**
* Provides the command line needed for running a python script
*/
public static class PythonRunner extends AbstractRunner {
public PythonRunner(IPythonNature nature) {
super(nature);
}
public String[] getCommandLine(List<String> argumentsAfterPython) {
String interpreter;
try {
interpreter = nature.getProjectInterpreter().getExecutableOrJar();
} catch (Exception e) {
throw new RuntimeException("Can't get the interpreter", e);
}
argumentsAfterPython.add(0, "-u");
argumentsAfterPython.add(0, interpreter);
return argumentsAfterPython.toArray(new String[argumentsAfterPython.size()]);
}
}
/**
* Provides the command line needed for running a jython script
*/
public static class JythonRunner extends AbstractRunner {
public JythonRunner(IPythonNature nature) {
super(nature);
}
public String[] getCommandLine(List<String> argumentsAfterPython) {
try {
return SimpleJythonRunner.makeExecutableCommandStr(nature.getProjectInterpreter().getExecutableOrJar(),
argumentsAfterPython.get(0), "", argumentsAfterPython.subList(1, argumentsAfterPython.size())
.toArray(new String[0]));
} catch (Exception e1) {
throw new RuntimeException(e1);
}
}
}
/**
* Provides the command line needed for running an ironpython script
*/
public static class IronPythonRunner extends AbstractRunner {
public IronPythonRunner(IPythonNature nature) {
super(nature);
}
public String[] getCommandLine(List<String> argumentsAfterPython) {
try {
argumentsAfterPython.add(0, "-u");
return SimpleIronpythonRunner.preparePythonCallParameters(nature.getProjectInterpreter()
.getExecutableOrJar(), argumentsAfterPython.get(0),
argumentsAfterPython.subList(1, argumentsAfterPython.size()).toArray(new String[0]), false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}