diff --git a/Implementation/.classpath b/Implementation/.classpath deleted file mode 100644 index e6f7288..0000000 --- a/Implementation/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Implementation/.gitignore b/Implementation/.gitignore index ae3c172..5b76f25 100644 --- a/Implementation/.gitignore +++ b/Implementation/.gitignore @@ -1 +1,37 @@ -/bin/ +# Created by https://www.gitignore.io/api/java,gradle + +### Java ### +*.class + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### Gradle ### +.gradle +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +# End of https://www.gitignore.io/api/java,gradle diff --git a/Implementation/.project b/Implementation/.project deleted file mode 100644 index f54e1c1..0000000 --- a/Implementation/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - Implementation - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/Implementation/.settings/org.eclipse.jdt.core.prefs b/Implementation/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 8b9e3c7..0000000 --- a/Implementation/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,10 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=13 -org.eclipse.jdt.core.compiler.compliance=13 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning -org.eclipse.jdt.core.compiler.release=enabled -org.eclipse.jdt.core.compiler.source=13 diff --git a/Implementation/chatapp/.idea/.gitignore b/Implementation/chatapp/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Implementation/chatapp/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Implementation/chatapp/.idea/artifacts/chatapp.xml b/Implementation/chatapp/.idea/artifacts/chatapp.xml new file mode 100644 index 0000000..72f7f8f --- /dev/null +++ b/Implementation/chatapp/.idea/artifacts/chatapp.xml @@ -0,0 +1,6 @@ + + + $PROJECT_DIR$/out/artifacts/chatapp + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/chatapp.iml b/Implementation/chatapp/.idea/chatapp.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/Implementation/chatapp/.idea/chatapp.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/compiler.xml b/Implementation/chatapp/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/Implementation/chatapp/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/gradle.xml b/Implementation/chatapp/.idea/gradle.xml new file mode 100644 index 0000000..611e7c8 --- /dev/null +++ b/Implementation/chatapp/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/jarRepositories.xml b/Implementation/chatapp/.idea/jarRepositories.xml new file mode 100644 index 0000000..fdc392f --- /dev/null +++ b/Implementation/chatapp/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/libraries/lib.xml b/Implementation/chatapp/.idea/libraries/lib.xml new file mode 100644 index 0000000..bcdcd04 --- /dev/null +++ b/Implementation/chatapp/.idea/libraries/lib.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/libraries/mysql_connector_java_8_0_22.xml b/Implementation/chatapp/.idea/libraries/mysql_connector_java_8_0_22.xml new file mode 100644 index 0000000..8a0367c --- /dev/null +++ b/Implementation/chatapp/.idea/libraries/mysql_connector_java_8_0_22.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/misc.xml b/Implementation/chatapp/.idea/misc.xml new file mode 100644 index 0000000..e513ffa --- /dev/null +++ b/Implementation/chatapp/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/modules.xml b/Implementation/chatapp/.idea/modules.xml new file mode 100644 index 0000000..9509de3 --- /dev/null +++ b/Implementation/chatapp/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/modules/chatapp.iml b/Implementation/chatapp/.idea/modules/chatapp.iml new file mode 100644 index 0000000..73cec4e --- /dev/null +++ b/Implementation/chatapp/.idea/modules/chatapp.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/.idea/vcs.xml b/Implementation/chatapp/.idea/vcs.xml new file mode 100644 index 0000000..b2bdec2 --- /dev/null +++ b/Implementation/chatapp/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Implementation/chatapp/build.gradle b/Implementation/chatapp/build.gradle new file mode 100644 index 0000000..040b2e0 --- /dev/null +++ b/Implementation/chatapp/build.gradle @@ -0,0 +1,44 @@ +plugins { + id 'java' + id 'application' + id 'org.openjfx.javafxplugin' version '0.0.9' + id 'org.beryx.jlink' version '2.15.1' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +sourceCompatibility = 11 + +repositories { + mavenCentral() +} + +javafx { + version = "11.0.2" + modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.graphics', 'javafx.base'] +} + + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' + compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.22' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.22' + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win" + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux" + runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac" +} + +mainClassName = 'chatapp.Launcher' + +jlink { + options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] + launcher { + name = 'hellofx' + } +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/Implementation/chatapp/build/resources/main/fenetres/ConnexionScreen.fxml b/Implementation/chatapp/build/resources/main/fenetres/ConnexionScreen.fxml new file mode 100644 index 0000000..c09f679 --- /dev/null +++ b/Implementation/chatapp/build/resources/main/fenetres/ConnexionScreen.fxml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/chatapp/build/resources/main/fenetres/View_ChangementPseudo.fxml b/Implementation/chatapp/build/resources/main/fenetres/View_ChangementPseudo.fxml new file mode 100644 index 0000000..5bfabb7 --- /dev/null +++ b/Implementation/chatapp/build/resources/main/fenetres/View_ChangementPseudo.fxml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/chatapp/build/resources/main/fenetres/View_Clavardage.fxml b/Implementation/chatapp/build/resources/main/fenetres/View_Clavardage.fxml new file mode 100644 index 0000000..ebb0e85 --- /dev/null +++ b/Implementation/chatapp/build/resources/main/fenetres/View_Clavardage.fxml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/chatapp/build/tmp/compileJava/source-classes-mapping.txt b/Implementation/chatapp/build/tmp/compileJava/source-classes-mapping.txt new file mode 100644 index 0000000..d9e6c14 --- /dev/null +++ b/Implementation/chatapp/build/tmp/compileJava/source-classes-mapping.txt @@ -0,0 +1,39 @@ +chatapp/Protocol/RunnerEcouteTCP.java + chatapp.Protocol.RunnerEcouteTCP +chatapp/View/DemarrerSession.java + chatapp.View.DemarrerSession +chatapp/Controller/ChatApp.java + chatapp.Controller.ChatApp +chatapp/Model/DataBase.java + chatapp.Model.DataBase +chatapp/View/ChangementPseudo.java + chatapp.View.ChangementPseudo +chatapp/Protocol/RunnerEcouteUDP.java + chatapp.Protocol.RunnerEcouteUDP +chatapp/Launcher.java + chatapp.Launcher +chatapp/Model/ListUtilisateurs.java + chatapp.Model.ListUtilisateurs +chatapp/Protocol/UDPEchange.java + chatapp.Protocol.RunnerUDP + chatapp.Protocol.UDPEchange +chatapp/Model/MessageHorodate.java + chatapp.Model.MessageHorodate +chatapp/Main.java + chatapp.Main +chatapp/View/View_Menu.java + chatapp.View.View_Menu +chatapp/Protocol/SessionClavardage.java + chatapp.Protocol.SessionClavardage +chatapp/View/ConnexionScreen.java + chatapp.View.ConnexionScreen +chatapp/View/View_Utilisateurs.java + chatapp.View.View_Utilisateurs +chatapp/Model/Utilisateur.java + chatapp.Model.Utilisateur +chatapp/View/FenetreSession.java + chatapp.View.FenetreSession + chatapp.View.FenetreSession$1 +chatapp/View/Clavardage.java + chatapp.View.Clavardage + chatapp.View.Clavardage$1 diff --git a/Implementation/chatapp/gradle/wrapper/gradle-wrapper.jar b/Implementation/chatapp/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/Implementation/chatapp/gradle/wrapper/gradle-wrapper.jar differ diff --git a/Implementation/chatapp/gradle/wrapper/gradle-wrapper.properties b/Implementation/chatapp/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..be52383 --- /dev/null +++ b/Implementation/chatapp/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Implementation/chatapp/gradlew b/Implementation/chatapp/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/Implementation/chatapp/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/Implementation/chatapp/gradlew.bat b/Implementation/chatapp/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/Implementation/chatapp/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Implementation/chatapp/settings.gradle b/Implementation/chatapp/settings.gradle new file mode 100644 index 0000000..876b43d --- /dev/null +++ b/Implementation/chatapp/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'chatapp' + diff --git a/Implementation/chatapp/src/main/java/chatapp/Controller/ChatApp.java b/Implementation/chatapp/src/main/java/chatapp/Controller/ChatApp.java new file mode 100644 index 0000000..2014c2a --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Controller/ChatApp.java @@ -0,0 +1,309 @@ +package chatapp.Controller; + +import chatapp.Model.*; +import chatapp.Protocol.*; +import javafx.application.Application; +import javafx.application.Platform; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ChatApp implements PropertyChangeListener { + + /* Liste des utilisateurs actifs */ + private ListUtilisateurs actifUsers ; + + /* ChatApp est associe a un utilisateur */ + private Utilisateur me; + + /* ChatApp est associe a une application qui le lance et que chatapp doit fermer a la fin */ + private Application main; + + private static ChatApp chatapp = null; + private RunnerEcouteTCP runnerEcouteTCP; + private RunnerEcouteUDP runnerEcouteUDP; + private boolean connecte; + private DataBase db; + + public boolean isConnecte() { + return connecte; + } + + /** + *

Constructeur de l'application de chat

+ * + * @param pseudo Pseudo de l'utilisateur + * @param port Port de communication + */ + public ChatApp(String pseudo, Integer port, Application main){ + this.actifUsers = new ListUtilisateurs() ; + // Recuperer adresse IP de l'utilisateur + InetAddress ip = null ; + ip = UDPEchange.getCurrentIp(); + this.me = new Utilisateur(pseudo,port,ip); + this.actifUsers.addList(getMe()); + + this.main = main; + this.db= DataBase.getInstance(); + this.connecte=false; + } + + /** + *

Methode permettant de créer qu'une seule instance de chatapp

+ * @param pseudo le pseudonyme que l'on souhaite donner à l'utilisateur + * @param port le port auquel on souhaite receptionner les requêtees UDP + * @param main le stage de l'interface graphique qui crée l'instance + * @return une instance de chatapp + */ + public static synchronized ChatApp getInstance(String pseudo, Integer port, Application main){ + if (chatapp == null) { + chatapp = new ChatApp(pseudo, port, main); + } + return chatapp; + } + + /** + * + * @return recupere l'instance de chatapp qui a ete creee au prealable + */ + public static ChatApp getInstance(){ + return chatapp; + } + + + + /*public void majHistorique2(MessageHorodate mh, String pseudo) { + Historique h = getMapHistorique().get(pseudo); + //h.addMessage(mh); + getMapHistorique().put(h.getUser2().getPseudo(),h); + }*/ + + + /** + *

Modification du pseudo de l'utilisateur + * Envoie en broadcast ses informations utilisateurs et son nouveau pseudo

+ * + * @param nouveau correspond au nouveau pseudo + * @return False si modiferPseudo a echoue, True sinon + */ + public Boolean modifierPseudo(String nouveau) throws IOException { + // Message que l'on envoie à tous les utilisateurs actifs + String broadcastMessage = "Demande Modification Pseudo\n" + this.getMe().toString() + "\n" + nouveau + "\n"; + UDPEchange.EnvoiBroadcast(broadcastMessage); + try { + Thread.sleep(2000); + /* L'utilisateur doit attendre la reponse de tous les utilisateurs connectes + * pour savoir si son pseudo est accepte + */ + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (UDPEchange.getPseudoValide()) { + System.out.println("Modification pseudo reussie"); + //Envoi un msg en broadcast a tout les utilisateurs pour les prevenir de son nouveau pseudo// + broadcastMessage = "Modification pseudo reussie\n" + this.getMe().toString() + "\n" + nouveau + "\n"; + UDPEchange.EnvoiBroadcast(broadcastMessage); + //-------Change son propre nom d'utilisateur-------// + this.getActifUsers().modifierList(this.getMe().getPseudo(), nouveau); + this.getMe().setPseudo(nouveau); + db.majPseudo(this.me.getId(),nouveau); + System.out.println("Changement pseudo accepte, nouvelle liste des utilisateurs actifs:"); + this.getActifUsers().afficherListeUtilisateurs(); + return true; + } + else + { + System.out.println("Echec Modification pseudo"); + return false; + } + } + + + /** + *

Methode appelee lors de la connexion d'un nouvel utilisateur. + * Il va prevenir les utilisateurs du reseau de son arrivee.

+ * @return False si Connexion a echoue, True sinon + */ + public Boolean connexion() throws IOException { + // Message que l'on envoie à tous les utilisateurs actifs + String broadcastMessage = "Connexion\n" + this.getMe().toString() ; + UDPEchange.EnvoiBroadcast(broadcastMessage); + try { + Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (UDPEchange.getConnecte()) { + System.out.println("Connexion reussie"); + return true; + } + else + { + System.out.println("Connexion echoue"); + UDPEchange.setConnecte(true); + return false ; + } + } + + /** + *

Methode appelee lors de la connexion de l'utilisateur, va prevenir les autres + * utlisateurs du reseau de l'arrivee de l'utilisateur sur celui-ci

+ * @param pseudo le pseudonyme avec lequel l'utilisateur souhaite se connecter + * @return False si Connexion a echoue, True sinon + * @throws IOException + */ + public Boolean connexion(String pseudo) throws IOException { + // Message que l'on envoie à tous les utilisateurs actifs + this.me.setPseudo(pseudo); + String broadcastMessage = "Connexion\n" + this.getMe().toString() ; + UDPEchange.EnvoiBroadcast(broadcastMessage); + try { + Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (UDPEchange.getConnecte()) { + System.out.println("Connexion reussie"); + this.connecte=true; + this.db.ajoutUtilisateurs(this.me.getId(),pseudo); + this.db.majUtilisateursActifs(true,this.me.getId()); + return true; + } + else + { + System.out.println("Connexion echoue"); + UDPEchange.setConnecte(true); + return false ; + } + } + + /** + *

Lance un thread pour ecouter les requetes TCP + * Informe le pcs que chatapp ecoute les notifications qu'il envoie

+ */ + public void activerEcouteTCP(){ + this.runnerEcouteTCP = new RunnerEcouteTCP(this); + this.runnerEcouteTCP.addPropertyChangeListener(this); + } + + /** + *

Demarre une session de clavardage avec l'utilisateur dont le pseudo est entre en parametre

+ * @param pseudo le pseudo de l'utilisateur avec lequel on souhaite communiquer + */ + public void demarrerSession(String pseudo){ + Utilisateur u2 = this.actifUsers.getPseudoList(pseudo); + SessionClavardage session = new SessionClavardage(u2,this); + runnerEcouteTCP.addSession(session); + } + + /** + *

Lance le thread pour receptionner les requetes UDP

+ */ + public void activerEcouteUDP(){ + this.runnerEcouteUDP = new RunnerEcouteUDP(this); + this.runnerEcouteUDP.start(); + } + /** + *

Methode appelee lors de la deconnexion de l'utilisateur. + * Il va prevenir les utilisateurs du reseau de son depart.

+ * + */ + public void deconnexion() throws IOException { + // Message que l'on envoie à tous les utilisateurs actifs + String broadcastMessage = "Deconnexion\n" + this.getMe().toString() ; + UDPEchange.EnvoiBroadcast(broadcastMessage); + db.majUtilisateursActifs(false,this.me.getId()); + this.connecte=false; + try { + main.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + Platform.exit(); + System.exit(0); + } + + /** + * Getter + * @return Utilisateur associee a ChatApp + */ + public Utilisateur getMe() { + return me; + } + + /** + * Getter + * @return Liste des utilisateurs actifs associee a ChatApp + */ + public ListUtilisateurs getActifUsers() { + return actifUsers; + } + + + + + /*public static void main (String[] args) throws IOException { + ChatApp app = new ChatApp(args[0],Integer.parseInt(args[1]),this.app) ; + System.out.println("On lance le chatapp"); + + + ExecutorService execUDP = Executors.newFixedThreadPool(1000); + execUDP.submit(new RunnerEcouteUDP(app)); + try { + app.connexion(); + } catch (IOException e) { + e.printStackTrace(); + } + ExecutorService execTCP = Executors.newFixedThreadPool(1000); + System.out.println("On lance l'écoute TCP de chatapp"); + execTCP.submit(new RunnerEcouteTCP(app)); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if(app.getMe().getPseudo().equals("Marvel")) { + app.getHist("Doudou").afficher10derniers(); + System.out.println("Tentative de connexion avec Doudou"); + TCPEchange.demarrerSession(app, app.actifUsers.getPseudoList("Doudou")); + } + + + + }*/ + + /** + *

Handler des differents evenements que chatapp ecoute

+ * @param evt l'evenement qui a ete indique par le pcs + */ + @Override + public void propertyChange(PropertyChangeEvent evt) { + switch (evt.getPropertyName()){ + case "chatCreated" : + SessionClavardage session = this.runnerEcouteTCP.getSessionClavardage(); + session.addPropertyChangeListener(this); + break; + } + } + + /** + *

Permet de recuperer stage de l'interface graphique qui a cree l'instance

+ * @return le stage de l'interface graphique qui a cree l'instance + */ + public Application getMain() { + return main; + } + + /** + *

Permet de recuperer la base de donnee associee

+ * @return la base de donnee associee + */ + public DataBase getDb(){return this.db;} +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Launcher.java b/Implementation/chatapp/src/main/java/chatapp/Launcher.java new file mode 100644 index 0000000..c464364 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Launcher.java @@ -0,0 +1,7 @@ +package chatapp; + +public class Launcher { + public static void main(String[] args) { + Main.main(args); + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Main.java b/Implementation/chatapp/src/main/java/chatapp/Main.java new file mode 100644 index 0000000..776724b --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Main.java @@ -0,0 +1,62 @@ +package chatapp; + +import chatapp.Controller.ChatApp; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Rectangle2D; +import javafx.scene.Scene; +import javafx.stage.Screen; +import javafx.stage.Stage; + +import java.io.IOException; + +public class Main extends Application { + ChatApp chatapp; + + /** + * Permet de lancer la fenetre principale de l'application + * @param primaryStage notre fenetre principale + * @throws Exception + */ + @Override + public void start(Stage primaryStage) throws Exception { + Rectangle2D tailleEcran = Screen.getPrimary().getBounds(); + this.chatapp = ChatApp.getInstance("Null",1234,this); + FXMLLoader fichier = new FXMLLoader(getClass().getResource("/fenetres/ConnexionScreen.fxml")); + Scene scene1 = new Scene(fichier.load(),600,400); + primaryStage.setScene(scene1); + primaryStage.setTitle("ChatApp"); + primaryStage.setMinWidth(600); + primaryStage.setMinHeight(400); + //primaryStage.setMaxWidth(600); + //primaryStage.setMaxHeight(400); + /*primaryStage.setMaxWidth(tailleEcran.getWidth()); + primaryStage.setMaxHeight(tailleEcran.getHeight());*/ + primaryStage.show(); + primaryStage.centerOnScreen(); + chatapp.activerEcouteTCP(); + chatapp.activerEcouteUDP(); + + } + + /** + *

Handler associe a la fermeture de l'application

+ * @throws Exception + */ + @Override + public void stop() throws Exception { + if(chatapp.isConnecte()){ + chatapp.deconnexion(); + } + else { + super.stop(); + Platform.exit(); + System.exit(0); + } + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Model/DataBase.java b/Implementation/chatapp/src/main/java/chatapp/Model/DataBase.java new file mode 100644 index 0000000..a7fbbd6 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Model/DataBase.java @@ -0,0 +1,482 @@ +package chatapp.Model; + +import java.sql.*; + +/** + *

+ * Classe representant la Base de données. + * Celle-ci stocke la liste des utilisateurs ainsi que les échanges entre eux + *

+ */ +public class DataBase { + private final String DBurl = "jdbc:mysql://srv-bdens.insa-toulouse.fr:3306" ; + private Connection connection = null; + private final String login = "tp_servlet_006"; + private final String pswd = "baePh9ei"; + + + /*Format de la table Utilisateurs + +--------+-------------+---------+---------------------+ + | ID | Pseudo | Actif | Date d'inscription | + +--------+-------------+---------+---------------------+ + Id correspond à l'addresse IP + Pseudo : Dernier Pseudo utilisé pour cette adresse IP, va etre remplacé par le pseudo actuel avec majPseudo + Date d'inscription comme son nom l'indique le jour de l'inscription de cette utilisateur + Actif est un boolean indicant si l'utilisateur est actif + + Chaque communication entres utilisateurs sera stocké dans une table de la forme + +------------------+-----------+---------------+---------------+ + | Destinataire | Source | Message | Date d'envoi | + +--------+---------------------+---------------+---------------+ + Destinataire -> Id du destinataire du message + Source -> Id de celui qui envoie le message + Message -> Msg envoye + Date d'envoie -> Date a laquelle Source a envoye le message a destinataire + */ + + private static final DataBase instance = null; // Singleton + + /** + * Constructeur de la database + * On installe le driver et on établit la connection. + */ + public DataBase() { + try { + //Besoin d'installer le driver JDBC entre java IDE et le system DBMS pour faire un pont entre les deux + Class.forName("com.mysql.cj.jdbc.Driver"); + System.out.println("Driver Installe"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + System.out.println("Echec installation Driver"); + } + try { + //Etablir une connexion , forme : (url, "myLogin", "myPassword"); + // Nabil : DECOMMENTER CETTE LIGNE + //this.connection = DriverManager.getConnection("jdbc:mysql://localhost/POO_AL_NM?allowPublicKeyRetrieval=true&useSSL=false", "root", "1234"); + // Auriane : DECOMMENTER CETTE LIGNE + this.connection = DriverManager.getConnection("jdbc:mysql://localhost:8889/POO_AL_NM?allowPublicKeyRetrieval=true&useSSL=false", "root", "root"); + //this.connection = DriverManager.getConnection(this.DBurl,login,pswd); + System.out.println("Connexion Etablie"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec d'etablissement de la connexion"); + } + } + + /** + * Méthode permettant de renvoyer une instance de la classe DataBase + * @return Retourne l'instance du singleton DataBase. + */ + public static DataBase getInstance() { + synchronized (DataBase.class) { + return new DataBase(); + } + } + + /** + * Methode permettant de creer une table pour stocker les messages entre deux utilisateurs + * @param ID1 Id du premier utilisateur + * @param ID2 Id du second utilisateur + */ + public void CreationTableHistorique(String ID1 , String ID2) { + // Pour eviter d'avoir les tables en double + String petit; + String grand; + int comparaison = ID1.compareTo(ID2); + if (comparaison < 0) { + petit = ID1; + grand = ID2 ; + } + else { + petit = ID2; + grand = ID1 ; + } + String nomTable = "Chat_" + petit + "_" + grand ; + String Requete = "CREATE TABLE IF NOT EXISTS`" + nomTable +"` (\n" + "`Destinataire` varchar(100) NOT NULL,\n" + " `Source` varchar(100) NOT NULL,\n" + " `Envoi` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + " `Message` text NOT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;"; + System.out.println(Requete); + PreparedStatement Ps = null ; + //Statement est utilisé pour envoyer une requete SQL à la base de donnee + try { + Ps = connection.prepareStatement(Requete); + System.out.println("Statement cree"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec creation Statement"); + } + //Execute la donnée SQL statement passe en parametre + try { + assert Ps != null; + Ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println(" Echec executeUpdate "); + } + } + + /** + * Methode permettant de mettre a jour le pseudo d'un utilisateur en fonction de son ID dans la base de donnee + * @param ID Id de l'utilisateur qui vient de changer de pseudo + * @param Pseudo Nouveau Pseudo de l'utilisateur + */ + public void majPseudo( String ID , String Pseudo) { + String requete= "UPDATE `Utilisateurs` SET `Pseudo`=? WHERE id=?"; + PreparedStatement Ps = null ; + //Statement est utilisé pour envoyer une requete SQL à la base de donnee + try { + Ps = connection.prepareStatement(requete); + Ps.setString(1, Pseudo); // ? n°1 devient la valeur contenu dans Pseudo + Ps.setString(2, ID); // ? n°2 devient la valeur contenu dans ID + System.out.println("Statement cree"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec creation Statement"); + } + //Execute la donnée SQL statement passe en parametre + try { + assert Ps != null; + Ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println(" Echec executeUpdate "); + } + } + + + + /** + * Methode permettant de mettre a jour le pseudo d'un utilisateur en fonction de son ID dans la base de donnee + * @param IDdest Id de l'utilisateur Destinataire du message + * @param IDsrc Id de celui qui envoi le message + * @param Msg Message envoye entre les deux utilisateurs + */ + public void ajoutHistorique(String IDdest , String IDsrc, String Msg) { + String petit; + String grand; + int comparaison = IDdest.compareTo(IDsrc); + if (comparaison < 0) { + petit = IDdest; + grand = IDsrc ; + } + else { + petit = IDsrc; + grand = IDdest ; + } + String nomTable = "Chat_" + petit + "_" + grand ; + String requete= "INSERT INTO `"+ nomTable +"`(`Destinataire`, `Source`, `Message`) VALUES ( ? , ? , ?)"; + PreparedStatement Ps = null ; + //Statement est utilisé pour envoyer une requete SQL à la base de donnee + try { + Ps = connection.prepareStatement(requete); + Ps.setString(1, IDdest); // ? n°1 devient la valeur contenu dans IDdest + Ps.setString(2, IDsrc); // ? n°2 devient la valeur contenu dans IDsrc + Ps.setString(3, Msg); // ? n°3 devient la valeur contenu dans Msg + //La date de l'envoi n'a pas besoin d'être renseigné, elle est automatique + System.out.println("Statement cree"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec creation Statement"); + } + //Execute la donnée SQL statement passe en parametre + try { + assert Ps != null; + Ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println(" Echec executeUpdate "); + } + } + + + /** + * Methode permettant d'ajouter un utilisateur dans la base de donnée si celui-ci n'existe pas deja + * @param ID Id de l'utilisateur que l'on veut rajouter + * @param Pseudo pseudo actuelle de l'utilisateur + */ + public void ajoutUtilisateurs(String ID , String Pseudo ) { + if(this.idExiste(ID)){ + this.majPseudo(ID, Pseudo); + } + else { + // L'utilisateur n'existe pas , on va le rajouter. + System.out.println("On rajoute l'utilisateur " + Pseudo); + String requete = "INSERT INTO `Utilisateurs` (`ID`, `Pseudo`, `Actif`) VALUES ( ? , ? , '1')"; + PreparedStatement Ps = null; + //Statement est utilisé pour envoyer une requete SQL à la base de donnee + try { + Ps = connection.prepareStatement(requete); + Ps.setString(1, ID); // ? n°1 devient la valeur contenu dans ID + Ps.setString(2, Pseudo); // ? n°2 devient la valeur contenu dans Pseudo + System.out.println("Statement cree"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec creation Statement"); + } + //Execute la donnée SQL statement passe en parametre + try { + assert Ps != null; + Ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println(" Echec executeUpdate "); + } + } + } + + /** + * Methode permettant de mettre a jour les utilisateurs actuellement actif + * @param Id Id de l'utilisateur qui vient de se connecter ou deconnecter + * @param Connecte Boolean true si il est connecte , false sinon + */ + public void majUtilisateursActifs(Boolean Connecte, String Id) { + String requete= "UPDATE `Utilisateurs` SET `Actif`=? WHERE id=?"; + PreparedStatement Ps = null ; + int Actif = Connecte ? 1 : 0; // True -> 1 , False -> 0 + //Statement est utilisé pour envoyer une requete SQL à la base de donnee + try { + Ps = connection.prepareStatement(requete); + Ps.setInt(1, Actif); // ? n°1 devient la valeur contenu dans Actif (1 ou 0) + Ps.setString(2, Id); // // ? n°2 devient la valeur contenu dans Id + System.out.println("Statement cree"); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("Echec creation Statement"); + } + //Execute la donnée SQL statement passe en parametre + try { + assert Ps != null; + Ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + System.out.println(" Echec executeUpdate "); + } + } + + /** + * Methode permettant de recuperer les N derniers messages envoyés entre 2 utilisateurs + * @param ID Utilisateur associé a ChatApp + * @param IDdestinataire Celui avec qui correspond ID + * @param N le nombre de messages souhaités + * @return Les N derniers Messages + */ + public String recupNMsg(String ID, String IDdestinataire, int N) { + StringBuilder Msg = new StringBuilder(); + String petit; + String grand; + int comparaison = ID.compareTo(IDdestinataire); + if (comparaison < 0) { + petit = ID; + grand = IDdestinataire; + } + else { + petit = IDdestinataire; + grand = ID ; + } + String nomTable = "Chat_" + petit + "_" + grand ; + String requete = "SELECT * FROM `"+ nomTable +"`"; + Statement stmt = null; + ResultSet rs = null ; + try { + stmt = this.connection.createStatement(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + try { + assert stmt != null; + rs = stmt.executeQuery(requete); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + Integer Taille = tailleBDD(nomTable); + if(Taille < N ){ + N = Taille ; + } + for(int i = 0 ; i < N; i++){ + try { + assert rs != null; + if( rs.next()){ + String IDSource = rs.getString("Source"); + String Envoi = rs.getTimestamp("Envoi").toString(); + String Message = rs.getString("Message"); + if (IDSource.equals(ID)) Msg.append("Moi (").append(Envoi).append(") : ").append(Message); + else { + String PseudoSource = getPseudo(IDSource) ; + Msg.append(PseudoSource).append(" (").append(Envoi).append(") : ").append(Message); + } + Msg.append('\n'); + } + // MSG de la forme : + // Source (Date) : Texte + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + return Msg.toString(); + } + + /** + * Methode permettant de recuperer le pseudo actuel d'un utilisateur en fonction de son ID + * @param idSource Id de l'utilsateur dont on veut connaitre le pseudo + * @return Pseudo + */ + private String getPseudo(String idSource) { + String Pseudo = "" ; + String requete= "SELECT * FROM `Utilisateurs` WHERE `ID` LIKE '" + idSource + "'"; + Statement stmt = null; + ResultSet rs = null ; + try { + stmt = this.connection.createStatement(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + try { + assert stmt != null; + rs = stmt.executeQuery(requete); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + try { + assert rs != null; + if (rs.next()){ + Pseudo = rs.getString("Pseudo") ; + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + return Pseudo ; + } + + /** + * Methode permettant de recuperer les messages d'une plage de donnée [deb,fin] envoyés entre 2 utilisateurs + * @param ID Utilisateur associé a ChatApp + * @param IDdestinataire Celui avec qui correspond ID + * @param deb On veut les messages à partir de l'indice deb + * @param fin On veut les messages jusqu'a l'indice fin + * @return Les messages d'une plage de donnée [deb,fin] + */ + public String recupMsg(String ID, String IDdestinataire, int deb , int fin) { + StringBuilder Msg = new StringBuilder(); + String petit; + String grand; + int comparaison = ID.compareTo(IDdestinataire); + if (comparaison < 0) { + petit = ID; + grand = IDdestinataire; + } + else { + petit = IDdestinataire; + grand = ID ; + } + String nomTable = "Chat_" + petit + "_" + grand ; + String requete = "SELECT * FROM `"+ nomTable+"`"; + Statement stmt = null; + ResultSet rs = null ; + try { + stmt = this.connection.createStatement(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + try { + assert stmt != null; + rs = stmt.executeQuery(requete); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + Integer Taille = tailleBDD(nomTable); + if(Taille < fin ){ + fin = Taille ; + } + for(int i = 0 ; i < fin; i++){ + try { + assert rs != null; + if( rs.next()){ + String IDSource = rs.getString("Source"); + String Envoi = rs.getTimestamp("Envoi").toString(); + String Message = rs.getString("Message"); + if (i >= deb) { + if (IDSource.equals(ID)) { + Msg.append("Moi (").append(Envoi).append(") : ").append(Message); + } else { + String PseudoSource = getPseudo(IDSource); + Msg.append(PseudoSource).append(" (").append(Envoi).append(") : ").append(Message); + } + Msg.append('\n'); + } + } + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + } + + return Msg.toString(); + } + + /** + * Cette méthode sert à recuperer la taille d'un base de donnée + * @param nomTable Nom de la table de donnée dont on veut récuperer le nom + * @return Taille de la BDD + */ + public Integer tailleBDD(String nomTable) { + Integer Taille = 0 ; + String requete = "SELECT * FROM `"+nomTable+ "`"; + Statement stmt = null; + ResultSet rs = null ; + try { + stmt = this.connection.createStatement(); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + try { + assert stmt != null; + rs = stmt.executeQuery(requete); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + while(true){ + try { + assert rs != null; + if (!rs.next()) break; + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + Taille++; // on incremente Taille pour chaque solution trouvée + } + return Taille; + } + + /** + * Methode permettant de savoir si un utilisateur existe dans la base de donnée 'Utilisateurs' + * @param ID On recherche l'utilisateur dont l'ID est ID + * @return True si l'utilisateur existe , False sinon + */ + public boolean idExiste(String ID){ + boolean existe = false ; + // Verification que l'utilisateur n'existe pas + String requete = "SELECT * FROM `Utilisateurs` WHERE `ID` LIKE '" + ID +"'"; + Statement stmt; + ResultSet rs = null ; + try { + stmt = this.connection.createStatement(); + rs = stmt.executeQuery(requete); + } catch (SQLException throwables) { + throwables.printStackTrace(); + } + existe = (!rs.equals(null)); + return existe; + } + + public String getNomTable(Utilisateur U1, Utilisateur U2){ + String petit; + String grand; + int comparaison; + comparaison = U1.getId().compareTo(U2.getId()); + if (comparaison < 0) { + petit = U1.getId(); + grand = U2.getId(); + } + else { + petit = U2.getId() ; + grand = U1.getId() ; + } + return "Chat_" + petit + "_" + grand ; + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Model/ListUtilisateurs.java b/Implementation/chatapp/src/main/java/chatapp/Model/ListUtilisateurs.java new file mode 100644 index 0000000..cf755af --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Model/ListUtilisateurs.java @@ -0,0 +1,142 @@ +package chatapp.Model; + +import java.net.InetAddress; +import java.util.ArrayList; + +/** + *

+ * Classe representant La liste des utilisateurs actifs, stockée localement + *

+ */ +public class ListUtilisateurs { + + // On conserve dans cette liste tout les utilisateurs actuellement actifs + private ArrayList actifUsers ; + + /** + * Constructeur : initialise la liste 'actifUsers' + */ + public ListUtilisateurs() { + this.actifUsers = new ArrayList<>() ; + } + + /** + * Ajouter des utilisateurs actifs dans l'attribut liste 'actifUsers' + * @param u on va rajouter cet utilisateur dans la liste + */ + public void addList(Utilisateur u) { + if((verifierUnicite(u.getPseudo()))) { + this.actifUsers.add(u); + } + } + + /** + * Recuperer un utilisateur a partir de son pseudo + * @param pseudo Pseudo de l'utilisateur que l'on souhaite retrouver + */ + public Utilisateur getPseudoList(String pseudo) { + for(Utilisateur elem: this.actifUsers) + { + if (elem.getPseudo().equals(pseudo) ) { + return elem ; + } + } + return null ; + } + + /** + * Recuperer un utilisateur a partir de son addresse IP + * @param ip @IP de l'utilisateur que l'on souhaite retrouver + */ + public Utilisateur getIPList(InetAddress ip) throws Exception { + for(Utilisateur elem: this.actifUsers) + { + if (elem.getIp().equals(ip) ) { + return elem ; + } + } + throw new Exception("No such user with this IP address") ; + } + + /** + * Supprimer de la liste des utilisateurs actifs 'actifUsers' un certain utilisateur + * @param u on va supprimer cet utilisateur dans la liste + */ + public void supprimerList(Utilisateur u) { + boolean Sup = false ; + for(Utilisateur elem: this.actifUsers) + { + if (elem.equals(u) ) { + this.actifUsers.remove(elem); + Sup = true ; + this.afficherListeUtilisateurs(); + } + } + if (!Sup) { + System.out.println("Tentative de retirer un objet non contenu dans la liste"); + } + } + + /** + * Modifier le pseudo d'un utilisateur dans la liste des utilisateurs actifs 'actifUsers' + * @param ancien correspond au pseudo remplacer + * @param nouveau correspond au nouveau pseudo + */ + public void modifierList(String ancien , String nouveau) { + for(Utilisateur elem: this.actifUsers) + { + if (ancien.equals( elem.getPseudo() ) ) { + this.actifUsers.remove(elem); + elem.setPseudo(nouveau); + this.addList(elem); + } + } + this.afficherListeUtilisateurs(); + } + + /** + * Methode permettant de savoir si un utilisateur est contenu dans la liste 'actifUsers' + * @param u on souhait savoir si cette utilisateur appartient a la liste + * @return True si il appartient, false sinon + */ + public Boolean appartient(Utilisateur u) { + return this.actifUsers.contains(u); + } + + + /** + * Verifie qu'aucun autre utilisateur ne possede le meme pseudo + * @param pseudo on va supprimer cet utilisateur dans la liste + * @return True si aucun utilisateur de la liste possede ce pseudo, false sinon + */ + public Boolean verifierUnicite(String pseudo) { + for(Utilisateur elem: this.actifUsers) + { + if (pseudo.equals( elem.getPseudo() ) ) { + return false ; + } + } + return true; + } + + /** + * Methode affichant la liste des utilisateurs actifs + */ + public void afficherListeUtilisateurs() { + System.out.println ("Liste des utilisateurs actifs : "); + StringBuilder Utilisateur = new StringBuilder(); + for(Utilisateur elem: this.actifUsers) + { + System.out.println (elem.toString()); + Utilisateur.append(elem).append("\n"); + } + } + + /** + * Getter + * @return La liste des utilisateurs actifs + */ + public ArrayList getActifUsers(){ + return this.actifUsers; + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Model/MessageHorodate.java b/Implementation/chatapp/src/main/java/chatapp/Model/MessageHorodate.java new file mode 100644 index 0000000..fec6bdf --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Model/MessageHorodate.java @@ -0,0 +1,174 @@ +package chatapp.Model; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + *

+ * Classe representant les messages envoyes en TCP lors d'une session de clavardage. + * Un message Horodate est compose d'un destintaire, d'une source , d'un message et d'une date d'envoie. + *

+ */ +public class MessageHorodate implements Serializable { + private Utilisateur destinataire ; + private Utilisateur source ; + private Date dateHorodatage ; + private int type; // 0 = debut de la communication, 1= message de communication, 2 = fin de la communicataion + private String Message; + + /** + *

+ * Constructeur , le message va etre horodate + * @param destinataire - Destinataire du message + * @param source - Source du message + * @param Message - Message envoye + *

+ */ + public MessageHorodate(Utilisateur destinataire, Utilisateur source, String Message, int type) { + this.setDestinataire(destinataire) ; + this.setSource(source) ; + this.setMessage(Message) ; + this.setDateHorodatage(new Date()); + this.type = type; + } + + /** + * Setter: Date d'horodatage + * On modifie le date d'horodatage + */ + public void setDate(Date d) { + this.setDateHorodatage(d); + } + + /** + *

+ * Permet de creer une representation string du message + * @return Les differents attributs de la classe sous forme de string + *

+ */ + @Override + public String toString() { + String Msg = ""; + Msg += ("Destinataire::" + this.getDestinataire() + "\n") ; + Msg += ("Source::" + this.getSource()+ "\n") ; + Msg += ("Type::"+ this.type+ "\n"); + Msg += ("Date::" + this.dateToString() + "\n") ; + Msg += ("Message::" + this.getMessage() + "\n" ); + return Msg ; + } + + /** + *

+ * Permet de creer une representation string de la date d'horodatage + * @return La date d'horodatage du message en format yyyy/MM/dd HH:mm:ss + *

+ */ + public String dateToString() { + DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + return format.format(this.getDateHorodatage()); + } + + + /** + *

+ * Permet de re creer un message horodate a partir d'un string + * @return un messageHorodate + *

+ */ + public static MessageHorodate stringToMessageHorodate(String s) { + String[] mots = s.split("\n"); + Utilisateur destinataire = Utilisateur.stringToUtilisateur(mots[0].split("::")[1]); + Utilisateur source = Utilisateur.stringToUtilisateur(mots[1].split("::")[1]); + int type = Integer.parseInt(mots[2].split("::")[1]); + String payload = ""; + for(int i=4; i< mots.length; i++) { + if(mots[i].startsWith("Message::")) { + mots[i]=mots[i].split("::")[1]; + } + payload += mots[i]+"\n"; + } + return new MessageHorodate(destinataire, source, payload, type); + } + + /** + * Getter: Utilisateur Source + * @return Utilisateur a l'origine du message + */ + public Utilisateur getSource() { + return source; + } + + /** + * Setter: Utilisateur Source + * On modifie l'utilisateur source + */ + public void setSource(Utilisateur source) { + this.source = source; + } + + /** + * Getter: Utilisateur Destinataire + * @return Utilisateur recevant le message + */ + public Utilisateur getDestinataire() { + return destinataire; + } + + /** + * Setter: Utilisateur Destinataire + * On modifie l'utilisateur Destinataire + */ + public void setDestinataire(Utilisateur destinataire) { + this.destinataire = destinataire; + } + + /** + * Getter: Message envoye + * @return Le message envoye + */ + public String getMessage() { + return Message; + } + + /** + * Setter: Message envoye + * On modifie le message envoye + */ + public void setMessage(String message) { + Message = message; + } + + /** + * Getter: 'Type' du message + * @return On recupere le Type du message + */ + public int getType() { + return type; + } + /** + * Setter: 'Type' du message horodate + * On modifie l'integer 'Type' + */ + public void setType(int Type) { + this.type = type; + } + + /** + * Getter: Date d'horodatage + * @return On recupere le date + */ + public Date getDateHorodatage() { + return dateHorodatage; + } + + /** + * Setter: Date d'horodatage + * On modifie le date. + */ + public void setDateHorodatage(Date dateHorodatage) { + this.dateHorodatage = dateHorodatage; + } + +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Model/Utilisateur.java b/Implementation/chatapp/src/main/java/chatapp/Model/Utilisateur.java new file mode 100644 index 0000000..dabb920 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Model/Utilisateur.java @@ -0,0 +1,90 @@ +package chatapp.Model; + + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + *

+ * Classe representant un Utilisateur + * Un Utilisateur est associe avec un pseudo, un numero de port, une addresse IP ainsi qu'un ID. + *

+ */ +public class Utilisateur { + + private String pseudo ; + private Integer port; + private final InetAddress ip ; + private final String id ; + + /** + * Constructeur : Utilisateur + * @param pseudo Le pseudo associe + * @param port + * @param ip + */ + public Utilisateur(String pseudo,Integer port, InetAddress ip ){ + this.setPseudo(pseudo) ; + this.setPort(port); + this.ip = ip ; + this.id = ip.getHostName() ; + } + + public String getPseudo() { + return pseudo; + } + + public void setPseudo(String pseudo) { + this.pseudo = pseudo; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public InetAddress getIp() { + return ip; + } + public String getId() { + return id; + } + + @Override + public String toString(){ + String s = ""; + s+="pseudo " + this.pseudo + " | "; + s+="port " + (this.port).toString() + " | "; + s+="ip " + (this.ip).toString() + " | "; + s+="id " + (this.id).toString() + " | "; + return s; + } + + public static Utilisateur stringToUtilisateur(String s) { + String name; + Integer port = 0; + String ip = "" ; + String id = ""; + String mots[] = s.split(" "); + name=mots[1]; + port=Integer.parseInt(mots[4]); + ip=mots[7]; + id=mots[10]; + Utilisateur user = null; + try { + user = new Utilisateur(name,port,InetAddress.getByName(ip.split("/")[1])); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return user; + } + + + public Boolean equals(Utilisateur u) { + return this.getId().equals( u.getId() ) ; + } + +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteTCP.java b/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteTCP.java new file mode 100644 index 0000000..7e09bf4 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteTCP.java @@ -0,0 +1,92 @@ +package chatapp.Protocol; + +import chatapp.Controller.ChatApp; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; + +/** + *

+ * Classe permettant de gérer les multiples connexions en TCP. + * Extend la classe Thread. + *

+ */ +public class RunnerEcouteTCP extends Thread { + public ChatApp app ; + private PropertyChangeSupport pcs; + // on conserve les sessions actives dans un attribut liste + private ArrayList ListeSessions = new ArrayList<>(); + + /** + * Constructeur + * @param app Un RunnerEcouteTCP est toujours associé a une application de Chat + */ + public RunnerEcouteTCP(ChatApp app) { + this.app = app ; + this.pcs = new PropertyChangeSupport(this); + this.start(); + } + + /** + * Permet aux classes qui appelle cette methode de connecter un PropertyChangeListener au PropertyChangeSupport + * @param pcl le propertyChangeListener qui va ecouter les evenements du propertyChangeSupport associe + */ + public void addPropertyChangeListener(PropertyChangeListener pcl) { + this.pcs.addPropertyChangeListener("NouvelleSession",pcl); + } + + /** + *

+ * Methode pour qu'un objet de la classe ChatApp soit constamment en a l'ecoute de potentielles connexions + * @param app L'utilisateur en ecoute de potentielles communications + *

+ */ + public void ecouteTCP(ChatApp app) { + ServerSocket ss; + System.out.println("Ecoute TCP activee"); + try { + ss = new ServerSocket(5000); // On ecoute sur le port 5000 + System.out.println("Socket d'ecoute cree"); + while(true) { // Ecoute en boucle + System.out.println("Attente Session de clavardage"); + Socket link = ss.accept(); // Blocante + SessionClavardage session = new SessionClavardage(link,app); + this.ListeSessions.add(session); + pcs.firePropertyChange("NouvelleSession",false,true); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Methode permettant d'ajouter une session active dans la liste 'ListeSessions' + * @param session Session Active que l'on souhaite rajouter + */ + public void addSession(SessionClavardage session){ + this.ListeSessions.add(session); + pcs.firePropertyChange("NouvelleSession",false,true); + } + + /** + * Methode permettant de recupere la derniere session de clavardage creee dans 'ListeSessions' + * @return Premiere Session Active + */ + public SessionClavardage getSessionClavardage() { + return(this.ListeSessions.remove(0)); + } + + /** + * Methode qui vient ecraser la méthode run de la classe Thread. + * La méthode 'ecouteTCP' est appele. + */ + @Override + public void run() { + ecouteTCP(this.app); + } + +} \ No newline at end of file diff --git a/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteUDP.java b/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteUDP.java new file mode 100644 index 0000000..06f2d9a --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Protocol/RunnerEcouteUDP.java @@ -0,0 +1,16 @@ +package chatapp.Protocol; + +import chatapp.Controller.ChatApp; + +public class RunnerEcouteUDP extends Thread { + ChatApp app ; + public RunnerEcouteUDP(ChatApp app) { + this.app = app ; + } + @Override + public void run() { + + UDPEchange.ecouteUDP(app); + + } +} \ No newline at end of file diff --git a/Implementation/chatapp/src/main/java/chatapp/Protocol/SessionClavardage.java b/Implementation/chatapp/src/main/java/chatapp/Protocol/SessionClavardage.java new file mode 100644 index 0000000..0a4f3d5 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Protocol/SessionClavardage.java @@ -0,0 +1,186 @@ +package chatapp.Protocol; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.ArrayList; + +import chatapp.Controller.ChatApp; +import chatapp.Model.DataBase; +import chatapp.Model.MessageHorodate; +import chatapp.Model.Utilisateur; +import chatapp.View.FenetreSession; +import javafx.application.Platform; + +public class SessionClavardage extends Thread { + private Socket link; + private ChatApp app; + private Utilisateur u2; + private ObjectOutputStream out; + private ObjectInputStream in; + private PropertyChangeSupport pcs; + private ArrayList derniersMsg; // on met temporairement les derniers msgs pour éviter les pb de synchro inter-threads + private int SessionID; + public SessionClavardage(Socket link, ChatApp app) { + this.setLink(link); + this.setApp(app); + try { + this.setU2(app.getActifUsers().getIPList(link.getInetAddress())); + this.setOut(new ObjectOutputStream(link.getOutputStream())); + this.setIn(new ObjectInputStream(link.getInputStream())); + }catch(Exception e) { + e.getStackTrace(); + } + this.derniersMsg = new ArrayList(); + this.SessionID = 2; + Platform.runLater( () -> + new FenetreSession(this) + ); + this.pcs = new PropertyChangeSupport(this); + this.start(); + } + + public SessionClavardage(Utilisateur u2, ChatApp app) { + this.setU2(u2); + this.setApp(app); + try { + Socket s = new Socket(u2.getIp(),5000); + this.setOut(new ObjectOutputStream(s.getOutputStream())); + this.setIn(new ObjectInputStream(s.getInputStream())); + this.setLink(s); + } catch (IOException e) { + + e.printStackTrace(); + } + this.derniersMsg = new ArrayList(); + this.pcs = new PropertyChangeSupport(this); + this.app.getDb().CreationTableHistorique("Doudou","Marvel"); + this.start(); + Platform.runLater( () -> + new FenetreSession(this) + ); + } + + + public void addPropertyChangeListener(PropertyChangeListener pcl){ + this.pcs.addPropertyChangeListener("MessageRecu",pcl); + this.pcs.addPropertyChangeListener("FinDeLaSession",pcl); + } + + public void arretSession() { + MessageHorodate msgh = new MessageHorodate(getU2(),getApp().getMe(),".",2); + try { + getOut().writeObject(msgh.toString()); + } catch (IOException e) { + //e.printStackTrace(); + } + finally { + try { + link.close(); + } catch (IOException e) { + + } + } + } + public void envoiMsg(String msg) { + MessageHorodate msgh = new MessageHorodate(getU2(),getApp().getMe(),msg,1); + try { + getOut().writeObject(msgh.toString()); + app.getDb().ajoutHistorique(u2.getId(), app.getMe().getId(),msg); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public MessageHorodate getDernierMsg() { + return this.derniersMsg.remove(0); + } + + + + public void run() { + String plaintext = null; + MessageHorodate msg = null; + System.out.println("Session demarre"); + app.getDb().CreationTableHistorique(app.getMe().getId(), u2.getId()); + while(true) { + try { + plaintext = (String) getIn().readObject(); + msg = MessageHorodate.stringToMessageHorodate(plaintext); + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + pcs.firePropertyChange("FinDeLaSession", false, true); + break; + } + if(msg.getType() == 2) { + pcs.firePropertyChange("FinDeLaSession", false, true); + try { + link.close(); + } catch (IOException e) { + break; + } + break; + } + derniersMsg.add(msg); + pcs.firePropertyChange("MessageRecu",false,true); + + } + } + + public ObjectOutputStream getOut() { + return out; + } + + public void setOut(ObjectOutputStream out) { + this.out = out; + } + + public ObjectInputStream getIn() { + return in; + } + + public void setIn(ObjectInputStream in) { + this.in = in; + } + + public Socket getLink() { + return link; + } + + public void setLink(Socket link) { + this.link = link; + } + + public ChatApp getApp() { + return app; + } + + public void setApp(ChatApp app) { + this.app = app; + } + + public Utilisateur getU2() { + return u2; + } + + public void setU2(Utilisateur u2) { + this.u2 = u2; + } + + + public int getSessionID() { + return SessionID; + } + + public void setSessionID(int sessionID) { + SessionID = sessionID; + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/Protocol/UDPEchange.java b/Implementation/chatapp/src/main/java/chatapp/Protocol/UDPEchange.java new file mode 100644 index 0000000..fadfbf5 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/Protocol/UDPEchange.java @@ -0,0 +1,365 @@ +package chatapp.Protocol; + +import java.io.IOException; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.Inet4Address; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import chatapp.Controller.*; +import chatapp.Model.*; +/** + *

+ * Classe representant les echanges UDP entre utilisateurs. + *

+ */ + +public class UDPEchange { + + private static Boolean Connecte = true; + // True si l'utilisateur peut se connecter avec ce nom d'utilisateur , False sinon + + private static Boolean EcouteEnCours = false; + /** + * Getter + * @return le boolean connecte (True s'il peut se connecter avec ce nom d'utilisateur , False sinon) + */ + public static Boolean getConnecte() { + return Connecte; + } + + /** + * Setter + * @param value La nouvelle valeur du boolean de connexion + */ + public static void setConnecte(Boolean value) { + Connecte = value ; + } + + private static Boolean PseudoValide = true; + // True si l'utilisateur a (ou demande) un pseudo valide , False sinon + + /** + * Getter + * @return le boolean PseudoValide (True s'il peut utiliser ce pseudo , False sinon) + */ + public static Boolean getPseudoValide() { + return PseudoValide; + } + + /** + * Setter + * @param value La nouvelle valeur du boolean concernant le pseudo valide + */ + public static void setPseudoValide(Boolean value) { + PseudoValide = value ; + } + + + /**

+ * Permet de recuperer l'adresse de l'hote sur le reseau au format IPv4. + * Si plusieurs adresses sont disponibles (plusieurs cartes réseaux), choisit la premiere trouvee + *

+ * @return l'adresse IP au format IPv4 + */ + public static InetAddress getCurrentIp() { + try { + Enumeration networkInterfaces = NetworkInterface + .getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface) networkInterfaces + .nextElement(); + Enumeration nias = ni.getInetAddresses(); + while(nias.hasMoreElements()) { + InetAddress ia= (InetAddress) nias.nextElement(); + if (!ia.isLinkLocalAddress() + && !ia.isLoopbackAddress() + && ia instanceof Inet4Address) { + return ia; + } + } + } + } catch (Exception e) { + System.out.println("unable to get current IP " + e.getMessage()); + } + return null; + } + /** + *

+ * Méthode permettant d'envoyer un message à tout les utilisateurs + * a l'aide du protocole UDP + *

+ * @param broadcastMessage correspond au message a transmettre aux utilisateurs + */ + public static void EnvoiBroadcast(String broadcastMessage) throws IOException { + int port = 1234 ; + // Envoie en broadcast à tous les utilsateurs + for (InetAddress broadcastAddr : listAllBroadcastAddresses()) { + DatagramSocket socket = new DatagramSocket(); + socket.setBroadcast(true); + byte[]buffer = broadcastMessage.getBytes(); + DatagramPacket packet = new DatagramPacket( buffer, buffer.length, broadcastAddr,port); + socket.send(packet); + socket.close(); + System.out.println("Broadcast sent with address " + broadcastAddr.toString()); + System.out.println("***********Message envoye***********"); + System.out.println("Dest Ip: " + broadcastAddr.toString()); + System.out.println("Dest port: " + String.valueOf(port)); + System.out.println("Contenu: "); + System.out.println(broadcastMessage); + System.out.println("************************************"); + } + } + + /** + *

+ * Methode permettant la reception de messages d'utilisateurs + * a l'aide du protocole UDP + *

+ * @param app L'application de chat de l'utilisateur qui receptionne le message + */ + public static void ecouteUDP(ChatApp app) + { + DatagramSocket socket = null; + ExecutorService exec = Executors.newFixedThreadPool(1000); + try { + socket = new DatagramSocket(1234); + } catch (SocketException e1) { + e1.printStackTrace(); + } + byte buffer[] = new byte[1024]; + System.out.println("Ecoute sur le port: 1234"); + while(true) + { + DatagramPacket data = new DatagramPacket(buffer,buffer.length); + try { + socket.receive(data); + } catch (IOException e) { + e.printStackTrace(); + } + // Un thread est lance à chaque reception d'un message + System.out.println("Message recu!"); + exec.submit(new RunnerUDP(data,app)); + } + } + + /** + *

+ * Methode permettant d'envoyer un message a utilisateur en particulier + * a l'aide du protocole UDP + *

+ * @param Adress l'addresse de l'utilisateur + * @param Message correspond au message à transmettre a l'utilisateur + */ + public static void envoiUnicast( InetAddress Adress , String Message ) throws IOException { + DatagramSocket socket = new DatagramSocket(); + byte[]buffer = Message.getBytes(); + DatagramPacket packet = new DatagramPacket( buffer, buffer.length, Adress, 1234 ); + socket.send(packet); + socket.close(); + System.out.println("***********Message envoye***********"); + System.out.println("Dest Ip: " + Adress.toString()); + System.out.println("Dest port: " + String.valueOf(1234)); + System.out.println("Contenu: "); + System.out.println(Message); + System.out.println("************************************"); + } + + /** + *

+ * Methode permettant de recuperer la liste des adresses de broadcast, chacune associer à une interface de la machine + *

+ */ + static List listAllBroadcastAddresses() throws SocketException { + List broadcastList = new ArrayList<>(); + Enumeration interfaces + = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface networkInterface = interfaces.nextElement(); + + if (networkInterface.isLoopback() || !networkInterface.isUp()) { + continue; + } + + networkInterface.getInterfaceAddresses().stream() + .map(a -> a.getBroadcast()) + .filter(Objects::nonNull) + .forEach(broadcastList::add); + } + return broadcastList; + } + +} + + + +/** + *

+ * Classe implementant l'interface Runnable. + * Contient les traitements a executer dans un thread lancer par des methodes de la class UDPEchange + *

+ */ +class RunnerUDP implements Runnable { + final DatagramPacket data ; + ChatApp app ; + + public RunnerUDP(DatagramPacket data, ChatApp app) { + this.data= data; + this.app = app ; + } + + /** + *

+ * Methode qui redefinie les traitements qui seront executes dans le thread: + * Met à jour la liste des utilisateurs actifs + *

+ * + */ + @Override + public void run() { + System.out.println("Thread started"); + String received = new String(data.getData(), 0, data.getLength()); + System.out.println("***********Message recu***********"); + System.out.println(received); + System.out.println("**********************************"); + String Type = received.split("\n")[0]; + + //**************************************************************************************************** + //**************************************************************************************************** + //****************************************Demande de connexion**************************************** + //**************************************************************************************************** + //**************************************** + if (Type.equals("Connexion")) { // un utilisateur vient d'arriver sur le reseau + System.out.println("Reception d'une demande de connexion"); + Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[1]); + if (! u.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même + String reponse = "Reponse Connexion\n"; + if (!( app.getActifUsers() ).verifierUnicite(u.getPseudo())) { + System.out.println("Pseudo deja present dans la liste"); + reponse += "false\n"; + } + else { + System.out.println("Ajout d'un nouvel utilisateur dans la liste des Utilisateurs"); + ( app.getActifUsers() ).addList(u); + reponse += "true\n"; + + } + reponse += app.getMe().toString(); + + try { + UDPEchange.envoiUnicast(u.getIp(),reponse); + }catch(IOException e) + { + System.out.println("Echec de l'envoi du message"); + } + + ( app.getActifUsers() ).afficherListeUtilisateurs(); + } + } + //******************************************************************************************************* + //******************************************************************************************************* + //****************************************Reponse d'une connexion**************************************** + //******************************************************************************************************* + //******************************************************************************************************* + + if (Type.equals("Reponse Connexion")) { // Un utilisateur te repond suite à ta demande de connexion + + if((received.split("\n")[1]).equals("true")) { + Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[2]); + app.getActifUsers().addList(u); + app.getActifUsers().afficherListeUtilisateurs(); + } + else { + System.out.println("Pseudo deja pris"); + UDPEchange.setConnecte(false); + } + } + + //******************************************************************************************************************* + //******************************************************************************************************************* + //****************************************Demande de modification d'un pseudo**************************************** + //******************************************************************************************************************* + //******************************************************************************************************************* + + if (Type.equals("Demande Modification Pseudo")) { + Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]); + if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même + String nouveau = received.split("\n")[2] ; + String Message = ""; + if(( app.getActifUsers() ).verifierUnicite(nouveau)) { + Message = "Bon Choix Pseudo\n" + nouveau ; + } + else { + Message = "Mauvais Choix Pseudo\n" ; + } + System.out.println(Message); + try { + UDPEchange.envoiUnicast(Source.getIp(),Message); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + //************************************************************************************************************ + //************************************************************************************************************ + //**************************************** Modification pseudo reussi **************************************** + //************************************************************************************************************ + //************************************************************************************************************ + + if (Type.equals("Modification pseudo reussi")) { + Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]); + if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même + String nouveau = received.split("\n")[2] ; + if(app.getActifUsers().appartient(Source)) { // On verifie d'abord que Source appartient bien a la liste des utilisateurs actifs + app.getActifUsers().modifierList(Source.getPseudo(), nouveau); + } + { + // Suite a une perte d'un message lors d'une connexion l'utilisateur Source n'apparait pas dans la liste + app.getActifUsers().addList(Source); + } + } + } + //********************************************************************************************************* + //********************************************************************************************************* + //****************************************Mauvais choix d'un pseudo**************************************** + //********************************************************************************************************* + //********************************************************************************************************* + if (Type.equals("Mauvais Choix Pseudo")) { + System.out.println("Ce choix de pseudo est déjà pris il te faut en choisir un autre"); + UDPEchange.setPseudoValide(false); + } + + //****************************************************************************************************************** + //****************************************************************************************************************** + //****************************************Bon choix d'un pseudo***************************************************** + //****************************************************************************************************************** + //****************************************************************************************************************** + + if (Type.equals("Bon Choix Pseudo")) { + // Il n'y a rien a faire ici + } + + //********************************************************************************************************* + //********************************************************************************************************* + //****************************************Demande d'une deconnexion**************************************** + //********************************************************************************************************* + //********************************************************************************************************* + + if (Type.equals("Deconnexion")) { + ( app.getActifUsers() ).supprimerList(Utilisateur.stringToUtilisateur(received.split("\n")[1])); + } + } + + + + +} diff --git a/Implementation/chatapp/src/main/java/chatapp/View/ChangementPseudo.java b/Implementation/chatapp/src/main/java/chatapp/View/ChangementPseudo.java new file mode 100644 index 0000000..b5f82b9 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/ChangementPseudo.java @@ -0,0 +1,99 @@ + +package chatapp.View; + + import java.io.IOException; + import java.net.URL; + import java.util.ResourceBundle; + + import chatapp.Controller.ChatApp; + import javafx.event.ActionEvent; + import javafx.fxml.FXML; + import javafx.fxml.FXMLLoader; + import javafx.scene.Parent; + import javafx.scene.Scene; + import javafx.scene.control.Alert; + import javafx.scene.control.Button; + import javafx.scene.control.TextField; + import javafx.scene.text.Text; + import javafx.stage.Stage; + +public class ChangementPseudo { + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // fx:id="validationButton" + private Button validationButton; // Value injected by FXMLLoader + + @FXML // fx:id="pseudonyme" + private TextField pseudonyme; // Value injected by FXMLLoader + + @FXML // fx:id="pseudonyme1" + private Text pseudonyme1; // Value injected by FXMLLoader + + @FXML // fx:id="MenuButton" + private Button MenuButton; // Value injected by FXMLLoader + + private ChatApp chatApp; + @FXML + void nouveauPseudo(ActionEvent event) { + + } + + + @FXML + /** + *

Handler permettant de retourner au menu principal sur pression du MenuButton

+ */ + void retourMenu(ActionEvent event) { + System.out.println("Retour au menu principal"); + Stage stage = (Stage) MenuButton.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + + @FXML + /** + *

Handler permettant de lancer la verrification de l'unicite du ppseudo sur pression du validtionButton

+ */ + void validerPseudo(ActionEvent event) { + boolean pseudoOK = false; + try { + pseudoOK = chatApp.modifierPseudo(pseudonyme.getText()); + } catch (IOException e) { + e.printStackTrace(); + } + if(pseudoOK){ + this.retourMenu(null); + } + else{ + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Changement pseudo"); + // Header Text: null + alert.setHeaderText(null); + alert.setContentText("Echec de Connexion: le pseudo "+pseudonyme.getText()+" est deja pris"); + alert.showAndWait(); + } + } + + /** + *

Initialization de la classe ChangementPseudo et permet d'initialiser les parametres

+ */ + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + chatApp = ChatApp.getInstance(); + pseudonyme1.setText(chatApp.getMe().getPseudo()); + this.validationButton.setDefaultButton(true); + //System.out.println(this.validationButton.isDefaultButton()); + } +} \ No newline at end of file diff --git a/Implementation/chatapp/src/main/java/chatapp/View/Clavardage.java b/Implementation/chatapp/src/main/java/chatapp/View/Clavardage.java new file mode 100644 index 0000000..aa859e8 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/Clavardage.java @@ -0,0 +1,139 @@ +package chatapp.View; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.net.URL; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.ResourceBundle; + +import chatapp.Controller.ChatApp; +import chatapp.Model.MessageHorodate; +import chatapp.Model.Utilisateur; +import chatapp.Protocol.SessionClavardage; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; +import javafx.stage.Stage; + +public class Clavardage implements Initializable, PropertyChangeListener { + @FXML //fx:id="plusButton" + public Button plusButton; + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // fx:id="AEnvoyer" + private TextField AEnvoyer; // Value injected by FXMLLoader + + @FXML // fx:id="EnvoyerButton" + private Button EnvoyerButton; // Value injected by FXMLLoader + + @FXML // fx:id="pseudonyme1" + private Text pseudonyme1; // Value injected by FXMLLoader + + @FXML // fx:id="ChatText" + private TextArea ChatText; // Value injected by FXMLLoader + + @FXML // fx:id="MenuButton" + + private Utilisateur u2; + private SessionClavardage session; + private String nomTable; + @FXML + /** + *

Handler gerant l'envoi du message contenu dans le TextField AEnvoyer et sur pression du bouton EnvoyerButton

+ */ + void envoyerMessage(ActionEvent event) { + String msg = AEnvoyer.getText(); + AEnvoyer.clear(); + if(!msg.equals("")) { + session.envoiMsg(msg); + Date d = new Date(); + DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:0"); + msg = "Moi (" + format.format(d).toString() + ") : " + msg + "\n"; + ChatText.appendText(msg); + + } + } + + + /** + * Setter + * @param session la session a associer a la classe + */ + public void setSession(SessionClavardage session) { + + this.session = session; + + this.session.addPropertyChangeListener(this); + this.u2=session.getU2(); + this.pseudonyme1.setText(u2.getPseudo()); + } + + /** + *

Handler des differents evenements auxquels s'est abonne le PropertyChangeListener + * La classe est informee lorsque la session recoit un message ou lorsque la session se termine

+ * @param evt l'evenement informe par le pcs + */ + @Override + public void propertyChange(PropertyChangeEvent evt) { + switch (evt.getPropertyName()){ + case "MessageRecu" : + MessageHorodate msgh = session.getDernierMsg(); + DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:0"); + Date d = new Date(); + String msg = u2.getPseudo(); + msg += " ("+ format.format(d).toString() +") "; + msg+=": "+msgh.getMessage(); + ChatText.appendText(msg); + break; + case "FinDeLaSession" : + this.session.arretSession(); + Platform.runLater(new Runnable() { + @Override + public void run() { + Stage stage = (Stage) AEnvoyer.getScene().getWindow(); + stage.close(); + } + }); + } + + } + + public SessionClavardage getSession(){ + return session; + } + + /** + * Permet d'initialiser les differents parametres de la classe + * @param location + * @param resources + */ + @Override + public void initialize(URL location, ResourceBundle resources) { + EnvoyerButton.setDefaultButton(true); + this.ChatText.setEditable(false); + } + + /** + *

Permet de recepurer plus de messages stoces dans la database en appuyant sur le bouton plusButton

+ * @param actionEvent + */ + public void ajouterMessagesHistorique(ActionEvent actionEvent) { + this.nomTable = this.session.getApp().getDb().getNomTable(u2,this.session.getApp().getMe()); + String historique = this.session.getApp().getDb().recupNMsg(session.getApp().getMe().getId(),this.u2.getId(), this.session.getApp().getDb().tailleBDD("Chat_mbp-de-auriane.home_mbp-de-auriane.home")); + ChatText.clear(); + ChatText.insertText(0,historique); + } +} \ No newline at end of file diff --git a/Implementation/chatapp/src/main/java/chatapp/View/ConnexionScreen.java b/Implementation/chatapp/src/main/java/chatapp/View/ConnexionScreen.java new file mode 100644 index 0000000..6ae272f --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/ConnexionScreen.java @@ -0,0 +1,70 @@ + +package chatapp.View; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +import chatapp.Controller.ChatApp; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.stage.Stage; + +public class ConnexionScreen { + + public Button connexionButton; + + public TextField pseudonyme; + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + connexionButton.setDefaultButton(true); + + } + + /** + *

Handler permettant de lancer la connexion avec le pseudonyme contenu dans le TextField pseudonyme en appuyant sur le connexionButton + *

+ * @param actionEvent + */ + public void connexion(ActionEvent actionEvent) { + Boolean connexion = false; + try { + connexion = ChatApp.getInstance().connexion(pseudonyme.getText()); + } catch (IOException e) { + e.printStackTrace(); + } + if(!connexion){ + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Connexion"); + // Header Text: null + alert.setHeaderText(null); + alert.setContentText("Echec de Connexion: le pseudo "+pseudonyme.getText()+" est deja pris"); + alert.showAndWait(); + } + else{ + Stage stage = (Stage) connexionButton.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/View/DemarrerSession.java b/Implementation/chatapp/src/main/java/chatapp/View/DemarrerSession.java new file mode 100644 index 0000000..4d987f4 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/DemarrerSession.java @@ -0,0 +1,77 @@ +/** + * Sample Skeleton for 'View_Demarrer_Session.fxml' Controller Class + */ + +package chatapp.View; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +import chatapp.Controller.ChatApp; +import chatapp.Model.ListUtilisateurs; +import chatapp.Model.Utilisateur; +import chatapp.Protocol.RunnerEcouteTCP; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.stage.Stage; + +public class DemarrerSession { + + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // fx:id="choixContact" + private ComboBox choixContact; // Value injected by FXMLLoader + + @FXML // fx:id="MenuButton" + private Button MenuButton; // Value injected by FXMLLoader + private ChatApp chatApp; + + /** + *

Handler permettant de demarrer une session de clavardage avec le contact choisi dans la comboBox choixContaact

+ * @param event + */ + @FXML + void demarrerSessionAvec(ActionEvent event) { + chatApp.demarrerSession(choixContact.getValue()); + } + + /** + *

Handler permettant de retourner au menu principal sur pression du MenuButton

+ */ + @FXML + void retourMenu(ActionEvent event) { + Stage stage = (Stage) MenuButton.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + + /** + *

Initialization de la classe ChangementPseudo et permet d'initialiser les parametres

+ */ + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + this.chatApp = ChatApp.getInstance(); + ListUtilisateurs utils = chatApp.getActifUsers(); + for(Utilisateur u : utils.getActifUsers()){ + choixContact.getItems().add(u.getPseudo()); + } + + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/View/FenetreSession.java b/Implementation/chatapp/src/main/java/chatapp/View/FenetreSession.java new file mode 100644 index 0000000..4ca243d --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/FenetreSession.java @@ -0,0 +1,46 @@ +package chatapp.View; + +import chatapp.Protocol.SessionClavardage; +import javafx.event.EventHandler; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; + +import java.beans.PropertyChangeListener; +import java.io.IOException; + +public class FenetreSession extends Stage { + SessionClavardage session; + /** + *

Permet l'ouverture de la fenetre associee a la session de clavardage

+ */ + public FenetreSession(SessionClavardage session) { + FXMLLoader fichier = new FXMLLoader(getClass().getResource("/fenetres/View_Clavardage.fxml")); + try{ + Parent rootchat = fichier.load(); + Clavardage controller = fichier.getController(); + System.out.println("Session id "+session.getSessionID()); + //controller.printsalut(); + controller.setSession(session); + Scene scene1 = null; + scene1 = new Scene(rootchat,600,400); + this.setScene(scene1); + this.setTitle("Session avec "+session.getU2().getPseudo()); + this.setMinWidth(600); + this.setMinHeight(400); + //this.setMaxWidth(600); + //this.setMaxHeight(400); + this.show(); + this.centerOnScreen(); + this.setOnCloseRequest(new EventHandler() { + public void handle(WindowEvent we) { + session.arretSession(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/View/View_Menu.java b/Implementation/chatapp/src/main/java/chatapp/View/View_Menu.java new file mode 100644 index 0000000..8c78146 --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/View_Menu.java @@ -0,0 +1,105 @@ +package chatapp.View; + + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +import chatapp.Controller.ChatApp; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.MenuItem; +import javafx.scene.text.Text; +import javafx.stage.Stage; + +public class View_Menu { + + public Text pseudonyme; + public MenuItem utilsActifsButton; + public MenuItem demarrerSessionButton; + public MenuItem changerPseudoButton; + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + private ChatApp chatapp; + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + this.chatapp = ChatApp.getInstance(); + this.pseudonyme.setText(this.chatapp.getMe().getPseudo()); + } + + /** + *

Handler permettant d'aller a la scene View_Utilisateurs pour afficher la liste des utilisateurs actifs

+ * @param actionEvent + */ + public void afficherUtilsActifs(ActionEvent actionEvent) { + Stage stage = (Stage) pseudonyme.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Utilisateurs.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + + /** + *

Handler permettant d'aller a la scene Demarrer_Session pour choisir un utilisateur avec qui clavarder + * @param actionEvent + */ + public void demarrerSession(ActionEvent actionEvent) { + Stage stage = (Stage) pseudonyme.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Demarrer_Session.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + + /** + *

Handler permettant d'aller a la scene View_ChangementPseudo pour changer son pseudonyme + * @param actionEvent + */ + public void changerPseudo(ActionEvent actionEvent) { + Stage stage = (Stage) pseudonyme.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_ChangementPseudo.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } + + /** + *

Handler permettant de se deconnecter et fermer l'application + * @param actionEvent + */ + public void deconnexion(ActionEvent actionEvent) { + try { + chatapp.deconnexion(); + /*chatapp.getMain().stop(); + Platform.exit(); + System.exit(0);*/ + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + + } +} diff --git a/Implementation/chatapp/src/main/java/chatapp/View/View_Utilisateurs.java b/Implementation/chatapp/src/main/java/chatapp/View/View_Utilisateurs.java new file mode 100644 index 0000000..96fcb3e --- /dev/null +++ b/Implementation/chatapp/src/main/java/chatapp/View/View_Utilisateurs.java @@ -0,0 +1,57 @@ +package chatapp.View; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +import chatapp.Controller.ChatApp; +import chatapp.Model.ListUtilisateurs; +import chatapp.Model.Utilisateur; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.TextArea; +import javafx.stage.Stage; + +public class View_Utilisateurs { + + public TextArea ListeUtilisateurs; + public Button MenuButton; + @FXML // ResourceBundle that was given to the FXMLLoader + private ResourceBundle resources; + + @FXML // URL location of the FXML file that was given to the FXMLLoader + private URL location; + + @FXML // This method is called by the FXMLLoader when initialization is complete + void initialize() { + ListUtilisateurs utilisateurs = ChatApp.getInstance().getActifUsers(); + + ListeUtilisateurs.setText(""); + for(Utilisateur elem : utilisateurs.getActifUsers()) { + ListeUtilisateurs.appendText( " - " +elem.getPseudo() + '\n'); + } + ListeUtilisateurs.setEditable(false); + + + } + + /** + *

Handler permettant de retourner au menu principal sur pression du MenuButton

+ */ + public void retourMenu(ActionEvent actionEvent) { + Stage stage = (Stage) MenuButton.getScene().getWindow(); + Parent root = null; + try { + root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml")); + } catch (IOException e) { + e.printStackTrace(); + } + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } +} diff --git a/Implementation/chatapp/src/main/resources/fenetres/ConnexionScreen.fxml b/Implementation/chatapp/src/main/resources/fenetres/ConnexionScreen.fxml new file mode 100644 index 0000000..c09f679 --- /dev/null +++ b/Implementation/chatapp/src/main/resources/fenetres/ConnexionScreen.fxml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/chatapp/src/main/resources/fenetres/View_ChangementPseudo.fxml b/Implementation/chatapp/src/main/resources/fenetres/View_ChangementPseudo.fxml new file mode 100644 index 0000000..5bfabb7 --- /dev/null +++ b/Implementation/chatapp/src/main/resources/fenetres/View_ChangementPseudo.fxml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/chatapp/src/main/resources/fenetres/View_Clavardage.fxml b/Implementation/chatapp/src/main/resources/fenetres/View_Clavardage.fxml new file mode 100644 index 0000000..ebb0e85 --- /dev/null +++ b/Implementation/chatapp/src/main/resources/fenetres/View_Clavardage.fxml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Implementation/src/Controller/ChatApp.java b/Implementation/src/Controller/ChatApp.java deleted file mode 100644 index ff0cabe..0000000 --- a/Implementation/src/Controller/ChatApp.java +++ /dev/null @@ -1,240 +0,0 @@ -package src.Controller; - -import java.io.IOException; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import src.Protocoles.*; - -/** -*

-* Classe recapitulant toutes les actions possibles pour un utilisateur -*

-*/ - -public class ChatApp { - - /* Liste des utilisateurs actifs */ - private ListUtilisateurs actifUsers ; - - /* Map on l'on stocke localement les historiques des messages */ - private Map mapHistorique ; - private boolean historiqueAvailable = true; - - /* ChatApp est associe a un utilisateur */ - private Utilisateur me; - - /** - * Constructeur de l'application de chat - * - * @param pseudo Pseudo de l'utilisateur - * @param port Port de communication - */ - public ChatApp(String pseudo, Integer port){ - this.actifUsers = new ListUtilisateurs() ; - // Recuperer adresse IP de l'utilisateur - InetAddress ip = null ; - ip = UDPEchange.getCurrentIp(); - this.me = new Utilisateur(pseudo,port,ip); - this.actifUsers.addList(getMe()); - this.mapHistorique = new HashMap() ; - } - - /** - * Mettre a jour dans Maphistorique, l'historique avec un utilisateur dont le nom est pseudo - * - * @param pseudo Pseudo de l'utilisateur - * @param h nouvel Historique entre les deux utilisateurs - */ - public synchronized void majHistorique(Historique h) { - getMapHistorique().put(h.getUser2().getPseudo(),h); - } - - /*public void majHistorique2(MessageHorodate mh, String pseudo) { - Historique h = getMapHistorique().get(pseudo); - //h.addMessage(mh); - getMapHistorique().put(h.getUser2().getPseudo(),h); - }*/ - - public void majHistorique2(String mh, String pseudo) { - Historique h = getMapHistorique().get(pseudo); - MessageHorodate msghor = new MessageHorodate(this.getMe(),this.getMe(),"rien",1); - System.out.println(">>"+mh+"<<"); - System.out.print(msghor.getDateHorodatage()); - System.out.println(msghor.getDestinataire()); - System.out.println(msghor.getSource()); - System.out.println(msghor.getType()); - - h.addMessage(msghor); - getMapHistorique().put(h.getUser2().getPseudo(),h); - } - - /** - * Modification du pseudo de l'utilisateur - * Envoie en broadcast ses informations utilisateurs et son nouveau pseudo - * - * @param nouveau correspond au nouveau pseudo - * @return False si modiferPseudo a echoue, True sinon - */ - public Boolean modifierPseudo(String nouveau) throws IOException { - // Message que l'on envoie à tous les utilisateurs actifs - String broadcastMessage = "Demande Modification Pseudo\n" + this.getMe().toString() + "\n" + nouveau + "\n"; - UDPEchange.EnvoiBroadcast(broadcastMessage); - try { - Thread.sleep(2000); - /* L'utilisateur doit attendre la reponse de tous les utilisateurs connectes - * pour savoir si son pseudo est accepte - */ - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (UDPEchange.getPseudoValide()) { - System.out.println("Modification pseudo reussie"); - //Envoi un msg en broadcast a tout les utilisateurs pour les prevenir de son nouveau pseudo// - broadcastMessage = "Modification pseudo reussie\n" + this.getMe().toString() + "\n" + nouveau + "\n"; - UDPEchange.EnvoiBroadcast(broadcastMessage); - //-------Change son propre nom d'utilisateur-------// - this.getActifUsers().modifierList(this.getMe().getPseudo(), nouveau); - this.getMe().setPseudo(nouveau); - System.out.println("Changement pseudo accepte, nouvelle liste des utilisateurs actifs:"); - this.getActifUsers().afficherListeUtilisateurs(); - return true; - } - else - { - System.out.println("Echec Modification pseudo"); - return false; - } - } - - - /** - * Methode appelee lors de la connexion d'un nouvel utilisateur. - * Il va prevenir les utilisateurs du reseau de son arrivee. - * @return False si Connexion a echoue, True sinon - */ - public Boolean connexion() throws IOException { - // Message que l'on envoie à tous les utilisateurs actifs - String broadcastMessage = "Connexion\n" + this.getMe().toString() ; - UDPEchange.EnvoiBroadcast(broadcastMessage); - try { - Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (UDPEchange.getConnecte()) { - System.out.println("Connexion reussie"); - return true; - } - else - { - System.out.println("Connexion echoue"); - UDPEchange.setConnecte(true); - return false ; - } - } - - /** - * Methode appelee lors de la deconnexion de l'utilisateur. - * Il va prevenir les utilisateurs du reseau de son depart. - * - */ - public void deconnexion() throws IOException { - // Message que l'on envoie à tous les utilisateurs actifs - String broadcastMessage = "Deconnexion\n" + this.getMe().toString() ; - UDPEchange.EnvoiBroadcast(broadcastMessage); - System.exit(1); - } - - /** - * Getter - * @return Utilisateur associee a ChatApp - */ - public Utilisateur getMe() { - return me; - } - - /** - * Getter - * @return Liste des utilisateurs actifs associee a ChatApp - */ - public ListUtilisateurs getActifUsers() { - return actifUsers; - } - - /** - * Getter - * @return la map des historiques - */ - public Map getMapHistorique() { - return mapHistorique; - } - - /** - * Obtenir l'historique entre deux utilisateurs - * @param pseudo Pseudo de l'utilisateur dont on souhaite obtenir l'historique - * @return Un historique - */ - public synchronized Historique getHist(String pseudo) { - Historique h = this.mapHistorique.get(pseudo); - if( h != null) { - return h ; - } - else { - h = new Historique(this.me, this.getActifUsers().getPseudoList(pseudo)); - return h ; - } - } - - public static void main (String[] args) throws IOException { - ChatApp app = new ChatApp(args[0],Integer.parseInt(args[1])) ; - - - - - ExecutorService execUDP = Executors.newFixedThreadPool(1000); - execUDP.submit(new RunnerEcouteUDP(app)); - try { - app.connexion(); - } catch (IOException e) { - e.printStackTrace(); - } - ExecutorService execTCP = Executors.newFixedThreadPool(1000); - execTCP.submit(new RunnerEcouteTCP(app)); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - if(app.getMe().getPseudo().equals("Marvel")) { - app.getHist("Doudou").afficher10derniers(); - System.out.println("Tentative de connexion avec Doudou"); - TCPEchange.demarrerSession(app, app.actifUsers.getPseudoList("Doudou")); - } - - - - } - - public boolean isHistoriqueAvailable() { - return historiqueAvailable; - } - - public void setHistoriqueAvailable(boolean historiqueAvailable) { - this.historiqueAvailable = historiqueAvailable; - } - -} - diff --git a/Implementation/src/Controller/Historique.java b/Implementation/src/Controller/Historique.java deleted file mode 100644 index 270502a..0000000 --- a/Implementation/src/Controller/Historique.java +++ /dev/null @@ -1,63 +0,0 @@ -package src.Controller; - -import java.util.ArrayList; - -/** -*

-* Classe permettant de sauvegarder les échanges entre deux utilisateurs -*

-*/ -public class Historique { - private Utilisateur User1; - private Utilisateur User2; - // Liste conservant les differents échanges - private ArrayList HistoriqueHorodate ; - - /** - *

- * Constructeur : un historique sauvegarde les echanges entre - * User1 et User2 - * @param User1 - un utilisateur - * @param User2 - un second utilisateur - *

- */ - public Historique(Utilisateur User1, Utilisateur User2) { - this.User1 = User1; - this.User2 = User2; - this.HistoriqueHorodate = new ArrayList(); - } - - /** - *

- * On ajoute un message échangé dans la liste 'HistoriqueHorodate' - * - * @param mh - le message horodate échangé - *

- */ - public void addMessage(MessageHorodate mh) { - this.HistoriqueHorodate.add(mh); - } - - /** - *

- * getter pour recuperer le second utilisateur - *

- */ - public Utilisateur getUser2() { - return User2; - } - - public void afficher10derniers() { - System.out.println("Demarrage de l'affichage partiel de l'historique"); - System.out.println("Il y a actuellement " + HistoriqueHorodate.size() +" elements dans l'historique"); - int n =10; - if(HistoriqueHorodate.size()<=10) { - n = HistoriqueHorodate.size(); - } - for(int i = 0; i actifUsers ; - - public ListUtilisateurs() { - this.actifUsers = new ArrayList() ; - } - /** - * Ajouter des utilisateurs actifs dans l'attribut liste 'actifUsers' - * - * @param u on va rajouter cet utilisateur dans la liste - */ - public void addList(Utilisateur u) { - if((verifierUnicite(u.getPseudo()))) { - this.actifUsers.add(u); - } - - - } - - /** - * Recuperer un utilisateur à partir de son pseudo - * - * @param pseudo Pseudo de l'utilisateur que l'on souhaite retrouver - */ - public Utilisateur getPseudoList(String pseudo) { - for(Utilisateur elem: this.actifUsers) - { - if (elem.getPseudo().equals(pseudo) ) { - return elem ; - } - } - return null ; - } - - /** - * Supprimer de la liste des utilisateurs actifs 'actifUsers' un certain utilisateur - * - * @param u on va supprimer cet utilisateur dans la liste - */ - public void supprimerList(Utilisateur u) { - Boolean Sup = false ; - for(Utilisateur elem: this.actifUsers) - { - if (elem.equals(u) ) { - this.actifUsers.remove(elem); - Sup = true ; - this.afficherListeUtilisateurs(); - } - } - if (!Sup) { - System.out.println("Tentative de retirer un objet non contenu dans la liste"); - } - } - - /** - * Modifie le nom d'un utilisateur dans la liste des utilisateurs actifs 'actifUsers' - * - * @param ancien correspond au pseudo remplacer - * @param nouveau correspond au nouveau pseudo - */ - public void modifierList(String ancien , String nouveau) { - for(Utilisateur elem: this.actifUsers) - { - if (ancien.equals( elem.getPseudo() ) ) { - this.actifUsers.remove(elem); - elem.setPseudo(nouveau);; - this.addList(elem); - - } - } - this.afficherListeUtilisateurs(); - } - - public Boolean appartient(Utilisateur u) { - return this.actifUsers.contains(u); - } - - - - /** - * Verifie qu'aucun autre utilisateur ne possède le même pseudo - * - * @param u on va supprimer cet utilisateur dans la liste - */ - public Boolean verifierUnicite(String pseudo) { - for(Utilisateur elem: this.actifUsers) - { - if (pseudo.equals( elem.getPseudo() ) ) { - return false ; - } - } - return true; - } - - /** - * Méthode affichant la liste des utilisateurs actifs - * - */ - public String afficherListeUtilisateurs() { - System.out.println ("Liste des utilisateurs actifs : "); - String Utilisateur = "" ; - for(Utilisateur elem: this.actifUsers) - { - System.out.println (elem.toString()); - Utilisateur += (elem + "\n"); - } - return Utilisateur; - } -} diff --git a/Implementation/src/Controller/MessageHorodate.java b/Implementation/src/Controller/MessageHorodate.java deleted file mode 100644 index 1d86472..0000000 --- a/Implementation/src/Controller/MessageHorodate.java +++ /dev/null @@ -1,142 +0,0 @@ -package src.Controller; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** -*

-* Classe representant les messages envoyés en TCP lors d'une session de clavardage -*

-*/ -public class MessageHorodate { - private Utilisateur destinataire ; - private Utilisateur source ; - private Date dateHorodatage ; - private int type; // 0 = debut de la communication, 1= message de communication, 2 = fin de la communicataion - private String Message; - - /** - *

- * Constructeur , le message va etre horodate - * @param destinataire - Destinataire du message - * @param source - Source du message - * @param Message - Message envoye - *

- */ - public MessageHorodate(Utilisateur destinataire, Utilisateur source, String Message, int type) { - this.setDestinataire(destinataire) ; - this.setSource(source) ; - this.setMessage(Message) ; - this.setDateHorodatage(new Date()); - this.type = type; - } - - public void setDate(Date d) { - this.setDateHorodatage(d); - } - - /** - *

- * permet de creer une representation string du message - * @return Les differents attributs de la classe sous forme de string - *

- */ - @Override - public String toString() { - String Msg = ""; - Msg += ("Destinataire::" + this.getDestinataire() + "\n") ; - Msg += ("Source::" + this.getSource()+ "\n") ; - Msg += ("Type::"+ this.type+ "\n"); - Msg += ("Date::" + this.dateToString() + "\n") ; - Msg += ("Message::" + this.getMessage() + "\n" ); - return Msg ; - } - - /** - *

- * permet de creer une representation string de la date d'horodatage - * @return La date d'horodatage du message en format yyyy/MM/dd HH:mm:ss - *

- */ - public String dateToString() { - DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - return format.format(this.getDateHorodatage()); - } - - - /** - *

- * Permet de re creer un message horodate a partir d'un string - * @return un messageHorodate - *

- */ - public static MessageHorodate stringToMessageHorodate(String s) { - - String mots[] = s.split("\n"); - Utilisateur destinataire = Utilisateur.stringToUtilisateur(mots[0].split("::")[1]); - Utilisateur source = Utilisateur.stringToUtilisateur(mots[1].split("::")[1]); - int type = Integer.parseInt(mots[2].split("::")[1]); - DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - Date date = new Date(); - /*try { - date = format.parse(mots[3].split("::")[1]); - } catch (Exception e) { - e.printStackTrace(); - }*/ - String payload = ""; - for(int i=4; i< mots.length; i++) { - if(mots[i].startsWith("Message::")) { - mots[i]=mots[i].split("::")[1]; - } - payload += mots[i]+"\n"; - } - - MessageHorodate mh = new MessageHorodate(destinataire, source, payload, type); - //mh.setDate(date); - - return mh ; - } - - public Utilisateur getSource() { - return source; - } - - public void setSource(Utilisateur source) { - this.source = source; - } - - public Utilisateur getDestinataire() { - return destinataire; - } - - public void setDestinataire(Utilisateur destinataire) { - this.destinataire = destinataire; - } - - public String getMessage() { - return Message; - } - - public void setMessage(String message) { - Message = message; - } - - public int getType() { - return type; - } - - public void setType(int Type) { - this.type = type; - } - - public Date getDateHorodatage() { - return dateHorodatage; - } - - public void setDateHorodatage(Date dateHorodatage) { - this.dateHorodatage = dateHorodatage; - } - -} diff --git a/Implementation/src/Controller/Modification_Pseudo.java b/Implementation/src/Controller/Modification_Pseudo.java deleted file mode 100644 index e34b110..0000000 --- a/Implementation/src/Controller/Modification_Pseudo.java +++ /dev/null @@ -1,51 +0,0 @@ -package src.Controller; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.IOException; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingConstants; - -public class Modification_Pseudo extends JPanel{ - ChatApp app; - public Modification_Pseudo(String name, ChatApp app) { - this.app = app ; - JLabel Text = new JLabel("Entrez un nouveau nom d'utilisateur!", SwingConstants.CENTER); - JTextField pseudofield = new JTextField(2); // Zone d'insertion de texte - JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png")); - //Ajout d'un bouton Valider - JButton Valider = new JButton("Valider"); - this.getRootPane().setDefaultButton(Valider); - //Listen to events from the Valider button. - Valider.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - String nouveau = pseudofield.getText(); - try { - Boolean resultat = app.modifierPseudo(nouveau); - if(resultat) { - - } - else { - //JOptionPane.showMessageDialog(this, "Echec de modification de pseudo, " + nouveau +" deja pris", JOptionPane.WARNING_MESSAGE); - - } - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - this.add(home); - this.add(Text); - this.add(BorderLayout.CENTER,pseudofield); - this.add(BorderLayout.SOUTH,Valider); - -} -} diff --git a/Implementation/src/Controller/Utilisateur.java b/Implementation/src/Controller/Utilisateur.java deleted file mode 100644 index 9a35547..0000000 --- a/Implementation/src/Controller/Utilisateur.java +++ /dev/null @@ -1,77 +0,0 @@ -package src.Controller; - -import java.net.InetAddress; -import java.net.UnknownHostException; - -public class Utilisateur extends Object { - - private String pseudo ; - private Integer port; - private InetAddress ip ; - private String id ; - - public Utilisateur(String pseudo,Integer port, InetAddress ip ){ - this.setPseudo(pseudo) ; - this.setPort(port); - this.ip = ip ; - this.id = ip.getHostName() ; - } - - public String getPseudo() { - return pseudo; - } - - public void setPseudo(String pseudo) { - this.pseudo = pseudo; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public InetAddress getIp() { - return ip; - } - public String getId() { - return id; - } - - @Override - public String toString(){ - String s = ""; - s+="pseudo " + this.pseudo + " | "; - s+="port " + (this.port).toString() + " | "; - s+="ip " + (this.ip).toString() + " | "; - s+="id " + (this.id).toString() + " | "; - return s; - } - - public static Utilisateur stringToUtilisateur(String s) { - String name = ""; - Integer port = 0; - String ip = "" ; - String id = ""; - String mots[] = s.split(" "); - name=mots[1]; - port=Integer.parseInt(mots[4]); - ip=mots[7]; - id=mots[10]; - Utilisateur user = null; - try { - user = new Utilisateur(name,port,InetAddress.getByName(ip.split("/")[1])); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return user; - } - - - public Boolean equals(Utilisateur u) { - return this.getId().equals( u.getId() ) ; - } - -} diff --git a/Implementation/src/Protocoles/RunnerEcouteTCP.java b/Implementation/src/Protocoles/RunnerEcouteTCP.java deleted file mode 100644 index 2706ea4..0000000 --- a/Implementation/src/Protocoles/RunnerEcouteTCP.java +++ /dev/null @@ -1,16 +0,0 @@ -package src.Protocoles; - -import src.Controller.ChatApp; - -public class RunnerEcouteTCP implements Runnable { - ChatApp app ; - public RunnerEcouteTCP(ChatApp app) { - this.app = app ; - } - @Override - public void run() { - - TCPEchange.ecouteTCP(app); - - } -} \ No newline at end of file diff --git a/Implementation/src/Protocoles/RunnerEcouteUDP.java b/Implementation/src/Protocoles/RunnerEcouteUDP.java deleted file mode 100644 index 7810123..0000000 --- a/Implementation/src/Protocoles/RunnerEcouteUDP.java +++ /dev/null @@ -1,16 +0,0 @@ -package src.Protocoles; - -import src.Controller.ChatApp; - -public class RunnerEcouteUDP implements Runnable { - ChatApp app ; - public RunnerEcouteUDP(ChatApp app) { - this.app = app ; - } - @Override - public void run() { - - UDPEchange.ecouteUDP(app); - - } -} \ No newline at end of file diff --git a/Implementation/src/Protocoles/TCPEchange.java b/Implementation/src/Protocoles/TCPEchange.java deleted file mode 100644 index 77c8be5..0000000 --- a/Implementation/src/Protocoles/TCPEchange.java +++ /dev/null @@ -1,320 +0,0 @@ -package src.Protocoles; - -import java.io.InputStream; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.OutputStream; -import java.net.DatagramSocket; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.NoSuchElementException; -import java.util.Scanner; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import src.Controller.*; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -/** -*

-* Classe representant les échanges TCP entre utilisateurs. -*

-*/ -public class TCPEchange { - - /** - *

- * Equivalent a un handshake. - * L'utilisateur associé a app souhaite entamé une discussion avec User2 - * @param app L'app associé à l'utilisateur qui souhaite entamé la discussion - * @param User2 Le destinataire - *

- */ - public static void demarrerSession(ChatApp app,Utilisateur User2 ) throws IOException { - System.out.println("Demmarrage d'une session de clavardage"); - Socket s = new Socket(User2.getIp(),5000); - System.out.println("Socket de demarrage d'une session cree"); - //ExecutorService exec = Executors.newFixedThreadPool(1000); - Thread t1 = new Thread(new RunnerTCPEcoute(s,app)); - Thread t2 = new Thread(new RunnerTCPEnvoi(s,app,User2,false)); - t1.start(); - t2.start(); - try { - t1.join(); - t2.join(); - }catch(InterruptedException e) { - System.out.println("Un thread s'est arrete brusquement"); - } - System.out.println("Tout s'est passe creme"); - app.getHist(User2.getPseudo()).afficher10derniers(); - - } - - /*public static void envoiTCP(ChatApp app,Utilisateur User2, String Msg, int type ) { - // On cree un messagehorodate - MessageHorodate mh = new MessageHorodate(app.getMe(), User2, Msg, type); - if( type == 1 ) { - // on ajoute le msg à son historique - Historique h = app.getHist(User2.getPseudo()); - h.addMessage(mh); - // on update la liste des historiques de app - app.majHistorique(h); - } - - try { - Socket s = new Socket(User2.getIp(), User2.getPort()); - PrintStream output = new PrintStream(s.getOutputStream()); - output.println(mh.toString()); - output.close(); - s.close(); - } catch (Exception e) { - e.printStackTrace(); - } - }*/ - - - /** - *

- * Méthode pour qu'un objet de la classe ChatApp soit constamment en écoute de potentielles connexions - * @param app L'utilisateur en écoute de potentielles communications - *

- */ - public static void ecouteTCP(ChatApp app) { - ServerSocket ss = null; - ExecutorService exec = Executors.newFixedThreadPool(1000); - System.out.println("Ecoute TCP activee"); - try { - ss = new ServerSocket(5000); // On ecoute sur le port 5000 - System.out.println("Socket d'ecoute cree"); - while(true) { // Ecoute en boucle - System.out.println("Attente Session de clavardage"); - Socket link = ss.accept(); // Blocante - exec.submit(new RunnerTCPEcoute(link,app)); // On crée un thread qui va gerer la connexion recu - System.out.println("L'ecoute TCP continue apres le premier thread demarre"); - } - } - catch (Exception e) { - e.printStackTrace(); - } - } -} - - -/** -*

-* Classe representant les threads s'occupant de l'envoie de messages en utilisant le protocole TCP. -* Cette classe implemente l'interface Runnable. -*

-*/ -class RunnerTCPEnvoi implements Runnable { - private Socket link; - private ChatApp app ; - private Utilisateur Destinataire; - final BufferedReader in; - final PrintWriter out; - final Scanner sc=new Scanner(System.in); - private boolean bonjourEnvoye = false; - - /** - *

- * Constructeur de la classe RunnerTCPEnvoi - * @param link - * @param app Un objet ChatApp dont l'utilisateur associé souhaite entame une discussion - * @param user2 Destinataire - * @param bonjour Boolean true si c'est le debut d'une connexion, false sinon - *

- */ - public RunnerTCPEnvoi(Socket link,ChatApp app, Utilisateur user2, boolean bonjour ) throws IOException { - this.link = link; - this.app = app; - this.Destinataire = user2; - this.out = new PrintWriter(link.getOutputStream()); - this.in = new BufferedReader (new InputStreamReader (link.getInputStream())); - this.bonjourEnvoye = bonjour; - } - - @Override - public void run() { - System.out.println("Creation d'un thread d'envoi"); - String msg; - - while(true){ - if(!bonjourEnvoye) { // bonjourEnvoye est a false si c'est le debut d'une communication - MessageHorodate mh = new MessageHorodate(Destinataire,app.getMe(),"Bonjour",2); - bonjourEnvoye = true; - System.out.println("Envoi d'un bonjour"); - out.println(mh); - out.flush(); - } - else { - try { - msg = sc.nextLine(); - }catch(NoSuchElementException e) { - break; - } - MessageHorodate mh = new MessageHorodate(Destinataire,app.getMe(),msg,1); - if(msg.equals("--STOP--")) { - mh = new MessageHorodate(Destinataire,app.getMe(),msg,0); // ENVOYER JUSTE --STOP-- SUFFIT - out.println(mh); - out.flush(); - break; - } - /* while(!app.isHistoriqueAvailable()) { - try{wait(); - }catch(InterruptedException e) {} - }*/ - //app.setHistoriqueAvailable(false); - synchronized( this.app.getMapHistorique()) { - Historique h = app.getHist(Destinataire.getPseudo()); - h.addMessage(mh); - app.majHistorique(h); - } - - // on update la liste des historiques de app - - //app.majHistorique2(mh.toString(),Destinataire.getPseudo()); - //app.setHistoriqueAvailable(false); - //notifyAll(); - out.println(mh); - System.out.println("Envoi d'un mesage"); - out.flush(); - } - } - try { - System.out.println("Fermeture du thread d'envoi"); - in.close(); - link.close(); - }catch(Exception e) { - // Gestion de l'exception de la fermeture de la socket - } -} - -} - - - -/** -*

-* Classe representant les threads s'occupant de la reception de messages en utilisant le protocole TCP. -* Cette classe implemente l'interface Runnable. -*

-*/ -class RunnerTCPEcoute implements Runnable { - final Socket link; - private ChatApp app ; - private Utilisateur u2; - private boolean u2Initialise; - public RunnerTCPEcoute(Socket link,ChatApp app ) { - this.link = link; - this.app = app; - this.u2Initialise=false; - } - - @Override - public void run() { - System.out.println("Creation d'un thread d'ecoute"); - try { - PrintStream output = new PrintStream(link.getOutputStream()); - //InputStream is = link.getInputStream(); - BufferedReader in = new BufferedReader (new InputStreamReader (link.getInputStream())); - - String line = ""; - String dest = ""; - String src = ""; - String type = ""; - String date = ""; - String payload = ""; - String msg = ""; - line = in.readLine(); - while (line != null) { - - - if(line.split("::")[0].equals("Destinataire")) { - if(msg.equals("")) { - dest = line+"\n"; - msg="."; - } - else { - msg=dest+src+type+date+payload; - payload = ""; - MessageHorodate mh = MessageHorodate.stringToMessageHorodate(msg); - System.out.println("Type du message:"+mh.getType()); - if(mh.getType()==1) { - /*while(!app.isHistoriqueAvailable()) { - try{wait(); - }catch(InterruptedException e) {} - } - app.setHistoriqueAvailable(false);*/ - System.out.println("Historique mis à jour lors de la reception"); - Historique h = app.getHist(mh.getSource().getPseudo()); - h.addMessage(mh); - app.majHistorique(h); - //app.setHistoriqueAvailable(true); - //notifyAll(); - //app.majHistorique2(mh,mh.getSource().getPseudo()); - } - else if(mh.getType()==0) { - break; - } - - } - } - else if(line.split("::")[0].equals("Source")) { - src = line+"\n"; - if(!u2Initialise) { - u2=Utilisateur.stringToUtilisateur(src.split("::")[1].replaceAll("\n", "")); - System.out.println("u2Initialise !"); - u2Initialise = true; - } - } - else if(line.split("::")[0].equals("Type")) { - if(line.split("::")[1].equals("2")) { - System.out.println("Bonjour recu!"); - //System.out.println(src.split("::")[1].replaceAll("\n", "")); - u2=Utilisateur.stringToUtilisateur(src.split("::")[1].replaceAll("\n", "")); - u2Initialise = true; - System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<"); - Thread t = new Thread(new RunnerTCPEnvoi(link,app,u2,true)); - t.start(); - System.out.println("Thread d'envoi envoye"); - } - type = line+"\n"; - } - else if(line.split("::")[0].equals("Date")) { - date = line+"\n"; - } - else if(line.split("::")[0].equals("Message")){ - payload = line+"\n"; - - } - else { - payload += line+"\n"; - } - - System.out.println("Received: "+ line); - line = in.readLine(); - - - } - System.out.println("Affichage de l'histo"); - System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<"); - app.getHist(u2.getPseudo()).afficher10derniers(); - in.close(); - link.close(); - } catch (IOException e) { - //e.printStackTrace(); - } finally { - System.out.println("Finishing thread"); - System.out.println("Affichage de l'histo"); - System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<"); - app.getHist(u2.getPseudo()).afficher10derniers(); - - - } - - } - } diff --git a/Implementation/src/Protocoles/UDPEchange.java b/Implementation/src/Protocoles/UDPEchange.java deleted file mode 100644 index 4652a0d..0000000 --- a/Implementation/src/Protocoles/UDPEchange.java +++ /dev/null @@ -1,358 +0,0 @@ -package src.Protocoles; - -import java.io.IOException; - -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.Inet4Address; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import src.Controller.*; -/** -*

-* Classe representant les echanges UDP entre utilisateurs. -*

-*/ - -public class UDPEchange { - - private static Boolean Connecte = true; - // True si l'utilisateur peut se connecter avec ce nom d'utilisateur , False sinon - - /** - * Getter - * @return le boolean connecte (True s'il peut se connecter avec ce nom d'utilisateur , False sinon) - */ - public static Boolean getConnecte() { - return Connecte; - } - - /** - * Setter - * @param value La nouvelle valeur du boolean de connexion - */ - public static void setConnecte(Boolean value) { - Connecte = value ; - } - - private static Boolean PseudoValide = true; - // True si l'utilisateur a (ou demande) un pseudo valide , False sinon - - /** - * Getter - * @return le boolean PseudoValide (True s'il peut utiliser ce pseudo , False sinon) - */ - public static Boolean getPseudoValide() { - return PseudoValide; - } - - /** - * Setter - * @param value La nouvelle valeur du boolean concernant le pseudo valide - */ - public static void setPseudoValide(Boolean value) { - PseudoValide = value ; - } - - - - public static InetAddress getCurrentIp() { - try { - Enumeration networkInterfaces = NetworkInterface - .getNetworkInterfaces(); - while (networkInterfaces.hasMoreElements()) { - NetworkInterface ni = (NetworkInterface) networkInterfaces - .nextElement(); - Enumeration nias = ni.getInetAddresses(); - while(nias.hasMoreElements()) { - InetAddress ia= (InetAddress) nias.nextElement(); - if (!ia.isLinkLocalAddress() - && !ia.isLoopbackAddress() - && ia instanceof Inet4Address) { - return ia; - } - } - } - } catch (Exception e) { - System.out.println("unable to get current IP " + e.getMessage()); - } - return null; - } - /** - *

- * Méthode permettant d'envoyer un message à tout les utilisateurs - * a l'aide du protocole UDP - *

- * @param broadcastMessage correspond au message a transmettre aux utilisateurs - */ - public static void EnvoiBroadcast(String broadcastMessage) throws IOException { - int port = 1234 ; - // Envoie en broadcast à tous les utilsateurs - for (InetAddress broadcastAddr : listAllBroadcastAddresses()) { - DatagramSocket socket = new DatagramSocket(); - socket.setBroadcast(true); - byte[]buffer = broadcastMessage.getBytes(); - DatagramPacket packet = new DatagramPacket( buffer, buffer.length, broadcastAddr,port); - socket.send(packet); - socket.close(); - System.out.println("Broadcast sent with address " + broadcastAddr.toString()); - System.out.println("***********Message envoye***********"); - System.out.println("Dest Ip: " + broadcastAddr.toString()); - System.out.println("Dest port: " + String.valueOf(port)); - System.out.println("Contenu: "); - System.out.println(broadcastMessage); - System.out.println("************************************"); - } - } - - /** - *

- * Methode permettant la reception de messages d'utilisateurs - * a l'aide du protocole UDP - *

- * @param app L'application de chat de l'utilisateur qui receptionne le message - */ - public static void ecouteUDP(ChatApp app) - { - DatagramSocket socket = null; - ExecutorService exec = Executors.newFixedThreadPool(1000); - try { - socket = new DatagramSocket(1234); - } catch (SocketException e1) { - e1.printStackTrace(); - } - byte buffer[] = new byte[1024]; - System.out.println("Ecoute sur le port: 1234"); - while(true) - { - DatagramPacket data = new DatagramPacket(buffer,buffer.length); - try { - socket.receive(data); - } catch (IOException e) { - e.printStackTrace(); - } - // Un thread est lance à chaque reception d'un message - System.out.println("Message recu!"); - exec.submit(new RunnerUDP(data,app)); - } - } - - /** - *

- * Methode permettant d'envoyer un message a utilisateur en particulier - * a l'aide du protocole UDP - *

- * @param Adress l'addresse de l'utilisateur - * @param Message correspond au message à transmettre a l'utilisateur - */ - public static void envoiUnicast( InetAddress Adress , String Message ) throws IOException { - DatagramSocket socket = new DatagramSocket(); - byte[]buffer = Message.getBytes(); - DatagramPacket packet = new DatagramPacket( buffer, buffer.length, Adress, 1234 ); - socket.send(packet); - socket.close(); - System.out.println("***********Message envoye***********"); - System.out.println("Dest Ip: " + Adress.toString()); - System.out.println("Dest port: " + String.valueOf(1234)); - System.out.println("Contenu: "); - System.out.println(Message); - System.out.println("************************************"); - } - - /** - *

- * Methode permettant de recuperer la liste des adresses de broadcast, chacune associer à une interface de la machine - *

- */ - static List listAllBroadcastAddresses() throws SocketException { - List broadcastList = new ArrayList<>(); - Enumeration interfaces - = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface networkInterface = interfaces.nextElement(); - - if (networkInterface.isLoopback() || !networkInterface.isUp()) { - continue; - } - - networkInterface.getInterfaceAddresses().stream() - .map(a -> a.getBroadcast()) - .filter(Objects::nonNull) - .forEach(broadcastList::add); - } - return broadcastList; - } - -} - - - -/** -*

-* Classe implementant l'interface Runnable. -* Contient les traitements a executer dans un thread lancer par des methodes de la class UDPEchange -*

-*/ -class RunnerUDP implements Runnable { - final DatagramPacket data ; - ChatApp app ; - - public RunnerUDP(DatagramPacket data, ChatApp app) { - this.data= data; - this.app = app ; - } - - /** - *

- * Methode qui redefinie les traitements qui seront executes dans le thread: - * Met à jour la liste des utilisateurs actifs - *

- * - */ - @Override - public void run() { - System.out.println("Thread started"); - String received = new String(data.getData(), 0, data.getLength()); - System.out.println("***********Message recu***********"); - System.out.println(received); - System.out.println("**********************************"); - String Type = received.split("\n")[0]; - - //**************************************************************************************************** - //**************************************************************************************************** - //****************************************Demande de connexion**************************************** - //**************************************************************************************************** - //**************************************** - if (Type.equals("Connexion")) { // un utilisateur vient d'arriver sur le reseau - System.out.println("Reception d'une demande de connexion"); - Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[1]); - if (! u.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même - String reponse = "Reponse Connexion\n"; - if (!( app.getActifUsers() ).verifierUnicite(u.getPseudo())) { - System.out.println("Pseudo deja present dans la liste"); - reponse += "false\n"; - } - else { - System.out.println("Ajout d'un nouvel utilisateur dans la liste des Utilisateurs"); - ( app.getActifUsers() ).addList(u); - reponse += "true\n"; - - } - reponse += app.getMe().toString(); - - try { - UDPEchange.envoiUnicast(u.getIp(),reponse); - }catch(IOException e) - { - System.out.println("Echec de l'envoi du message"); - } - - ( app.getActifUsers() ).afficherListeUtilisateurs(); - } - } - //******************************************************************************************************* - //******************************************************************************************************* - //****************************************Reponse d'une connexion**************************************** - //******************************************************************************************************* - //******************************************************************************************************* - - if (Type.equals("Reponse Connexion")) { // Un utilisateur te repond suite à ta demande de connexion - - if((received.split("\n")[1]).equals("true")) { - Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[2]); - app.getActifUsers().addList(u); - app.getActifUsers().afficherListeUtilisateurs(); - } - else { - System.out.println("Pseudo deja pris"); - UDPEchange.setConnecte(false); - } - } - - //******************************************************************************************************************* - //******************************************************************************************************************* - //****************************************Demande de modification d'un pseudo**************************************** - //******************************************************************************************************************* - //******************************************************************************************************************* - - if (Type.equals("Demande Modification Pseudo")) { - Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]); - if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même - String nouveau = received.split("\n")[2] ; - String Message = ""; - if(( app.getActifUsers() ).verifierUnicite(nouveau)) { - Message = "Bon Choix Pseudo\n" + nouveau ; - } - else { - Message = "Mauvais Choix Pseudo\n" ; - } - System.out.println(Message); - try { - UDPEchange.envoiUnicast(Source.getIp(),Message); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - //************************************************************************************************************ - //************************************************************************************************************ - //**************************************** Modification pseudo reussi **************************************** - //************************************************************************************************************ - //************************************************************************************************************ - - if (Type.equals("Modification pseudo reussi")) { - Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]); - if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même - String nouveau = received.split("\n")[2] ; - if(app.getActifUsers().appartient(Source)) { // On verifie d'abord que Source appartient bien a la liste des utilisateurs actifs - app.getActifUsers().modifierList(Source.getPseudo(), nouveau); - } - { - // Suite a une perte d'un message lors d'une connexion l'utilisateur Source n'apparait pas dans la liste - app.getActifUsers().addList(Source); - } - } - } - //********************************************************************************************************* - //********************************************************************************************************* - //****************************************Mauvais choix d'un pseudo**************************************** - //********************************************************************************************************* - //********************************************************************************************************* - if (Type.equals("Mauvais Choix Pseudo")) { - System.out.println("Ce choix de pseudo est déjà pris il te faut en choisir un autre"); - UDPEchange.setPseudoValide(false); - } - - //****************************************************************************************************************** - //****************************************************************************************************************** - //****************************************Bon choix d'un pseudo***************************************************** - //****************************************************************************************************************** - //****************************************************************************************************************** - - if (Type.equals("Bon Choix Pseudo")) { - // Il n'y a rien a faire ici - } - - //********************************************************************************************************* - //********************************************************************************************************* - //****************************************Demande d'une deconnexion**************************************** - //********************************************************************************************************* - //********************************************************************************************************* - - if (Type.equals("Deconnexion")) { - ( app.getActifUsers() ).supprimerList(Utilisateur.stringToUtilisateur(received.split("\n")[1])); - } - } - - - - -} diff --git a/Implementation/src/View/View_Accueil.java b/Implementation/src/View/View_Accueil.java deleted file mode 100644 index 3f349cb..0000000 --- a/Implementation/src/View/View_Accueil.java +++ /dev/null @@ -1,133 +0,0 @@ -package src.View; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingConstants; - -import src.Controller.*; -import src.Protocoles.*; - - -/* - * Classe represenyant la fenetre d'accueil pour la connexion d'un utilisateur. - */ -public class View_Accueil implements ActionListener{ - JFrame frame; - JPanel panel; - JTextField pseudofield; - JLabel Text; - JButton Connexion; - - /* - * Constructeur d'une fenetre d'affichage pour la connexion d'un utilisateur. - * Cette fenetre sera munie d'un bouton de connexion et d'une zone de saisie de pseudo. - */ - public View_Accueil () { - //creer une instance JFrame - frame = new JFrame("ChatApp-AL-NM"); - //sortir quand l’utilisateur ferme le frame - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - // fixer les dimensions de la fenetre - frame.setSize(new Dimension(120, 40)); - //Creer le JPanel - panel = new JPanel(new GridLayout(3,1)); - //Ajouter les elements - this.addWidgets(); - //Set the default button. - frame.getRootPane().setDefaultButton(Connexion); - //Ajouter le panel a la window - frame.getContentPane().add(panel, BorderLayout.CENTER); - //L'utilisateur ne pourra pas aggrandir la fenetre - this.frame.setResizable(false); - //Afficher la fenetre - frame.pack(); - frame.setVisible(true); - } - - /** - * Creer et ajouter les outils de la fenetre - */ - private void addWidgets() { - // Créer Zone d'insertion de texte pour le pseudo - this.pseudofield = new JTextField(2); - // creation d'un label qui contiendra un txt au centre - this.Text = new JLabel("Bonjour, Entrez un nom d'utilisateur!", SwingConstants.CENTER); - //Ajout d'un bouton Connexion - this.Connexion = new JButton("Connexion"); - //On associe au bouton Connexion des actions a realiser - this.Connexion.addActionListener(this); - // On ajouter les differents elements au panel - panel.add(pseudofield); - panel.add(Text); - panel.add(Connexion); - //ajouter un effet de bord transparent au composant Jlabel - Text.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); - } - - /* - * Definir des traitements en réponse à un clic sur le bouton connexion - * @param event Un clic sur le bouton connexion - */ - public void actionPerformed(ActionEvent event) { - // on recupere le texte entree dans la zone de saisie - String pseudo = pseudofield.getText(); - // On crée un objet de type ChatApp - ChatApp app = new ChatApp(pseudo, 3000) ; - // on crée un thread qui va ecouter les connexions entrantes - ExecutorService execUDP = Executors.newFixedThreadPool(1000); - execUDP.submit(new RunnerEcouteUDP(app)); - Boolean connexion = false ; - try { - // on tente une connexion avec ce pseudo - connexion = app.connexion(); - } catch (IOException e) { - e.printStackTrace(); - } - // Dans les deux cas de figures (reussite ou echec) on affiche un pop-up pour expliquer la situation - if(connexion) { - // La connexion a reussi - JOptionPane.showMessageDialog(frame, "Bonjour " + pseudo) ; - frame.dispose(); - // on lance une nouvelle fenetre de type View_Menu - View_Menu fenetreCourante= new View_Menu(app); - } - else { - // La connexion a echoue, il est possible de rentrer un nouveau pseudo - JOptionPane.showMessageDialog(frame, "Echec de Connexion , ce pseudo est deja pris !"); - } - } - - private static void createAndShowGUI() { - // Etre certain d'avoir une joli fenetre - JFrame.setDefaultLookAndFeelDecorated(true); - // On crée une fentre d'acceuil - View_Accueil fenetre = new View_Accueil(); - } - - public static void main(String[] args) { - //Schedule a job for the event-dispatching thread: - //creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(new Runnable() { - public void run() { - createAndShowGUI(); - } - }); - } - -} diff --git a/Implementation/src/View/View_Clavardage.java b/Implementation/src/View/View_Clavardage.java deleted file mode 100644 index 767ec92..0000000 --- a/Implementation/src/View/View_Clavardage.java +++ /dev/null @@ -1,167 +0,0 @@ -package src.View; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; - -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingConstants; - -import src.Controller.*; - -import java.awt.GridBagLayout; -import java.awt.Font; -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.Insets; - -/* - * Classe representant la fenetre pour chaque session de clavardage. - */ -public class View_Clavardage { - JFrame frame ; - ChatApp app; - Utilisateur destination ; // Celui avec qui on va discuter - Utilisateur source; //Nous - WindowAdapter wa ; - JPanel panel ; - JTextArea textAreaAffichage ; - - /* - * Constructeur d'une fenetre de session de clavardage. - * @param app Un objet de type ChatApp pour posseder toutes les informations de l'utilisateur - * @param User2 L'utilisateur avec qui l'on souhaite discuter et passer en parametre sous forme de String - */ - public View_Clavardage(ChatApp app, String User2) { - this.app = app ; - this.frame = new JFrame("ChatApp-AL-NM"); - this.source = this.app.getMe(); - this.destination = Utilisateur.stringToUtilisateur(User2); - this.frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - // fixer les dimensions de la fenetre - this.frame.setSize(new Dimension(394, 344)); - this.frame.setResizable(false); - wa = new WindowAdapter(){ - public void windowClosing(WindowEvent e){ - int reponse = View_Menu.showConfirmDialog(); - if (reponse==0){ - frame.dispose(); - } - }}; - addWidgets(); - frame.addWindowListener( wa ) ; - frame.setVisible(true); - } - - /** - * Creer et ajouter les outils de la fenetre - */ - private void addWidgets() { - GridBagLayout gridBagLayout = new GridBagLayout(); - gridBagLayout.columnWidths = new int[]{394, 0}; - gridBagLayout.rowHeights = new int[]{16, 220, 74, 0}; - gridBagLayout.columnWeights = new double[]{0.0, Double.MIN_VALUE}; - gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE}; - this.frame.getContentPane().setLayout(gridBagLayout); - this.panel = new JPanel(); - // Zone pour ecrire de nouveau message - JTextArea textAreaSaisie = new JTextArea(5,3); - textAreaSaisie.setLineWrap(true); - textAreaSaisie.setForeground(Color.LIGHT_GRAY); - textAreaSaisie.setFont(new Font("Lucida Grande", Font.ITALIC, 11)); - textAreaSaisie.setText("Entrer du texte ici !!!"); - JScrollPane scrollPane = new JScrollPane(textAreaSaisie); - // Creation d'un bouton envoye - JButton send = new JButton("Envoye"); - frame.getRootPane().setDefaultButton(send); - send.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - //UTILISER TCPENVOI - String AEnvoyer = textAreaSaisie.getText(); - textAreaAffichage.append(AEnvoyer); - textAreaSaisie.setText(""); - }}); - // Creation d'un bouton vider la zone de saisie de texte - JButton reset = new JButton("Vider"); - reset.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - textAreaSaisie.setText(""); - }}); - JLabel titre = new JLabel("Chat avec "+ this.destination.getPseudo(),SwingConstants.CENTER); - GridBagConstraints gbc_titre = new GridBagConstraints(); - gbc_titre.anchor = GridBagConstraints.NORTH; - gbc_titre.fill = GridBagConstraints.HORIZONTAL; - gbc_titre.insets = new Insets(0, 0, 5, 0); - gbc_titre.gridx = 0; - gbc_titre.gridy = 0; - frame.getContentPane().add(titre, gbc_titre); - // Zone d'affichage de l'historique - this.textAreaAffichage = new JTextArea(10,5); - textAreaAffichage.setLineWrap(true); - this.textAreaAffichage.setText(""); - JScrollPane scrollPaneAffichage = new JScrollPane(this.textAreaAffichage); - this.textAreaAffichage.setEditable(false); // il sert juste a afficher - GridBagConstraints gbc_textAreaAffichage = new GridBagConstraints(); - gbc_textAreaAffichage.fill = GridBagConstraints.BOTH; - gbc_textAreaAffichage.insets = new Insets(0, 0, 5, 0); - gbc_textAreaAffichage.gridx = 0; - gbc_textAreaAffichage.gridy = 1; - frame.getContentPane().add(scrollPaneAffichage, gbc_textAreaAffichage); - panel.add(BorderLayout.CENTER, scrollPane); - panel.add(BorderLayout.SOUTH,send); - panel.add(BorderLayout.SOUTH,reset); - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - //Add the panel to the window. - GridBagConstraints gbc_panel = new GridBagConstraints(); - gbc_panel.anchor = GridBagConstraints.NORTH; - gbc_panel.fill = GridBagConstraints.HORIZONTAL; - gbc_panel.gridx = 0; - gbc_panel.gridy = 2; - frame.getContentPane().add(panel, gbc_panel); - /* - * - *JTextArea textAreaAffichage = new JTextArea(10,5); - textAreaAffichage.setEditable(false); - JTextArea textAreaSaisie = new JTextArea(10,5); - textAreaSaisie.setForeground(Color.LIGHT_GRAY); - textAreaSaisie.setFont(new Font("Lucida Grande", Font.ITALIC, 11)); - textAreaSaisie.setText("Entrer du texte ici !!!"); - JScrollPane scrollPane = new JScrollPane(textAreaSaisie); - JButton send = new JButton("Envoye"); - frame.getRootPane().setDefaultButton(send); - send.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - //UTILISER TCPENVOI - textAreaSaisie.setText(""); - }}); - JButton reset = new JButton("Vider"); - reset.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - textAreaSaisie.setText(""); - }}); - JLabel titre = new JLabel("Chat avec "+ this.destination.getPseudo(),SwingConstants.CENTER); - panel.add(BorderLayout.CENTER, scrollPane); - //panel.add(scrollPane); - panel.add(BorderLayout.SOUTH,send); - panel.add(BorderLayout.SOUTH,reset); - panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); - //Add the panel to the window. - frame.getContentPane().add(BorderLayout.SOUTH, panel); - frame.getContentPane().add(BorderLayout.CENTER, textAreaAffichage); - frame.getContentPane().add(BorderLayout.NORTH, titre); - */ - } - - -} diff --git a/Implementation/src/View/View_Menu.java b/Implementation/src/View/View_Menu.java deleted file mode 100644 index 3ffea35..0000000 --- a/Implementation/src/View/View_Menu.java +++ /dev/null @@ -1,256 +0,0 @@ -package src.View; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.Vector; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import javax.imageio.ImageIO; -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.SwingConstants; - -import src.Controller.*; - -import java.awt.Font; -import java.awt.Color; -import java.awt.ComponentOrientation; -import java.awt.SystemColor; - -/* - * Classe representant la fenetre de menu. Lance apres la connexion d'un utilisateur - */ -public class View_Menu { - JFrame frame; - JPanel panel; - JMenuBar menu; - ChatApp app; - JLabel jlabel; - JLabel Txt; - WindowAdapter wa ; - - /* - * Constructeur d'une fenetre de menu apres la connexion d'un utilisateur. - * @param app Un objet de type ChatApp pour posseder toutes les informations de l'utilisateur - */ - public View_Menu(ChatApp app) { - this.app = app ; - //creer une instance JFrame - frame = new JFrame("ChatApp-AL-NM"); - frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - // fixer les dimensions de la fenetre - frame.setSize(new Dimension(394, 344)); - // Lorsque l'utilisateur souhaite quitter la fenetre on affiche un pop-up pour verifier son choix - wa = new WindowAdapter(){ - public void windowClosing(WindowEvent e){ - int reponse = showConfirmDialog(); - if (reponse==0){ - try { - // on deconnecte l'app avant de quitter - // Tout les utilisateurs sont donc prevenus du depart - app.deconnexion(); - } catch (IOException e1) { - e1.printStackTrace(); - } - frame.dispose(); - } - }}; - frame.addWindowListener( wa ) ; - // Menu pour les differentes actions réalisables - menu = new JMenuBar(); - //Creation d'un JPanel - panel = new JPanel(new GridLayout(3,1)); - panel.setForeground(SystemColor.menuText); - // Ajouter tout les elements a la fenetre - this.addWidgets(); - // ajouter le panel a la fenetre - frame.getContentPane().add(panel, BorderLayout.CENTER); - // Afficher la fenetre - frame.pack(); - frame.setVisible(true); - } - - /** - * Methode static creant un pop-up demandant a l'utilisateur si il souhaite vraiment quitter. - */ - static int showConfirmDialog(){ - return JOptionPane.showConfirmDialog( - null, - "Voulez-vous vraiment quitter?", - "Quitter", - JOptionPane.YES_NO_OPTION); - } - /** - * Creer et ajouter les outils de la fenetre - */ - private void addWidgets() { - // On ajoute une jolie icone - jlabel = new JLabel(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Logo.png"), JLabel.CENTER); - - Txt = new JLabel("Menu principal de " + app.getMe().getPseudo()); - Txt.setFont(new Font("Tamil MN", Font.PLAIN, 30)); - Txt.setHorizontalAlignment(SwingConstants.CENTER); - - //On cree une item Actions que l'on ajoutera a la bar de menu - JMenu Actions = new JMenu("Actions"); - Actions.setForeground(Color.WHITE); - Actions.setHorizontalAlignment(SwingConstants.CENTER); - // Définir le sous-menu pour Actions - JMenuItem actifs = new JMenuItem("Utilisateurs actifs"); - JMenuItem session = new JMenuItem("Session de Clavardage"); - JMenuItem pseudo = new JMenuItem("Modifier Pseudo"); - JMenuItem deconnexion = new JMenuItem("Deconnexion"); - // Ajouter les sous items a actions - Actions.add(actifs); - Actions.add(session); - Actions.add(pseudo); - Actions.add(deconnexion); - // On ajoute l'item Action dans la bar de menu - menu.add(Actions); - // On ajouter les differents elements au panel - panel.add(BorderLayout.NORTH , menu); - panel.add(BorderLayout.CENTER, jlabel); - panel.add(BorderLayout.SOUTH , Txt ); - - //****************************************************************************************************************** - //**************************************** Actions lorsque l'on clique sur actifs ********************************** - //****************************************************************************************************************** - actifs.addActionListener( new ActionListener(){ - public void actionPerformed(ActionEvent event) { - JPanel panel1 = new JPanel(); - JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png")); - - JTextArea textArea = new JTextArea(20,20); - textArea.insert("Liste Utilisateurs Actifs \n",0); - JScrollPane scrollPane = new JScrollPane(textArea); - - String utilisateurs = app.getActifUsers().afficherListeUtilisateurs(); - for(String elem : utilisateurs.split("\n")) { - textArea.append( " - " +Utilisateur.stringToUtilisateur(elem).getPseudo() + '\n'); - } - panel1.add(textArea); - home.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - frame.dispose(); - new View_Menu(app); - } }); - textArea.setEditable(false); - frame.getContentPane().removeAll(); - frame.getContentPane().add(BorderLayout.CENTER, panel1); - frame.getContentPane().add(BorderLayout.NORTH , home); - frame.setVisible(true); - }}); - - //****************************************************************************************************************** - //**************************************** Actions lorsque l'on clique sur Session ********************************* - //****************************************************************************************************************** - session.addActionListener( new ActionListener(){ - public void actionPerformed(ActionEvent event) { - JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png")); - home.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - frame.dispose(); - new View_Menu(app); - } }); - String utilisateurs = app.getActifUsers().afficherListeUtilisateurs(); - Vector vector = new Vector(); - for(String elem : utilisateurs.split("\n")) { - vector.add(elem); - } - // Créer une liste déroulante - JComboBox cb = new JComboBox(vector); - cb.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent event) { - Object selected = cb.getSelectedItem(); - new View_Clavardage(app, selected.toString()); - - } - }); - JPanel panel1 = new JPanel(new GridLayout(2,1)); - panel1.add(home); - panel1.add(cb); - frame.getContentPane().removeAll(); - frame.getContentPane().add(panel1,BorderLayout.CENTER); - frame.setVisible(true); - } }); - - //****************************************************************************************************************** - //**************************************** Actions lorsque l'on clique sur Pseudo ********************************** - //****************************************************************************************************************** - pseudo.addActionListener( new ActionListener(){ - public void actionPerformed(ActionEvent event) { - JLabel Text = new JLabel("Entrez un nouveau nom d'utilisateur!", SwingConstants.CENTER); - JTextField pseudofield = new JTextField(2); // Zone d'insertion de texte - JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png")); - home.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - frame.dispose(); - new View_Menu(app); - } }); - //Ajout d'un bouton Valider - JButton Valider = new JButton("Valider"); - frame.getRootPane().setDefaultButton(Valider); - //Listen to events from the Valider button. - Valider.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent event) { - String nouveau = pseudofield.getText(); - try { - Boolean resultat = app.modifierPseudo(nouveau); - if(resultat) { - JOptionPane.showMessageDialog(frame, "Modification pseudo Reussi"); - frame.dispose(); - new View_Menu(app); - } - else { - JOptionPane.showMessageDialog(frame, "Echec Modification pseudo "); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - JPanel panel1 = new JPanel(new GridLayout(4,1)); - panel1.add(home); - panel1.add(Text); - panel1.add(pseudofield); - panel1.add(Valider); - frame.getContentPane().removeAll(); - frame.getContentPane().add(panel1,BorderLayout.CENTER); - frame.setVisible(true); - }}); - //****************************************************************************************************************** - //**************************************** Actions lorsque l'on clique sur Deconnexion ***************************** - //****************************************************************************************************************** - deconnexion.addActionListener( new ActionListener(){ - public void actionPerformed(ActionEvent event) { - frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); - } }); - - } - -} - diff --git a/Implementation/src/View/jgoodies-forms-1.8.0-sources.jar b/Implementation/src/View/jgoodies-forms-1.8.0-sources.jar deleted file mode 100644 index b680434..0000000 Binary files a/Implementation/src/View/jgoodies-forms-1.8.0-sources.jar and /dev/null differ diff --git a/Implementation/src/View/jgoodies-forms-1.8.0.jar b/Implementation/src/View/jgoodies-forms-1.8.0.jar deleted file mode 100644 index 5e4585f..0000000 Binary files a/Implementation/src/View/jgoodies-forms-1.8.0.jar and /dev/null differ diff --git a/Implementation/src/images/Home.png b/Implementation/src/images/Home.png deleted file mode 100644 index b0c3484..0000000 Binary files a/Implementation/src/images/Home.png and /dev/null differ diff --git a/Implementation/src/images/Logo.png b/Implementation/src/images/Logo.png deleted file mode 100644 index 4c03097..0000000 Binary files a/Implementation/src/images/Logo.png and /dev/null differ