Package domain

Source Code of domain.IRCController$ThrottledException

package domain;

import gui.GUIController;
import gui.ComponentSwitcher.ComponentChoice;

import java.io.IOException;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.JOptionPane;
import server.ServerController;

/**
* Met de IRCController worden alle kanalen beheert.
* De klasse is zowel een Observer (server) als een Observable (gui).
* @author David Covemaeker, Maarten Minnebo, Tim Van Thuyne, Toon Kint
*/

public class IRCController extends Observable implements Observer
{
  private ServerController serverController;
  private String oldLogin = "***";
  private String login;
  private HashMap<String, IRCChannel> channelHashMap;
  private GUIController guiController;
 
  /**
   * De constructor van de IRCController maakt de channelHashMap aan, die een HashMap is waar alle kanalen in terecht komen.
   * De HashMap bevat als sleutel een String die de naam van het kanaal bevat en het IRCChannel die aan de naam wordt gelinkt.
   */
  public IRCController(GUIController guic)
  {
    this.channelHashMap = new HashMap<String, IRCChannel>();
    guiController = guic;
  }
 
  /**
   * Maakt ServerController aan, die op zijn beurt een ServerReader en -Writer object aanmaakt.
   * De IRCController wordt observer van de ServerReader.
   * @param server De gebruikte irc server ("irc.quakenet.org")
   * @param login Loginnaam van de gebruiker
   * @param port De gebruikte poort (6667)
   */
  public boolean connect (String server, String login, int port) throws IOException
  {
    this.login = login;
    serverController = new ServerController(server, login, port);
   
    if(serverController.getSocket() != null)
    {
      serverController.getServerReader().addObserver(this);
      return true;
    }
    else
      return false;
  }
 
  /**
   * Verbreekt de connectie met de server.
   * @throws IOException
   */
  public void disconnect() throws IOException
 
    if(!channelHashMap.isEmpty())
    {
      channelHashMap.clear();
      serverController.writeLine("QUIT :Je suis chemin!");
      serverController.closeSocket();
    }
  }
 
  public void changeNick(String newNick) throws IOException
  {
    serverController.writeLine(":" + login + " NICK " + newNick);
    oldLogin = login;
    login = newNick;
  }
 
  /**
   * Methode update van de interface Observer, wordt opgeroepen als ServerReader tekst ontvangt van de server.
   * Bepaalt wat voor soort bericht (message) het is en hoe erop gereageerd moet worden.
   * De reacties zijn a.d.h.v. de Request for Comments 2812. De IRC Protocol.
   * @param arg0 Het observable object
   * @param arg1 Het argument dat wordt doorgegeven aan de notifyObservers methode
   */
  @Override
  public void update(Observable arg0, Object arg1)
  {
    // TODO Auto-generated method stub
    String message = (String) arg1;
    try
    {
      if (
          !pingMessage(message) && !joinMessage(message) && !partMessage(message) && !kickMessage(message) && !nickMessage(message) &&
          !quitMessage(message) && !VersionMessage(message) && !loginError(message) && !userListControl(message) &&
          !MotdMessage(message) && !throttled(message) && message.contains(" PRIVMSG ")
        )
      {
        putLineInChannel(message);
      }
    }
    catch (IllegalArgumentException iae)
    {
      JOptionPane.showMessageDialog(guiController.getMainFrame().getContentPane(), iae.getMessage(), "Loginnaam niet beschikbaar", JOptionPane.WARNING_MESSAGE);
      if(!(message.contains(oldLogin) && message.contains(login)))
        guiController.getMainFrame().switchToComponent(guiController, ComponentChoice.StartScherm);
    }
    catch (ThrottledException te)
    {
      JOptionPane.showMessageDialog(guiController.getMainFrame().getContentPane(), te.getMessage(), "Server weigert verbinding", JOptionPane.ERROR_MESSAGE);
      guiController.getMainFrame().switchToComponent(guiController, ComponentChoice.StartScherm);
    }
    catch (IOException e)
    {
      JOptionPane.showMessageDialog(guiController.getMainFrame().getContentPane(), "De verbinding is gestopt.", "Verbindingsfout", JOptionPane.ERROR_MESSAGE);
      System.exit(1);
    }
  }
 
  /**
   * Maakt in alle controles gebruik van:
   * EXCEL "!"
   * COLON ":"
   * POUND "#"
   */
 
  /**
   * Plaats een gewone geschreven zin in de channel.
   * @param line De ingegeven lijn
   */
  private void putLineInChannel(String line)
  {
    // TODO Auto-generated method stub
    int indexOfExcl = line.indexOf("!");
    String nickname = line.substring(1, indexOfExcl);
    line = line.substring(1);
    int indexOfColon = line.indexOf(":");
    int indexOfPound = line.indexOf("#");
    String channel;
   
    try
    {
      channel = line.substring(indexOfPound, indexOfColon-1);
    }
    catch(StringIndexOutOfBoundsException e)
    {
      channel = nickname;
    }
   
    String message = line.substring(indexOfColon+1);
   
    try
    {
      channelHashMap.get(channel.toLowerCase()).addChatMessage(nickname, message);
     
    }
    catch(NullPointerException e)
    {
      channelHashMap.put(channel.toLowerCase(), new IRCChannel(login));
      setChanged();
      notifyObservers(nickname);
      channelHashMap.get(channel.toLowerCase()).addChatMessage(nickname, message);
    }
  }
 
  /**
   * Schrijft een chatbericht naar het meegegeven kanaal.
   * @param channel Kanaal waarin bericht is ingegeven
   * @param line Het ingegeven bericht
   */
  public void writeToChannel(String channel, String line) throws IOException
  {
    serverController.sayLine(channel, line);
   
    try
    {
      channelHashMap.get(channel.toLowerCase()).addChatMessage(login, line);
    }
    catch (NullPointerException e){}
  }
 
  /**
   * @param channel Gewenst kanaalnaam.
   * @return IRCChannel die gelinkt is aan de naam die de paramater channel bevat
   */
  public IRCChannel getIRCChannel(String channel)
  {
    return channelHashMap.get(channel.toLowerCase());
  }
 
  /**
   * Client aan kanaal toevoegen.
   * Nieuw object wordt toevoegt aan de hashmap.
   * Schrijft een speciaal bericht (JOIN) naar de server.
   * @param channel Gewenste kanaal
   * @throws Exception Als client al in het kanaal zit
   */
  public void joinChannel(String channel) throws Exception
  {
    if (!channelHashMap.containsKey(channel.toLowerCase()))
    {
      serverController.writeLine("JOIN " + channel);
      channelHashMap.put(channel.toLowerCase(), new IRCChannel(login));
    }
    else
    {
      throw new Exception("Client zit al in kanaal.");
    }
  }
 
  /**
   * Verlaat kanaal.
   * Object wordt uit hashmap verwijdert.
   * Schrijft een speciaal bericht (PART) naar de server.
   * @param channel Kanaal dat client wil verlaten.
   */
  public void leaveChannel(String channel) throws IOException
  {
    if (channelHashMap.containsKey(channel.toLowerCase()))
    {
      channelHashMap.remove(channel.toLowerCase());
     
      if (channel.startsWith("#"))
        serverController.writeLine("PART " + channel);
    }
  }
 
  /**
   * Een privaat kanaal wordt geopent tussen twee mensen.
   * @param nickname De naam van de client waarmee je een privaat gesprek voert
   * @throws Exception Als je al een privaat kanaal open hebt staan met die persoon
   */
  public void startPrivateChat(String nickname) throws Exception
  {
    if (!channelHashMap.containsKey(nickname.toLowerCase()))
    {
      channelHashMap.put(nickname.toLowerCase(), new IRCChannel(nickname));
    }
    else
    {
      throw new Exception("Je bent alreeds in private chat met die persoon!");
    }
  } 
 
  /**
   * Command: PING (3.7.2.) en PONG (3.7.3.)
   * Nagaan of de verzonden lijn een PING bericht is. Indien dit het geval is moet er gereageerd worden met een PONG bericht.
   * In de lijn wordt PING dan vervangen door PONG.
   * @param line De ontvangen lijn
   * @return match True als de lijn een PING bericht was, anders false
   */
  private boolean pingMessage(String line) throws IOException
  {
    boolean match = false;
    if (line.toUpperCase().startsWith("PING"))
    {
      serverController.writeLine("PONG" + line.substring(4));
      match = true;
    }
    return match;
  }

  /**
   * Command: JOIN (3.2.1.)
   * Kijken of de verzonden lijn een JOIN bericht is.
   * Het JOIN bericht van JAVA1 op kanaal #HoGent is als volgt:
   * :JAVA1!jto@tolsun.oulu.fi JOIN #HoGent
   * @param line De ontvangen lijn
   * @return match True als boodschap een JOIN is, anders false
   */
  private boolean joinMessage(String line)
  {
    boolean match = false;
    if (line.contains(" JOIN ") && !line.contains("PRIVMSG"))
    {
      int indexOfExcl = line.indexOf("!");
      String nickname = line.substring(1, indexOfExcl);
      int indexOfPound = line.indexOf("#");
      String channel = line.substring(indexOfPound);

      channelHashMap.get(channel.toLowerCase()).addClientJoinedChannelMessage(nickname);
      channelHashMap.get(channel.toLowerCase()).addUserToListModel(nickname);
      match = true;
    }
    return match;
  }

  /**
   * Command: PART (3.2.2.)
   * Kijken of de verzonden lijn een PART bericht is.
   * Het PART bericht van JAVA1 die kanaal #HoGent verlaat met bericht "Ik ben weg.", is als volgt:
   * :JAVA1!jto@tolsun.oulu.fi PART #HoGent :Ik ben weg.
   * --> controleren op dubbelpunt (:), als die er staat geeft user een reden van vertrek.
   * @param line De ontvangen lijn
   * @return match True als boodschap een PART is, anders false
   */
  private boolean partMessage(String line)
  {
    boolean match = false;
    if (line.contains(" PART ") && !line.contains("PRIVMSG") && !line.contains(login))
    {
      int indexOfExcl = line.indexOf("!");
      String nickname = line.substring(1, indexOfExcl);
      String channel = "";
      String reason = "";
      int indexOfPound = line.indexOf("#");
      line = line.substring(1);
     
      if (line.contains(":"))
      {
        int indexOfColon = line.indexOf(":");
        channel = line.substring(indexOfPound-1, indexOfColon-1);
        reason = line.substring(indexOfColon+1);
      }
      else
      {
        channel = line.substring(indexOfPound-1);
      }
     
      System.out.println("|" + channel + "|" + nickname + "|" + reason + "|");
      channelHashMap.get(channel.toLowerCase()).addClientPartChannelMessage(nickname, reason);
      channelHashMap.get(channel.toLowerCase()).removeUserFromListModel(nickname);
      match = true;
    }
    return match;
  }

  /**
   * Command: KICK (3.2.8.)
   * Kijken of de verzonden lijn een KICK bericht is.
   * KICK command zorgt ervoor dat iemand gedwongen uit het kanaal wordt verwijdert.
   * Het KICK bericht van JAVA1 op kanaal #HoGent om COBOL te verwijderen uit het kanaal #HoGent, is als volgt:
   * :JAVA1!jto@tolsun.oulu.fi KICK #HoGent COBOL :De reden van vertrek.
   * --> controleren op dubbelpunt (:), als die er staat is er een reden voor de kick.
   * @param line De ontvangen lijn
   * @return match True als boodschap een KICK is, anders false
   */
  private boolean kickMessage(String line)
  {
    boolean match = false;
    if (line.contains(" KICK ") && !line.contains("PRIVMSG"))
    {
      String channel = "";
      String reason = "";
      String channelVictim = "";
      int indexOfSpace;
     
      line = line.substring(1);
      int indexOfExcl = line.indexOf("!");
      String kicker = line.substring(0, indexOfExcl);
      int indexOfPound = line.indexOf("#");
     
      if (line.contains(":"))
      {
        int indexOfColon = line.indexOf(":");
        reason = line.substring(indexOfColon+1);
        channelVictim = line.substring(indexOfPound, indexOfColon-1);
        indexOfSpace = channelVictim.indexOf(" ");
        channel = channelVictim.substring(0, indexOfSpace);
      }
      else
      {
        channelVictim = line.substring(indexOfPound-1);
        indexOfSpace = channelVictim.indexOf(" ");
        channel = channelVictim.substring(0, indexOfSpace);
      }
     
      String victim = channelVictim.substring(indexOfSpace+1);
      channelHashMap.get(channel.toLowerCase()).addClientKickedOutMessage(kicker, victim, reason);
      channelHashMap.get(channel.toLowerCase()).removeUserFromListModel(victim);
      match = true;
    }
    return match;
  }
 
  /**
   * Command: NICK (3.1.2.)
   * Kijken of de verzonden lijn een NICK bericht is.
   * NICK command zorgt ervoor dat iemand een loginnaam kan krijgen of veranderen.
   * De HashMap wordt doorlopen om alle kanalen te verwittigen dat de user zijn loginnaam heeft veranderd,
   * enkel de kanalen waar de user zich bevindt gebruiken deze informatie.
   * Het NICK bericht van JAVA1 om zijn naam te veranderen in JAVA2, is als volgt:
   * :JAVA1!jto@tolsun.oulu.fi NICK JAVA2
   * @param line De ontvangen lijn
   * @return match True als boodschap een NICK is, anders false
   */
  private boolean nickMessage(String line)
  {
    boolean match = false;
   
    if (line.contains(" NICK ") && !line.contains("PRIVMSG"))
    {
      line = line.substring(1);
      int indexOfExcl = line.indexOf("!");
      String oldName = line.substring(0, indexOfExcl);
      int indexOfColon = line.indexOf(":");
      String newName = line.substring(indexOfColon+1);
      System.out.println(oldName + " heeft zijn bijnaam veranderd naar " + newName);
     
      Set<Entry<String, IRCChannel>> channelSet = channelHashMap.entrySet();
      for(Entry<String, IRCChannel> entry : channelSet)
      {
        entry.getValue().addNickChangeMessage(oldName, newName);
        entry.getValue().changeLoginName(oldName, newName);
      }
      match = true;
    }
    return match;
  }

  /**
   * Command: QUIT (3.1.7.)
   * Kijken of de verzonden lijn een QUIT bericht is.
   * QUIT command geeft terug dat de client de chat verlaten heeft.
   * Daarnaast wordt de hashMap doorlopen en worden alle kanalen verwittigt dat de client weg is.
   * Enkel de kanalen waarin de client aanwezig was, gaat deze informatie gaan gebruiken.
   * Het QUIT bericht dat toont dat JAVA1 de chat heeft verlaten met als reden "Ik ben weg.", is als volgt:
   * :JAVA1!jto@tolsun.oulu.fi KICK :Ik ben weg.
   * @param line De ontvangen lijn
   * @return match True als boodschap een QUIT is, anders false
   */
  private boolean quitMessage(String line)
  {
    boolean match = false;
    if (line.contains(" QUIT ") && !line.contains("PRIVMSG"))
    {
      line = line.substring(1);
      int indexOfExcl = line.indexOf("!");
      String nickname = line.substring(0, indexOfExcl);
      int indexOfColon = line.indexOf(":Quit:");
      String reason = line.substring(indexOfColon+7);

      Set<Entry<String, IRCChannel>> channelSet = channelHashMap.entrySet();
      for(Entry<String, IRCChannel> entry : channelSet)
      {
        entry.getValue().addClientQuitServerMessage(nickname, reason);
        entry.getValue().removeUserFromListModel(nickname);
      }
      match = true;
    }
    return match;
  }

  /**
   * Command: Version (3.4.3.)
   * Kijken of de verzonden lijn een VERSION bericht is.
   * @param line De ontvangen lijn
   * @return match True als boodschap een VERSION is, anders false
   */
  private boolean VersionMessage(String linethrows IOException
  {
    boolean match = false;
    line = line.substring(1);
    final char SOH = 1; // ASCII character 0x01
    if (line.substring(0,10).contains("!") && line.contains(SOH+"VERSION"+SOH))
    {
      int indexOfExcl = line.indexOf("!");
      String nick = line.substring(0, indexOfExcl);
      serverController.writeLine("NOTICE " + nick + " :" + SOH +"VERSION HoGent Datacom Client:1.0:Java SE 6.0" + SOH);
      match = true;
    }
    return match;
  }
 
  /**
   * Gaat na of de loginnaam geldig is (controleert op error replies), anders werpt hij een IllegalArgumentException.
   * Error replies:
   * 432 - ERR_ERRONEUSNICKNAME - Nadat een ongeldige nickname is doorgegeven.
   * 433 -  ERR_NICKNAMEINUSE -  Nadat een bestaande nickname is doorgegeven.
   * @param line De ontvangen lijn
   * @return match Toont of de lijn de error reply 432 of 433 was of niet.
   */
  private boolean loginError(String line) throws IllegalArgumentException
  {
    boolean match = false;
    if ((line.contains("433") || line.contains("432")) && !line.contains("PRIVMSG"))
    {
      match = true;
      throw new IllegalArgumentException("Je gekozen loginnaam is al in gebruik.\nProbeer opnieuw.");
    }
    return match;
  }
 
  /**
   * Kijkt of de lijn een userlist is van een channel (volgens error reply 353):
   * 353 - RPL_NAMREPLY
   * "( "=" / "*" / "@" ) <channel>
     *  :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
     * --> "@" secret channels
     * --> "*" private channels
     * --> "=" public channels
   * @param line De ontvangen lijn
   * @return match Toont of de lijn de error reply 353 was of niet.
   */
  private boolean userListControl(String line)
  {
    boolean match = false;
    if (line.contains(" 353 ") && !line.contains("PRIVMSG"))
    {
      line = line.substring(1);
      int indexOfColon = line.indexOf(":");
      int indexOfPound = line.indexOf("#");
      String channel = line.substring(indexOfPound, indexOfColon-1);
      String logins = line.substring(indexOfColon+1);

      String[] arrayLogin;
      String delimiter = " ";
      arrayLogin = logins.split(delimiter); // Dit deelt de string (met de logins) op in een array.

      channelHashMap.get(channel.toLowerCase()).addUsersToListModel(arrayLogin);
      match = true;
    }
    return match;
  }
 
  /**
   * Kijkt of de lijn een Motd message is, staat voor Message of the day.
   * 376 - RPL_ENDOFMOTD
   *
   * @param line De ontvangen lijn
   * @return match True als de lijn het einde van de MOTD aangeeft, anders false
   */
  private boolean MotdMessage(String line) {
    boolean match = false;
    if (line.contains(" 376 ") && !line.contains("PRIVMSG")) {
      setChanged();
      notifyObservers();
      match = true;
    }
    return match;
  }
 
  /**
   * Controleert of we de server niet te vaak proberen aanroepen om te verbinden en dus overbelasten
   *
   * @param line
   * @return
   * @throws ThrottledException als je de server overbelast
   */
  private boolean throttled(String line) throws ThrottledException
  {
    if (line.equals("ERROR :Your host is trying to (re)connect too fast -- throttled"))
    {
      throw new ThrottledException("Je probeert te snel na elkaar te verbinden.\nDe server laat dit niet toe.");
    }
    return false;
  }
 
  /**
   * Exceptie die wordt gesmeten als je te vaak met dezelfde server probeert te verbinden op korte tijd.
   */
  private class ThrottledException extends Exception 
  {
    private static final long serialVersionUID = 3001089494818023780L;
    public ThrottledException(String reason)
    {
      super(reason);
    }
  }
}
TOP

Related Classes of domain.IRCController$ThrottledException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.