From 98e2821b38a775737e42a2479a6bc65107210859 Mon Sep 17 00:00:00 2001 From: Elliot Kroo Date: Thu, 11 Mar 2010 15:21:30 -0800 Subject: reorganizing the first level of folders (trunk/branch folders are not the git way :) --- .../org/mozilla/javascript/tools/shell/Main.java | 638 +++++++++++++++++++++ 1 file changed, 638 insertions(+) create mode 100644 infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java (limited to 'infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java') diff --git a/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java b/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java new file mode 100644 index 0000000..9120892 --- /dev/null +++ b/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java @@ -0,0 +1,638 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Patrick Beard + * Norris Boyd + * Igor Bukanov + * Rob Ginda + * Kurt Westerfeld + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript.tools.shell; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.net.MalformedURLException; +import java.util.*; +import org.mozilla.javascript.*; +import org.mozilla.javascript.tools.ToolErrorReporter; + +/** + * The shell program. + * + * Can execute scripts interactively or in batch mode at the command line. + * An example of controlling the JavaScript engine. + * + * @author Norris Boyd + */ +public class Main +{ + public static ShellContextFactory + shellContextFactory = new ShellContextFactory(); + + public static Global global = new Global(); + static protected ToolErrorReporter errorReporter; + static protected int exitCode = 0; + static private final int EXITCODE_RUNTIME_ERROR = 3; + static private final int EXITCODE_FILE_NOT_FOUND = 4; + static boolean processStdin = true; + static Vector fileList = new Vector(5); + private static SecurityProxy securityImpl; + + static { + global.initQuitAction(new IProxy(IProxy.SYSTEM_EXIT)); + } + + /** + * Proxy class to avoid proliferation of anonymous classes. + */ + private static class IProxy implements ContextAction, QuitAction + { + private static final int PROCESS_FILES = 1; + private static final int EVAL_INLINE_SCRIPT = 2; + private static final int SYSTEM_EXIT = 3; + + private int type; + String[] args; + String scriptText; + + IProxy(int type) + { + this.type = type; + } + + public Object run(Context cx) + { + if (type == PROCESS_FILES) { + processFiles(cx, args); + } else if (type == EVAL_INLINE_SCRIPT) { + Script script = loadScriptFromSource(cx, scriptText, + "", 1, null); + if (script != null) { + evaluateScript(script, cx, getGlobal()); + } + } else { + throw Kit.codeBug(); + } + return null; + } + + public void quit(Context cx, int exitCode) + { + if (type == SYSTEM_EXIT) { + System.exit(exitCode); + return; + } + throw Kit.codeBug(); + } + } + + /** + * Main entry point. + * + * Process arguments as would a normal Java program. Also + * create a new Context and associate it with the current thread. + * Then set up the execution environment and begin to + * execute scripts. + */ + public static void main(String args[]) { + try { + if (Boolean.getBoolean("rhino.use_java_policy_security")) { + initJavaPolicySecuritySupport(); + } + } catch (SecurityException ex) { + ex.printStackTrace(System.err); + } + + int result = exec(args); + if (result != 0) { + System.exit(result); + } + } + + /** + * Execute the given arguments, but don't System.exit at the end. + */ + public static int exec(String origArgs[]) + { + errorReporter = new ToolErrorReporter(false, global.getErr()); + shellContextFactory.setErrorReporter(errorReporter); + String[] args = processOptions(origArgs); + if (processStdin) + fileList.addElement(null); + + if (!global.initialized) { + global.init(shellContextFactory); + } + IProxy iproxy = new IProxy(IProxy.PROCESS_FILES); + iproxy.args = args; + shellContextFactory.call(iproxy); + + return exitCode; + } + + static void processFiles(Context cx, String[] args) + { + // define "arguments" array in the top-level object: + // need to allocate new array since newArray requires instances + // of exactly Object[], not ObjectSubclass[] + Object[] array = new Object[args.length]; + System.arraycopy(args, 0, array, 0, args.length); + Scriptable argsObj = cx.newArray(global, array); + global.defineProperty("arguments", argsObj, + ScriptableObject.DONTENUM); + + for (int i=0; i < fileList.size(); i++) { + processSource(cx, (String) fileList.elementAt(i)); + } + + } + + public static Global getGlobal() + { + return global; + } + + /** + * Parse arguments. + */ + public static String[] processOptions(String args[]) + { + String usageError; + goodUsage: for (int i = 0; ; ++i) { + if (i == args.length) { + return new String[0]; + } + String arg = args[i]; + if (!arg.startsWith("-")) { + processStdin = false; + fileList.addElement(arg); + String[] result = new String[args.length - i - 1]; + System.arraycopy(args, i+1, result, 0, args.length - i - 1); + return result; + } + if (arg.equals("-version")) { + if (++i == args.length) { + usageError = arg; + break goodUsage; + } + int version; + try { + version = Integer.parseInt(args[i]); + } catch (NumberFormatException ex) { + usageError = args[i]; + break goodUsage; + } + if (!Context.isValidLanguageVersion(version)) { + usageError = args[i]; + break goodUsage; + } + shellContextFactory.setLanguageVersion(version); + continue; + } + if (arg.equals("-opt") || arg.equals("-O")) { + if (++i == args.length) { + usageError = arg; + break goodUsage; + } + int opt; + try { + opt = Integer.parseInt(args[i]); + } catch (NumberFormatException ex) { + usageError = args[i]; + break goodUsage; + } + if (opt == -2) { + // Compatibility with Cocoon Rhino fork + opt = -1; + } else if (!Context.isValidOptimizationLevel(opt)) { + usageError = args[i]; + break goodUsage; + } + shellContextFactory.setOptimizationLevel(opt); + continue; + } + if (arg.equals("-strict")) { + shellContextFactory.setStrictMode(true); + errorReporter.setIsReportingWarnings(true); + continue; + } + if (arg.equals("-fatal-warnings")) { + shellContextFactory.setWarningAsError(true); + continue; + } + if (arg.equals("-e")) { + processStdin = false; + if (++i == args.length) { + usageError = arg; + break goodUsage; + } + if (!global.initialized) { + global.init(shellContextFactory); + } + IProxy iproxy = new IProxy(IProxy.EVAL_INLINE_SCRIPT); + iproxy.scriptText = args[i]; + shellContextFactory.call(iproxy); + continue; + } + if (arg.equals("-w")) { + errorReporter.setIsReportingWarnings(true); + continue; + } + if (arg.equals("-f")) { + processStdin = false; + if (++i == args.length) { + usageError = arg; + break goodUsage; + } + fileList.addElement(args[i].equals("-") ? null : args[i]); + continue; + } + if (arg.equals("-sealedlib")) { + global.setSealedStdLib(true); + continue; + } + if (arg.equals("-debug")) { + shellContextFactory.setGeneratingDebug(true); + continue; + } + if (arg.equals("-?") || + arg.equals("-help")) { + // print usage message + global.getOut().println( + ToolErrorReporter.getMessage("msg.shell.usage", Main.class.getName())); + System.exit(1); + } + usageError = arg; + break goodUsage; + } + // print error and usage message + global.getOut().println( + ToolErrorReporter.getMessage("msg.shell.invalid", usageError)); + global.getOut().println( + ToolErrorReporter.getMessage("msg.shell.usage", Main.class.getName())); + System.exit(1); + return null; + } + + private static void initJavaPolicySecuritySupport() + { + Throwable exObj; + try { + Class cl = Class.forName + ("org.mozilla.javascript.tools.shell.JavaPolicySecurity"); + securityImpl = (SecurityProxy)cl.newInstance(); + SecurityController.initGlobal(securityImpl); + return; + } catch (ClassNotFoundException ex) { + exObj = ex; + } catch (IllegalAccessException ex) { + exObj = ex; + } catch (InstantiationException ex) { + exObj = ex; + } catch (LinkageError ex) { + exObj = ex; + } + throw Kit.initCause(new IllegalStateException( + "Can not load security support: "+exObj), exObj); + } + + /** + * Evaluate JavaScript source. + * + * @param cx the current context + * @param filename the name of the file to compile, or null + * for interactive mode. + */ + public static void processSource(Context cx, String filename) + { + if (filename == null || filename.equals("-")) { + PrintStream ps = global.getErr(); + if (filename == null) { + // print implementation version + ps.println(cx.getImplementationVersion()); + } + + // Use the interpreter for interactive input + cx.setOptimizationLevel(-1); + + BufferedReader in = new BufferedReader + (new InputStreamReader(global.getIn())); + int lineno = 1; + boolean hitEOF = false; + while (!hitEOF) { + String[] prompts = global.getPrompts(cx); + if (filename == null) + ps.print(prompts[0]); + ps.flush(); + String source = ""; + + // Collect lines of source to compile. + while (true) { + String newline; + try { + newline = in.readLine(); + } + catch (IOException ioe) { + ps.println(ioe.toString()); + break; + } + if (newline == null) { + hitEOF = true; + break; + } + source = source + newline + "\n"; + lineno++; + if (cx.stringIsCompilableUnit(source)) + break; + ps.print(prompts[1]); + } + Script script = loadScriptFromSource(cx, source, "", + lineno, null); + if (script != null) { + Object result = evaluateScript(script, cx, global); + // Avoid printing out undefined or function definitions. + if (result != Context.getUndefinedValue() && + !(result instanceof Function && + source.trim().startsWith("function"))) + { + try { + ps.println(Context.toString(result)); + } catch (RhinoException rex) { + ToolErrorReporter.reportException( + cx.getErrorReporter(), rex); + } + } + NativeArray h = global.history; + h.put((int)h.getLength(), h, source); + } + } + ps.println(); + } else { + processFile(cx, global, filename); + } + System.gc(); + } + + public static void processFile(Context cx, Scriptable scope, + String filename) + { + if (securityImpl == null) { + processFileSecure(cx, scope, filename, null); + } else { + securityImpl.callProcessFileSecure(cx, scope, filename); + } + } + + static void processFileSecure(Context cx, Scriptable scope, + String path, Object securityDomain) + { + Script script; + if (path.endsWith(".class")) { + script = loadCompiledScript(cx, path, securityDomain); + } else { + String source = (String)readFileOrUrl(path, true); + if (source == null) { + exitCode = EXITCODE_FILE_NOT_FOUND; + return; + } + + // Support the executable script #! syntax: If + // the first line begins with a '#', treat the whole + // line as a comment. + if (source.length() > 0 && source.charAt(0) == '#') { + for (int i = 1; i != source.length(); ++i) { + int c = source.charAt(i); + if (c == '\n' || c == '\r') { + source = source.substring(i); + break; + } + } + } + script = loadScriptFromSource(cx, source, path, 1, securityDomain); + } + if (script != null) { + evaluateScript(script, cx, scope); + } + } + + public static Script loadScriptFromSource(Context cx, String scriptSource, + String path, int lineno, + Object securityDomain) + { + try { + return cx.compileString(scriptSource, path, lineno, + securityDomain); + } catch (EvaluatorException ee) { + // Already printed message. + exitCode = EXITCODE_RUNTIME_ERROR; + } catch (RhinoException rex) { + ToolErrorReporter.reportException( + cx.getErrorReporter(), rex); + exitCode = EXITCODE_RUNTIME_ERROR; + } catch (VirtualMachineError ex) { + // Treat StackOverflow and OutOfMemory as runtime errors + ex.printStackTrace(); + String msg = ToolErrorReporter.getMessage( + "msg.uncaughtJSException", ex.toString()); + exitCode = EXITCODE_RUNTIME_ERROR; + Context.reportError(msg); + } + return null; + } + + private static Script loadCompiledScript(Context cx, String path, + Object securityDomain) + { + byte[] data = (byte[])readFileOrUrl(path, false); + if (data == null) { + exitCode = EXITCODE_FILE_NOT_FOUND; + return null; + } + // XXX: For now extract class name of compiled Script from path + // instead of parsing class bytes + int nameStart = path.lastIndexOf('/'); + if (nameStart < 0) { + nameStart = 0; + } else { + ++nameStart; + } + int nameEnd = path.lastIndexOf('.'); + if (nameEnd < nameStart) { + // '.' does not exist in path (nameEnd < 0) + // or it comes before nameStart + nameEnd = path.length(); + } + String name = path.substring(nameStart, nameEnd); + try { + GeneratedClassLoader loader = SecurityController.createLoader(cx.getApplicationClassLoader(), securityDomain); + Class clazz = loader.defineClass(name, data); + loader.linkClass(clazz); + if (!Script.class.isAssignableFrom(clazz)) { + throw Context.reportRuntimeError("msg.must.implement.Script"); + } + return (Script) clazz.newInstance(); + } catch (RhinoException rex) { + ToolErrorReporter.reportException( + cx.getErrorReporter(), rex); + exitCode = EXITCODE_RUNTIME_ERROR; + } catch (IllegalAccessException iaex) { + exitCode = EXITCODE_RUNTIME_ERROR; + Context.reportError(iaex.toString()); + } catch (InstantiationException inex) { + exitCode = EXITCODE_RUNTIME_ERROR; + Context.reportError(inex.toString()); + } + return null; + } + + public static Object evaluateScript(Script script, Context cx, + Scriptable scope) + { + try { + return script.exec(cx, scope); + } catch (RhinoException rex) { + ToolErrorReporter.reportException( + cx.getErrorReporter(), rex); + exitCode = EXITCODE_RUNTIME_ERROR; + } catch (VirtualMachineError ex) { + // Treat StackOverflow and OutOfMemory as runtime errors + ex.printStackTrace(); + String msg = ToolErrorReporter.getMessage( + "msg.uncaughtJSException", ex.toString()); + exitCode = EXITCODE_RUNTIME_ERROR; + Context.reportError(msg); + } + return Context.getUndefinedValue(); + } + + public static InputStream getIn() { + return getGlobal().getIn(); + } + + public static void setIn(InputStream in) { + getGlobal().setIn(in); + } + + public static PrintStream getOut() { + return getGlobal().getOut(); + } + + public static void setOut(PrintStream out) { + getGlobal().setOut(out); + } + + public static PrintStream getErr() { + return getGlobal().getErr(); + } + + public static void setErr(PrintStream err) { + getGlobal().setErr(err); + } + + /** + * Read file or url specified by path. + * @return file or url content as byte[] or as String if + * convertToString is true. + */ + private static Object readFileOrUrl(String path, boolean convertToString) + { + URL url = null; + // Assume path is URL if it contains dot and there are at least + // 2 characters in the protocol part. The later allows under Windows + // to interpret paths with driver letter as file, not URL. + if (path.indexOf(':') >= 2) { + try { + url = new URL(path); + } catch (MalformedURLException ex) { + } + } + + InputStream is = null; + int capacityHint = 0; + if (url == null) { + File file = new File(path); + capacityHint = (int)file.length(); + try { + is = new FileInputStream(file); + } catch (IOException ex) { + Context.reportError(ToolErrorReporter.getMessage( + "msg.couldnt.open", path)); + return null; + } + } else { + try { + URLConnection uc = url.openConnection(); + is = uc.getInputStream(); + capacityHint = uc.getContentLength(); + // Ignore insane values for Content-Length + if (capacityHint > (1 << 20)) { + capacityHint = -1; + } + } catch (IOException ex) { + Context.reportError(ToolErrorReporter.getMessage( + "msg.couldnt.open.url", url.toString(), ex.toString())); + return null; + } + } + if (capacityHint <= 0) { + capacityHint = 4096; + } + + byte[] data; + try { + try { + data = Kit.readStream(is, capacityHint); + } finally { + is.close(); + } + } catch (IOException ex) { + Context.reportError(ex.toString()); + return null; + } + + Object result; + if (!convertToString) { + result = data; + } else { + // Convert to String using the default encoding + // XXX: Use 'charset=' argument of Content-Type if URL? + result = new String(data); + } + return result; + } + +} -- cgit v1.2.3