This chapter presents the class that starts the mail monitor application.
The MonitorStarter class builds the user interface for MailMonitor. It verifies the command line parameters and passes their values to MailMonitor. It loads the resource bundles and creates an error handler. It loads the bean class, the processor class and the connector class. It instantiates the processor and connector classes. It creates an instance of MailMonitor and calls its start() method.
The name of the connector class is taken from the ConnectorResources.properties file. You may edit it to replace the default connectors or to add connectors for new protocols.
The user interface consists of an AWT console and three buttons: "Start", "Process Now" and "Stop". The mail monitor's methods are called when the user clicks on these buttons.
The appExit() method is invoked when the user closes the window or when a fatal error occurs. The frame is disposed and the logger is closed. If the MailMonitor object was created a new thread is started and its run() method calls monitor.stop() and monitor.join(). This way, the monitor's thread stops before the call of System.exit(). The use of a new thread makes sure that the thread that called appExit() isn't blocked. This might be the main thread of the application or the event handling thread of AWT. It is important not to block the AWT thread even if the frame is disposed because the bean processor might have opened some other windows.
MonitorStarter.java:
package com.devsphere.apps.mapping.monitor;
import com.devsphere.logging.*;
import com.devsphere.helpers.logging.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
/**
* Starter for MailMonitor
*/
public class MonitorStarter {
public static final String MONITOR_RESOURCES
= "com.devsphere.apps.mapping.monitor.MonitorResources";
public static final String CONNECTOR_RESOURCES
= "com.devsphere.apps.mapping.monitor.ConnectorResources";
protected static ResourceBundle monitorRes = null;
protected static ResourceBundle connectorRes = null;
protected static ApplicationErrorHandler errorHandler = null;
protected static CompoundLogger logger = null;
protected static Frame frame = null;
protected static MailMonitor monitor = null;
/**
* Main method
*/
public static void main(String args[]) {
// Get the monitor resources
try {
monitorRes = ResourceBundle.getBundle(MONITOR_RESOURCES);
} catch (MissingResourceException e) {
System.err.println(e.getMessage());
appExit(1);
}
// Get the connector resources
try {
connectorRes = ResourceBundle.getBundle(CONNECTOR_RESOURCES);
} catch (MissingResourceException e) {
System.err.println(e.getMessage());
appExit(1);
}
// Create the error handler
errorHandler = new ApplicationErrorHandler(monitorRes) {
protected void shutdown() {
appExit(1);
}
};
// Verify the number of parameters
if (args.length != 11)
errorHandler.fatalError("[WRONG_NUMBER_OF_PARAMETERS]", null);
// Create the log file
String logFile = args[10];
PrintWriter logStream = null;
try {
logStream = new PrintWriter(new FileOutputStream(logFile));
} catch (IOException e) {
errorHandler.fatalError("[COULDNT_CREATE_LOG_FILE]", e, logFile);
}
// Create the logger
logger = new CompoundLogger(
new PrintLogger(System.err),
new PrintLogger(logStream));
errorHandler.setLogger(logger);
// Get the bean class
Class beanClass = null;
String beanName = args[0];
try {
beanClass = Class.forName(beanName);
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_LOAD_BEAN_CLASS]", t, beanName);
}
// Get the processor class
Class procClass = null;
String procName = args[1];
try {
procClass = Class.forName(procName);
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_LOAD_PROC_CLASS]", t, procName);
}
// Get the processing method
Method method = null;
String methodName = args[2];
try {
Class paramClasses[] = { beanClass };
method = procClass.getMethod(methodName, paramClasses);
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_GET_PROC_METHOD]", t, methodName);
}
// Create the processor object if necessary
Object processor = null;
if (!Modifier.isStatic(method.getModifiers()))
try {
processor = procClass.newInstance();
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_INSTANTIATE_PROC_CLASS]", t,
procName);
}
// Get the mail protocol
String protocol = args[3];
// Get the connector name
String conName = null;
try {
conName = connectorRes.getObject(protocol + ".class").toString();
} catch (MissingResourceException e) {
errorHandler.fatalError("[CON_NAME_NOT_FOUND]", e, protocol);
}
// Get the connector class
Class conClass = null;
try {
conClass = Class.forName(conName);
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_LOAD_CON_CLASS]", t, conName);
}
// Create the connector object
Object connector = null;
try {
connector = conClass.newInstance();
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_INSTANTIATE_CON_CLASS]", t,
conName);
}
// Verify the connector class
if (!(connector instanceof StoreConnector))
errorHandler.fatalError("[INVALID_CON_CLASS]", null, conName);
// Get the mail parameters
String host = args[4];
String user = args[5];
String password = args[6];
String folder = args[7];
// Get the seconds parameter
int seconds = 0;
String secondsParam = args[8];
try {
seconds = Integer.parseInt(secondsParam);
} catch (NumberFormatException e) {
}
if (seconds <= 0)
errorHandler.fatalError("[INVALID_NUMBER_OF_SECONDS]", null,
secondsParam);
// Get the debug parameter
boolean debug = Boolean.valueOf(args[9]).booleanValue();
// Create the frame
frame = new Frame(getLabelResource("[TITLE]"));
frame.setLayout(new BorderLayout());
frame.add(new Label(user + "@" + host), BorderLayout.NORTH);
// Add the console
TextArea console = new TextArea(20, 80);
console.setEditable(false);
frame.add(console, BorderLayout.CENTER);
// Add the buttons
Panel buttonPanel = new Panel(new FlowLayout());
Button startButton = new Button(getLabelResource("[START]"));
buttonPanel.add(startButton);
Button processNowButton = new Button(getLabelResource("[PROCESS_NOW]"));
buttonPanel.add(processNowButton);
Button stopButton = new Button(getLabelResource("[STOP]"));
buttonPanel.add(stopButton);
frame.add(buttonPanel, BorderLayout.SOUTH);
// Add the console to the existent logger
logger = new CompoundLogger(logger, new AWTLogger(console));
errorHandler.setLogger(logger);
// Create the mail monitor
try {
monitor = new MailMonitor(beanClass, processor, method,
protocol, host, user, password, folder, seconds, debug,
logger, monitorRes, (StoreConnector) connector);
} catch (Exception t) {
errorHandler.fatalError("[COULDNT_CREATE_MONITOR]", t);
}
// Register the listeners
frame.addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent e)
{ appExit(0); } });
startButton.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent e)
{ monitor.start(); } });
processNowButton.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent e)
{ monitor.processNow(); } });
stopButton.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent e)
{ monitor.stop(); } });
// Show the frame
frame.pack();
frame.setLocation(100, 0);
frame.setVisible(true);
monitor.start();
}
/**
* Gets a label from the monitor resources
*/
protected static String getLabelResource(String key) {
try {
return monitorRes.getObject(key).toString();
} catch (MissingResourceException e) {
if (logger != null)
logger.log(e.getMessage());
}
return key;
}
/**
* Closes the application
*/
protected static void appExit(final int code) {
if (frame != null)
frame.dispose();
if (monitor == null) {
if (logger != null)
logger.close();
System.exit(code);
}
Thread closer = new Thread() {
public void run() {
monitor.stop();
monitor.join();
if (logger != null)
logger.close();
System.exit(code);
}
};
closer.start();
}
}
MonitorResources.properties:
# MonitorStarter
[WRONG_NUMBER_OF_PARAMETERS]=Wrong number of command line parameters\n\
Usage: java MonitorStarter <bean_name> <processor_class> <processing_method>\n\
<protocol> <host> <user> <password> <folder> <seconds> <debug> <logfile>
[COULDNT_CREATE_LOG_FILE]=Couldn''t create the log file\: {0}
[COULDNT_LOAD_BEAN_CLASS]=Couldn''t load the bean class\: {0}
[COULDNT_LOAD_PROC_CLASS]=Couldn''t load the processor class\: {0}
[COULDNT_GET_PROC_METHOD]=Couldn''t get the processing method\: {0}
[COULDNT_INSTANTIATE_PROC_CLASS]=Couldn''t instantiate the processor class\: {0}
[CON_NAME_NOT_FOUND]=Connector name not found for the {0} protocol
[COULDNT_LOAD_CON_CLASS]=Couldn''t load the connector class\: {0}
[COULDNT_INSTANTIATE_CON_CLASS]=Couldn''t instantiate the connector class\: {0}
[INVALID_CON_CLASS]=Invalid connector class\: {0}
[INVALID_NUMBER_OF_SECONDS]=Invalid number of seconds\: {0}
[COULDNT_CREATE_MONITOR]=Couldn''t create the mail monitor
[START]=Start
[PROCESS_NOW]=Process Now
[STOP]=Stop
[TITLE]=Mail Monitor
# MailMonitor
[COULDNT_INSTANTIATE_BEAN_CLASS]=Couldn''t instantiate the bean class\: {0}
[MAPPING_ERRORS]=Errors occurred during the text-to-bean mapping\: {0}
[COULDNT_READ_BEAN_DATA]=Couldn''t read the bean''s data encoded as text properties
[PROCESSING_ERROR]=Processing error
[COULDNT_INVOKE_PROC_METHOD]=Couldn''t invoke the processing method\: {0}
[NO_PROTOCOL_PROVIDER]=No provider for the {0} protocol
[COULDNT_GET_STORE]=Couldn''t get the store object for the {0} protocol
[COULDNT_CONNECT]=Couldn''t connect to {0}
[FOLDER_NOT_FOUND]=Folder not found\: {0}
[COULDNT_GET_FOLDER]=Couldn''t get the folder\: {0}
[COULDNT_OPEN_FOLDER]=Couldn''t open the folder\: {0}
[COULDNT_CLOSE_FOLDER]=Couldn''t close the folder\: {0}
[COULDNT_CLOSE_CONNECTION]=Couldn''t close the connection to {0}
[COULDNT_GET_INPUT_STREAM]=Couldn''t get the input stream of a message
[COULDNT_GET_SEEN_FLAG]=Couldn''t get the SEEN flag of a message
[COULDNT_GET_MESSAGES]=Couldn''t get the messages
[CONNECTED]=Connected
[DISCONNECTED]=Disconnected
[BEGIN_PROCESSING]=Begin processing
[END_PROCESSING]=End processing
[THREAD_START]=Thread\: Start
[THREAD_CANCEL_INTERRUPTION_REQUEST]=Thread\: Cancel interruption request
[THREAD_INTERRUPTION_REQUEST]=Thread\: Interruption request
ConnectorResources.properties:
dir.class=com.devsphere.apps.mapping.monitor.DIRStoreConnector
pop3.class=com.devsphere.apps.mapping.monitor.POP3StoreConnector
imap.class=com.devsphere.apps.mapping.monitor.IMAPStoreConnector
The next chapter shows you how to launch the monitor starter.
|