package betsy.tools; import java.awt.Desktop; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.LinkedList; import java.util.List; import java.util.function.Consumer; import java.util.stream.Collectors; import betsy.bpel.engines.AbstractBPELEngine; import betsy.bpel.repositories.BPELEngineRepository; import betsy.bpmn.engines.AbstractBPMNEngine; import betsy.bpmn.repositories.BPMNEngineRepository; import betsy.common.engines.EngineLifecycle; import javafx.application.Application; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.control.ScrollPane; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.stage.Stage; /** * The GUI to install, start and stop a local engine or all local engines. */ public class EngineControlGUI extends Application { private static class LogFileUtil { /** * Requires BPEL or BPMN EngineExtended to be passed! */ public static Path copyLogsToTempFolder(Object e) { final Path tmpFolder = createTempFolder(e.toString()); if (e instanceof AbstractBPELEngine) { AbstractBPELEngine eNew = (AbstractBPELEngine) e; eNew.storeLogs(tmpFolder); } else if (e instanceof AbstractBPMNEngine) { AbstractBPMNEngine eNew = (AbstractBPMNEngine) e; eNew.storeLogs(tmpFolder); } return tmpFolder; } public static Path createTempFolder(String context) { try { return Files.createTempDirectory("betsy-" + context + "-logs"); } catch (IOException e1) { throw new IllegalStateException("Could not create temp folder", e1); } } } private final ObservableList<String> actions = FXCollections.observableList(new LinkedList<>()); @Override public void start(Stage primaryStage) throws Exception { BorderPane pane = new BorderPane(); pane.setCenter(new ScrollPane(createCenterPanel())); ListView<String> listView = new ListView<>(actions); listView.setMaxWidth(Double.MAX_VALUE); listView.setPrefWidth(750); pane.setTop(new ScrollPane(listView)); primaryStage.setTitle("ECC - EngineExtended Control Center"); Scene scene = new Scene(pane, 800, 1000); primaryStage.setScene(scene); primaryStage.show(); toast("UP AND RUNNING"); } public static void main(String... args) { launch(args); } private Pane createCenterPanel() { GridPane pane = new GridPane(); pane.setHgap(1); pane.setVgap(3); final List<EngineLifecycle> bpelEngines = new BPELEngineRepository().getByName("ALL").stream().collect(Collectors.toList()); final List<EngineLifecycle> bpmnEngines = new BPMNEngineRepository().getByName("ALL").stream().collect(Collectors.toList()); final List<EngineLifecycle> engines = new LinkedList<>(); engines.addAll(bpelEngines); engines.addAll(bpmnEngines); int rowCounter = 0; for (EngineLifecycle engine : bpelEngines) { List<Node> nodes = createEngineRow(engine); pane.addRow(rowCounter, nodes.toArray(new Node[nodes.size()])); rowCounter++; } // empty row List<Node> emptyRow = createEmptyRow(7); pane.addRow(rowCounter, emptyRow.toArray(new Node[emptyRow.size()])); rowCounter++; for (EngineLifecycle engine : bpmnEngines) { List<Node> nodes = createEngineRow(engine); pane.addRow(rowCounter, nodes.toArray(new Node[nodes.size()])); rowCounter++; } // empty row List<Node> emptyRow2 = createEmptyRow(7); pane.addRow(rowCounter, emptyRow2.toArray(new Node[emptyRow2.size()])); rowCounter++; List<Node> nodes = getAllEnginesRow(engines); pane.addRow(rowCounter, nodes.toArray(new Node[nodes.size()])); return pane; } private List<Node> getAllEnginesRow(List<EngineLifecycle> engines) { List<Node> nodes = new LinkedList<>(); nodes.add(new Label("ALL")); nodes.add(createAllButton(engines, "install", EngineLifecycle::install)); nodes.add(createAllButton(engines, "uninstall", EngineLifecycle::uninstall)); nodes.add(new Label()); nodes.add(createAllButton(engines, "start", EngineLifecycle::startup)); nodes.add(createAllButton(engines, "stop", EngineLifecycle::shutdown)); nodes.add(new Label()); return nodes; } private List<Node> createEngineRow(EngineLifecycle engine) { List<Node> nodes = new LinkedList<>(); nodes.add(new Label(engine.toString())); nodes.add(createButton("install", engine, EngineLifecycle::install)); nodes.add(createButton("uninstall", engine, EngineLifecycle::uninstall)); nodes.add(createButton("isInstalled?", engine, (e) -> { boolean isInstalled = engine.isInstalled(); Platform.runLater(() -> toast(engine.toString() + " is " + (isInstalled ? "installed" : "uninstalled"))); })); nodes.add(createButton("start", engine, EngineLifecycle::startup)); nodes.add(createButton("stop", engine, EngineLifecycle::shutdown)); nodes.add(createButton("isRunning?", engine, (e) -> { boolean isRunning = engine.isRunning(); Platform.runLater(() -> toast(engine.toString() + " is " + (isRunning ? "started" : "shutdown"))); })); nodes.add(createButton("open folder with logs", engine, (e) -> { final Path tmpFolder = LogFileUtil.copyLogsToTempFolder(e); try { Desktop.getDesktop().open(tmpFolder.toFile()); } catch (IOException e1) { throw new IllegalStateException("Could not open folder " + tmpFolder, e1); } })); return nodes; } private Button createAllButton(List<EngineLifecycle> engines, String name, Consumer<EngineLifecycle> f) { Button button = new Button(name); button.setOnAction(e -> { for (final EngineLifecycle engine : engines) { executeEngineAction(name, engine, (x) -> f.accept(engine)); } }); return button; } private Button createButton(final String name, final EngineLifecycle engine, Consumer<EngineLifecycle> action) { Button button = new Button(name); button.setOnAction((e) -> executeEngineAction(name, engine, action)); return button; } private void executeEngineAction(String name, EngineLifecycle engine, Consumer<EngineLifecycle> action) { executeAction(name + " of " + engine.toString(), () -> action.accept(engine)); } private void executeAction(final String name, final Runnable action) { new Thread(new Task<Void>() { public Void call() { Platform.runLater(() -> toast(name)); action.run(); Platform.runLater(() -> toast(name + " DONE")); return null; } }).start(); } private void toast(String message) { String time = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM).format(LocalTime.now()); String toastMessage = String.format("[%s] %s", time, message); System.out.println(toastMessage); actions.add(0, toastMessage); } private List<Node> createEmptyRow(int columns) { List<Node> nodes = new LinkedList<>(); for (int i = 0; i < columns; i++) { nodes.add(new Label()); } return nodes; } }