package client;
import java.util.*;
import msgs.*;
import msgs.TTConstants.Actions;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
/**
* MsgParser: Parses incoming messages from the server
* Team 9: Andrew Hayworth, Brian Parrella, Ryan Kortmann, Nina Papa
* @author Andrew Hayworth
*/
public class MsgParser extends Thread implements TTConstants {
private ClientMsg cmsg;
private static boolean go;
// this is lazy gui coding ... but I'm a lazy guy.
private JDialog jd;
private JTextArea jta;
public MsgParser() {
go = true;
}
public void run() {
while (go) {
// only process if there's something to process
if(!(ServerListener.inQ.isEmpty())){
cmsg = ServerListener.inQ.remove(0);
System.out.println(cmsg.getAction());
switch (cmsg.getAction()) {
case ADMIN_DISCONNECT:
System.out.println("Disco msg recvd");
// shit, we gotta gtfo!
System.exit(0);
break;
case ADMIN_LIST_CHATS:
ArrayList<String> a = new ArrayList<String>();
a.addAll(TTClient.pmChats.keySet());
String[] as = makeStringArray(a);
cmsg.setChats(as);
ServerSender.outQ.add(cmsg);
break;
// msgs sent to and from the server with action OFFLINE_MSG are offline PM messages, and responses from the server
case OFFLINE_MSG:
if (cmsg instanceof PMMsg) {
// we only actually care if they came back online. the server sneds OK for every new message we send,
//but I dont actually care if it fails, so i never test for that.
if (((PMMsg)cmsg).getSpecialResponse() == 3 ) {
// they came back online, so we change the chat with their name to reflect this and resend the last message requested
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setSpecialResponse(0);
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setTargetIP(((PMMsg)cmsg).getUserIP());
PMSender.outQ.add(new SimpleMsg(((PMMsg)cmsg).getMsg(), TTClient.name, TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).getTargetName(), TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).getTargetIP(), TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).getFromIP(), false));
break;
}
}
if (cmsg instanceof OfflinePMMsg) {
/// HERE BE HACKS!!! DONT TOUCH!!!
// sweet, someone needed to talk to us so badly that they left us a message!
// this is the case that we already have a window open for them
if (TTClient.pmChats.containsKey(((OfflinePMMsg)cmsg).getFromUser())) {
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).setVisible(true);
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).updateWindow(((OfflinePMMsg)cmsg).getMsg());
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).setSpecialResponse(2);
}
else {
// we dont have a window open for them yet, create one!
TTClient.pmChats.put(((OfflinePMMsg)cmsg).getFromUser(), new PMChat(new PMMsg(TTClient.ip, TTClient.name, null, TTClient.key, ((OfflinePMMsg)cmsg).getFromUser())));
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).updateWindow("**** Messages sent to you while offline ****");
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).updateWindow(((OfflinePMMsg)cmsg).getMsg());
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).setFromIP(((OfflinePMMsg)cmsg).getIp());
TTClient.pmChats.get(((OfflinePMMsg)cmsg).getFromUser()).setSpecialResponse(2);
}
}
break;
// we tried to pm a user, check the response from the server to see if we're allowed
case PM_USER:
// not allowed to pm -- ie, we're blocked
if (((PMMsg)cmsg).getSpecialResponse() == 1) {
JOptionPane.showMessageDialog(null, "Msg Failed!", "Not allowed to PM this user", JOptionPane.ERROR_MESSAGE);
break;
}
// allowed to pm, but they're offline
// send to the server instead
else if (((PMMsg)cmsg).getSpecialResponse() == 2) {
// we should create a new chat, and instead of simplemsgs , we send pmmsgs to the server
if (!(TTClient.pmChats.containsKey(((PMMsg)cmsg).getWantsUser()))) {
//they have no window open for this user yet
JOptionPane.showMessageDialog(null, "Requested user is offline -- all messages will be stored and sent to the user when they log on.", "User offline!", JOptionPane.INFORMATION_MESSAGE);
TTClient.pmChats.put(((PMMsg)cmsg).getWantsUser(), new PMChat((PMMsg) cmsg));
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setSpecialResponse(2);
}
else
{
// have a window, raise it.
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setVisible(true);
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setSpecialResponse(2);
}
break;
}
//yay, we're allowed to pm and they're online!
else {
if(!(TTRunningClient.jf.isVisible()))
{
// TTClient.trayIcon.displayMessage("Message from: " + ((PMMsg)cmsg).getWantsUser(), ((PMMsg)cmsg).getMsg(), org.jdesktop.jdic.tray.TrayIcon.INFO_MESSAGE_TYPE);
}
if (!(TTClient.pmChats.containsKey(((PMMsg)cmsg).getWantsUser()))) {
TTClient.pmChats.put(((PMMsg)cmsg).getWantsUser(), new PMChat((PMMsg) cmsg));
}
else
{
TTClient.pmChats.get(((PMMsg)cmsg).getWantsUser()).setVisible(true);
}
break;
}
case KEEP_ALIVE:
// server sends periodic keepalives. it just expects a reply, it doesnt care what it is, just resend the last thing we got in.
ServerSender.outQ.add(cmsg);
break;
case PROFILE_UPDATE:
// we tried to update our profile. success == silent, failure == this case:
if (cmsg.getResponse() == TTConstants.Responses.DENY) {
JOptionPane.showMessageDialog(null, "Update Failed!", "Update Failed!", JOptionPane.ERROR_MESSAGE);
}
break;
case PROFILE_REQUEST:
// we either wanted to update our profile, or are looking at someone elses.
// if we're currently updating our profile, display the editor window
if (TTClient.updatingProfile) {
TTClient.updatingProfile = false;
jd = new JDialog();
JButton send = new JButton("Send");
send.setMnemonic('S');
JButton cancel = new JButton("Cancel");
cancel.setMnemonic('C');
jta = new JTextArea(10, 10);
jta.setText(((ProfileMsg)cmsg).getProfile());
JScrollPane jsp = new JScrollPane(jta);
JPanel jp = new JPanel();
jd.add(jsp, BorderLayout.CENTER);
jp.add(send);
jp.add(cancel);
jd.add(jp, BorderLayout.SOUTH);
jd.setSize(200,200);
jd.setTitle("Edit Profile");
jd.setLocationRelativeTo(null);
jd.setVisible(true);
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) { jd.dispose(); }
});
send.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
ProfileMsg pm = new ProfileMsg(TTClient.ip, TTClient.name, TTClient.pwd, TTClient.key, true, jta.getText());
pm.setProfile(jta.getText());
pm.setAction(Actions.PROFILE_UPDATE);
ServerSender.outQ.add(pm);
jd.dispose();
}
});
}
// must have not been actually editing, just viewing
else {
if (cmsg.getResponse() == Responses.OK) {
JDialog jd = new JDialog();
JPanel jp = new JPanel();
JEditorPane jep = new JEditorPane();
jep.setContentType("text/html");
jep.setEditable(false);
jep.setText(((ProfileMsg)cmsg).getProfile());
System.out.println(jep.getText());
JScrollPane jsp = new JScrollPane(jep);
//jp.add(jsp);
//jd.add(jp);
jd.add(jsp);
jd.setSize(200,200);
jd.setTitle("Profile: " + ((ProfileMsg)cmsg).getWantsProfile());
jd.setLocationRelativeTo(null);
jd.setVisible(true);
}
// whoops, can't do that.
else {
JOptionPane.showMessageDialog(null, "Not allowed to view this profile", "Denied!", JOptionPane.ERROR_MESSAGE);
}
}
break;
case OFFLINE_NOTICE:
// one of our buddies went offline
TTClient.blDataStatus.remove(cmsg.getUser());
TTClient.blDataStatus.put(cmsg.getUser(), 0);
TTClient.updateBLNeeded = true;
TTClient.playLogout();
//gah, broken systems!
// make sure that if they have a chat, they now know they're offline...
if (TTClient.pmChats.containsKey(cmsg.getUser())) {
TTClient.pmChats.get(cmsg.getUser()).setSpecialResponse(2);
}
break;
case ONLINE_NOTICE:
// one of our buddies came online
TTClient.blDataStatus.remove(cmsg.getUser());
TTClient.blDataStatus.put(cmsg.getUser(), 1);
TTClient.updateBLNeeded = true;
TTClient.playLogin();
if (TTClient.pmChats.containsKey(cmsg.getUser())) {
TTClient.pmChats.get(cmsg.getUser()).setSpecialResponse(0);
}
break;
case WANT_BL:
// we requested our buddy list
if (((BLMsg) cmsg).getBuddyList() != null) {
TTClient.blData = makeStringArray(((BLMsg)cmsg).getBuddyList());
HashMap<String, Integer> h = new HashMap<String, Integer>();
// hackish method of getting things into the online status table initially
for (String s : TTClient.blData) {
h.put(s, 0);
}
// now we query the entire group status
QueryMsg qm = new QueryMsg(TTClient.ip, TTClient.name, TTClient.pwd, TTClient.key, TTClient.name);
qm.setAction(TTConstants.Actions.QUERY_GROUP);
qm.setUserList(h);
ServerSender.outQ.add(qm);
TTClient.updateBLNeeded = true;
}
else {
// have no buddy list -- just add a blank line or something
String[] s = { "" };
TTClient.blData = s;
TTClient.updateBLNeeded = true;
}
break;
case QUERY_GROUP:
// we got back a hashtable full of the status of the group
TTClient.blDataStatus = ((QueryMsg)cmsg).getUserList();
TTClient.updateBLNeeded = true;
break;
case BL_UPDATE:
// we tried to update our list. complain if things failed
if (cmsg.getResponse() != Responses.OK) {
JOptionPane.showMessageDialog(null, "BuddyList update failed!", "Update failed!", JOptionPane.WARNING_MESSAGE);
}
else {
// reset our copy of bl data.
TTClient.blData = null;
TTClient.blData = makeStringArray(((BLMsg)cmsg).getBuddyList());
HashMap<String, Integer> h = new HashMap<String, Integer>();
for (String s : TTClient.blData) {
h.put(s, 0);
}
// and query for group status again
QueryMsg qm = new QueryMsg(TTClient.ip, TTClient.name, TTClient.pwd, TTClient.key, TTClient.name);
qm.setAction(TTConstants.Actions.QUERY_GROUP);
qm.setUserList(h);
ServerSender.outQ.add(qm);
TTClient.updateBLNeeded = true;
}
break;
case CHAT_UPDATE:
// a group chat update message came in
// if we do find the chat in the chat table
//System.out.println("Chat title is " + ((ChatMsg)cmsg).getTitle());
if (TTClient.chats.containsKey(((ChatMsg)cmsg).getTitle()) && (cmsg.getResponse() == Responses.OK)) {
// update it
//System.out.println(((ChatMsg)cmsg).getTitle());
TTClient.chats.get(((ChatMsg)cmsg).getTitle()).updateChat(cmsg.getUser(), cmsg.getMsg());
if (!cmsg.getUser().equals(TTClient.name)) TTClient.playMsgIn(); // only chime if it was an external update.
}
// otherwise, we just ignore the message, we must not be caring about it anymore or its a mistake
//else System.out.println("couldnt find chat");
break;
case JOIN_CHAT:
// we tried to join a chat
if (cmsg.getResponse() == Responses.OK) {
((ChatMsg)cmsg).getMembers().add(TTClient.name);
// sweet, create a new one
TTClient.chats.put(((ChatMsg)cmsg).getTitle(), new Chat((ChatMsg)cmsg));
}
else {
// complain
JOptionPane.showMessageDialog(null, "Not allowed to join this chat, or it doesn't exist.", "Join chat failed!", JOptionPane.ERROR_MESSAGE);
}
break;
case NEW_CHAT:
// we tried to create a chat
if (cmsg.getResponse() != Responses.DENY) {
// yay, add it to the list of running group chats!
TTClient.chats.put(((ChatMsg)cmsg).getTitle(), new Chat((ChatMsg) cmsg));
}
else {
// whine and cry
JOptionPane.showMessageDialog(null, "Server does not allow you to create this chat.", "Create chat failed!", JOptionPane.ERROR_MESSAGE);
}
break;
}
}
else {
// queue was empty, so sleep as not to absolutely kill CPU/memory usage.
// YES, this was a real problem until we added this in!
try { Thread.sleep(100); }
catch(InterruptedException e) {}
}
}
}
//OH MY GOD I HATE JAVA WHY CAN'T I JUST CAST FROM OBJECT[] TO STRING[] ??
// this method exists as a convient way to get from an object[] array to a string[] array
private String[] makeStringArray(ArrayList<String> al) {
String[] s = new String[al.size()];
for (int i = 0; i < s.length; i++) {
s[i] = al.get(i);
System.out.println(i + " " + s[i]);
}
return s;
}
/**
* Kills off this thread/class
*/
public static void killMsgParser() {
while (go) {
if (ServerListener.inQ.isEmpty()) go = false;
else try {
Thread.sleep(10);
}
catch (Exception e) {}
}
}
}
|