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