protected static int run(String message, String[] commandArray, File outputFile) {
   PrintStream out = System.out;
   PrintStream err = System.err;
   PrintStream fileStream = null;
   try {
     outputFile.getParentFile().mkdirs();
     fileStream = new PrintStream(new FileOutputStream(outputFile));
     System.setErr(fileStream);
     System.setOut(fileStream);
     return run(message, commandArray);
   } catch (FileNotFoundException e) {
     return -1;
   } finally {
     System.setOut(out);
     System.setErr(err);
     if (fileStream != null) fileStream.close();
   }
 }
  /*
   * Accepts a new request from the HTTP server and creates
   * a conventional execution environment for the request.
   * If the application was invoked as a FastCGI server,
   * the first call to FCGIaccept indicates that the application
   * has completed its initialization and is ready to accept
   * a request.  Subsequent calls to FCGI_accept indicate that
   * the application has completed its processing of the
   * current request and is ready to accept a new request.
   * If the application was invoked as a CGI program, the first
   * call to FCGIaccept is essentially a no-op and the second
   * call returns EOF (-1) as does an error. Application should exit.
   *
   * If the application was invoked as a FastCGI server,
   * and this is not the first call to this procedure,
   * FCGIaccept first flushes any buffered output to the HTTP server.
   *
   * On every call, FCGIaccept accepts the new request and
   * reads the FCGI_PARAMS stream into System.props. It also creates
   * streams that understand FastCGI protocol and take input from
   * the HTTP server send output and error output to the HTTP server,
   * and assigns these new streams to System.in, System.out and
   * System.err respectively.
   *
   * For now, we will just return an int to the caller, which is why
   * this method catches, but doen't throw Exceptions.
   *
   */
  public int FCGIaccept() {
    int acceptResult = 0;

    /*
     * If first call, mark it and if fcgi save original system properties,
     * If not first call, and  we are cgi, we should be gone.
     */
    if (!acceptCalled) {
      isFCGI = System.getenv("FCGI_PORT") != null;
      acceptCalled = true;
      if (isFCGI) {
        /*
         * save original system properties (nonrequest)
         * and get a server socket
         */
        startupProps = new Properties(System.getProperties());
        String str = new String(System.getenv("FCGI_PORT"));
        if (str.length() <= 0) {
          return -1;
        }
        int portNum = Integer.parseInt(str);

        try {
          srvSocket = new ServerSocket(portNum);
        } catch (IOException e) {
          if (request != null) {
            request.socket = null;
          }
          srvSocket = null;
          request = null;
          return -1;
        }
      }
    } else {
      if (!isFCGI) {
        return -1;
      }
    }
    /*
     * If we are cgi, just leave everything as is, otherwise set up env
     */
    if (isFCGI) {
      try {
        acceptResult = FCGIAccept();
      } catch (IOException e) {
        return -1;
      }
      if (acceptResult < 0) {
        return -1;
      }

      /*
       * redirect stdin, stdout and stderr to fcgi socket
       */
      System.setIn(new BufferedInputStream(request.inStream, 8192));
      System.setOut(new PrintStream(new BufferedOutputStream(request.outStream, 8192)));
      System.setErr(new PrintStream(new BufferedOutputStream(request.errStream, 512)));
      System.setProperties(request.params);
    }
    return 0;
  }
  public static void main() {
    // Main
    frame = new JFrame("Java Playground");
    frame.setSize(640, 480);
    // Make sure the divider is properly resized
    frame.addComponentListener(
        new ComponentAdapter() {
          public void componentResized(ComponentEvent c) {
            splitter.setDividerLocation(.8);
          }
        });
    // Make sure the JVM is reset on close
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosed(WindowEvent w) {
            new FrameAction().kill();
          }
        });

    // Setting up the keybinding
    // Ctrl+k or Cmd+k -> compile
    bind(KeyEvent.VK_K);

    // Ctrl+e or Cmd+e -> console
    bind(KeyEvent.VK_E);

    // Save, New file, Open file, Print.
    // Currently UNUSED until I figure out how normal java files and playground files will
    // interface.
    bind(KeyEvent.VK_S);
    bind(KeyEvent.VK_N);
    bind(KeyEvent.VK_O);
    bind(KeyEvent.VK_P);

    // Binds the keys to the action defined in the FrameAction class.
    frame.getRootPane().getActionMap().put("console", new FrameAction());

    // The main panel for typing code in.
    text = new JTextPane();
    textScroll = new JScrollPane(text);
    textScroll.setBorder(null);
    textScroll.setPreferredSize(new Dimension(640, 480));

    // Document with syntax highlighting. Currently unfinished.
    doc = text.getStyledDocument();
    doc.addDocumentListener(
        new DocumentListener() {
          public void changedUpdate(DocumentEvent d) {}

          public void insertUpdate(DocumentEvent d) {}

          public void removeUpdate(DocumentEvent d) {}
        });

    ((AbstractDocument) doc).setDocumentFilter(new NewLineFilter());

    // The output log; a combination compiler warning/error/runtime error/output log.
    outputText = new JTextPane();
    outputScroll = new JScrollPane(outputText);
    outputScroll.setBorder(null);

    // "Constant" for the error font
    error = new SimpleAttributeSet();
    error.addAttribute(StyleConstants.CharacterConstants.Italic, Boolean.TRUE);
    error.addAttribute(StyleConstants.Foreground, Color.RED);

    // "Constant" for the warning message font
    warning = new SimpleAttributeSet();
    warning.addAttribute(StyleConstants.CharacterConstants.Italic, Boolean.TRUE);
    warning.addAttribute(StyleConstants.Foreground, Color.PINK);

    // "Constant" for the debugger error font
    progErr = new SimpleAttributeSet();
    progErr.addAttribute(StyleConstants.Foreground, Color.BLUE);

    // Print streams to redirect System.out and System.err.
    out = new TextOutputStream(outputText, null);
    err = new TextOutputStream(outputText, error);
    System.setOut(new PrintStream(out));
    System.setErr(new PrintStream(err));

    // Sets up the output log
    outputText.setEditable(false);
    outputScroll.setVisible(true);

    // File input/output setup
    chooser = new JFileChooser();

    // Setting up miscellaneous stuff
    compiler = ToolProvider.getSystemJavaCompiler();
    JVMrunning = false;
    redirectErr = null;
    redirectOut = null;
    redirectIn = null;

    // Sets up the splitter pane and opens the program up
    splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textScroll, outputScroll);
    consoleDisplayed = false;
    splitter.remove(outputScroll); // Initially hides terminal until it is needed
    splitter.setOneTouchExpandable(true);
    frame.add(splitter);
    frame.setVisible(true);

    // Sets the divider to the proper one, for debugging
    // splitter.setDividerLocation(.8);
  }