/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) 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. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.core.utils; import org.apache.log4j.Logger; /** * This class is designed to work with log4j based on threads and not class * names. This allows all the classes invoked by a thread to log their messages * to the same location. This is particularly useful when messages from share * common code should be associated with a higher level <EM>service</EM> or * <EM>application</EM>. * * @author <A HREF="mailto:weave@oculan.com">Brian Weaver </A> * @author <A HREF="http://www.opennms.org/">OpenNMS </A> */ public class ThreadCategory { public enum Level { FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL, OFF } private static final String DEFAULT_CATEGORY = "UNCATEGORIZED"; private String messagePrefix = null; private final Logger m_delegate; /** * This thread local variable is used to store the category that threads * (and their children) should use to log information. If a thread has a set * category and then starts a new thread, the new thread will inherit the * category of the parent thread. */ private static InheritableThreadLocal<String> s_threadCategory = new InheritableThreadLocal<String>(); /** * This constructor creates a new ThreadCategory instance. * * @param name * The name of the category */ protected ThreadCategory(String name) { m_delegate = Logger.getLogger(name); } /** * This method is used to get the category instance associated with the * thread. If the category for the thread has not been set then the passed * class is used to find the appropriate category. If a category is found * for the thread group then it is returned to the caller. * * @param c * The class used to find the category if it was not set. * @return The instance for the thread. * @see java.lang.InheritableThreadLocal */ public static ThreadCategory getInstance(Class<?> c) { return getLog4jInstance(c); } /** * <p>getLog4jInstance</p> * * @param c a {@link java.lang.Class} object. * @return a {@link org.opennms.core.utils.ThreadCategory} object. */ public static ThreadCategory getLog4jInstance(Class<?> c) { return getLog4jInstance(c.getName()); } /** * <p>getSlf4jInstance</p> * * @param c a {@link java.lang.Class} object. * @return a {@link org.slf4j.Logger} object. */ public static org.slf4j.Logger getSlf4jInstance(Class<?> c) { return getSlf4jInstance(c.getName()); } /** * This method is used to get the category instance associated with the * thread. If the category for the thread has not been set then the passed * name is used to find the appropriate category. If a category is found for * the thread group then it is returned to the caller. * * @param cname * The name used to find the category if it was not set. * @return The instance for the thread. * @see java.lang.InheritableThreadLocal */ public static ThreadCategory getInstance(String cname) { return getLog4jInstance(cname); } /** * <p>getLog4jInstance</p> * * @param cname a {@link java.lang.String} object. * @return a {@link org.opennms.core.utils.ThreadCategory} object. */ public static ThreadCategory getLog4jInstance(String cname) { String prefix = getPrefix(); if ((prefix != null) && !prefix.equals("")) { return new ThreadCategory(prefix + "." + cname); } else { return new ThreadCategory(cname); } } /** * <p>getSlf4jInstance</p> * * @param cname a {@link java.lang.String} object. * @return a {@link org.slf4j.Logger} object. */ public static org.slf4j.Logger getSlf4jInstance(String cname) { String prefix = getPrefix(); if ((prefix != null) && !prefix.equals("")) { return org.slf4j.LoggerFactory.getLogger(prefix + "." + cname); } else { return org.slf4j.LoggerFactory.getLogger(cname); } } /** * This method is used to get the category instance associated with the * thread. If the instance has not been set then a default category is * returned to the caller. * * @return The instance for the thread, null if it is not set. * @see java.lang.InheritableThreadLocal */ public static ThreadCategory getInstance() { return getLog4jInstance(); } /** * <p>getLog4jInstance</p> * * @return a {@link org.opennms.core.utils.ThreadCategory} object. */ public static ThreadCategory getLog4jInstance() { String prefix = getPrefix(); if (prefix != null) { return new ThreadCategory(prefix); } else { /* * Use the default category anywhere that ThreadCategory * is instantiated without a prefix, classname, or user- * specified string. */ return new ThreadCategory(DEFAULT_CATEGORY); } } /** * <p>getSlf4jInstance</p> * * @return a {@link org.slf4j.Logger} object. */ public static org.slf4j.Logger getSlf4jInstance() { String prefix = getPrefix(); if (prefix != null) { return org.slf4j.LoggerFactory.getLogger(prefix); } else { return org.slf4j.LoggerFactory.getLogger(DEFAULT_CATEGORY); } } /** * This method is used to set a prefix for the category name that is used * for all category instances in this thread. This is used to insure that * all messages from a particular thread end up in the same log file, * regardless of the package or class name of the class that generated the * log message. Please restrict the usage of this function to only the * highest level threads. * * @param prefix a {@link java.lang.String} object. */ public static void setPrefix(String prefix) { s_threadCategory.set(prefix); } /** * This is used to retrieve the current prefix as it has been inherited by * the calling thread. This is needed by many dynamic threading classes like * the {@link RunnableConsumerThreadPool} to ensure that all the * internal threads run in the same category. * * @return The prefix string as inherited by the calling thread. */ public static String getPrefix() { return s_threadCategory.get(); } /** * <p>debug</p> * * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. * @see org.apache.log4j.Category#debug(java.lang.Object, java.lang.Throwable) */ public void debug(String message, Throwable t) { m_delegate.debug(messagePrefix == null ? message : messagePrefix + message, t); } /** * <p>debug</p> * * @param message a {@link java.lang.String} object. * @see org.apache.log4j.Category#debug(java.lang.Object) */ public void debug(String message) { m_delegate.debug(messagePrefix == null ? message : messagePrefix + message); } /** * <p>error</p> * * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. * @see org.apache.log4j.Category#error(java.lang.Object, java.lang.Throwable) */ public void error(String message, Throwable t) { m_delegate.error(messagePrefix == null ? message : messagePrefix + message, t); } /** * <p>error</p> * * @param message a {@link java.lang.String} object. * @see org.apache.log4j.Category#error(java.lang.Object) */ public void error(String message) { m_delegate.error(messagePrefix == null ? message : messagePrefix + message); } /** * <p>fatal</p> * * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. * @see org.apache.log4j.Category#fatal(java.lang.Object, java.lang.Throwable) */ public void fatal(String message, Throwable t) { m_delegate.fatal(messagePrefix == null ? message : messagePrefix + message, t); } /** * <p>fatal</p> * * @param message a {@link java.lang.String} object. * @see org.apache.log4j.Category#fatal(java.lang.Object) */ public void fatal(String message) { m_delegate.fatal(messagePrefix == null ? message : messagePrefix + message); } /** * <p>info</p> * * @see org.apache.log4j.Category#info(java.lang.Object, java.lang.Throwable) * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. */ public void info(String message, Throwable t) { m_delegate.info(messagePrefix == null ? message : messagePrefix + message, t); } /** * <p>info</p> * * @see org.apache.log4j.Category#info(java.lang.Object) * @param message a {@link java.lang.String} object. */ public void info(String message) { // m_delegate.info(messagePrefix == null ? message : messagePrefix + message); m_delegate.info(message); } /** * <p>trace</p> * * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. * @see org.apache.log4j.Logger#trace(java.lang.Object, java.lang.Throwable) */ public void trace(String message, Throwable t) { m_delegate.trace(messagePrefix == null ? message : messagePrefix + message, t); } /** * <p>trace</p> * * @param message a {@link java.lang.String} object. * @see org.apache.log4j.Logger#trace(java.lang.Object) */ public void trace(String message) { m_delegate.trace(messagePrefix == null ? message : messagePrefix + message); } /** * <p>warn</p> * * @param message a {@link java.lang.String} object. * @param t a {@link java.lang.Throwable} object. * @see org.apache.log4j.Category#warn(java.lang.Object, java.lang.Throwable) */ public void warn(String message, Throwable t) { m_delegate.warn(message, t); } /** * <p>warn</p> * * @param message a {@link java.lang.String} object. * @see org.apache.log4j.Category#warn(java.lang.Object) */ public void warn(String message) { m_delegate.warn(message); } /** * <p>Getter for the field <code>messagePrefix</code>.</p> * * @return the messagePrefix */ public String getMessagePrefix() { return messagePrefix; } /** * <p>clearMessagePrefix</p> */ public void clearMessagePrefix() { messagePrefix = null; } /** * <p>Setter for the field <code>messagePrefix</code>.</p> * * @param messagePrefix the messagePrefix to set */ public void setMessagePrefix(String messagePrefix) { this.messagePrefix = messagePrefix; } /** * <p>isDebugEnabled</p> * * @see org.apache.log4j.Category#isDebugEnabled() * @return a boolean. */ public boolean isDebugEnabled() { return m_delegate.isDebugEnabled(); } /** * <p>isEnabledFor</p> * * @param level a {@link org.opennms.core.utils.ThreadCategory.Level} object. * @see org.apache.log4j.Category#isEnabledFor(org.apache.log4j.Priority) * @return a boolean. */ public boolean isEnabledFor(Level level) { switch(level) { case FATAL: return m_delegate.isEnabledFor(org.apache.log4j.Level.FATAL); case ERROR: return m_delegate.isEnabledFor(org.apache.log4j.Level.ERROR); case WARN: return m_delegate.isEnabledFor(org.apache.log4j.Level.WARN); case INFO: return m_delegate.isEnabledFor(org.apache.log4j.Level.INFO); case DEBUG: return m_delegate.isEnabledFor(org.apache.log4j.Level.DEBUG); case TRACE: return m_delegate.isEnabledFor(org.apache.log4j.Level.TRACE); case ALL: return m_delegate.isEnabledFor(org.apache.log4j.Level.ALL); case OFF: return m_delegate.isEnabledFor(org.apache.log4j.Level.OFF); default: throw new IllegalArgumentException("Invalid logging level: " + level); } } /** * <p>isInfoEnabled</p> * * @see org.apache.log4j.Category#isInfoEnabled() * @return a boolean. */ public boolean isInfoEnabled() { return m_delegate.isInfoEnabled(); } /** * <p>isTraceEnabled</p> * * @see org.apache.log4j.Logger#isTraceEnabled() * @return a boolean. */ public boolean isTraceEnabled() { return m_delegate.isTraceEnabled(); } /** * <p>getName</p> * * @see org.apache.log4j.Category#getName() * @return a {@link java.lang.String} object. */ public final String getName() { return m_delegate.getName(); } /** * <p>getLevel</p> * * @see org.apache.log4j.Category#getLevel() * @return a {@link org.opennms.core.utils.ThreadCategory.Level} object. */ public final Level getLevel() { switch(m_delegate.getLevel().toInt()) { case org.apache.log4j.Level.FATAL_INT: return Level.FATAL; case org.apache.log4j.Level.ERROR_INT: return Level.ERROR; case org.apache.log4j.Level.WARN_INT: return Level.WARN; case org.apache.log4j.Level.INFO_INT: return Level.INFO; case org.apache.log4j.Level.DEBUG_INT: return Level.DEBUG; case org.apache.log4j.Level.TRACE_INT: return Level.TRACE; case org.apache.log4j.Level.ALL_INT: return Level.ALL; case org.apache.log4j.Level.OFF_INT: return Level.OFF; default: throw new IllegalStateException("Invalid logging level set: " + m_delegate.getLevel()); } } /** * <p>setLevel</p> * * @param level a {@link org.opennms.core.utils.ThreadCategory.Level} object. * @see org.apache.log4j.Category#setLevel(org.apache.log4j.Level) */ public void setLevel(Level level) { switch(level) { case FATAL: m_delegate.setLevel(org.apache.log4j.Level.FATAL); break; case ERROR: m_delegate.setLevel(org.apache.log4j.Level.ERROR); break; case WARN: m_delegate.setLevel(org.apache.log4j.Level.WARN); break; case INFO: m_delegate.setLevel(org.apache.log4j.Level.INFO); break; case DEBUG: m_delegate.setLevel(org.apache.log4j.Level.DEBUG); break; case TRACE: m_delegate.setLevel(org.apache.log4j.Level.TRACE); break; case ALL: m_delegate.setLevel(org.apache.log4j.Level.ALL); break; case OFF: m_delegate.setLevel(org.apache.log4j.Level.OFF); break; } } }