mirror of
https://github.com/Akomry/sae302_applicom.git
synced 2025-12-06 08:43:54 +00:00
Merge branch 'dev-persistance' into 'dev'
feat(config): ajout de persistance de données See merge request iut_rt/but2/sae302-applicom/bouclyma!14
This commit is contained in:
commit
cbbb95f6d5
10 changed files with 153 additions and 18 deletions
|
|
@ -64,6 +64,12 @@
|
||||||
<artifactId>sqlite-jdbc</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<version>3.48.0.0</version>
|
<version>3.48.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>2.0.16</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ module rtgre.chat {
|
||||||
requires net.synedra.validatorfx;
|
requires net.synedra.validatorfx;
|
||||||
requires org.json;
|
requires org.json;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
|
requires org.xerial.sqlitejdbc;
|
||||||
|
|
||||||
|
|
||||||
opens rtgre.chat to javafx.fxml;
|
opens rtgre.chat to javafx.fxml;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ public class ChatLauncher {
|
||||||
ChatApplication.main(args);
|
ChatApplication.main(args);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
System.out.println("test2");
|
System.out.println("test2");
|
||||||
ChatApplication.main(args);
|
ChatApplication.main(args);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,23 +6,28 @@ import javafx.scene.Scene;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Locale;
|
import java.nio.file.Files;
|
||||||
import java.util.Objects;
|
import java.util.*;
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class ChatApplication extends Application {
|
public class ChatApplication extends Application {
|
||||||
public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName());
|
public static final Logger LOGGER = Logger.getLogger(ChatApplication.class.getCanonicalName());
|
||||||
|
private ChatController controller;
|
||||||
|
private Stage stage;
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
InputStream is = ChatApplication.class
|
InputStream is = ChatApplication.class
|
||||||
.getResource("logging.properties").openStream();
|
.getResource("logging.properties").openStream();
|
||||||
LogManager.getLogManager().readConfiguration(is);
|
LogManager.getLogManager().readConfiguration(is);
|
||||||
|
if (!Files.exists(new File("target/").toPath())) {
|
||||||
|
Files.createDirectory(new File("target").toPath());
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.log(Level.INFO, "Cannot read configuration file", e);
|
LOGGER.log(Level.INFO, "Cannot read configuration file", e);
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +46,44 @@ public class ChatApplication extends Application {
|
||||||
stage.setMinHeight(400);
|
stage.setMinHeight(400);
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
stage.show();
|
stage.show();
|
||||||
|
this.controller = fxmlLoader.getController();
|
||||||
|
this.stage = stage;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(getClass().getResourceAsStream("config.properties"));
|
||||||
|
if (!properties.getProperty("width").isEmpty() && !properties.getProperty("height").isEmpty()) {
|
||||||
|
stage.setWidth(Double.parseDouble(properties.getProperty("width")));
|
||||||
|
stage.setHeight(Double.parseDouble(properties.getProperty("height")));
|
||||||
|
}
|
||||||
|
if (properties.getProperty("posx").isEmpty() || properties.getProperty("height").isEmpty()) {
|
||||||
|
stage.centerOnScreen();
|
||||||
|
} else {
|
||||||
|
stage.setX(Double.parseDouble(properties.getProperty("posx")));
|
||||||
|
stage.setY(Double.parseDouble(properties.getProperty("posy")));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Cannot load stage config!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(getClass().getResourceAsStream("config.properties"));
|
||||||
|
properties.setProperty("width", String.valueOf(stage.getWidth()));
|
||||||
|
properties.setProperty("height", String.valueOf(stage.getHeight()));
|
||||||
|
properties.setProperty("posx", String.valueOf(stage.getX()));
|
||||||
|
properties.setProperty("posy", String.valueOf(stage.getY()));
|
||||||
|
|
||||||
|
properties.setProperty("split1", String.valueOf(controller.senderSplitPane.getDividerPositions()[0]));
|
||||||
|
properties.setProperty("split2", String.valueOf(controller.exchangeSplitPane.getDividerPositions()[0]));
|
||||||
|
LOGGER.finest(properties.toString());
|
||||||
|
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Cannot store stage info in config!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,12 @@ import rtgre.modeles.*;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -69,6 +69,7 @@ public class ChatController implements Initializable {
|
||||||
public Label statusLabel;
|
public Label statusLabel;
|
||||||
public Label dateTimeLabel;
|
public Label dateTimeLabel;
|
||||||
public Contact contact;
|
public Contact contact;
|
||||||
|
public SplitPane senderSplitPane;
|
||||||
private ContactMap contactMap = new ContactMap();
|
private ContactMap contactMap = new ContactMap();
|
||||||
private ObservableList<Contact> contactObservableList = FXCollections.observableArrayList();
|
private ObservableList<Contact> contactObservableList = FXCollections.observableArrayList();
|
||||||
private ObservableList<Post> postsObservableList = FXCollections.observableArrayList();
|
private ObservableList<Post> postsObservableList = FXCollections.observableArrayList();
|
||||||
|
|
@ -78,7 +79,8 @@ public class ChatController implements Initializable {
|
||||||
private RoomMap roomMap = new RoomMap();
|
private RoomMap roomMap = new RoomMap();
|
||||||
private ObservableList<Room> roomObservableList = FXCollections.observableArrayList();
|
private ObservableList<Room> roomObservableList = FXCollections.observableArrayList();
|
||||||
private ResourceBundle i18nBundle;
|
private ResourceBundle i18nBundle;
|
||||||
|
private Properties properties = new Properties();
|
||||||
|
private Vector<String> hostlist;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
|
|
@ -87,14 +89,41 @@ public class ChatController implements Initializable {
|
||||||
this.avatarImageView.setImage(image);
|
this.avatarImageView.setImage(image);
|
||||||
this.i18nBundle = resourceBundle;
|
this.i18nBundle = resourceBundle;
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream in = ChatController.class.getResourceAsStream("config.properties");
|
||||||
|
System.out.println(ChatController.class.getResource("config.properties").getPath());
|
||||||
|
properties.load(in);
|
||||||
|
if (contact != null) {
|
||||||
|
this.contact.setAvatar(Contact.base64ToImage(properties.getProperty("avatar")));
|
||||||
|
}
|
||||||
|
this.avatarImageView.setImage(SwingFXUtils.toFXImage(Contact.base64ToBufferedImage(properties.getProperty("avatar")), null));
|
||||||
|
for (String host : (String[]) properties.getProperty("hosts").split(",")) {
|
||||||
|
host = host.replace("[", "").replace("]", "").replace(" ", "");
|
||||||
|
hostComboBox.getItems().addAll(host);
|
||||||
|
}
|
||||||
|
hostComboBox.setValue(!properties.getProperty("lasthost").isEmpty() ? properties.getProperty("lasthost") : hostComboBox.getItems().get(0));
|
||||||
|
loginTextField.setText(!properties.getProperty("login").isEmpty() ? properties.getProperty("login") : "");
|
||||||
|
if (!properties.getProperty("split2").isEmpty()) {
|
||||||
|
exchangeSplitPane.setDividerPositions(Double.parseDouble(properties.getProperty("split2")));
|
||||||
|
}
|
||||||
|
if (!properties.getProperty("split1").isEmpty()) {
|
||||||
|
exchangeSplitPane.setDividerPositions(Double.parseDouble(properties.getProperty("split2")));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
LOGGER.warning("Impossible de charger le fichier de configuration! Configuration par défaut chargée");
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
Thread dateTimeLoop = new Thread(this::dateTimeLoop);
|
Thread dateTimeLoop = new Thread(this::dateTimeLoop);
|
||||||
dateTimeLoop.setDaemon(true);
|
dateTimeLoop.setDaemon(true);
|
||||||
dateTimeLoop.start();
|
dateTimeLoop.start();
|
||||||
|
|
||||||
hostComboBox.getItems().addAll("localhost:2024");
|
|
||||||
hostComboBox.getItems().addAll("localhost:2025");
|
|
||||||
hostComboBox.setValue("localhost:2024");
|
|
||||||
hostComboBox.setOnAction(this::statusNameUpdate);
|
hostComboBox.setOnAction(this::statusNameUpdate);
|
||||||
|
|
||||||
statusLabel.setText(i18nBundle.getString("disconnected"));
|
statusLabel.setText(i18nBundle.getString("disconnected"));
|
||||||
|
|
@ -141,6 +170,8 @@ public class ChatController implements Initializable {
|
||||||
if (controller.isOk()) {
|
if (controller.isOk()) {
|
||||||
hostComboBox.getItems().add(controller.hostTextField.getText());
|
hostComboBox.getItems().add(controller.hostTextField.getText());
|
||||||
hostComboBox.setValue(controller.hostTextField.getText());
|
hostComboBox.setValue(controller.hostTextField.getText());
|
||||||
|
properties.setProperty("hosts", hostComboBox.getItems().toString());
|
||||||
|
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warning("Impossible d'ouvrir la fenêtre de dialogue: fxml introuvable \n" + e.getMessage());
|
LOGGER.warning("Impossible d'ouvrir la fenêtre de dialogue: fxml introuvable \n" + e.getMessage());
|
||||||
|
|
@ -206,12 +237,21 @@ public class ChatController implements Initializable {
|
||||||
File selectedFile = fileChooser.showOpenDialog(stage);
|
File selectedFile = fileChooser.showOpenDialog(stage);
|
||||||
if (selectedFile != null) {
|
if (selectedFile != null) {
|
||||||
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
|
avatarImageView.setImage(new Image(selectedFile.toURI().toString()));
|
||||||
contact.setAvatar(ImageIO.read(selectedFile));
|
if (contact != null) {
|
||||||
|
contact.setAvatar(ImageIO.read(selectedFile));
|
||||||
|
}
|
||||||
|
properties.setProperty("avatar", Contact.imageToBase64(ImageIO.read(selectedFile)));
|
||||||
|
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warning("Impossible de lire l'image!");
|
LOGGER.warning("Impossible de lire l'image!");
|
||||||
}
|
}
|
||||||
client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
|
try {
|
||||||
|
client.sendEvent(new rtgre.modeles.Event("CONT", this.contact.toJsonObject()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.warning("Impossible d'envoyer l'évenement CONT! L'utilisateur est-il connecté?");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -243,6 +283,14 @@ public class ChatController implements Initializable {
|
||||||
initPostListView();
|
initPostListView();
|
||||||
this.statusLabel.setText("%s%s@%s:%s".formatted(i18nBundle.getString("connected"), this.contact.getLogin(), host, port));
|
this.statusLabel.setText("%s%s@%s:%s".formatted(i18nBundle.getString("connected"), this.contact.getLogin(), host, port));
|
||||||
this.connectionButton.setText(i18nBundle.getString("disconnect"));
|
this.connectionButton.setText(i18nBundle.getString("disconnect"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
properties.setProperty("login", loginTextField.getText());
|
||||||
|
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.warning("Unable to store login in config!");
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
new Alert(Alert.AlertType.ERROR, i18nBundle.getString("connectionError")).showAndWait();
|
new Alert(Alert.AlertType.ERROR, i18nBundle.getString("connectionError")).showAndWait();
|
||||||
connectionButton.setSelected(false);
|
connectionButton.setSelected(false);
|
||||||
|
|
@ -281,6 +329,13 @@ public class ChatController implements Initializable {
|
||||||
|
|
||||||
private void statusNameUpdate(Event event) {
|
private void statusNameUpdate(Event event) {
|
||||||
statusLabel.setText("not connected to " + hostComboBox.getValue());
|
statusLabel.setText("not connected to " + hostComboBox.getValue());
|
||||||
|
|
||||||
|
properties.setProperty("lasthost", hostComboBox.getValue());
|
||||||
|
try {
|
||||||
|
properties.store(new FileOutputStream(getClass().getResource("config.properties").getPath()), null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warning("Unable to write last host to config!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,4 +176,16 @@ public class Contact {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BufferedImage base64ToBufferedImage(String avatar64) {
|
||||||
|
byte[] bytes64 = Base64.getDecoder().decode(avatar64);
|
||||||
|
try {
|
||||||
|
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes64));
|
||||||
|
return image;
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.severe("Impossible de convertir le base64 en image");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import javax.xml.transform.Result;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import org.sqlite.JDBC;
|
||||||
|
|
||||||
import static rtgre.chat.ChatApplication.LOGGER;
|
import static rtgre.chat.ChatApplication.LOGGER;
|
||||||
|
|
||||||
|
|
@ -13,7 +14,7 @@ public class DatabaseApi {
|
||||||
|
|
||||||
public DatabaseApi() {
|
public DatabaseApi() {
|
||||||
try {
|
try {
|
||||||
this.con = DriverManager.getConnection("jdbc:sqlite:chat/src/main/resources/rtgre/chat/dbase.db");
|
this.con = DriverManager.getConnection("jdbc:sqlite:target/dbase.db");
|
||||||
this.stmt = con.createStatement();
|
this.stmt = con.createStatement();
|
||||||
initDB(con);
|
initDB(con);
|
||||||
LOGGER.info("Database connected!");
|
LOGGER.info("Database connected!");
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ import java.util.logging.Level;
|
||||||
import java.util.logging.LogManager;
|
import java.util.logging.LogManager;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static rtgre.chat.ChatApplication.LOGGER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Programme serveur qui renvoie les chaines de caractères lues jusqu'à recevoir le message "fin"
|
* Programme serveur qui renvoie les chaines de caractères lues jusqu'à recevoir le message "fin"
|
||||||
*/
|
*/
|
||||||
public class ChatServer {
|
public class ChatServer {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(ChatServer.class.getCanonicalName());
|
|
||||||
|
|
||||||
private Vector<ChatClientHandler> clientList;
|
private Vector<ChatClientHandler> clientList;
|
||||||
private PostVector postVector;
|
private PostVector postVector;
|
||||||
private ContactMap contactMap;
|
private ContactMap contactMap;
|
||||||
|
|
@ -41,6 +41,11 @@ public class ChatServer {
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
try {
|
||||||
|
Class.forName("org.sqlite.JDBC");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
ChatServer server = new ChatServer(2024);
|
ChatServer server = new ChatServer(2024);
|
||||||
//daisyConnect();
|
//daisyConnect();
|
||||||
server.acceptClients();
|
server.acceptClients();
|
||||||
|
|
|
||||||
|
|
@ -71,10 +71,10 @@
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
<SplitPane fx:id="exchangeSplitPane" dividerPositions="0.9" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
<SplitPane fx:id="exchangeSplitPane" dividerPositions="0.9" VBox.vgrow="ALWAYS">
|
||||||
<items>
|
<items>
|
||||||
<ListView fx:id="postListView" prefHeight="200.0" prefWidth="348.0" />
|
<ListView fx:id="postListView" prefHeight="200.0" prefWidth="348.0" />
|
||||||
<SplitPane dividerPositions="0.1" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0">
|
<SplitPane fx:id="senderSplitPane" dividerPositions="0.1" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0">
|
||||||
<items>
|
<items>
|
||||||
<ListView fx:id="roomsListView" prefHeight="200.0" prefWidth="200.0" />
|
<ListView fx:id="roomsListView" prefHeight="200.0" prefWidth="200.0" />
|
||||||
<ListView fx:id="contactsListView" prefHeight="200.0" prefWidth="200.0" />
|
<ListView fx:id="contactsListView" prefHeight="200.0" prefWidth="200.0" />
|
||||||
|
|
|
||||||
10
chat/src/main/resources/rtgre/chat/config.properties
Normal file
10
chat/src/main/resources/rtgre/chat/config.properties
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue