package com.idega.block.messenger.presentation; import java.net.URL; import java.net.URLConnection; import java.net.MalformedURLException; import java.applet.Applet; import java.applet.AudioClip; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.util.Vector; import java.util.Hashtable; import java.util.Enumeration; import java.awt.Component; import java.awt.Label; import java.awt.Graphics; import java.awt.Color; import java.awt.Dimension; import java.awt.Toolkit; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; import com.idega.block.messenger.data.Message; import com.idega.block.messenger.data.Packet; import com.idega.block.messenger.data.Property; import com.idega.block.messenger.business.MessageListener; import com.idega.presentation.awt.ImageLabel; import com.idega.presentation.awt.SingleLineItem; /** * Title: MessengerApplet * Description: Simple client sceleton * Copyright: Copyright (c) 2001 * Company: Idega Software * @author <a href="mailto:eiki@idega.is">Eirikur S. Hrafnsson</a> * @version 1.0 */ public class MessengerApplet extends Applet implements ActionListener{ private static String FRAME_NAME= "IdegaWeb Messenger"; private static int FRAME_WIDTH = 295; private static int FRAME_HEIGHT = 310; private static String SESSION_ID = "session_id"; private static String USER_ID = "user_id"; private static String USER_NAME = "user_name"; private static String USER_LIST = "user_list"; private static String USER_LIST_VERSION = "user_list_version"; private static String SERVLET_URL = "servlet_url"; private static String SERVER_ROOT_URL = "server_root_url"; private static String RESOURCE_URL = "resource_url"; private static String LOG_OUT = "log_out"; private boolean loggingOff = false; private String sessionId; private String userId; private String userName; private String userListVersion = "v.0"; private String servletURL; private URL hostURL; private String resourceURL; private Hashtable dialogs = new Hashtable(); private MessageListener cycler; private AudioClip alertSound; private String keyPressed=null; //private Image offscreenImage; //private Graphics offscr; private long checkTimer = 3000; private Packet packetToServlet; private Packet packetFromServlet; /**Construct the applet*/ public MessengerApplet() { /**@todo make this a parameter*/ } /**Initialize the applet*/ public void init() { try { this.sessionId = this.getParameter(SESSION_ID, "noId"); this.userId = this.getParameter(USER_ID, "-1"); this.userName = this.getParameter(USER_NAME, "Anonymous"); this.servletURL = this.getParameter(SERVLET_URL, "servlet/ClientServer"); this.hostURL = new URL(this.getParameter(SERVER_ROOT_URL, getCodeBase().getProtocol()+"://"+getCodeBase().getHost()+":"+getCodeBase().getPort())); this.resourceURL = this.getParameter(RESOURCE_URL,"/idegaweb/bundles/com.idega.block.messenger.bundle/resources/"); if(this.cycler==null){ this.cycler = new MessageListener(this.checkTimer); this.cycler.addActionListener(this); this.cycler.start(); } } catch(MalformedURLException e) { System.out.println("MessageApplet: error in init getting parameters!"); e.printStackTrace(System.err); } setBackground(Color.white); this.alertSound = getAudioClip(getCodeBase(),"notify.au"); } /** * Display the list of Messages <br> * * Iterate over the vector of Messages and display */ private void dispatchMessagesToDialogs(Vector MessageVector){ Enumeration enumer = MessageVector.elements(); Message aMessage = null; while (enumer.hasMoreElements()){ aMessage = (Message) enumer.nextElement(); MessageDialog messageDialog = (MessageDialog) this.dialogs.get(Integer.toString(aMessage.getId())); if( messageDialog == null ) { //create a new dialog messageDialog = createAMessageDialog(false,aMessage); } messageDialog.addMessage(aMessage); messageDialog.setVisible(true); } } private MessageDialog createAMessageDialog(boolean newId, Message aMessage){ MessageDialog messageDialog; messageDialog = new MessageDialog(FRAME_NAME,aMessage,new ImageLabel(getImage(getCodeBase(),"idegalogo.gif"))); Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); messageDialog.setLocation((d.width - messageDialog.getSize().width) / 2, (d.height - messageDialog.getSize().height) / 2); messageDialog.setSize(FRAME_WIDTH,FRAME_HEIGHT); messageDialog.addActionListener(this); if( this.alertSound!=null ) { messageDialog.setAudioClip(this.alertSound); } else { System.out.println("alert is null"); } if( newId ) { this.dialogs.put(Integer.toString(messageDialog.hashCode()),messageDialog); } else { this.dialogs.put(Integer.toString(aMessage.getId()),messageDialog); } return messageDialog; } private synchronized void getMessagesFromDialog(MessageDialog dialog){//gets called on and iw-send event action if( this.packetToServlet == null ){ this.packetToServlet = new Packet(); } this.packetToServlet.setSender(this.sessionId); Vector msg = dialog.getMessages(); int length = msg.size(); for (int i = 0; i < length; i++) { ((Message)msg.elementAt(i)).setSender(this.sessionId); } /**@todo make this work for many dialogs..*/ this.packetToServlet.addMessages(msg); dialog.clearMessageVector(); cycle(); } private URLConnection getURLConnection(){ System.out.println("GETTING URLConnection"); URLConnection servletConnection = null; try{ // connect to the servlet System.out.println("Connecting to servlet..."); URL servlet = new URL(this.hostURL,this.servletURL); servletConnection = servlet.openConnection(); System.out.println("Connected"); // inform the connection that we will send output and accept input servletConnection.setDoInput(true); servletConnection.setDoOutput(true); // Don't used a cached version of URL connection. servletConnection.setUseCaches(false); // Specify the content type that we will send binary data servletConnection.setRequestProperty("Content-Type", "application/octet-stream"); //servletConnection.setRequestProperty("Connection", "Keep-Alive"); } catch (Exception e){ System.out.println("MessengerApplet : error in getURLConnection"+e.toString()); e.printStackTrace(System.err); } return servletConnection; } /** * Sends the message object to a servlet. It is serialized over the URL connection */ private void sendPacket(URLConnection conn){ ObjectOutputStream outputToServlet = null; try{ if( this.packetToServlet == null) { this.packetToServlet = new Packet(); } if( !this.loggingOff ){ this.packetToServlet.addProperty(new Property(SESSION_ID,this.sessionId)); this.packetToServlet.addProperty(new Property(USER_ID,this.userId)); this.packetToServlet.addProperty(new Property(USER_LIST_VERSION,this.userListVersion)); this.packetToServlet.setSender(this.sessionId); } System.out.println("sending packets"); outputToServlet = new ObjectOutputStream(conn.getOutputStream()); // serialize the object outputToServlet.writeObject(this.packetToServlet); outputToServlet.flush(); outputToServlet.close(); System.out.println("Sending Complete."); } catch (IOException e){ System.out.println(e.getMessage()); e.printStackTrace(System.err); } } /** * Read the input from the servlet. <b> * * The servlet will return a serialized Packet ( with messages, processes and/or property changes ) * */ private void receivePacket(URLConnection conn){ this.packetFromServlet = null; ObjectInputStream theInputFromServlet = null; try{ System.out.println("receiving packets"); theInputFromServlet = new ObjectInputStream(conn.getInputStream()); // read the serialized Packet from the servlet System.out.println("Reading data..."); this.packetFromServlet = (Packet) theInputFromServlet.readObject(); theInputFromServlet.close(); System.out.println("Finished reading data."); } catch (IOException e){ System.out.println(e.getMessage()); e.printStackTrace(System.err); } catch (ClassNotFoundException e){ System.out.println(e.getMessage()); e.printStackTrace(System.err); } } private void processPacket(){ System.out.println("processing the packet ..."); if( this.packetFromServlet!=null ){ this.packetFromServlet.process(this); //Message stuff Vector messages = this.packetFromServlet.getMessages(); if( messages!= null) { dispatchMessagesToDialogs(messages); } //Property stuff userlists etc. Vector props = this.packetFromServlet.getProperties(); Vector userlist = null; if( props!=null ){ int length = props.size(); for (int i = 0; i < length; i++) { if( ((Property)props.elementAt(i)).getKey().equals(USER_LIST) ){ userlist = (Vector)((Property)props.elementAt(i)).getValue(); //update the userlist if(userlist!=null){ syncUserList(userlist); } } else if (((Property)props.elementAt(i)).getKey().equals(USER_LIST_VERSION) ){ this.userListVersion = (String)((Property)props.elementAt(i)).getValue(); } } } }else{ System.err.println("MessengerApplet : packetFromServlet == null !!"); } System.out.println("DONE! processing the packet"); refresh(); this.packetToServlet = null; } private void syncUserList(Vector userlist){ this.removeAll(); int length = userlist.size(); for (int k = 0; k < length; k++) { Property user = (Property)userlist.elementAt(k); String id = user.getKey(); if( !id.equalsIgnoreCase(this.sessionId) ){ addToUserList( id , (String)user.getValue() );//new user } refresh(); } System.out.println("MessengerApplet: userListVersion : "+this.userListVersion); } private void addToUserList(String sendToId, String name){ System.out.println("MessengerApplet: Adding to userlist! id: "+sendToId+" name: "+name); Message msg = new Message(); msg.setSender(sendToId); msg.setSenderName(name); msg.setRecipientName(this.userName); MessageDialog dialog = createAMessageDialog(true,msg); SingleLineItem item = new SingleLineItem(this); item.setId(sendToId); item.setWindowToOpen(dialog); item.addActionListener(this); item.add(new ImageLabel(getImage(getCodeBase(),"face_in.gif"))); item.setNextToFillRight(true); item.add(new Label(name)); add(item); } private void refresh(){ doLayout(); Component[] comps = getComponents(); for (int i = 0; i < comps.length; i++) { comps[i].doLayout(); comps[i].repaint(); comps[i].paintAll(getGraphics()); } repaint(); } public synchronized void cycle(){ URLConnection conn = getURLConnection(); // send the Packet object to the servlet using serialization sendPacket(conn); // now, let's read the packet from the servlet. receivePacket(conn); // get messages, perform processes change properties processPacket(); conn = null; } private Packet getPacketToServlet(){ return this.packetToServlet; } private Packet getPacketFromServlet(){ return this.packetFromServlet; } public synchronized void actionPerformed(ActionEvent e){ String action = e.getActionCommand(); if(action.equalsIgnoreCase("iw-send")){ MessageDialog d = (MessageDialog) e.getSource(); getMessagesFromDialog(d); } else if(action.equalsIgnoreCase("iw-cycle")){ cycle(); } System.out.println("MessengerApplet: action command was :"+action); refresh(); } public void update(Graphics g){ paint(g); } /**Start the applet*/ public void start() { } /**Stop the applet*/ public void stop() { logOff(); if(this.cycler!=null){ this.cycler.stop(); } } protected void logOff(){ this.packetToServlet = new Packet(); this.packetToServlet.addProperty(new Property(LOG_OUT,this.sessionId)); this.loggingOff = true; sendPacket(getURLConnection()); } /**Destroy the applet*/ public void destroy() { logOff(); Graphics g = getGraphics(); if(g != null) { g.dispose(); // crucial g = null; } if(this.cycler!=null){ this.cycler.destroy(); } this.dialogs.clear(); this.dialogs=null; /**@todo travers through hashtable and do this messageDialog.setVisible(false); messageDialog.cancel(); messageDialog.dispose(); messageDialog = null; */ } /**Get Applet information*/ public String getAppletInfo() { return FRAME_NAME; } /**Get a parameter value*/ public String getParameter(String key, String def) { return (getParameter(key) != null ? getParameter(key) : def); } /**Get parameter info*/ public String[][] getParameterInfo() { String[][] pinfo = { {"session_id", "String", "The users sessionId"}, {"user_id", "String", "The users memberId"}, {"servlet_url", "String", "The clientServers url"}, }; return pinfo; } }