diff --git a/corefx/src/main/java/com/core/Controller.java b/corefx/src/main/java/com/core/Controller.java index f9aa820f..3ffdaf32 100644 --- a/corefx/src/main/java/com/core/Controller.java +++ b/corefx/src/main/java/com/core/Controller.java @@ -84,15 +84,16 @@ public class Controller implements Initializable { private ConnectDialog connectDialog = new ConnectDialog(this); private GuiPreferencesDialog guiPreferencesDialog = new GuiPreferencesDialog(this); private NodeTypeCreateDialog nodeTypeCreateDialog = new NodeTypeCreateDialog(this); + private TerminalDialog terminalDialog = new TerminalDialog(this); - public void connectToCore(String coreUrl) { + public void connectToCore(String address, int port) { coreWebSocket.stop(); ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(() -> { try { - coreWebSocket.start(coreUrl); - coreClient.setUrl(coreUrl); + coreWebSocket.start(address, port); + coreClient.setConnection(address, port); initialJoin(); } catch (IOException | URISyntaxException ex) { Toast.error(String.format("Connection failure: %s", ex.getMessage()), ex); @@ -287,6 +288,7 @@ public class Controller implements Initializable { connectDialog.setOwner(window); guiPreferencesDialog.setOwner(window); nodeTypeCreateDialog.setOwner(window); + terminalDialog.setOwner(window); } @FXML @@ -386,6 +388,11 @@ public class Controller implements Initializable { } } + @FXML + private void onSessionNodesMenu(ActionEvent event) { + + } + @FXML private void onSessionHooksMenu(ActionEvent event) { hooksDialog.showDialog(); @@ -427,10 +434,12 @@ public class Controller implements Initializable { public void initialize(URL location, ResourceBundle resources) { coreWebSocket = new CoreWebSocket(this); configuration = ConfigUtils.load(); - String coreUrl = configuration.getCoreRest(); - logger.info("core rest: {}", coreUrl); - connectDialog.setCoreUrl(coreUrl); - connectToCore(coreUrl); + String address = configuration.getCoreAddress(); + int port = configuration.getCorePort(); + logger.info("core connection: {}:{}", address, port); + connectDialog.setAddress(address); + connectDialog.setPort(port); + connectToCore(address, port); logger.info("controller initialize"); swingNode.setContent(networkGraph.getGraphViewer()); diff --git a/corefx/src/main/java/com/core/client/ICoreClient.java b/corefx/src/main/java/com/core/client/ICoreClient.java index 707e70c4..d1e31f78 100644 --- a/corefx/src/main/java/com/core/client/ICoreClient.java +++ b/corefx/src/main/java/com/core/client/ICoreClient.java @@ -12,7 +12,9 @@ import java.util.Map; import java.util.Set; public interface ICoreClient { - void setUrl(String url); + void setConnection(String address, int port); + + boolean isLocalConnection(); Integer currentSession(); @@ -78,6 +80,8 @@ public interface ICoreClient { boolean createNode(CoreNode node) throws IOException; + String nodeCommand(CoreNode node, String command) throws IOException; + boolean editNode(CoreNode node) throws IOException; boolean deleteNode(CoreNode node) throws IOException; diff --git a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java b/corefx/src/main/java/com/core/client/rest/CoreRestClient.java index b6021696..a3617383 100644 --- a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java +++ b/corefx/src/main/java/com/core/client/rest/CoreRestClient.java @@ -14,13 +14,20 @@ import java.util.*; @Data public class CoreRestClient implements ICoreClient { private static final Logger logger = LogManager.getLogger(); - private String baseUrl; + private String address; + private int port; private Integer sessionId; private SessionState sessionState; @Override - public void setUrl(String url) { - this.baseUrl = url; + public void setConnection(String address, int port) { + this.address = address; + this.port = port; + } + + @Override + public boolean isLocalConnection() { + return address.equals("127.0.0.1") || address.equals("localhost"); } @Override @@ -39,7 +46,7 @@ public class CoreRestClient implements ICoreClient { } private String getUrl(String path) { - return String.format("%s/%s", baseUrl, path); + return String.format("http://%s:%s/%s", address, port, path); } @Override @@ -295,12 +302,19 @@ public class CoreRestClient implements ICoreClient { return WebUtils.putJson(url, config); } + @Override + public String nodeCommand(CoreNode node, String command) throws IOException { + String url = getUrl(String.format("sessions/%s/nodes/%s/command", sessionId, node.getId())); + return WebUtils.putJson(url, command, String.class); + } + @Override public boolean createNode(CoreNode node) throws IOException { String url = getUrl(String.format("sessions/%s/nodes", sessionId)); return WebUtils.postJson(url, node); } + @Override public boolean editNode(CoreNode node) throws IOException { String url = getUrl(String.format("sessions/%s/nodes/%s", sessionId, node.getId())); diff --git a/corefx/src/main/java/com/core/graph/NetworkGraph.java b/corefx/src/main/java/com/core/graph/NetworkGraph.java index c8357d7a..c63b6a18 100644 --- a/corefx/src/main/java/com/core/graph/NetworkGraph.java +++ b/corefx/src/main/java/com/core/graph/NetworkGraph.java @@ -19,6 +19,7 @@ import edu.uci.ics.jung.visualization.control.GraphMouseListener; import edu.uci.ics.jung.visualization.control.ModalGraphMouse; import edu.uci.ics.jung.visualization.decorators.EdgeShape; import edu.uci.ics.jung.visualization.renderers.Renderer; +import javafx.application.Platform; import lombok.Data; import org.apache.commons.net.util.SubnetUtils; import org.apache.logging.log4j.LogManager; @@ -119,24 +120,28 @@ public class NetworkGraph { controller.getCoreClient().isRunning()); if (mouseEvent.getClickCount() == 2 && controller.getCoreClient().isRunning()) { - try { - String shellCommand = controller.getConfiguration().getShellCommand(); - String terminalCommand = controller.getCoreClient().getTerminalCommand(node); - terminalCommand = String.format("%s %s", shellCommand, terminalCommand); - logger.info("launching node terminal: {}", terminalCommand); - String[] commands = terminalCommand.split("\\s+"); - logger.info("launching node terminal: {}", Arrays.toString(commands)); - Process p = new ProcessBuilder(commands).start(); + if (controller.getCoreClient().isLocalConnection()) { try { - if (!p.waitFor(5, TimeUnit.SECONDS)) { - Toast.error("Node terminal command failed"); + String shellCommand = controller.getConfiguration().getShellCommand(); + String terminalCommand = controller.getCoreClient().getTerminalCommand(node); + terminalCommand = String.format("%s %s", shellCommand, terminalCommand); + logger.info("launching node terminal: {}", terminalCommand); + String[] commands = terminalCommand.split("\\s+"); + logger.info("launching node terminal: {}", Arrays.toString(commands)); + Process p = new ProcessBuilder(commands).start(); + try { + if (!p.waitFor(5, TimeUnit.SECONDS)) { + Toast.error("Node terminal command failed"); + } + } catch (InterruptedException ex) { + logger.error("error waiting for terminal to start", ex); } - } catch (InterruptedException ex) { - logger.error("error waiting for terminal to start", ex); + } catch (IOException ex) { + logger.error("error launching terminal", ex); + Toast.error("Node terminal failed to start"); } - } catch (IOException ex) { - logger.error("error launching terminal", ex); - Toast.error("Node terminal failed to start"); + } else { + Platform.runLater(() -> controller.getTerminalDialog().showDialog(node)); } } } diff --git a/corefx/src/main/java/com/core/ui/dialogs/ConnectDialog.java b/corefx/src/main/java/com/core/ui/dialogs/ConnectDialog.java index c5e4d6ba..0aa87fb1 100644 --- a/corefx/src/main/java/com/core/ui/dialogs/ConnectDialog.java +++ b/corefx/src/main/java/com/core/ui/dialogs/ConnectDialog.java @@ -4,8 +4,6 @@ import com.core.Controller; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXTextField; import javafx.fxml.FXML; -import javafx.stage.Modality; -import javafx.stage.StageStyle; import lombok.Data; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -13,16 +11,19 @@ import org.apache.logging.log4j.Logger; @Data public class ConnectDialog extends StageDialog { private static final Logger logger = LogManager.getLogger(); - private String coreUrl; + private String address; + private int port; private JFXButton saveButton; - @FXML JFXTextField urlTextField; + @FXML JFXTextField addressTextField; + @FXML JFXTextField portTextField; public ConnectDialog(Controller controller) { super(controller, "/fxml/connect_dialog.fxml"); saveButton = createButton("Connect"); saveButton.setOnAction(event -> { - coreUrl = urlTextField.getText(); - controller.connectToCore(coreUrl); + address = addressTextField.getText(); + port = Integer.parseInt(portTextField.getText()); + controller.connectToCore(address, port); close(); }); addCancelButton(); @@ -31,7 +32,8 @@ public class ConnectDialog extends StageDialog { } public void showDialog() { - urlTextField.setText(coreUrl); + addressTextField.setText(address); + portTextField.setText(Integer.toString(port)); show(); } } diff --git a/corefx/src/main/java/com/core/ui/dialogs/StageDialog.java b/corefx/src/main/java/com/core/ui/dialogs/StageDialog.java index 38d1d2f1..13634bb5 100644 --- a/corefx/src/main/java/com/core/ui/dialogs/StageDialog.java +++ b/corefx/src/main/java/com/core/ui/dialogs/StageDialog.java @@ -68,13 +68,11 @@ public class StageDialog { buttonBar.setAlignment(Pos.CENTER_RIGHT); buttonBar.setSpacing(10); - gridPane.addRow(1, buttonBar); stage.initModality(Modality.APPLICATION_MODAL); FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlPath)); loader.setController(this); - try { Parent parent = loader.load(); setContent(parent); @@ -82,6 +80,8 @@ public class StageDialog { logger.error("error loading fxml: {}", fxmlPath, ex); throw new RuntimeException(ex); } + + gridPane.addRow(1, buttonBar); } public void close() { @@ -118,7 +118,7 @@ public class StageDialog { } public void show() { - if (buttonBar.getChildren().isEmpty()) { + if (buttonBar.getChildren().isEmpty() && gridPane.getChildren().contains(buttonBar)) { gridPane.getChildren().remove(1); gridPane.getRowConstraints().remove(1); gridPane.setVgap(0); diff --git a/corefx/src/main/java/com/core/ui/dialogs/TerminalDialog.java b/corefx/src/main/java/com/core/ui/dialogs/TerminalDialog.java new file mode 100644 index 00000000..bff0a844 --- /dev/null +++ b/corefx/src/main/java/com/core/ui/dialogs/TerminalDialog.java @@ -0,0 +1,71 @@ +package com.core.ui.dialogs; + +import com.core.Controller; +import com.core.data.CoreNode; +import com.core.ui.Toast; +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXTextArea; +import com.jfoenix.controls.JFXTextField; +import javafx.concurrent.Task; +import javafx.fxml.FXML; +import lombok.Data; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Data +public class TerminalDialog extends StageDialog { + private static final Logger logger = LogManager.getLogger(); + private String address; + private int port; + private JFXButton saveButton; + @FXML JFXTextArea outputTextArea; + @FXML JFXTextField commandTextField; + private CoreNode node; + + public TerminalDialog(Controller controller) { + super(controller, "/fxml/terminal_dialog.fxml"); + commandTextField.setOnAction(event -> { + String command = commandTextField.getText(); + addOutput(String.format("$> %s", command)); + new Thread(new CommandTask(command)).start(); + commandTextField.clear(); + }); + } + + + private class CommandTask extends Task { + private String command; + + CommandTask(String command) { + this.command = command; + } + + @Override + protected String call() throws Exception { + return getCoreClient().nodeCommand(node, command); + } + + @Override + protected void succeeded() { + addOutput(getValue()); + } + + @Override + protected void failed() { + Toast.error("Failed sending terminal command"); + } + } + + private void addOutput(String output) { + outputTextArea.appendText(String.format("%s%n", output)); + } + + public void showDialog(CoreNode node) { + this.node = node; + setTitle(String.format("%s Pseudo Terminal", node.getName())); + outputTextArea.setText(""); + commandTextField.setText(""); + commandTextField.requestFocus(); + show(); + } +} diff --git a/corefx/src/main/java/com/core/utils/ConfigUtils.java b/corefx/src/main/java/com/core/utils/ConfigUtils.java index 0859c4c3..f597db45 100644 --- a/corefx/src/main/java/com/core/utils/ConfigUtils.java +++ b/corefx/src/main/java/com/core/utils/ConfigUtils.java @@ -107,8 +107,8 @@ public final class ConfigUtils { } // override configuration from command line - String coreRest = System.getProperty("core-rest"); - configuration.setCoreRest(coreRest); + String coreAddress = System.getProperty("coreAddress"); + configuration.setCoreAddress(coreAddress); return configuration; } catch (IOException ex) { diff --git a/corefx/src/main/java/com/core/utils/Configuration.java b/corefx/src/main/java/com/core/utils/Configuration.java index d5faec05..8cb58cb1 100644 --- a/corefx/src/main/java/com/core/utils/Configuration.java +++ b/corefx/src/main/java/com/core/utils/Configuration.java @@ -9,7 +9,8 @@ import java.util.List; @Data @NoArgsConstructor public class Configuration { - private String coreRest; + private String coreAddress; + private int corePort; private String xmlPath; private String mobilityPath; private String iconPath; diff --git a/corefx/src/main/java/com/core/utils/WebUtils.java b/corefx/src/main/java/com/core/utils/WebUtils.java index 61b9fa52..fec69313 100644 --- a/corefx/src/main/java/com/core/utils/WebUtils.java +++ b/corefx/src/main/java/com/core/utils/WebUtils.java @@ -139,6 +139,17 @@ public final class WebUtils { } } + public static T putJson(String url, Object json, Class clazz) throws IOException { + logger.debug("put json: {} - {}", url, json); + RequestBody body = RequestBody.create(JSON, JsonUtils.toString(json)); + Request request = new Request.Builder() + .url(url) + .put(body) + .build(); + String response = readResponse(request); + return JsonUtils.read(response, clazz); + } + public static T post(String url, Class clazz) throws IOException { logger.debug("post: {}", url); RequestBody body = new FormBody.Builder().build(); diff --git a/corefx/src/main/java/com/core/websocket/CoreWebSocket.java b/corefx/src/main/java/com/core/websocket/CoreWebSocket.java index c5cc89b5..451f8416 100644 --- a/corefx/src/main/java/com/core/websocket/CoreWebSocket.java +++ b/corefx/src/main/java/com/core/websocket/CoreWebSocket.java @@ -21,8 +21,8 @@ public class CoreWebSocket { this.controller = controller; } - public void start(String url) throws URISyntaxException { - socket = IO.socket(url); + public void start(String address, int port) throws URISyntaxException { + socket = IO.socket(String.format("http://%s:%s", address, port)); socket.on(Socket.EVENT_CONNECT, args -> logger.info("connected to web socket")); socket.on("node", this::handleNodes); socket.on("event", this::handleEvents); diff --git a/corefx/src/main/resources/config.json b/corefx/src/main/resources/config.json index 55db8ff4..fc214032 100644 --- a/corefx/src/main/resources/config.json +++ b/corefx/src/main/resources/config.json @@ -1,5 +1,6 @@ { - "coreRest": "http://127.0.0.1:5000", + "coreAddress": "127.0.0.1", + "corePort": 5000, "xmlPath": null, "mobilityPath": null, "shellCommand": "gnome-terminal --window --" diff --git a/corefx/src/main/resources/css/main.css b/corefx/src/main/resources/css/main.css index 81a47cc7..252c1254 100644 --- a/corefx/src/main/resources/css/main.css +++ b/corefx/src/main/resources/css/main.css @@ -30,6 +30,7 @@ } .code { + -fx-background-color: black; -fx-text-fill: lime; -fx-font-family: monospaced; -jfx-focus-color: lime; diff --git a/corefx/src/main/resources/fxml/connect_dialog.fxml b/corefx/src/main/resources/fxml/connect_dialog.fxml index ec2b4f2e..2f154f0d 100644 --- a/corefx/src/main/resources/fxml/connect_dialog.fxml +++ b/corefx/src/main/resources/fxml/connect_dialog.fxml @@ -10,7 +10,9 @@ - diff --git a/corefx/src/main/resources/fxml/main.fxml b/corefx/src/main/resources/fxml/main.fxml index 706576e1..263e2129 100644 --- a/corefx/src/main/resources/fxml/main.fxml +++ b/corefx/src/main/resources/fxml/main.fxml @@ -34,6 +34,7 @@ + diff --git a/corefx/src/main/resources/fxml/terminal_dialog.fxml b/corefx/src/main/resources/fxml/terminal_dialog.fxml new file mode 100644 index 00000000..d0192dc3 --- /dev/null +++ b/corefx/src/main/resources/fxml/terminal_dialog.fxml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + +