/**
* Source code taken from {@link http://wiki.eclipse.org/EclipseLink/Foundation/Logging}.
* Supports use of log4j with eclipselink.
*/
package org.eclipse.persistence.logging;
import java.io.OutputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.log4j.Logger;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.EclipseLinkLogRecord;
import org.eclipse.persistence.logging.JavaLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.logging.SessionLogEntry;
import org.eclipse.persistence.sessions.Session;
/**
* PUBLIC:
* This is a wrapper class for org.apache.commons.logging.Log.
* It is used when messages need to be logged through apache commons logging 1.1.
*
* History :
*
* - 05/05/2009 : Updated API to EclipseLink 1.1 version + Javadoc fixes
* - 08/05/2009 : Fix for log4j levels in conflict with eclipselink jpa levels (shouldLog)
*
* TODO : Use Enum instead of int values for Levels (OO Design)
*
* Requires :
* - Jakarta Commons Logging 1.1 : http://commons.apache.org/logging/
* - commons-logging-1.1.1.jar
*
* - Log4j 1.2 : http://logging.apache.org/log4j/
* - log4j-1.2.15.jar
*
*
* @author laurent bourges (voparis) : bourges.laurent@gmail.com
*
* @see AbstractSessionLog
* @see JavaLog
* @see SessionLogEntry
*/
public final class CommonsLoggingSessionLog extends AbstractSessionLog {
//~ Constants --------------------------------------------------------------------------------------------------------
/**
* internal debugger FLAG : use System.out
*/
public static final boolean FORCE_INTERNAL_DEBUG = false;
/**
* internal debugger FLAG : use a stack trace to find caller class
*/
public static final boolean FORCE_INTERNAL_DEBUG_STACK = false;
/**
* internal cache FLAG for LogWrapper's levels
*/
public static final boolean USE_INTERNAL_CACHE = true;
/**
* internal apache commons Logging diagnostic FLAG : use System.out
*/
public static final boolean FORCE_APACHE_COMMONS_LOGGING_DIAGNOSTICS = false;
/**
* value -1 corresponds to an undefined Level
*/
public static final int UNDEFINED_LEVEL = -1;
/**
* Stores the default session name in case there is the session name is missing. org.eclipse.persistence
* package used by Log4J configuration
*/
public static final String ECLIPSELINK_NAMESPACE = "org.eclipse.persistence";
/**
* org.eclipse.persistence.default used by Log4J configuration
*/
public static final String DEFAULT_ECLIPSELINK_NAMESPACE = ECLIPSELINK_NAMESPACE + ".default";
/**
* org.eclipse.persistence.session used by Log4J configuration
*/
public static final String SESSION_ECLIPSELINK_NAMESPACE = ECLIPSELINK_NAMESPACE + ".session";
/**
* Copied from JavaLog for compatibility issues
*/
public static final String LOGGING_LOCALIZATION_STRING = "org.eclipse.persistence.internal.localization.i18n.LoggingLocalizationResource";
/**
* Copied from JavaLog for compatibility issues
*/
public static final String TRACE_LOCALIZATION_STRING = "org.eclipse.persistence.internal.localization.i18n.TraceLocalizationResource";
/**
* Stores all the java.util.logging.Levels. The indexes are EclipseLink logging levels.
*/
public static final Level[] JAVA_LEVELS = new Level[]{
Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG, Level.INFO,
Level.WARNING, Level.SEVERE, Level.OFF
};
static {
/* static Initializer to call onInit method */
onInit();
}
//~ Members ----------------------------------------------------------------------------------------------------------
/**
* formats the EclipseLinkLogRecords. Acts as a static variable but not declared static to avoid classLoader
* leaks (clone does not deep clone this instance)
*/
private final FastLogFormatter LOG_FORMATTER = new FastLogFormatter();
/**
* Represents the HashMap that stores all the name space strings. The keys are category names. The values are
* namespace strings. Acts as a static variable but not declared static to avoid classLoader leaks (clone does not
* deep clone this map). Note : Unsynchronized Map = should be thread-safe !
*/
private final Map<String, String> NAMESPACE_MAP = new HashMap<String, String>(32);
/**
* LogWrapper instances. Acts as a static variable but not declared static to avoid classLoader leaks (clone
* does not deep clone this map) Note : Unsynchronized Map = should be thread-safe !
*/
private final Map<String, LogWrapper> CATEGORY_LOGGERS = new HashMap<String, LogWrapper>(32);
/**
* Stores the namespace for session, i.e."org.eclipse.persistence.session.#sessionname#".
*/
private String sessionNameSpace;
//~ Constructors -----------------------------------------------------------------------------------------------------
/**
* PUBLIC:
*
* CommonsLoggingSessionLog Constructor.
*
* Used by :
* org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.updateLoggers :
* creates an instance for singletonLog and sessionLog
*
* This adds a root logger for DEFAULT_ECLIPSELINK_NAMESPACE.
*/
public CommonsLoggingSessionLog() {
super();
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.new : instance : " + this, true);
}
addLogger(DEFAULT_ECLIPSELINK_NAMESPACE, DEFAULT_ECLIPSELINK_NAMESPACE);
}
//~ Methods ----------------------------------------------------------------------------------------------------------
/**
* PUBLIC:
*
* OnInit method : define system properties for org.apache.commons.logging
*/
public static final void onInit() {
if (FORCE_APACHE_COMMONS_LOGGING_DIAGNOSTICS) {
/**
* The name (<code>org.apache.commons.logging.diagnostics.dest</code>)
* of the property used to enable internal commons-logging
* diagnostic output, in order to get information on what logging
* implementations are being discovered, what classloaders they
* are loaded through, etc.
* <p>
* If a system property of this name is set then the value is
* assumed to be the name of a file. The special strings
* STDOUT or STDERR (case-sensitive) indicate output to
* System.out and System.err respectively.
* <p>
* Diagnostic logging should be used only to debug problematic
* configurations and should not be set in normal production use.
*/
System.setProperty("org.apache.commons.logging.diagnostics.dest", "STDOUT");
}
}
/**
* PUBLIC:
*
* onExit method : release all ClassLoader references due to apache commons logging LogFactory
*
* NOTE : <b>This method must be called in the context of a web application via ServletContextListener.contextDestroyed(ServletContextEvent)</b>
*
* @see org.apache.commons.logging.LogFactory#release(ClassLoader)
*/
public static final void onExit() {
// Classloader unload problem with commons-logging :
LogFactory.release(Thread.currentThread().getContextClassLoader());
}
/**
* PUBLIC: Return the effective log level for the name space extracted from session and category. If a
* Logger's level is set to be null then the Logger will use an effective Level that will be obtained by walking up
* the parent tree and using the first non-null Level.
*
* @param category category
*
* @return the effective level according to the java.util.logging.Levels
*/
@Override
public final int getLevel(final String category) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLevel : IN : category : " + category);
}
final LogWrapper lw = getLogWrapper(category);
int l = OFF;
if (lw != null) {
l = lw.getLevel();
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLevel : OUT : category : " + category + " : level : " + getLevelString(l));
}
return l;
}
/**
* PUBLIC: Set the log level to a logger with name space extracted from the given category.
*
* @param level value according to the java.util.logging.Levels
* @param category category
*/
@Override
public final void setLevel(final int level, final String category) {
AccessController.doPrivileged(
new PrivilegedAction<Object>() {
public Object run() {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.setLevel : IN : category : " + category + " to level : " +
getLevelString(level), true);
}
final LogWrapper lw = getLogWrapper(category);
if (lw == null) {
error("CommonsLoggingSessionLog.setLevel : category not found : " + category);
} else {
final Logger logger = getLog4JLogger(lw.getLog());
if (logger == null) {
error("CommonsLoggingSessionLog.setLevel : Logger not found : " + category + " : " + lw.getLog());
} else {
final org.apache.log4j.Level realLevel = getLevelFor(level);
if (realLevel == org.apache.log4j.Level.OFF) {
// force level to OFF :
lw.setLevel(OFF);
error("CommonsLoggingSessionLog.setLevel : unknown level : " + getLevelString(level) + " : level set to OFF");
} else {
lw.setLevel(level);
}
logger.setLevel(realLevel);
if (logger.isEnabledFor(org.apache.log4j.Level.WARN)) {
logger.warn("CommonsLoggingSessionLog.setLevel : Logger Level set to : " + logger.getLevel());
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.setLevel : OUT : category : " + category + " to level : " +
logger.getLevel());
}
}
}
// nothing to return :
return null;
}
});
}
/**
* PUBLIC: Set the output stream that will receive the formatted log entries. DO nothing as Log4J manages the
* appenders (console or files) via Log4J configuration
*
* @param fileOutputStream the file output stream will receive the formatted log entries.
*/
@Override
public final void setWriter(final OutputStream fileOutputStream) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.setWriter : stream : " + fileOutputStream);
}
// do nothing
}
/**
* PUBLIC: Set the session and session namespace.
*
* @param pSession an eclipselink Session
*/
@Override
public final void setSession(final Session pSession) {
super.setSession(pSession);
if (pSession != null) {
final String sessionName = pSession.getName();
if ((sessionName != null) && (sessionName.length() != 0)) {
this.sessionNameSpace = SESSION_ECLIPSELINK_NAMESPACE + "." + sessionName;
} else {
this.sessionNameSpace = DEFAULT_ECLIPSELINK_NAMESPACE;
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.setSession : sessionNameSpace : " + this.sessionNameSpace);
}
//Initialize loggers eagerly
addLogger(this.sessionNameSpace, this.sessionNameSpace);
addDefaultLoggers(this.sessionNameSpace);
}
}
/**
* PUBLIC: Check if a message of the given lev would actually be logged by the logger with name space built
* from the given session and category. Return the shouldLog for the given category Note : this method is very very
* used so optimized for performance.
*
* @param level value according to the java.util.logging.Levels
* @param category category
*
* @return true if the given message will be logged
*/
@Override
public final boolean shouldLog(final int level, final String category) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.shouldLog : IN : category : " + category + " : " + getLevelString(level));
}
boolean res = false;
switch (level) {
case OFF:
res = false;
break;
case ALL:
res = true;
break;
default:
final LogWrapper lw = getLogWrapper(category);
if (lw == null) {
error("CommonsLoggingSessionLog.shouldLog : category : " + category + " - NO LOGGER FOUND");
res = false;
} else {
res = level >= lw.getLevel();
}
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.shouldLog : OUT : category : " + category + " : " + res);
}
return res;
}
/**
* PUBLIC: Log a SessionLogEntry
*
* @param entry SessionLogEntry that holds all the information for a EclipseLink logging event
*/
public final void log(final SessionLogEntry entry) {
if (shouldLog(entry.getLevel(), entry.getNameSpace())) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.log : namespace : " + entry.getNameSpace() + " message : " + entry.getMessage());
}
final Log log = getLog(entry.getNameSpace());
if (log == null) {
error("CommonsLoggingSessionLog.log : no Log found for : " + entry.getNameSpace());
} else {
final Level javaLevel = getJavaLevel(entry.getLevel());
internalLog(entry, javaLevel, log);
}
}
}
/**
* PUBLIC: Log a throwable.
*
* @param throwable a throwable
*/
@Override
public final void throwing(final Throwable throwable) {
final Log log = getLog(null);
if (log != null) {
log.error(null, throwable);
}
}
/**
* INTERNAL: Each session owns its own session log because session is stored in the session log
*
* @return value TODO : Value Description
*/
@Override
public final Object clone() {
// There is no special treatment required for cloning here
// The state of this object is described by member variables sessionLogger and categoryLoggers.
// This state depends on session.
// If session for the clone is going to be the same as session for this there is no
// need to do "deep" cloning.
// If not, the session being cloned should call setSession() on its JavaLog object to initialize it correctly.
final CommonsLoggingSessionLog cloneLog = (CommonsLoggingSessionLog) super.clone();
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.clone : cloned instance : " + cloneLog, true);
}
return cloneLog;
}
/**
* INTERNAL: Add Logger to the categoryloggers.
*
* @param loggerCategory category
* @param loggerNameSpace name space
*/
private final void addLogger(final String loggerCategory, final String loggerNameSpace) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.addLogger : category : " + loggerCategory + " in name space : " + loggerNameSpace);
}
this.CATEGORY_LOGGERS.put(loggerCategory, new LogWrapper(this, loggerCategory, LogFactory.getLog(loggerNameSpace)));
}
/**
* INTERNAL: Return the name space for the given category from the map.
*
* @param category category
*
* @return name space for the given category
*/
private final String getNameSpaceString(final String category) {
if (getSession() == null) {
return DEFAULT_ECLIPSELINK_NAMESPACE;
} else if ((category == null) || (category.length() == 0)) {
return this.sessionNameSpace;
} else {
return this.NAMESPACE_MAP.get(category);
}
}
/**
* INTERNAL: Return the LogWrapper instance for the given category Note : this method is very very used so
* optimized for performance.
*
* @param category category
*
* @return LogWrapper instance or null if not found
*/
private final LogWrapper getLogWrapper(final String category) {
LogWrapper lw = null;
if (getSession() == null) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLogWrapper : " + category + " : SESSION NULL");
}
lw = this.CATEGORY_LOGGERS.get(DEFAULT_ECLIPSELINK_NAMESPACE);
} else {
lw = this.CATEGORY_LOGGERS.get(category);
if (lw == null) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLogWrapper : " + category + " : CATEGORY IS NULL ?");
}
// really few cases :
if ((category == null) || (category.length() == 0)) {
lw = this.CATEGORY_LOGGERS.get(this.sessionNameSpace);
}
}
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLogWrapper : " + category + " = " + lw);
}
return lw;
}
/**
* INTERNAL: Return the apache commons logging Log instance for the given category
*
* @param category category
*
* @return value Log instance or null if not found
*/
private final Log getLog(final String category) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLogger : IN : category : " + category);
}
final LogWrapper lw = getLogWrapper(category);
Log log = null;
if (lw != null) {
log = lw.getLog();
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLogger : OUT : log : " + log);
}
return log;
}
/**
* INTERNAL: Adds default loggers for the given name space
*
* @param namespace name space
*/
private final void addDefaultLoggers(final String namespace) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.addDefaultLoggers : nameSpace : " + namespace);
}
String loggerCategory;
String loggerNameSpace;
final String[] categories = SessionLog.loggerCatagories;
final int size = categories.length;
for (int i = 0; i < size; i++) {
loggerCategory = categories[i];
loggerNameSpace = namespace + "." + loggerCategory;
this.NAMESPACE_MAP.put(loggerCategory, loggerNameSpace);
addLogger(loggerCategory, loggerNameSpace);
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.addDefaultLoggers : NAMESPACE_MAP : " + this.NAMESPACE_MAP);
debug("CommonsLoggingSessionLog.addDefaultLoggers : CATEGORY_LOGGERS : " + this.CATEGORY_LOGGERS);
}
}
/**
* INTERNAL: Build a LogRecord
*
* @param entry SessionLogEntry that holds all the information for a EclipseLink logging event
* @param level according to eclipselink level
* @param log commons-logging 1.1 wrapper
*/
private final void internalLog(final SessionLogEntry entry, final Level level, final Log log) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.internalLog : " + computeMessage(entry, level));
}
final int entryLevel = entry.getLevel();
switch (entryLevel) {
case SEVERE:
log.error(computeMessage(entry, level));
break;
case WARNING:
log.warn(computeMessage(entry, level));
break;
case INFO:
case CONFIG:
log.info(computeMessage(entry, level));
break;
case FINE:
case FINER:
case FINEST:
log.debug(computeMessage(entry, level));
break;
case ALL:
log.trace(computeMessage(entry, level));
break;
case OFF:
break;
default:
error("CommonsLoggingSessionLog.internalLog : unknown level : " + entryLevel);
break;
}
}
/**
* INTERNAL: Computes the log message
*
* @param entry SessionLogEntry that holds all the information for a EclipseLink logging event
* @param level according to eclipselink level
*
* @return value TODO : Value Description
*/
private final String computeMessage(final SessionLogEntry entry, final Level level) {
// Format message so that we do not depend on the bundle
final EclipseLinkLogRecord lr = new EclipseLinkLogRecord(level, formatMessage(entry));
lr.setSourceClassName(null);
lr.setSourceMethodName(null);
lr.setLoggerName(getNameSpaceString(entry.getNameSpace()));
if (shouldPrintSession()) {
lr.setSessionString(getSessionString(entry.getSession()));
}
if (shouldPrintConnection()) {
lr.setConnection(entry.getConnection());
}
lr.setThrown(entry.getException());
lr.setShouldLogExceptionStackTrace(shouldLogExceptionStackTrace());
lr.setShouldPrintDate(shouldPrintDate());
lr.setShouldPrintThread(shouldPrintThread());
return this.LOG_FORMATTER.format(lr);
}
/**
* INTERNAL: Return the corresponding java.util.logging.Level for a given eclipselink level.
*
* @param level according to eclipselink level
*
* @return value according to the java.util.logging.Levels
*/
private static final Level getJavaLevel(final int level) {
return JAVA_LEVELS[level];
}
/**
* INTERNAL: Returns Log4JLogger instance
*
* @param log commons-logging 1.1 wrapper
*
* @return Log4JLogger instance
*/
private static final Logger getLog4JLogger(final Log log) {
Logger l = null;
if (log instanceof Log4JLogger) {
l = ((Log4JLogger) log).getLogger();
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLog4JLogger : " + l);
}
return l;
}
/**
* PUBLIC: SHOULD BE in AbstractSessionLog
*
* @see AbstractSessionLog#getLevelString() Return the log level as a string value.
*/
private static final String getLevelString(final int level) {
switch (level) {
case OFF:
return "OFF";
case SEVERE:
return "SEVERE";
case WARNING:
return "WARNING";
case INFO:
return "INFO";
case CONFIG:
return "CONFIG";
case FINE:
return "FINE";
case FINER:
return "FINER";
case FINEST:
return "FINEST";
case ALL:
return "ALL";
default:
return "INFO";
}
}
/**
* Returns the real Log4J Level
* @param level eclipselink level
* @return org.apache.log4j.Level
*/
private static final org.apache.log4j.Level getLevelFor(final int level) {
org.apache.log4j.Level realLevel = null;
switch (level) {
case SEVERE:
realLevel = org.apache.log4j.Level.ERROR;
break;
case WARNING:
realLevel = org.apache.log4j.Level.WARN;
break;
case INFO:
case CONFIG:
realLevel = org.apache.log4j.Level.INFO;
break;
case FINE:
case FINER:
case FINEST:
realLevel = org.apache.log4j.Level.DEBUG;
break;
case ALL:
realLevel = org.apache.log4j.Level.ALL;
break;
case OFF:
realLevel = org.apache.log4j.Level.OFF;
break;
default:
realLevel = org.apache.log4j.Level.OFF;
error("CommonsLoggingSessionLog.getLevelFor : unknown level : " + getLevelString(level) + " = OFF");
break;
}
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.getLevelFor : level : " + getLevelString(level) + " = " + realLevel);
}
return realLevel;
}
/**
* Prints the message in Std out
* @param message message to print
*/
protected final static void debug(final String message) {
debug(message, false);
}
/**
* Prints the message in Std out
* @param message message to print
* @param printStack adds a stack trace to find caller class
*/
protected final static void debug(final String message, final boolean printStack) {
System.out.println(message);
// if (printStack && FORCE_INTERNAL_DEBUG_STACK) {
// // to inspect the calling stack :
// new Throwable().printStackTrace(System.out);
// }
}
/**
* Prints the message in Std err
* @param message message to print
*/
protected final static void error(final String message) {
System.err.println(message);
}
/**
* Prints the message in Std err
* @param message message to print
*/
protected final static void error(final Throwable th) {
th.printStackTrace(System.err);
}
//~ Inner Classes ----------------------------------------------------------------------------------------------------
/**
* INTERNAL: LogWrapper class wraps the real apache commons logging Log instance
*/
private static final class LogWrapper {
//~ Members --------------------------------------------------------------------------------------------------------
/** parent CommonsLoggingSessionLog instance */
private final CommonsLoggingSessionLog sessionLog;
/** category for debug mode */
private final String category;
/** apache commons logging Log instance */
private final Log log;
/** parent LogWrapper */
private final LogWrapper parent;
/** child LogWrapper instances */
private List<LogWrapper> children = null;
/** level as defined by java.util.logging.Levels. Can be changed at runtime */
private int level = UNDEFINED_LEVEL;
/** cached level as defined by java.util.logging.Levels. Extracted from parent LogWrapper instances */
private int cachedLevel = UNDEFINED_LEVEL;
//~ Constructors ---------------------------------------------------------------------------------------------------
/**
* INTERNAL:
*
* Constructor
*
* @param log apache commons logging Log instance
*/
protected LogWrapper(final CommonsLoggingSessionLog sessionLog, final String category, final Log log) {
this.sessionLog = sessionLog;
this.category = category;
this.log = log;
final Logger logger = CommonsLoggingSessionLog.getLog4JLogger(log);
String parentName = null;
if (logger != null) {
parentName = logger.getParent().getName();
}
if ((parentName != null) && !"null".equals(parentName)) {
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.LogWrapper.new : parent : " + parentName);
}
this.parent = this.sessionLog.getLogWrapper(parentName);
if (this.parent != null) {
this.parent.addChild(this);
}
} else {
this.parent = null;
}
}
//~ Methods --------------------------------------------------------------------------------------------------------
/**
* INTERNAL: Returns the category
*
* @return category
*/
protected final String getCategory() {
return this.category;
}
/**
* INTERNAL: Reset the cachedLevel
*/
protected final void resetCachedLevel() {
this.cachedLevel = UNDEFINED_LEVEL;
if (FORCE_INTERNAL_DEBUG) {
debug("CommonsLoggingSessionLog.LogWrapper.setLevel : reset cachedLevel for : " + getCategory());
}
}
/**
* INTERNAL: Returns the apache commons logging Log instance
*
* @return apache commons logging Log instance
*/
protected final Log getLog() {
return this.log;
}
/**
* INTERNAL: Returns the level according to the java.util.logging.Levels
*
* @return level computed from cachedLevel and internal level
*/
protected final int getLevel() {
int res = this.cachedLevel;
// if the cachedLevel is undefined : compute it from parents :
if (res == UNDEFINED_LEVEL) {
// first gives the internal level :
res = this.level;
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.getLevel : this : " + getCategory() + " : UNCACHED level : " + getLevelString(res));
}
if (res == UNDEFINED_LEVEL) {
res = computeLevel(UNDEFINED_LEVEL);
if (USE_INTERNAL_CACHE) {
this.cachedLevel = res;
}
}
}
return res;
}
/**
* INTERNAL: Defines the level according to the java.util.logging.Levels
*
* @param level value according to the java.util.logging.Levels
*/
protected final void setLevel(final int level) {
this.level = level;
if (USE_INTERNAL_CACHE) {
this.resetCachedLevel();
if (this.children != null) {
// reset cachedLevel for all children :
for (final LogWrapper cw : this.children) {
cw.resetCachedLevel();
}
}
}
}
/**
* INTERNAL: Adds a child LogWrapper
*
* @param lw
*/
protected final void addChild(final LogWrapper lw) {
if (this.children == null) {
this.children = new ArrayList<LogWrapper>();
}
this.children.add(lw);
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.addChild : this : " + getCategory() + " : child : " + lw.getCategory());
}
}
/**
* INTERNAL: Computes the cached Level
*
* @param localLevel this.level copy
*
* @return level
*/
private final int computeLevel(final int localLevel) {
LogWrapper pw;
LogWrapper lw = this;
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.computeLevel : IN : " + getCategory() + " : level : " +
CommonsLoggingSessionLog.getLevelString(localLevel));
}
while ((lw != null) &&
(((lw == this) && (localLevel == UNDEFINED_LEVEL)) ||
((lw != this) && (lw.getLevel() == UNDEFINED_LEVEL)))) {
pw = lw.parent;
if (pw != lw) {
lw = pw;
} else {
// exit from loop :
lw = null;
}
}
int computedLevel = OFF;
if (lw != null) {
computedLevel = lw.getLevel();
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.computeLevel : category : " + lw.getCategory() + " - computedLevel : " + getLevelString(computedLevel) + " : " + lw.getLog());
}
final Logger logger = getLog4JLogger(lw.getLog());
if (logger == null) {
error("CommonsLoggingSessionLog.computeLevel : Logger not found : " + lw.getCategory() + " : " + lw.getLog());
} else {
final org.apache.log4j.Level realLevel = getLevelFor(computedLevel);
final boolean enabled = logger.isEnabledFor(realLevel);
if (!enabled) {
computedLevel = OFF;
}
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.computeLevel : category : " + lw.getCategory() + " : realLevel : " + realLevel + " - enabled = " + enabled);
}
}
}
if (FORCE_INTERNAL_DEBUG) {
System.out.println(
"CommonsLoggingSessionLog.LogWrapper.computeLevel : OUT : " + getCategory() + " : level : " +
CommonsLoggingSessionLog.getLevelString(computedLevel));
}
return computedLevel;
}
}
}
//~ End of file --------------------------------------------------------------------------------------------------------