axiom.util.Logger.java Source code

Java tutorial

Introduction

Here is the source code for axiom.util.Logger.java

Source

/*
 * Helma License Notice
 *
 * The contents of this file are subject to the Helma License
 * Version 2.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://adele.helma.org/download/helma/license.txt
 *
 * Copyright 1998-2003 Helma Software. All Rights Reserved.
 *
 * $RCSfile: Logger.java,v $
 * $Author: hannes $
 * $Revision: 1.26 $
 * $Date: 2006/02/09 14:11:08 $
 */

package axiom.util;

import org.apache.commons.logging.Log;

import java.io.*;
import java.text.*;
import java.util.*;

/**
 * A simple logger that writes to a PrintStream such as System.out.
 */
public class Logger implements Log {

    // buffer for log items
    List entries;

    // Writer for log output
    PrintWriter writer;

    // the canonical name for this logger
    String canonicalName;

    // fields for date rendering and caching
    static DateFormat dformat = new SimpleDateFormat("[yyyy/MM/dd HH:mm:ss] ");
    static long dateLastRendered;
    static String dateCache;

    public final static int TRACE = 1;
    public final static int DEBUG = 2;
    public final static int INFO = 3;
    public final static int WARN = 4;
    public final static int ERROR = 5;
    public final static int FATAL = 6;

    int logLevel = INFO;

    /**
     * zero argument constructor, only here for FileLogger subclass
     */
    Logger() {
        init();
    }

    /**
     * Create a logger for a PrintStream, such as System.out.
     */
    protected Logger(PrintStream out) {
        init();
        writer = new PrintWriter(out);
        canonicalName = out.toString();

        // create a synchronized list for log entries since different threads may
        // attempt to modify the list at the same time
        entries = Collections.synchronizedList(new LinkedList());
    }

    /**
     * Get loglevel from System properties
     */
    private void init() {
        String level = System.getProperty("axiom.loglevel");
        if ("trace".equalsIgnoreCase(level))
            logLevel = TRACE;
        else if ("debug".equalsIgnoreCase(level))
            logLevel = DEBUG;
        else if ("info".equalsIgnoreCase(level))
            logLevel = INFO;
        else if ("warn".equalsIgnoreCase(level))
            logLevel = WARN;
        else if ("error".equalsIgnoreCase(level))
            logLevel = ERROR;
        else if ("fatal".equalsIgnoreCase(level))
            logLevel = FATAL;
    }

    /**
     * Get the current log level.
     * @return the current log level
     */
    public int getLogLevel() {
        return logLevel;
    }

    /**
     * Set the log level for this logger.
     * @param logLevel the new log level
     */
    public void setLogLevel(int logLevel) {
        this.logLevel = logLevel;
    }

    /**
     * Return a string representation of this Logger
     */
    public String toString() {
        return new StringBuffer(getClass().getName()).append("[").append(canonicalName).append(",").append(logLevel)
                .append("]").toString();
    }

    /**
     *  Return an object  which identifies  this logger.
     */
    public String getCanonicalName() {
        return canonicalName;
    }

    /**
     * Append a message to the log.
     */
    public void log(String msg) {
        // it's enough to render the date every second
        if ((System.currentTimeMillis() - 1000) > dateLastRendered) {
            renderDate();
        }
        // add a safety net so we don't grow indefinitely even if writer thread
        // has gone. the 2000 entries threshold is somewhat arbitrary. 
        if (entries.size() < 2000) {
            entries.add(dateCache + msg);
        }
    }

    /**
     * This is called by the runner thread to perform actual output.
     */
    void write() {
        if (entries.isEmpty()) {
            return;
        }

        try {
            int l = entries.size();

            for (int i = 0; i < l; i++) {
                String entry = (String) entries.remove(0);
                writer.println(entry);
            }

            writer.flush();

        } catch (Exception x) {
            int size = entries.size();

            if (size > 1000) {
                // more than 1000 entries queued plus exception - something
                // is definitely wrong with this logger. Write a message to std err and
                // discard queued log entries.
                System.err.println("Error writing log file " + this + ": " + x);
                System.err.println("Discarding " + size + " log entries.");
                entries.clear();
            }
        }
    }

    // Pre-render the date to use for log messages. Called about once a second.
    static synchronized void renderDate() {
        Date date = new Date();
        dateCache = dformat.format(date);
        dateLastRendered = date.getTime();
    }

    // methods to implement org.apache.commons.logging.Log interface

    public boolean isTraceEnabled() {
        return logLevel <= TRACE;
    }

    public boolean isDebugEnabled() {
        return logLevel <= DEBUG;
    }

    public boolean isInfoEnabled() {
        return logLevel <= INFO;
    }

    public boolean isWarnEnabled() {
        return logLevel <= WARN;
    }

    public boolean isErrorEnabled() {
        return logLevel <= ERROR;
    }

    public boolean isFatalEnabled() {
        return logLevel <= FATAL;
    }

    public void trace(Object parm1) {
        if (logLevel <= TRACE)
            log(parm1.toString());
    }

    public void trace(Object parm1, Throwable parm2) {
        if (logLevel <= TRACE)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    public void debug(Object parm1) {
        if (logLevel <= DEBUG)
            log(parm1.toString());
    }

    public void debug(Object parm1, Throwable parm2) {
        if (logLevel <= DEBUG)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    public void info(Object parm1) {
        if (logLevel <= INFO)
            log(parm1.toString());
    }

    public void info(Object parm1, Throwable parm2) {
        if (logLevel <= INFO)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    public void warn(Object parm1) {
        if (logLevel <= WARN)
            log(parm1.toString());
    }

    public void warn(Object parm1, Throwable parm2) {
        if (logLevel <= WARN)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    public void error(Object parm1) {
        if (logLevel <= ERROR)
            log(parm1.toString());
    }

    public void error(Object parm1, Throwable parm2) {
        if (logLevel <= ERROR)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    public void fatal(Object parm1) {
        if (logLevel <= FATAL)
            log(parm1.toString());
    }

    public void fatal(Object parm1, Throwable parm2) {
        if (logLevel <= FATAL)
            log(parm1.toString() + "\n" + getStackTrace(parm2));
    }

    // utility method to get the stack trace from a Throwable as string
    public static String getStackTrace(Throwable t) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter writer = new PrintWriter(stringWriter);
        t.printStackTrace(writer);
        writer.close();
        return stringWriter.toString();
    }

}