/*
This file is part of Subsonic.
Subsonic 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 3 of the License, or
(at your option) any later version.
Subsonic 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 Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus
*/
package net.sourceforge.subsonic;
import net.sourceforge.subsonic.service.*;
import net.sourceforge.subsonic.util.*;
import org.apache.commons.lang.exception.*;
import org.eclipse.jetty.util.log.Log;
import java.io.*;
import java.text.*;
import java.util.*;
import net.sourceforge.subsonic.domain.LogLevel;
/**
* Logger implementation which logs to SUBSONIC_HOME/madsonic.log. <br/>
* Note: Third party logging libraries (such as log4j and Commons logging) are
* intentionally not used. These libraries causes a lot of headache when
* deploying to some application servers (for instance Jetty and JBoss).
*
* @author Sindre Mehus
* @version $Revision: 1.1 $ $Date: 2005/05/09 19:58:26 $
*/
public class Logger {
private String LogfileLevel;
private String category;
private static List<Entry> entries = Collections.synchronizedList(new BoundedList<Entry>(512));
private static PrintWriter writer;
/**
* Creates a logger for the given class.
*
* @param clazz
* The class.
* @return A logger for the class.
*/
public static Logger getLogger(Class clazz) {
return new Logger(clazz.getName());
}
/**
* Creates a logger for the given namee.
*
* @param name
* The name.
* @return A logger for the name.
*/
public static Logger getLogger(String name) {
return new Logger(name);
}
/**
* Returns the last few log entries.
*
* @return The last few log entries.
*/
public static Entry[] getLatestLogEntries(boolean reverse) {
Entry[] LogEntries = entries.toArray(new Entry[0]);
if (reverse) {
Collections.reverse(Arrays.asList(LogEntries));
}
return LogEntries;
}
private Logger(String name) {
int lastDot = name.lastIndexOf('.');
if (lastDot == -1) {
category = name;
} else {
category = name.substring(lastDot + 1);
}
}
public void test(Object message, Throwable error) {
add(Level.TEST, message, error);
}
/**
* Logs a debug message.
*
* @param message
* The log message.
*/
public void debug(Object message) {
debug(message, null);
}
/**
* Logs a debug message.
*
* @param message
* The message.
* @param error
* The optional exception.
*/
public void debug(Object message, Throwable error) {
add(Level.DEBUG, message, error);
}
/**
* Logs an info message.
*
* @param message
* The message.
*/
public void info(Object message) {
info(message, null);
}
/**
* Logs an info message.
*
* @param message
* The message.
* @param error
* The optional exception.
*/
public void info(Object message, Throwable error) {
add(Level.INFO, message, error);
}
/**
* Logs a warning message.
*
* @param message
* The message.
*/
public void warn(Object message) {
warn(message, null);
}
/**
* Logs a warning message.
*
* @param message
* The message.
* @param error
* The optional exception.
*/
public void warn(Object message, Throwable error) {
add(Level.WARN, message, error);
}
/**
* Logs an error message.
*
* @param message
* The message.
*/
public void error(Object message) {
error(message, null);
}
/**
* Logs an error message.
*
* @param message
* The message.
* @param error
* The optional exception.
*/
public void error(Object message, Throwable error) {
add(Level.ERROR, message, error);
}
private void add(Level level, Object message, Throwable error) {
LogLevel logLevel = LogLevel.valueOf(SettingsService.getLogfileLevel());
switch (logLevel) {
case OFF:
break;
case ERROR:
if(level.toString().contains("ERROR")) {
addEntry(level, message, error);
}
break;
case WARN:
if(level.toString().contains("ERROR")
|| level.toString().contains("WARN")) {
addEntry(level, message, error);
}
break;
case INFO:
if(level.toString().contains("ERROR")
|| level.toString().contains("WARN")
|| level.toString().contains("INFO")) {
addEntry(level, message, error);
}
break;
case DEBUG:
if(level.toString().contains("ERROR")
|| level.toString().contains("WARN")
|| level.toString().contains("INFO")
|| level.toString().contains("DEBUG")) {
addEntry(level, message, error);
}
break;
case TEST:
if(level.toString().contains("ERROR")
|| level.toString().contains("WARN")
|| level.toString().contains("DEBUG")
|| level.toString().contains("TEST")) {
addEntry(level, message, error);
}
break;
}
}
private void addEntry(Level level, Object message, Throwable error) {
Entry entry = new Entry(category, level, message, error);
try {
getPrintWriter().println(entry);
} catch (IOException x) {
System.err.println("Failed to write to madsonic.log.");
x.printStackTrace();
}
entries.add(entry);
}
private static synchronized PrintWriter getPrintWriter() throws IOException {
if (writer == null) {
writer = new PrintWriter(new FileWriter(getLogFile(), false), true);
}
return writer;
}
public static File getLogFile() {
File subsonicHome = SettingsService.getSubsonicHome();
return new File(subsonicHome, "madsonic.log");
}
public String getLogfileLevel() {
return LogfileLevel;
}
public void setLogfileLevel(String logfileLevel) {
LogfileLevel = logfileLevel;
}
/**
* Log level.
*/
public enum Level {
DEBUG, INFO, WARN, ERROR, TEST
}
/**
* Log entry.
*/
public static class Entry {
private String category;
private Date date;
private Level level;
private Object message;
private Throwable error;
private static final DateFormat DATE_FORMAT = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss,SSS");
public Entry(String category, Level level, Object message,
Throwable error) {
this.date = new Date();
this.category = category;
this.level = level;
this.message = message;
this.error = error;
}
public String getCategory() {
return category;
}
public Date getDate() {
return date;
}
public Level getLevel() {
return level;
}
public Object getMessage() {
return message;
}
public Throwable getError() {
return error;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append('[').append(DATE_FORMAT.format(date)).append("] ");
buf.append(level).append(' ');
buf.append(category).append(" - ");
buf.append(message);
if (error != null) {
buf.append('\n')
.append(ExceptionUtils.getFullStackTrace(error));
}
return buf.toString();
}
}
}