/*
* The MIT License
*
- * Copyright 2015 Eddie Berrisford-Lynch <dev@fun2be.me>.
+ * Copyright 20
+ @Override
+ public void eventDispatched(AWTEvent event) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+15 Eddie Berrisford-Lynch <dev@fun2be.me>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*/
package uk.ac.ntu.n0521366.wsyd.management;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.Desktop;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.File;
-import javax.swing.ImageIcon;
-import java.awt.Desktop;
+import java.io.IOException;
import java.net.URI;
import java.net.InetAddress;
-import java.io.IOException;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
-import javax.swing.Timer;
-import javax.swing.table.DefaultTableModel;
import java.net.UnknownHostException;
-import java.util.logging.Logger;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Filter;
-import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.MessageFormat;
+import java.util.logging.*;
+import java.util.Date;
import java.util.ArrayList;
+import javax.swing.ImageIcon;
+import javax.swing.Timer;
+import javax.swing.table.DefaultTableModel;
import uk.ac.ntu.n0521366.wsyd.libs.logging.TableModelHandler;
-import uk.ac.ntu.n0521366.wsyd.libs.message.MessageLogRecord;
-import uk.ac.ntu.n0521366.wsyd.libs.message.MessagePresence;
-import uk.ac.ntu.n0521366.wsyd.libs.message.MessageServerControl;
-import uk.ac.ntu.n0521366.wsyd.libs.net.WSYD_SocketAddress.Protocol;
+import uk.ac.ntu.n0521366.wsyd.libs.message.*;
import uk.ac.ntu.n0521366.wsyd.libs.net.*;
-import uk.ac.ntu.n0521366.wsyd.libs.net.ServiceAddressMap.LastSeenHost;
/**
+ * GUI client that receives log messages from the servers (and clients) and can restart/stop the servers.
+ *
+ * Log messages are received over UDP encapsulated in {@see uk.ac.ntu.n0521366.wsyd.libs.net.NetworkMessage} objects and displayed in
+ * a scrolling table. Log messages are sent from remote hosts using the {@see uk.ac.ntu.n0521366.wsyd.libs.logging.PacketHandler} attached to
+ * each remote host's Logger instance.
+ *
+ * Remote hosts discover the Log Service by watching for a multicast announcement from this application. Multicast
+ * can be enabled and disabled on the Log menu. Remote hosts will log to their local console until this Log Service
+ * is discovered.
*
+ * The level of logging can be changed from ALL to OFF. The table can be set to automatically scroll.
+ *
* @author Eddie Berrisford-Lynch <dev@fun2be.me>
*/
public class ServerManagement extends javax.swing.JFrame implements NetworkMessageEventListener, Filter {
/**
- * class-wide logger
+ * Handles display and sending of log messages.
*/
- Logger LOGGER = null;
-
+ private Logger LOGGER;
+
/**
* Location of resource bundles, images, icons
*/
/**
* Readable/displayable name of this application
*/
- final String _title = "ServerManagement";
+ private final String _title = "ServerManagement";
/**
- * Network services to address map.
+ * Name of the network log server to advertise with multicast neighbour discovery
*/
- ServiceAddressMap _serviceToAddressMap;
+ private final String logServiceName = "LogService";
/**
- * The UDP listener address for incoming log messages
+ * Network services to address map.
*/
- WSYD_SocketAddress _udpLogServiceSA = null;
+ ServiceAddressMap _serviceToAddressMap;
+
- /**
- * UDP multi-cast presence advertiser
- */
- WSYD_SocketAddress _multicastAdvertiserSA = null;
-
/**
* Log service running in a SwingWorker thread.
*/
* Multi-cast neighbour advertise and discover service in a SwingWorker thread.
*/
NetworkServerUDPMulticast _multicastServer = null;
-
+
+ /**
+ * Whether process should announce itself using multicast.
+ *
+ * Provides neighbour discovery without DNS or manual IP address configuration.
+ */
boolean _multicastAnnouncements = false;
/**
* Enable or suspend logging
*/
private boolean _doLogging;
-
+
/**
* Enable or suspend table auto-scroll
*/
private boolean _autoScroll;
-
+
/**
* Regular presence announcements
*/
- Timer regularTasks;
+ Timer _regularTasks;
+
+ java.awt.event.ActionListener logLevelEvent;
/**
* Creates new GUI
* Instantiating code <em>must</em> also call initListeners()
- *
+ *
* @see #initListeners()
*/
public ServerManagement() {
- if (LOGGER == null) // single instance of the Logger shared by all class objects
- LOGGER = Logger.getLogger(_title);
- LOGGER.setLevel(Level.ALL);
+ LOGGER = Logger.getLogger(_title);
+ // workaround to ensure all levels of log messages are recorded locally before the ServerLog service is available on the network
+ Logger l = LOGGER;
+ while (l != null) {
+ try {
+ l.setLevel(Level.ALL);
+ } catch (SecurityException ex ) {
+ System.err.println("LOGGER: cannot set level for logger " + l.getName());
+ }
+ l = l.getParent();
+ }
+
_serviceToAddressMap = new ServiceAddressMap(_title, LOGGER);
+
+ // receives notifications from the log level menu buttons
+ logLevelEvent = new java.awt.event.ActionListener() {
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ gMenuLogLevelActionPerformed(evt);
+ }
+ };
initComponents();
_doLogging = true;
_autoScroll = true;
this();
this._multicastAnnouncements = multicastAnnouncements;
gMenuLogServiceAnnounce.setSelected(_multicastAnnouncements);
- // TODO: implement constructor setting IP address of SocialServer from command-line value
if (serverSocial != null)
- _serviceToAddressMap.put("ServerSocial", new LastSeenHost(new InetSocketAddress(serverSocial, Network.PORTS_SERVER_SOCIAL), LastSeenHost.STATE.STATIC));
+ _serviceToAddressMap.put("ServerSocial", new ServiceAddressMap.LastSeenHost(new InetSocketAddress(serverSocial, Network.PORTS_SERVER_SOCIAL), ServiceAddressMap.LastSeenHost.STATE.STATIC));
}
+
/**
- * Initialise listeners and other objects that require a reference to 'this'.
+ * Custom simplified logging function.
+ *
+ * Encapsulates the commonly repeated code of Logger method calls
*
+ * @param level the Logger.Level of this message
+ * @param format MessageFormat.format() formatter
+ * @param message zero or more arguments for MessageFormat.format() to process
+ */
+ protected void logp(Level level, String format, Object... message) {
+ if (LOGGER != null)
+ LOGGER.logp(level, _title, null, MessageFormat.format(format, (Object[]) message));
+ }
+
+ /**
+ * Initialise listeners and other objects that require a reference to 'this'.
+ *
* Passing 'this' from within the constructor is unsafe since the object is not
* fully constructed, so do it here. The compiler and virtual machine are free to move 'final'
* properties outside the constructor which means they may not be correctly
* initialised before the constructor returns. This is especially problematic
* in multi-threading applications.
- *
+ *
* @return a reference to 'this' so method calls can be chained (e.g. new ServerManagement().initListeners().setVisible(true) )
* @throws UnknownHostException
*/
- public ServerManagement initListeners() throws UnknownHostException {
+ public ServerManagement initListeners() throws UnknownHostException {
LOGGER.addHandler(new TableModelHandler(this)); // send messages to the GUI log table
LOGGER.setUseParentHandlers(false); // don't send messages to the default error stream logger of the parent
- LOGGER.logp(Level.INFO, _title, null, "Server Management starting");
-
- _udpLogServiceSA = new WSYD_SocketAddress(Network.PORTS_SERVER_LOG, Protocol.UDP);
+ logp(Level.INFO, "Server Management starting");
+
+ WSYD_SocketAddress _udpLogServiceSA = new WSYD_SocketAddress(Network.PORTS_SERVER_LOG, WSYD_SocketAddress.Protocol.UDP);
_udpLogService = new NetworkServerUDP(_udpLogServiceSA, _title + "Log", _serviceToAddressMap, LOGGER);
- _udpLogService.getEventManager().addNetworkMessageEventListener(this, "Log");
+ _udpLogService.getEventManager().addNetworkMessageEventListener(this);
_udpLogService.setSimulate(false);
_udpLogService.execute();
- _multicastAdvertiserSA = new WSYD_SocketAddress(Network.MULTICAST_IP, Network.PORTS_MULTICAST_DISCOVERY, Protocol.UDP);
+ WSYD_SocketAddress _multicastAdvertiserSA = new WSYD_SocketAddress(Network.MULTICAST_IPv4, Network.PORTS_MULTICAST_DISCOVERY, WSYD_SocketAddress.Protocol.UDP);
_multicastServer = new NetworkServerUDPMulticast(_multicastAdvertiserSA, _title + "MC", _serviceToAddressMap, LOGGER);
_multicastServer.getEventManager().addNetworkMessageEventListener(this, "Neighbour");
_multicastServer.execute();
// permit broadcasting to pseudo-host 'all' since this is multicast
- _serviceToAddressMap.put("all", new LastSeenHost(new InetSocketAddress(Network.MULTICAST_IP, Network.PORTS_MULTICAST_DISCOVERY), LastSeenHost.STATE.STATIC));
-
+ _serviceToAddressMap.put("all", new ServiceAddressMap.LastSeenHost(new InetSocketAddress(Network.MULTICAST_IPv4, Network.PORTS_MULTICAST_DISCOVERY), ServiceAddressMap.LastSeenHost.STATE.STATIC));
+
// log any static entries in the service map
- for (java.util.Map.Entry<String, LastSeenHost> entry: this._serviceToAddressMap.getEntrySet()) {
- LastSeenHost host = entry.getValue();
- if (host.state == LastSeenHost.STATE.STATIC)
- LOGGER.logp(Level.FINER, _title, null, MessageFormat.format("Static Service: {0} = {1}:{2,number,#####}", entry.getKey(), host.address.getHostString(), host.address.getPort()));
+ for (java.util.Map.Entry<String, ServiceAddressMap.LastSeenHost> entry: this._serviceToAddressMap.getEntrySet()) {
+ ServiceAddressMap.LastSeenHost host = entry.getValue();
+ if (host.state == ServiceAddressMap.LastSeenHost.STATE.STATIC)
+ logp(Level.FINER, "Static Service: {0} = {1}:{2,number,#####}", entry.getKey(), host.address.getHostString(), host.address.getPort());
}
-
+
ActionListener regularTasksActionListener = new ActionListener() {
// provide a way to read the current version of the parent process object's fields
ServerManagement owner;
-
+
// XXX: Anonymous class initialisation - effectively used as the body of the object's constructor
{
// XXX: access to the outer class's instance object
*/
@Override
public void actionPerformed(ActionEvent e) {
- String serviceName = "LogService";
// check the current value ofthe parent process' flag
if (owner._multicastAnnouncements) {
- // Create local log report first
- LogRecord record = new LogRecord(Level.FINEST, "Multicast: Announcing Presence");
- record.setSourceClassName(serviceName);
- record.setMillis(System.currentTimeMillis());
- LOGGER.log(record);
-
+ logp(Level.FINEST, "Multicast: Announcing Presence");
// Announce the log service
- MessagePresence mp = new MessagePresence(_title + serviceName, _udpLogService.getSocketAddress());
+ MessagePresence mp = new MessagePresence(logServiceName, _udpLogService.getSocketAddress());
NetworkMessage nm = NetworkMessage.createNetworkMessage("Neighbour", "all", mp);
- nm.setSender(_title + serviceName);
+ nm.setSender(logServiceName);
_multicastServer.queueMessage(nm);
}
// clean up the known hosts map
}
};
- regularTasks = new Timer(1000, regularTasksActionListener);
- regularTasks.setInitialDelay(100);
- regularTasks.start();
-
+ _regularTasks = new Timer(1000, regularTasksActionListener);
+ _regularTasks.setInitialDelay(100);
+ _regularTasks.start();
+
return this;
}
/**
* Add a log record to the log table if logging is enabled.
- *
+ *
* Abusing an already-existing logging interface. This method isn't filtering, it is called by
* the Logger's TableModelHandler to publish records.
- *
+ *
* @see TableModelHandler
* @param record
* @return true if logging is enabled
@Override
public boolean isLoggable(LogRecord record) {
if (_doLogging) {
- if (record != null) {
+ if (record != null && LOGGER.isLoggable(record.getLevel())) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// add the log record to the log table
((DefaultTableModel)gLogTable.getModel()).addRow(
packetSend.setPort(address.getPort());
DatagramSocket socket = new DatagramSocket();
- // acknowledge receipt
socket.send(packetSend);
- 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()));
+ logp(Level.FINEST, "Sending packet for {0} to {1} ({3}:{4,number,integer}) from {2}", message.getIntent(), message.getTarget(), message.getSender(), packetSend.getAddress().getHostAddress(), packetSend.getPort());
result = true; // successful
} catch (IOException e) {
- // TODO: serverSend() add IOException handler
- e.printStackTrace();
+ logp(Level.SEVERE, "UDPSend(): ", e.toString());
}
}
}
return result;
}
+
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
- buttonGroup1 = new javax.swing.ButtonGroup();
+ buttonGroupLogLevels = new javax.swing.ButtonGroup();
gDialogAbout = new javax.swing.JDialog();
gTextAreaAbout = new javax.swing.JTextArea();
gBtnAbout = new javax.swing.JButton();
gMenuLogControl = new javax.swing.JCheckBoxMenuItem();
gMenuLogAutoScroll = new javax.swing.JCheckBoxMenuItem();
gMenuLogServiceAnnounce = new javax.swing.JCheckBoxMenuItem();
+ gMenuLogLevel = new javax.swing.JMenu();
+ gMenuLogLevelAll = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelFinest = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelFiner = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelFine = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelConfig = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelInfo = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelWarning = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelSevere = new javax.swing.JRadioButtonMenuItem();
+ gMenuLogLevelOff = new javax.swing.JRadioButtonMenuItem();
gMenuServers = new javax.swing.JMenu();
gMenuServerSocial = new javax.swing.JMenu();
gMenuServerSocialRestart = new javax.swing.JMenuItem();
});
gMenuLog.add(gMenuLogServiceAnnounce);
+ gMenuLogLevel.setText("Level");
+
+ buttonGroupLogLevels.add(gMenuLogLevelAll);
+ gMenuLogLevelAll.setSelected(true);
+ gMenuLogLevelAll.setText("ALL");
+ gMenuLogLevelAll.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelAll);
+
+ buttonGroupLogLevels.add(gMenuLogLevelFinest);
+ gMenuLogLevelFinest.setText("FINEST");
+ gMenuLogLevelFinest.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelFinest);
+
+ buttonGroupLogLevels.add(gMenuLogLevelFiner);
+ gMenuLogLevelFiner.setText("FINER");
+ gMenuLogLevelFiner.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelFiner);
+
+ buttonGroupLogLevels.add(gMenuLogLevelFine);
+ gMenuLogLevelFine.setText("FINE");
+ gMenuLogLevelFine.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelFine);
+
+ buttonGroupLogLevels.add(gMenuLogLevelConfig);
+ gMenuLogLevelConfig.setText("CONFIG");
+ gMenuLogLevelConfig.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelConfig);
+
+ buttonGroupLogLevels.add(gMenuLogLevelInfo);
+ gMenuLogLevelInfo.setText("INFO");
+ gMenuLogLevelInfo.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelInfo);
+
+ buttonGroupLogLevels.add(gMenuLogLevelWarning);
+ gMenuLogLevelWarning.setText("WARNING");
+ gMenuLogLevelWarning.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelWarning);
+
+ buttonGroupLogLevels.add(gMenuLogLevelSevere);
+ gMenuLogLevelSevere.setText("SEVERE");
+ gMenuLogLevelSevere.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelSevere);
+
+ buttonGroupLogLevels.add(gMenuLogLevelOff);
+ gMenuLogLevelOff.setText("OFF");
+ gMenuLogLevelOff.addActionListener(logLevelEvent);
+ gMenuLogLevel.add(gMenuLogLevelOff);
+
+ gMenuLog.add(gMenuLogLevel);
+
gMenuBar.add(gMenuLog);
gMenuServers.setText("Servers");
pack();
}// </editor-fold>//GEN-END:initComponents
+ /**
+ * Sets the log level in response to GUI Log Level menu selections.
+ *
+ * @param evt
+ */
+ private void gMenuLogLevelActionPerformed(java.awt.event.ActionEvent evt) {
+ LOGGER.logp(Level.SEVERE, _title, null, "Changing to log level " + evt.getActionCommand());
+ LOGGER.setLevel(Level.parse(evt.getActionCommand()));
+ }
+
private void gMenuServerSocialRestartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuServerSocialRestartActionPerformed
// TODO add your handling code here:
LOGGER.logp(Level.FINEST, _title, null, "Requesting ServerSocial Restart");
nm.setSender(_title);
UDPSend(nm);
-
+
}//GEN-LAST:event_gMenuServerSocialRestartActionPerformed
/**
* When the (disguised) mug-icon button is pressed load a web page in the system default browser.
- *
+ *
* Displays a news story about Microsoft Store's 'Scroogle' mug which coincidentally has a tag line
* that is almost identical to the chosen name of this application.
- *
- * @param evt
+ *
+ * @param evt
*/
private void AboutAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AboutAction
try {
/**
* Show the Help>About dialog and auto-close it after 20 seconds.
- *
+ *
* @param evt
*/
private void gMenuHelpAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuHelpAboutActionPerformed
/**
* Save log entries to a file.
- *
- * @param evt
+ *
+ * @param evt
*/
private void gMenuFileSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuFileSaveActionPerformed
if (gFileChooser.showSaveDialog(this) == javax.swing.JFileChooser.APPROVE_OPTION) {
/**
* Clear the log table.
- * @param evt
+ * @param evt
*/
private void gMenuLogClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogClearActionPerformed
((DefaultTableModel)gLogTable.getModel()).setRowCount(0);
/**
* Enable or disable logging.
- * @param evt
+ * @param evt
*/
private void gMenuLogControlActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogControlActionPerformed
_doLogging = !_doLogging;
/**
* Enable or disable automatic scrolling of the log table.
- * @param evt
+ * @param evt
*/
private void gMenuLogAutoScrollActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogAutoScrollActionPerformed
_autoScroll = !_autoScroll;
/**
* Enable or disable multicast log service announcements.
- * @param evt
+ * @param evt
*/
private void gMenuLogServiceAnnounceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gMenuLogServiceAnnounceActionPerformed
this._multicastAnnouncements = gMenuLogServiceAnnounce.isSelected();
NetworkMessage nm = event.getNetworkMessage();
if (nm == null || !_doLogging)
return;
- // is it a LogRecord?
+
+ String type = nm.getMessage().getMessageType();
switch (nm.getIntent()) {
case "Log":
MessageLogRecord m = (MessageLogRecord) nm.getMessage();
return;
this.isLoggable(m.record);
break;
+
case "Neighbour":
- String type = nm.getMessage().getMessageType();
- if (type.equals(MessagePresence.getType())) { // Presence
+ if (type.equals(MessagePresence.getType())) {
MessagePresence mp = (MessagePresence)nm.getMessage();
+ // add or update the last-seen time of the Sender host in the known services map
+ ServiceAddressMap.LastSeenHost host = new ServiceAddressMap.LastSeenHost(new InetSocketAddress(nm.getReceivedFrom().getAddress(), mp.socketAddress.getPort()));
+ this._serviceToAddressMap.put(mp.serviceName, host);
+ logp(Level.FINEST, "Added \"{0}\" ({1}) to service map", mp.serviceName, host.address.toString());
switch (mp.serviceName) {
- case "ServerSocial":
+ case "ServerSocialMC":
gMenuServerSocial.setEnabled(true);
break;
- case "ServerChat":
+ case "ServerChatMC":
gMenuServerChat.setEnabled(true);
- break;
+ break;
}
}
-
+ break;
default: // log all unhandled messages
- LogRecord record = new LogRecord(Level.WARNING,
- MessageFormat.format("Unhandled NetworkMessage received with intent: \"{0}\" sender: \"{1}\" target: \"{2}\"",
- nm.getIntent(), nm.getSender(), nm.getTarget() )
- );
- record.setMillis(System.currentTimeMillis());
- LOGGER.log(record);
+ logp(Level.WARNING, "Unhandled NetworkMessage received with intent: \"{0}\" sender: \"{1}\" target: \"{2}\"", nm.getIntent(), nm.getSender(), nm.getTarget());
}
}
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.ButtonGroup buttonGroupLogLevels;
+ private javax.swing.JButton gBtnAbout;
+ private javax.swing.JDialog gDialogAbout;
+ private javax.swing.JFileChooser gFileChooser;
+ private javax.swing.JScrollPane gLogScroller;
+ private javax.swing.JTable gLogTable;
+ private javax.swing.JMenuBar gMenuBar;
+ private javax.swing.JMenu gMenuFile;
+ private javax.swing.JMenuItem gMenuFileSave;
+ private javax.swing.JMenu gMenuHelp;
+ private javax.swing.JMenuItem gMenuHelpAbout;
+ private javax.swing.JMenu gMenuLog;
+ private javax.swing.JCheckBoxMenuItem gMenuLogAutoScroll;
+ private javax.swing.JMenuItem gMenuLogClear;
+ private javax.swing.JCheckBoxMenuItem gMenuLogControl;
+ private javax.swing.JMenu gMenuLogLevel;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelAll;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelConfig;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelFine;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelFiner;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelFinest;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelInfo;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelOff;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelSevere;
+ private javax.swing.JRadioButtonMenuItem gMenuLogLevelWarning;
+ private javax.swing.JCheckBoxMenuItem gMenuLogServiceAnnounce;
+ private javax.swing.JMenu gMenuServerChat;
+ private javax.swing.JMenuItem gMenuServerChatRestart;
+ private javax.swing.JMenuItem gMenuServerChatStop;
+ private javax.swing.JMenu gMenuServerSocial;
+ private javax.swing.JMenuItem gMenuServerSocialRestart;
+ private javax.swing.JMenuItem gMenuServerSocialStop;
+ private javax.swing.JMenu gMenuServers;
+ private javax.swing.JTextArea gTextAreaAbout;
+ // End of variables declaration//GEN-END:variables
+
/**
* @param args the command line arguments
*/
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
- * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
//</editor-fold>
/* Create and display the form */
class App implements Runnable {
- public boolean multicastAnnouncements = false;
+ public boolean multicastAnnouncements = true;
public InetAddress serverSocial = null;
+
+ /**
+ * Constructs, initialises and starts the server management GUI.
+ */
@Override
public void run() {
try {
- new ServerManagement(multicastAnnouncements, serverSocial).initListeners().setVisible(true);
+ new ServerManagement(multicastAnnouncements, serverSocial).initListeners().setVisible(true);
}
- catch(UnknownHostException e) {
- System.err.println("Error: cannot create log server listener socket");
+ catch(UnknownHostException ex) {
+ Logger.getLogger(ServerManagement.class.getName()).log(Level.SEVERE, null, MessageFormat.format("Error: initListeners(): {0}", ex.toString()));
}
}
}
App app = new App();
-
- // process command line arguments
+
+ // process command line arguments. Use indexed for in order to easily read values of switch arguments
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "-announce":
app.multicastAnnouncements = true;
break;
+ case "-noannounce":
+ app.multicastAnnouncements = false;
+ break;
case "-server":
if (args.length >= i+1) {
// read the next argument as an IP address
temp = InetAddress.getByName(args[i+1]);
app.serverSocial = temp;
} catch (UnknownHostException e) {
- System.err.println(MessageFormat.format("Error: {0} is not a valid hostname or IP address", args[i+1]));
+ Logger.getLogger(ServerManagement.class.getName()).log(Level.SEVERE, null, MessageFormat.format("Error: {0} is not a valid hostname or IP address", args[i+1]));
}
}
break;
}
java.awt.EventQueue.invokeLater(app);
}
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.ButtonGroup buttonGroup1;
- private javax.swing.JButton gBtnAbout;
- private javax.swing.JDialog gDialogAbout;
- private javax.swing.JFileChooser gFileChooser;
- private javax.swing.JScrollPane gLogScroller;
- private javax.swing.JTable gLogTable;
- private javax.swing.JMenuBar gMenuBar;
- private javax.swing.JMenu gMenuFile;
- private javax.swing.JMenuItem gMenuFileSave;
- private javax.swing.JMenu gMenuHelp;
- private javax.swing.JMenuItem gMenuHelpAbout;
- private javax.swing.JMenu gMenuLog;
- private javax.swing.JCheckBoxMenuItem gMenuLogAutoScroll;
- private javax.swing.JMenuItem gMenuLogClear;
- private javax.swing.JCheckBoxMenuItem gMenuLogControl;
- private javax.swing.JCheckBoxMenuItem gMenuLogServiceAnnounce;
- private javax.swing.JMenu gMenuServerChat;
- private javax.swing.JMenuItem gMenuServerChatRestart;
- private javax.swing.JMenuItem gMenuServerChatStop;
- private javax.swing.JMenu gMenuServerSocial;
- private javax.swing.JMenuItem gMenuServerSocialRestart;
- private javax.swing.JMenuItem gMenuServerSocialStop;
- private javax.swing.JMenu gMenuServers;
- private javax.swing.JTextArea gTextAreaAbout;
- // End of variables declaration//GEN-END:variables
}