From 1a5e3c2d64be1c05a422fd78b23a31de155eca64 Mon Sep 17 00:00:00 2001 From: "alexanders@b2ef00c0-3703-41da-baef-cfe82387ac0c" Date: Wed, 3 Feb 2010 00:48:31 +0000 Subject: removed duplicate trunk directory --HG-- extra : convert_revision : svn%3Ab2ef00c0-3703-41da-baef-cfe82387ac0c/trunk%404 --- .../org/mozilla/javascript/tools/shell/Global.java | 1038 ++++++++++++++++++++ 1 file changed, 1038 insertions(+) create mode 100644 trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java (limited to 'trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/shell/Global.java') 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; +} + -- cgit v1.2.3