// --------------------------------------------------------------------------- // 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 mLayout = null; private static Appender mAppender = null; private static Level mLogLevel = Level.DEBUG; private static String[] mSearchPaths = 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 mFilename = "jWebSocket.log"; /** * Pattern for jWebSocket log file. */ private static String mPattern = "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p - %C{1}: %m%n"; /** * buffer size if write cache for logs is activated (recommended) * buffer size = 0 means no write cache. */ private static int mBuffersize = 8096; // 8K is log4j default private static int mLogTarget = CONSOLE; // ROLLING_FILE; private static String getLogsFolderPath(String aFileName, 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 + aFileName; } 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 + aFileName; } } 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 (mLayout == null) { mLayout = new PatternLayout(); mLayout.setConversionPattern(mPattern); } if (mAppender == null) { String logsPath = getLogsFolderPath(mFilename, mSearchPaths); if (ROLLING_FILE == mLogTarget && logsPath != null) { try { RollingFileAppender lRFA = new RollingFileAppender(mLayout, logsPath, true /* append, don't truncate */); lRFA.setBufferedIO(mBuffersize > 0); lRFA.setImmediateFlush(true); if (mBuffersize > 0) { lRFA.setBufferSize(mBuffersize); } lRFA.setEncoding("UTF-8"); mAppender = lRFA; } catch (IOException ex) { mAppender = new ConsoleAppender(mLayout); } } else if (SINGLE_FILE == mLogTarget && logsPath != null) { try { FileAppender lFA = new FileAppender(mLayout, logsPath, true /* append, don't truncate */); lFA.setBufferedIO(mBuffersize > 0); lFA.setImmediateFlush(true); if (mBuffersize > 0) { lFA.setBufferSize(mBuffersize); } lFA.setEncoding("UTF-8"); mAppender = lFA; } catch (IOException ex) { mAppender = new ConsoleAppender(mLayout); } } else { mAppender = new ConsoleAppender(mLayout); if (CONSOLE != mLogTarget) { 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) { mSearchPaths = aSearchPaths; if (aLogLevel != null) { mLogLevel = Level.toLevel(aLogLevel); } if (aLogTarget != null) { if ("console".equals(aLogTarget)) { mLogTarget = Logging.CONSOLE; } else if ("singlefile".equals(aLogTarget)) { mLogTarget = Logging.SINGLE_FILE; } else if ("rollingfile".equals(aLogTarget)) { mLogTarget = Logging.ROLLING_FILE; } } if (aFilename != null) { mFilename = aFilename; } if (aPattern != null) { mPattern = aPattern; } if (aBuffersize != null) { mBuffersize = 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); } } public static boolean isInitialized() { return (mAppender != null); } /** * 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 (mAppender != null) { // System.out.println("Closing logs..."); // properly close log files if such mAppender.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(mAppender); // don't inherit global log4j settings, we intend to configure that // in our own jWebSocket.xml config file. logger.setAdditivity(false); logger.setLevel(mLogLevel); return logger; } }