Source code: org/zazof/jteg/MessageManager.java
1 package org.zazof.jteg;
2
3 import org.zazof.jteg.gui.ChatPanel;
4 import java.util.Vector;
5 import java.util.Enumeration;
6 import java.util.StringTokenizer;
7 import java.io.IOException;
8
9 /**
10 * This class is responsible for:
11 * <ul>
12 * <li>Processing incoming messages from the server in a protocolindependent way
13 * <li>Converting information from this application to the string that is accurate for the active protocol
14 * <li>Managing the listeners that are interested in one or more messages coming from the server
15 * </ul>
16 * Ideally, only this class should have contact with the TEGServer
17 * <br>
18 * Implements the Singleton pattern.
19 *
20 * @author Yves Vandewoude (stcham)
21 * @author Jef De Geeter (zazof)
22 * @date December 2001
23 */
24
25
26 public class MessageManager implements Runnable{
27
28 private MessageManager(){
29 }
30
31 public static MessageManager getInstance(){
32 if (instance == null) instance = new MessageManager();
33 return instance;
34 }
35
36 public void startThread(){
37 $currentThread = new Thread(this);
38 $isRunning = true;
39 $currentThread.start();
40 }
41
42 // this thread polls the TEGServer for new messages.
43 public void run(){
44 String newMessage;
45 Message m;
46 while ($isRunning){
47 try{
48
49 newMessage = $server.getMessageFromServer();
50 // select the submessages from new_message, each submessage is separated by ";"
51 if (newMessage != null)
52 {
53 StringTokenizer st = new StringTokenizer(newMessage, ";");
54 while(st.hasMoreTokens()){
55 try
56 {
57 m = decodeMessage(st.nextToken());
58 notifyAllListeners(m);
59 }
60 catch (UnknownMessageException exc){
61 System.out.println(exc.getMessage());
62 }
63 }
64 }
65 }
66 catch (IOException exc){
67 exc.printStackTrace();
68 }
69 catch (ServerException se){
70 if (DEBUG) System.out.println("ServerException received with message: " + se.getMessage());
71 $isRunning = false;
72 }
73 }
74 }
75
76 public void addMessageListener(MessageListener ml){
77 if (DEBUG) System.out.println("Added message listener: " + ml.toString());
78 listeners.add(ml);
79 }
80
81 public void removeMessageListener(MessageListener ml){
82 listeners.remove(ml);
83 }
84
85 public void notifyAllListeners(Message m){
86 Enumeration enumm = listeners.elements();
87 while (enumm.hasMoreElements()){
88 ((MessageListener) enumm.nextElement()).messageArrived(m);
89 }
90 }
91
92 /**
93 * Makes the actual connection with server on the specified port. Before sending any message
94 * to the TEG server, this method should be called.
95 */
96
97 public void makeConnectionWithServer(String server, int port)
98 throws IOException, ServerException
99 {
100 $server.makeConnectionWithServer(server, port);
101 init();
102 $connected = true;
103 $isRunning = true;
104 }
105
106 /**
107 * Disconnect from the server, if we are connected. Otherwise, nothing happens.
108 *
109 */
110 public void disconnect()
111 {
112 if ($connected)
113 {
114 $isRunning = false;
115 $connected = false;
116 $server.disconnect();
117 }
118 }
119
120
121 /**
122 *
123 * This method will build the correct messagestring to the server based on the 'parts'
124 * that are supplied as a parameter in a StringArray. It will then send this message
125 * to the server.
126 *
127 * @param messageParts A StringArray that contains the different parts required to build the message. The first item (messageParts[0]) must contain the messagetype.
128 *
129 * @exception UnknownMessageException If no valid message can be constructed from the messageparts using the active protocol
130 * @exception ServerException If a problem occurs while sending the message to the server
131 *
132 */
133
134 public void sendToServer(String[] messageParts)
135 throws UnknownMessageException, ServerException
136 {
137 if (!($connected)) init();
138 String messageToSend = $entryPoint.constructMessageString(messageParts);
139 $server.send(messageToSend, "Problem with message constructed from: " + messageParts[0]);
140 }
141
142
143 /**
144 *
145 * This method will broadcast a specific message to all those interested in an InformationMessage
146 * This method may be used for reducing coupling between domain & GUI layer.
147 *
148 * @param messageParts A StringArray that contains the different parts required to build the message. The first item (messageParts[0]) must contain the messagetype, which is usually 'internalinfo' in the case of an internal BroadCast.
149 *
150 * @exception UnknownMessageException If no valid message can be constructed from the messageparts using the active protocol
151 *
152 */
153
154 public void broadCastInternalMessage(String[] messageParts)
155 throws UnknownMessageException
156 {
157 // Since we are not necessarily connected, we can not use the MessageChain in all cases.
158 if ($connected)
159 {
160 if (DEBUG) System.out.println("We are connected, and use the MessageChain for internal broadcast!");
161 Message informationMessage = $entryPoint.decodeMessage($entryPoint.constructMessageString(messageParts));
162 notifyAllListeners(informationMessage);
163 }
164 else
165 {
166 if (DEBUG) System.out.println("We are not yet connected! We create a Informationmessage ourselves...");
167 Message someInformationMessage = new InformationMessage(null);
168 if (DEBUG) System.out.println("Informationmessage created");
169 String messageString = someInformationMessage.constructMessageString(messageParts);
170 if (DEBUG) System.out.println("MessageString created: " + messageString);
171 Message result = someInformationMessage.decodeMessage(messageString);
172 if (DEBUG) System.out.println("Result achieved");
173 notifyAllListeners(result);
174 if (DEBUG) System.out.println("Listeners notified with a message with name: "+ result.getMessageName());
175 }
176 }
177
178 /**
179 *
180 * This method will ask the playerstatus to the server.
181 *
182 * @exception ServerException If a problem occurs while sending the message to the server
183 */
184 public void askPlayerStatus()
185 throws ServerException
186 {
187 try
188 {
189 String[] playerStatus = {"playerstatus"};
190 sendToServer(playerStatus);
191 }
192 catch (UnknownMessageException exc)
193 {
194 // Should normally not happen
195 System.out.println("Ooooops... problem. We received an UnknownMessageException when asking for the playerstatus!");
196 exc.printStackTrace();
197 }
198 }
199
200 // ******************************************************************************
201 // Private methods or instantiationvariables of the MessageManagerClass
202 // ******************************************************************************
203
204 private Message decodeMessage(String message) throws UnknownMessageException{
205 return $entryPoint.decodeMessage(message);
206 }
207
208 private void init()
209 {
210 try
211 {
212 $builder = MessageChainBuilder.builderFactory($server.getProtocolVersion());
213 $entryPoint = $builder.returnEntryPoint();
214
215 }
216 catch (Exception e)
217 {
218 System.out.println("Exception thrown: " + e.getMessage());
219 e.printStackTrace();
220 }
221 }
222
223 private Vector listeners = new Vector(5);
224 private static MessageManager instance;
225 private Thread $currentThread;
226 private boolean $isRunning;
227 private boolean $connected = false;
228 private Message $entryPoint;
229 private MessageChainBuilder $builder;
230 private static boolean DEBUG = false;
231 private TEGServer $server = new TEGServer();
232 }
233