0
|
1 /*
|
|
2 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 *
|
|
5 * This code is free software; you can redistribute it and/or modify it
|
|
6 * under the terms of the GNU General Public License version 2 only, as
|
|
7 * published by the Free Software Foundation.
|
|
8 *
|
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 * version 2 for more details (a copy is included in the LICENSE file that
|
|
13 * accompanied this code).
|
|
14 *
|
|
15 * You should have received a copy of the GNU General Public License version
|
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 *
|
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 package sun.jvm.hotspot.utilities.soql;
|
|
26
|
|
27 import java.io.*;
|
|
28 import java.util.*;
|
|
29 import javax.script.Invocable;
|
|
30 import javax.script.ScriptContext;
|
|
31 import javax.script.ScriptEngine;
|
|
32 import javax.script.ScriptEngineManager;
|
|
33 import javax.script.ScriptException;
|
|
34 import sun.jvm.hotspot.debugger.*;
|
|
35 import sun.jvm.hotspot.oops.*;
|
|
36 import sun.jvm.hotspot.runtime.*;
|
|
37 import sun.jvm.hotspot.utilities.*;
|
|
38 import sun.jvm.hotspot.tools.*;
|
|
39 import sun.jvm.hotspot.tools.jcore.*;
|
|
40 import java.lang.reflect.Method;
|
|
41 import java.lang.reflect.Modifier;
|
|
42
|
|
43 /**
|
|
44 * Simple wrapper around jsr-223 JavaScript script engine.
|
|
45 * In addition to wrapping useful functionality of jsr-223 engine,
|
|
46 * this class exposed certain "global" functions to the script.
|
|
47 */
|
|
48 public abstract class JSJavaScriptEngine extends MapScriptObject {
|
|
49 /**
|
|
50 * Start a read-eval-print loop with this engine.
|
|
51 */
|
|
52 public void startConsole() {
|
|
53 start(true);
|
|
54 }
|
|
55
|
|
56 /**
|
|
57 * Initialize the engine so that we can "eval" strings
|
|
58 * and files later.
|
|
59 */
|
|
60 public void start() {
|
|
61 start(false);
|
|
62 }
|
|
63
|
|
64 /**
|
|
65 * Define a global function that invokes given Method.
|
|
66 */
|
|
67 public void defineFunction(Object target, Method method) {
|
|
68 putFunction(target, method, false);
|
|
69 }
|
|
70
|
|
71 /**
|
|
72 * Call the script function of given name passing the
|
|
73 * given arguments.
|
|
74 */
|
|
75 public Object call(String name, Object[] args) {
|
|
76 Invocable invocable = (Invocable)engine;
|
|
77 try {
|
|
78 return invocable.invokeFunction(name, args);
|
|
79 } catch (RuntimeException re) {
|
|
80 throw re;
|
|
81 } catch (Exception exp) {
|
|
82 throw new RuntimeException(exp);
|
|
83 }
|
|
84 }
|
|
85
|
|
86 /**
|
|
87 address function returns address of JSJavaObject as String. For other
|
|
88 type of objects, the result is undefined.
|
|
89 */
|
|
90 public Object address(Object[] args) {
|
|
91 if (args.length != 1) return UNDEFINED;
|
|
92 Object o = args[0];
|
|
93 if (o != null && o instanceof JSJavaObject) {
|
|
94 return ((JSJavaObject)o).getOop().getHandle().toString();
|
|
95 } else {
|
|
96 return UNDEFINED;
|
|
97 }
|
|
98 }
|
|
99
|
|
100
|
|
101 /**
|
|
102 classof function gets type of given JSJavaInstance or JSJavaArray. Or
|
|
103 given a string class name, this function gets the class object. For
|
|
104 other type of objects, the result is undefined.
|
|
105 */
|
|
106 public Object classof(Object[] args) {
|
|
107 if (args.length != 1) {
|
|
108 return UNDEFINED;
|
|
109 }
|
|
110 Object o = args[0];
|
|
111 if (o != null) {
|
|
112 if (o instanceof JSJavaObject) {
|
|
113 if (o instanceof JSJavaInstance) {
|
|
114 return ((JSJavaInstance)o).getJSJavaClass();
|
|
115 } else if (o instanceof JSJavaArray) {
|
|
116 return ((JSJavaArray)o).getJSJavaClass();
|
|
117 } else {
|
|
118 return UNDEFINED;
|
|
119 }
|
|
120 } else if (o instanceof String) {
|
|
121 InstanceKlass ik = SystemDictionaryHelper.findInstanceKlass((String) o);
|
|
122 return getJSJavaFactory().newJSJavaKlass(ik).getJSJavaClass();
|
|
123 } else {
|
|
124 return UNDEFINED;
|
|
125 }
|
|
126 } else {
|
|
127 return UNDEFINED;
|
|
128 }
|
|
129 }
|
|
130
|
|
131 /**
|
|
132 * dumpClass function creates a .class file for a given Class object.
|
|
133 * On success, returns true. Else, returns false. Second optional argument
|
|
134 * specifies the directory in which .class content is dumped. This defaults
|
|
135 * to '.'
|
|
136 */
|
|
137 public Object dumpClass(Object[] args) {
|
|
138 if (args.length == 0) {
|
|
139 return Boolean.FALSE;
|
|
140 }
|
|
141 Object clazz = args[0];
|
|
142 if (clazz == null) {
|
|
143 return Boolean.FALSE;
|
|
144 }
|
|
145 InstanceKlass ik = null;
|
|
146 if (clazz instanceof String) {
|
|
147 String name = (String) clazz;
|
|
148 if (name.startsWith("0x")) {
|
|
149 // treat it as address
|
|
150 VM vm = VM.getVM();
|
|
151 Address addr = vm.getDebugger().parseAddress(name);
|
|
152 Oop oop = vm.getObjectHeap().newOop(addr.addOffsetToAsOopHandle(0));
|
|
153 if (oop instanceof InstanceKlass) {
|
|
154 ik = (InstanceKlass) oop;
|
|
155 } else {
|
|
156 return Boolean.FALSE;
|
|
157 }
|
|
158 } else {
|
|
159 ik = SystemDictionaryHelper.findInstanceKlass((String) clazz);
|
|
160 }
|
|
161 } else if (clazz instanceof JSJavaClass) {
|
|
162 JSJavaKlass jk = ((JSJavaClass)clazz).getJSJavaKlass();
|
|
163 if (jk != null && jk instanceof JSJavaInstanceKlass) {
|
|
164 ik = ((JSJavaInstanceKlass)jk).getInstanceKlass();
|
|
165 }
|
|
166 } else {
|
|
167 return Boolean.FALSE;
|
|
168 }
|
|
169
|
|
170 if (ik == null) return Boolean.FALSE;
|
|
171 StringBuffer buf = new StringBuffer();
|
|
172 if (args.length > 1) {
|
|
173 buf.append(args[1].toString());
|
|
174 } else {
|
|
175 buf.append('.');
|
|
176 }
|
|
177
|
|
178 buf.append(File.separatorChar);
|
|
179 buf.append(ik.getName().asString().replace('/', File.separatorChar));
|
|
180 buf.append(".class");
|
|
181 String fileName = buf.toString();
|
|
182 File file = new File(fileName);
|
|
183
|
|
184 try {
|
|
185 int index = fileName.lastIndexOf(File.separatorChar);
|
|
186 File dir = new File(fileName.substring(0, index));
|
|
187 dir.mkdirs();
|
|
188 FileOutputStream fos = new FileOutputStream(file);
|
|
189 ClassWriter cw = new ClassWriter(ik, fos);
|
|
190 cw.write();
|
|
191 fos.close();
|
|
192 } catch (IOException exp) {
|
|
193 printError(exp.toString(), exp);
|
|
194 return Boolean.FALSE;
|
|
195 }
|
|
196
|
|
197 return Boolean.TRUE;
|
|
198 }
|
|
199
|
|
200 /**
|
|
201 * dumpHeap function creates a heap dump file.
|
|
202 * On success, returns true. Else, returns false.
|
|
203 */
|
|
204 public Object dumpHeap(Object[] args) {
|
|
205 String fileName = "heap.bin";
|
|
206 if (args.length > 0) {
|
|
207 fileName = args[0].toString();
|
|
208 }
|
|
209 return new JMap().writeHeapHprofBin(fileName)? Boolean.TRUE: Boolean.FALSE;
|
|
210 }
|
|
211
|
|
212 /**
|
|
213 help function prints help message for global functions and variables.
|
|
214 */
|
|
215 public void help(Object[] args) {
|
|
216 println("Function/Variable Description");
|
|
217 println("================= ===========");
|
|
218 println("address(jobject) returns the address of the Java object");
|
|
219 println("classof(jobject) returns the class object of the Java object");
|
|
220 println("dumpClass(jclass,[dir]) writes .class for the given Java Class");
|
|
221 println("dumpHeap([file]) writes heap in hprof binary format");
|
|
222 println("help() prints this help message");
|
|
223 println("identityHash(jobject) returns the hashCode of the Java object");
|
|
224 println("mirror(jobject) returns a local mirror of the Java object");
|
|
225 println("load([file1, file2,...]) loads JavaScript file(s). With no files, reads <stdin>");
|
|
226 println("object(string) converts a string address into Java object");
|
|
227 println("owner(jobject) returns the owner thread of this monitor or null");
|
|
228 println("sizeof(jobject) returns the size of Java object in bytes");
|
|
229 println("staticof(jclass, field) returns a static field of the given Java class");
|
|
230 println("read([prompt]) reads a single line from standard input");
|
|
231 println("quit() quits the interactive load call");
|
|
232 println("jvm the target jvm that is being debugged");
|
|
233 }
|
|
234
|
|
235 /**
|
|
236 identityHash function gets identity hash code value of given
|
|
237 JSJavaObject. For other type of objects, the result is undefined.
|
|
238 */
|
|
239 public Object identityHash(Object[] args) {
|
|
240 if (args.length != 1) return UNDEFINED;
|
|
241 Object o = args[0];
|
|
242 if (o != null && o instanceof JSJavaObject) {
|
|
243 return new Long(((JSJavaObject)o).getOop().identityHash());
|
|
244 } else {
|
|
245 return UNDEFINED;
|
|
246 }
|
|
247 }
|
|
248
|
|
249
|
|
250 /**
|
|
251 * Load and execute a set of JavaScript source files.
|
|
252 * This method is defined as a JavaScript function.
|
|
253 */
|
|
254 public void load(Object[] args) {
|
|
255 for (int i = 0; i < args.length; i++) {
|
|
256 processSource(args[i].toString());
|
|
257 }
|
|
258 }
|
|
259
|
|
260 /**
|
|
261 mirror function creats local copy of the Oop wrapper supplied.
|
|
262 if mirror can not be created, return undefined. For other types,
|
|
263 mirror is undefined.
|
|
264 */
|
|
265 public Object mirror(Object[] args) {
|
|
266 Object o = args[0];
|
|
267 if (o != null && o instanceof JSJavaObject) {
|
|
268 Oop oop = ((JSJavaObject)o).getOop();
|
|
269 Object res = null;
|
|
270 try {
|
|
271 if (oop instanceof InstanceKlass) {
|
|
272 res = getObjectReader().readClass((InstanceKlass) oop);
|
|
273 } else {
|
|
274 res = getObjectReader().readObject(oop);
|
|
275 }
|
|
276 } catch (Exception e) {
|
|
277 if (debug) e.printStackTrace(getErrorStream());
|
|
278 }
|
|
279 return (res != null)? res : UNDEFINED;
|
|
280 } else {
|
|
281 return UNDEFINED;
|
|
282 }
|
|
283 }
|
|
284
|
|
285 /**
|
|
286 owner function gets owning thread of given JSJavaObjec, if any, else
|
|
287 returns null. For other type of objects, the result is undefined.
|
|
288 */
|
|
289 public Object owner(Object[] args) {
|
|
290 Object o = args[0];
|
|
291 if (o != null && o instanceof JSJavaObject) {
|
|
292 return getOwningThread((JSJavaObject)o);
|
|
293 } else {
|
|
294 return UNDEFINED;
|
|
295 }
|
|
296 }
|
|
297
|
|
298 /**
|
|
299 object function takes a string address and returns a JSJavaObject.
|
|
300 For other type of objects, the result is undefined.
|
|
301 */
|
|
302 public Object object(Object[] args) {
|
|
303 Object o = args[0];
|
|
304 if (o != null && o instanceof String) {
|
|
305 VM vm = VM.getVM();
|
|
306 Address addr = vm.getDebugger().parseAddress((String)o);
|
|
307 Oop oop = vm.getObjectHeap().newOop(addr.addOffsetToAsOopHandle(0));
|
|
308 return getJSJavaFactory().newJSJavaObject(oop);
|
|
309 } else {
|
|
310 return UNDEFINED;
|
|
311 }
|
|
312 }
|
|
313
|
|
314 /**
|
|
315 sizeof function returns size of a Java object in bytes. For other type
|
|
316 of objects, the result is undefined.
|
|
317 */
|
|
318 public Object sizeof(Object[] args) {
|
|
319 if (args.length != 1) return UNDEFINED;
|
|
320 Object o = args[0];
|
|
321 if (o != null && o instanceof JSJavaObject) {
|
|
322 return new Long(((JSJavaObject)o).getOop().getObjectSize());
|
|
323 } else {
|
|
324 return UNDEFINED;
|
|
325 }
|
|
326 }
|
|
327
|
|
328 /**
|
|
329 staticof function gets static field of given class. Both class and
|
|
330 field name are specified as strings. undefined is returned if there is
|
|
331 no such named field.
|
|
332 */
|
|
333 public Object staticof(Object[] args) {
|
|
334 Object classname = args[0];
|
|
335 Object fieldname = args[1];
|
|
336 if (fieldname == null || classname == null ||
|
|
337 !(fieldname instanceof String)) {
|
|
338 return UNDEFINED;
|
|
339 }
|
|
340
|
|
341 InstanceKlass ik = null;
|
|
342 if (classname instanceof JSJavaClass) {
|
|
343 JSJavaClass jclass = (JSJavaClass) classname;
|
|
344 JSJavaKlass jk = jclass.getJSJavaKlass();
|
|
345 if (jk != null && jk instanceof JSJavaInstanceKlass) {
|
|
346 ik = ((JSJavaInstanceKlass)jk).getInstanceKlass();
|
|
347 }
|
|
348 } else if (classname instanceof String) {
|
|
349 ik = SystemDictionaryHelper.findInstanceKlass((String)classname);
|
|
350 } else {
|
|
351 return UNDEFINED;
|
|
352 }
|
|
353
|
|
354 if (ik == null) {
|
|
355 return UNDEFINED;
|
|
356 }
|
|
357 JSJavaFactory factory = getJSJavaFactory();
|
|
358 try {
|
|
359 return ((JSJavaInstanceKlass) factory.newJSJavaKlass(ik)).getStaticFieldValue((String)fieldname);
|
|
360 } catch (NoSuchFieldException e) {
|
|
361 return UNDEFINED;
|
|
362 }
|
|
363 }
|
|
364
|
|
365 /**
|
|
366 * read function reads a single line of input from standard input
|
|
367 */
|
|
368 public Object read(Object[] args) {
|
|
369 BufferedReader in = getInputReader();
|
|
370 if (in == null) {
|
|
371 return null;
|
|
372 }
|
|
373 if (args.length > 0) {
|
|
374 print(args[0].toString());
|
|
375 print(":");
|
|
376 }
|
|
377 try {
|
|
378 return in.readLine();
|
|
379 } catch (IOException exp) {
|
|
380 exp.printStackTrace();
|
|
381 throw new RuntimeException(exp);
|
|
382 }
|
|
383 }
|
|
384
|
|
385 /**
|
|
386 * Quit the shell.
|
|
387 * This only affects the interactive mode.
|
|
388 */
|
|
389 public void quit(Object[] args) {
|
|
390 quit();
|
|
391 }
|
|
392
|
|
393 public void writeln(Object[] args) {
|
|
394 for (int i = 0; i < args.length; i++) {
|
|
395 print(args[i].toString());
|
|
396 print(" ");
|
|
397 }
|
|
398 println("");
|
|
399 }
|
|
400
|
|
401 public void write(Object[] args) {
|
|
402 for (int i = 0; i < args.length; i++) {
|
|
403 print(args[i].toString());
|
|
404 print(" ");
|
|
405 }
|
|
406 }
|
|
407
|
|
408 //-- Internals only below this point
|
|
409 protected void start(boolean console) {
|
|
410 ScriptContext context = engine.getContext();
|
|
411 OutputStream out = getOutputStream();
|
|
412 if (out != null) {
|
|
413 context.setWriter(new PrintWriter(out));
|
|
414 }
|
|
415 OutputStream err = getErrorStream();
|
|
416 if (err != null) {
|
|
417 context.setErrorWriter(new PrintWriter(err));
|
|
418 }
|
|
419 // load "sa.js" initialization file
|
|
420 loadInitFile();
|
|
421 // load "~/jsdb.js" (if found) to perform user specific
|
|
422 // initialization steps, if any.
|
|
423 loadUserInitFile();
|
|
424
|
|
425 JSJavaFactory fac = getJSJavaFactory();
|
|
426 JSJavaVM jvm = (fac != null)? fac.newJSJavaVM() : null;
|
|
427 // call "main" function from "sa.js" -- main expects
|
|
428 // 'this' object and jvm object
|
|
429 call("main", new Object[] { this, jvm });
|
|
430
|
|
431 // if asked, start read-eval-print console
|
|
432 if (console) {
|
|
433 processSource(null);
|
|
434 }
|
|
435 }
|
|
436
|
|
437 protected JSJavaScriptEngine(boolean debug) {
|
|
438 this.debug = debug;
|
|
439 ScriptEngineManager manager = new ScriptEngineManager();
|
|
440 engine = manager.getEngineByName("javascript");
|
|
441 if (engine == null) {
|
|
442 throw new RuntimeException("can't load JavaScript engine");
|
|
443 }
|
|
444 Method[] methods = getClass().getMethods();
|
|
445 for (int i = 0; i < methods.length; i++) {
|
|
446 Method m = methods[i];
|
|
447 if (! Modifier.isPublic(m.getModifiers())) {
|
|
448 continue;
|
|
449 }
|
|
450 Class[] argTypes = m.getParameterTypes();
|
|
451 if (argTypes.length == 1 &&
|
|
452 argTypes[0] == Object[].class) {
|
|
453 putFunction(this, m);
|
|
454 }
|
|
455 }
|
|
456 }
|
|
457
|
|
458 protected JSJavaScriptEngine() {
|
|
459 this(false);
|
|
460 }
|
|
461
|
|
462 protected abstract ObjectReader getObjectReader();
|
|
463 protected abstract JSJavaFactory getJSJavaFactory();
|
|
464 protected void printPrompt(String str) {
|
|
465 System.err.print(str);
|
|
466 System.err.flush();
|
|
467 }
|
|
468
|
|
469 protected void loadInitFile() {
|
|
470 InputStream is = JSJavaScriptEngine.class.getResourceAsStream("sa.js");
|
|
471 BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
|
472 evalReader(reader, "sa.js");
|
|
473 }
|
|
474
|
|
475 protected void loadUserInitFile() {
|
|
476 File initFile = new File(getUserInitFileDir(), getUserInitFileName());
|
|
477 if (initFile.exists() && initFile.isFile()) {
|
|
478 // load the init script
|
|
479 processSource(initFile.getAbsolutePath());
|
|
480 }
|
|
481 }
|
|
482
|
|
483 protected String getUserInitFileDir() {
|
|
484 return System.getProperty("user.home");
|
|
485 }
|
|
486
|
|
487 protected String getUserInitFileName() {
|
|
488 return "jsdb.js";
|
|
489 }
|
|
490
|
|
491 protected BufferedReader getInputReader() {
|
|
492 if (inReader == null) {
|
|
493 inReader = new BufferedReader(new InputStreamReader(System.in));
|
|
494 }
|
|
495 return inReader;
|
|
496 }
|
|
497
|
|
498 protected PrintStream getOutputStream() {
|
|
499 return System.out;
|
|
500 }
|
|
501
|
|
502 protected PrintStream getErrorStream() {
|
|
503 return System.err;
|
|
504 }
|
|
505
|
|
506 protected void print(String name) {
|
|
507 getOutputStream().print(name);
|
|
508 }
|
|
509
|
|
510 protected void println(String name) {
|
|
511 getOutputStream().println(name);
|
|
512 }
|
|
513
|
|
514 protected void printError(String message) {
|
|
515 printError(message, null);
|
|
516 }
|
|
517
|
|
518 protected void printError(String message, Exception exp) {
|
|
519 getErrorStream().println(message);
|
|
520 if (exp != null && debug) {
|
|
521 exp.printStackTrace(getErrorStream());
|
|
522 }
|
|
523 }
|
|
524
|
|
525 protected boolean isQuitting() {
|
|
526 return quitting;
|
|
527 }
|
|
528
|
|
529 protected void quit() {
|
|
530 quitting = true;
|
|
531 }
|
|
532
|
|
533 protected ScriptEngine getScriptEngine() {
|
|
534 return engine;
|
|
535 }
|
|
536
|
|
537 private JSJavaThread getOwningThread(JSJavaObject jo) {
|
|
538 Oop oop = jo.getOop();
|
|
539 Mark mark = oop.getMark();
|
|
540 ObjectMonitor mon = null;
|
|
541 Address owner = null;
|
|
542 JSJavaThread owningThread = null;
|
|
543 // check for heavyweight monitor
|
|
544 if (! mark.hasMonitor()) {
|
|
545 // check for lightweight monitor
|
|
546 if (mark.hasLocker()) {
|
|
547 owner = mark.locker().getAddress(); // save the address of the Lock word
|
|
548 }
|
|
549 // implied else: no owner
|
|
550 } else {
|
|
551 // this object has a heavyweight monitor
|
|
552 mon = mark.monitor();
|
|
553
|
|
554 // The owner field of a heavyweight monitor may be NULL for no
|
|
555 // owner, a JavaThread * or it may still be the address of the
|
|
556 // Lock word in a JavaThread's stack. A monitor can be inflated
|
|
557 // by a non-owning JavaThread, but only the owning JavaThread
|
|
558 // can change the owner field from the Lock word to the
|
|
559 // JavaThread * and it may not have done that yet.
|
|
560 owner = mon.owner();
|
|
561 }
|
|
562
|
|
563 // find the owning thread
|
|
564 if (owner != null) {
|
|
565 JSJavaFactory factory = getJSJavaFactory();
|
|
566 owningThread = (JSJavaThread) factory.newJSJavaThread(VM.getVM().getThreads().owningThreadFromMonitor(owner));
|
|
567 }
|
|
568 return owningThread;
|
|
569 }
|
|
570
|
|
571 /**
|
|
572 * Evaluate JavaScript source.
|
|
573 * @param filename the name of the file to compile, or null
|
|
574 * for interactive mode.
|
|
575 */
|
|
576 private void processSource(String filename) {
|
|
577 if (filename == null) {
|
|
578 BufferedReader in = getInputReader();
|
|
579 String sourceName = "<stdin>";
|
|
580 int lineno = 0;
|
|
581 boolean hitEOF = false;
|
|
582 do {
|
|
583 int startline = lineno;
|
|
584 printPrompt("jsdb> ");
|
|
585 Object source = read(EMPTY_ARRAY);
|
|
586 if (source == null) {
|
|
587 hitEOF = true;
|
|
588 break;
|
|
589 }
|
|
590 lineno++;
|
|
591 Object result = evalString(source.toString(), sourceName, startline);
|
|
592 if (result != null) {
|
|
593 printError(result.toString());
|
|
594 }
|
|
595 if (isQuitting()) {
|
|
596 // The user executed the quit() function.
|
|
597 break;
|
|
598 }
|
|
599 } while (!hitEOF);
|
|
600 } else {
|
|
601 Reader in = null;
|
|
602 try {
|
|
603 in = new BufferedReader(new FileReader(filename));
|
|
604 evalReader(in, filename);
|
|
605 } catch (FileNotFoundException ex) {
|
|
606 println("File '" + filename + "' not found");
|
|
607 throw new RuntimeException(ex);
|
|
608 }
|
|
609 }
|
|
610 }
|
|
611
|
|
612 protected Object evalString(String source, String filename, int lineNum) {
|
|
613 try {
|
|
614 engine.put(ScriptEngine.FILENAME, filename);
|
|
615 return engine.eval(source);
|
|
616 } catch (ScriptException sexp) {
|
|
617 printError(sexp.toString(), sexp);
|
|
618 } catch (Exception exp) {
|
|
619 printError(exp.toString(), exp);
|
|
620 }
|
|
621 return null;
|
|
622 }
|
|
623
|
|
624 private Object evalReader(Reader in, String filename) {
|
|
625 try {
|
|
626 engine.put(ScriptEngine.FILENAME, filename);
|
|
627 return engine.eval(in);
|
|
628 } catch (ScriptException sexp) {
|
|
629 System.err.println(sexp);
|
|
630 printError(sexp.toString(), sexp);
|
|
631 } finally {
|
|
632 try {
|
|
633 in.close();
|
|
634 } catch (IOException ioe) {
|
|
635 printError(ioe.toString(), ioe);
|
|
636 }
|
|
637 }
|
|
638 return null;
|
|
639 }
|
|
640
|
|
641 // lazily initialized input reader
|
|
642 private BufferedReader inReader;
|
|
643 // debug mode or not
|
|
644 protected final boolean debug;
|
|
645 private boolean quitting;
|
|
646 // underlying jsr-223 script engine
|
|
647 private ScriptEngine engine;
|
|
648 }
|