1 /*
2  * Copyright (c) 2000, 2017 Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Distribution License v. 1.0, which is available at
6  * http://www.eclipse.org/org/documents/edl-v10.php.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  */
10 
11 /*
12  * @(#)SimpleChat.java	1.13 07/02/07
13  */
14 
15 import java.awt.*;
16 import java.awt.event.*;
17 import java.io.Serializable;
18 import java.net.InetAddress;
19 import java.util.Vector;
20 import java.util.Enumeration;
21 
22 import javax.jms.*;
23 
24 /**
25  * The SimpleChat example is a basic 'chat' application that uses
26  * the JMS APIs. It uses JMS Topics to represent chat rooms or
27  * chat topics.
28  *
29  * When the application is launched, use the 'Chat' menu to
30  * start or connect to a chat session.
31  *
32  * The command line option '-DimqAddressList='can be used to affect
33  * how the application connects to the message service provided by
34  * the Oracle GlassFish(tm) Server Message Queue software.
35  *
36  * It should be pointed out that the bulk of the application is
37  * AWT - code for the GUI. The code that implements the messages
38  * sent/received by the chat application is small in size.
39  *
40  * The SimpleChat example consists of the following classes, all
41  * contained in one file:
42  *
43  *	SimpleChat		- contains main() entry point, GUI/JMS
44  *				  initialization code.
45  *	SimpleChatPanel		- GUI for message textareas.
46  *	SimpleChatDialog	- GUI for "Connect" popup dialog.
47  *	ChatObjMessage	        - chat message class.
48  *
49  * Description of the ChatObjMessage class and how it is used
50  * ==========================================================
51  * The ChatObjMessage class is used to broadcast messages in
52  * the JMS simplechat example.
53  * The interface SimpleChatMessageTypes (defined in this file)
54  * has several message 'types':
55  *
56  * From the interface definition:
57  *     public static int   JOIN    = 0;
58  *     public static int   MSG     = 1;
59  *     public static int   LEAVE   = 2;
60  *
61  * JOIN    - for applications to announce that they just joined the chat
62  * MSG     - for normal text messages
63  * LEAVE   - for applications to announce that are leaving the chat
64  *
65  * Each ChatObjMessage also has fields to indicate who the sender is
66  * - a simple String identifier.
67  *
68  * When the chat application enters a chat session, it broadcasts a JOIN
69  * message. Everybody currently in the chat session will get this and
70  * the chat GUI will recognize the message of type JOIN and will print
71  * something like this in the 'Messages in chat:' textarea:
72  *
73  *         *** johndoe has joined chat session
74  *
75  * Once an application has entered a chat session, messages sent as part of
76  * a normal 'chat' are sent as ChatObjMessage's of type MSG. Upon seeing
77  * these messages, the chat GUI simply displays the sender and the message
78  * text as follows:
79  *
80  *         johndoe: Hello World !
81  *
82  * When a chat disconnect is done, prior to doing the various JMS cleanup
83  * operations, a LEAVE message is sent. The chat GUI sees this and prints
84  * something like:
85  *
86  *         *** johndoe has left chat session
87  *
88  *
89  */
90 public class SimpleChat implements ActionListener,
91 				WindowListener,
92 				MessageListener  {
93 
94     ConnectionFactory            connectionFactory;
95     Connection                   connection;
96     Session                      session;
97     MessageProducer              msgProducer;
98     MessageConsumer              msgConsumer;
99     Topic                        topic;
100 
101     boolean                      connected = false;
102 
103     String                       name, hostName, topicName, outgoingMsgTypeString;
104     int                          outgoingMsgType;
105 
106     Frame                        frame;
107     SimpleChatPanel              scp;
108     SimpleChatDialog             scd = null;
109     MenuItem                     connectItem, disconnectItem, clearItem, exitItem;
110     Button                       sendB, connectB, cancelB;
111 
112     SimpleChatMessageCreator     outgoingMsgCreator;
113 
114     SimpleChatMessageCreator     txtMsgCreator,	objMsgCreator, mapMsgCreator, bytesMsgCreator, streamMsgCreator;
115 
116     /**
117      * @param args	Arguments passed via the command line. These are
118      *			used to create the ConnectionFactory.
119      */
main(String[] args)120     public static void main(String[] args) {
121 	SimpleChat	sc = new SimpleChat();
122 
123 	sc.initGui();
124 	sc.initJms(args);
125     }
126 
127     /**
128      * SimpleChat constructor.
129      * Initializes the chat user name, topic, hostname.
130      */
SimpleChat()131     public SimpleChat()  {
132         name = System.getProperty("user.name", "johndoe");
133         topicName = "defaulttopic";
134 
135 	try  {
136 	    hostName = InetAddress.getLocalHost().getHostName();
137 	} catch (Exception e)  {
138 	    hostName = "localhost";
139 	}
140     }
141 
getMessageCreator(int type)142     public SimpleChatMessageCreator getMessageCreator(int type)  {
143 	switch (type)  {
144 	case SimpleChatDialog.MSG_TYPE_TEXT:
145 	    if (txtMsgCreator == null)  {
146 		txtMsgCreator = new SimpleChatTextMessageCreator();
147 	    }
148 	    return (txtMsgCreator);
149 
150 	case SimpleChatDialog.MSG_TYPE_OBJECT:
151 	    if (objMsgCreator == null)  {
152 		objMsgCreator = new SimpleChatObjMessageCreator();
153 	    }
154 	    return (objMsgCreator);
155 
156 	case SimpleChatDialog.MSG_TYPE_MAP:
157 	    if (mapMsgCreator == null)  {
158 		mapMsgCreator = new SimpleChatMapMessageCreator();
159 	    }
160 	    return (mapMsgCreator);
161 
162 	case SimpleChatDialog.MSG_TYPE_BYTES:
163 	    if (bytesMsgCreator == null)  {
164 		bytesMsgCreator = new SimpleChatBytesMessageCreator();
165 	    }
166 	    return (bytesMsgCreator);
167 
168 	case SimpleChatDialog.MSG_TYPE_STREAM:
169 	    if (streamMsgCreator == null)  {
170 		streamMsgCreator = new SimpleChatStreamMessageCreator();
171 	    }
172 	    return (streamMsgCreator);
173 	}
174 
175 	return (null);
176     }
177 
getMessageCreator(Message msg)178     public SimpleChatMessageCreator getMessageCreator(Message msg)  {
179 	if (msg instanceof TextMessage)  {
180 	    if (txtMsgCreator == null)  {
181 		txtMsgCreator = new SimpleChatTextMessageCreator();
182 	    }
183 	    return (txtMsgCreator);
184 	} else if (msg instanceof ObjectMessage)  {
185 	    if (objMsgCreator == null)  {
186 		objMsgCreator = new SimpleChatObjMessageCreator();
187 	    }
188 	    return (objMsgCreator);
189 	} else if (msg instanceof MapMessage)  {
190 	    if (mapMsgCreator == null)  {
191 		mapMsgCreator = new SimpleChatMapMessageCreator();
192 	    }
193 	    return (mapMsgCreator);
194 	} else if (msg instanceof BytesMessage)  {
195 	    if (bytesMsgCreator == null)  {
196 		bytesMsgCreator = new SimpleChatBytesMessageCreator();
197 	    }
198 	    return (bytesMsgCreator);
199 	} else if (msg instanceof StreamMessage)  {
200 	    if (streamMsgCreator == null)  {
201 		streamMsgCreator = new SimpleChatStreamMessageCreator();
202 	    }
203 	    return (streamMsgCreator);
204 	}
205 
206 	return (null);
207     }
208 
209     /*
210      * BEGIN INTERFACE ActionListener
211      */
212     /**
213      * Detects the various UI actions and performs the
214      * relevant action:
215      *	Connect menu item (on Chat menu):	Show Connect dialog
216      *	Disconnect menu item (on Chat menu):	Disconnect from chat
217      *	Connect button (on Connect dialog):	Connect to specified
218      *						chat
219      *	Cancel button (on Connect dialog):	Hide Connect dialog
220      *	Send button:				Send message to chat
221      *	Clear menu item (on Chat menu):		Clear chat textarea
222      *	Exit menu item (on Chat menu):		Exit application
223      *
224      * @param ActionEvent UI event
225      */
actionPerformed(ActionEvent e)226     public void actionPerformed(ActionEvent e)  {
227 	Object		obj = e.getSource();
228 
229 	if (obj == connectItem)  {
230 	    queryForChatNames();
231 	} else if (obj == disconnectItem)  {
232 	    doDisconnect();
233 	} else if (obj == connectB)  {
234 	    scd.setVisible(false);
235 
236 	    topicName = scd.getChatTopicName();
237 	    name = scd.getChatUserName();
238 	    outgoingMsgTypeString = scd.getMsgTypeString();
239 	    outgoingMsgType = scd.getMsgType();
240 	    doConnect();
241 	} else if (obj == cancelB)  {
242 	    scd.setVisible(false);
243 	} else if (obj == sendB)  {
244 	    sendNormalMessage();
245 	} else if (obj == clearItem)  {
246 	    scp.clear();
247 	} else if (obj == exitItem)  {
248 	    exit();
249 	}
250     }
251     /*
252      * END INTERFACE ActionListener
253      */
254 
255     /*
256      * BEGIN INTERFACE WindowListener
257      */
windowClosing(WindowEvent e)258     public void windowClosing(WindowEvent e)  {
259         e.getWindow().dispose();
260     }
windowClosed(WindowEvent e)261     public void windowClosed(WindowEvent e)  {
262 	exit();
263     }
windowActivated(WindowEvent e)264     public void windowActivated(WindowEvent e)  { }
windowDeactivated(WindowEvent e)265     public void windowDeactivated(WindowEvent e)  { }
windowDeiconified(WindowEvent e)266     public void windowDeiconified(WindowEvent e)  { }
windowIconified(WindowEvent e)267     public void windowIconified(WindowEvent e)  { }
windowOpened(WindowEvent e)268     public void windowOpened(WindowEvent e)  { }
269     /*
270      * END INTERFACE WindowListener
271      */
272 
273     /*
274      * BEGIN INTERFACE MessageListener
275      */
276     /**
277      * Display chat message on gui.
278      *
279      * @param msg message received
280      */
onMessage(Message msg)281     public void onMessage(Message msg)  {
282 	String		sender, msgText;
283 	int		type;
284 	SimpleChatMessageCreator	inboundMsgCreator;
285 
286 	inboundMsgCreator = getMessageCreator(msg);
287 
288 	if (inboundMsgCreator == null)  {
289             errorMessage("Message received is not supported ! ");
290 	    return;
291 	}
292 
293 	/*
294 	 *  Need to fetch msg values in this order.
295 	 */
296 	type = inboundMsgCreator.getChatMessageType(msg);
297 	sender = inboundMsgCreator.getChatMessageSender(msg);
298 	msgText = inboundMsgCreator.getChatMessageText(msg);
299 
300 	if (type == SimpleChatMessageTypes.BADTYPE)  {
301             errorMessage("Message received in wrong format ! ");
302 	    return;
303 	}
304 
305 	scp.newMessage(sender, type, msgText);
306     }
307     /*
308      * END INTERFACE MessageListener
309      */
310 
311 
312     /*
313      * Popup the SimpleChatDialog to query the user for the chat user
314      * name and chat topic.
315      */
queryForChatNames()316     private void queryForChatNames()  {
317 	if (scd == null)  {
318 	    scd = new SimpleChatDialog(frame);
319 	    connectB = scd.getConnectButton();
320 	    connectB.addActionListener(this);
321 	    cancelB = scd.getCancelButton();
322 	    cancelB.addActionListener(this);
323 	}
324 
325 	scd.setChatUserName(name);
326 	scd.setChatTopicName(topicName);
327 	scd.show();
328     }
329 
330     /*
331      * Performs the actual chat connect.
332      * The createChatSession() method does the real work
333      * here, creating:
334      *		Connection
335      *		Session
336      *		Topic
337      *		MessageConsumer
338      *		MessageProducer
339      */
doConnect()340     private void doConnect()  {
341 	if (connectedToChatSession())
342 	    return;
343 
344 	outgoingMsgCreator = getMessageCreator(outgoingMsgType);
345 
346 	if (createChatSession(topicName) == false) {
347 	    errorMessage("Unable to create Chat session.  " +
348 			 "Please verify a broker is running");
349 	    return;
350 	}
351 	setConnectedToChatSession(true);
352 
353 	connectItem.setEnabled(false);
354 	disconnectItem.setEnabled(true);
355 
356 	scp.setUserName(name);
357 	scp.setDestName(topicName);
358 	scp.setMsgType(outgoingMsgTypeString);
359 	scp.setHostName(hostName);
360 	scp.setEnabled(true);
361     }
362 
363     /*
364      * Disconnects from chat session.
365      * destroyChatSession() performs the JMS cleanup.
366      */
doDisconnect()367     private void doDisconnect()  {
368 	if (!connectedToChatSession())
369 	    return;
370 
371 	destroyChatSession();
372 
373 	setConnectedToChatSession(false);
374 
375 	connectItem.setEnabled(true);
376 	disconnectItem.setEnabled(false);
377 	scp.setEnabled(false);
378     }
379 
380     /*
381      * These methods set/return a flag that indicates
382      * whether the application is currently involved in
383      * a chat session.
384      */
setConnectedToChatSession(boolean b)385     private void setConnectedToChatSession(boolean b)  {
386 	connected = b;
387     }
connectedToChatSession()388     private boolean connectedToChatSession()  {
389 	return (connected);
390     }
391 
392     /*
393      * Exit application. Does some cleanup if
394      * necessary.
395      */
exit()396     private void exit()  {
397 	doDisconnect();
398         System.exit(0);
399     }
400 
401     /*
402      * Create the application GUI.
403      */
initGui()404     private void initGui() {
405 
406 	frame = new Frame("Simple Chat");
407 
408 	frame.addWindowListener(this);
409 
410 	MenuBar	menubar = createMenuBar();
411 
412         frame.setMenuBar(menubar);
413 
414 	scp = new SimpleChatPanel();
415 	scp.setUserName(name);
416 	scp.setDestName(topicName);
417 	scp.setHostName(hostName);
418 	sendB = scp.getSendButton();
419 	sendB.addActionListener(this);
420 
421 	frame.add(scp);
422 	frame.pack();
423 	frame.setVisible(true);
424 
425 	scp.setEnabled(false);
426     }
427 
428     /*
429      * Create menubar for application.
430      */
createMenuBar()431     private MenuBar createMenuBar() {
432 	MenuBar	mb = new MenuBar();
433         Menu chatMenu;
434 
435 	chatMenu = (Menu) mb.add(new Menu("Chat"));
436 	connectItem = (MenuItem) chatMenu.add(new MenuItem("Connect ..."));
437 	disconnectItem = (MenuItem) chatMenu.add(new MenuItem("Disconnect"));
438 	clearItem = (MenuItem) chatMenu.add(new MenuItem("Clear Messages"));
439 	exitItem = (MenuItem) chatMenu.add(new MenuItem("Exit"));
440 
441 	disconnectItem.setEnabled(false);
442 
443         connectItem.addActionListener(this);
444         disconnectItem.addActionListener(this);
445         clearItem.addActionListener(this);
446 	exitItem.addActionListener(this);
447 
448 	return (mb);
449     }
450 
451     /*
452      * Send message using text that is currently in the SimpleChatPanel
453      * object. The text message is obtained via scp.getMessage()
454      *
455      * An object of type ChatObjMessage is created containing the typed
456      * text. A JMS ObjectMessage is used to encapsulate this ChatObjMessage
457      * object.
458      */
sendNormalMessage()459     private void sendNormalMessage()  {
460 	Message		msg;
461 
462 	if (!connectedToChatSession())  {
463 	    errorMessage("Cannot send message: Not connected to chat session!");
464 
465 	    return;
466 	}
467 
468 	try  {
469 	    msg = outgoingMsgCreator.createChatMessage(session,
470 					name,
471 					SimpleChatMessageTypes.NORMAL,
472 					scp.getMessage());
473 
474             msgProducer.send(msg);
475 	    scp.setMessage("");
476 	    scp.requestFocus();
477 	} catch (Exception ex)  {
478 	    errorMessage("Caught exception while sending NORMAL message: " + ex);
479 	}
480     }
481 
482     /*
483      * Send a message to the chat session to inform people
484      * we just joined the chat.
485      */
sendJoinMessage()486     private void sendJoinMessage()  {
487 	Message		msg;
488 
489 	try  {
490 	    msg = outgoingMsgCreator.createChatMessage(session,
491 					name,
492 					SimpleChatMessageTypes.JOIN,
493 					null);
494 
495             msgProducer.send(msg);
496 	} catch (Exception ex)  {
497 	    errorMessage("Caught exception while sending JOIN message: " + ex);
498 	}
499     }
500     /*
501      * Send a message to the chat session to inform people
502      * we are leaving the chat.
503      */
sendLeaveMessage()504     private void sendLeaveMessage()  {
505 	Message		msg;
506 
507 	try  {
508 	    msg = outgoingMsgCreator.createChatMessage(session,
509 					name,
510 					SimpleChatMessageTypes.LEAVE,
511 					null);
512 
513             msgProducer.send(msg);
514 	} catch (Exception ex)  {
515 	    errorMessage("Caught exception while sending LEAVE message: " + ex);
516 	}
517     }
518 
519     /*
520      * JMS initialization.
521      * This is simply creating the ConnectionFactory.
522      */
initJms(String args[])523     private void initJms(String args[]) {
524 	/* XXX: chg for JMS1.1 to use BasicConnectionFactory for non-JNDI useage
525 	 * remove --- Use BasicConnectionFactory directly - no JNDI
526 	*/
527 	try  {
528             connectionFactory
529 		= new com.sun.messaging.ConnectionFactory();
530 	} catch (Exception e)  {
531 	    errorMessage("Caught Exception: " + e);
532 	}
533     }
534 
535     /*
536      * Create 'chat session'. This involves creating:
537      *		Connection
538      *		Session
539      *		Topic
540      *		MessageConsumer
541      *		MessageProducer
542      */
createChatSession(String topicStr)543     private boolean createChatSession(String topicStr) {
544 	try  {
545 	    /*
546 	     * Create the connection...
547 	     *
548 	    */
549             connection = connectionFactory.createConnection();
550 
551 	    /*
552 	     * Not transacted
553 	     * Auto acknowledegement
554 	     */
555             session = connection.createSession(false,
556 						Session.AUTO_ACKNOWLEDGE);
557 
558 	    topic = session.createTopic(topicStr);
559 	    msgProducer = session.createProducer(topic);
560 	    /*
561 	     * Non persistent delivery
562 	     */
563 	    msgProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
564 	    msgConsumer = session.createConsumer(topic);
565 	    msgConsumer.setMessageListener(this);
566 
567             connection.start();
568 
569 	    sendJoinMessage();
570 
571 	    return true;
572 
573 	} catch (Exception e)  {
574 	    errorMessage("Caught Exception: " + e);
575             e.printStackTrace();
576             return false;
577 	}
578     }
579     /*
580      * Destroy/close 'chat session'.
581      */
destroyChatSession()582     private void destroyChatSession()  {
583 	try  {
584 	    sendLeaveMessage();
585 
586 	    msgConsumer.close();
587 	    msgProducer.close();
588 	    session.close();
589 	    connection.close();
590 
591 	    topic = null;
592 	    msgConsumer = null;
593 	    msgProducer = null;
594 	    session = null;
595 	    connection = null;
596 
597 	} catch (Exception e)  {
598 	    errorMessage("Caught Exception: " + e);
599 	}
600 
601     }
602 
603     /*
604      * Display error. Right now all we do is dump to
605      * stderr.
606      */
errorMessage(String s)607     private void errorMessage(String s)  {
608         System.err.println(s);
609     }
610 
611 
612 }
613 
614 /**
615  * This class provides the bulk of the UI:
616  *	sendMsgTA	TextArea for typing messages to send
617  *	msgsTA		TextArea for displaying messages in chat
618  *	sendB		Send button for activating a message 'Send'.
619  *
620  *	...and various labels to indicate the chat topic name,
621  *	the user name, and host name.
622  *
623  */
624 class SimpleChatPanel extends Panel implements SimpleChatMessageTypes  {
625     private String	destName,
626 			userName,
627 			msgType,
628 			hostName;
629 
630     private Button	sendB;
631 
632     private Label	destLabel, userLabel, msgTypeLabel, msgsLabel,
633 			sendMsgLabel;
634 
635     private TextArea	msgsTA;
636 
637     private TextArea	sendMsgTA;
638 
639     /**
640      * SimpleChatPanel constructor
641      */
SimpleChatPanel()642     public SimpleChatPanel()  {
643 	init();
644     }
645 
646     /**
647      * Set the chat username
648      * @param userName Chat userName
649      */
setUserName(String userName)650     public void setUserName(String userName)  {
651 	this.userName = userName;
652 	userLabel.setText("User Id: " + userName);
653 	sendB.setLabel("Send Message as " + userName);
654     }
655     /**
656      * Set the chat hostname. This is pretty much
657      * the host that the router is running on.
658      * @param hostName Chat hostName
659      */
setHostName(String hostName)660     public void setHostName(String hostName)  {
661 	this.hostName = hostName;
662     }
663     /**
664      * Sets the topic name.
665      * @param destName Chat topic name
666      */
setDestName(String destName)667     public void setDestName(String destName)  {
668 	this.destName = destName;
669 	destLabel.setText("Topic: " + destName);
670     }
671 
setMsgType(String msgType)672     public void setMsgType(String msgType)  {
673 	this.msgType = msgType;
674 	msgTypeLabel.setText("Outgoing Msg Type: " + msgType);
675     }
676 
677     /**
678      * Returns the 'Send' button.
679      */
getSendButton()680     public Button getSendButton()  {
681 	return(sendB);
682     }
683 
684     /**
685      * Clears the chat message text area.
686      */
clear()687     public void clear()  {
688 	msgsTA.setText("");
689     }
690 
691     /**
692      * Appends the passed message to the chat message text area.
693      * @param msg Message to display
694      */
newMessage(String sender, int type, String text)695     public void newMessage(String sender, int type, String text)  {
696 	switch (type)  {
697 	case NORMAL:
698 	    msgsTA.append(sender +  ": " + text + "\n");
699 	break;
700 
701 	case JOIN:
702 	    msgsTA.append("*** " +  sender +  " has joined chat session\n");
703 	break;
704 
705 	case LEAVE:
706 	    msgsTA.append("*** " +  sender +  " has left chat session\n");
707 	break;
708 
709 	default:
710 	}
711     }
712 
713     /**
714      * Sets the string to display on the chat message textarea
715      * @param s String to display
716      */
setMessage(String s)717     public void setMessage(String s)  {
718 	sendMsgTA.setText(s);
719     }
720     /**
721      * Returns the contents of the chat message textarea
722      */
getMessage()723     public String getMessage()  {
724 	return (sendMsgTA.getText());
725     }
726 
727     /*
728      * Init chat panel GUI elements.
729      */
init()730     private void init()  {
731 
732 	Panel	dummyPanel;
733 
734 	setLayout(new BorderLayout(0, 0));
735 
736 	destLabel = new Label("Topic:");
737 
738 	userLabel = new Label("User Id: ");
739 
740 	msgTypeLabel = new Label("Outgoing Msg Type:");
741 
742 
743 
744 	dummyPanel = new Panel();
745 	dummyPanel.setLayout(new BorderLayout(0, 0));
746 	dummyPanel.add("North", destLabel);
747 	dummyPanel.add("Center", userLabel);
748 	dummyPanel.add("South", msgTypeLabel);
749 	add("North", dummyPanel);
750 
751 	dummyPanel = new Panel();
752 	dummyPanel.setLayout(new BorderLayout(0, 0));
753 	msgsLabel = new Label("Messages in chat:");
754 	msgsTA = new TextArea(15, 40);
755 	msgsTA.setEditable(false);
756 
757 	dummyPanel.add("North", msgsLabel);
758 	dummyPanel.add("Center", msgsTA);
759 	add("Center", dummyPanel);
760 
761 	dummyPanel = new Panel();
762 	dummyPanel.setLayout(new BorderLayout(0, 0));
763 	sendMsgLabel = new Label("Type Message:");
764 	sendMsgTA = new TextArea(5, 40);
765 	sendB = new Button("Send Message");
766 	dummyPanel.add("North", sendMsgLabel);
767 	dummyPanel.add("Center", sendMsgTA);
768 	dummyPanel.add("South", sendB);
769 	add("South", dummyPanel);
770     }
771 }
772 
773 /**
774  * Dialog for querying the chat user name and chat topic.
775  *
776  */
777 class SimpleChatDialog extends Dialog  {
778 
779     public final static int	MSG_TYPE_UNDEFINED	= -1;
780     public final static int	MSG_TYPE_OBJECT		= 0;
781     public final static int	MSG_TYPE_TEXT		= 1;
782     public final static int	MSG_TYPE_MAP		= 2;
783     public final static int	MSG_TYPE_BYTES		= 3;
784     public final static int	MSG_TYPE_STREAM		= 4;
785 
786     private TextField	nameF, topicF;
787     private Choice	msgTypeChoice;
788     private Button	connectB, cancelB;
789 
790     /**
791      * SimpleChatDialog constructor.
792      * @param f Parent frame.
793      */
SimpleChatDialog(Frame f)794     public SimpleChatDialog(Frame f)  {
795 	super(f, "Simple Chat: Connect information", true);
796 	init();
797 	setResizable(false);
798     }
799 
800     /**
801      * Return 'Connect' button
802      */
getConnectButton()803     public Button getConnectButton()  {
804 	return (connectB);
805     }
806     /**
807      * Return 'Cancel' button
808      */
getCancelButton()809     public Button getCancelButton()  {
810 	return (cancelB);
811     }
812 
813     /**
814      * Return chat user name entered.
815      */
getChatUserName()816     public String getChatUserName()  {
817 	if (nameF == null)
818 	    return (null);
819 	return (nameF.getText());
820     }
821     /**
822      * Set chat user name.
823      * @param s chat user name
824      */
setChatUserName(String s)825     public void setChatUserName(String s)  {
826 	if (nameF == null)
827 	    return;
828 	nameF.setText(s);
829     }
830 
831     /**
832      * Set chat topic
833      * @param s chat topic
834      */
setChatTopicName(String s)835     public void setChatTopicName(String s)  {
836 	if (topicF == null)
837 	    return;
838 	topicF.setText(s);
839     }
840     /**
841      * Return chat topic
842      */
getChatTopicName()843     public String getChatTopicName()  {
844 	if (topicF == null)
845 	    return (null);
846 	return (topicF.getText());
847     }
848 
849     /*
850      * Get message type
851      */
getMsgType()852     public int getMsgType()  {
853 	if (msgTypeChoice == null)
854 	    return (MSG_TYPE_UNDEFINED);
855 	return (msgTypeChoice.getSelectedIndex());
856     }
857 
getMsgTypeString()858     public String getMsgTypeString()  {
859 	if (msgTypeChoice == null)
860 	    return (null);
861 	return (msgTypeChoice.getSelectedItem());
862     }
863 
864     /*
865      * Init GUI elements.
866      */
init()867     private void init()  {
868 	Panel			p, dummyPanel, labelPanel, valuePanel;
869 	GridBagLayout		labelGbag, valueGbag;
870 	GridBagConstraints      labelConstraints, valueConstraints;
871 	Label			chatNameLabel, chatTopicLabel,
872 				msgTypeLabel;
873 	int			i, j;
874 
875 	p = new Panel();
876 	p.setLayout(new BorderLayout());
877 
878 	dummyPanel = new Panel();
879 	dummyPanel.setLayout(new BorderLayout());
880 
881 	/***/
882 	labelPanel = new Panel();
883 	labelGbag = new GridBagLayout();
884 	labelConstraints = new GridBagConstraints();
885 	labelPanel.setLayout(labelGbag);
886 	j = 0;
887 
888 	valuePanel = new Panel();
889 	valueGbag = new GridBagLayout();
890 	valueConstraints = new GridBagConstraints();
891 	valuePanel.setLayout(valueGbag);
892 	i = 0;
893 
894 	chatNameLabel = new Label("Chat User Name:", Label.RIGHT);
895 	chatTopicLabel = new Label("Chat Topic:", Label.RIGHT);
896 	msgTypeLabel = new Label("Outgoing Msg Type:", Label.RIGHT);
897 
898 	labelConstraints.gridx = 0;
899 	labelConstraints.gridy = j++;
900 	labelConstraints.weightx = 1.0;
901 	labelConstraints.weighty = 1.0;
902 	labelConstraints.anchor = GridBagConstraints.EAST;
903 	labelGbag.setConstraints(chatNameLabel, labelConstraints);
904 	labelPanel.add(chatNameLabel);
905 
906 	labelConstraints.gridy = j++;
907 	labelGbag.setConstraints(chatTopicLabel, labelConstraints);
908 	labelPanel.add(chatTopicLabel);
909 
910 	labelConstraints.gridy = j++;
911 	labelGbag.setConstraints(msgTypeLabel, labelConstraints);
912 	labelPanel.add(msgTypeLabel);
913 
914 	nameF = new TextField(20);
915 	topicF = new TextField(20);
916 	msgTypeChoice = new Choice();
917 	msgTypeChoice.insert("ObjectMessage", MSG_TYPE_OBJECT);
918 	msgTypeChoice.insert("TextMessage", MSG_TYPE_TEXT);
919 	msgTypeChoice.insert("MapMessage", MSG_TYPE_MAP);
920 	msgTypeChoice.insert("BytesMessage", MSG_TYPE_BYTES);
921 	msgTypeChoice.insert("StreamMessage", MSG_TYPE_STREAM);
922 	msgTypeChoice.select(MSG_TYPE_STREAM);
923 
924 	valueConstraints.gridx = 0;
925 	valueConstraints.gridy = i++;
926 	valueConstraints.weightx = 1.0;
927 	valueConstraints.weighty = 1.0;
928 	valueConstraints.anchor = GridBagConstraints.WEST;
929 	valueGbag.setConstraints(nameF, valueConstraints);
930 	valuePanel.add(nameF);
931 
932 	valueConstraints.gridy = i++;
933 	valueGbag.setConstraints(topicF, valueConstraints);
934 	valuePanel.add(topicF);
935 
936 	valueConstraints.gridy = i++;
937 	valueGbag.setConstraints(msgTypeChoice, valueConstraints);
938 	valuePanel.add(msgTypeChoice);
939 
940 	dummyPanel.add("West", labelPanel);
941 	dummyPanel.add("Center", valuePanel);
942 	/***/
943 
944 	p.add("North", dummyPanel);
945 
946 	dummyPanel = new Panel();
947 	connectB = new Button("Connect");
948 	cancelB = new Button("Cancel");
949 	dummyPanel.add(connectB);
950 	dummyPanel.add(cancelB);
951 
952 	p.add("South", dummyPanel);
953 
954 	add(p);
955 	pack();
956     }
957 }
958 
959 interface SimpleChatMessageTypes  {
960     public static int	JOIN	= 0;
961     public static int	NORMAL	= 1;
962     public static int	LEAVE	= 2;
963     public static int	BADTYPE	= -1;
964 }
965 
966 interface SimpleChatMessageCreator  {
createChatMessage(Session session, String sender, int type, String text)967     public Message createChatMessage(Session session, String sender,
968 					int type, String text);
isUsable(Message msg)969     public boolean isUsable(Message msg);
getChatMessageType(Message msg)970     public int getChatMessageType(Message msg);
getChatMessageSender(Message msg)971     public String getChatMessageSender(Message msg);
getChatMessageText(Message msg)972     public String getChatMessageText(Message msg);
973 }
974 
975 class SimpleChatTextMessageCreator implements
976 			SimpleChatMessageCreator, SimpleChatMessageTypes  {
977     private static String MSG_SENDER_PROPNAME =	"SIMPLECHAT_MSG_SENDER";
978     private static String MSG_TYPE_PROPNAME =	"SIMPLECHAT_MSG_TYPE";
979 
createChatMessage(Session session, String sender, int type, String text)980     public Message createChatMessage(Session session, String sender,
981 					int type, String text)  {
982 	TextMessage		txtMsg = null;
983 
984         try  {
985             txtMsg = session.createTextMessage();
986 	    txtMsg.setStringProperty(MSG_SENDER_PROPNAME, sender);
987 	    txtMsg.setIntProperty(MSG_TYPE_PROPNAME, type);
988 	    txtMsg.setText(text);
989         } catch (Exception ex)  {
990 	    System.err.println("Caught exception while creating message: " + ex);
991         }
992 
993 	return (txtMsg);
994     }
995 
isUsable(Message msg)996     public boolean isUsable(Message msg)  {
997 	if (msg instanceof TextMessage)  {
998 	    return (true);
999 	}
1000 
1001 	return (false);
1002     }
1003 
getChatMessageType(Message msg)1004     public int getChatMessageType(Message msg)  {
1005 	int	type = BADTYPE;
1006 
1007 	try  {
1008 	    TextMessage	txtMsg = (TextMessage)msg;
1009 	    type = txtMsg.getIntProperty(MSG_TYPE_PROPNAME);
1010 	} catch (Exception ex)  {
1011 	    System.err.println("Caught exception: " + ex);
1012 	}
1013 
1014 	return (type);
1015     }
1016 
getChatMessageSender(Message msg)1017     public String getChatMessageSender(Message msg)  {
1018 	String	sender = null;
1019 
1020 	try  {
1021 	    TextMessage	txtMsg = (TextMessage)msg;
1022 	    sender = txtMsg.getStringProperty(MSG_SENDER_PROPNAME);
1023 	} catch (Exception ex)  {
1024 	    System.err.println("Caught exception: " + ex);
1025 	}
1026 
1027 	return (sender);
1028     }
1029 
getChatMessageText(Message msg)1030     public String getChatMessageText(Message msg)  {
1031 	String	text = null;
1032 
1033 	try  {
1034 	    TextMessage	txtMsg = (TextMessage)msg;
1035 	    text = txtMsg.getText();
1036 	} catch (Exception ex)  {
1037 	    System.err.println("Caught exception: " + ex);
1038 	}
1039 
1040 	return (text);
1041     }
1042 }
1043 
1044 class SimpleChatObjMessageCreator implements
1045 		SimpleChatMessageCreator, SimpleChatMessageTypes  {
createChatMessage(Session session, String sender, int type, String text)1046     public Message createChatMessage(Session session, String sender,
1047 					int type, String text)  {
1048 	ObjectMessage		objMsg = null;
1049 	ChatObjMessage	sMsg;
1050 
1051         try  {
1052             objMsg = session.createObjectMessage();
1053             sMsg = new ChatObjMessage(sender, type, text);
1054             objMsg.setObject(sMsg);
1055         } catch (Exception ex)  {
1056 	    System.err.println("Caught exception while creating message: " + ex);
1057         }
1058 
1059 	return (objMsg);
1060     }
1061 
isUsable(Message msg)1062     public boolean isUsable(Message msg)  {
1063 	try  {
1064 	    ChatObjMessage	sMsg = getSimpleChatMessage(msg);
1065 	    if (sMsg == null)  {
1066 	        return (false);
1067 	    }
1068 	} catch (Exception ex)  {
1069 	    System.err.println("Caught exception: " + ex);
1070 	}
1071 
1072 	return (true);
1073     }
1074 
getChatMessageType(Message msg)1075     public int getChatMessageType(Message msg)  {
1076 	int	type = BADTYPE;
1077 
1078 	try  {
1079 	    ChatObjMessage	sMsg = getSimpleChatMessage(msg);
1080 	    if (sMsg != null)  {
1081 	        type = sMsg.getType();
1082 	    }
1083 	} catch (Exception ex)  {
1084 	    System.err.println("Caught exception: " + ex);
1085 	}
1086 
1087 	return (type);
1088     }
1089 
getChatMessageSender(Message msg)1090     public String getChatMessageSender(Message msg)  {
1091 	String		sender = null;
1092 
1093 	try  {
1094 	    ChatObjMessage	sMsg = getSimpleChatMessage(msg);
1095 	    if (sMsg != null)  {
1096 	        sender = sMsg.getSender();
1097 	    }
1098 	} catch (Exception ex)  {
1099 	    System.err.println("Caught exception: " + ex);
1100 	}
1101 
1102 	return (sender);
1103     }
1104 
getChatMessageText(Message msg)1105     public String getChatMessageText(Message msg)  {
1106 	String			text = null;
1107 
1108 	try  {
1109 	    ChatObjMessage	sMsg = getSimpleChatMessage(msg);
1110 	    if (sMsg != null)  {
1111 	        text = sMsg.getMessage();
1112 	    }
1113 	} catch (Exception ex)  {
1114 	    System.err.println("Caught exception: " + ex);
1115 	}
1116 
1117 	return (text);
1118     }
1119 
getSimpleChatMessage(Message msg)1120     private ChatObjMessage getSimpleChatMessage(Message msg)  {
1121 	ObjectMessage		objMsg;
1122 	ChatObjMessage	sMsg = null;
1123 
1124 	if (!(msg instanceof ObjectMessage))  {
1125 	    System.err.println("SimpleChatObjMessageCreator: Message received not of type ObjectMessage!");
1126 	    return (null);
1127 	}
1128 
1129 	objMsg = (ObjectMessage)msg;
1130 
1131 	try  {
1132 	    sMsg = (ChatObjMessage)objMsg.getObject();
1133 	} catch (Exception ex)  {
1134 	    System.err.println("Caught exception: " + ex);
1135 	}
1136 
1137 	return (sMsg);
1138     }
1139 }
1140 
1141 class SimpleChatMapMessageCreator implements
1142 			SimpleChatMessageCreator, SimpleChatMessageTypes  {
1143     private static String MAPMSG_SENDER_PROPNAME =	"SIMPLECHAT_MAPMSG_SENDER";
1144     private static String MAPMSG_TYPE_PROPNAME =	"SIMPLECHAT_MAPMSG_TYPE";
1145     private static String MAPMSG_TEXT_PROPNAME =	"SIMPLECHAT_MAPMSG_TEXT";
1146 
createChatMessage(Session session, String sender, int type, String text)1147     public Message createChatMessage(Session session, String sender,
1148 					int type, String text)  {
1149 	MapMessage		mapMsg = null;
1150 
1151         try  {
1152             mapMsg = session.createMapMessage();
1153 	    mapMsg.setInt(MAPMSG_TYPE_PROPNAME, type);
1154 	    mapMsg.setString(MAPMSG_SENDER_PROPNAME, sender);
1155 	    mapMsg.setString(MAPMSG_TEXT_PROPNAME, text);
1156         } catch (Exception ex)  {
1157 	    System.err.println("Caught exception while creating message: " + ex);
1158         }
1159 
1160 	return (mapMsg);
1161     }
1162 
isUsable(Message msg)1163     public boolean isUsable(Message msg)  {
1164 	if (msg instanceof MapMessage)  {
1165 	    return (true);
1166 	}
1167 
1168 	return (false);
1169     }
1170 
getChatMessageType(Message msg)1171     public int getChatMessageType(Message msg)  {
1172 	int	type = BADTYPE;
1173 
1174 	try  {
1175 	    MapMessage	mapMsg = (MapMessage)msg;
1176 	    type = mapMsg.getInt(MAPMSG_TYPE_PROPNAME);
1177 	} catch (Exception ex)  {
1178 	    System.err.println("Caught exception: " + ex);
1179 	}
1180 
1181 	return (type);
1182     }
1183 
getChatMessageSender(Message msg)1184     public String getChatMessageSender(Message msg)  {
1185 	String	sender = null;
1186 
1187 	try  {
1188 	    MapMessage	mapMsg = (MapMessage)msg;
1189 	    sender = mapMsg.getString(MAPMSG_SENDER_PROPNAME);
1190 	} catch (Exception ex)  {
1191 	    System.err.println("Caught exception: " + ex);
1192 	}
1193 
1194 	return (sender);
1195     }
1196 
getChatMessageText(Message msg)1197     public String getChatMessageText(Message msg)  {
1198 	String	text = null;
1199 
1200 	try  {
1201 	    MapMessage	mapMsg = (MapMessage)msg;
1202 	    text = mapMsg.getString(MAPMSG_TEXT_PROPNAME);
1203 	} catch (Exception ex)  {
1204 	    System.err.println("Caught exception: " + ex);
1205 	}
1206 
1207 	return (text);
1208     }
1209 }
1210 
1211 class SimpleChatBytesMessageCreator implements
1212 			SimpleChatMessageCreator, SimpleChatMessageTypes  {
1213 
createChatMessage(Session session, String sender, int type, String text)1214     public Message createChatMessage(Session session, String sender,
1215 					int type, String text)  {
1216 	BytesMessage		bytesMsg = null;
1217 
1218         try  {
1219 	    byte	b[];
1220 
1221             bytesMsg = session.createBytesMessage();
1222 	    bytesMsg.writeInt(type);
1223 	    /*
1224 	     * Write length of sender and text strings
1225 	     */
1226 	    b = sender.getBytes();
1227 	    bytesMsg.writeInt(b.length);
1228 	    bytesMsg.writeBytes(b);
1229 
1230 	    if (text != null)  {
1231 	        b = text.getBytes();
1232 	        bytesMsg.writeInt(b.length);
1233 	        bytesMsg.writeBytes(b);
1234 	    } else  {
1235 	        bytesMsg.writeInt(0);
1236 	    }
1237         } catch (Exception ex)  {
1238 	    System.err.println("Caught exception while creating message: " + ex);
1239         }
1240 
1241 	return (bytesMsg);
1242     }
1243 
isUsable(Message msg)1244     public boolean isUsable(Message msg)  {
1245 	if (msg instanceof BytesMessage)  {
1246 	    return (true);
1247 	}
1248 
1249 	return (false);
1250     }
1251 
getChatMessageType(Message msg)1252     public int getChatMessageType(Message msg)  {
1253 	int	type = BADTYPE;
1254 
1255 	try  {
1256 	    BytesMessage	bytesMsg = (BytesMessage)msg;
1257 	    type = bytesMsg.readInt();
1258 	} catch (Exception ex)  {
1259 	    System.err.println("Caught exception: " + ex);
1260 	}
1261 
1262 	return (type);
1263     }
1264 
getChatMessageSender(Message msg)1265     public String getChatMessageSender(Message msg)  {
1266 	String	sender = null;
1267 
1268 	sender = readSizeFetchString(msg);
1269 
1270 	return (sender);
1271     }
1272 
getChatMessageText(Message msg)1273     public String getChatMessageText(Message msg)  {
1274 	String	text = null;
1275 
1276 	text = readSizeFetchString(msg);
1277 
1278 	return (text);
1279     }
1280 
readSizeFetchString(Message msg)1281     private String readSizeFetchString(Message msg)  {
1282 	String	stringData = null;
1283 
1284 	try  {
1285 	    BytesMessage	bytesMsg = (BytesMessage)msg;
1286 	    int			length, needToRead;
1287 	    byte		b[];
1288 
1289 	    length = bytesMsg.readInt();
1290 
1291 	    if (length == 0)  {
1292 		return ("");
1293 	    }
1294 
1295 	    b = new byte [length];
1296 
1297 	    /*
1298 	     * Loop to keep reading until all the bytes are read in
1299 	     */
1300 	    needToRead = length;
1301 	    while (needToRead > 0)  {
1302 	        byte tmpBuf[] = new byte [needToRead];
1303 	        int ret = bytesMsg.readBytes(tmpBuf);
1304 	        if (ret > 0)  {
1305 	            for (int i=0; i < ret; ++i)  {
1306 	                b[b.length - needToRead +i] = tmpBuf[i];
1307 	            }
1308 	            needToRead -= ret;
1309 	        }
1310 	    }
1311 
1312 	    stringData = new String(b);
1313 	} catch (Exception ex)  {
1314 	    System.err.println("Caught exception: " + ex);
1315 	}
1316 
1317 	return (stringData);
1318     }
1319 }
1320 
1321 class SimpleChatStreamMessageCreator implements
1322 			SimpleChatMessageCreator, SimpleChatMessageTypes  {
1323 
createChatMessage(Session session, String sender, int type, String text)1324     public Message createChatMessage(Session session, String sender,
1325 					int type, String text)  {
1326 	StreamMessage		streamMsg = null;
1327 
1328         try  {
1329 	    byte	b[];
1330 
1331             streamMsg = session.createStreamMessage();
1332 	    streamMsg.writeInt(type);
1333 	    streamMsg.writeString(sender);
1334 
1335 	    if (text == null)  {
1336 		text = "";
1337 	    }
1338 	    streamMsg.writeString(text);
1339         } catch (Exception ex)  {
1340 	    System.err.println("Caught exception while creating message: " + ex);
1341         }
1342 
1343 	return (streamMsg);
1344     }
1345 
isUsable(Message msg)1346     public boolean isUsable(Message msg)  {
1347 	if (msg instanceof StreamMessage)  {
1348 	    return (true);
1349 	}
1350 
1351 	return (false);
1352     }
1353 
getChatMessageType(Message msg)1354     public int getChatMessageType(Message msg)  {
1355 	int	type = BADTYPE;
1356 
1357 	try  {
1358 	    StreamMessage	streamMsg = (StreamMessage)msg;
1359 	    type = streamMsg.readInt();
1360 	} catch (Exception ex)  {
1361 	    System.err.println("getChatMessageType(): Caught exception: " + ex);
1362 	}
1363 
1364 	return (type);
1365     }
1366 
getChatMessageSender(Message msg)1367     public String getChatMessageSender(Message msg)  {
1368 	String	sender = null;
1369 
1370 	try  {
1371 	    StreamMessage	streamMsg = (StreamMessage)msg;
1372 	    sender = streamMsg.readString();
1373 	} catch (Exception ex)  {
1374 	    System.err.println("getChatMessageSender(): Caught exception: " + ex);
1375 	}
1376 
1377 	return (sender);
1378     }
1379 
getChatMessageText(Message msg)1380     public String getChatMessageText(Message msg)  {
1381 	String	text = null;
1382 
1383 	try  {
1384 	    StreamMessage	streamMsg = (StreamMessage)msg;
1385 	    text = streamMsg.readString();
1386 	} catch (Exception ex)  {
1387 	    System.err.println("getChatMessageText(): Caught exception: " + ex);
1388 	}
1389 
1390 	return (text);
1391     }
1392 
1393 }
1394 
1395 
1396 
1397 
1398 /**
1399  * Object representing a message sent by chat application.
1400  * We use this class and wrap a javax.jms.ObjectMessage
1401  * around it instead of using a javax.jms.TextMessage
1402  * because a simple string is not sufficient. We want
1403  * be able to to indicate that a message is one of these
1404  * types:
1405  *	join message	('Hi, I just joined')
1406  *	regular message	(For regular chat messages)
1407  *	leave message	('Bye, I'm leaving')
1408  *
1409  */
1410 class ChatObjMessage implements java.io.Serializable, SimpleChatMessageTypes  {
1411     private int		type = NORMAL;
1412     private String	sender,
1413 			message;
1414 
1415     /**
1416      * ChatObjMessage constructor. Construct a message with the given
1417      * sender and message.
1418      * @param sender Message sender
1419      * @param type Message type
1420      * @param message The message to send
1421      */
ChatObjMessage(String sender, int type, String message)1422     public ChatObjMessage(String sender, int type, String message)  {
1423 	this.sender = sender;
1424 	this.type = type;
1425 	this.message = message;
1426     }
1427 
1428     /**
1429      * Returns message sender.
1430      */
getSender()1431     public String getSender()  {
1432 	return (sender);
1433     }
1434 
1435     /**
1436      * Returns message type
1437      */
getType()1438     public int getType()  {
1439 	return (type);
1440     }
1441 
1442     /**
1443      * Sets the message string
1444      * @param message The message string
1445      */
setMessage(String message)1446     public void setMessage(String message)  {
1447 	this.message = message;
1448     }
1449     /**
1450      * Returns the message string
1451      */
getMessage()1452     public String getMessage()  {
1453 	return (message);
1454     }
1455 }
1456