diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6951c29
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.idea/
+/.settings/
+java-chat.iml
diff --git a/pom.xml b/pom.xml
index 05188ae..21c5d05 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,4 +3,22 @@
org.progmethoden
java-chat
0.0.1-SNAPSHOT
+
+
+
+
+ com.google.code.gson
+ gson
+ 2.10.1
+
+
+
+ org.mockito
+ mockito-core
+ 4.1.10
+ test
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/ChatClient.java b/src/main/java/ChatClient.java
new file mode 100644
index 0000000..30b486c
--- /dev/null
+++ b/src/main/java/ChatClient.java
@@ -0,0 +1,112 @@
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.io.*;
+import java.net.Socket;
+
+public class ChatClient extends JFrame implements KeyListener {
+ private String address;
+ private String connectionFailedMessage;
+ private Socket connectionToServer;
+ private BufferedReader fromServerReader;
+ private PrintWriter toServerWriter;
+
+ // GUI
+ private JTextArea outputTextArea;
+ private JTextField inputTextField;
+ private JScrollPane outputScrollPane;
+
+ public ChatClient() {
+ super("Chat");
+ address = JOptionPane.showInputDialog("bitte IP-Adresse");
+ if (null != address) {
+ connectionFailedMessage = "Verbindung zum Server " + (address.isEmpty() ? "" : ("\"" + address + "\"")) + " fehlgeschlagen.";
+ receiveMessages();
+ }
+ }
+
+ private void initGui() {
+ outputTextArea = new JTextArea();
+ outputTextArea.setEditable(false);
+ outputTextArea.setBorder(BorderFactory.createTitledBorder("Chat"));
+
+ outputScrollPane = new JScrollPane(outputTextArea);
+
+ inputTextField = new JTextField();
+ inputTextField.setBorder(BorderFactory.createTitledBorder("Nachricht eingeben"));
+ inputTextField.addKeyListener(this);
+
+ add(outputScrollPane, BorderLayout.CENTER);
+ add(inputTextField, BorderLayout.SOUTH);
+
+ setVisible(true);
+ setSize(Constants.WINDOW_WIDTH, Constants.WINDOW_HEIGHT);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+ setLocationRelativeTo(null);
+ }
+ private void receiveMessages() {
+ try {
+ connectionToServer = new Socket(address, Constants.PORT);
+ fromServerReader = new BufferedReader(new InputStreamReader(connectionToServer.getInputStream()));
+ toServerWriter = new PrintWriter(new OutputStreamWriter(connectionToServer.getOutputStream()));
+
+ initGui();
+
+ while (true) {
+ String message = fromServerReader.readLine();
+ outputTextArea.append(message + "\n");
+ outputScrollPane.getVerticalScrollBar().setValue(outputScrollPane.getVerticalScrollBar().getMaximum());
+ }
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(null, connectionFailedMessage);
+ dispose();
+ } finally {
+ if (null != connectionToServer) {
+ try {
+ connectionToServer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (null != fromServerReader) {
+ try {
+ fromServerReader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if(null != toServerWriter) {
+ toServerWriter.close();
+ }
+ }
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ String message = inputTextField.getText();
+ if (!message.isEmpty()) {
+ toServerWriter.println(message);
+ toServerWriter.flush();
+ inputTextField.setText("");
+ }
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+
+ }
+
+ public static void main(String[] args) {
+ new ChatClient();
+ }
+}
diff --git a/src/main/java/ChatServer.java b/src/main/java/ChatServer.java
new file mode 100644
index 0000000..0c60774
--- /dev/null
+++ b/src/main/java/ChatServer.java
@@ -0,0 +1,60 @@
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class ChatServer {
+ private ServerSocket serverSocket;
+ private List clients; // Liste, um alle verbundenen Clients zu verwalten
+
+ public ChatServer(int port) {
+ clients = new CopyOnWriteArrayList<>(); // Verwende CopyOnWriteArrayList für die Thread-Sicherheit
+
+ try {
+ serverSocket = new ServerSocket(port);
+ System.out.println("Started ChatServer on port " + port);
+
+ while (true) {
+ System.out.println("waiting for new Client...");
+ Socket connectionToClient = serverSocket.accept(); // Auf Verbindungen von Clients warten
+ ClientHandler client = new ClientHandler(this, connectionToClient);
+ clients.add(client); // Neuen Client zur Liste hinzufügen
+ System.out.println("Accepted new Client");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (serverSocket != null) {
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ }
+ // Methode, um eine Nachricht an alle verbundenen Clients zu senden
+ public void broadcastMessage(String message) {
+ System.out.println(message);
+ if (message != null) {
+ for (ClientHandler client : clients) {
+ client.sendMessage(message); // Nachricht an jeden Client senden
+ }
+ }
+
+ }
+
+ public static void main(String[] args) {
+ new ChatServer(3141); // ChatServer auf Port 3141 starten (eventuell den Port flexibler noch wählen? falls belegt)
+
+ }
+ // Methode, um einen Client aus der Liste der verbundenen Clients zu entfernen
+ public void removeClient(ClientHandler client) {
+ clients.remove(client);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/ClientHandler.java b/src/main/java/ClientHandler.java
new file mode 100644
index 0000000..74fa305
--- /dev/null
+++ b/src/main/java/ClientHandler.java
@@ -0,0 +1,65 @@
+import java.io.*;
+import java.net.Socket;
+
+public class ClientHandler implements Runnable {
+ private ChatServer chatServer;
+ private Socket connectionToClient;
+ private String name;
+ private BufferedReader fromClientReader;
+ private PrintWriter toClientWriter;
+
+ // Constructor for ClientHandler
+ public ClientHandler(ChatServer chatServer, Socket connectionToClient) {
+ this.chatServer = chatServer;
+ this.connectionToClient = connectionToClient;
+ name = connectionToClient.getInetAddress().getHostAddress(); // Use the client's IP address as their name for simplicity
+
+ new Thread(this).start();} // Start a new thread for this client handler
+
+ @Override
+ public void run() {
+
+ try {
+ // Set up input and output streams for communication with the client
+ fromClientReader = new BufferedReader (new InputStreamReader(connectionToClient.getInputStream()));
+ toClientWriter = new PrintWriter (new OutputStreamWriter(connectionToClient.getOutputStream()));
+
+ chatServer.broadcastMessage(name + " connected."); // Broadcast a message when the client is connected
+
+ // Read messages from the client and broadcast them to all clients
+ String message = fromClientReader.readLine();
+ while (message!=null) {
+ // Broadcast the client's message to all connected clients
+ chatServer.broadcastMessage(name + ": " + message);
+ message = fromClientReader.readLine();
+ }
+ }
+
+ catch (IOException e) {
+ throw new RuntimeException(e); // Handle exceptions by throwing a runtime exception
+ }
+ finally {
+ chatServer.removeClient(this);
+ chatServer.broadcastMessage(name + " disconnected."); // Broadcast a message when the client is disconnected
+
+ // Close resources in the finally block
+ if (fromClientReader != null) {
+ try {
+ fromClientReader.close();
+ }
+ catch (IOException e){
+ e.printStackTrace();
+ }
+ }
+ if (toClientWriter != null) {
+ toClientWriter.close();
+ }
+ }
+ }
+
+ //Method to send a message to the client
+ public void sendMessage(String message) {
+ toClientWriter.println(message); // Send the message to the client
+ toClientWriter.flush(); // Flush the stream
+ }
+}
diff --git a/src/main/java/Constants.java b/src/main/java/Constants.java
new file mode 100644
index 0000000..5848138
--- /dev/null
+++ b/src/main/java/Constants.java
@@ -0,0 +1,5 @@
+public class Constants {
+ public static final int WINDOW_WIDTH = 800;
+ public static final int WINDOW_HEIGHT = 600;
+ public static final int PORT = 3141;
+}
diff --git a/src/main/java/CreateUser.java b/src/main/java/CreateUser.java
new file mode 100644
index 0000000..c799654
--- /dev/null
+++ b/src/main/java/CreateUser.java
@@ -0,0 +1,155 @@
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+
+import java.io.*;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import java.io.FileWriter;
+import java.io.IOException;
+
+import java.util.UUID;
+
+class CreateUser {
+ private String id;
+ private String userName;
+ private String password;
+ private String birthday;
+ private boolean stayLoggedIn;
+
+
+ // Constructor
+ public CreateUser(String id, String name, String password, String birthday) {
+ this.id = id;
+ this.userName = name;
+ this.password = password;
+ this.birthday = birthday;
+ }
+
+ // Getters and Setters
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(String birthday) {
+ this.birthday = birthday;
+ }
+
+ public boolean isStayLoggedIn() {
+ return stayLoggedIn;
+ }
+
+ public void setStayLoggedIn(boolean stayLoggedIn) {
+ this.stayLoggedIn = stayLoggedIn;
+ }
+
+ // Function to create user with validation
+ public static CreateUser createUser(String id, String userName, String password, String birthday) {
+ if (userName == null || userName.isEmpty()) {
+ throw new IllegalArgumentException("Username cannot be empty");
+ }
+ if (password == null || password.isEmpty()) {
+ throw new IllegalArgumentException("Password cannot be empty");
+ }
+ if (password.length() < 6) {
+ throw new IllegalArgumentException("Password must be at least 6 characters long");
+ } return new CreateUser(id, userName, password, birthday);
+ }
+
+ // Function to save to JSON file, replace with database call later
+ public void saveToJsonFile(String filename) {
+ List userList = readUserListFromJsonFile(filename);
+ userList.add(this);
+
+ try (FileWriter fileWriter = new FileWriter(filename)) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ gson.toJson(userList, fileWriter);
+ System.out.println("User information appended to " + filename);
+ } catch (IOException e) {
+ System.out.println("Error occurred while saving user information to JSON file: " + e.getMessage());
+ }
+ }
+
+ // Function to read user information from a JSON file
+ public static List readUserListFromJsonFile(String filename) {
+ List userList = new ArrayList<>();
+ try (Reader reader = new FileReader(filename)) {
+ Type userListType = new TypeToken>() {}.getType();
+ Gson gson = new Gson();
+ userList = gson.fromJson(reader, userListType);
+ } catch (FileNotFoundException e) {
+ // File does not exist yet, so return an empty list
+ } catch (IOException e) {
+ System.out.println("Error occurred while reading user information from JSON file: " + e.getMessage());
+ }
+ return userList;
+ }
+
+ // Function to update stayLoggedIn variable in the JSON file
+ public static void updateStayLoggedIn(String filename, String username, boolean stayLoggedIn) {
+ List userList = readUserListFromJsonFile(filename);
+
+ for (CreateUser user : userList) {
+ if (user.getUserName().equals(username)) {
+ user.setStayLoggedIn(stayLoggedIn);
+ break;
+ }
+ }
+
+ try (FileWriter fileWriter = new FileWriter(filename)) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ gson.toJson(userList, fileWriter);
+ System.out.println("StayLoggedIn updated in " + filename);
+ } catch (IOException e) {
+ System.out.println("Error occurred while updating StayLoggedIn in JSON file: " + e.getMessage());
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ // Example usage
+ UUID randomUUID = UUID.randomUUID();
+ CreateUser user = createUser(randomUUID.toString(), "Test User", "TestPasswort123", "01.01.2000");
+
+ // Example of accessing properties
+ System.out.println("UserID: " + user.getId());
+ System.out.println("User Name: " + user.getUserName());
+ System.out.println("User Password: " + user.getPassword());
+ System.out.println("User Birthday: " + user.getBirthday());
+
+
+ // Save user information to a JSON file
+ user.saveToJsonFile("user.json");
+
+ updateStayLoggedIn("user.json", "Test User", true);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Error: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/LoginGUI.java b/src/main/java/LoginGUI.java
new file mode 100644
index 0000000..675ffa5
--- /dev/null
+++ b/src/main/java/LoginGUI.java
@@ -0,0 +1,122 @@
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+public class LoginGUI extends JFrame implements ActionListener {
+ private JTextField usernameField;
+ private JPasswordField passwordField;
+ private JButton loginButton;
+ private JCheckBox stayLoggedInCheckbox;
+
+ public LoginGUI() {
+ setTitle("Login");
+ setSize(300, 180);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+ setLayout(null);
+
+ JLabel usernameLabel = new JLabel("Username:");
+ usernameLabel.setBounds(20, 20, 80, 25);
+ add(usernameLabel);
+
+ usernameField = new JTextField();
+ usernameField.setBounds(100, 20, 160, 25);
+ add(usernameField);
+
+ JLabel passwordLabel = new JLabel("Password:");
+ passwordLabel.setBounds(20, 50, 80, 25);
+ add(passwordLabel);
+
+ passwordField = new JPasswordField();
+ passwordField.setBounds(100, 50, 160, 25);
+ add(passwordField);
+
+ stayLoggedInCheckbox = new JCheckBox("Stay Logged In");
+ stayLoggedInCheckbox.setBounds(20, 80, 150, 25);
+ add(stayLoggedInCheckbox);
+
+ loginButton = new JButton("Login");
+ loginButton.setBounds(100, 110, 100, 25);
+ loginButton.addActionListener(this);
+ add(loginButton);
+
+ getRootPane().setDefaultButton(loginButton);
+
+ passwordField.addKeyListener(new EnterKeyListener());
+
+ stayLoggedInCheckbox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ boolean stayLoggedIn = stayLoggedInCheckbox.isSelected();
+ String username = usernameField.getText();
+ updateStayLoggedIn(username, stayLoggedIn);
+ }
+ });
+
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == loginButton) {
+ login();
+ }
+ }
+
+ private void login() {
+ String username = usernameField.getText();
+ String password = new String(passwordField.getPassword());
+ boolean stayLoggedIn = stayLoggedInCheckbox.isSelected(); // Get checkbox state
+
+ if (authenticateUser(username, password)) {
+ JOptionPane.showMessageDialog(this, "Login successful!");
+ // Perform actions after successful login
+
+ dispose();
+ } else {
+ JOptionPane.showMessageDialog(this, "Invalid username or password", "Login Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void updateStayLoggedIn(String username, boolean stayLoggedIn) {
+ // Update stayLoggedIn in the JSON file for the user
+ CreateUser.updateStayLoggedIn("user.json", username, stayLoggedIn);
+ }
+
+ // Function to authenticate the user by comparing the entered username and password with the saved user data
+ private boolean authenticateUser(String username, String password) {
+ List userList = CreateUser.readUserListFromJsonFile("user.json");
+ if (userList != null) {
+ for (CreateUser user : userList) {
+ if (user.getUserName().equals(username) && user.getPassword().equals(password)) {
+ return true; //Success
+ }
+ }
+ }
+ return false; // Fail
+ }
+
+
+ private class EnterKeyListener implements KeyListener {
+ @Override
+ public void keyTyped(KeyEvent e) {}
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+ login();
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {}
+ }
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(() -> {
+ LoginGUI loginGUI = new LoginGUI();
+ loginGUI.setVisible(true);
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/SignUpGUI.java b/src/main/java/SignUpGUI.java
new file mode 100644
index 0000000..b19cf8e
--- /dev/null
+++ b/src/main/java/SignUpGUI.java
@@ -0,0 +1,103 @@
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.util.UUID;
+
+public class SignUpGUI extends JFrame implements ActionListener {
+ private JTextField usernameField, passwordField, confirmPasswordField, birthdayField;
+ private JButton signUpButton;
+
+ public SignUpGUI() {
+ setTitle("Sign Up");
+ setSize(300, 250);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+ setLayout(null);
+
+ JLabel usernameLabel = new JLabel("Username:");
+ usernameLabel.setBounds(20, 20, 80, 25);
+ add(usernameLabel);
+
+ usernameField = new JTextField();
+ usernameField.setBounds(100, 20, 160, 25);
+ add(usernameField);
+
+ JLabel passwordLabel = new JLabel("Password:");
+ passwordLabel.setBounds(20, 50, 80, 25);
+ add(passwordLabel);
+
+ passwordField = new JPasswordField();
+ passwordField.setBounds(100, 50, 160, 25);
+ add(passwordField);
+
+ JLabel confirmPasswordLabel = new JLabel("Confirm Password:");
+ confirmPasswordLabel.setBounds(20, 80, 120, 25);
+ add(confirmPasswordLabel);
+
+ confirmPasswordField = new JPasswordField();
+ confirmPasswordField.setBounds(140, 80, 120, 25);
+ add(confirmPasswordField);
+
+ JLabel birthdayLabel = new JLabel("Birthday:");
+ birthdayLabel.setBounds(20, 110, 80, 25);
+ add(birthdayLabel);
+
+ birthdayField = new JTextField();
+ birthdayField.setBounds(100, 110, 160, 25);
+ add(birthdayField);
+
+ signUpButton = new JButton("Sign Up");
+ signUpButton.setBounds(100, 150, 100, 25);
+ signUpButton.addActionListener(this);
+ add(signUpButton);
+
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == signUpButton) {
+ String username = usernameField.getText();
+ String password = passwordField.getText();
+ String confirmPassword = confirmPasswordField.getText();
+ String birthday = birthdayField.getText();
+
+ if (!password.equals(confirmPassword)) {
+ JOptionPane.showMessageDialog(this, "Passwords do not match!", "Sign Up Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ if (!isUsernameAvailable("user.json", username)) {
+ JOptionPane.showMessageDialog(this, "Username already exists!", "Sign Up Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ try {
+ UUID randomUUID = UUID.randomUUID();
+ CreateUser user = CreateUser.createUser(randomUUID.toString(), username, password, birthday);
+ user.saveToJsonFile("user.json");
+ JOptionPane.showMessageDialog(this, "User signed up successfully!");
+ dispose();
+ } catch (IllegalArgumentException ex) {
+ JOptionPane.showMessageDialog(this, "Error: " + ex.getMessage(), "Sign Up Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ // Function to check if the input username doesn't already exist in the JSON file
+ private boolean isUsernameAvailable(String filename, String username) {
+ List userList = CreateUser.readUserListFromJsonFile(filename);
+ if (userList != null) {
+ for (CreateUser user : userList) {
+ if (user.getUserName().equals(username)) {
+ return false; // Username already exists
+ }
+ }
+ }
+ return true; // Username is available
+ }
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(() -> {
+ SignUpGUI signUpGUI = new SignUpGUI();
+ signUpGUI.setVisible(true);
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/test b/src/main/java/test
deleted file mode 100644
index e69de29..0000000
diff --git a/user.json b/user.json
new file mode 100644
index 0000000..5437c96
--- /dev/null
+++ b/user.json
@@ -0,0 +1,23 @@
+[
+ {
+ "id": "a2864d79-1079-4cbb-8d77-f5f84995580d",
+ "userName": "Another Test User",
+ "password": "TestPasswort123",
+ "birthday": "01.01.2000",
+ "stayLoggedIn": false
+ },
+ {
+ "id": "3690702d-9c7e-48fb-8a01-ef89b3b76268",
+ "userName": "TestUser2",
+ "password": "123456",
+ "birthday": "01.01.2000",
+ "stayLoggedIn": false
+ },
+ {
+ "id": "685bc3a6-e706-4214-a5e1-8443d1a5258e",
+ "userName": "Test User",
+ "password": "Test",
+ "birthday": "01.01.2000",
+ "stayLoggedIn": true
+ }
+]
\ No newline at end of file