// ---------------------------------------------------------------------------
// jWebSocket - Shared Logging Support
// Copyright (c) 2010 Alexander Schulze, Innotrade GmbH
// ---------------------------------------------------------------------------
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 3 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 Lesser General Public License for
// more details.
// You should have received a copy of the GNU Lesser General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>.
// ---------------------------------------------------------------------------
package org.jwebsocket.logging;
import java.io.IOException;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.RollingFileAppender;
import org.jwebsocket.config.LoggingConfig;
/**
* Provides the common used jWebSocket logging support based on
* Apache's log4j.
* @author aschulze
*/
public class Logging {
private static PatternLayout layout = null;
private static Appender appender = null;
private static Level logLevel = Level.DEBUG;
private static String[] searchPaths = null;
/**
* Log output is send to the console (stdout).
*/
public final static int CONSOLE = 0;
/**
* Log output is send to a rolling file.
*/
public final static int ROLLING_FILE = 1;
/**
* Log output is send to a single file.
*/
public final static int SINGLE_FILE = 2;
/**
* Name of jWebSocket log file.
*/
private static String filename = "jWebSocket.log";
/**
* Pattern for jWebSocket log file.
*/
private static String pattern = "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %C{1}: %m%n";
/**
* Buffersize if write cache for logs is activated (recommended)
* Buffersize = 0 means no write cache.
*/
private static int buffersize = 8096; // 8K is log4j default
private static int logTarget = CONSOLE; // ROLLING_FILE;
private static String getLogsFolderPath(String fileName, String[] aPaths) {
// try to obtain JWEBSOCKET_HOME environment variable
String lWebSocketHome = System.getenv("JWEBSOCKET_HOME");
String lFileSep = System.getProperty("file.separator");
String lWebSocketLogs = null;
if (lWebSocketHome != null) {
// append trailing slash if needed
if (!lWebSocketHome.endsWith(lFileSep)) {
lWebSocketHome += lFileSep;
}
// logs are located in %JWEBSOCKET_HOME%/logs
lWebSocketLogs = lWebSocketHome + "logs" + lFileSep + fileName;
}
if (lWebSocketLogs == null) {
// try to obtain CATALINA_HOME environment variable
lWebSocketHome = System.getenv("CATALINA_HOME");
if (lWebSocketHome != null) {
// append trailing slash if needed
if (!lWebSocketHome.endsWith(lFileSep)) {
lWebSocketHome += lFileSep;
}
// logs are located in %CATALINA_HOME%/logs
lWebSocketLogs = lWebSocketHome + "logs" + lFileSep + fileName;
}
}
return lWebSocketLogs;
}
// TODO: Load the conversion pattern and the logging target from a configuration file (e.g. jWebSocket.xml)
/**
* Initializes the Apache log4j system to produce the desired logging
* output.
* @param aLogLevel one of the values TRACE, DEBUG, INFO, WARN, ERROR or FATAL.
*
*/
private static void checkLogAppender() {
if (layout == null) {
layout = new PatternLayout();
layout.setConversionPattern(pattern);
}
if (appender == null) {
String logsPath = getLogsFolderPath(filename, searchPaths);
if (ROLLING_FILE == logTarget && logsPath != null) {
try {
RollingFileAppender lRFA = new RollingFileAppender(layout,
logsPath, true /* append, don't truncate */);
lRFA.setBufferedIO(buffersize > 0);
lRFA.setImmediateFlush(true);
if (buffersize > 0) {
lRFA.setBufferSize(buffersize);
}
lRFA.setEncoding("UTF-8");
appender = lRFA;
} catch (IOException ex) {
appender = new ConsoleAppender(layout);
}
} else if (SINGLE_FILE == logTarget && logsPath != null) {
try {
FileAppender lFA = new FileAppender(layout, logsPath,
true /* append, don't truncate */);
lFA.setBufferedIO(buffersize > 0);
lFA.setImmediateFlush(true);
if (buffersize > 0) {
lFA.setBufferSize(buffersize);
}
lFA.setEncoding("UTF-8");
appender = lFA;
} catch (IOException ex) {
appender = new ConsoleAppender(layout);
}
} else {
appender = new ConsoleAppender(layout);
if (CONSOLE != logTarget) {
System.out.println("JWEBSOCKET_HOME"
+ " variable not set or invalid configuration,"
+ " using console output for log file.");
}
}
}
}
/**
* Initializes the jWebSocket logging system with the given log level.
* All subsequently instantiated class specific loggers will use this
* setting.
* @param aLogLevel
*/
public static void initLogs(String aLogLevel, String aLogTarget,
String aFilename, String aPattern, Integer aBuffersize,
String[] aSearchPaths) {
searchPaths = aSearchPaths;
if (aLogLevel != null) {
logLevel = Level.toLevel(aLogLevel);
}
if (aLogTarget != null) {
if ("console".equals(aLogTarget)) {
logTarget = Logging.CONSOLE;
} else if ("singlefile".equals(aLogTarget)) {
logTarget = Logging.SINGLE_FILE;
} else if ("rollingfile".equals(aLogTarget)) {
logTarget = Logging.ROLLING_FILE;
}
}
if (aFilename != null) {
filename = aFilename;
}
if (aPattern != null) {
pattern = aPattern;
}
if (aBuffersize != null) {
buffersize = aBuffersize;
}
checkLogAppender();
}
public static void initLogs(LoggingConfig aLoggingConfig, String[] aSearchPaths) {
if (aLoggingConfig != null) {
initLogs(
aLoggingConfig.getLevel(),
aLoggingConfig.getAppender(),
aLoggingConfig.getFilename(),
aLoggingConfig.getPattern(),
aLoggingConfig.getBufferSize(),
aSearchPaths);
}
}
/**
* closes the log file. Take care that no further lines are appended
* to the logs after it has been closed!
*/
public static void exitLogs() {
if (appender != null) {
// System.out.println("Closing logs...");
// properly close log files if such
appender.close();
// System.out.println("Logs closed.");
}
}
/**
* Returns a logger for a certain class by using the jWebSocket settings
* for logging and ignoring inherited log4j settings.
* @param aClass
* @return Logger the new logger for the given class.
*/
public static Logger getLogger(Class aClass) {
checkLogAppender();
Logger logger = Logger.getLogger(aClass);
logger.addAppender(appender);
// don't inherit global log4j settings, we intend to configure that
// in our own jWebSocket.xml config file.
logger.setAdditivity(false);
logger.setLevel(logLevel);
return logger;
}
}