diff --git a/work/Clients/NetworkClients.jar b/work/Clients/NetworkClients.jar new file mode 100644 index 0000000..6f0fc06 Binary files /dev/null and b/work/Clients/NetworkClients.jar differ diff --git a/work/Clients/src/Clients/AphorismClient.java b/work/Clients/src/Clients/AphorismClient.java new file mode 100644 index 0000000..0cca22e --- /dev/null +++ b/work/Clients/src/Clients/AphorismClient.java @@ -0,0 +1,19 @@ +package Clients; + +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +public class AphorismClient extends ClientModule { + + public AphorismClient(TextArea ta_Resp, TextArea ta_Logs) { + super(ta_Resp, ta_Logs); + } + public AphorismClient(TextArea ta_Resp, TextArea ta_Logs, TextField tf_request) { + super(ta_Resp, ta_Logs, tf_request); + } + + @Override + public void write() { + out.println("get"); + } +} diff --git a/work/Clients/src/Clients/Client.java b/work/Clients/src/Clients/Client.java new file mode 100644 index 0000000..b92fca8 --- /dev/null +++ b/work/Clients/src/Clients/Client.java @@ -0,0 +1,78 @@ +package Clients; + +import java.io.IOException; +import java.net.Socket; + +public class Client extends Thread { + + private Socket server; + private ClientModule module; + private boolean connected = false; + + private Client(String host, int port, ClientModule module) { + setDaemon(true); + this.module = module; + try { + server = new Socket(host, port); + connected = true; + module.printLog("Connection established"); + } catch (IOException ex) { + module.printLog("Connecting failed"); + connected = false; + } + } + + public static Client getInstance(String host, int port, ClientModule module) { + return new Client(host, port, module); + } + public String getDialog() { + return module.getDialog(); + } + public void setSelected(boolean state) { + module.setSelected(state); + } + public boolean isConnected() { + return connected; + } + + @Override + public String toString() { + return module.toString(); + } + + public void close() { + try { + if (server != null) { + server.close(); + module.printLog("Client disconnected successfully"); + connected = false; + } + } catch (IOException ex) { + module.printLog("Client terminating failed"); + connected = false; + } + } + + @Override + public void run() { + try{ + module.workWith(server); + } catch (IOException ex) { + module.printLog("Input / Output closing failed"); + } catch (NullPointerException ex) { + module.printLog(""); + } finally { + close(); + } + } + + public void sendRequest() { + module.printLog("send request to server"); + module.write(); + } + public void disconnect() { + module.printLog("send disconnecting command"); + module.write(module.getDisconnectCmd()); + module.go = false; + } +} diff --git a/work/Clients/src/Clients/ClientModule.java b/work/Clients/src/Clients/ClientModule.java new file mode 100644 index 0000000..5d6f885 --- /dev/null +++ b/work/Clients/src/Clients/ClientModule.java @@ -0,0 +1,101 @@ +package Clients; + +import javafx.application.Platform; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.Socket; + +public abstract class ClientModule { + //stores dialog with server + StringBuilder dialog = new StringBuilder(); + //indicates if the client is selected in the list of clients + boolean selected = false; + //terminate tool + public volatile boolean go = true; + public TextArea taResp; + public TextArea taLogs; + public TextField tfRequest; + public BufferedReader in; + public PrintWriter out; + private String disconnectCmd = "exit"; + + public ClientModule(TextArea ta_Resp, TextArea ta_Logs) { + taResp = ta_Resp; + taLogs = ta_Logs; + } + public ClientModule(TextArea ta_Resp, TextArea ta_Logs, TextField tf_request) { + taResp = ta_Resp; + taLogs = ta_Logs; + tfRequest = tf_request; + } + + public String getDialog() { + return dialog.toString(); + } + public void setSelected(boolean state) { + selected = state; + } + + public String getDisconnectCmd() { + return disconnectCmd; + } + + public void printLog(String log) { + Platform.runLater(() -> taLogs.appendText(log + "\n")); + + } + public void printResp(String response) { + Platform.runLater(() -> taResp.setText(response)); + } + public void workWith(Socket server) throws IOException { + try { + in = new BufferedReader(new InputStreamReader(server.getInputStream())); + out = new PrintWriter(server.getOutputStream(), true); + printLog("in/out streams opened"); + listen(); + } catch (IOException ex) { + printLog("Input / Output opening failed"); + } finally { + in.close(); + out.close(); + printLog("in/out streams closed"); + } + } + + public void write() { + out.println(tfRequest.getText()); + tfRequest.clear(); + } + public void write(String command) { + out.println(command); + } + + + public void listen() { + Thread listener = new Thread(() -> { + String input = ""; + try { + while (!input.equalsIgnoreCase("exit")) { + printResp(input); + try { + input = in.readLine(); + } catch (IOException ex) { + printLog("input reading failed"); + break; + } + printLog("Server response : " + input); + } + } catch (NullPointerException ex) { + printLog("Server connection lost"); + } + }); + listener.setDaemon(true); + listener.start(); + while (go && listener.isAlive()) Thread.onSpinWait(); + } +} diff --git a/work/Clients/src/Clients/InfoClient.java b/work/Clients/src/Clients/InfoClient.java new file mode 100644 index 0000000..99ed475 --- /dev/null +++ b/work/Clients/src/Clients/InfoClient.java @@ -0,0 +1,22 @@ +package Clients; + +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +public class InfoClient extends ClientModule { + + public InfoClient(TextArea ta_Resp, TextArea ta_Logs) { + super(ta_Resp, ta_Logs); + } + + public InfoClient(TextArea ta_Resp, TextArea ta_Logs, TextField tf_request) { + super(ta_Resp, ta_Logs, tf_request); + } + + @Override + public void printResp(String response) { + taResp.clear(); + for (String line : response.split("\\|")) + taResp.appendText(line + "\n"); + } +} diff --git a/work/Clients/src/Clients/NoticeModule.java b/work/Clients/src/Clients/NoticeModule.java new file mode 100644 index 0000000..a6c102f --- /dev/null +++ b/work/Clients/src/Clients/NoticeModule.java @@ -0,0 +1,33 @@ +package Clients; + +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +public class NoticeModule extends ClientModule { + private static int numOfClients = 0; + private int index; + + public NoticeModule(TextArea ta_Resp, TextArea ta_Logs) { + super(ta_Resp, ta_Logs); + numOfClients++; + index = numOfClients; + } + + public NoticeModule(TextArea ta_Resp, TextArea ta_Logs, TextField tf_request) { + super(ta_Resp, ta_Logs, tf_request); + numOfClients++; + index = numOfClients; + } + + @Override + public void printResp(String response) { + dialog.append(response).append("\n"); + if (selected) + taResp.appendText(response + "\n"); + } + + @Override + public String toString() { + return "Listener#" + index; + } +} diff --git a/work/Clients/src/Clients/TimeClient.java b/work/Clients/src/Clients/TimeClient.java new file mode 100644 index 0000000..ae15ec2 --- /dev/null +++ b/work/Clients/src/Clients/TimeClient.java @@ -0,0 +1,19 @@ +package Clients; + +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +public class TimeClient extends ClientModule { + + public TimeClient(TextArea ta_Resp, TextArea ta_Logs) { + super(ta_Resp, ta_Logs); + } + public TimeClient(TextArea ta_Resp, TextArea ta_Logs, TextField tf_request) { + super(ta_Resp, ta_Logs, tf_request); + } + + @Override + public void write() { + out.println("get"); + } +} diff --git a/work/Clients/src/META-INF/MANIFEST.MF b/work/Clients/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..440fa71 --- /dev/null +++ b/work/Clients/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: sample.Main + diff --git a/work/Clients/src/sample/Controller.java b/work/Clients/src/sample/Controller.java new file mode 100644 index 0000000..c4f19d9 --- /dev/null +++ b/work/Clients/src/sample/Controller.java @@ -0,0 +1,237 @@ +package sample; + +import Clients.*; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.ListView; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +import java.net.URL; +import java.util.ResourceBundle; + +public class Controller implements Initializable { + + Client timeClient; + + Client aphClient; + + Client notClient; + @FXML + ListView listeners; + ObservableList data; + + Client infoClient; + + + @FXML + TextField tfHost_timeCl; + @FXML + TextField tfPort_timeCl; + @FXML + TextArea taResp_timeCl; + @FXML + TextArea taLogs_timeCl; + @FXML + Button btnCon_timeCl; + @FXML + Button btnDisCon_timeCl; + @FXML + Button btnReq_timeCl; + + @FXML + TextField tfHost_aphCl; + @FXML + TextField tfPort_aphCl; + @FXML + TextArea taResp_aphCl; + @FXML + TextArea taLogs_aphCl; + @FXML + Button btnCon_aphCl; + @FXML + Button btnDisCon_aphCl; + @FXML + Button btnReq_aphCl; + + @FXML + TextField tfHost_notCl; + @FXML + TextField tfPort_notCl; + @FXML + TextField tfReq_notCl; + @FXML + TextArea taResp_notCl; + @FXML + TextArea taLogs_notCl; + @FXML + Button btnCon_notCl; + @FXML + Button btnDisCon_notCl; + @FXML + Button btnReq_notCl; + + @FXML + TextField tfHost_infoCl; + @FXML + TextField tfPort_infoCl; + @FXML + TextField tfReq_infoCl; + @FXML + TextArea taResp_infoCl; + @FXML + TextArea taLogs_infoCl; + @FXML + Button btnCon_infoCl; + @FXML + Button btnDisCon_infoCl; + @FXML + Button btnReq_infoCl; + + Thread buttonsState; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + tfPort_timeCl.setText("1201"); + tfHost_timeCl.setText("localhost"); + tfPort_aphCl.setText("1202"); + tfHost_aphCl.setText("localhost"); + tfPort_notCl.setText("1203"); + tfHost_notCl.setText("localhost"); + tfPort_infoCl.setText("1204"); + tfHost_infoCl.setText("localhost"); + + data = FXCollections.observableArrayList(); + listeners.setItems(data); + //show dialog of the elected client + listeners.getSelectionModel().selectedItemProperty().addListener((observableValue, old_client, new_client) -> { + if (data.isEmpty()) { + taResp_notCl.setText(""); + } + else{ + if (old_client != null) + old_client.setSelected(false); + taResp_notCl.setText(new_client.getDialog()); + new_client.setSelected(true); + } + }); + + buttonsState = new Thread(() -> { + while (true) { + btn_state_if_timeClient(timeClient == null || !timeClient.isAlive()); + btn_state_if_aphClient(aphClient == null || !aphClient.isAlive()); + btn_state_if_notClient(data.isEmpty()); + btn_state_if_infoClient(infoClient == null || !infoClient.isAlive()); + Thread.onSpinWait(); + } + }); + buttonsState.setDaemon(true); + buttonsState.start(); + } + private void btn_state_if_timeClient(boolean flag) { + btnCon_timeCl.setDisable(!flag); + btnDisCon_timeCl.setDisable(flag); + btnReq_timeCl.setDisable(flag); + } + private void btn_state_if_aphClient(boolean flag) { + btnCon_aphCl.setDisable(!flag); + btnDisCon_aphCl.setDisable(flag); + btnReq_aphCl.setDisable(flag); + } + private void btn_state_if_notClient(boolean flag) { + btnCon_notCl.setDisable(false); + btnDisCon_notCl.setDisable(flag); + btnReq_notCl.setDisable(flag); + } + private void btn_state_if_infoClient(boolean flag) { + btnCon_infoCl.setDisable(!flag); + btnDisCon_infoCl.setDisable(flag); + btnReq_infoCl.setDisable(flag); + } + private int whichPort(int port, TextField tfPort, TextArea taLogs) { + try { + port = Integer.parseInt(tfPort.getText()); + } catch (NumberFormatException e) { + taLogs.appendText("WARNING: invalid format of the port field\n"); + } + return port; + } + private void runClient(Client client) { + if (client.isConnected()) + client.start(); + } + + @FXML + void OnClick_btnCon_timeCl() { + timeClient = Client.getInstance(tfHost_timeCl.getText(), + whichPort(1201, tfPort_timeCl, taLogs_timeCl), new TimeClient(taResp_timeCl, taLogs_timeCl)); + runClient(timeClient); + + } + @FXML + void OnCLick_btnDisCon_timeCl() { + timeClient.disconnect(); + } + @FXML + void OnClick_btnReq_timeCl() { + timeClient.sendRequest(); + } + + @FXML + void OnClick_btnCon_aphCl() { + aphClient = Client.getInstance(tfHost_aphCl.getText(), + whichPort(1202, tfPort_aphCl, taLogs_aphCl), new AphorismClient(taResp_aphCl, taLogs_aphCl)); + runClient(aphClient); + } + @FXML + void OnCLick_btnDisCon_aphCl() { + aphClient.disconnect(); + } + @FXML + void OnClick_btnReq_aphCl() { + aphClient.sendRequest(); + } + + @FXML + void OnClick_btnCon_notCl() { + notClient = Client.getInstance(tfHost_notCl.getText(), + whichPort(1203, tfPort_notCl, taLogs_notCl), new NoticeModule(taResp_notCl, taLogs_notCl, tfReq_notCl)); + if (notClient.isConnected()){ + data.add(notClient); + notClient.start(); + if (notClient.isAlive()) { + listeners.getSelectionModel().select(notClient); + } + } + + } + @FXML + void OnCLick_btnDisCon_notCl() { + Client client = listeners.getSelectionModel().getSelectedItem(); + data.remove(client); + client.disconnect(); + } + @FXML + void OnClick_btnReq_notCl() { + listeners.getSelectionModel().getSelectedItem().sendRequest(); + } + + @FXML + void OnClick_btnCon_infoCl() { + + infoClient = Client.getInstance(tfHost_infoCl.getText(), + whichPort(1204, tfPort_infoCl, taLogs_infoCl), new InfoClient(taResp_infoCl, taLogs_infoCl, tfReq_infoCl)); + runClient(infoClient); + } + @FXML + void OnCLick_btnDisCon_infoCl() { + infoClient.disconnect(); + } + @FXML + void OnClick_btnReq_infoCl() { + infoClient.sendRequest(); + } +} diff --git a/work/Clients/src/sample/Main.java b/work/Clients/src/sample/Main.java new file mode 100644 index 0000000..fc51a77 --- /dev/null +++ b/work/Clients/src/sample/Main.java @@ -0,0 +1,23 @@ +package sample; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) throws Exception{ + Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); + primaryStage.setTitle("Clients"); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } + + + public static void main(String[] args) { + launch(args); + } +} diff --git a/work/Clients/src/sample/sample.fxml b/work/Clients/src/sample/sample.fxml new file mode 100644 index 0000000..8e77305 --- /dev/null +++ b/work/Clients/src/sample/sample.fxml @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/work/Servers/NetworkServers.jar b/work/Servers/NetworkServers.jar new file mode 100644 index 0000000..4a88b3e Binary files /dev/null and b/work/Servers/NetworkServers.jar differ diff --git a/work/Servers/src/META-INF/MANIFEST.MF b/work/Servers/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..440fa71 --- /dev/null +++ b/work/Servers/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: sample.Main + diff --git a/work/Servers/src/notes.JSON b/work/Servers/src/notes.JSON new file mode 100644 index 0000000..9b7d776 --- /dev/null +++ b/work/Servers/src/notes.JSON @@ -0,0 +1,36 @@ +[ + { + "id": 1, + "notes": [ + { + "time": "14:02", + "note": "1st note of 1st" + }, + { + "time": "14:03", + "note": "2st note of 1st" + }, + { + "time": "14:04", + "note": "3st note of 1st" + } + ] + }, + { + "id": 2, + "notes": [ + { + "time": "17:01", + "note": "1st note of 2nd" + }, + { + "time": "17:03", + "note": "2st note of 2nd" + }, + { + "time": "17:13", + "note": "3st note of 2nd" + } + ] + } +] \ No newline at end of file diff --git a/work/Servers/src/sample/Controller.java b/work/Servers/src/sample/Controller.java new file mode 100644 index 0000000..d0fedaa --- /dev/null +++ b/work/Servers/src/sample/Controller.java @@ -0,0 +1,152 @@ +package sample; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; + +import java.net.URL; +import java.util.ResourceBundle; + +import srvs.*; + +public class Controller implements Initializable { + + private Server timeServer; + private Server aphServer; + private Server notServer; + private Server infoServer; + + @FXML + TextField tfPort_timeMod; + @FXML + Button btnStart_timeMod; + @FXML + Button btnStop_timeMod; + @FXML + TextArea taLog_timeMod; + + + @FXML + TextField tfPort_aphMod; + @FXML + Button btnStart_aphMod; + @FXML + Button btnStop_aphMod; + @FXML + TextArea taLog_aphMod; + + @FXML + TextField tfPort_notMod; + @FXML + Button btnStart_notMod; + @FXML + Button btnStop_notMod; + @FXML + TextArea taLog_notMod; + + @FXML + TextField tfPort_infoMod; + @FXML + Button btnStart_infoMod; + @FXML + Button btnStop_infoMod; + @FXML + TextArea taLog_infoMod; + + private Thread buttonsState; + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + //set default ports for servers + tfPort_timeMod.setText("1201"); + tfPort_aphMod.setText("1202"); + tfPort_notMod.setText("1203"); + tfPort_infoMod.setText("1204"); + + buttonsState = new Thread(() -> { + while (true) { + btn_state_if_timeServer(timeServer == null || !timeServer.isAlive()); + btn_state_if_aphServer(aphServer == null || !aphServer.isAlive()); + btn_state_if_notServer(notServer == null || !notServer.isAlive()); + btn_state_if_infoServer(infoServer == null || !infoServer.isAlive()); + Thread.onSpinWait(); + } + }); + buttonsState.setDaemon(true); + buttonsState.start(); + } + private void btn_state_if_timeServer(boolean flag) { + btnStart_timeMod.setDisable(!flag); + btnStop_timeMod.setDisable(flag); + } + private void btn_state_if_aphServer(boolean flag) { + btnStart_aphMod.setDisable(!flag); + btnStop_aphMod.setDisable(flag); + } + private void btn_state_if_notServer(boolean flag) { + btnStart_notMod.setDisable(!flag); + btnStop_notMod.setDisable(flag); + } + private void btn_state_if_infoServer(boolean flag) { + btnStart_infoMod.setDisable(!flag); + btnStop_infoMod.setDisable(flag); + } + + //Reads port from the textField and checks it. Return read port or default port. + private int whichPort(int port, TextField tfPort, TextArea taLogs) { + try { + port = Integer.parseInt(tfPort.getText()); + } catch (NumberFormatException e) { + taLogs.appendText("WARNING: invalid format of the port field\n"); + } + return port; + } + private void stopServer(Server server) { + server.module.doLog("send stop command to the server\n"); + server.terminateFlag = true; + server.close(); + } + + @FXML + void onClick_startBtn_timeMod() { + timeServer = Server.getInstance(new TimeModule(taLog_timeMod), whichPort(1201, tfPort_timeMod, taLog_timeMod)).multiThread(false); + timeServer.start(); + } + @FXML + void onClick_stopBtn_timeMod() { + stopServer(timeServer); + } + + @FXML + void onClick_startBtn_aphMod() { + aphServer = Server.getInstance(new AphorismModule(taLog_aphMod), whichPort(1202, tfPort_aphMod, taLog_aphMod)).multiThread(false); + aphServer.start(); + } + @FXML + void onClick_stopBtn_aphMod() { + stopServer(aphServer); + } + + @FXML + void onClick_startBtn_notMod() { + notServer = Server.getInstance(new NoticeModule(taLog_notMod), whichPort(1203, tfPort_notMod, taLog_notMod)).multiThread(true); + notServer.start(); + } + @FXML + void onClick_stopBtn_notMod() { + stopServer(notServer); + } + + @FXML + void onClick_startBtn_infoMod() { + infoServer = Server.getInstance(new InfoModule(taLog_infoMod), whichPort(1204, tfPort_infoMod, taLog_infoMod)).multiThread(false); + infoServer.start(); + } + @FXML + void onClick_stopBtn_infoMod() { + stopServer(infoServer); + } +} diff --git a/work/Servers/src/sample/Main.java b/work/Servers/src/sample/Main.java new file mode 100644 index 0000000..cbd246d --- /dev/null +++ b/work/Servers/src/sample/Main.java @@ -0,0 +1,23 @@ +package sample; + +import javafx.application.Application; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class Main extends Application { + + @Override + public void start(Stage primaryStage) throws Exception{ + Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); + primaryStage.setTitle("Servers"); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } + + + public static void main(String[] args) { + launch(args); + } +} diff --git a/work/Servers/src/sample/sample.fxml b/work/Servers/src/sample/sample.fxml new file mode 100644 index 0000000..6c37a99 --- /dev/null +++ b/work/Servers/src/sample/sample.fxml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +