1
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3
* The contents of this file are subject to the Netscape Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/NPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is Rhino code, released
16
* The Initial Developer of the Original Code is Netscape
17
* Communications Corporation. Portions created by Netscape are
18
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
27
* Alternatively, the contents of this file may be used under the
28
* terms of the GNU Public License (the "GPL"), in which case the
29
* provisions of the GPL are applicable instead of those above.
30
* If you wish to allow use of your version of this file only
31
* under the terms of the GPL and not to allow others to use your
32
* version of this file under the NPL, indicate your decision by
33
* deleting the provisions above and replace them with the notice
34
* and other provisions required by the GPL. If you do not delete
35
* the provisions above, a recipient may use your version of this
36
* file under either the NPL or the GPL.
39
package org.mozilla.javascript.tools.shell;
43
import java.lang.reflect.*;
44
import org.mozilla.javascript.*;
45
import org.mozilla.javascript.tools.ToolErrorReporter;
50
* Can execute scripts interactively or in batch mode at the command line.
51
* An example of controlling the JavaScript engine.
60
* Process arguments as would a normal Java program. Also
61
* create a new Context and associate it with the current thread.
62
* Then set up the execution environment and begin to
65
public static void main(String args[]) {
66
int result = exec(args);
72
* Execute the given arguments, but don't System.exit at the end.
74
public static int exec(String args[]) {
75
Context cx = Context.enter();
76
// Create the top-level scope object.
77
global = new Global(cx);
78
errorReporter = new ToolErrorReporter(false, global.getErr());
79
cx.setErrorReporter(errorReporter);
81
args = processOptions(cx, args);
84
if (fileList.size() == 0 && args.length > 0) {
86
fileList.addElement(args[0]);
89
fileList.addElement(null);
91
// get the command line arguments after the name of the script,
92
// and define "arguments" array in the top-level object
93
Object[] array = args;
94
if (args.length > 0) {
95
int length = args.length - skip;
96
array = new Object[length];
97
System.arraycopy(args, skip, array, 0, length);
99
Scriptable argsObj = cx.newArray(global, array);
100
global.defineProperty("arguments", argsObj,
101
ScriptableObject.DONTENUM);
103
for (int i=0; i < fileList.size(); i++) {
104
processSource(cx, (String) fileList.get(i));
114
public static String[] processOptions(Context cx, String args[]) {
115
cx.setTargetPackage(""); // default to no package
116
for (int i=0; i < args.length; i++) {
117
String arg = args[i];
118
if (!arg.startsWith("-")) {
119
processStdin = false;
120
String[] result = new String[args.length - i];
121
System.arraycopy(args, i, result, 0, args.length - i);
124
if (arg.equals("-version")) {
125
if (++i == args.length)
127
double d = cx.toNumber(args[i]);
130
cx.setLanguageVersion((int) d);
133
if (arg.equals("-opt") || arg.equals("-O")) {
134
if (++i == args.length)
136
double d = cx.toNumber(args[i]);
139
cx.setOptimizationLevel((int)d);
142
if (arg.equals("-e")) {
143
processStdin = false;
144
if (++i == args.length)
146
Reader reader = new StringReader(args[i]);
147
evaluateReader(cx, global, reader, "<command>", 1);
150
if (arg.equals("-w")) {
151
errorReporter.setIsReportingWarnings(true);
154
if (arg.equals("-f")) {
155
processStdin = false;
156
if (++i == args.length)
158
fileList.addElement(args[i].equals("-") ? null : args[i]);
163
return new String[0];
167
* Print a usage message.
169
public static void usage(String s) {
170
p(ToolErrorReporter.getMessage("msg.shell.usage", s));
175
* Evaluate JavaScript source.
177
* @param cx the current context
178
* @param filename the name of the file to compile, or null
179
* for interactive mode.
181
public static void processSource(Context cx, String filename) {
182
if (filename == null || filename.equals("-")) {
183
// Use the interpreter for interactive input
184
cx.setOptimizationLevel(-1);
186
BufferedReader in = new BufferedReader
187
(new InputStreamReader(global.getIn()));
189
boolean hitEOF = false;
191
int startline = lineno;
192
if (filename == null)
193
global.getErr().print("js> ");
194
global.getErr().flush();
197
// Collect lines of source to compile.
201
newline = in.readLine();
203
catch (IOException ioe) {
204
global.getErr().println(ioe.toString());
207
if (newline == null) {
211
source = source + newline + "\n";
213
if (cx.stringIsCompilableUnit(source))
216
Reader reader = new StringReader(source);
217
Object result = evaluateReader(cx, global, reader,
218
"<stdin>", startline);
219
if (result != cx.getUndefinedValue()) {
221
global.getErr().println(cx.toString(result));
222
} catch (EcmaError ee) {
223
String msg = ToolErrorReporter.getMessage(
224
"msg.uncaughtJSException", ee.toString());
225
exitCode = EXITCODE_RUNTIME_ERROR;
226
if (ee.getSourceName() != null) {
227
Context.reportError(msg, ee.getSourceName(),
230
ee.getColumnNumber());
232
Context.reportError(msg);
236
NativeArray h = global.history;
237
h.put((int)h.jsGet_length(), h, source);
239
global.getErr().println();
240
} else processFile(cx, global, filename);
244
public static void processFile(Context cx, Scriptable scope,
249
in = new PushbackReader(new FileReader(filename));
251
// Support the executable script #! syntax: If
252
// the first line begins with a '#', treat the whole
253
// line as a comment.
255
while ((c = in.read()) != -1) {
256
if (c == '\n' || c == '\r')
259
((PushbackReader) in).unread(c);
261
// No '#' line, just reopen the file and forget it
262
// ever happened. OPT closing and reopening
263
// undoubtedly carries some cost. Is this faster
264
// or slower than leaving the PushbackReader
267
in = new FileReader(filename);
269
filename = new java.io.File(filename).getCanonicalPath();
271
catch (FileNotFoundException ex) {
272
Context.reportError(ToolErrorReporter.getMessage(
275
exitCode = EXITCODE_FILE_NOT_FOUND;
277
} catch (IOException ioe) {
278
global.getErr().println(ioe.toString());
281
// Here we evalute the entire contents of the file as
282
// a script. Text is printed only if the print() function
284
evaluateReader(cx, scope, in, filename, 1);
287
public static Object evaluateReader(Context cx, Scriptable scope,
288
Reader in, String sourceName,
291
Object result = cx.getUndefinedValue();
293
result = cx.evaluateReader(scope, in, sourceName, lineno, null);
295
catch (WrappedException we) {
296
global.getErr().println(we.getWrappedException().toString());
297
we.printStackTrace();
299
catch (EcmaError ee) {
300
String msg = ToolErrorReporter.getMessage(
301
"msg.uncaughtJSException", ee.toString());
302
exitCode = EXITCODE_RUNTIME_ERROR;
303
if (ee.getSourceName() != null) {
304
Context.reportError(msg, ee.getSourceName(),
307
ee.getColumnNumber());
309
Context.reportError(msg);
312
catch (EvaluatorException ee) {
313
// Already printed message.
314
exitCode = EXITCODE_RUNTIME_ERROR;
316
catch (JavaScriptException jse) {
317
// Need to propagate ThreadDeath exceptions.
318
Object value = jse.getValue();
319
if (value instanceof ThreadDeath)
320
throw (ThreadDeath) value;
321
exitCode = EXITCODE_RUNTIME_ERROR;
322
Context.reportError(ToolErrorReporter.getMessage(
323
"msg.uncaughtJSException",
326
catch (IOException ioe) {
327
global.getErr().println(ioe.toString());
333
catch (IOException ioe) {
334
global.getErr().println(ioe.toString());
340
private static void p(String s) {
341
global.getOut().println(s);
344
public static ScriptableObject getScope() {
348
public static InputStream getIn() {
349
return Global.getInstance(global).getIn();
352
public static void setIn(InputStream in) {
353
Global.getInstance(global).setIn(in);
356
public static PrintStream getOut() {
357
return Global.getInstance(global).getOut();
360
public static void setOut(PrintStream out) {
361
Global.getInstance(global).setOut(out);
364
public static PrintStream getErr() {
365
return Global.getInstance(global).getErr();
368
public static void setErr(PrintStream err) {
369
Global.getInstance(global).setErr(err);
372
static protected ToolErrorReporter errorReporter;
373
static protected Global global;
374
static protected int exitCode = 0;
375
static private final int EXITCODE_RUNTIME_ERROR = 3;
376
static private final int EXITCODE_FILE_NOT_FOUND = 4;
377
//static private DebugShell debugShell;
378
static boolean processStdin = true;
379
static Vector fileList = new Vector(5);
1
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3
* The contents of this file are subject to the Netscape Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/NPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is Rhino code, released
16
* The Initial Developer of the Original Code is Netscape
17
* Communications Corporation. Portions created by Netscape are
18
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
28
* Alternatively, the contents of this file may be used under the
29
* terms of the GNU Public License (the "GPL"), in which case the
30
* provisions of the GPL are applicable instead of those above.
31
* If you wish to allow use of your version of this file only
32
* under the terms of the GPL and not to allow others to use your
33
* version of this file under the NPL, indicate your decision by
34
* deleting the provisions above and replace them with the notice
35
* and other provisions required by the GPL. If you do not delete
36
* the provisions above, a recipient may use your version of this
37
* file under either the NPL or the GPL.
40
package org.mozilla.javascript.tools.shell;
44
import java.net.MalformedURLException;
46
import java.lang.reflect.*;
47
import org.mozilla.javascript.*;
48
import org.mozilla.javascript.tools.ToolErrorReporter;
53
* Can execute scripts interactively or in batch mode at the command line.
54
* An example of controlling the JavaScript engine.
60
public static final ShellContextFactory
61
shellContextFactory = new ShellContextFactory();
64
* Proxy class to avoid proliferation of anonymous classes.
66
private static class IProxy implements ContextAction
68
private static final int PROCESS_FILES = 1;
69
private static final int EVAL_INLINE_SCRIPT = 2;
80
public Object run(Context cx)
82
if (type == PROCESS_FILES) {
83
processFiles(cx, args);
84
} else if (type == EVAL_INLINE_SCRIPT) {
85
evaluateScript(cx, getGlobal(), null, scriptText,
86
"<command>", 1, null);
98
* Process arguments as would a normal Java program. Also
99
* create a new Context and associate it with the current thread.
100
* Then set up the execution environment and begin to
103
public static void main(String args[]) {
105
if (Boolean.getBoolean("rhino.use_java_policy_security")) {
106
initJavaPolicySecuritySupport();
108
} catch (SecurityException ex) {
109
ex.printStackTrace(System.err);
112
int result = exec(args);
119
* Execute the given arguments, but don't System.exit at the end.
121
public static int exec(String origArgs[])
124
for (int i=0; i < origArgs.length; i++) {
125
String arg = origArgs[i];
126
if (arg.equals("-sealedlib")) {
132
errorReporter = new ToolErrorReporter(false, global.getErr());
133
shellContextFactory.setErrorReporter(errorReporter);
134
String[] args = processOptions(origArgs);
136
fileList.addElement(null);
138
IProxy iproxy = new IProxy(IProxy.PROCESS_FILES);
140
shellContextFactory.call(iproxy);
145
static void processFiles(Context cx, String[] args)
147
if (!global.initialized) {
150
// define "arguments" array in the top-level object:
151
// need to allocate new array since newArray requires instances
152
// of exactly Object[], not ObjectSubclass[]
153
Object[] array = new Object[args.length];
154
System.arraycopy(args, 0, array, 0, args.length);
155
Scriptable argsObj = cx.newArray(global, array);
156
global.defineProperty("arguments", argsObj,
157
ScriptableObject.DONTENUM);
159
for (int i=0; i < fileList.size(); i++) {
160
processSource(cx, (String) fileList.elementAt(i));
165
public static Global getGlobal()
173
public static String[] processOptions(String args[])
176
goodUsage: for (int i = 0; ; ++i) {
177
if (i == args.length) {
178
return new String[0];
180
String arg = args[i];
181
if (!arg.startsWith("-")) {
182
processStdin = false;
183
fileList.addElement(arg);
184
String[] result = new String[args.length - i - 1];
185
System.arraycopy(args, i+1, result, 0, args.length - i - 1);
188
if (arg.equals("-version")) {
189
if (++i == args.length) {
195
version = Integer.parseInt(args[i]);
196
} catch (NumberFormatException ex) {
197
usageError = args[i];
200
if (!Context.isValidLanguageVersion(version)) {
201
usageError = args[i];
204
shellContextFactory.setLanguageVersion(version);
207
if (arg.equals("-opt") || arg.equals("-O")) {
208
if (++i == args.length) {
214
opt = Integer.parseInt(args[i]);
215
} catch (NumberFormatException ex) {
216
usageError = args[i];
220
// Compatibility with Cocoon Rhino fork
222
} else if (!Context.isValidOptimizationLevel(opt)) {
223
usageError = args[i];
226
shellContextFactory.setOptimizationLevel(opt);
229
if (arg.equals("-strict")) {
230
shellContextFactory.setStrictMode(true);
233
if (arg.equals("-e")) {
234
processStdin = false;
235
if (++i == args.length) {
239
IProxy iproxy = new IProxy(IProxy.EVAL_INLINE_SCRIPT);
240
iproxy.scriptText = args[i];
241
shellContextFactory.call(iproxy);
244
if (arg.equals("-w")) {
245
errorReporter.setIsReportingWarnings(true);
248
if (arg.equals("-f")) {
249
processStdin = false;
250
if (++i == args.length) {
254
fileList.addElement(args[i].equals("-") ? null : args[i]);
257
if (arg.equals("-sealedlib")) {
258
// Should already be processed
259
if (!sealedStdLib) Kit.codeBug();
265
// print usage message
266
p(ToolErrorReporter.getMessage("msg.shell.usage", usageError));
271
private static void initJavaPolicySecuritySupport()
275
Class cl = Class.forName
276
("org.mozilla.javascript.tools.shell.JavaPolicySecurity");
277
securityImpl = (SecurityProxy)cl.newInstance();
278
SecurityController.initGlobal(securityImpl);
280
} catch (ClassNotFoundException ex) {
282
} catch (IllegalAccessException ex) {
284
} catch (InstantiationException ex) {
286
} catch (LinkageError ex) {
289
throw Kit.initCause(new IllegalStateException(
290
"Can not load security support: "+exObj), exObj);
294
* Evaluate JavaScript source.
296
* @param cx the current context
297
* @param filename the name of the file to compile, or null
298
* for interactive mode.
300
public static void processSource(Context cx, String filename)
302
if (filename == null || filename.equals("-")) {
303
if (filename == null) {
304
// print implementation version
305
getOut().println(cx.getImplementationVersion());
308
// Use the interpreter for interactive input
309
cx.setOptimizationLevel(-1);
311
BufferedReader in = new BufferedReader
312
(new InputStreamReader(global.getIn()));
314
boolean hitEOF = false;
316
int startline = lineno;
317
if (filename == null)
318
global.getErr().print("js> ");
319
global.getErr().flush();
322
// Collect lines of source to compile.
326
newline = in.readLine();
328
catch (IOException ioe) {
329
global.getErr().println(ioe.toString());
332
if (newline == null) {
336
source = source + newline + "\n";
338
if (cx.stringIsCompilableUnit(source))
341
Object result = evaluateScript(cx, global, null, source,
342
"<stdin>", startline, null);
343
if (result != cx.getUndefinedValue()) {
345
global.getErr().println(cx.toString(result));
346
} catch (RhinoException rex) {
347
errorReporter.reportException(rex);
350
NativeArray h = global.history;
351
h.put((int)h.getLength(), h, source);
353
global.getErr().println();
355
processFile(cx, global, filename);
360
public static void processFile(Context cx, Scriptable scope,
363
if (securityImpl == null) {
364
processFileSecure(cx, scope, filename, null);
366
securityImpl.callProcessFileSecure(cx, scope, filename);
370
static void processFileSecure(Context cx, Scriptable scope,
371
String filename, Object securityDomain)
374
// Try filename first as URL
376
URL url = new URL(filename);
377
InputStream is = url.openStream();
378
in = new BufferedReader(new InputStreamReader(is));
379
} catch (MalformedURLException mfex) {
380
// fall through to try it as a file
382
} catch (IOException ioex) {
383
Context.reportError(ToolErrorReporter.getMessage(
384
"msg.couldnt.open.url", filename, ioex.toString()));
385
exitCode = EXITCODE_FILE_NOT_FOUND;
390
// Try filename as file
392
in = new PushbackReader(new FileReader(filename));
394
// Support the executable script #! syntax: If
395
// the first line begins with a '#', treat the whole
396
// line as a comment.
398
while ((c = in.read()) != -1) {
399
if (c == '\n' || c == '\r')
402
((PushbackReader) in).unread(c);
404
// No '#' line, just reopen the file and forget it
405
// ever happened. OPT closing and reopening
406
// undoubtedly carries some cost. Is this faster
407
// or slower than leaving the PushbackReader
410
in = new FileReader(filename);
412
filename = new java.io.File(filename).getCanonicalPath();
414
catch (FileNotFoundException ex) {
415
Context.reportError(ToolErrorReporter.getMessage(
418
exitCode = EXITCODE_FILE_NOT_FOUND;
420
} catch (IOException ioe) {
421
global.getErr().println(ioe.toString());
424
// Here we evalute the entire contents of the file as
425
// a script. Text is printed only if the print() function
427
evaluateScript(cx, scope, in, null, filename, 1, securityDomain);
430
public static Object evaluateScript(Context cx, Scriptable scope,
431
Reader in, String script,
433
int lineno, Object securityDomain)
435
if (!global.initialized) {
438
Object result = cx.getUndefinedValue();
443
result = cx.evaluateReader(scope, in,
449
} catch (IOException ioe) {
450
global.getErr().println(ioe.toString());
453
result = cx.evaluateString(scope, script, sourceName, lineno,
456
} catch (WrappedException we) {
457
global.getErr().println(we.getWrappedException().toString());
458
we.printStackTrace();
459
} catch (EvaluatorException ee) {
460
// Already printed message.
461
exitCode = EXITCODE_RUNTIME_ERROR;
462
} catch (RhinoException rex) {
463
errorReporter.reportException(rex);
464
exitCode = EXITCODE_RUNTIME_ERROR;
465
} catch (VirtualMachineError ex) {
466
// Treat StackOverflow and OutOfMemory as runtime errors
467
ex.printStackTrace();
468
String msg = ToolErrorReporter.getMessage(
469
"msg.uncaughtJSException", ex.toString());
470
exitCode = EXITCODE_RUNTIME_ERROR;
471
Context.reportError(msg);
476
private static void p(String s) {
477
global.getOut().println(s);
480
public static ScriptableObject getScope() {
481
if (!global.initialized) {
482
global.init(Context.getCurrentContext());
487
public static InputStream getIn() {
488
return Global.getInstance(getGlobal()).getIn();
491
public static void setIn(InputStream in) {
492
Global.getInstance(getGlobal()).setIn(in);
495
public static PrintStream getOut() {
496
return Global.getInstance(getGlobal()).getOut();
499
public static void setOut(PrintStream out) {
500
Global.getInstance(getGlobal()).setOut(out);
503
public static PrintStream getErr() {
504
return Global.getInstance(getGlobal()).getErr();
507
public static void setErr(PrintStream err) {
508
Global.getInstance(getGlobal()).setErr(err);
511
static protected final Global global = new Global();
512
static protected ToolErrorReporter errorReporter;
513
static protected int exitCode = 0;
514
static private final int EXITCODE_RUNTIME_ERROR = 3;
515
static private final int EXITCODE_FILE_NOT_FOUND = 4;
516
//static private DebugShell debugShell;
517
static boolean processStdin = true;
518
static boolean sealedStdLib = false;
519
static Vector fileList = new Vector(5);
520
private static SecurityProxy securityImpl;