예제 #1
0
파일: MLJAM.java 프로젝트: paxtonhare/mljam
 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 + ")");
 }
예제 #2
0
  /**
   * 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
      }
    }
  } // }}}
예제 #3
0
 private String backgroundColour(String type) {
   LispExpr e = interpreter.getGlobalExpr(type);
   if (!(e instanceof LispString)) {
     e = interpreter.getGlobalExpr("text-background-colour");
     if (!(e instanceof LispString)) {
       return "white";
     }
   }
   return ((LispString) e).toString();
 }
예제 #4
0
  private void parseAndLoadInputs(String inputs) throws Exception {
    String inputTokens[] = inputs.split("\\s+");

    for (int i = 0; i < inputTokens.length; i++) {
      String token = inputTokens[i];

      if (token.equals("")) {
        continue;
      } else if (token.equals("true")) {
        _interpreter.boolStack().push(true);
        _interpreter.inputStack().push(true);
      } else if (token.equals("false")) {
        _interpreter.boolStack().push(false);
        _interpreter.inputStack().push(false);
      } else if (token.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")) {
        if (token.indexOf('.') != -1) {
          _interpreter.floatStack().push(Float.parseFloat(token));
          _interpreter.inputStack().push(Float.parseFloat(token));
        } else {
          _interpreter.intStack().push(Integer.parseInt(token));
          _interpreter.inputStack().push(Integer.parseInt(token));
        }
      } else {
        throw new Exception(
            "Inputs must be of type int, float, or boolean. \"" + token + "\" is none of these.");
      }
    }
  }
예제 #5
0
  public static void main(String argv[]) {
    // basically, if a command-line parameter is supplied
    // then assume it is a file name and execute it as
    // a simpular program without using the GUI at all.
    if (argv.length == 0) {
      // no command-line parameters, so use GUI.
      InterpreterFrame f = new InterpreterFrame();
    } else if (argv[0].equals("-no-gui")) {
      // run interpreter without GUI!

      // setup new argument list for original
      // Main method
      String[] newargv = new String[argv.length - 1];
      for (int i = 1; i != argv.length; ++i) {
        newargv[i - 1] = argv[i];
      }
      Interpreter.main(newargv);
    } else {
      // run interpreter with GUI, but
      // load requested file.

      InterpreterFrame f = new InterpreterFrame();
      // load file into text view
      f.textView.setText(f.physReadTextFile(new File(argv[0])));
      // update status
      f.statusView.setText(" Loaded file \"" + argv[0] + "\".");
      // reset dirty bit
      f.dirty = false;
    }
  }
예제 #6
0
  public static void main(String[] args) throws Exception {

    if (args.length < 1) {
      System.out.println("java ScalaInterpretNIO [script file]");
      return;
    }

    FileChannel fc = new FileInputStream(args[0]).getChannel();
    MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
    CharBuffer chb = Charset.defaultCharset().decode(buffer);

    Interpreter p = new Interpreter(new Settings());

    p.interpret(chb.toString());

    p.close();
  }
예제 #7
0
  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;
  }
예제 #8
0
  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;
  }
예제 #9
0
  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);
    }
  }
예제 #10
0
  /**
   * 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
      // }
    }
  } // }}}
 public void run(String path) {
   if (path == null || path.equals("")) path = showDialog();
   if (path == null) return;
   openingStartupMacrosInEditor = path.indexOf("StartupMacros") != -1;
   String text = open(path);
   if (text != null) {
     String functions = Interpreter.getAdditionalFunctions();
     if (functions != null) {
       if (!(text.endsWith("\n") || functions.startsWith("\n"))) text = text + "\n" + functions;
       else text = text + functions;
     }
     install(text);
   }
 }
예제 #12
0
  private void checkForInputIn(String programString) {
    String added = "";
    String numstr = "";
    int index = 0;
    int numindex = 0;
    int spaceindex = 0;
    int parenindex = 0;
    int endindex = 0;

    while (true) {

      index = programString.indexOf("input.in");
      if (index == -1) break;

      // System.out.println(programString + "    " + index);

      numindex = index + 8;
      if (!Character.isDigit(programString.charAt(numindex))) {
        programString = programString.substring(numindex);
        continue;
      }

      spaceindex = programString.indexOf(' ', numindex);
      parenindex = programString.indexOf(')', numindex);
      if (spaceindex == -1) endindex = parenindex;
      else if (parenindex == -1) endindex = spaceindex;
      else endindex = Math.min(spaceindex, parenindex);

      numstr = programString.substring(numindex, endindex);

      // Check for doubles in added
      if (added.indexOf(" " + numstr + " ") == -1) {
        added = added + " " + numstr + " ";
        _interpreter.AddInstruction("input.in" + numstr, new InputInN(Integer.parseInt(numstr)));
      }

      programString = programString.substring(numindex);
    }
  }
예제 #13
0
  public InterpreterFrame() {
    super("Simple Lisp Interpreter");

    // Create the menu
    menubar = buildMenuBar();
    setJMenuBar(menubar);
    // Create the toolbar
    toolbar = buildToolBar();
    // disable cut and copy actions
    cutAction.setEnabled(false);
    copyAction.setEnabled(false);
    // Setup text area for editing source code
    // and setup document listener so interpreter
    // is notified when current file modified and
    // when the cursor is moved.
    textView = buildEditor();
    textView.getDocument().addDocumentListener(this);
    textView.addCaretListener(this);

    // set default key bindings
    bindKeyToCommand("ctrl C", "(buffer-copy)");
    bindKeyToCommand("ctrl X", "(buffer-cut)");
    bindKeyToCommand("ctrl V", "(buffer-paste)");
    bindKeyToCommand("ctrl E", "(buffer-eval)");
    bindKeyToCommand("ctrl O", "(file-open)");
    bindKeyToCommand("ctrl S", "(file-save)");
    bindKeyToCommand("ctrl Q", "(exit)");

    // Give text view scrolling capability
    Border border =
        BorderFactory.createCompoundBorder(
            BorderFactory.createEmptyBorder(3, 3, 3, 3),
            BorderFactory.createLineBorder(Color.gray));
    JScrollPane topSplit = addScrollers(textView);
    topSplit.setBorder(border);

    // Create tabbed pane for console/problems
    consoleView = makeConsoleArea(10, 50, true);
    problemsView = makeConsoleArea(10, 50, false);
    tabbedPane = buildProblemsConsole();

    // Plug the editor and problems/console together
    // using a split pane. This allows one to change
    // their relative size using the split-bar in
    // between them.
    splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topSplit, tabbedPane);

    // Create status bar
    statusView = new JLabel(" Status");
    lineNumberView = new JLabel("0:0");
    statusbar = buildStatusBar();

    // Now, create the outer panel which holds
    // everything together
    outerpanel = new JPanel();
    outerpanel.setLayout(new BorderLayout());
    outerpanel.add(toolbar, BorderLayout.PAGE_START);
    outerpanel.add(splitPane, BorderLayout.CENTER);
    outerpanel.add(statusbar, BorderLayout.SOUTH);
    getContentPane().add(outerpanel);

    // tell frame to fire a WindowsListener event
    // but not to close when "x" button clicked.
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    addWindowListener(this);
    // set minimised icon to use
    setIconImage(makeImageIcon("spi.png").getImage());

    // setup additional internal functions
    InternalFunctions.setup_internals(interpreter, this);

    // set default window size
    Component top = splitPane.getTopComponent();
    Component bottom = splitPane.getBottomComponent();
    top.setPreferredSize(new Dimension(100, 400));
    bottom.setPreferredSize(new Dimension(100, 200));
    pack();

    // load + run user configuration file (if there is one)
    String homedir = System.getProperty("user.home");
    try {
      interpreter.load(homedir + "/.simplelisp");
    } catch (FileNotFoundException e) {
      // do nothing if file does not exist!
      System.out.println("Didn't find \"" + homedir + "/.simplelisp\"");
    }

    textView.grabFocus();
    setVisible(true);

    // redirect all I/O to problems/console
    redirectIO();

    // start highlighter thread
    highlighter = new DisplayThread(250);
    highlighter.setDaemon(true);
    highlighter.start();
  }
예제 #14
0
  /**
   * Initializes an InspectorInput. The file should be organized as follows:
   *
   * <p>1 Program to execute 2 Execution limit 3 Integer, float, or boolean inputs 4 Available
   * instructions. This is only used for creating random code with code.rand or exec.rand
   *
   * @param inFile The file to input from.
   */
  private void InitInspectorInput(File inFile) throws Exception {
    _interpreter = new Interpreter();

    // Read fileString
    String fileString = Params.ReadFileString(inFile);

    // Get programString
    int indexNewline = fileString.indexOf("\n");
    String programString = fileString.substring(0, indexNewline).trim();
    fileString = fileString.substring(indexNewline + 1);

    // Get _executionLimit
    indexNewline = fileString.indexOf("\n");
    if (indexNewline != -1) {
      String limitString = fileString.substring(0, indexNewline).trim();

      _executionLimit = Integer.parseInt(limitString);
      fileString = fileString.substring(indexNewline + 1);
    } else {
      // If here, no inputs to be pushed were included
      _executionLimit = Integer.parseInt(fileString);
      fileString = "";
    }

    // Get inputs and push them onto correct stacks. If fileString = ""
    // at this point, then can still do the following with correct result.
    indexNewline = fileString.indexOf("\n");
    if (indexNewline != -1) {
      String inputsString = fileString.substring(0, indexNewline).trim();
      fileString = fileString.substring(indexNewline + 1);

      // Parse the inputs and load them into the interpreter
      parseAndLoadInputs(inputsString);
    } else {
      parseAndLoadInputs(fileString);
      fileString = "";
    }

    // Get the available instructions for random code generation
    indexNewline = fileString.indexOf("\n");
    if (!fileString.trim().equals("")) {
      _interpreter.SetInstructions(new Program(_interpreter, fileString.trim()));
    }

    // Check for input.inN instructions
    checkForInputIn(programString);

    // Add random integer and float parameters
    _interpreter._minRandomInt = -10;
    _interpreter._maxRandomInt = 10;
    _interpreter._randomIntResolution = 1;
    _interpreter._minRandomFloat = -10.0f;
    _interpreter._maxRandomFloat = 10.0f;
    _interpreter._randomFloatResolution = 0.01f;

    _interpreter._maxRandomCodeSize = 50;

    // Load the program
    _program = new Program(_interpreter, programString);
    _interpreter.LoadProgram(_program); // Initializes program
  }
예제 #15
0
  /**
   * Parse the BSHBlock for for the class definition and generate the class using ClassGenerator.
   */
  public static Class generateClassImpl(
      String name,
      Modifiers modifiers,
      Class[] interfaces,
      Class superClass,
      BSHBlock block,
      boolean isInterface,
      CallStack callstack,
      Interpreter interpreter)
      throws EvalError {
    // Scripting classes currently requires accessibility
    // This can be eliminated with a bit more work.
    try {
      Capabilities.setAccessibility(true);
    } catch (Capabilities.Unavailable e) {
      throw new EvalError(
          "Defining classes currently requires reflective Accessibility.", block, callstack);
    }

    NameSpace enclosingNameSpace = callstack.top();
    String packageName = enclosingNameSpace.getPackage();
    String className =
        enclosingNameSpace.isClass ? (enclosingNameSpace.getName() + "$" + name) : name;
    String fqClassName = packageName == null ? className : packageName + "." + className;

    BshClassManager bcm = interpreter.getClassManager();
    // Race condition here...
    bcm.definingClass(fqClassName);

    // Create the class static namespace
    NameSpace classStaticNameSpace = new NameSpace(enclosingNameSpace, className);
    classStaticNameSpace.isClass = true;

    callstack.push(classStaticNameSpace);

    // Evaluate any inner class class definitions in the block
    // effectively recursively call this method for contained classes first
    block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSCLASSES);

    // Generate the type for our class
    Variable[] variables = getDeclaredVariables(block, callstack, interpreter, packageName);
    DelayedEvalBshMethod[] methods = getDeclaredMethods(block, callstack, interpreter, packageName);

    ClassGeneratorUtil classGenerator =
        new ClassGeneratorUtil(
            modifiers,
            className,
            packageName,
            superClass,
            interfaces,
            variables,
            methods,
            classStaticNameSpace,
            isInterface);
    byte[] code = classGenerator.generateClass();

    // if debug, write out the class file to debugClasses directory
    if (DEBUG_DIR != null)
      try {
        FileOutputStream out = new FileOutputStream(DEBUG_DIR + '/' + className + ".class");
        out.write(code);
        out.close();
      } catch (IOException e) {
        throw new IllegalStateException(
            "cannot create file " + DEBUG_DIR + '/' + className + ".class", e);
      }

    // Define the new class in the classloader
    Class genClass = bcm.defineClass(fqClassName, code);

    // import the unq name into parent
    enclosingNameSpace.importClass(fqClassName.replace('$', '.'));

    try {
      classStaticNameSpace.setLocalVariable(
          ClassGeneratorUtil.BSHINIT, block, false /*strictJava*/);
    } catch (UtilEvalError e) {
      throw new InterpreterError("unable to init static: " + e);
    }

    // Give the static space its class static import
    // important to do this after all classes are defined
    classStaticNameSpace.setClassStatic(genClass);

    // evaluate the static portion of the block in the static space
    block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSSTATIC);

    callstack.pop();

    if (!genClass.isInterface()) {
      // Set the static bsh This callback
      String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC + className;
      try {
        LHS lhs = Reflect.getLHSStaticField(genClass, bshStaticFieldName);
        lhs.assign(classStaticNameSpace.getThis(interpreter), false /*strict*/);
      } catch (Exception e) {
        throw new InterpreterError("Error in class gen setup: " + e);
      }
    }

    bcm.doneDefiningClass(fqClassName);
    return genClass;
  }
 public void installLibrary(String path) {
   String text = open(path);
   if (text != null) Interpreter.setAdditionalFunctions(text);
 }
예제 #17
0
파일: MLJAM.java 프로젝트: paxtonhare/mljam
  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;
  }
예제 #18
0
파일: MLJAM.java 프로젝트: paxtonhare/mljam
  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());
    }
  }