1 /*------------------------------------------------------------------------------
2 Name: SimpleChat.java
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 ------------------------------------------------------------------------------*/
6 package javaclients.chat;
7
8 import org.xmlBlaster.util.FileLocator;
9 import org.xmlBlaster.util.Global;
10 import org.xmlBlaster.util.XmlBlasterException;
11 import org.xmlBlaster.util.dispatch.ConnectionStateEnum;
12 import org.xmlBlaster.util.MsgUnit;
13 import org.xmlBlaster.client.qos.ConnectQos;
14 import org.xmlBlaster.client.key.UpdateKey;
15 import org.xmlBlaster.client.qos.UpdateQos;
16 import org.xmlBlaster.client.key.GetKey;
17 import org.xmlBlaster.client.I_Callback;
18 import org.xmlBlaster.client.I_ConnectionStateListener;
19 import org.xmlBlaster.client.I_XmlBlasterAccess;
20
21 import java.util.logging.Logger;
22 import java.awt.event.*;
23 import java.awt.*;
24 import java.util.StringTokenizer;
25 import java.text.DateFormat;
26
27 /**
28 * This client is a simple chat application using xmlBlaster.
29 * <p>
30 * It demonstrates 'raw' Corba access.
31 * Usage:
32 * java javaclients.chat.SimpleChat -loginName "nickname"
33 * @author Mike Groezinger
34 */
35 public class SimpleChat extends Frame implements I_Callback, ActionListener, I_ConnectionStateListener {
36
37 private static final long serialVersionUID = 1L;
38 // XmlBlaster attributes
39 private final Global glob;
40 private static Logger log = Logger.getLogger(SimpleChat.class.getName());
41 private I_XmlBlasterAccess xmlBlasterConnection = null;
42 private static String qos = "<qos></qos>";
43 private String publishOid = "javaclients.chat.SimpleChat";
44 private String xmlKey = null;
45 private String logFileName = null;
46 private boolean withSound = true;
47
48 // UI elements
49 private Button connectButton, actionButton, whoisThereButton, soundButton;
50 private Panel fPanel;
51 private TextArea output;
52 private TextField input;
53 private Label label;
54
55 private java.lang.reflect.Method speakMethod = null;
56 private Object speaker = null;
57
58 public SimpleChat(Global glob){
59 super(glob.getProperty().get("loginName", "SimpleChat - <NoName>"));
60 this.glob = glob;
61
62
63 this.addWindowListener(
64 new WindowAdapter() {
65 public void windowClosing(WindowEvent event)
66 {
67 logout();
68 System.exit(0);
69 }
70 }
71 );
72
73 initUI();
74 pack();
75 logFileName = glob.getProperty().get("logFile", System.getProperty("user.home") + System.getProperty("file.separator") + "xmlBlasterChat.log");
76 log.info("Logging messages to " + logFileName);
77
78 //prepare the speach synthetizer ...
79 try {
80 Class speech = Class.forName("com.eclettic.speech.DefaultInputSpeaker");
81 java.lang.reflect.Constructor constr = speech.getConstructor((Class[])null);
82 this.speaker = constr.newInstance((Object[])null);
83 Class[] argClasses = new Class[1];
84 argClasses[0] = String.class;
85 this.speakMethod = speech.getMethod("speak", argClasses);
86 }
87 catch (Throwable ex) {
88 log.severe("Audio output of messages not activated, please use JDK 1.4 or better and add speech.jar to your classpath: " + ex.toString());
89 }
90
91 label.setText(logFileName);
92 readOldMessagesFromFile();
93 }
94
95
96 protected void publishMessage(String content) {
97 try {
98 xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
99 "<key oid='" + publishOid + "' contentMime='text/plain'>\n" +
100 "</key>";
101 MsgUnit msgUnit = new MsgUnit(xmlKey, content.getBytes(), "<qos></qos>");
102 log.fine("Publishing ...");
103 xmlBlasterConnection.publish(msgUnit);
104 } catch(XmlBlasterException e) {
105 log.warning("XmlBlasterException: " + e.getMessage());
106 }
107 log.fine("Publishing done");
108 }
109
110 protected void getUserList() {
111 if (xmlBlasterConnection == null) {
112 log.severe("Please log in first");
113 return;
114 }
115
116 publishMessage("I am retrieving the connected users list (ignore this)");
117 try {
118 GetKey getKeyWrapper = new GetKey(glob, "__sys__UserList");
119 MsgUnit[] msgUnit = xmlBlasterConnection.get(getKeyWrapper.toXml(),"<qos></qos>");
120 if (msgUnit != null) {
121 for (int i=0; i < msgUnit.length; i++) {
122 appendOutput("users: " + System.getProperty("line.separator") +
123 new String(msgUnit[i].getContent()) +
124 System.getProperty("line.separator"));
125 }
126 appendOutput("these where all users connected" +
127 System.getProperty("line.separator"));
128 }
129 }
130 catch (XmlBlasterException ex) {
131 log.severe("error when getting the list of users");
132 }
133 }
134
135 /** initialize UI */
136 public void initUI() {
137 // MAIN-Frame
138 this.setLayout(new BorderLayout());
139 fPanel = new Panel();
140 fPanel.setLayout(new BorderLayout());
141 this.add("North", fPanel);
142
143 // Button to connect to xmlBlaster
144 connectButton = new Button("Connect");
145 connectButton.setActionCommand("connect");
146 connectButton.addActionListener(this);
147 fPanel.add(connectButton, BorderLayout.WEST);
148
149
150 label = new Label("LOGGING");
151 add(label, BorderLayout.SOUTH);
152
153 // Button for sending message (Publish )
154 actionButton = new Button("Send");
155 actionButton.setActionCommand("send");
156 actionButton.addActionListener(this);
157 fPanel.add(actionButton, BorderLayout.EAST);
158
159 // Button for requesting list of who is connected
160 whoisThereButton = new Button("Who is There ?");
161 whoisThereButton.setActionCommand("whoisThere");
162 whoisThereButton.addActionListener(this);
163 fPanel.add(whoisThereButton, BorderLayout.SOUTH);
164
165
166
167
168 // Button for requesting list of who is connected
169 String soundText = "with Sound";
170 if (!this.withSound) soundText = "no Sound";
171 soundButton = new Button(soundText);
172 soundButton.setActionCommand("sound");
173 soundButton.addActionListener(this);
174 fPanel.add(soundButton, BorderLayout.NORTH);
175
176 // Textfield for input
177 input = new TextField(60);
178 input.addActionListener(this);
179 fPanel.add(input, BorderLayout.CENTER);
180
181 // Textfield for output (which comes from xmlBlaster callback)
182 output = new TextArea("",12,80);
183 output.setEditable(false);
184 // add("South",output);
185 add("Center",output);
186 }
187
188 // event-handler
189 public void actionPerformed(ActionEvent ev) {
190 String command = ev.getActionCommand();
191 //Object obj = ev.getSource();
192
193 if ("whoisThere".equals(command)) {
194 getUserList();
195 return;
196 }
197
198 if ("sound".equals(command)) {
199 if (this.withSound) {
200 this.withSound = false;
201 this.soundButton.setLabel("no Sound");
202 fPanel.repaint();
203
204 }
205 else {
206 this.withSound = true;
207 this.soundButton.setLabel("with Sound");
208 fPanel.repaint();
209 }
210 }
211
212 if(command.equals("connect")){
213 // Connect to xmlBlaster server
214 if((connectButton.getLabel()).equals("Connect")){
215 initBlaster();
216 connectButton.setLabel("Logout");
217 }
218 //logout from server
219 else if((connectButton.getLabel()).equals("Logout")){
220 logout();
221 connectButton.setLabel("Connect");
222 }
223 }
224 // publish new message
225 else if( command.equals("send") ||
226 ( (ev.getSource()) instanceof TextField )){
227
228 if (xmlBlasterConnection == null) {
229 log.severe("Please log in first");
230 return;
231 }
232
233 //----------- Construct a message and publish it ---------
234 String content = input.getText();
235
236 publishMessage(content);
237 input.setText("");
238 }
239 }
240
241 /** adds text to output-field */
242 public void appendOutput(String text){
243 output.append(text);
244 // output.insert(text, 0);
245
246 try { FileLocator.appendToFile(logFileName, text); } catch(XmlBlasterException e) { log.warning("Can't log message:" + e.toString()); }
247 //output.repaint();
248 this.repaint();
249 }
250
251 /**
252 * This is the callback method invoked from xmlBlaster
253 * delivering us a new asynchronous message.
254 * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
255 */
256 public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
257 {
258 String msgContent = new String(content);
259
260 if (this.withSound) {
261 java.awt.Toolkit.getDefaultToolkit().beep();
262
263 if ((this.speakMethod != null) && (this.speaker !=null)) {
264 try {
265 Object[] args = new Object[1];
266 args[0] = msgContent;
267 this.speakMethod.invoke(this.speaker, args);
268 }
269 catch (Throwable ex){
270 log.severe("Audio output of messages not activated, please use JDK 1.4 or better and add speech.jar to your classpath: " + ex.toString());
271 }
272 }
273 toFront();
274 }
275
276
277 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
278 String text = df.format(new java.util.Date());
279 text += "[" + updateQos.getSender() +"]: ";
280 text += msgContent;
281 appendOutput(text +System.getProperty("line.separator"));
282 log.info("CallBack\n");
283
284 return "";
285 }
286
287 /** find xmlBlaster server, login and subscribe */
288 public void initBlaster(){
289 try {
290 xmlBlasterConnection = glob.getXmlBlasterAccess();
291 ConnectQos qos = new ConnectQos(glob);
292 xmlBlasterConnection.connect(qos, this);
293 xmlBlasterConnection.registerConnectionListener(this); // configure settings on command line or in xmlBlaster.properties
294 }
295 catch (Exception e) {
296 log.severe(e.toString());
297 e.printStackTrace();
298 }
299 subscription();
300 }
301
302 private void readOldMessagesFromFile()
303 {
304 // Read old messages from log file ...
305 try {
306 String data = FileLocator.readAsciiFile(logFileName);
307 StringTokenizer st = new StringTokenizer(data, "\n");
308 while (st.hasMoreTokens()) {
309 String tmp = st.nextToken();
310 output.append(tmp+System.getProperty("line.separator"));
311 }
312 } catch (XmlBlasterException e) {
313 log.warning("Can't read old logs from " + logFileName + ": " + e.toString());
314 }
315 }
316
317 /** subscribe to messages */
318 public void subscription() {
319 try {
320 //----------- Subscribe to OID -------
321 log.fine("Subscribing using the exact oid ...");
322 String xmlKeyPub = "<key oid='" + publishOid + "' queryType='EXACT'>\n" +
323 "</key>";
324 xmlBlasterConnection.subscribe(xmlKeyPub, "<qos></qos>");
325 log.fine("Subscribed to '" + publishOid + "' ...");
326 } catch(XmlBlasterException e) {
327 log.warning("XmlBlasterException: " + e.getMessage());
328 }
329 }
330
331 /** unsubsrcibe and logout from xmlBlaster */
332 public void logout(){
333 if (xmlBlasterConnection == null) return;
334 //----------- Unsubscribe from the previous message --------
335 if (xmlKey != null) {
336 log.fine("Unsubscribe ...");
337 try {
338 xmlBlasterConnection.unSubscribe(xmlKey, qos);
339 } catch(XmlBlasterException e) {
340 log.warning("XmlBlasterException: " + e.getMessage());
341 }
342 log.info("Unsubscribe done");
343 }
344
345 //----------- Logout --------------------------------------
346 log.fine("Logout ...");
347 xmlBlasterConnection.disconnect(null);
348 }
349
350 private static void usage(Global glob) {
351 System.out.println(glob.usage());
352 System.err.println("Example: java javaclients.chat.SimpleChat -loginName Heidi");
353 System.exit(1);
354 }
355
356 /**
357 * This is the callback method invoked from I_XmlBlasterAccess
358 * informing the client in an asynchronous mode if the connection was established.
359 * @see I_ConnectionStateListener
360 */
361 public void reachedAlive(ConnectionStateEnum oldState, I_XmlBlasterAccess connection)
362 {
363 subscription();
364 if (connection.getQueue().getNumOfEntries() > 0) {
365 log.info("We were lucky, reconnected to xmlBlaster, sending backup " +
366 connection.getQueue().getNumOfEntries() + " messages ...");
367 }
368 else
369 log.info("We were lucky, reconnected to xmlBlaster, no backup messages to flush");
370 }
371 public void reachedAliveSync(ConnectionStateEnum oldState, I_XmlBlasterAccess connection) {
372 }
373
374
375 /**
376 * This is the callback method invoked from I_XmlBlasterAccess
377 * informing the client in an asynchronous mode if the connection was lost.
378 * @see I_ConnectionStateListener
379 */
380 public void reachedPolling(ConnectionStateEnum oldState, I_XmlBlasterAccess connection)
381 {
382 log.warning("I_ConnectionStateListener: Lost connection to xmlBlaster");
383 }
384
385 /**
386 * @see I_ConnectionStateListener
387 */
388 public void reachedDead(ConnectionStateEnum oldState, I_XmlBlasterAccess connection)
389 {
390 log.warning("I_ConnectionStateListener: DEAD - Lost connection to xmlBlaster, giving up.");
391 }
392
393 public static void main(String args[]) {
394 Global glob = new Global();
395 if (glob.init(args) != 0) {
396 usage(glob);
397 System.exit(1);
398 }
399
400 SimpleChat chat = new SimpleChat(glob);
401 chat.setSize(460,350);
402 chat.show();
403 }
404 }
syntax highlighted by Code2HTML, v. 0.9.1