Call external javascript functions from java
--------------- RunScript.java ----------------- import java.io.*; import java.nio.file.*; import java.util.concurrent.*; import javax.script.*; import javafx.application.*; import javafx.stage.*; import javafx.scene.*; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.geometry.*; import javafx.scene.text.*; public class RunScript extends Application { ScriptEngine engine; long iniTime; CompiledScript compiledScript; boolean compiled = false; Future<?> future = null; ExecutorService executorService; @Override public void start(Stage stage) { String engineName = "JavaScript"; File file = new File("script.txt"); TextArea scriptArea = new TextArea(); TextArea resultArea = new TextArea(); resultArea.setEditable(false); Font font = Font.font("Monospaced"); scriptArea.setFont(font); resultArea.setFont(font); BorderPane layout = new BorderPane(); Scene scene = new Scene(layout, 900, 600); stage.setScene(scene); if (file.exists()) { try { scriptArea.appendText(new String(Files.readAllBytes(file.toPath()))); } catch (Exception e) {} } else scriptArea.setText(demoJavaScript()); scriptArea.home(); ScriptEngineManager manager = new ScriptEngineManager(); engine = manager.getEngineByName(engineName); if (engine == null) throw new RuntimeException("No script engine found for " + engineName); ScriptContext context = engine.getContext(); Writer writer = new Writer() { @Override public void write(char cbuf[], int off, int len) { String s = new String(cbuf, off, len); Platform.runLater(() -> { resultArea.appendText(s); }); } @Override public void flush() {} @Override public void close() {} }; context.setErrorWriter(writer); context.setWriter(writer); SplitPane splitPane = new SplitPane(scriptArea, resultArea); layout.setCenter(splitPane); BorderPane bottomPane = new BorderPane(); BorderPane.setMargin(bottomPane, new Insets(2)); Button button = new Button(); bottomPane.setLeft(button); button.setMinWidth(60); String stRun = "Run", stStop = "Stop"; button.setText(stRun); button.setOnAction((event) -> { button.setText(stStop); if (future != null && !future.isDone()) { future.cancel(true); button.setDisable(true); } else { resultArea.clear(); String script = new String(scriptArea.getText()); executorService = Executors.newSingleThreadExecutor((runnable) -> { Thread thread = new Thread(runnable); thread.setDaemon(true); return thread; }); future = executorService.submit(() -> { try { iniTime = System.currentTimeMillis(); if (engine instanceof Compilable) { if (!compiled) { compiledScript = ((Compilable)engine).compile(script); compiled = true; Platform.runLater(() -> { resultArea.appendText("Compile time: " + (System.currentTimeMillis() - iniTime) + " ms\n"); }); iniTime = System.currentTimeMillis(); } compiledScript.eval(); } else { engine.eval(script); } Platform.runLater(() -> { resultArea.appendText("Run time: " + (System.currentTimeMillis() - iniTime) + " ms\n"); }); } catch (Exception e) { Platform.runLater(() -> { resultArea.appendText(e.getMessage() + "\n"); }); } Platform.runLater(() -> { button.setText(stRun); button.setDisable(false); resultArea.setScrollTop(Double.MAX_VALUE); }); }); executorService.shutdown(); } }); layout.setBottom(bottomPane); scriptArea.textProperty().addListener((observable, oldValue, newValue) -> { compiled = false; }); stage.setOnCloseRequest(event -> { try { Files.write(file.toPath(), scriptArea.getText().getBytes()); } catch (Exception e) {} }); stage.show(); } String demoJavaScript() { StringBuilder sb = new StringBuilder(); sb.append("for (var angle = 0; angle <= Math.PI * 2; angle += .2) {\n"); sb.append(" var y = 15 * Math.sin(angle);\n"); sb.append(" if (y > 0) print(repeat(' ', 15) + repeat('*', y));\n"); sb.append(" else print(repeat(' ', 15 + y) + repeat('*', -y));\n"); sb.append(" //java.lang.Thread.sleep(100);\n"); sb.append(" sleep(100);\n"); sb.append("}\n\n"); sb.append("function repeat(s, n) {\n"); sb.append(" return new Array(Math.max(0, Math.floor(n)) + 1).join(s);\n"); sb.append("}\n\n"); sb.append("function sleep(milliseconds) {\n"); sb.append(" var ending = new Date().getTime() + milliseconds;\n"); sb.append(" while (new Date().getTime() < ending )\n"); sb.append(" if (java.lang.Thread.currentThread().isInterrupted())\n"); sb.append(" throw new java.lang.InterruptedException();\n"); sb.append("}\n\n"); return sb.toString(); } }