1 4 package demo.chatter; 5 6 import java.awt.BorderLayout ; 7 import java.awt.Color ; 8 import java.awt.Container ; 9 import java.awt.Dimension ; 10 import java.awt.Font ; 11 import java.awt.event.ActionEvent ; 12 import java.awt.event.ActionListener ; 13 import java.awt.event.WindowEvent ; 14 import java.awt.event.WindowListener ; 15 import java.util.Random ; 16 17 import javax.management.MBeanServer ; 18 import javax.management.MBeanServerFactory ; 19 import javax.management.MBeanServerNotification ; 20 import javax.management.Notification ; 21 import javax.management.NotificationFilter ; 22 import javax.management.NotificationListener ; 23 import javax.management.ObjectName ; 24 import javax.swing.DefaultListModel ; 25 import javax.swing.ImageIcon ; 26 import javax.swing.JFrame ; 27 import javax.swing.JLabel ; 28 import javax.swing.JList ; 29 import javax.swing.JPanel ; 30 import javax.swing.JScrollPane ; 31 import javax.swing.JTextField ; 32 import javax.swing.JTextPane ; 33 import javax.swing.text.Document ; 34 import javax.swing.text.Style ; 35 import javax.swing.text.StyleConstants ; 36 37 42 public class Main extends JFrame implements ActionListener , ChatterDisplay, 43 WindowListener { 44 45 private final ChatManager chatManager = new ChatManager(); 46 47 private final JTextPane display = new JTextPane (); 48 49 private User user; 50 51 private final JList buddyList = new JList (); 52 53 private boolean isServerDown = false; 54 private static final String CHATTER_SYSTEM = "SYSTEM"; 55 56 public Main() { 57 try { 58 final String nodeId = registerForNotifications(); 59 user = new User(nodeId, this); 60 populateCurrentUsers(); 61 login(); 62 } 63 catch (final Exception e) { 64 throw new RuntimeException (e); 65 } 66 67 addWindowListener(this); 68 setDefaultLookAndFeelDecorated(true); 69 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 70 final Container content = getContentPane(); 71 72 display.setFont(new Font ("Andale Mono", Font.PLAIN, 9)); 73 display.setEditable(false); 74 display.setRequestFocusEnabled(false); 75 76 final JTextField input = new JTextField (); 77 input.setFont(new Font ("Andale Mono", Font.PLAIN, 9)); 78 input.addActionListener(this); 79 final JScrollPane scroll = new JScrollPane (display); 80 final Random r = new Random (); 81 final JLabel avatar = new JLabel (user.getName() + " (node id: " 82 + user.getNodeId() + ")", new ImageIcon (getClass().getResource( 83 "/images/buddy" + r.nextInt(10) + ".gif")), JLabel.LEFT); 84 avatar.setForeground(Color.WHITE); 85 avatar.setFont(new Font ("Georgia", Font.PLAIN, 16)); 86 avatar.setVerticalTextPosition(JLabel.CENTER); 87 final JPanel buddypanel = new JPanel (); 88 buddypanel.setBackground(Color.DARK_GRAY); 89 buddypanel.setLayout(new BorderLayout ()); 90 buddypanel.add(avatar, BorderLayout.CENTER); 91 92 final JPanel buddyListPanel = new JPanel (); 93 buddyListPanel.setBackground(Color.WHITE); 94 buddyListPanel.add(buddyList); 95 buddyList.setFont(new Font ("Andale Mono", Font.BOLD, 9)); 96 97 content.setLayout(new BorderLayout ()); 98 content.add(buddypanel, BorderLayout.NORTH); 99 content.add(scroll, BorderLayout.CENTER); 100 content.add(input, BorderLayout.SOUTH); 101 content.add(new JScrollPane (buddyListPanel), BorderLayout.EAST); 102 pack(); 103 104 setTitle("Chatter: " + user.getName()); 105 setSize(new Dimension (600, 400)); 106 setVisible(true); 107 input.requestFocus(); 108 } 109 110 public void actionPerformed(final ActionEvent e) { 111 final JTextField input = (JTextField ) e.getSource(); 112 final String message = input.getText(); 113 input.setText(""); 114 ( 115 new Thread () { 116 public void run() { 117 chatManager.send(user, message); 118 } 119 }).start(); 120 121 if (isServerDown) { 122 updateMessage(user.getName(), message, true); 123 } 124 } 125 126 public void handleConnectedServer() { 127 isServerDown = false; 128 javax.swing.SwingUtilities.invokeLater( 129 new Runnable () { 130 public void run() { 131 Main.this.buddyList.setVisible(true); 132 Main.this.buddyList.setEnabled(true); 133 } 134 }); 135 } 136 137 public void handleDisconnectedServer() { 138 isServerDown = true; 139 updateMessage("The server is down; all of your messages will be queued until the server goes back up again."); 140 javax.swing.SwingUtilities.invokeLater( 141 new Runnable () { 142 public void run() { 143 Main.this.buddyList.setVisible(false); 144 Main.this.buddyList.setEnabled(false); 145 } 146 }); 147 } 148 149 public synchronized void handleDisconnectedUser(final String nodeId) { 150 chatManager.removeUser(nodeId); 151 populateCurrentUsers(); 152 } 153 154 public synchronized void handleNewUser(final String username) { 155 populateCurrentUsers(); 156 } 157 158 public void updateMessage(final String username, final String message, 159 final boolean isOwnMessage) { 160 javax.swing.SwingUtilities.invokeLater( 161 new Runnable () { 162 public void run() { 163 try { 164 final Document doc = display.getDocument(); 165 final Style style = display.addStyle("Style", null); 166 167 if (isOwnMessage) { 168 StyleConstants.setItalic(style, true); 169 StyleConstants.setForeground(style, Color.LIGHT_GRAY); 170 StyleConstants.setFontSize(style, 9); 171 } 172 173 if (username.equals(CHATTER_SYSTEM)) { 174 StyleConstants.setItalic(style, true); 175 StyleConstants.setForeground(style, Color.RED); 176 } 177 else { 178 StyleConstants.setBold(style, true); 179 doc.insertString(doc.getLength(), username + ": ", 180 style); 181 } 182 183 StyleConstants.setBold(style, false); 184 doc.insertString(doc.getLength(), message, style); 185 doc.insertString(doc.getLength(), "\n", style); 186 187 display.setCaretPosition(doc.getLength()); 188 } 189 catch (final javax.swing.text.BadLocationException ble) { 190 System.err.println(ble.getMessage()); 191 } 192 } 193 }); 194 } 195 196 public void windowClosing(WindowEvent e) { 197 handleDisconnectedUser(user.getNodeId()); 198 } 199 200 public void windowActivated(WindowEvent e) { 201 } 203 204 public void windowClosed(WindowEvent e) { 205 } 207 208 public void windowDeactivated(WindowEvent e) { 209 } 211 212 public void windowDeiconified(WindowEvent e) { 213 } 215 216 public void windowIconified(WindowEvent e) { 217 } 219 220 public void windowOpened(WindowEvent e) { 221 } 223 224 void login() { 225 synchronized (chatManager) { 236 chatManager.registerUser(user); 237 } 238 } 239 240 private synchronized void populateCurrentUsers() { 241 DefaultListModel list = new DefaultListModel (); 242 final Object [] currentUsers = chatManager.getCurrentUsers(); 243 for (int i = 0; i < currentUsers.length; i++) { 244 list.addElement(new String (((User) currentUsers[i]) 245 .getName())); 246 } 247 buddyList.setModel(list); 248 } 249 250 private void updateMessage(final String message) { 251 updateMessage(CHATTER_SYSTEM, message, true); 252 } 253 254 261 private String registerForNotifications() throws Exception { 262 final java.util.List servers = MBeanServerFactory.findMBeanServer(null); 263 if (servers.size() == 0) { 264 265 System.err.println("WARNING: No JMX servers found, unable to register for notifications."); 266 return "0"; 267 } 268 269 final MBeanServer server = (MBeanServer ) servers.get(0); 270 final ObjectName clusterBean = new ObjectName ( 271 "org.terracotta:type=Terracotta Cluster,name=Terracotta Cluster Bean"); 272 final ObjectName delegateName = 273 ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate"); 274 final java.util.List clusterBeanBag = new java.util.ArrayList (); 275 276 final NotificationListener listener0 = 278 new NotificationListener () { 279 public void handleNotification(Notification notification, 280 Object handback) { 281 synchronized (clusterBeanBag) { 282 clusterBeanBag.add(handback); 283 clusterBeanBag.notifyAll(); 284 } 285 } 286 }; 287 288 final NotificationFilter filter0 = 290 new NotificationFilter () { 291 public boolean isNotificationEnabled(Notification notification) { 292 if (notification.getType().equals("JMX.mbean.registered") 293 && ((MBeanServerNotification ) notification) 294 .getMBeanName().equals(clusterBean)) { 295 return true; 296 } 297 return false; 298 } 299 }; 300 301 server.addNotificationListener(delegateName, listener0, filter0, 303 clusterBean); 304 305 final java.util.Set allObjectNames = server.queryNames(null, null); 308 309 if (!allObjectNames.contains(clusterBean)) { 310 synchronized (clusterBeanBag) { 311 while (clusterBeanBag.isEmpty()) { 312 clusterBeanBag.wait(); 313 } 314 } 315 } 316 317 server.removeNotificationListener(delegateName, listener0); 319 320 final NotificationListener listener1 = 322 new NotificationListener () { 323 public void handleNotification(Notification notification, 324 Object handback) { 325 String nodeId = notification.getMessage(); 326 if (notification.getType().endsWith("thisNodeConnected")) { 327 handleConnectedServer(); 328 } 329 if (notification.getType().endsWith("thisNodeDisconnected")) { 330 handleDisconnectedServer(); 331 } 332 else if (notification.getType().endsWith("nodeDisconnected")) { 333 handleDisconnectedUser(nodeId); 334 } 335 } 336 }; 337 338 server.addNotificationListener(clusterBean, listener1, null, 340 clusterBean); 341 return (server.getAttribute(clusterBean, "NodeId")).toString(); 342 } 343 344 public static void main(final String [] args) { 345 javax.swing.SwingUtilities.invokeLater( 346 new Runnable () { 347 public void run() { 348 new Main(); 349 } 350 }); 351 } 352 } 353 | Popular Tags |