| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.monkeyrunner; |
| |
| import com.google.common.base.Predicate; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableMap.Builder; |
| import com.google.common.collect.Lists; |
| |
| import org.python.core.Py; |
| import org.python.core.PyException; |
| import org.python.core.PyJavaPackage; |
| import org.python.core.PyList; |
| import org.python.core.PyObject; |
| import org.python.core.PyString; |
| import org.python.core.PySystemState; |
| import org.python.util.InteractiveConsole; |
| import org.python.util.JLineConsole; |
| import org.python.util.PythonInterpreter; |
| |
| import java.io.File; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| |
| /** |
| * Runs Jython based scripts. |
| */ |
| public class ScriptRunner { |
| private static final Logger LOG = Logger.getLogger(MonkeyRunnerOptions.class.getName()); |
| |
| /** The "this" scope object for scripts. */ |
| private final Object scope; |
| private final String variable; |
| |
| /** Private constructor. */ |
| private ScriptRunner(Object scope, String variable) { |
| this.scope = scope; |
| this.variable = variable; |
| } |
| |
| /** Creates a new instance for the given scope object. */ |
| public static ScriptRunner newInstance(Object scope, String variable) { |
| return new ScriptRunner(scope, variable); |
| } |
| |
| /** |
| * Runs the specified Jython script. First runs the initialization script to |
| * preload the appropriate client library version. |
| * |
| * @param scriptfilename the name of the file to run. |
| * @param args the arguments passed in (excluding the filename). |
| * @param plugins a list of plugins to load. |
| * @return the error code from running the script. |
| */ |
| public static int run(String executablePath, String scriptfilename, |
| Collection<String> args, Map<String, |
| Predicate<PythonInterpreter>> plugins) { |
| // Add the current directory of the script to the python.path search path. |
| File f = new File(scriptfilename); |
| |
| // Adjust the classpath so jython can access the classes in the specified classpath. |
| Collection<String> classpath = Lists.newArrayList(f.getParent()); |
| classpath.addAll(plugins.keySet()); |
| |
| String[] argv = new String[args.size() + 1]; |
| argv[0] = f.getAbsolutePath(); |
| int x = 1; |
| for (String arg : args) { |
| argv[x++] = arg; |
| } |
| |
| initPython(executablePath, classpath, argv); |
| |
| PythonInterpreter python = new PythonInterpreter(); |
| |
| // Now let the mains run. |
| for (Map.Entry<String, Predicate<PythonInterpreter>> entry : plugins.entrySet()) { |
| boolean success; |
| try { |
| success = entry.getValue().apply(python); |
| } catch (Exception e) { |
| LOG.log(Level.SEVERE, "Plugin Main through an exception.", e); |
| continue; |
| } |
| if (!success) { |
| LOG.severe("Plugin Main returned error for: " + entry.getKey()); |
| } |
| } |
| |
| // Bind __name__ to __main__ so mains will run |
| python.set("__name__", "__main__"); |
| // Also find __file__ |
| python.set("__file__", scriptfilename); |
| |
| try { |
| python.execfile(scriptfilename); |
| } catch (PyException e) { |
| if (Py.SystemExit.equals(e.type)) { |
| // Then recover the error code so we can pass it on |
| return (Integer) e.value.__tojava__(Integer.class); |
| } |
| // Then some other kind of exception was thrown. Log it and return error; |
| LOG.log(Level.SEVERE, "Script terminated due to an exception", e); |
| return 1; |
| } |
| return 0; |
| } |
| |
| public static void runString(String executablePath, String script) { |
| initPython(executablePath); |
| PythonInterpreter python = new PythonInterpreter(); |
| python.exec(script); |
| } |
| |
| public static Map<String, PyObject> runStringAndGet(String executablePath, |
| String script, String... names) { |
| return runStringAndGet(executablePath, script, Arrays.asList(names)); |
| } |
| |
| public static Map<String, PyObject> runStringAndGet(String executablePath, |
| String script, Collection<String> names) { |
| initPython(executablePath); |
| final PythonInterpreter python = new PythonInterpreter(); |
| python.exec(script); |
| |
| Builder<String, PyObject> builder = ImmutableMap.builder(); |
| for (String name : names) { |
| builder.put(name, python.get(name)); |
| } |
| return builder.build(); |
| } |
| |
| private static void initPython(String executablePath) { |
| List<String> arg = Collections.emptyList(); |
| initPython(executablePath, arg, new String[] {""}); |
| } |
| |
| private static void initPython(String executablePath, |
| Collection<String> pythonPath, String[] argv) { |
| Properties props = new Properties(); |
| |
| // Build up the python.path |
| StringBuilder sb = new StringBuilder(); |
| sb.append(System.getProperty("java.class.path")); |
| for (String p : pythonPath) { |
| sb.append(":").append(p); |
| } |
| props.setProperty("python.path", sb.toString()); |
| |
| /** Initialize the python interpreter. */ |
| // Default is 'message' which displays sys-package-mgr bloat |
| // Choose one of error,warning,message,comment,debug |
| props.setProperty("python.verbose", "error"); |
| |
| // This needs to be set for sys.executable to function properly |
| props.setProperty("python.executable", executablePath); |
| |
| PythonInterpreter.initialize(System.getProperties(), props, argv); |
| |
| String frameworkDir = System.getProperty("java.ext.dirs"); |
| File monkeyRunnerJar = new File(frameworkDir, "monkeyrunner.jar"); |
| if (monkeyRunnerJar.canRead()) { |
| PySystemState.packageManager.addJar(monkeyRunnerJar.getAbsolutePath(), false); |
| } |
| } |
| |
| /** |
| * Start an interactive python interpreter. |
| */ |
| public static void console(String executablePath) { |
| initPython(executablePath); |
| InteractiveConsole python = new JLineConsole(); |
| python.interact(); |
| } |
| } |