/* Copyright (C) 2009 Diego Darriba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package es.uvigo.darwin.prottest.util.logging; import es.uvigo.darwin.prottest.util.exception.ProtTestInternalException; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.StreamHandler; @SuppressWarnings("rawtypes") public class ProtTestLogger { public static final String DEFAULT_LOGGER_NAME = "default"; public static final Level DEFAULT_LEVEL = Level.INFO; private static HashMap<String, ProtTestLogger> loggers; static { loggers = new HashMap<String, ProtTestLogger>(); ProtTestLogger defaultLogger = new ProtTestLogger(DEFAULT_LOGGER_NAME); loggers.put(DEFAULT_LOGGER_NAME, defaultLogger); } private String loggerName; private Level loggerLevel; private List<Handler> handlers; private Handler stdHandler; private Handler lowLevelHandler = null; public static ProtTestLogger getLogger(String loggerName, boolean force) { if (!loggers.containsKey(loggerName)) { if (force) loggers.put(loggerName, new ProtTestLogger(loggerName)); else return null; } return loggers.get(loggerName); } public static boolean exists(Class classLogger) { return getLogger(classLogger.getName(), false) != null; } public ProtTestLogger(String loggerName) { this.loggerName = loggerName; if (loggers.containsKey(loggerName)) throw new ProtTestInternalException("ProtTestLogger with name " + loggerName + " already exists. " + " Use getLogger() instead"); this.loggerLevel = Level.ALL; // Add standard output handler this.handlers = new ArrayList<Handler>(); stdHandler = new StreamHandler(System.out, new ProtTestLogFormatter()); stdHandler.setLevel(Level.OFF); handlers.add(stdHandler); } public static ProtTestLogger getDefaultLogger() { return getLogger(DEFAULT_LOGGER_NAME, true); } /** * Check if a message of the given level would actually be logged by this * logger. This check is based on the Loggers effective level, which may be * inherited from its parent. * * @param level * a message logging level * @return true if the given message level is currently being logged. */ public boolean isLoggable(Level level) { if (level.intValue() < loggerLevel.intValue() || loggerLevel.intValue() == Level.OFF.intValue()) { return false; } return true; } public void addHandler(Handler handler) { if (handler == null) { throw new NullPointerException(); } this.handlers.add(handler); } public void addHandler(Handler[] newHandlers) { for (Handler handler : newHandlers) { if (handler == null) { throw new NullPointerException(); } if (!handlers.contains(handler)) this.handlers.add(handler); } } public Handler addHandler(OutputStream out) { return addHandler(out, DEFAULT_LEVEL); } public Handler addHandler(OutputStream out, Level level) { if (out == null) { throw new NullPointerException(); } Handler handler = new StreamHandler(out, new ProtTestLogFormatter()); handler.setLevel(level); this.handlers.add(handler); return handler; } public Handler addHandler(Writer out) { return addHandler(out, DEFAULT_LEVEL); } public Handler addHandler(final Writer out, Level level) { if (out == null) { throw new NullPointerException(); } Handler handler = new StreamHandler( new OutputStream() { protected Writer _writer = out; protected String _encoding; private byte[] _buf=new byte[1]; @Override public void close() throws IOException { _writer.close(); _writer=null; _encoding=null; } @Override public void flush() throws IOException { _writer.flush(); } @Override public void write(byte[] b) throws IOException { if (_encoding==null) _writer.write(new String(b)); else _writer.write(new String(b,_encoding)); } @Override public void write(byte[] b, int off, int len) throws IOException { if (_encoding==null) _writer.write(new String(b,off,len)); else _writer.write(new String(b,off,len,_encoding)); } public synchronized void write(int b) throws IOException { _buf[0]=(byte)b; write(_buf); } }, new ProtTestLogFormatter()); handler.setLevel(level); this.handlers.add(handler); return handler; } public Handler addLowLevelHandler(final Writer out) { if (out == null) { throw new NullPointerException(); } Handler handler = new StreamHandler(new OutputStream() { protected Writer _writer = out; protected String _encoding; private byte[] _buf=new byte[1]; @Override public void close() throws IOException { _writer.close(); _writer=null; _encoding=null; } @Override public void flush() throws IOException { _writer.flush(); } @Override public void write(byte[] b) throws IOException { if (_encoding==null) _writer.write(new String(b)); else _writer.write(new String(b,_encoding)); } @Override public void write(byte[] b, int off, int len) throws IOException { if (_encoding==null) _writer.write(new String(b,off,len)); else _writer.write(new String(b,off,len,_encoding)); } public synchronized void write(int b) throws IOException { _buf[0]=(byte)b; write(_buf); } }, new ProtTestLogFormatter()); handler.setLevel(Level.ALL); lowLevelHandler = handler; return handler; } public Handler getLowLevelHandler() { return lowLevelHandler; } public boolean removeHandler(Handler handler) { return this.handlers.remove(handler); } public Handler[] getHandlers() { return handlers.toArray(new Handler[0]); } public void setStdHandlerLevel(Level newLevel) { if (newLevel == null) { throw new NullPointerException(); } stdHandler.setLevel(newLevel); } public Level getStdHandlerLevel() { return stdHandler.getLevel(); } public void setLevel(Level newLevel) { if (newLevel == null) { throw new NullPointerException(); } loggerLevel = newLevel; } public Level getLevel() { return loggerLevel; } public void info(String text) { log(Level.INFO, text); } public void warning(String text) { log(Level.WARNING, text); } public void config(String text) { log(Level.CONFIG, text); } public void severe(String text) { log(Level.SEVERE, text); } public void fine(String text) { log(Level.FINE, text); } public void finer(String text) { log(Level.FINER, text); } public void finest(String text) { log(Level.FINEST, text); } public void infoln(String text) { log(Level.INFO, text + "\n"); flush(); } public void warningln(String text) { log(Level.WARNING, text + "\n"); flush(); } public void configln(String text) { log(Level.CONFIG, text + "\n"); flush(); } public void severeln(String text) { log(Level.SEVERE, text + "\n"); flush(); } public void fineln(String text) { log(Level.FINE, text + "\n"); flush(); } public void finerln(String text) { log(Level.FINER, text + "\n"); flush(); } public void finestln(String text) { log(Level.FINEST, text + "\n"); flush(); } public static void info(String text, Class loggingClass) { log(Level.INFO, text, loggingClass); } public static void warning(String text, Class loggingClass) { log(Level.WARNING, text, loggingClass); } public static void config(String text, Class loggingClass) { log(Level.CONFIG, text, loggingClass); } public static void severe(String text, Class loggingClass) { log(Level.SEVERE, text, loggingClass); } public static void fine(String text, Class loggingClass) { log(Level.FINE, text, loggingClass); } public static void finer(String text, Class loggingClass) { log(Level.FINER, text, loggingClass); } public static void finest(String text, Class loggingClass) { log(Level.FINEST, text, loggingClass); } public static void infoln(String text, Class loggingClass) { log(Level.INFO, text + "\n", loggingClass); flush(loggingClass); } public static void warningln(String text, Class loggingClass) { log(Level.WARNING, text + "\n", loggingClass); flush(loggingClass); } public static void configln(String text, Class loggingClass) { log(Level.CONFIG, text + "\n", loggingClass); flush(loggingClass); } public static void severeln(String text, Class loggingClass) { log(Level.SEVERE, text + "\n", loggingClass); flush(loggingClass); } public static void fineln(String text, Class loggingClass) { log(Level.FINE, text + "\n", loggingClass); flush(loggingClass); } public static void finerln(String text, Class loggingClass) { log(Level.FINER, text + "\n", loggingClass); flush(loggingClass); } public static void finestln(String text, Class loggingClass) { log(Level.FINEST, text + "\n", loggingClass); flush(loggingClass); } public static void log(Level level, String text, Class loggingClass) { // default logging + class logging getDefaultLogger().log(level, text); if (exists(loggingClass)) getLogger(loggingClass.getName(), false).log(level, text); } public void log(Level level, String text) { log(new LogRecord(level, text)); } public void log(LogRecord lr) { if (lr.getLevel().intValue() > loggerLevel.intValue() && loggerLevel.intValue() != Level.OFF.intValue()) { for (Handler handler : handlers) handler.publish(lr); } } public static void lowLevelLog(String text) { if (getDefaultLogger().lowLevelHandler != null) { LogRecord lr = new LogRecord(Level.INFO, text + "\n"); getDefaultLogger().lowLevelHandler.publish(lr); getDefaultLogger().lowLevelHandler.flush(); } } public void flush() { for (Handler handler : handlers) handler.flush(); } public static void flush(Class loggingClass) { getDefaultLogger().flush(); if (exists(loggingClass)) getLogger(loggingClass.getName(), false).flush(); } }