eu.asterics.mw.services.AstericsErrorHandling.java Source code

Java tutorial

Introduction

Here is the source code for eu.asterics.mw.services.AstericsErrorHandling.java

Source

/*
 *    AsTeRICS - Assistive Technology Rapid Integration and Construction Set
 *
 *
 *        d8888      88888888888       8888888b.  8888888 .d8888b.   .d8888b.
 *       d88888          888           888   Y88b   888  d88P  Y88b d88P  Y88b
 *      d88P888          888           888    888   888  888    888 Y88b.    
 *     d88P 888 .d8888b  888   .d88b.  888   d88P   888  888         "Y888b. 
 *    d88P  888 88K      888  d8P  Y8b 8888888P"    888  888            "Y88b.
 *   d88P   888 "Y8888b. 888  88888888 888 T88b     888  888    888       "888
 *  d8888888888      X88 888  Y8b.     888  T88b    888  Y88b  d88P Y88b  d88P
 * d88P     888  88888P' 888   "Y8888  888   T88b 8888888 "Y8888P"   "Y8888P"
 *
 *
 *                    homepage: http://www.asterics.org
 *
 *     This project has been partly funded by the European Commission,
 *                      Grant Agreement Number 247730
 *  
 *  
 *         Dual License: MIT or GPL v3.0 with "CLASSPATH" exception
 *         (please refer to the folder LICENSE)
 *
 */

package eu.asterics.mw.services;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.apache.commons.io.FileUtils;

import eu.asterics.mw.are.AREProperties;
import eu.asterics.mw.are.AREStatus;
import eu.asterics.mw.are.DeploymentManager;
import eu.asterics.mw.are.asapi.StatusObject;
import eu.asterics.mw.gui.ErrorLogPane;
import eu.asterics.mw.model.runtime.IRuntimeComponentInstance;

/*
 *    AsTeRICS - Assistive Technology Rapid Integration and Construction Set
 *
 *
 *        d8888      88888888888       8888888b.  8888888 .d8888b.   .d8888b.
 *       d88888          888           888   Y88b   888  d88P  Y88b d88P  Y88b
 *      d88P888          888           888    888   888  888    888 Y88b.    
 *     d88P 888 .d8888b  888   .d88b.  888   d88P   888  888         "Y888b. 
 *    d88P  888 88K      888  d8P  Y8b 8888888P"    888  888            "Y88b.
 *   d88P   888 "Y8888b. 888  88888888 888 T88b     888  888    888       "888
 *  d8888888888      X88 888  Y8b.     888  T88b    888  Y88b  d88P Y88b  d88P
 * d88P     888  88888P' 888   "Y8888  888   T88b 8888888 "Y8888P"   "Y8888P"
 *
 *
 *                    homepage: http://www.asterics.org
 *
 *     This project has been partly funded by the European Commission,
 *                      Grant Agreement Number 247730
 *  
 *  
 *         Dual License: MIT or GPL v3.0 with "CLASSPATH" exception
 *         (please refer to the folder LICENSE)
 *
 */

/**
 * This class provides Error Handling functionality the ARE and the components 
 * 
 *         Date: Aug 25, 2010
 *         Time: 11:35:35 AM
 */

public class AstericsErrorHandling implements IAstericsErrorHandling {
    public static final String LOG_PATH_PROPERTY = "eu.asterics.mw.services.AstericsErrorHandling.logPath";
    public static final String LOG_CONSOLE_LOGLEVEL_PROPERTY = "eu.asterics.mw.services.AstericsErrorHandling.consoleLogLevel";
    public static final AstericsErrorHandling instance = new AstericsErrorHandling();
    private ArrayList<StatusObject> statusObjects = null;
    static String LOGGER_OPTIONS = ".logger";

    private static int statusObjectIndex = 0;
    private static Logger logger = null;

    private AstericsErrorHandling() {
        super();
        this.statusObjects = new ArrayList<StatusObject>();
    }

    /**
     * This method is used by the components to report an error. It logs the error in "warning" logger
     *  and sets the status of the ARE to "ERROR" to denote that an error has occurred 
     * @param component the component instance that reports the error
     * @param errorMsg the error message
     */
    public void reportError(IRuntimeComponentInstance component, final String errorMsg) {
        if (component != null) {
            String componentID = DeploymentManager.instance
                    .getIRuntimeComponentInstanceIDFromIRuntimeComponentInstance(component);
            if (componentID != null) {
                //System.out.println("componentID: "+componentID);
                logger.warning(componentID + ": " + errorMsg);
                setStatusObject(AREStatus.ERROR.toString(), componentID, errorMsg);
            }
        }

        AREProperties props = AREProperties.instance;
        if (props.checkProperty("showErrorDialogs", "1")) {

            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    ErrorLogPane.appendLog(errorMsg);
                    DeploymentManager.instance.setStatus(AREStatus.ERROR);

                    AstericsErrorHandling.this.notifyAREEventListeners("onAreError", errorMsg);

                    JOptionPane op = new JOptionPane(errorMsg, JOptionPane.WARNING_MESSAGE);

                    JDialog dialog = op.createDialog("AsTeRICS Runtime Environment:");
                    dialog.setAlwaysOnTop(true);
                    dialog.setModal(false);
                    dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                    dialog.setVisible(true);
                }
            });
        }
    }

    /**
     * This method is used by the components to report informative messages. It logs 
     * the message in "info" logger.
     * @param component the component instance that reports the informative message
     * @param info the informative message
     */
    public void reportInfo(IRuntimeComponentInstance component, String info) {
        String componentID = DeploymentManager.instance
                .getIRuntimeComponentInstanceIDFromIRuntimeComponentInstance(component);
        logger.fine(componentID + ": " + info);

    }

    /**
     * This method is used by the components to report.. Ok
     */
    public void reportOk(IRuntimeComponentInstance component, String info) {
        String componentID = DeploymentManager.instance
                .getIRuntimeComponentInstanceIDFromIRuntimeComponentInstance(component);
        logger.fine(componentID + ": " + info);
        setStatusObject(AREStatus.OK.toString(), componentID, info);

    }

    /**
     * This method is used by the components to report debugging messages. It logs 
     * the message in "fine" logger. 
     * @param component the component instance that reports the debugging message
     * @param info the debugging message
     */
    public void reportDebugInfo(IRuntimeComponentInstance component, String info) {
        String componentID = DeploymentManager.instance
                .getIRuntimeComponentInstanceIDFromIRuntimeComponentInstance(component);
        logger.fine(componentID + ": " + info);

    }

    /**
     * This method is used to set a new Status Object. The object is set by the
     * component specified by componentID with the error message specified by errorMsg 
     * and with the ARE status as specified by status. If a component is not specified,
     * the Status Object is set for the ARE.
     * @param componentID the ID of the component that sets the Status Object or null if
     * the Status Object is set by the ARE
     * @param errorMsg the error message in the new Status Object
     * @param status the new status of the ARE
     */
    public void setStatusObject(String status, String componentID, String errorMsg) {
        StatusObject statusObject = new StatusObject(status, componentID, errorMsg);
        statusObjects.add(statusObject);
    }

    /**
     * This method returns an array of all Status Objects if fullList is true or 
     * an array of all Status Objects created after the last time this method has 
     * been called if otherwise.  
     * @param fullList the boolean flag. If true an array of all Status Objects will be
     * returned. If false an array of all Status Objects created after the last time this 
     * method has been called will be returned
     */
    public StatusObject[] getStatusObjects(boolean fullList) {

        StatusObject[] allObjects = statusObjects.toArray(new StatusObject[statusObjects.size()]);
        StatusObject[] res = null;
        int i = 0;

        if (!fullList) {
            res = new StatusObject[statusObjects.size() - statusObjectIndex];
            i = statusObjectIndex;
            statusObjectIndex = statusObjects.size();
        } else {
            res = new StatusObject[statusObjects.size()];
            i = 0;
            statusObjectIndex = statusObjects.size();
        }

        for (int j = 0; i < statusObjects.size(); i++, j++) {
            res[j] = allObjects[i];
        }

        return res;
    }

    /**
     * This method creates the logger. Actually there are 4 types of loggers: 
     * "severe": logs fatal errors i.e. errors that prevent the ARE from functioning
     * "warning": logs errors other than fatal e.g. component errors
     * "info": logs informative messages
     * "fine": logs debugging messages
     * 
     * Each logger by default also logs all messages with severity level higher than its own. 
     * E.g. the warning logger logs warning and severe messages, the info logger logs info, 
     * warning and severe messages etc. The same applies to the consoleHandler, i.e. by 
     * setting its level to info, the console will also print severe and warning messages 
     * along with info messages
     */
    public Logger getLogger() {
        if (logger == null) {
            logger = Logger.getLogger("AstericsLogger");

            FileHandler warningFileHandler, severeFileHandler, infoFileHandler, fineFileHandler;
            ConsoleHandler consoleHandler;
            try {
                //cleanup before starting:
                logger.setUseParentHandlers(false);

                // remove and handlers that will be replaced
                Handler[] handlers = logger.getHandlers();
                for (Handler handler : handlers) {
                    if (handler.getClass() == ConsoleHandler.class)
                        logger.removeHandler(handler);
                }

                File logFolder = new File(System.getProperty(LOG_PATH_PROPERTY, ResourceRegistry.TMP_FOLDER));
                if (!logFolder.exists()) {
                    FileUtils.forceMkdir(logFolder);
                }
                //Create handlers
                severeFileHandler = new FileHandler(new File(logFolder, "asterics_logger_severe.log").getPath(),
                        true);
                warningFileHandler = new FileHandler(new File(logFolder, "asterics_logger_warning.log").getPath(),
                        true);
                infoFileHandler = new FileHandler(new File(logFolder, "asterics_logger.log").getPath(), true);
                fineFileHandler = new FileHandler(new File(logFolder, "asterics_logger_fine.log").getPath(), true);
                consoleHandler = new ConsoleHandler();

                //Set report level of handlers
                severeFileHandler.setLevel(Level.SEVERE);
                warningFileHandler.setLevel(Level.WARNING);
                infoFileHandler.setLevel(Level.INFO);
                fineFileHandler.setLevel(Level.FINE);

                //The consoleHandler prints log messaged to the console. Its 
                //severety level can be adjusted accordingly. 
                String level = getLoggerLevel();
                switch (level) {
                case "INFO":
                    consoleHandler.setLevel(Level.INFO);
                    break;
                case "WARNING":
                    consoleHandler.setLevel(Level.WARNING);
                    break;
                case "FINE":
                    consoleHandler.setLevel(Level.FINE);
                    break;
                case "SEVERE":
                    consoleHandler.setLevel(Level.SEVERE);
                    break;

                default:
                    consoleHandler.setLevel(Level.INFO);
                    break;
                }

                //Add handlers to the logger
                logger.addHandler(warningFileHandler);
                logger.addHandler(severeFileHandler);
                logger.addHandler(infoFileHandler);
                logger.addHandler(fineFileHandler);
                logger.addHandler(consoleHandler);

                //Create formatters for the handlers (optional)
                severeFileHandler.setFormatter(new SimpleFormatter());
                warningFileHandler.setFormatter(new SimpleFormatter());
                infoFileHandler.setFormatter(new SimpleFormatter());
                fineFileHandler.setFormatter(new SimpleFormatter());
                consoleHandler.setFormatter(new SimpleFormatter());

                logger.setLevel(Level.ALL);
                logger.setUseParentHandlers(false);

            } catch (SecurityException e) {
                System.out.println(AstericsErrorHandling.class.getName() + ": Error creating AstericsLogger: "
                        + e.getMessage());
            } catch (IOException e) {
                //logger.warning(this.getClass().getName()+
                //   ": Error creating AstericsLogger: "+e.getMessage());
                System.out.println(AstericsErrorHandling.class.getName() + ": Error creating AstericsLogger: "
                        + e.getMessage());
            }
        }

        return logger;
    }

    private String getLoggerLevel() {
        String lineInput;
        StringTokenizer tkz;
        String consoleLogLevel = "";
        try (BufferedReader in = new BufferedReader(new FileReader(LOGGER_OPTIONS));) {

            while ((lineInput = in.readLine()) != null) {
                tkz = new StringTokenizer(lineInput, ":");
                if (tkz.nextToken().compareToIgnoreCase("error_level") == 0) {
                    consoleLogLevel = tkz.nextToken();
                    break;
                }
            }
            in.close();
        } catch (IOException ioe) {
        }
        consoleLogLevel = System.getProperty(LOG_CONSOLE_LOGLEVEL_PROPERTY, consoleLogLevel);
        return consoleLogLevel;
    }

    private void notifyAREEventListeners(String methodName, String msg) {
        ArrayList<IAREEventListener> listeners = AREServices.instance.getAREEventListners();

        if (methodName.equals("onAreError")) {
            for (IAREEventListener listener : listeners) {
                listener.onAreError(msg);
            }
        }

    }

}