corefx - changed core client to use address and port, added pseudo terminal for remote connections

This commit is contained in:
Blake J. Harnden 2018-11-30 15:12:30 -08:00
parent 080a03c8be
commit 3025287486
16 changed files with 186 additions and 45 deletions

View file

@ -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());

View file

@ -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;

View file

@ -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()));

View file

@ -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,6 +120,7 @@ public class NetworkGraph {
controller.getCoreClient().isRunning());
if (mouseEvent.getClickCount() == 2 && controller.getCoreClient().isRunning()) {
if (controller.getCoreClient().isLocalConnection()) {
try {
String shellCommand = controller.getConfiguration().getShellCommand();
String terminalCommand = controller.getCoreClient().getTerminalCommand(node);
@ -138,6 +140,9 @@ public class NetworkGraph {
logger.error("error launching terminal", ex);
Toast.error("Node terminal failed to start");
}
} else {
Platform.runLater(() -> controller.getTerminalDialog().showDialog(node));
}
}
}

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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<String> {
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();
}
}

View file

@ -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) {

View file

@ -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;

View file

@ -139,6 +139,17 @@ public final class WebUtils {
}
}
public static <T> T putJson(String url, Object json, Class<T> 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> T post(String url, Class<T> clazz) throws IOException {
logger.debug("post: {}", url);
RequestBody body = new FormBody.Builder().build();

View file

@ -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);

View file

@ -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 --"

View file

@ -30,6 +30,7 @@
}
.code {
-fx-background-color: black;
-fx-text-fill: lime;
-fx-font-family: monospaced;
-jfx-focus-color: lime;

View file

@ -10,7 +10,9 @@
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
<children>
<Label maxWidth="1.7976931348623157E308" text="URL" />
<JFXTextField fx:id="urlTextField" />
<Label maxWidth="1.7976931348623157E308" text="Address" />
<JFXTextField fx:id="addressTextField" />
<Label maxWidth="1.7976931348623157E308" text="Port" />
<JFXTextField fx:id="portTextField" />
</children>
</VBox>

View file

@ -34,6 +34,7 @@
</Menu>
<Menu mnemonicParsing="false" text="Session">
<items>
<MenuItem mnemonicParsing="false" onAction="#onSessionNodesMenu" text="Nodes" />
<MenuItem mnemonicParsing="false" onAction="#onSessionHooksMenu" text="Hooks" />
<MenuItem mnemonicParsing="false" onAction="#onOptionsMenuLocation" text="Location" />
<MenuItem mnemonicParsing="false" onAction="#onOptionsMenuBackground" text="Background" />

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXTextArea?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: black;" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<JFXTextArea fx:id="outputTextArea" editable="false" styleClass="code" VBox.vgrow="ALWAYS" />
<HBox style="-fx-background-color: black;">
<children>
<JFXTextField editable="false" prefColumnCount="3" styleClass="code" text="\$&gt; " />
<JFXTextField fx:id="commandTextField" maxWidth="1.7976931348623157E308" styleClass="code" HBox.hgrow="ALWAYS" />
</children>
</HBox>
</children>
</VBox>