About us
Contact us
Products
Services
Articles
 Twitter    Bookmark and Share

16. Monitor Starter

Contents | Previous Chapter | Next Chapter

This chapter presents the class that starts the mail monitor application.


16.1. Starting the Monitor

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.


16.2. Closing the Application

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

16.3. Hints and Tips

The next chapter shows you how to launch the monitor starter.

Contents | Previous Chapter | Next Chapter

Copyright © 2000-2009 Devsphere

About us
Contact us
Products
Services
Articles