diff --git a/build.gradle b/build.gradle index 953b621..baa8f5a 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,8 @@ dependencies { runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win" runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux" runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac" + implementation 'com.google.code.gson:gson:2.8.6' + } mainClassName = 'app.insa.clav.Launcher' diff --git a/src/main/java/app/insa/clav/Core/Model.java b/src/main/java/app/insa/clav/Core/Model.java index 03d3c2a..ac3ac2b 100644 --- a/src/main/java/app/insa/clav/Core/Model.java +++ b/src/main/java/app/insa/clav/Core/Model.java @@ -4,10 +4,7 @@ import app.insa.clav.Messages.Message; import app.insa.clav.Messages.MessageChatTxt; import app.insa.clav.Messages.MessageInit; import app.insa.clav.Messages.MessagePseudo; -import app.insa.clav.Reseau.TCPChatConnection; -import app.insa.clav.Reseau.TCPListener; -import app.insa.clav.Reseau.UDPInput; -import app.insa.clav.Reseau.UDPOutput; +import app.insa.clav.Reseau.*; import javafx.application.Application; import javafx.application.Platform; import jdk.jshell.execution.Util; @@ -16,11 +13,9 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; -import java.util.ArrayList; +import java.nio.charset.StandardCharsets; +import java.util.*; import java.net.*; -import java.util.Collections; -import java.util.Timer; -import java.util.TimerTask; //Toutes les interactions avec l'utilisateur (pour tester) /** @@ -32,6 +27,9 @@ public class Model implements PropertyChangeListener{ * Liste des utilisateurs connectés. */ private ArrayList userList; + + private ServletConnection servCon; + /** * Timer qui permet de planifier des éxécutions dans le temps */ @@ -105,7 +103,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 */ private Model(int inputPort, int outputPort, int tcpListenerPort, Application app){ try { - this.user = new Utilisateurs("NA", InetAddress.getLocalHost(), 0, inputPort); + this.user = new Utilisateurs("NA", InetAddress.getLocalHost(), 0, inputPort, false); this.UDPOut = new UDPOutput(InetAddress.getLocalHost(), outputPort); this.UDPIn = new UDPInput(user.getInetAddress(),inputPort); this.tcpListener = new TCPListener(this.user.getInetAddress(),tcpListenerPort,user.getId()); @@ -120,6 +118,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 this.listTCPConnection = new ArrayList(); this.dbAccess = DataBaseAccess.getInstance(); this.app = app; + this.servCon = ServletConnection.getInstance(); } /** @@ -248,16 +247,47 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 * Méthode appelée par le controleur quand la vue envoie un signal d'appuis bouton changer Pseudo * @param pseudo * Pseudo rentré par l'utilisateur - * @return */ - public boolean choosePseudo(String pseudo, boolean isConfirmationNeeded){ + public void choosePseudo(String pseudo, boolean isConfirmationNeeded){ this.ancienPseudo = this.user.getPseudo(); this.user.setPseudo(pseudo); - this.UDPIn.setFilterValue(2,true); - this.UDPIn.setFilterValue(3,true); - this.sendPseudoBroadcast(); - this.tim.schedule(new TimerTaskResponseWait(isConfirmationNeeded),1000); - return true; + this.UDPIn.setFilterValue(2, true); + this.UDPIn.setFilterValue(3, true); + if (!this.user.isOutdoor()) { + this.sendPseudoBroadcast(); + this.tim.schedule(new TimerTaskResponseWait(isConfirmationNeeded), 2000); + ArrayList outdoorUsers = servCon.getRemoteActiveUsers(); + for (Utilisateurs newUser : outdoorUsers) { + if (newUser.getPseudo().equals(this.user.getPseudo())) { + this.isPseudoOk = false; + this.user.setPseudo(this.ancienPseudo); + this.ancienPseudo = ""; + this.support.firePropertyChange("pseudoRefused", this.user.getPseudo(), this.ancienPseudo); + } + if (!this.userList.contains(newUser)) { + this.userList.add(newUser); + Collections.sort(this.userList); + this.support.firePropertyChange("newUserConnected", -1, -2); + } + } + } + else{ + this.tim.schedule(new TimerTaskResponseWait(isConfirmationNeeded), 2000); + ArrayList users = servCon.getAllActiveUsers(); + for (Utilisateurs newUser : users) { + if (newUser.getPseudo().equals(this.user.getPseudo())) { + this.isPseudoOk = false; + this.user.setPseudo(this.ancienPseudo); + this.ancienPseudo = ""; + this.support.firePropertyChange("pseudoRefused", this.user.getPseudo(), this.ancienPseudo); + } + if (!this.userList.contains(newUser)) { + this.userList.add(newUser); + Collections.sort(this.userList); + this.support.firePropertyChange("newUserConnected", -1, -2); + } + } + } } /** Sets the id @@ -331,7 +361,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 break; case 2 : MessagePseudo msgP2 = (MessagePseudo) msg; - Utilisateurs newUser2 = new Utilisateurs(msgP2.pseudo,msgP2.srcIP,msgP2.id,msgP2.srcResponsePort); + Utilisateurs newUser2 = new Utilisateurs(msgP2.pseudo,msgP2.srcIP,msgP2.id,msgP2.srcResponsePort,false); if (!this.userList.contains(newUser2)) { this.userList.add(newUser2); Collections.sort(this.userList); @@ -341,7 +371,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 case 3 : System.out.println("Received message type 3"); MessagePseudo msgP3 = (MessagePseudo) msg; - Utilisateurs newUser3 = new Utilisateurs(msgP3.pseudo,msgP3.srcIP,msgP3.id,msgP3.srcResponsePort); + Utilisateurs newUser3 = new Utilisateurs(msgP3.pseudo,msgP3.srcIP,msgP3.id,msgP3.srcResponsePort,false); if (!this.userList.contains(newUser3)) { this.userList.add(newUser3); Collections.sort(this.userList); @@ -355,7 +385,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 break; case 4: MessagePseudo msgP4 = (MessagePseudo) msg; - Utilisateurs newUser4 = new Utilisateurs(msgP4.pseudo,msgP4.srcIP,msgP4.id,msgP4.srcResponsePort); + Utilisateurs newUser4 = new Utilisateurs(msgP4.pseudo,msgP4.srcIP,msgP4.id,msgP4.srcResponsePort,false); this.userList.remove(newUser4); this.userList.add(newUser4); Collections.sort(this.userList); @@ -363,7 +393,7 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 break; case 7 : MessagePseudo msgP7 = (MessagePseudo) msg; - Utilisateurs User7 = new Utilisateurs(msgP7.pseudo,msgP7.srcIP,msgP7.id,msgP7.srcResponsePort); + Utilisateurs User7 = new Utilisateurs(msgP7.pseudo,msgP7.srcIP,msgP7.id,msgP7.srcResponsePort,false); this.userList.remove(User7); this.support.firePropertyChange("newUserConnected",true,false); default : @@ -486,8 +516,6 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 } this.dbAccess.deleteHistory(remoteId,user.getId()); } - - /** * Classe interne au model pour au bout d'une seconde d'envoi de demande pseudo type 1, * on desactive les filtes et on met à jour la vue. @@ -514,7 +542,13 @@ ID 2 -> Listening on 6002, sending on 5002, tcpServer on 7002 support.firePropertyChange("pseudoValide",ancienPseudo,user.getPseudo()); UDPIn.setFilterValue(1,true); if (isConfirmationNeeded){ - sendPseudoValideBroadcast(); + if (!user.isOutdoor()) { + sendPseudoValideBroadcast(); + servCon.submitConnectionIndoor(user); + } + else{ + servCon.submitConnectionOutdoor(user); + } } } else{ diff --git a/src/main/java/app/insa/clav/Core/Utilisateurs.java b/src/main/java/app/insa/clav/Core/Utilisateurs.java index 5922246..cf41fcb 100644 --- a/src/main/java/app/insa/clav/Core/Utilisateurs.java +++ b/src/main/java/app/insa/clav/Core/Utilisateurs.java @@ -13,6 +13,7 @@ public class Utilisateurs implements Comparable{ private int id; private int port; private String login; + private boolean isOutdoor; public Date getLatestUpdate() { return latestUpdate; @@ -24,11 +25,12 @@ public class Utilisateurs implements Comparable{ private Date latestUpdate; - public Utilisateurs(String pseudo, InetAddress inetAddress, int id, int port) { + public Utilisateurs(String pseudo, InetAddress inetAddress, int id, int port, boolean isOutdoor) { this.pseudo = pseudo; this.inetAddress = inetAddress; this.id = id; this.port = port; + this.isOutdoor = isOutdoor; } public void setPseudo(String pseudo) { @@ -63,6 +65,16 @@ public class Utilisateurs implements Comparable{ return port; } + + public boolean isOutdoor() { + return isOutdoor; + } + + public void setOutdoor(boolean outdoor) { + isOutdoor = outdoor; + } + + @Override public String toString(){ return Integer.toString(this.id) + "|" + this.pseudo + "|" + this.inetAddress.toString() + "|" + Integer.toString(this.port); diff --git a/src/main/java/app/insa/clav/Reseau/ServletConnection.java b/src/main/java/app/insa/clav/Reseau/ServletConnection.java new file mode 100644 index 0000000..750c174 --- /dev/null +++ b/src/main/java/app/insa/clav/Reseau/ServletConnection.java @@ -0,0 +1,208 @@ +package app.insa.clav.Reseau; +import app.insa.clav.Core.Utilisateurs; +import app.insa.clav.Messages.MessagePseudo; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +public class ServletConnection { + + private static ServletConnection instance = null; + + public final GsonBuilder builder; + public final Gson gson; + public String baseURL; + + public ServletConnection(){ + builder = new GsonBuilder(); + gson = builder.create();; + //baseURL = "https://srv-gei-tomcat.insa-toulouse.fr/ServletJiggly/"; + baseURL = "http://localhost:8080/Gradle___com_example___ServeurClavardage_1_0_SNAPSHOT_war/"; + } + + public static ServletConnection getInstance(){ + synchronized(ServletConnection.class){ + if (instance == null) { + instance = new ServletConnection(); + } + } + return instance; + } + + public ArrayList getRemoteActiveUsers(){ + URL url = null; + HttpURLConnection con = null; + ArrayList resList = null; + try { + url = new URL(baseURL + "getOutdoorUsers"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + int status = con.getResponseCode(); + System.out.println("Error code HTTP request = " + status); + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer content = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + System.out.println("Response : " + content); + Type listType = new TypeToken>(){}.getType(); + resList = gson.fromJson(content.toString(),listType); + //resList = new Utilisateurs[Integer.parseInt(con.getHeaderField("sizeArray"))]; + } catch (IOException e) { + e.printStackTrace(); + } + return resList; + } + + public void submitConnectionIndoor(Utilisateurs user){ + URL url = null; + HttpURLConnection con = null; + try { + url = new URL(baseURL + "submitConnectionIndoor"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setDoOutput(true); + try(OutputStream os = con.getOutputStream()) { + byte[] input = gson.toJson(user).getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + int status = con.getResponseCode(); + System.out.println("Error code HTTP request submit indoor = " + status); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void submitConnectionOutdoor(Utilisateurs user) { + URL url = null; + HttpURLConnection con = null; + try { + url = new URL(baseURL + "submitConnectionOutdoor"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setDoOutput(true); + try(OutputStream os = con.getOutputStream()) { + byte[] input = gson.toJson(user).getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + int status = con.getResponseCode(); + System.out.println("Error code HTTP request submit outdoor = " + status); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public ArrayList getAllActiveUsers() { + URL url = null; + HttpURLConnection con = null; + ArrayList resList = null; + try { + url = new URL(baseURL + "getAllUsers"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + int status = con.getResponseCode(); + System.out.println("Error code HTTP request = " + status); + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer content = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + } + in.close(); + System.out.println("Response : " + content); + Type listType = new TypeToken>(){}.getType(); + resList = gson.fromJson(content.toString(),listType); + } catch (IOException e) { + e.printStackTrace(); + } + return resList; + } + + public void submitDeconnectionOutdoor(Utilisateurs user){ + URL url = null; + HttpURLConnection con = null; + try { + url = new URL(baseURL + "submitDeconnectionOutdoor"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setDoOutput(true); + try(OutputStream os = con.getOutputStream()) { + byte[] input = gson.toJson(user).getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + int status = con.getResponseCode(); + System.out.println("Error code HTTP request submit deco outdoor = " + status); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void submitDeconnectionIndoor(Utilisateurs user){ + URL url = null; + HttpURLConnection con = null; + try { + url = new URL(baseURL + "submitDeconnectionIndoor"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + + try { + con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setDoOutput(true); + try(OutputStream os = con.getOutputStream()) { + byte[] input = gson.toJson(user).getBytes(StandardCharsets.UTF_8); + os.write(input, 0, input.length); + } + int status = con.getResponseCode(); + System.out.println("Error code HTTP request submit deco indoor = " + status); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/app/insa/clav/UIControllers/ConnectionScreenController.java b/src/main/java/app/insa/clav/UIControllers/ConnectionScreenController.java index 421c3c7..89f57c8 100644 --- a/src/main/java/app/insa/clav/UIControllers/ConnectionScreenController.java +++ b/src/main/java/app/insa/clav/UIControllers/ConnectionScreenController.java @@ -4,6 +4,7 @@ import app.insa.clav.Core.DataBaseAccess; import app.insa.clav.Core.Model; import app.insa.clav.Core.Utilisateurs; import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXToggleButton; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.event.ActionEvent; @@ -117,6 +118,13 @@ public class ConnectionScreenController implements Initializable, PropertyChange */ private boolean isSubmittingNewPseudoIn; + + /** + * True if the user is outdoor + */ + @FXML + private JFXToggleButton isOutdoorUserButton; + private DataBaseAccess dbAccess; private String loginUp; @@ -193,6 +201,11 @@ public class ConnectionScreenController implements Initializable, PropertyChange } + @FXML + void outdoorUserAction(ActionEvent event) { + this.model.user.setOutdoor(this.isOutdoorUserButton.isSelected()); + } + /** * Handler of notifications sent by te model * @param evt @@ -204,7 +217,7 @@ public class ConnectionScreenController implements Initializable, PropertyChange this.model.deletePropertyChangeListener(this,"pseudoValide"); this.model.deletePropertyChangeListener(this,"pseudoRefused"); System.out.println("Pseudo valide"); - if (isSubmittingUp){ + if (isSubmittingUp && !this.model.user.isOutdoor()){ this.pseudoValideUp(); } if (this.isSubmittingNewPseudoIn){ diff --git a/src/main/resources/fxml/connectionScreen.fxml b/src/main/resources/fxml/connectionScreen.fxml index 78c6804..5f1af62 100644 --- a/src/main/resources/fxml/connectionScreen.fxml +++ b/src/main/resources/fxml/connectionScreen.fxml @@ -1,6 +1,7 @@ + @@ -50,5 +51,6 @@ +