Esempio n. 1
0
  private void doSave(WebPageContext page) throws IOException, ServletException {
    if (!page.isFormPost()) {
      throw new IllegalArgumentException("Must post!");
    }

    new DebugFilter.PageWriter(page) {
      {
        File file = getFile(page);
        Preconditions.checkNotNull(file);
        String code = page.paramOrDefault(String.class, "code", "");

        try {
          CLASS_FOUND:
          if (file.isDirectory()) {
            Object result = evaluateJava(page.getServletContext(), code);

            if (result instanceof Collection) {
              for (Object item : (Collection<?>) result) {
                if (item instanceof Class) {
                  file =
                      new File(
                          file,
                          ((Class<?>) item).getName().replace('.', File.separatorChar) + ".java");
                  IoUtils.createParentDirectories(file);
                  break CLASS_FOUND;
                }
              }
            }

            throw new IllegalArgumentException("Syntax error!");
          }

          IoUtils.createFile(file);

          FileOutputStream fileOutput = new FileOutputStream(file);

          try {
            fileOutput.write(code.replaceAll("(?:\r\n|[\r\n])", "\n").getBytes("UTF-8"));
            writeStart("p", "class", "alert alert-success");
            writeHtml("Saved Successfully! (");
            writeObject(new Date());
            writeHtml(")");
            writeEnd();

          } finally {
            fileOutput.close();
          }

        } catch (Exception ex) {
          writeStart("pre", "class", "alert alert-error");
          writeObject(ex);
          writeEnd();
        }
      }
    };
  }
Esempio n. 2
0
  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {

    WebPageContext page = new WebPageContext(this, request, response);
    String action = page.param(String.class, "action");

    if ("run".equals(action)) {
      if (page.param(String.class, "isSave") != null) {
        doSave(page);

      } else {
        page.paramOrDefault(Type.class, "type", Type.JAVA).run(page);
      }

    } else {
      doEdit(page);
    }
  }
Esempio n. 3
0
  private static File getFile(WebPageContext page) throws IOException {
    String file = page.param(String.class, "file");

    if (file == null) {
      String servletPath = page.param(String.class, "servletPath");

      if (servletPath != null) {
        file = page.getServletContext().getRealPath(servletPath);
      }
    }

    if (file == null) {
      return null;
    }

    File fileInstance = new File(file);

    if (!fileInstance.exists()) {
      IoUtils.createParentDirectories(fileInstance);
    }

    return fileInstance;
  }
Esempio n. 4
0
  private void doEdit(WebPageContext page) throws IOException, ServletException {
    final Type type = page.paramOrDefault(Type.class, "type", Type.JAVA);
    final File file = getFile(page);
    final StringBuilder codeBuilder = new StringBuilder();

    if (file != null) {
      if (file.exists()) {
        if (file.isDirectory()) {
          // Can't edit a directory.

        } else {
          codeBuilder.append(IoUtils.toString(file, StandardCharsets.UTF_8));
        }

      } else {
        String filePath = file.getPath();

        if (filePath.endsWith(".java")) {
          filePath = filePath.substring(0, filePath.length() - 5);

          for (File sourceDirectory : CodeUtils.getSourceDirectories()) {
            String sourceDirectoryPath = sourceDirectory.getPath();

            if (filePath.startsWith(sourceDirectoryPath)) {
              String classPath = filePath.substring(sourceDirectoryPath.length());

              if (classPath.startsWith(File.separator)) {
                classPath = classPath.substring(1);
              }

              int lastSepAt = classPath.lastIndexOf(File.separatorChar);

              if (lastSepAt < 0) {
                codeBuilder.append("public class ");
                codeBuilder.append(classPath);

              } else {
                codeBuilder.append("package ");
                codeBuilder.append(
                    classPath.substring(0, lastSepAt).replace(File.separatorChar, '.'));
                codeBuilder.append(";\n\npublic class ");
                codeBuilder.append(classPath.substring(lastSepAt + 1));
              }

              codeBuilder.append(" {\n}");
              break;
            }
          }
        }
      }

    } else {
      Set<String> imports = findImports();

      imports.add("com.psddev.dari.db.*");
      imports.add("com.psddev.dari.util.*");
      imports.add("java.util.*");

      String includes = Settings.get(String.class, INCLUDE_IMPORTS_SETTING);

      if (!ObjectUtils.isBlank(includes)) {
        Collections.addAll(imports, includes.trim().split("\\s*,?\\s+"));
      }

      String excludes = Settings.get(String.class, EXCLUDE_IMPORTS_SETTING);

      if (!ObjectUtils.isBlank(excludes)) {
        for (String exclude : excludes.trim().split("\\s*,?\\s+")) {
          imports.remove(exclude);
        }
      }

      for (String i : imports) {
        codeBuilder.append("import ");
        codeBuilder.append(i);
        codeBuilder.append(";\n");
      }

      codeBuilder.append('\n');
      codeBuilder.append("public class Code {\n");
      codeBuilder.append("    public static Object main() throws Throwable {\n");

      String query = page.param(String.class, "query");
      String objectClass = page.paramOrDefault(String.class, "objectClass", "Object");

      if (query == null) {
        codeBuilder.append("        return null;\n");

      } else {
        codeBuilder
            .append("        Query<")
            .append(objectClass)
            .append("> query = ")
            .append(query)
            .append(";\n");
        codeBuilder
            .append("        PaginatedResult<")
            .append(objectClass)
            .append("> result = query.select(0L, 10);\n");
        codeBuilder.append("        return result;\n");
      }

      codeBuilder.append("    }\n");
      codeBuilder.append("}\n");
    }

    new DebugFilter.PageWriter(page) {
      {
        List<Object> inputs = CodeDebugServlet.Static.getInputs(getServletContext());
        Object input = inputs == null || inputs.isEmpty() ? null : inputs.get(0);
        String name;

        if (file == null) {
          name = null;

        } else {
          name = file.toString();
          int slashAt = name.lastIndexOf('/');

          if (slashAt > -1) {
            name = name.substring(slashAt + 1);
          }
        }

        startPage("Code Editor", name);
        writeStart("div", "class", "row-fluid");

        if (input != null) {
          writeStart(
              "div",
              "class",
              "codeInput",
              "style",
              "bottom: 65px; position: fixed; top: 55px; width: 18%; z-index: 1000;");
          writeStart("h2").writeHtml("Input").writeEnd();
          writeStart(
              "div",
              "style",
              "bottom: 0; overflow: auto; position: absolute; top: 38px; width: 100%;");
          writeObject(input);
          writeEnd();
          writeEnd();
          writeStart("style", "type", "text/css");
          write(".codeInput pre { white-space: pre; word-break: normal; word-wrap: normal; }");
          writeEnd();
          writeStart("script", "type", "text/javascript");
          write("$('.codeInput').hover(function() {");
          write("$(this).css('width', '50%');");
          write("}, function() {");
          write("$(this).css('width', '18%');");
          write("});");
          writeEnd();
        }

        writeStart(
            "div",
            "class",
            input != null ? "span9" : "span12",
            "style",
            input != null ? "margin-left: 20%" : null);
        writeStart(
            "form",
            "action",
            page.url(null),
            "class",
            "code",
            "method",
            "post",
            "style",
            "margin-bottom: 70px;",
            "target",
            "result");
        writeElement("input", "name", "action", "type", "hidden", "value", "run");
        writeElement("input", "name", "type", "type", "hidden", "value", type);
        writeElement("input", "name", "file", "type", "hidden", "value", file);
        writeElement(
            "input",
            "name",
            "jspPreviewUrl",
            "type",
            "hidden",
            "value",
            page.param(String.class, "jspPreviewUrl"));

        writeStart("textarea", "name", "code");
        writeHtml(codeBuilder);
        writeEnd();
        writeStart(
            "div",
            "class",
            "form-actions",
            "style",
            "bottom: 0; left: 0; margin: 0; padding: 10px 20px; position:fixed; right: 0; z-index: 1000;");
        writeElement("input", "class", "btn btn-primary", "type", "submit", "value", "Run");
        writeStart(
            "label",
            "class",
            "checkbox",
            "style",
            "display: inline-block; margin-left: 10px; white-space: nowrap;");
        writeElement("input", "name", "isLiveResult", "type", "checkbox");
        writeHtml("Live Result");
        writeEnd();
        writeStart(
            "label",
            "style",
            "display: inline-block; margin-left: 10px; white-space: nowrap;",
            "title",
            "Shortcut: ?_vim=true");
        boolean vimMode = page.param(boolean.class, "_vim");
        writeStart(
            "label",
            "class",
            "checkbox",
            "style",
            "display: inline-block; margin-left: 10px; white-space: nowrap;");
        writeElement(
            "input",
            "name",
            "_vim",
            "type",
            "checkbox",
            "value",
            "true",
            vimMode ? "checked" : "_unchecked",
            "true");
        writeHtml("Vim Mode");
        writeEnd();
        writeEnd();
        writeElement(
            "input",
            "class",
            "btn btn-success pull-right",
            "name",
            "isSave",
            "type",
            "submit",
            "value",
            "Save");
        writeElement(
            "input",
            "class",
            "btn pull-right",
            "style",
            "margin-right: 10px;",
            "name",
            "clearCode",
            "type",
            "submit",
            "value",
            "Clear");
        writeEnd();
        writeEnd();

        writeStart(
            "div",
            "class",
            "resultContainer",
            "style",
            "background: rgba(255, 255, 255, 0.8);"
                + "border-color: rgba(0, 0, 0, 0.2);"
                + "border-style: solid;"
                + "border-width: 0 0 0 1px;"
                + "max-height: 45%;"
                + "top: 55px;"
                + "overflow: auto;"
                + "padding: 0px 20px 5px 10px;"
                + "position: fixed;"
                + "z-index: 3;"
                + "right: 0px;"
                + "width: 35%;");
        writeStart("h2").writeHtml("Result").writeEnd();
        writeStart("div", "class", "frame", "name", "result");
        writeEnd();
        writeEnd();

        writeStart("script", "type", "text/javascript");
        write("$('body').frame();");
        write("var $codeForm = $('form.code');");

        write("var lineMarkers = [ ];");
        write("var columnMarkers = [ ];");
        write("var codeMirror = CodeMirror.fromTextArea($('textarea')[0], {");
        write("'indentUnit': 4,");
        write("'lineNumbers': true,");
        write("'lineWrapping': true,");
        write("'matchBrackets': true,");
        write("'mode': 'text/x-java'");
        write("});");

        // Save code to local storage when the user stops typing for 1 second
        write("if (window.localStorage !== undefined) {");
        write("var baseCode = $('textarea[name=code]').text();");

        write("var windowStorageCodeKey = 'bsp.codeDebugServlet.code';");
        write(
            "if (window.localStorage.getItem(windowStorageCodeKey) !== null && window.localStorage.getItem(windowStorageCodeKey).trim()) {");
        write("codeMirror.getDoc().setValue(window.localStorage.getItem(windowStorageCodeKey))");
        write("}");

        write("var typingTimer;");
        write("codeMirror.on('keydown', function() {");
        write("clearTimeout(typingTimer);");
        write("});");
        write("codeMirror.on('keyup', function() {");
        write("clearTimeout(typingTimer);");
        write("typingTimer = setTimeout(function(){");
        write(
            "window.localStorage.setItem(windowStorageCodeKey, codeMirror.getDoc().getValue());},");
        write("1000);");
        write("});");
        write("}");

        // Reset code to original page load value and clear window storage
        write("$('.form-actions input[name=clearCode]').on('click', function(e) {");
        write("e.preventDefault();");
        write("if (baseCode !== undefined && baseCode.trim()) {");
        write("codeMirror.getDoc().setValue(baseCode);");
        write("if (window.localStorage !== undefined) {");
        write("window.localStorage.removeItem(windowStorageCodeKey);");
        write("}");
        write("}");
        write("});");

        write("codeMirror.on('change', $.throttle(1000, function() {");
        write("if ($codeForm.find(':checkbox[name=isLiveResult]').is(':checked')) {");
        write("$codeForm.submit();");
        write("}");
        write("}));");

        write("$('input[name=_vim]').change(function() {");
        write("codeMirror.setOption('vimMode', $(this).is(':checked'));");
        write("});");
        write("$('input[name=_vim]').change();");

        int line = page.param(int.class, "line");
        if (line > 0) {
          write("var line = ");
          write(String.valueOf(line));
          write(" - 1;");
          write("codeMirror.setCursor(line);");
          write("codeMirror.addLineClass(line, 'selected', 'selected');");
          write("$(window).scrollTop(codeMirror.cursorCoords().top - $(window).height() / 2);");
        }

        write("var $resultContainer = $('.resultContainer');");
        write("$resultContainer.find('.frame').bind('load', function() {");
        write(
            "$.each(lineMarkers, function() { codeMirror.clearMarker(this); codeMirror.setLineClass(this, null, null); });");
        write("$.each(columnMarkers, function() { this.clear(); });");
        write("var $frame = $(this).find('.syntaxErrors li').each(function() {");
        write("var $error = $(this);");
        write("var line = parseInt($error.attr('data-line')) - 1;");
        write("var column = parseInt($error.attr('data-column')) - 1;");
        write("if (line > -1 && column > -1) {");
        write("lineMarkers.push(codeMirror.setMarker(line, '!'));");
        write("codeMirror.setLineClass(line, 'errorLine', 'errorLine');");
        write(
            "columnMarkers.push(codeMirror.markText({ 'line': line, 'ch': column }, { 'line': line, 'ch': column + 1 }, 'errorColumn'));");
        write("}");
        write("});");
        write("});");
        writeEnd();

        writeEnd();
        writeEnd();
        endPage();
      }

      @Override
      public void startBody(String... titles) throws IOException {
        writeStart("body");
        writeStart("div", "class", "navbar navbar-fixed-top");
        writeStart("div", "class", "navbar-inner");
        writeStart("div", "class", "container-fluid");
        writeStart("span", "class", "brand");
        writeStart("a", "href", DebugFilter.Static.getServletPath(page.getRequest(), ""));
        writeHtml("Dari");
        writeEnd();
        writeHtml("Code Editor \u2192 ");
        writeEnd();

        writeStart(
            "form",
            "action",
            page.url(null),
            "method",
            "get",
            "style",
            "float: left; height: 40px; line-height: 40px; margin: 0; padding-left: 10px;");
        writeStart(
            "select",
            "class",
            "span6",
            "name",
            "file",
            "onchange",
            "$(this).closest('form').submit();");
        writeStart("option", "value", "");
        writeHtml("PLAYGROUND");
        writeEnd();
        for (File sourceDirectory : CodeUtils.getSourceDirectories()) {
          writeStart("optgroup", "label", sourceDirectory);
          writeStart(
              "option",
              "selected",
              sourceDirectory.equals(file) ? "selected" : null,
              "value",
              sourceDirectory);
          writeHtml("NEW CLASS IN ").writeHtml(sourceDirectory);
          writeEnd();
          writeFileOption(file, sourceDirectory, sourceDirectory);
          writeEnd();
        }
        writeEnd();
        writeEnd();

        includeStylesheet("/_resource/chosen/chosen.css");
        includeScript("/_resource/chosen/chosen.jquery.min.js");
        writeStart("script", "type", "text/javascript");
        write("(function() {");
        write("$('select[name=file]').chosen({ 'search_contains': true });");
        write("})();");
        writeEnd();
        writeEnd();
        writeEnd();
        writeEnd();
        writeStart("div", "class", "container-fluid", "style", "padding-top: 54px;");
      }

      private void writeFileOption(File file, File sourceDirectory, File source)
          throws IOException {
        if (source.isDirectory()) {
          for (File child : source.listFiles()) {
            writeFileOption(file, sourceDirectory, child);
          }

        } else {
          writeStart(
              "option", "selected", source.equals(file) ? "selected" : null, "value", source);
          writeHtml(source.toString().substring(sourceDirectory.toString().length()));
          writeEnd();
        }
      }
    };
  }