From d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Tue, 8 Jun 2010 08:22:05 +0200 Subject: reverted folder structure change for better mergeing with upstream --- .../javascript/tools/shell/ConsoleTextArea.java | 300 ++++++ .../javascript/tools/shell/Environment.java | 141 +++ .../org/mozilla/javascript/tools/shell/Global.java | 1038 ++++++++++++++++++++ .../mozilla/javascript/tools/shell/JSConsole.java | 225 +++++ .../javascript/tools/shell/JavaPolicySecurity.java | 240 +++++ .../org/mozilla/javascript/tools/shell/Main.java | 638 ++++++++++++ .../mozilla/javascript/tools/shell/QuitAction.java | 50 + .../javascript/tools/shell/SecurityProxy.java | 48 + .../tools/shell/ShellContextFactory.java | 114 +++ 9 files changed, 2794 insertions(+) create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ConsoleTextArea.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Environment.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JSConsole.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JavaPolicySecurity.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/QuitAction.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/SecurityProxy.java create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ShellContextFactory.java (limited to 'trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell') diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ConsoleTextArea.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ConsoleTextArea.java new file mode 100644 index 0000000..08cac62 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ConsoleTextArea.java @@ -0,0 +1,300 @@ +/* -*- 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 JavaScript Debugger code, released + * November 21, 2000. + * + * The Initial Developer of the Original Code is + * See Beyond Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Christopher Oliver + * + * 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.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.Document; +import javax.swing.text.Segment; + +class ConsoleWrite implements Runnable { + private ConsoleTextArea textArea; + private String str; + + public ConsoleWrite(ConsoleTextArea textArea, String str) { + this.textArea = textArea; + this.str = str; + } + + public void run() { + textArea.write(str); + } +} + +class ConsoleWriter extends java.io.OutputStream { + + private ConsoleTextArea textArea; + private StringBuffer buffer; + + public ConsoleWriter(ConsoleTextArea textArea) { + this.textArea = textArea; + buffer = new StringBuffer(); + } + + public synchronized void write(int ch) { + buffer.append((char)ch); + if(ch == '\n') { + flushBuffer(); + } + } + + public synchronized void write (char[] data, int off, int len) { + for(int i = off; i < len; i++) { + buffer.append(data[i]); + if(data[i] == '\n') { + flushBuffer(); + } + } + } + + public synchronized void flush() { + if (buffer.length() > 0) { + flushBuffer(); + } + } + + public void close () { + flush(); + } + + private void flushBuffer() { + String str = buffer.toString(); + buffer.setLength(0); + SwingUtilities.invokeLater(new ConsoleWrite(textArea, str)); + } +} + +public class ConsoleTextArea + extends JTextArea implements KeyListener, DocumentListener +{ + static final long serialVersionUID = 8557083244830872961L; + + private ConsoleWriter console1; + private ConsoleWriter console2; + private PrintStream out; + private PrintStream err; + private PrintWriter inPipe; + private PipedInputStream in; + private java.util.Vector history; + private int historyIndex = -1; + private int outputMark = 0; + + public void select(int start, int end) { + requestFocus(); + super.select(start, end); + } + + public ConsoleTextArea(String[] argv) { + super(); + history = new java.util.Vector(); + console1 = new ConsoleWriter(this); + console2 = new ConsoleWriter(this); + out = new PrintStream(console1); + err = new PrintStream(console2); + PipedOutputStream outPipe = new PipedOutputStream(); + inPipe = new PrintWriter(outPipe); + in = new PipedInputStream(); + try { + outPipe.connect(in); + } catch(IOException exc) { + exc.printStackTrace(); + } + getDocument().addDocumentListener(this); + addKeyListener(this); + setLineWrap(true); + setFont(new Font("Monospaced", 0, 12)); + } + + + synchronized void returnPressed() { + Document doc = getDocument(); + int len = doc.getLength(); + Segment segment = new Segment(); + try { + doc.getText(outputMark, len - outputMark, segment); + } catch(javax.swing.text.BadLocationException ignored) { + ignored.printStackTrace(); + } + if(segment.count > 0) { + history.addElement(segment.toString()); + } + historyIndex = history.size(); + inPipe.write(segment.array, segment.offset, segment.count); + append("\n"); + outputMark = doc.getLength(); + inPipe.write("\n"); + inPipe.flush(); + console1.flush(); + } + + public void eval(String str) { + inPipe.write(str); + inPipe.write("\n"); + inPipe.flush(); + console1.flush(); + } + + public void keyPressed(KeyEvent e) { + int code = e.getKeyCode(); + if(code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT) { + if(outputMark == getCaretPosition()) { + e.consume(); + } + } else if(code == KeyEvent.VK_HOME) { + int caretPos = getCaretPosition(); + if(caretPos == outputMark) { + e.consume(); + } else if(caretPos > outputMark) { + if(!e.isControlDown()) { + if(e.isShiftDown()) { + moveCaretPosition(outputMark); + } else { + setCaretPosition(outputMark); + } + e.consume(); + } + } + } else if(code == KeyEvent.VK_ENTER) { + returnPressed(); + e.consume(); + } else if(code == KeyEvent.VK_UP) { + historyIndex--; + if(historyIndex >= 0) { + if(historyIndex >= history.size()) { + historyIndex = history.size() -1; + } + if(historyIndex >= 0) { + String str = (String)history.elementAt(historyIndex); + int len = getDocument().getLength(); + replaceRange(str, outputMark, len); + int caretPos = outputMark + str.length(); + select(caretPos, caretPos); + } else { + historyIndex++; + } + } else { + historyIndex++; + } + e.consume(); + } else if(code == KeyEvent.VK_DOWN) { + int caretPos = outputMark; + if(history.size() > 0) { + historyIndex++; + if(historyIndex < 0) {historyIndex = 0;} + int len = getDocument().getLength(); + if(historyIndex < history.size()) { + String str = (String)history.elementAt(historyIndex); + replaceRange(str, outputMark, len); + caretPos = outputMark + str.length(); + } else { + historyIndex = history.size(); + replaceRange("", outputMark, len); + } + } + select(caretPos, caretPos); + e.consume(); + } + } + + public void keyTyped(KeyEvent e) { + int keyChar = e.getKeyChar(); + if(keyChar == 0x8 /* KeyEvent.VK_BACK_SPACE */) { + if(outputMark == getCaretPosition()) { + e.consume(); + } + } else if(getCaretPosition() < outputMark) { + setCaretPosition(outputMark); + } + } + + public synchronized void keyReleased(KeyEvent e) { + } + + public synchronized void write(String str) { + insert(str, outputMark); + int len = str.length(); + outputMark += len; + select(outputMark, outputMark); + } + + public synchronized void insertUpdate(DocumentEvent e) { + int len = e.getLength(); + int off = e.getOffset(); + if(outputMark > off) { + outputMark += len; + } + } + + public synchronized void removeUpdate(DocumentEvent e) { + int len = e.getLength(); + int off = e.getOffset(); + if(outputMark > off) { + if(outputMark >= off + len) { + outputMark -= len; + } else { + outputMark = off; + } + } + } + + public synchronized void postUpdateUI() { + // this attempts to cleanup the damage done by updateComponentTreeUI + requestFocus(); + setCaret(getCaret()); + select(outputMark, outputMark); + } + + public synchronized void changedUpdate(DocumentEvent e) { + } + + + public InputStream getIn() { + return in; + } + + public PrintStream getOut() { + return out; + } + + public PrintStream getErr() { + return err; + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Environment.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Environment.java new file mode 100644 index 0000000..19904b9 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Environment.java @@ -0,0 +1,141 @@ +/* -*- 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): + * + * 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 ***** */ + +/* + Environment.java + + Wraps java.lang.System properties. + + by Patrick C. Beard + */ + +package org.mozilla.javascript.tools.shell; + +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.ScriptableObject; + +import java.util.Vector; +import java.util.Enumeration; +import java.util.Properties; + +/** + * Environment, intended to be instantiated at global scope, provides + * a natural way to access System properties from JavaScript. + * + * @author Patrick C. Beard + */ +public class Environment extends ScriptableObject +{ + static final long serialVersionUID = -430727378460177065L; + + private Environment thePrototypeInstance = null; + + public static void defineClass(ScriptableObject scope) { + try { + ScriptableObject.defineClass(scope, Environment.class); + } catch (Exception e) { + throw new Error(e.getMessage()); + } + } + + public String getClassName() { + return "Environment"; + } + + public Environment() { + if (thePrototypeInstance == null) + thePrototypeInstance = this; + } + + public Environment(ScriptableObject scope) { + setParentScope(scope); + Object ctor = ScriptRuntime.getTopLevelProp(scope, "Environment"); + if (ctor != null && ctor instanceof Scriptable) { + Scriptable s = (Scriptable) ctor; + setPrototype((Scriptable) s.get("prototype", s)); + } + } + + public boolean has(String name, Scriptable start) { + if (this == thePrototypeInstance) + return super.has(name, start); + + return (System.getProperty(name) != null); + } + + public Object get(String name, Scriptable start) { + if (this == thePrototypeInstance) + return super.get(name, start); + + String result = System.getProperty(name); + if (result != null) + return ScriptRuntime.toObject(getParentScope(), result); + else + return Scriptable.NOT_FOUND; + } + + public void put(String name, Scriptable start, Object value) { + if (this == thePrototypeInstance) + super.put(name, start, value); + else + System.getProperties().put(name, ScriptRuntime.toString(value)); + } + + private Object[] collectIds() { + Properties props = System.getProperties(); + Enumeration names = props.propertyNames(); + Vector keys = new Vector(); + while (names.hasMoreElements()) + keys.addElement(names.nextElement()); + Object[] ids = new Object[keys.size()]; + keys.copyInto(ids); + return ids; + } + + public Object[] getIds() { + if (this == thePrototypeInstance) + return super.getIds(); + return collectIds(); + } + + public Object[] getAllIds() { + if (this == thePrototypeInstance) + return super.getAllIds(); + return collectIds(); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java new file mode 100644 index 0000000..fdb8f4e --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java @@ -0,0 +1,1038 @@ +/* -*- 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 + * Igor Bukanov + * Norris Boyd + * Rob Ginda + * Kurt Westerfeld + * Matthias Radestock + * + * 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.*; +import java.lang.reflect.*; +import org.mozilla.javascript.*; +import org.mozilla.javascript.tools.ToolErrorReporter; +import org.mozilla.javascript.serialize.*; + +/** + * This class provides for sharing functions across multiple threads. + * This is of particular interest to server applications. + * + * @author Norris Boyd + */ +public class Global extends ImporterTopLevel +{ + static final long serialVersionUID = 4029130780977538005L; + + NativeArray history; + private InputStream inStream; + private PrintStream outStream; + private PrintStream errStream; + private boolean sealedStdLib = false; + boolean initialized; + private QuitAction quitAction; + private String[] prompts = { "js> ", " > " }; + + public Global() + { + } + + public Global(Context cx) + { + init(cx); + } + + public boolean isInitialized() { + return initialized; + } + + /** + * Set the action to call from quit(). + */ + public void initQuitAction(QuitAction quitAction) + { + if (quitAction == null) + throw new IllegalArgumentException("quitAction is null"); + if (this.quitAction != null) + throw new IllegalArgumentException("The method is once-call."); + + this.quitAction = quitAction; + } + + public void init(ContextFactory factory) + { + factory.call(new ContextAction() { + public Object run(Context cx) + { + init(cx); + return null; + } + }); + } + + public void init(Context cx) + { + // Define some global functions particular to the shell. Note + // that these functions are not part of ECMA. + initStandardObjects(cx, sealedStdLib); + String[] names = { + "defineClass", + "deserialize", + "gc", + "help", + "load", + "loadClass", + "print", + "quit", + "readFile", + "readUrl", + "runCommand", + "seal", + "serialize", + "spawn", + "sync", + "toint32", + "version", + }; + defineFunctionProperties(names, Global.class, + ScriptableObject.DONTENUM); + + // Set up "environment" in the global scope to provide access to the + // System environment variables. + Environment.defineClass(this); + Environment environment = new Environment(this); + defineProperty("environment", environment, + ScriptableObject.DONTENUM); + + history = (NativeArray) cx.newArray(this, 0); + defineProperty("history", history, ScriptableObject.DONTENUM); + initialized = true; + } + + /** + * Print a help message. + * + * This method is defined as a JavaScript function. + */ + public static void help(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + PrintStream out = getInstance(funObj).getOut(); + out.println(ToolErrorReporter.getMessage("msg.help")); + } + + public static void gc(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + System.gc(); + } + + + /** + * Print the string values of its arguments. + * + * This method is defined as a JavaScript function. + * Note that its arguments are of the "varargs" form, which + * allows it to handle an arbitrary number of arguments + * supplied to the JavaScript function. + * + */ + public static Object print(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + PrintStream out = getInstance(funObj).getOut(); + for (int i=0; i < args.length; i++) { + if (i > 0) + out.print(" "); + + // Convert the arbitrary JavaScript value into a string form. + String s = Context.toString(args[i]); + + out.print(s); + } + out.println(); + return Context.getUndefinedValue(); + } + + /** + * Call embedding-specific quit action passing its argument as + * int32 exit code. + * + * This method is defined as a JavaScript function. + */ + public static void quit(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + Global global = getInstance(funObj); + if (global.quitAction != null) { + int exitCode = (args.length == 0 ? 0 + : ScriptRuntime.toInt32(args[0])); + global.quitAction.quit(cx, exitCode); + } + } + + /** + * Get and set the language version. + * + * This method is defined as a JavaScript function. + */ + public static double version(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + double result = cx.getLanguageVersion(); + if (args.length > 0) { + double d = Context.toNumber(args[0]); + cx.setLanguageVersion((int) d); + } + return result; + } + + /** + * Load and execute a set of JavaScript source files. + * + * This method is defined as a JavaScript function. + * + */ + public static void load(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + { + for (int i = 0; i < args.length; i++) { + Main.processFile(cx, thisObj, Context.toString(args[i])); + } + } + + /** + * Load a Java class that defines a JavaScript object using the + * conventions outlined in ScriptableObject.defineClass. + *

+ * This method is defined as a JavaScript function. + * @exception IllegalAccessException if access is not available + * to a reflected class member + * @exception InstantiationException if unable to instantiate + * the named class + * @exception InvocationTargetException if an exception is thrown + * during execution of methods of the named class + * @see org.mozilla.javascript.ScriptableObject#defineClass(Scriptable,Class) + */ + public static void defineClass(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + throws IllegalAccessException, InstantiationException, + InvocationTargetException + { + Class clazz = getClass(args); + ScriptableObject.defineClass(thisObj, clazz); + } + + /** + * Load and execute a script compiled to a class file. + *

+ * This method is defined as a JavaScript function. + * When called as a JavaScript function, a single argument is + * expected. This argument should be the name of a class that + * implements the Script interface, as will any script + * compiled by jsc. + * + * @exception IllegalAccessException if access is not available + * to the class + * @exception InstantiationException if unable to instantiate + * the named class + */ + public static void loadClass(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + throws IllegalAccessException, InstantiationException + { + Class clazz = getClass(args); + if (!Script.class.isAssignableFrom(clazz)) { + throw reportRuntimeError("msg.must.implement.Script"); + } + Script script = (Script) clazz.newInstance(); + script.exec(cx, thisObj); + } + + private static Class getClass(Object[] args) { + if (args.length == 0) { + throw reportRuntimeError("msg.expected.string.arg"); + } + Object arg0 = args[0]; + if (arg0 instanceof Wrapper) { + Object wrapped = ((Wrapper)arg0).unwrap(); + if (wrapped instanceof Class) + return (Class)wrapped; + } + String className = Context.toString(args[0]); + try { + return Class.forName(className); + } + catch (ClassNotFoundException cnfe) { + throw reportRuntimeError("msg.class.not.found", className); + } + } + + public static void serialize(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + throws IOException + { + if (args.length < 2) { + throw Context.reportRuntimeError( + "Expected an object to serialize and a filename to write " + + "the serialization to"); + } + Object obj = args[0]; + String filename = Context.toString(args[1]); + FileOutputStream fos = new FileOutputStream(filename); + Scriptable scope = ScriptableObject.getTopLevelScope(thisObj); + ScriptableOutputStream out = new ScriptableOutputStream(fos, scope); + out.writeObject(obj); + out.close(); + } + + public static Object deserialize(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + throws IOException, ClassNotFoundException + { + if (args.length < 1) { + throw Context.reportRuntimeError( + "Expected a filename to read the serialization from"); + } + String filename = Context.toString(args[0]); + FileInputStream fis = new FileInputStream(filename); + Scriptable scope = ScriptableObject.getTopLevelScope(thisObj); + ObjectInputStream in = new ScriptableInputStream(fis, scope); + Object deserialized = in.readObject(); + in.close(); + return Context.toObject(deserialized, scope); + } + + public String[] getPrompts(Context cx) { + if (ScriptableObject.hasProperty(this, "prompts")) { + Object promptsJS = ScriptableObject.getProperty(this, + "prompts"); + if (promptsJS instanceof Scriptable) { + Scriptable s = (Scriptable) promptsJS; + if (ScriptableObject.hasProperty(s, 0) && + ScriptableObject.hasProperty(s, 1)) + { + Object elem0 = ScriptableObject.getProperty(s, 0); + if (elem0 instanceof Function) { + elem0 = ((Function) elem0).call(cx, this, s, + new Object[0]); + } + prompts[0] = Context.toString(elem0); + Object elem1 = ScriptableObject.getProperty(s, 1); + if (elem1 instanceof Function) { + elem1 = ((Function) elem1).call(cx, this, s, + new Object[0]); + } + prompts[1] = Context.toString(elem1); + } + } + } + return prompts; + } + + /** + * The spawn function runs a given function or script in a different + * thread. + * + * js> function g() { a = 7; } + * js> a = 3; + * 3 + * js> spawn(g) + * Thread[Thread-1,5,main] + * js> a + * 3 + */ + public static Object spawn(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + { + Scriptable scope = funObj.getParentScope(); + Runner runner; + if (args.length != 0 && args[0] instanceof Function) { + Object[] newArgs = null; + if (args.length > 1 && args[1] instanceof Scriptable) { + newArgs = cx.getElements((Scriptable) args[1]); + } + if (newArgs == null) { newArgs = ScriptRuntime.emptyArgs; } + runner = new Runner(scope, (Function) args[0], newArgs); + } else if (args.length != 0 && args[0] instanceof Script) { + runner = new Runner(scope, (Script) args[0]); + } else { + throw reportRuntimeError("msg.spawn.args"); + } + runner.factory = cx.getFactory(); + Thread thread = new Thread(runner); + thread.start(); + return thread; + } + + /** + * The sync function creates a synchronized function (in the sense + * of a Java synchronized method) from an existing function. The + * new function synchronizes on the this object of + * its invocation. + * js> var o = { f : sync(function(x) { + * print("entry"); + * Packages.java.lang.Thread.sleep(x*1000); + * print("exit"); + * })}; + * js> spawn(function() {o.f(5);}); + * Thread[Thread-0,5,main] + * entry + * js> spawn(function() {o.f(5);}); + * Thread[Thread-1,5,main] + * js> + * exit + * entry + * exit + */ + public static Object sync(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + { + if (args.length == 1 && args[0] instanceof Function) { + return new Synchronizer((Function)args[0]); + } + else { + throw reportRuntimeError("msg.sync.args"); + } + } + + /** + * Execute the specified command with the given argument and options + * as a separate process and return the exit status of the process. + *

+ * Usage: + *

+     * runCommand(command)
+     * runCommand(command, arg1, ..., argN)
+     * runCommand(command, arg1, ..., argN, options)
+     * 
+ * All except the last arguments to runCommand are converted to strings + * and denote command name and its arguments. If the last argument is a + * JavaScript object, it is an option object. Otherwise it is converted to + * string denoting the last argument and options objects assumed to be + * empty. + * Te following properties of the option object are processed: + * + */ + public static Object runCommand(Context cx, Scriptable thisObj, + Object[] args, Function funObj) + throws IOException + { + int L = args.length; + if (L == 0 || (L == 1 && args[0] instanceof Scriptable)) { + throw reportRuntimeError("msg.runCommand.bad.args"); + } + + InputStream in = null; + OutputStream out = null, err = null; + ByteArrayOutputStream outBytes = null, errBytes = null; + Object outObj = null, errObj = null; + String[] environment = null; + Scriptable params = null; + Object[] addArgs = null; + if (args[L - 1] instanceof Scriptable) { + params = (Scriptable)args[L - 1]; + --L; + Object envObj = ScriptableObject.getProperty(params, "env"); + if (envObj != Scriptable.NOT_FOUND) { + if (envObj == null) { + environment = new String[0]; + } else { + if (!(envObj instanceof Scriptable)) { + throw reportRuntimeError("msg.runCommand.bad.env"); + } + Scriptable envHash = (Scriptable)envObj; + Object[] ids = ScriptableObject.getPropertyIds(envHash); + environment = new String[ids.length]; + for (int i = 0; i != ids.length; ++i) { + Object keyObj = ids[i], val; + String key; + if (keyObj instanceof String) { + key = (String)keyObj; + val = ScriptableObject.getProperty(envHash, key); + } else { + int ikey = ((Number)keyObj).intValue(); + key = Integer.toString(ikey); + val = ScriptableObject.getProperty(envHash, ikey); + } + if (val == ScriptableObject.NOT_FOUND) { + val = Undefined.instance; + } + environment[i] = key+'='+ScriptRuntime.toString(val); + } + } + } + Object inObj = ScriptableObject.getProperty(params, "input"); + if (inObj != Scriptable.NOT_FOUND) { + in = toInputStream(inObj); + } + outObj = ScriptableObject.getProperty(params, "output"); + if (outObj != Scriptable.NOT_FOUND) { + out = toOutputStream(outObj); + if (out == null) { + outBytes = new ByteArrayOutputStream(); + out = outBytes; + } + } + errObj = ScriptableObject.getProperty(params, "err"); + if (errObj != Scriptable.NOT_FOUND) { + err = toOutputStream(errObj); + if (err == null) { + errBytes = new ByteArrayOutputStream(); + err = errBytes; + } + } + Object addArgsObj = ScriptableObject.getProperty(params, "args"); + if (addArgsObj != Scriptable.NOT_FOUND) { + Scriptable s = Context.toObject(addArgsObj, + getTopLevelScope(thisObj)); + addArgs = cx.getElements(s); + } + } + Global global = getInstance(funObj); + if (out == null) { + out = (global != null) ? global.getOut() : System.out; + } + if (err == null) { + err = (global != null) ? global.getErr() : System.err; + } + // If no explicit input stream, do not send any input to process, + // in particular, do not use System.in to avoid deadlocks + // when waiting for user input to send to process which is already + // terminated as it is not always possible to interrupt read method. + + String[] cmd = new String[(addArgs == null) ? L : L + addArgs.length]; + for (int i = 0; i != L; ++i) { + cmd[i] = ScriptRuntime.toString(args[i]); + } + if (addArgs != null) { + for (int i = 0; i != addArgs.length; ++i) { + cmd[L + i] = ScriptRuntime.toString(addArgs[i]); + } + } + + int exitCode = runProcess(cmd, environment, in, out, err); + if (outBytes != null) { + String s = ScriptRuntime.toString(outObj) + outBytes.toString(); + ScriptableObject.putProperty(params, "output", s); + } + if (errBytes != null) { + String s = ScriptRuntime.toString(errObj) + errBytes.toString(); + ScriptableObject.putProperty(params, "err", s); + } + + return new Integer(exitCode); + } + + /** + * The seal function seals all supplied arguments. + */ + public static void seal(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + { + for (int i = 0; i != args.length; ++i) { + Object arg = args[i]; + if (!(arg instanceof ScriptableObject) || arg == Undefined.instance) + { + if (!(arg instanceof Scriptable) || arg == Undefined.instance) + { + throw reportRuntimeError("msg.shell.seal.not.object"); + } else { + throw reportRuntimeError("msg.shell.seal.not.scriptable"); + } + } + } + + for (int i = 0; i != args.length; ++i) { + Object arg = args[i]; + ((ScriptableObject)arg).sealObject(); + } + } + + /** + * The readFile reads the given file content and convert it to a string + * using the specified character coding or default character coding if + * explicit coding argument is not given. + *

+ * Usage: + *

+     * readFile(filePath)
+     * readFile(filePath, charCoding)
+     * 
+ * The first form converts file's context to string using the default + * character coding. + */ + public static Object readFile(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + throws IOException + { + if (args.length == 0) { + throw reportRuntimeError("msg.shell.readFile.bad.args"); + } + String path = ScriptRuntime.toString(args[0]); + String charCoding = null; + if (args.length >= 2) { + charCoding = ScriptRuntime.toString(args[1]); + } + + return readUrl(path, charCoding, true); + } + + /** + * The readUrl opens connection to the given URL, read all its data + * and converts them to a string + * using the specified character coding or default character coding if + * explicit coding argument is not given. + *

+ * Usage: + *

+     * readUrl(url)
+     * readUrl(url, charCoding)
+     * 
+ * The first form converts file's context to string using the default + * charCoding. + */ + public static Object readUrl(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + throws IOException + { + if (args.length == 0) { + throw reportRuntimeError("msg.shell.readUrl.bad.args"); + } + String url = ScriptRuntime.toString(args[0]); + String charCoding = null; + if (args.length >= 2) { + charCoding = ScriptRuntime.toString(args[1]); + } + + return readUrl(url, charCoding, false); + } + + /** + * Convert the argumnet to int32 number. + */ + public static Object toint32(Context cx, Scriptable thisObj, Object[] args, + Function funObj) + { + Object arg = (args.length != 0 ? args[0] : Undefined.instance); + if (arg instanceof Integer) + return arg; + return ScriptRuntime.wrapInt(ScriptRuntime.toInt32(arg)); + } + + public InputStream getIn() { + return inStream == null ? System.in : inStream; + } + + public void setIn(InputStream in) { + inStream = in; + } + + public PrintStream getOut() { + return outStream == null ? System.out : outStream; + } + + public void setOut(PrintStream out) { + outStream = out; + } + + public PrintStream getErr() { + return errStream == null ? System.err : errStream; + } + + public void setErr(PrintStream err) { + errStream = err; + } + + public void setSealedStdLib(boolean value) + { + sealedStdLib = value; + } + + private static Global getInstance(Function function) + { + Scriptable scope = function.getParentScope(); + if (!(scope instanceof Global)) + throw reportRuntimeError("msg.bad.shell.function.scope", + String.valueOf(scope)); + return (Global)scope; + } + + /** + * Runs the given process using Runtime.exec(). + * If any of in, out, err is null, the corresponding process stream will + * be closed immediately, otherwise it will be closed as soon as + * all data will be read from/written to process + * + * @return Exit value of process. + * @throws IOException If there was an error executing the process. + */ + private static int runProcess(String[] cmd, String[] environment, + InputStream in, OutputStream out, + OutputStream err) + throws IOException + { + Process p; + if (environment == null) { + p = Runtime.getRuntime().exec(cmd); + } else { + p = Runtime.getRuntime().exec(cmd, environment); + } + + try { + PipeThread inThread = null; + if (in != null) { + inThread = new PipeThread(false, in, p.getOutputStream()); + inThread.start(); + } else { + p.getOutputStream().close(); + } + + PipeThread outThread = null; + if (out != null) { + outThread = new PipeThread(true, p.getInputStream(), out); + outThread.start(); + } else { + p.getInputStream().close(); + } + + PipeThread errThread = null; + if (err != null) { + errThread = new PipeThread(true, p.getErrorStream(), err); + errThread.start(); + } else { + p.getErrorStream().close(); + } + + // wait for process completion + for (;;) { + try { + p.waitFor(); + if (outThread != null) { + outThread.join(); + } + if (inThread != null) { + inThread.join(); + } + if (errThread != null) { + errThread.join(); + } + break; + } catch (InterruptedException ignore) { + } + } + + return p.exitValue(); + } finally { + p.destroy(); + } + } + + static void pipe(boolean fromProcess, InputStream from, OutputStream to) + throws IOException + { + try { + final int SIZE = 4096; + byte[] buffer = new byte[SIZE]; + for (;;) { + int n; + if (!fromProcess) { + n = from.read(buffer, 0, SIZE); + } else { + try { + n = from.read(buffer, 0, SIZE); + } catch (IOException ex) { + // Ignore exception as it can be cause by closed pipe + break; + } + } + if (n < 0) { break; } + if (fromProcess) { + to.write(buffer, 0, n); + to.flush(); + } else { + try { + to.write(buffer, 0, n); + to.flush(); + } catch (IOException ex) { + // Ignore exception as it can be cause by closed pipe + break; + } + } + } + } finally { + try { + if (fromProcess) { + from.close(); + } else { + to.close(); + } + } catch (IOException ex) { + // Ignore errors on close. On Windows JVM may throw invalid + // refrence exception if process terminates too fast. + } + } + } + + private static InputStream toInputStream(Object value) + throws IOException + { + InputStream is = null; + String s = null; + if (value instanceof Wrapper) { + Object unwrapped = ((Wrapper)value).unwrap(); + if (unwrapped instanceof InputStream) { + is = (InputStream)unwrapped; + } else if (unwrapped instanceof byte[]) { + is = new ByteArrayInputStream((byte[])unwrapped); + } else if (unwrapped instanceof Reader) { + s = readReader((Reader)unwrapped); + } else if (unwrapped instanceof char[]) { + s = new String((char[])unwrapped); + } + } + if (is == null) { + if (s == null) { s = ScriptRuntime.toString(value); } + is = new ByteArrayInputStream(s.getBytes()); + } + return is; + } + + private static OutputStream toOutputStream(Object value) { + OutputStream os = null; + if (value instanceof Wrapper) { + Object unwrapped = ((Wrapper)value).unwrap(); + if (unwrapped instanceof OutputStream) { + os = (OutputStream)unwrapped; + } + } + return os; + } + + private static String readUrl(String filePath, String charCoding, + boolean urlIsFile) + throws IOException + { + int chunkLength; + InputStream is = null; + try { + if (!urlIsFile) { + URL urlObj = new URL(filePath); + URLConnection uc = urlObj.openConnection(); + is = uc.getInputStream(); + chunkLength = uc.getContentLength(); + if (chunkLength <= 0) + chunkLength = 1024; + if (charCoding == null) { + String type = uc.getContentType(); + if (type != null) { + charCoding = getCharCodingFromType(type); + } + } + } else { + File f = new File(filePath); + + long length = f.length(); + chunkLength = (int)length; + if (chunkLength != length) + throw new IOException("Too big file size: "+length); + + if (chunkLength == 0) { return ""; } + + is = new FileInputStream(f); + } + + Reader r; + if (charCoding == null) { + r = new InputStreamReader(is); + } else { + r = new InputStreamReader(is, charCoding); + } + return readReader(r, chunkLength); + + } finally { + if (is != null) + is.close(); + } + } + + private static String getCharCodingFromType(String type) + { + int i = type.indexOf(';'); + if (i >= 0) { + int end = type.length(); + ++i; + while (i != end && type.charAt(i) <= ' ') { + ++i; + } + String charset = "charset"; + if (charset.regionMatches(true, 0, type, i, charset.length())) + { + i += charset.length(); + while (i != end && type.charAt(i) <= ' ') { + ++i; + } + if (i != end && type.charAt(i) == '=') { + ++i; + while (i != end && type.charAt(i) <= ' ') { + ++i; + } + if (i != end) { + // i is at the start of non-empty + // charCoding spec + while (type.charAt(end -1) <= ' ') { + --end; + } + return type.substring(i, end); + } + } + } + } + return null; + } + + private static String readReader(Reader reader) + throws IOException + { + return readReader(reader, 4096); + } + + private static String readReader(Reader reader, int initialBufferSize) + throws IOException + { + char[] buffer = new char[initialBufferSize]; + int offset = 0; + for (;;) { + int n = reader.read(buffer, offset, buffer.length - offset); + if (n < 0) { break; } + offset += n; + if (offset == buffer.length) { + char[] tmp = new char[buffer.length * 2]; + System.arraycopy(buffer, 0, tmp, 0, offset); + buffer = tmp; + } + } + return new String(buffer, 0, offset); + } + + static RuntimeException reportRuntimeError(String msgId) { + String message = ToolErrorReporter.getMessage(msgId); + return Context.reportRuntimeError(message); + } + + static RuntimeException reportRuntimeError(String msgId, String msgArg) + { + String message = ToolErrorReporter.getMessage(msgId, msgArg); + return Context.reportRuntimeError(message); + } +} + + +class Runner implements Runnable, ContextAction { + + Runner(Scriptable scope, Function func, Object[] args) { + this.scope = scope; + f = func; + this.args = args; + } + + Runner(Scriptable scope, Script script) { + this.scope = scope; + s = script; + } + + public void run() + { + factory.call(this); + } + + public Object run(Context cx) + { + if (f != null) + return f.call(cx, scope, scope, args); + else + return s.exec(cx, scope); + } + + ContextFactory factory; + private Scriptable scope; + private Function f; + private Script s; + private Object[] args; +} + +class PipeThread extends Thread { + + PipeThread(boolean fromProcess, InputStream from, OutputStream to) { + setDaemon(true); + this.fromProcess = fromProcess; + this.from = from; + this.to = to; + } + + public void run() { + try { + Global.pipe(fromProcess, from, to); + } catch (IOException ex) { + throw Context.throwAsScriptRuntimeEx(ex); + } + } + + private boolean fromProcess; + private InputStream from; + private OutputStream to; +} + diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JSConsole.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JSConsole.java new file mode 100644 index 0000000..f6fe3a1 --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JSConsole.java @@ -0,0 +1,225 @@ +/* -*- 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 JavaScript Debugger code, released + * November 21, 2000. + * + * The Initial Developer of the Original Code is + * See Beyond Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Christopher Oliver + * + * 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.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; + +import javax.swing.ButtonGroup; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import org.mozilla.javascript.SecurityUtilities; + +public class JSConsole extends JFrame implements ActionListener +{ + static final long serialVersionUID = 2551225560631876300L; + + private File CWD; + private JFileChooser dlg; + private ConsoleTextArea consoleTextArea; + + public String chooseFile() { + if(CWD == null) { + String dir = SecurityUtilities.getSystemProperty("user.dir"); + if(dir != null) { + CWD = new File(dir); + } + } + if(CWD != null) { + dlg.setCurrentDirectory(CWD); + } + dlg.setDialogTitle("Select a file to load"); + int returnVal = dlg.showOpenDialog(this); + if(returnVal == JFileChooser.APPROVE_OPTION) { + String result = dlg.getSelectedFile().getPath(); + CWD = new File(dlg.getSelectedFile().getParent()); + return result; + } + return null; + } + + public static void main(String args[]) { + new JSConsole(args); + } + + public void createFileChooser() { + dlg = new JFileChooser(); + javax.swing.filechooser.FileFilter filter = + new javax.swing.filechooser.FileFilter() { + public boolean accept(File f) { + if(f.isDirectory()) { + return true; + } + String name = f.getName(); + int i = name.lastIndexOf('.'); + if(i > 0 && i < name.length() -1) { + String ext = name.substring(i + 1).toLowerCase(); + if(ext.equals("js")) { + return true; + } + } + return false; + } + + public String getDescription() { + return "JavaScript Files (*.js)"; + } + }; + dlg.addChoosableFileFilter(filter); + + } + + public JSConsole(String[] args) { + super("Rhino JavaScript Console"); + JMenuBar menubar = new JMenuBar(); + createFileChooser(); + String[] fileItems = {"Load...", "Exit"}; + String[] fileCmds = {"Load", "Exit"}; + char[] fileShortCuts = {'L', 'X'}; + String[] editItems = {"Cut", "Copy", "Paste"}; + char[] editShortCuts = {'T', 'C', 'P'}; + String[] plafItems = {"Metal", "Windows", "Motif"}; + boolean [] plafState = {true, false, false}; + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('F'); + JMenu editMenu = new JMenu("Edit"); + editMenu.setMnemonic('E'); + JMenu plafMenu = new JMenu("Platform"); + plafMenu.setMnemonic('P'); + for(int i = 0; i < fileItems.length; ++i) { + JMenuItem item = new JMenuItem(fileItems[i], + fileShortCuts[i]); + item.setActionCommand(fileCmds[i]); + item.addActionListener(this); + fileMenu.add(item); + } + for(int i = 0; i < editItems.length; ++i) { + JMenuItem item = new JMenuItem(editItems[i], + editShortCuts[i]); + item.addActionListener(this); + editMenu.add(item); + } + ButtonGroup group = new ButtonGroup(); + for(int i = 0; i < plafItems.length; ++i) { + JRadioButtonMenuItem item = new JRadioButtonMenuItem(plafItems[i], + plafState[i]); + group.add(item); + item.addActionListener(this); + plafMenu.add(item); + } + menubar.add(fileMenu); + menubar.add(editMenu); + menubar.add(plafMenu); + setJMenuBar(menubar); + consoleTextArea = new ConsoleTextArea(args); + JScrollPane scroller = new JScrollPane(consoleTextArea); + setContentPane(scroller); + consoleTextArea.setRows(24); + consoleTextArea.setColumns(80); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + pack(); + setVisible(true); + // System.setIn(consoleTextArea.getIn()); + // System.setOut(consoleTextArea.getOut()); + // System.setErr(consoleTextArea.getErr()); + Main.setIn(consoleTextArea.getIn()); + Main.setOut(consoleTextArea.getOut()); + Main.setErr(consoleTextArea.getErr()); + Main.main(args); + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + String plaf_name = null; + if(cmd.equals("Load")) { + String f = chooseFile(); + if(f != null) { + f = f.replace('\\', '/'); + consoleTextArea.eval("load(\"" + f + "\");"); + } + } else if(cmd.equals("Exit")) { + System.exit(0); + } else if(cmd.equals("Cut")) { + consoleTextArea.cut(); + } else if(cmd.equals("Copy")) { + consoleTextArea.copy(); + } else if(cmd.equals("Paste")) { + consoleTextArea.paste(); + } else { + if(cmd.equals("Metal")) { + plaf_name = "javax.swing.plaf.metal.MetalLookAndFeel"; + } else if(cmd.equals("Windows")) { + plaf_name = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + } else if(cmd.equals("Motif")) { + plaf_name = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + } + if(plaf_name != null) { + try { + UIManager.setLookAndFeel(plaf_name); + SwingUtilities.updateComponentTreeUI(this); + consoleTextArea.postUpdateUI(); + // updateComponentTreeUI seems to mess up the file + // chooser dialog, so just create a new one + createFileChooser(); + } catch(Exception exc) { + JOptionPane.showMessageDialog(this, + exc.getMessage(), + "Platform", + JOptionPane.ERROR_MESSAGE); + } + } + } + + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JavaPolicySecurity.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JavaPolicySecurity.java new file mode 100644 index 0000000..de39a5e --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/JavaPolicySecurity.java @@ -0,0 +1,240 @@ +/* -*- 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, 1999. + * + * 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): + * Igor Bukanov + * + * 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.security.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; + +import org.mozilla.javascript.*; + +public class JavaPolicySecurity extends SecurityProxy +{ + + public Class getStaticSecurityDomainClassInternal() { + return ProtectionDomain.class; + } + + private static class Loader extends ClassLoader + implements GeneratedClassLoader + { + private ProtectionDomain domain; + + Loader(ClassLoader parent, ProtectionDomain domain) { + super(parent != null ? parent : getSystemClassLoader()); + this.domain = domain; + } + + public Class defineClass(String name, byte[] data) { + return super.defineClass(name, data, 0, data.length, domain); + } + + public void linkClass(Class cl) { + resolveClass(cl); + } + } + + private static class ContextPermissions extends PermissionCollection + { + static final long serialVersionUID = -1721494496320750721L; + +// Construct PermissionCollection that permits an action only +// if it is permitted by staticDomain and by security context of Java stack on +// the moment of constructor invocation + ContextPermissions(ProtectionDomain staticDomain) { + _context = AccessController.getContext(); + if (staticDomain != null) { + _statisPermissions = staticDomain.getPermissions(); + } + setReadOnly(); + } + + public void add(Permission permission) { + throw new RuntimeException("NOT IMPLEMENTED"); + } + + public boolean implies(Permission permission) { + if (_statisPermissions != null) { + if (!_statisPermissions.implies(permission)) { + return false; + } + } + try { + _context.checkPermission(permission); + return true; + }catch (AccessControlException ex) { + return false; + } + } + + public Enumeration elements() + { + return new Enumeration() { + public boolean hasMoreElements() { return false; } + public Object nextElement() { return null; } + }; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(getClass().getName()); + sb.append('@'); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(" (context="); + sb.append(_context); + sb.append(", static_permitions="); + sb.append(_statisPermissions); + sb.append(')'); + return sb.toString(); + } + + AccessControlContext _context; + PermissionCollection _statisPermissions; + } + + public JavaPolicySecurity() + { + // To trigger error on jdk-1.1 with lazy load + new CodeSource(null, (java.security.cert.Certificate[])null); + } + + protected void callProcessFileSecure(final Context cx, + final Scriptable scope, + final String filename) + { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + URL url = getUrlObj(filename); + ProtectionDomain staticDomain = getUrlDomain(url); + Main.processFileSecure(cx, scope, url.toExternalForm(), + staticDomain); + return null; + } + }); + } + + private URL getUrlObj(String url) + { + URL urlObj; + try { + urlObj = new URL(url); + } catch (MalformedURLException ex) { + // Assume as Main.processFileSecure it is file, need to build its + // URL + String curDir = System.getProperty("user.dir"); + curDir = curDir.replace('\\', '/'); + if (!curDir.endsWith("/")) { + curDir = curDir+'/'; + } + try { + URL curDirURL = new URL("file:"+curDir); + urlObj = new URL(curDirURL, url); + } catch (MalformedURLException ex2) { + throw new RuntimeException + ("Can not construct file URL for '"+url+"':" + +ex2.getMessage()); + } + } + return urlObj; + } + + private ProtectionDomain getUrlDomain(URL url) + { + CodeSource cs; + cs = new CodeSource(url, (java.security.cert.Certificate[])null); + PermissionCollection pc = Policy.getPolicy().getPermissions(cs); + return new ProtectionDomain(cs, pc); + } + + public GeneratedClassLoader + createClassLoader(ClassLoader parentLoader, Object securityDomain) + { + ProtectionDomain domain = (ProtectionDomain)securityDomain; + return new Loader(parentLoader, domain); + } + + public Object getDynamicSecurityDomain(Object securityDomain) + { + ProtectionDomain staticDomain = (ProtectionDomain)securityDomain; + return getDynamicDomain(staticDomain); + } + + private ProtectionDomain getDynamicDomain(ProtectionDomain staticDomain) { + ContextPermissions p = new ContextPermissions(staticDomain); + ProtectionDomain contextDomain = new ProtectionDomain(null, p); + return contextDomain; + } + + public Object callWithDomain(Object securityDomain, + final Context cx, + final Callable callable, + final Scriptable scope, + final Scriptable thisObj, + final Object[] args) + { + ProtectionDomain staticDomain = (ProtectionDomain)securityDomain; + // There is no direct way in Java to intersect permitions according + // stack context with additional domain. + // The following implementation first constructs ProtectionDomain + // that allows actions only allowed by both staticDomain and current + // stack context, and then constructs AccessController for this dynamic + // domain. + // If this is too slow, alternative solution would be to generate + // class per domain with a proxy method to call to infect + // java stack. + // Another optimization in case of scripts coming from "world" domain, + // that is having minimal default privileges is to construct + // one AccessControlContext based on ProtectionDomain + // with least possible privileges and simply call + // AccessController.doPrivileged with this untrusted context + + ProtectionDomain dynamicDomain = getDynamicDomain(staticDomain); + ProtectionDomain[] tmp = { dynamicDomain }; + AccessControlContext restricted = new AccessControlContext(tmp); + + PrivilegedAction action = new PrivilegedAction() { + public Object run() { + return callable.call(cx, scope, thisObj, args); + } + }; + + return AccessController.doPrivileged(action, restricted); + } +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Main.java new file mode 100644 index 0000000..9120892 --- /dev/null +++ b/trunk/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; + } + +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/QuitAction.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/QuitAction.java new file mode 100644 index 0000000..dcad90e --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/QuitAction.java @@ -0,0 +1,50 @@ +/* -*- 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): + * Igor Bukanov + * + * 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 org.mozilla.javascript.Context; + +/** + * Defines action to perform in response to quit command. + */ +public interface QuitAction +{ + public void quit(Context cx, int exitCode); +} + diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/SecurityProxy.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/SecurityProxy.java new file mode 100644 index 0000000..8f029ea --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/SecurityProxy.java @@ -0,0 +1,48 @@ +/* -*- 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, 1999. + * + * 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): + * Igor Bukanov + * + * 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 org.mozilla.javascript.*; + +public abstract class SecurityProxy extends SecurityController +{ + protected abstract void callProcessFileSecure(Context cx, Scriptable scope, + String filename); + +} diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ShellContextFactory.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ShellContextFactory.java new file mode 100644 index 0000000..ba7e62c --- /dev/null +++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/ShellContextFactory.java @@ -0,0 +1,114 @@ +/* -*- 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): + * Igor Bukanov + * Bob Jervis + * + * 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 org.mozilla.javascript.*; + +public class ShellContextFactory extends ContextFactory +{ + private boolean strictMode; + private boolean warningAsError; + private int languageVersion; + private int optimizationLevel; + private boolean generatingDebug; + private ErrorReporter errorReporter; + + protected boolean hasFeature(Context cx, int featureIndex) + { + switch (featureIndex) { + case Context.FEATURE_STRICT_VARS: + case Context.FEATURE_STRICT_EVAL: + case Context.FEATURE_STRICT_MODE: + return strictMode; + + case Context.FEATURE_WARNING_AS_ERROR: + return warningAsError; + } + return super.hasFeature(cx, featureIndex); + } + + protected void onContextCreated(Context cx) + { + cx.setLanguageVersion(languageVersion); + cx.setOptimizationLevel(optimizationLevel); + if (errorReporter != null) { + cx.setErrorReporter(errorReporter); + } + cx.setGeneratingDebug(generatingDebug); + super.onContextCreated(cx); + } + + public void setStrictMode(boolean flag) + { + checkNotSealed(); + this.strictMode = flag; + } + + public void setWarningAsError(boolean flag) + { + checkNotSealed(); + this.warningAsError = flag; + } + + public void setLanguageVersion(int version) + { + Context.checkLanguageVersion(version); + checkNotSealed(); + this.languageVersion = version; + } + + public void setOptimizationLevel(int optimizationLevel) + { + Context.checkOptimizationLevel(optimizationLevel); + checkNotSealed(); + this.optimizationLevel = optimizationLevel; + } + + public void setErrorReporter(ErrorReporter errorReporter) + { + if (errorReporter == null) throw new IllegalArgumentException(); + this.errorReporter = errorReporter; + } + + public void setGeneratingDebug(boolean generatingDebug) + { + this.generatingDebug = generatingDebug; + } +} -- cgit v1.2.3