4 * Copyright 2015 TJ <hacker@iam.tj>.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 package uk.ac.ntu.n0521366.wsyd.management;
26 import java.io.FileWriter;
27 import java.io.BufferedWriter;
29 import javax.swing.ImageIcon;
30 import java.awt.Desktop;
32 import java.net.InetAddress;
33 import java.io.IOException;
34 import java.awt.event.ActionEvent;
35 import java.awt.event.ActionListener;
36 import java.net.DatagramPacket;
37 import java.net.DatagramSocket;
38 import java.net.InetSocketAddress;
39 import javax.swing.Timer;
40 import javax.swing.table.DefaultTableModel;
41 import java.net.UnknownHostException;
42 import java.util.logging.Logger;
43 import java.util.logging.Level;
44 import java.util.logging.LogRecord;
45 import java.util.logging.Filter;
46 import java.util.Date;
47 import java.text.SimpleDateFormat;
48 import java.text.MessageFormat;
49 import java.util.ArrayList;
50 import uk.ac.ntu.n0521366.wsyd.libs.logging.TableModelHandler;
51 import uk.ac.ntu.n0521366.wsyd.libs.message.MessageLogRecord;
52 import uk.ac.ntu.n0521366.wsyd.libs.message.MessagePresence;
53 import uk.ac.ntu.n0521366.wsyd.libs.message.MessageServerControl;
54 import uk.ac.ntu.n0521366.wsyd.libs.net.WSYD_SocketAddress.Protocol;
55 import uk.ac.ntu.n0521366.wsyd.libs.net.*;
56 import uk.ac.ntu.n0521366.wsyd.libs.net.ServiceAddressMap.LastSeenHost;
59 * @author TJ <hacker@iam.tj>
61 public class ServerManagement extends javax.swing.JFrame implements NetworkMessageEventListener, Filter {
68 * Location of resource bundles, images, icons
70 private static final String resourcePath = "/uk/ac/ntu/n0521366/wsyd/resources";
73 * Readable/displayable name of this application
75 final String _title = "ServerManagement";
78 * Network services to address map.
80 ServiceAddressMap _serviceToAddressMap;
83 * The UDP listener address for incoming log messages
85 WSYD_SocketAddress _udpLogServiceSA = null;
88 * UDP multi-cast presence advertiser
90 WSYD_SocketAddress _multicastAdvertiserSA = null;
93 * Log service running in a SwingWorker thread.
95 NetworkServerUDP _udpLogService = null;
98 * Multi-cast neighbour advertise and discover service in a SwingWorker thread.
100 NetworkServerUDPMulticast _multicastServer = null;
102 boolean _multicastAnnouncements = false;
105 * Enable or suspend logging
107 private boolean _doLogging;
110 * Enable or suspend table auto-scroll
112 private boolean _autoScroll;
115 * Regular presence announcements
121 * Instantiating code <em>must</em> also call initListeners()
123 * @see #initListeners()
125 public ServerManagement() {
126 if (LOGGER == null) // single instance of the Logger shared by all class objects
127 LOGGER = Logger.getLogger(_title);
128 LOGGER.setLevel(Level.ALL);
129 _serviceToAddressMap = new ServiceAddressMap(_title, LOGGER);
133 setLocationRelativeTo(null); // center on screen
134 // XXX: workaround for bug in NetBeans that doesn't set the displayed background colour, only the component colour, from the Properties editor
135 gDialogAbout.getContentPane().setBackground(gDialogAbout.getBackground());
139 * Creates new Server Management GUI that also announces itself using Multicast Neighbour discovery.
140 * @param multicastAnnouncements true if it should announce itself
141 * @param serverSocial IP address of ServerSocial - if non-null prevents ServerSocial map entry being treated as stale
143 public ServerManagement(boolean multicastAnnouncements, InetAddress serverSocial) {
145 this._multicastAnnouncements = multicastAnnouncements;
146 gMenuLogServiceAnnounce.setSelected(_multicastAnnouncements);
147 // TODO: implement constructor setting IP address of SocialServer from command-line value
150 * Initialise listeners and other objects that require a reference to 'this'.
152 * Passing 'this' from within the constructor is unsafe since the object is not
153 * fully constructed, so do it here. The compiler and virtual machine are free to move 'final'
154 * properties outside the constructor which means they may not be correctly
155 * initialised before the constructor returns. This is especially problematic
156 * in multi-threading applications.
158 * @return a reference to 'this' so method calls can be chained (e.g. new ServerManagement().initListeners().setVisible(true) )
159 * @throws UnknownHostException
161 public ServerManagement initListeners() throws UnknownHostException {
162 LOGGER.addHandler(new TableModelHandler(this)); // send messages to the GUI log table
163 LOGGER.setUseParentHandlers(false); // don't send messages to the default error stream logger of the parent
164 LOGGER.log(Level.INFO, "Server Management starting");
166 _udpLogServiceSA = new WSYD_SocketAddress(Network.PORTS_SERVER_LOG, Protocol.UDP);
167 _udpLogService = new NetworkServerUDP(_udpLogServiceSA, _title + "Log", _serviceToAddressMap, LOGGER);
168 _udpLogService.addNetworkMessageEventListener(this, "Log");
169 _udpLogService.setSimulate(false);
170 _udpLogService.execute();
172 _multicastAdvertiserSA = new WSYD_SocketAddress(Network.MULTICAST_IP, Network.PORTS_MULTICAST_DISCOVERY, Protocol.UDP);
173 _multicastServer = new NetworkServerUDPMulticast(_multicastAdvertiserSA, _title + "MC", _serviceToAddressMap, LOGGER);
174 _multicastServer.addNetworkMessageEventListener(this, "Neighbour");
175 _multicastServer.execute();
176 // permit broadcasting to pseudo-host 'all' since this is multicast
177 _serviceToAddressMap.put("all", new LastSeenHost(new InetSocketAddress(Network.MULTICAST_IP, Network.PORTS_MULTICAST_DISCOVERY), LastSeenHost.STATE.STATIC));
179 ActionListener regularTasksActionListener = new ActionListener() {
180 // provide a way to read the current version of the parent process object's fields
181 ServerManagement owner;
183 // XXX: Anonymous class initialisation - effectively used as the body of the object's constructor
185 // XXX: access to the outer class's instance object
186 owner = ServerManagement.this;
190 * Activated by timer events to send multi-cast neighbour
191 * announcements for the Log Service.
196 public void actionPerformed(ActionEvent e) {
197 String serviceName = "LogService";
198 // check the current value ofthe parent process' flag
199 if (owner._multicastAnnouncements) {
200 // Create local log report first
201 LogRecord record = new LogRecord(Level.FINEST, "Multicast: Announcing Presence");
202 record.setSourceClassName(serviceName);
203 record.setMillis(System.currentTimeMillis());
206 // Announce the log service
207 MessagePresence mp = new MessagePresence(_title + serviceName, _udpLogService.getSocketAddress());
208 NetworkMessage nm = NetworkMessage.createNetworkMessage("Neighbour", "all", mp);
209 nm.setSender(_title + serviceName);
210 _multicastServer.queueMessage(nm);
212 // clean up the known hosts map
213 ArrayList<String> servicesRemoved = _serviceToAddressMap.cleanServiceAddressMap(5000);
214 // keep Server menu up-to-date
215 for (String service : servicesRemoved) {
218 gMenuServerSocial.setEnabled(false);
221 gMenuServerChat.setEnabled(false);
228 regularTasks = new Timer(1000, regularTasksActionListener);
229 regularTasks.setInitialDelay(100);
230 regularTasks.start();
236 * Add a log record to the log table if logging is enabled.
238 * Abusing an already-existing logging interface. This method isn't filtering, it is called by
239 * the Logger's TableModelHandler to publish records.
241 * @see TableModelHandler
243 * @return true if logging is enabled
246 public boolean isLoggable(LogRecord record) {
248 if (record != null) {
249 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
250 // add the log record to the log table
251 ((DefaultTableModel)gLogTable.getModel()).addRow(
253 df.format(new Date(record.getMillis())),
254 record.getLevel().toString(),
255 record.getSourceClassName(),
259 if (_autoScroll) { // keep last record added in the view
260 int row = gLogTable.getModel().getRowCount();
261 gLogTable.scrollRectToVisible(gLogTable.getCellRect(row, 0, true));
268 protected boolean UDPSend(NetworkMessage message) {
269 boolean result = false;
271 if (message != null) {
272 InetSocketAddress address = this._serviceToAddressMap.getServiceAddress(message.getTarget());
273 if (address != null) {
274 message.setSender("ServerManagement");
276 byte[] dataSend = NetworkMessage.serialize(message);
277 DatagramPacket packetSend = new DatagramPacket(dataSend, dataSend.length);
278 // set target's remote host address and port
279 packetSend.setAddress(address.getAddress());
280 packetSend.setPort(address.getPort());
282 DatagramSocket socket = new DatagramSocket();
283 // acknowledge receipt
284 socket.send(packetSend);
285 LOGGER.logp(Level.FINEST, _title, null, MessageFormat.format("Sending packet for {0} to {1} ({3}:{4,number,integer}) from {2}", message.getIntent(), message.getTarget(), message.getSender(), packetSend.getAddress().getHostAddress(), packetSend.getPort()));
287 result = true; // successful
288 } catch (IOException e) {
289 // TODO: serverSend() add IOException handler
298 * This method is called from within the constructor to initialize the form.
299 * WARNING: Do NOT modify this code. The content of this method is always
300 * regenerated by the Form Editor.
302 @SuppressWarnings("unchecked")
303 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
304 private void initComponents() {
306 buttonGroup1 = new javax.swing.ButtonGroup();
307 gDialogAbout = new javax.swing.JDialog();
308 gTextAreaAbout = new javax.swing.JTextArea();
309 gBtnAbout = new javax.swing.JButton();
310 gFileChooser = new javax.swing.JFileChooser();
311 gLogScroller = new javax.swing.JScrollPane();
312 gLogTable = new javax.swing.JTable();
313 gMenuBar = new javax.swing.JMenuBar();
314 gMenuFile = new javax.swing.JMenu();
315 gMenuFileSave = new javax.swing.JMenuItem();
316 gMenuLog = new javax.swing.JMenu();
317 gMenuLogClear = new javax.swing.JMenuItem();
318 gMenuLogControl = new javax.swing.JCheckBoxMenuItem();
319 gMenuLogAutoScroll = new javax.swing.JCheckBoxMenuItem();
320 gMenuLogServiceAnnounce = new javax.swing.JCheckBoxMenuItem();
321 gMenuServers = new javax.swing.JMenu();
322 gMenuServerSocial = new javax.swing.JMenu();
323 gMenuServerSocialRestart = new javax.swing.JMenuItem();
324 gMenuServerSocialStop = new javax.swing.JMenuItem();
325 gMenuServerChat = new javax.swing.JMenu();
326 gMenuServerChatRestart = new javax.swing.JMenuItem();
327 gMenuServerChatStop = new javax.swing.JMenuItem();
328 gMenuHelp = new javax.swing.JMenu();
329 gMenuHelpAbout = new javax.swing.JMenuItem();
331 gDialogAbout.setTitle("About");
332 gDialogAbout.setBackground(new java.awt.Color(255, 255, 255));
333 gDialogAbout.setIconImage(new ImageIcon( getClass().getResource(resourcePath +"/ScroogledKeepCalmMug.icon.png")).getImage());
334 gDialogAbout.setMinimumSize(new java.awt.Dimension(590, 340));
335 gDialogAbout.setResizable(false);
336 gDialogAbout.getContentPane().setLayout(null);
338 gTextAreaAbout.setEditable(false);
339 gTextAreaAbout.setColumns(20);
340 gTextAreaAbout.setRows(5);
341 gTextAreaAbout.setText("Server Management client\n© Copyright 2015 TJ <hacker@iam.tj>\n\n<<< Click on the mug to learn more!\n\nI will disappear in 20 seconds.\n\n");
342 gTextAreaAbout.setBorder(null);
343 gDialogAbout.getContentPane().add(gTextAreaAbout);
344 gTextAreaAbout.setBounds(310, 30, 270, 200);
346 gBtnAbout.setBackground(new java.awt.Color(255, 255, 255));
347 gBtnAbout.setFont(new java.awt.Font("Dialog", 1, 18)); // NOI18N
348 gBtnAbout.setIcon(new javax.swing.ImageIcon(getClass().getResource("/uk/ac/ntu/n0521366/wsyd/resources/ScroogledKeepCalmMug.png"))); // NOI18N
349 gBtnAbout.setText("We Stealz Your Dataz");
350 gBtnAbout.setBorder(null);
351 gBtnAbout.setBorderPainted(false);
352 gBtnAbout.setContentAreaFilled(false);
353 gBtnAbout.setDefaultCapable(false);
354 gBtnAbout.setFocusPainted(false);
355 gBtnAbout.setRolloverEnabled(false);
356 gBtnAbout.setVerticalAlignment(javax.swing.SwingConstants.TOP);
357 gBtnAbout.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
358 gBtnAbout.addActionListener(new java.awt.event.ActionListener() {
359 public void actionPerformed(java.awt.event.ActionEvent evt) {
363 gDialogAbout.getContentPane().add(gBtnAbout);
364 gBtnAbout.setBounds(0, 0, 530, 324);
366 gFileChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
367 gFileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
368 gFileChooser.setDialogTitle("Save As");
370 setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
371 setTitle("We Stealz Your Dataz Servers Management");
372 setIconImage(new ImageIcon( getClass().getResource(resourcePath +"/ScroogledKeepCalmMug.icon.png")).getImage());
374 gLogScroller.setAutoscrolls(true);
376 gLogTable.setModel(new javax.swing.table.DefaultTableModel(
378 {null, null, null, null}
381 "Time", "Level", "Facility", "Message"
384 Class[] types = new Class [] {
385 java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
387 boolean[] canEdit = new boolean [] {
388 false, false, false, false
391 public Class getColumnClass(int columnIndex) {
392 return types [columnIndex];
395 public boolean isCellEditable(int rowIndex, int columnIndex) {
396 return canEdit [columnIndex];
399 gLogTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
400 gLogTable.setFillsViewportHeight(true);
401 gLogTable.getTableHeader().setReorderingAllowed(false);
402 gLogScroller.setViewportView(gLogTable);
403 if (gLogTable.getColumnModel().getColumnCount() > 0) {
404 gLogTable.getColumnModel().getColumn(0).setPreferredWidth(128);
405 gLogTable.getColumnModel().getColumn(1).setPreferredWidth(128);
406 gLogTable.getColumnModel().getColumn(2).setPreferredWidth(128);
409 getContentPane().add(gLogScroller, java.awt.BorderLayout.CENTER);
411 gMenuFile.setText("File");
413 gMenuFileSave.setText("Save...");
414 gMenuFileSave.setActionCommand("FileSave");
415 gMenuFileSave.addActionListener(new java.awt.event.ActionListener() {
416 public void actionPerformed(java.awt.event.ActionEvent evt) {
417 gMenuFileSaveActionPerformed(evt);
420 gMenuFile.add(gMenuFileSave);
422 gMenuBar.add(gMenuFile);
424 gMenuLog.setText("Log");
426 gMenuLogClear.setText("Clear");
427 gMenuLogClear.setActionCommand("LogTableClear");
428 gMenuLogClear.addActionListener(new java.awt.event.ActionListener() {
429 public void actionPerformed(java.awt.event.ActionEvent evt) {
430 gMenuLogClearActionPerformed(evt);
433 gMenuLog.add(gMenuLogClear);
435 gMenuLogControl.setSelected(true);
436 gMenuLogControl.setText("Running");
437 gMenuLogControl.setActionCommand("LogControl");
438 gMenuLogControl.addActionListener(new java.awt.event.ActionListener() {
439 public void actionPerformed(java.awt.event.ActionEvent evt) {
440 gMenuLogControlActionPerformed(evt);
443 gMenuLog.add(gMenuLogControl);
445 gMenuLogAutoScroll.setSelected(true);
446 gMenuLogAutoScroll.setText("Auto-scroll");
447 gMenuLogAutoScroll.setActionCommand("LogAutoScroll");
448 gMenuLogAutoScroll.addActionListener(new java.awt.event.ActionListener() {
449 public void actionPerformed(java.awt.event.ActionEvent evt) {
450 gMenuLogAutoScrollActionPerformed(evt);
453 gMenuLog.add(gMenuLogAutoScroll);
455 gMenuLogServiceAnnounce.setSelected(true);
456 gMenuLogServiceAnnounce.setText("Multicast Announce");
457 gMenuLogServiceAnnounce.addActionListener(new java.awt.event.ActionListener() {
458 public void actionPerformed(java.awt.event.ActionEvent evt) {
459 gMenuLogServiceAnnounceActionPerformed(evt);
462 gMenuLog.add(gMenuLogServiceAnnounce);
464 gMenuBar.add(gMenuLog);
466 gMenuServers.setText("Servers");
468 gMenuServerSocial.setText("Social");
469 gMenuServerSocial.setEnabled(false);
471 gMenuServerSocialRestart.setText("Restart");
472 gMenuServerSocialRestart.setActionCommand("SocialRestart");
473 gMenuServerSocialRestart.addActionListener(new java.awt.event.ActionListener() {
474 public void actionPerformed(java.awt.event.ActionEvent evt) {
475 gMenuServerSocialRestartActionPerformed(evt);
478 gMenuServerSocial.add(gMenuServerSocialRestart);
480 gMenuServerSocialStop.setText("Stop");
481 gMenuServerSocialStop.setActionCommand("SocialStop");
482 gMenuServerSocial.add(gMenuServerSocialStop);
484 gMenuServers.add(gMenuServerSocial);
486 gMenuServerChat.setText("Chat");
487 gMenuServerChat.setEnabled(false);
489 gMenuServerChatRestart.setText("Restart");
490 gMenuServerChatRestart.setActionCommand("ChatRestart");
491 gMenuServerChat.add(gMenuServerChatRestart);
493 gMenuServerChatStop.setText("Stop");
494 gMenuServerChatStop.setActionCommand("ChatStop");
495 gMenuServerChat.add(gMenuServerChatStop);
497 gMenuServers.add(gMenuServerChat);
499 gMenuBar.add(gMenuServers);
501 gMenuHelp.setText("Help");
503 gMenuHelpAbout.setText("About");
504 gMenuHelpAbout.addActionListener(new java.awt.event.ActionListener() {
505 public void actionPerformed(java.awt.event.ActionEvent evt) {
506 gMenuHelpAboutActionPerformed(evt);
509 gMenuHelp.add(gMenuHelpAbout);
511 gMenuBar.add(gMenuHelp);
513 setJMenuBar(gMenuBar);
516 }// </editor-fold>//GEN-END:initComponents
518 private void gMenuServerSocialRestartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuServerSocialRestartActionPerformed
519 // TODO add your handling code here:
520 LOGGER.logp(Level.FINEST, _title, null, "Requesting ServerSocial Restart");
521 MessageServerControl mc = new MessageServerControl(MessageServerControl.EXIT.NO , MessageServerControl.RESTART.YES);
522 NetworkMessage nm = NetworkMessage.createNetworkMessage("Control", "ServerSocialControl", mc);
523 nm.setSender(_title);
527 }//GEN-LAST:event_gMenuServerSocialRestartActionPerformed
530 * When the (disguised) mug-icon button is pressed load a web page in the system default browser.
532 * Displays a news story about Microsoft Store's 'Scroogle' mug which coincidentally has a tag line
533 * that is almost identical to the chosen name of this application.
537 private void AboutAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AboutAction
539 Desktop.getDesktop().browse(URI.create("http://www.slate.com/blogs/future_tense/2013/11/20/microsoft_scroogled_gear_anti_google_t_shirts_mugs_say_keep_calm_while_we.html"));
540 } catch(IOException e) {
542 }//GEN-LAST:event_AboutAction
545 * Show the Help>About dialog and auto-close it after 20 seconds.
549 private void gMenuHelpAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuHelpAboutActionPerformed
550 ActionListener autoCloseAboutDlg = new ActionListener() {
552 public void actionPerformed(ActionEvent e) {
553 gDialogAbout.setVisible(false);
557 gDialogAbout.setLocationRelativeTo(this); // center in application window
558 gDialogAbout.setVisible(true);
559 Timer autoClose = new Timer(20000, autoCloseAboutDlg);
561 }//GEN-LAST:event_gMenuHelpAboutActionPerformed
564 * Save log entries to a file.
568 private void gMenuFileSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuFileSaveActionPerformed
569 if (gFileChooser.showSaveDialog(this) == javax.swing.JFileChooser.APPROVE_OPTION) {
570 File saveAs = gFileChooser.getSelectedFile();
572 BufferedWriter writer = new BufferedWriter(new FileWriter(saveAs));
575 for (int row = 0; row < gLogTable.getModel().getRowCount(); row++) {
576 StringBuilder record = new StringBuilder();
577 int colMax = gLogTable.getModel().getColumnCount();
578 for (int col = 0; col < colMax; col++) {
579 record.append(gLogTable.getModel().getValueAt(row, col));
580 if (col < colMax - 1) {
584 writer.write(record.toString());
588 } catch (IOException e) {
589 System.err.println("Unable to write to file");
592 }//GEN-LAST:event_gMenuFileSaveActionPerformed
595 * Clear the log table.
598 private void gMenuLogClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogClearActionPerformed
599 ((DefaultTableModel)gLogTable.getModel()).setRowCount(0);
600 }//GEN-LAST:event_gMenuLogClearActionPerformed
603 * Enable or disable logging.
606 private void gMenuLogControlActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogControlActionPerformed
607 _doLogging = !_doLogging;
608 gMenuLogControl.setSelected(_doLogging);
609 }//GEN-LAST:event_gMenuLogControlActionPerformed
612 * Enable or disable automatic scrolling of the log table.
615 private void gMenuLogAutoScrollActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogAutoScrollActionPerformed
616 _autoScroll = !_autoScroll;
617 gMenuLogAutoScroll.setSelected(_autoScroll);
618 }//GEN-LAST:event_gMenuLogAutoScrollActionPerformed
621 * Enable or disable multicast log service announcements.
624 private void gMenuLogServiceAnnounceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogServiceAnnounceActionPerformed
625 this._multicastAnnouncements = gMenuLogServiceAnnounce.isSelected();
626 }//GEN-LAST:event_gMenuLogServiceAnnounceActionPerformed
629 * Receive a NetworkMessageEvent and dispose of it
633 public void NetworkMessageReceived(NetworkMessageEvent event) {
634 NetworkMessage nm = event.getNetworkMessage();
635 if (nm == null || !_doLogging)
637 // is it a LogRecord?
638 switch (nm.getIntent()) {
640 MessageLogRecord m = (MessageLogRecord) nm.getMessage();
643 this.isLoggable(m.record);
646 String type = nm.getMessage().getMessageType();
647 if (type.equals(MessagePresence.getType())) { // Presence
648 MessagePresence mp = (MessagePresence)nm.getMessage();
649 switch (mp.serviceName) {
651 gMenuServerSocial.setEnabled(true);
654 gMenuServerChat.setEnabled(true);
660 default: // log all unhandled messages
661 LogRecord record = new LogRecord(Level.WARNING,
662 MessageFormat.format("Unhandled NetworkMessage received with intent: \"{0}\" sender: \"{1}\" target: \"{2}\"",
663 nm.getIntent(), nm.getSender(), nm.getTarget() )
665 record.setMillis(System.currentTimeMillis());
671 * @param args the command line arguments
673 public static void main(String args[]) {
674 /* Set the Nimbus look and feel */
675 //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
676 /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
677 * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
680 for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
681 if ("Nimbus".equals(info.getName())) {
682 javax.swing.UIManager.setLookAndFeel(info.getClassName());
686 } catch (ClassNotFoundException|InstantiationException|IllegalAccessException|javax.swing.UnsupportedLookAndFeelException ex) {
687 java.util.logging.Logger.getLogger(ServerManagement.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
693 /* Create and display the form */
694 class App implements Runnable {
695 public boolean multicastAnnouncements = false;
696 public InetAddress serverSocial = null;
700 new ServerManagement(multicastAnnouncements, serverSocial).initListeners().setVisible(true);
702 catch(UnknownHostException e) {
703 System.err.println("Error: cannot create log server listener socket");
709 // process command line arguments
710 for (int i = 0; i < args.length; i++) {
713 app.multicastAnnouncements = true;
716 if (args.length >= i+1) {
717 // read the next argument as an IP address
720 temp = InetAddress.getByName(args[i+1]);
721 app.serverSocial = temp;
722 } catch (UnknownHostException e) {
723 System.err.println(MessageFormat.format("Error: {0} is not a valid hostname or IP address", args[i+1]));
729 java.awt.EventQueue.invokeLater(app);
732 // Variables declaration - do not modify//GEN-BEGIN:variables
733 private javax.swing.ButtonGroup buttonGroup1;
734 private javax.swing.JButton gBtnAbout;
735 private javax.swing.JDialog gDialogAbout;
736 private javax.swing.JFileChooser gFileChooser;
737 private javax.swing.JScrollPane gLogScroller;
738 private javax.swing.JTable gLogTable;
739 private javax.swing.JMenuBar gMenuBar;
740 private javax.swing.JMenu gMenuFile;
741 private javax.swing.JMenuItem gMenuFileSave;
742 private javax.swing.JMenu gMenuHelp;
743 private javax.swing.JMenuItem gMenuHelpAbout;
744 private javax.swing.JMenu gMenuLog;
745 private javax.swing.JCheckBoxMenuItem gMenuLogAutoScroll;
746 private javax.swing.JMenuItem gMenuLogClear;
747 private javax.swing.JCheckBoxMenuItem gMenuLogControl;
748 private javax.swing.JCheckBoxMenuItem gMenuLogServiceAnnounce;
749 private javax.swing.JMenu gMenuServerChat;
750 private javax.swing.JMenuItem gMenuServerChatRestart;
751 private javax.swing.JMenuItem gMenuServerChatStop;
752 private javax.swing.JMenu gMenuServerSocial;
753 private javax.swing.JMenuItem gMenuServerSocialRestart;
754 private javax.swing.JMenuItem gMenuServerSocialStop;
755 private javax.swing.JMenu gMenuServers;
756 private javax.swing.JTextArea gTextAreaAbout;
757 // End of variables declaration//GEN-END:variables