private static void endInterpreter(String contextId) throws EvalError { Interpreter i = interpreters.get(contextId); if (i == null) return; i.eval("clear();"); // can't hurt to tell bsh to clean up internally interpreters.remove(contextId); // now wait for GC Log.log("Destroyed context: " + contextId + " (" + i + ")"); }
/** * Runs a BeanShell script. Errors are passed to the caller. * * <p>If the <code>in</code> parameter is non-null, the script is read from that stream; otherwise * it is read from the file identified by <code>path</code> . * * <p>The <code>scriptPath</code> BeanShell variable is set to the path name of the script. * * @param path The script file's VFS path. * @param in The reader to read the script from, or <code>null</code> . * @param namespace The namespace to run the script in. * @exception Exception instances are thrown when various BeanShell errors occur * @since jEdit 4.2pre5 */ public void _runScript(String path, Reader in, NameSpace namespace) throws Exception { log.info("Running script " + path); Interpreter interp = createInterpreter(namespace); try { if (in == null) { in = res.getResourceAsReader(path); } setupDefaultVariables(namespace); interp.set("scriptPath", path); running = true; interp.eval(in, namespace, path); } catch (Exception e) { unwrapException(e); } finally { running = false; try { // no need to do this for macros! if (namespace == global) { resetDefaultVariables(namespace); interp.unset("scriptPath"); } } catch (EvalError e) { // do nothing } } } // }}}
static String getBshVersion() { if (bshVersion != null) return bshVersion; /* We have included a getVersion() command to detect the version of bsh. If bsh is packaged in the WAR file it could access it directly as a bsh command. But if bsh is in the app server's classpath it won't see it here, so we will source it directly. This command works around the lack of a coherent version number in the early versions. */ Interpreter bsh = new Interpreter(); try { bsh.eval(new InputStreamReader(BshServlet.class.getResource("getVersion.bsh").openStream())); bshVersion = (String) bsh.eval("getVersion()"); } catch (Exception e) { bshVersion = "BeanShell: unknown version"; } return bshVersion; }
Object evalScript( String script, StringBuffer scriptOutput, boolean captureOutErr, HttpServletRequest request, HttpServletResponse response) throws EvalError { // Create a PrintStream to capture output ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream pout = new PrintStream(baos); // Create an interpreter instance with a null inputstream, // the capture out/err stream, non-interactive Interpreter bsh = new Interpreter(null, pout, pout, false); // set up interpreter bsh.set("bsh.httpServletRequest", request); bsh.set("bsh.httpServletResponse", response); // Eval the text, gathering the return value or any error. Object result = null; String error = null; PrintStream sout = System.out; PrintStream serr = System.err; if (captureOutErr) { System.setOut(pout); System.setErr(pout); } try { // Eval the user text result = bsh.eval(script); } finally { if (captureOutErr) { System.setOut(sout); System.setErr(serr); } } pout.flush(); scriptOutput.append(baos.toString()); return result; }
public static void main(String args[]) throws Exception { Yylex l = null; parser p; Interpreter I; try { if (args.length == 0) l = new Yylex(System.in); else l = new Yylex(new FileReader(args[0])); } catch (FileNotFoundException e) { System.err.println("Error: File not found: " + args[0]); System.exit(1); } p = new parser(l); /* The default parser is the first-defined entry point. */ /* You may want to change this. Other options are: */ /* */ try { calc.Absyn.Exp parse_tree = p.pExp(); I = new Interpreter(); // I.eval(parse_tree) ; System.out.println(I.eval(parse_tree)); /*System.out.println(); System.out.println("Parse Succesful!"); System.out.println(); System.out.println("[Abstract Syntax]"); System.out.println(); System.out.println(PrettyPrinter.show(parse_tree)); System.out.println(); System.out.println("[Linearized Tree]"); System.out.println(); System.out.println(PrettyPrinter.print(parse_tree)); */ } catch (Throwable e) { System.err.println( "At line " + String.valueOf(l.line_num()) + ", near \"" + l.buff() + "\" :"); System.err.println(" " + e.getMessage()); System.exit(1); } }
/** * Evaluates the specified BeanShell expression. Unlike <code>eval()</code> , this method passes * any exceptions to the caller. * * @param namespace The namespace * @param command The expression * @return Description of the Return Value * @exception Exception instances are thrown when various BeanShell errors occur * @since jEdit 3.2pre7 */ public Object _eval(NameSpace namespace, String command) throws Exception { Interpreter interp = createInterpreter(namespace); try { setupDefaultVariables(namespace); if (log.isDebugEnabled()) { log.debug("Running script: " + command); } return interp.eval(command); } catch (Exception e) { unwrapException(e); // never called return null; } finally { // try { resetDefaultVariables(namespace); // } // catch (UtilEvalError e) { // do nothing // } } } // }}}
private static Interpreter getInterpreter(String contextId) throws EvalError { // Get the appropriate interpreter Interpreter i = null; boolean createdInterp = false; synchronized (interpreters) { // serialize two gets of the same name i = interpreters.get(contextId); if (i == null) { i = new Interpreter(); interpreters.put(contextId, i); createdInterp = true; } } if (createdInterp) { Log.log("Created context: " + contextId + " (" + i + ")"); // Now configure stdin and stdout to capture 10k of content // Store references to the circular buffers within the interpreter itself. // This provides a nice place to store them plus theoretically allows // advanced use from within the bsh environment. // On Windows print() outputs \r\n but in XQuery that's normalized to \n // so the 10k of Java buffer may produce less than 10k of content in XQuery! OutputStream circularOutput = new CircularByteArrayOutputStream(10240); PrintStream printOutput = new PrintStream(circularOutput); i.setOut(printOutput); i.set("mljamout", circularOutput); OutputStream circularError = new CircularByteArrayOutputStream(10240); PrintStream printError = new PrintStream(circularError); i.setErr(printError); i.set("mljamerr", circularError); // Capture the built-in System.out and System.err also. // (Commented out since System appears global, can't do per interpreter.) // i.set("mljamprintout", printOutput); // i.set("mljamprinterr", printError); // i.eval("System.setOut(mljamprintout);"); // i.eval("System.setErr(mljamprinterr);"); // Need to expose hexdecode() and base64decode() built-in functions i.eval("hexdecode(String s) { return com.xqdev.jam.MLJAM.hexDecode(s); }"); i.eval("base64decode(String s) { return com.xqdev.jam.MLJAM.base64Decode(s); }"); // Let's tell the context what its id is i.set("mljamid", contextId); } // Update the last accessed time, used for cleaning i.set("mljamlast", System.currentTimeMillis()); // If it's been long enough, go snooping for stale contexts if (System.currentTimeMillis() > lastClean + CLEAN_INTERVAL) { Log.log("Initiated periodic scan for stale context objects"); lastClean = System.currentTimeMillis(); Iterator<Interpreter> itr = interpreters.values().iterator(); while (itr.hasNext()) { Interpreter interp = itr.next(); Long last = (Long) interp.get("mljamlast"); if (System.currentTimeMillis() > last + STALE_TIMEOUT) { itr.remove(); Log.log("Staled context: " + interp.get("mljamid") + " (" + interp + ")"); } else if ((System.currentTimeMillis() > last + TEMP_STALE_TIMEOUT) && ("" + interp.get("mljamid")).startsWith("temp:")) { itr.remove(); Log.log("Staled temp context: " + interp.get("mljamid") + " (" + interp + ")"); } } } return i; }
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { // A good request looks like /mljam/contextid/verb?name=varname // The extra path info includes the context id and verb String extra = req.getPathInfo(); // "/contextid/verb" if (extra == null || extra.equals("")) { throw new ClientProblemException( "Request requires a context id and verb in its extra path info"); } String[] parts = extra.split("/"); // { "", "contextid", "verb" } if (parts.length < 2) { throw new ClientProblemException( "Request requires a context id and verb in its extra path info"); } else if (parts.length < 3) { throw new ClientProblemException("Request requires a verb in its extra path info"); } String contextId = parts[1]; String verb = parts[2]; String method = req.getMethod(); if (method.equalsIgnoreCase("get")) { // We have three GET verbs: get, get-stdout, get-stderr. // These are all idempotent, while the POST verbs aren't. The get // verb accept a "name" query string parameter. The get verb returns // either XQuery to evaluate (indicated by x-marklogic/xquery content type) // or a raw binary (indicated by an application/binary-encoded content type). if (verb.equalsIgnoreCase("get")) { String name = req.getParameter("name"); if (name == null || name.equals("")) { throw new ClientProblemException("The get verb requires a name parameter"); } Interpreter i = getInterpreter(contextId); Object o = i.get(name); if (o instanceof byte[]) { sendBinaryResponse(res, (byte[]) o); } else if (o instanceof String) { sendStringResponse(res, (String) o); } else { sendXQueryResponse(res, o); } } else if (verb.equalsIgnoreCase("get-stdout")) { Interpreter i = getInterpreter(contextId); i.getOut().flush(); CircularByteArrayOutputStream circ = (CircularByteArrayOutputStream) i.get("mljamout"); if (circ != null) { sendStringResponse(res, circ.toString()); circ.reset(); } else { throw new ServerProblemException("Could not fetch mljamout from interpreter context"); } } else if (verb.equalsIgnoreCase("get-stderr")) { Interpreter i = getInterpreter(contextId); i.getErr().flush(); CircularByteArrayOutputStream circ = (CircularByteArrayOutputStream) i.get("mljamerr"); if (circ != null) { sendStringResponse(res, circ.toString()); circ.reset(); } else { throw new ServerProblemException("Could not fetch mljamerr from interpreter context"); } } else { throw new ClientProblemException("Unrecognized GET verb: " + verb); } } else if (method.equalsIgnoreCase("post")) { // We have six POST verbs: eval, unset, end, source, set-string, and set-binary. // These are POST verbs because they aren't idempotent. // The set-string, set-binary, unset, and source verbs accept a "name" // query string parameter. The set-string and set-binary verbs accept // a value in their post body. The eval verb accepts code in its post body. if (verb.equalsIgnoreCase("set-string")) { String name = req.getParameter("name"); if (name == null || name.equals("")) { throw new ClientProblemException("The set-string verb requires a name parameter"); } String body = getBody(req); // a value of "" is legit Interpreter i = getInterpreter(contextId); i.unset(name); i.set(name, body); sendNoResponse(res); } else if (verb.equalsIgnoreCase("set-binary")) { String name = req.getParameter("name"); if (name == null || name.equals("")) { throw new ClientProblemException("The set-binary verb requires a name parameter"); } String body = getBody(req); // a value of "" is legit byte[] bodyBytes = hexDecode(body); // later could do this streaming for speed Interpreter i = getInterpreter(contextId); i.unset(name); i.set(name, bodyBytes); sendNoResponse(res); } else if (verb.equalsIgnoreCase("eval")) { String body = getBody(req); if (body == null || body.equals("")) { throw new ClientProblemException( "The eval verb requires a post body containing code to eval"); } Interpreter i = getInterpreter(contextId); i.eval(body); sendNoResponse(res); } else if (verb.equalsIgnoreCase("eval-get")) { String body = getBody(req); if (body == null || body.equals("")) { throw new ClientProblemException( "The eval-get verb requires a post body containing code to eval"); } Interpreter i = getInterpreter(contextId); Object o = i.eval(body); if (o instanceof byte[]) { sendBinaryResponse(res, (byte[]) o); } else if (o instanceof String) { sendStringResponse(res, (String) o); } else { sendXQueryResponse(res, o); } } else if (verb.equalsIgnoreCase("unset")) { String name = req.getParameter("name"); if (name == null || name.equals("")) { throw new ClientProblemException("The unset verb requires a name parameter"); } Interpreter i = getInterpreter(contextId); i.unset(name); sendNoResponse(res); } else if (verb.equalsIgnoreCase("end")) { endInterpreter(contextId); sendNoResponse(res); } else if (verb.equalsIgnoreCase("source")) { String name = req.getParameter("name"); if (name == null || name.equals("")) { throw new ClientProblemException("The source verb requires a name parameter"); } Interpreter i = getInterpreter(contextId); i.source(name); sendNoResponse(res); } else { throw new ClientProblemException("Unrecognized POST verb: " + verb); } } } catch (TargetError e) { Throwable target = e.getTarget(); Log.log(e); Log.log("Target: " + target); sendServerProblemResponse( res, target.getClass().getName() + ": " + target.getMessage() + " when executing Java code: " + e.getErrorText()); // include full trace? } catch (EvalError e) { Log.log(e); sendServerProblemResponse( res, e.getClass().getName() + ": " + e.getMessage()); // include full trace? } catch (ClientProblemException e) { Log.log(e); sendClientProblemResponse(res, e.getMessage()); } catch (ServerProblemException e) { Log.log(e); sendServerProblemResponse(res, e.getMessage()); } }