package serveur;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.Commentaire;
import com.Groupe;
import com.MessageDiffere;
import com.Publication;
import client.InterfaceClientChat;
import profil.Profil;
import profil.ProfilSocial;
import util.Constantes;
import util.ProfilException;
import util.Serialiser;
/**
* Implemente l'interface InterfaceServeur pour fournir un serveur complet de gestion des groupes, des profils et du chat
* @author Meryeme AIT-MAMA, Yohann CALLEA, Babacar CISSE, Antoine DALLE-RIVE, Kevin FRANCES, Tarek JAOUANI
* @see java.rmi.server.UnicastRemoteObject
* @see InterfaceServeur
*/
public class Serveur extends UnicastRemoteObject implements InterfaceServeur {
/** Serial UID au 20-04-2011 */
private static final long serialVersionUID = 20042011L;
/** Adresse du serveur. */
protected String adresse;
/** Numero du port. */
protected int port;
/**
* Table de hash contenant les pseudos et les URL des clients disponibles pour "chatter" <br/>
* L'url est au format "rmi://adresse:port/pseudo
*/
protected Map<String, String> clients;
/* ---------- Chat ---------- */
/**
* Initialise l'ensemble contenant l'URL des clients distants, l'adresse du serveur et le numero du
* port par defaut.
* @throws RemoteException
*/
public Serveur() throws RemoteException {
super();
System.out.println("Démarrage du serveur...");
this.port = Constantes.PORT;
this.clients = new HashMap<String, String>();
try {
this.adresse = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
System.err.println("L'adresse IP de l'hôte ne peut être déterminée, le serveur n'a pas été lancé.");
System.exit(1);
}
// Création du registre RMI, tant que le port choisi est utilisé, on incrémente le port (jusqu'à 500 tentatives)
for(int i=500; i>0; i--) {
try {
LocateRegistry.createRegistry(port);
break;
} catch (RemoteException e) {
port++;
}
}
if (port == Constantes.PORT + 500) {
System.err.println("Une erreur est survenue durant la création du registre");
System.exit(1);
}
System.out.println("Serveur enregistré au registre sur le port " + port + "...");
try {
// Lie le serveur de chat à l'adresse indiquée
Naming.rebind("rmi://" + adresse + ":" + port + "/" + Constantes.SERVER_NAME, this);
System.out.println("Serveur démarré");
System.out.println("-------------------------------");
System.out.println("URL de l'hôte : " + "rmi://" + adresse + ":" + port + "/" + Constantes.SERVER_NAME);
System.out.println("-------------------------------");
} catch (MalformedURLException e) {
System.err.println("Erreur : L'URL du serveur est invalide");
System.exit(1);
}
}
@Override
public boolean enregistrer(String url) throws RemoteException {
try {
// On vérifie que l'url correspond à un client
InterfaceClientChat client = (InterfaceClientChat) Naming.lookup(url);
String pseudo = client.getUtilisateur();
if (clients.get(pseudo) != null)
return false;
// Ajout du client à l'annuaire
clients.put(pseudo, url);
System.out.println(client.getUtilisateur() + " vient de se connecter.");
} catch(Exception ex) {
return false;
}
return true;
}
@Override
public void desenregistrer(String user) throws RemoteException {
if (clients.remove(user) != null)
System.out.println(user + " est maintenant hors-ligne.");
}
@Override
public String getAdresse(String pseudo) throws RemoteException {
return clients.get(pseudo);
}
@Override
public List<String> getConnectes() throws RemoteException {
return new ArrayList<String>(clients.keySet());
}
@Override
public List<String> getConnectes(String pseudo) throws RemoteException {
// Récupération de la liste des pseudonymes des utilisateurs actuellement connectés
List<String> connectes = new ArrayList<String>(clients.keySet());
// Récupération de la liste des amis de l'utilisateur
List<String> amis = getProfil(pseudo).getAmis();
// Suppression des pseudonymes qui ne sont pas contenus dans la liste d'amis
connectes.retainAll(amis);
return connectes;
}
@Override
public String getUrl() throws RemoteException {
return adresse;
}
/* ---------- Profils ---------- */
@Override
public Profil connexion(String login, String password) throws RemoteException, ProfilException {
Profil profil = null;
try {
// Récupération de la liste des profils
HashMap<String, Profil> profils = Serialiser.deserialiser(Constantes.PROFIL);
profil = profils.get(login);
} catch (IOException e) {
throw new ProfilException(ProfilException.INVALID_USERNAME);
}
// Si le profil n'existe pas, on retourne null
if (profil == null) {
System.out.println("Echec de la connexion pour l'utilisateur " + login + " : profil inexistant");
throw new ProfilException(ProfilException.INVALID_USERNAME);
}
// Si la combinaison login/mot de passe est correcte, on retourne le profil correspondant
if (profil.getPassword().equals(password)) {
System.out.println(login + " vient de se connecter");
return profil;
}
// Si le profil existe mais que le mot de passe st incorrect pour ce profil, on retourne null
System.out.println("Echec de la connexion pour l'utilisateur " + login + " : mot de passe incorrect");
throw new ProfilException(ProfilException.INVALID_PASSWORD);
}
@Override
public boolean newProfil(Profil profil) throws RemoteException, ProfilException {
try {
if (profil == null)
return false;
// Récupération de la liste des profils
HashMap<String,Profil> profils;
try {
profils = Serialiser.deserialiser(Constantes.PROFIL);
} catch (FileNotFoundException e) {
profils = new HashMap<String,Profil>();
}
// Si un profil de même pseudo existe déjà, une exception est levée
if (profils.get(profil.getPseudo()) != null)
throw new ProfilException();
// Ajout du nouveau profil à la liste
profils.put(profil.getPseudo(), profil);
// Enregistrement de cette nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean deleteProfil(String pseudo) throws RemoteException {
try {
// Récupération de la liste des profils
HashMap<String,Profil> profils = Serialiser.deserialiser(Constantes.PROFIL);
// Si aucun profil n'est lié à ce pseudo, on retourne false, sinon on le supprime
if (profils.remove(pseudo) == null)
return false;
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean modifyProfil(String pseudo, Profil profil) throws RemoteException, ProfilException {
try {
// Récupération de la liste des profils
HashMap<String,Profil> profils = Serialiser.deserialiser(Constantes.PROFIL);
// S'il manque une information au nouveau profil ou que le pseudo entré n'est lié à aucun profil
// On lève une Exception
if (profils.get(pseudo) == null)
throw new ProfilException(ProfilException.INVALID_USERNAME);
else if (profil.getPseudo() == null)
throw new ProfilException(ProfilException.MISSING_USERNAME);
else if (profil.getPassword() == null)
throw new ProfilException(ProfilException.MISSING_PASSWORD);
else if (profil.getNom() == null)
throw new ProfilException(ProfilException.MISSING_NOM);
else if (profil.getPrenom() == null)
throw new ProfilException(ProfilException.MISSING_PRENOM);
else if (profil.getSexe() == null)
throw new ProfilException(ProfilException.MISSING_SEXE);
// Modification du profil
profils.put(profil.getPseudo(), profil);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public Profil getProfil(String pseudo) throws RemoteException {
try {
// Récupération de la liste des profils
HashMap<String,Profil> profils = Serialiser.deserialiser(Constantes.PROFIL);
return profils.get(pseudo);
} catch (IOException e) {
return null;
}
}
@Override
public boolean addFriend(String pseudo, String ami) throws RemoteException {
if (pseudo.equals(ami))
return false;
HashMap<String, Profil> profils;
try {
// Récupération de la liste des profils
profils = Serialiser.deserialiser(Constantes.PROFIL);
} catch (IOException e) {
return false;
}
try {
// Récupération du profil des deux utilisateurs
Profil profil1 = profils.get(pseudo);
Profil profil2 = profils.get(ami);
// Les utilisateurs deviennent réciproquement "amis"
// S'ils le sont déja -> Retour faux
if (profil1.getAmi(ami) == null)
profil1.ajouterAmi(ami);
else
return false;
if (profil2.getAmi(pseudo) == null)
profil2.ajouterAmi(pseudo);
else
return false;
// Enregistrement des modifications apportées au profil
profils.put(pseudo, profil1);
profils.put(ami, profil2);
} catch (NullPointerException e) {
return false;
}
try {
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean publier(String pseudo, Publication publication) throws RemoteException {
HashMap<String, Profil> profils;
ProfilSocial profil;
try {
// Récupération de la liste des profils
profils = Serialiser.deserialiser(Constantes.PROFIL);
// Récupération du profil correspondant
profil = (ProfilSocial)profils.get(pseudo);
// Ajout de la publication à la liste des publications
profil.addPublication(publication);
// Mise à jour de la liste des profils
profils.put(pseudo, profil);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean commenter(Publication publication, Commentaire commentaire, String nom) throws RemoteException {
Publication pb = null;
HashMap<String, Profil> profils;
ProfilSocial profil;
try {
// Récupération de la liste des profils
profils = Serialiser.deserialiser(Constantes.PROFIL);
try {
// Récupération du profil correspondant
profil = (ProfilSocial)profils.get(nom);
// Récupération de la publication à commenter
for (Publication pub : profil.getPublications()) {
if (pub.getDate().compareTo(publication.getDate()) == 0 || pub.getPseudo().equals(publication.getPseudo())) {
pb = pub;
break;
}
}
// Ajout du commentaire à la liste des commentaires liés à cette publication
pb.comment(commentaire);
// Mise à jour de la liste des profils
profils.put(nom, profil);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (NullPointerException e1) { // Aucun pseudonyme profil ne correspond au nom entré en paramètre, ou la publication n'a pas été trouvée pour ce profil
HashMap<String, Groupe> groupes;
Groupe groupe;
// Récupération de la liste des groupes
groupes = Serialiser.deserialiser(Constantes.GROUPES);
try {
// Récupération du groupe correspondant
groupe = groupes.get(nom);
// Récupération de la publication à commenter
for (Publication pub : groupe.getPublications()) {
if (pub.getDate().compareTo(publication.getDate()) == 0 || pub.getPseudo().equals(publication.getPseudo())) {
pb = pub;
break;
}
}
// Ajout du commentaire à la liste des commentaires liés à cette publication
pb.comment(commentaire);
// Mise à jour de la liste des groupes
groupes.put(nom, groupe);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
} catch (NullPointerException e2) { // Le nom ne correspond ni à un groupe, ni à un profil, ou la publication n'existe pas
return false;
}
}
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean like(Publication publication, String nom, boolean like, String pseudo) throws RemoteException {
Publication pb = null;
HashMap<String, Profil> profils;
ProfilSocial profil;
try {
// Récupération de la liste des profils
profils = Serialiser.deserialiser(Constantes.PROFIL);
try {
// Récupération du profil correspondant
profil = (ProfilSocial)profils.get(nom);
// Récupération de la publication à aimer (ou non)
for (Publication pub : profil.getPublications()) {
if (pub.getDate().equals(publication.getDate()) && pub.getPseudo().equals(publication.getPseudo())) {
pb = pub;
break;
}
}
// Like ou Dislike sur la publication
if (like)
pb.like(pseudo);
else
pb.dislike(pseudo);
// Mise à jour de la liste des profils
profils.put(nom, profil);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (NullPointerException e1) { // Aucun pseudonyme profil ne correspond au nom entré en paramètre, ou la publication n'a pas été trouvée pour ce profil
HashMap<String, Groupe> groupes;
Groupe groupe;
// Récupération de la liste des groupes
groupes = Serialiser.deserialiser(Constantes.GROUPES);
try {
// Récupération du groupe correspondant
groupe = groupes.get(nom);
// Récupération de la publication à commenter
for (Publication pub : groupe.getPublications()) {
if (pub.getDate().compareTo(publication.getDate()) == 0 && pub.getPseudo().equals(publication.getPseudo())) {
pb = pub;
break;
}
}
// Like ou Dislike sur la publication
if (like)
pb.like(pseudo);
else
pb.dislike(pseudo);
// Mise à jour de la liste des groupes
groupes.put(nom, groupe);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
} catch (NullPointerException e2) { // Le nom ne correspond ni à un groupe, ni à un profil, ou la publication n'existe pas
return false;
}
}
} catch (IOException e) {
return false;
}
return true;
}
/* ---------- Groupes ---------- */
@Override
public Groupe getGroup(String nom) throws RemoteException {
try {
// Récupération de la liste des groupes
HashMap<String,Groupe> groupes = Serialiser.deserialiser(Constantes.GROUPES);
return groupes.get(nom);
} catch (IOException e) {
return null;
}
}
@Override
public boolean newGroup(Groupe groupe) throws RemoteException, ProfilException {
try {
if (groupe == null)
return false;
// Récupération de la liste des groupes
HashMap<String,Groupe> groupes;
try {
groupes = Serialiser.deserialiser(Constantes.GROUPES);
} catch (FileNotFoundException e) {
groupes = new HashMap<String,Groupe>();
}
// Si un groupe de même nom existe déjà, une exception est levée
if (groupes.get(groupe.getNom()) != null)
throw new ProfilException();
// Ajout du nouveau groupe à la liste
groupes.put(groupe.getNom(), groupe);
// Enregistrement de cette nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean deleteGroup(String nom) throws RemoteException {
try {
// Récupération de la liste des groupes
HashMap<String,Groupe> groupes = Serialiser.deserialiser(Constantes.GROUPES);
// Si aucun groupe n'est lié à ce nom, on retourne false, sinon on le supprime
if (groupes.remove(nom) == null)
return false;
// Enregistrement de la nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
} catch (IOException e) {
return false;
}
return true;
}
@Override
public boolean joinGroup(String pseudo, String groupe) throws RemoteException {
try {
// Récupération de la liste des groupes
HashMap<String,Groupe> groupes = Serialiser.deserialiser(Constantes.GROUPES);
HashMap<String,Profil> profils = Serialiser.deserialiser(Constantes.PROFIL);
// Ajout du groupe aux centres d'interets du profil
ProfilSocial profil = (ProfilSocial)profils.get(pseudo);
profil.addInteret(groupe);
profils.put(pseudo, profil);
// Récupération du groupe concerné
Groupe gr = groupes.get(groupe);
// Ajout du nouveau membre à la liste des membres adhérant à ce groupe
gr.addMembre(pseudo);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
Serialiser.serialiser(profils, Constantes.PROFIL);
} catch (Exception e) {
return false;
}
return true;
}
@Override
public boolean publierGroupe(String nom, Publication publication) throws RemoteException {
HashMap<String, Groupe> groupes;
Groupe groupe;
try {
// Récupération de la liste des groupes
groupes = Serialiser.deserialiser(Constantes.GROUPES);
// Récupération du groupe correspondant
groupe = groupes.get(nom);
if (!groupe.getMembres().contains(publication.getPseudo()))
return false;
// Ajout de la publication à la liste des publications
groupe.addPublication(publication);
// Mise à jour de la liste des groupes
groupes.put(nom, groupe);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(groupes, Constantes.GROUPES);
} catch (IOException e) {
return false;
}
return true;
}
/* ---------- Messages différés ---------- */
@Override
public void sendMessage(String destinataire, MessageDiffere message) throws RemoteException {
HashMap<String, List<MessageDiffere>> messages;
List<MessageDiffere> mailbox;
try {
// Récupération de la liste des messages
messages = Serialiser.deserialiser(Constantes.MESSAGES);
// Récupération de la liste des messages correspondant au pseudo
mailbox = messages.get(destinataire);
// Ajout de la publication à la liste des publications
try {
mailbox.add(message);
} catch (NullPointerException e) {
mailbox = new ArrayList<MessageDiffere>();
mailbox.add(message);
}
// Mise à jour de la liste des messages
messages.put(destinataire, mailbox);
// Enregistrement de la nouvelle liste
Serialiser.serialiser(messages, Constantes.MESSAGES);
} catch (IOException e) {
throw new RemoteException();
}
}
@Override
public void sendMessage(List<String> destinataires, MessageDiffere message) throws RemoteException {
HashMap<String, List<MessageDiffere>> messages;
List<MessageDiffere> mailbox;
try {
// Récupération de la liste des messages
messages = Serialiser.deserialiser(Constantes.MESSAGES);
for (String destinataire : destinataires) {
// Récupération de la liste des messages correspondant au pseudo
mailbox = messages.get(destinataire);
// Ajout du message à la liste des messages
try {
mailbox.add(message);
} catch (NullPointerException e) {
mailbox = new ArrayList<MessageDiffere>();
mailbox.add(message);
}
// Mise à jour de la liste des messages
messages.put(destinataire, mailbox);
}
// Enregistrement de la nouvelle liste
Serialiser.serialiser(messages, Constantes.MESSAGES);
} catch (IOException e) {
throw new RemoteException();
}
}
@Override
public List<MessageDiffere> getMessages(String pseudo) throws RemoteException {
HashMap<String, List<MessageDiffere>> messages;
try {
// Récupération de la liste des messages
messages = Serialiser.deserialiser(Constantes.MESSAGES);
// Retour de la liste des messages reçus par l'utilisateur
return messages.get(pseudo);
} catch (IOException e) {
return null;
}
}
}