package se.nicklasgavelin.log;
import com.intel.bluetooth.DebugLog;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
import se.nicklasgavelin.configuration.ProjectProperties;
/**
* Manages the logging of the application.
* If the log4j logging class can't be found the logging will be
* disabled by default. Otherwise the logging will follow
* the settings in the Configuration class
*
* @author Nicklas Gavelin, nicklas.gavelin@gmail.com, LuleƄ University of
* Technology
* @version 2.1
*
* Notice: Based on the debug logger in Bluecove
*/
public class Logging
{
private static final Logging log = new Logging();
private static boolean initialized = false;
private static Collection<Appender> logAppenders;
private static boolean log4exists = true;
private static final String log4logger = "site.nicklas.log.Log4JLogger";
private static final String from = Logging.class.getName();
private static final Collection<String> fromCollection = new ArrayList<String>();
private static final Logger logger = Logger.getLogger( ProjectProperties.getInstance().getLoggerName() );// Configuration.loggerName
// );
static
{
fromCollection.add( from );
}
/**
* Different debug levels,
* mirrors that of log4j levels
*/
public static enum Level
{
/**
* Debugging
*/
DEBUG( java.util.logging.Level.FINE ),
/**
* Information
*/
INFO( java.util.logging.Level.FINEST ),
/**
* Warnings
*/
WARN( java.util.logging.Level.WARNING ),
/**
* Errors
*/
ERROR( java.util.logging.Level.SEVERE ),
/**
* Fatal errors
*/
FATAL( java.util.logging.Level.SEVERE );
private static int nextVal = 0;
private int val;
private java.util.logging.Level l;
private Level( java.util.logging.Level _l )
{
this.initialize();
this.l = _l;
}
private void initialize()
{
this.val = Level.nextVal++;
}
protected int getValue()
{
return this.val;
}
protected java.util.logging.Level getLevel()
{
return this.l;
}
}
/**
* Create a logging object
*/
private Logging()
{
}
/**
* Returns the log instance
*
* @return The log instance
*/
public static Logging getInstance()
{
return log;
}
/*
* ************************************
* CLASSES
*/
/**
* Log appender interface
*/
protected static interface Appender
{
/**
* Log message
*
* @param l The log level
* @param message The log message
* @param t Throwable object to log
*/
public void log( Level l, String message, Throwable t );
public boolean isLogEnabled( Level l );
}
/*
* *******************
* INITIALIZE
*/
/**
* Initialize the debugger
*/
private static void initialize()
{
// Check if we have initialized earlier
if( initialized )
return;
// Set initialized
initialized = true;
logAppenders = new ArrayList<Appender>();
// Check if we can use log4j as debugger
try
{
Appender log4jAppender = (Appender) Class.forName( Logging.log4logger ).newInstance();
add( log4jAppender );
// System.out.println( "[" + Logging.class.getCanonicalName() +
// "] Redirecting log to log4j (" + Configuration.debugEnabled + ")" );
}
catch( Throwable e )
{
log4exists = false;
setLevel();
Logging.debug( "[" + Logging.class.getCanonicalName() + "] Turning off debug as no log4j instance could be created" );
}
}
private static void setLevel()
{
// Fetch project settings
ProjectProperties pp = ProjectProperties.getInstance();
Logger topLogger = java.util.logging.Logger.getLogger( pp.getLoggerName() );// Configuration.loggerName
// );
topLogger.setLevel( pp.getDebugLevel().getLevel() ); // Configuration.debugLevel.getLevel()
// );
// Set bluecove log status
DebugLog.setDebugEnabled( pp.getBluecoveDebugEnabled() );
// Handler for console (reuse it if it already exists)
Handler consoleHandler = null;
// see if there is already a console handler
for( Handler handler : topLogger.getHandlers() )
{
if( handler instanceof ConsoleHandler )
{
// found the console handler
consoleHandler = handler;
break;
}
}
if( consoleHandler == null )
{
// there was no console handler found, create a new one
consoleHandler = new ConsoleHandler();
topLogger.addHandler( consoleHandler );
}
// set the console handler to fine:
consoleHandler.setLevel( pp.getDebugLevel().getLevel() );// Configuration.debugLevel.getLevel()
// );
}
/**
* Enable or disable logging manually
*
* @param enabled True to enable, false to disable
*/
public static void setDebugEnabled( boolean enabled )
{
initialize();
// Configuration.debugEnabled = enabled;
ProjectProperties.getInstance().setDebugEnabled( enabled );
}
/**
* Call all log appenders
*
* @param l The log level
* @param msg The message
* @param t Any throwable to log
*/
private static void callAppenders( Level l, String msg, Throwable t )
{
// Perform initialization if not already done
initialize();
ProjectProperties pp = ProjectProperties.getInstance();
// Check if we have debug enabled or if the level is fatal
if( ( !pp.getDebugEnabled() && !l.equals( Level.FATAL ) ) )
return;
// Check if we want the messages of this level to be logged
if( l.getValue() < pp.getDebugLevel().getValue() )
return;
if( !log4exists )
{
// Native debug
nativeDebug( l, msg, t );
}
else
{
Iterator<Appender> i = logAppenders.iterator();
while( i.hasNext() )
{
Appender la = i.next();
la.log( l, msg, t );
}
}
}
/**
* Debug method that is run instead of appenders if no appenders
* could be found
*
* @param l The level of the message
* @param msg The message
* @param t The throwable object or null
*/
private static void nativeDebug( Level l, String msg, Throwable t )
{
// Fetch location for the message
UtilsJavaSE.StackTraceLocation s = UtilsJavaSE.getLocation( fromCollection );
logger.setLevel( ProjectProperties.getInstance().getDebugLevel().getLevel() );
Logging.logger.logp( l.getLevel(), s.className, s.methodName, "\t" + msg + "\n", t );
}
// /**
// * Returns the location from which the message was created
// *
// * @param s The stack location
// *
// * @return The location or ""
// */
// private static String fromLocation( UtilsJavaSE.StackTraceLocation s )
// {
// if( s == null )
// return "";
// return s.className + "." + s.methodName + "(" + s.fileName + ":" + s.lineNumber + ")";
// }
/**
* Add an appender to call when running callAppenders
*
* @param loggerAppender The appender to add
*/
private static void add( Appender loggerAppender )
{
logAppenders.add( loggerAppender );
}
/*
* ***********************************
* LOGGING
*/
/**
* Print a debug message
*
* @param msg The debug message
*/
public static void debug( String msg )
{
callAppenders( Level.DEBUG, msg, null );
}
/**
* Print a debug message with a throwable object
*
* @param msg The message to log
* @param t The throwable object to log
*/
public static void debug( String msg, Throwable t )
{
callAppenders( Level.DEBUG, msg, t );
}
/**
* Print a debug message with a specific extra value
*
* @param msg The message to log
* @param v The value to log
*/
public static void debug( String msg, String v )
{
callAppenders( Level.DEBUG, msg + " " + v, null );
}
/**
* Print a debug message with a specific object
*
* @param msg The message to log
* @param o The object to log
*/
public static void debug( String msg, Object o )
{
callAppenders( Level.DEBUG, msg + " " + o.toString(), null );
}
/**
* Print an error message
*
* @param msg The error message
*/
public static void error( String msg )
{
callAppenders( Level.ERROR, msg, null );
}
/**
* Print an error message with a specific throwable object
*
* @param msg The message to log
* @param t The throwable object to log
*/
public static void error( String msg, Throwable t )
{
callAppenders( Level.ERROR, msg, t );
}
/**
* Print an error message and a specific value
*
* @param msg The message to log
* @param v The value to log
*/
public static void error( String msg, String v )
{
callAppenders( Level.ERROR, msg + " " + v, null );
}
/**
* Print an error message and a specific object
*
* @param msg The message to log
* @param o The object to log
*/
public static void error( String msg, Object o )
{
callAppenders( Level.ERROR, msg + " " + o.toString(), null );
}
/**
* Print an info message
*
* @param msg The info message
*/
public static void info( String msg )
{
callAppenders( Level.INFO, msg, null );
}
/**
* Print a specific info message and a throwable object
*
* @param msg The message to log
* @param t The throwable object
*/
public static void info( String msg, Throwable t )
{
callAppenders( Level.INFO, msg, t );
}
/**
* Print a specific info message and a value
*
* @param msg The message to log
* @param v The value to log
*/
public static void info( String msg, String v )
{
callAppenders( Level.INFO, msg + " " + v, null );
}
/**
* Log a warning message with an object
*
* @param msg The warning message
* @param o The object to log
*/
public static void info( String msg, Object o )
{
callAppenders( Level.INFO, msg + " " + o.toString(), null );
}
/**
* Log a warning message
*
* @param msg The warning message
*/
public static void warn( String msg )
{
callAppenders( Level.WARN, msg, null );
}
/**
* Log a warning message and a throwable object
*
* @param msg The warning message
* @param t The throwable object
*/
public static void warn( String msg, Throwable t )
{
callAppenders( Level.WARN, msg, t );
}
/**
* Log a warning message with a value
*
* @param msg The warning message
* @param v The value to log
*/
public static void warn( String msg, String v )
{
callAppenders( Level.WARN, msg + " " + v, null );
}
/**
* Log a warning message with an object
*
* @param msg The warning message
* @param o The object to log
*/
public static void warn( String msg, Object o )
{
callAppenders( Level.WARN, msg + " " + o.toString(), null );
}
/**
* Log a fatal message
*
* @param msg The fatal message
*/
public static void fatal( String msg )
{
callAppenders( Level.FATAL, msg, null );
}
/**
* Log a fatal message with a value
*
* @param msg The fatal message
* @param v The value to log
*/
public static void fatal( String msg, String v )
{
callAppenders( Level.FATAL, msg + " " + v, null );
}
/**
* Log a fatal message with a throwable object
*
* @param msg The fatal message
* @param e Throwable to log
*/
public static void fatal( String msg, Throwable e )
{
callAppenders( Level.FATAL, msg, e );
}
/**
* Log a fatal message with an object
*
* @param msg The fatal message
* @param o The object to log
*/
public static void fatal( String msg, Object o )
{
callAppenders( Level.FATAL, msg + " " + o.toString(), null );
}
}