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