public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { return invokeImpl(proxy, method, args); } catch (TargetError te) { // Unwrap target exception. If the interface declares that // it throws the ex it will be delivered. If not it will be // wrapped in an UndeclaredThrowable throw te.getTarget(); } catch (EvalError ee) { // Ease debugging... // XThis.this refers to the enclosing class instance if (Interpreter.DEBUG) Interpreter.debug( "EvalError in scripted interface: " + XThis.this.toString() + ": " + ee); throw ee; } }
@Test public void misc_tests() throws Exception { Assert.assertEquals(true, TestUtil.eval("return true == true;")); Assert.assertEquals(true, TestUtil.eval("return false == false;")); Assert.assertEquals(false, TestUtil.eval("return true == false;")); Assert.assertEquals(false, TestUtil.eval("return false == true;")); try { TestUtil.eval("throw new RuntimeException();"); Assert.fail(); } catch (TargetError e) { Assert.assertTrue(e.getTarget().getClass() == RuntimeException.class); } Assert.assertEquals( "foobar", TestUtil.eval( "String a;", "try {", " a = \"foobar\";", "} catch (Exception e) {", " throw e;", "}", "return a;")); String script = "boolean fieldBool = false;\n" + "int fieldInt = 0;\n" + "Boolean fieldBool2 = false;\n" + "void run() {\n" + "fieldBool = ! fieldBool;\n" + "fieldBool2 = ! fieldBool2;\n" + "fieldInt++;\n" + "System.out.println(\"fieldBool: \"+fieldBool);\n" + "System.out.println(\"fieldBool2: \"+fieldBool2);\n" + "System.out.println(\"fieldInt: \"+fieldInt);\n" + "}\n"; Interpreter bsh = new Interpreter(); bsh.eval(script); Runnable runnable = (Runnable) bsh.getInterface(Runnable.class); runnable.run(); }
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()); } }