/** * Logback: the reliable, generic, fast and flexible logging framework. * Copyright (C) 1999-2013, QOS.ch. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */ package ch.qos.logback.classic; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.slf4j.helpers.MarkerIgnoringBase; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import ch.qos.logback.core.CoreConstants; public class HLogger extends MarkerIgnoringBase { private static final long serialVersionUID = 1L; static int instanceCount = 0; /** * The name of this logger */ private String name; // The assigned levelInt of this logger. Can be null. private Level level; // The effective levelInt is the assigned levelInt and if null, a levelInt is // inherited form a parent. private Level effectiveLevel; /** * The parent of this category. All categories have at least one ancestor * which is the root category. */ HLogger parent; /** * The children of this logger. A logger may have zero or more children. */ Map<String, HLogger> childrenMap; /** * Array of appenders. */ private ArrayList<Appender<ILoggingEvent>> appenderList; /** * Additivity is set to true by default, that is children inherit the * appenders of their ancestors by default. If this variable is set to * <code>false</code> then the appenders located in the ancestors of this * logger will not be used. However, the children of this logger will inherit * its appenders, unless the children have their additivity flag set to * <code>false</code> too. See the user manual for more details. */ protected boolean additive = true; HLogger(String name, HLogger parent) { this.name = name; this.parent = parent; instanceCount++; } Level getEffectiveLevel() { return effectiveLevel; } Level getLevel() { return level; } public String getName() { return name; } private boolean isRootLogger() { // only the root logger has a null parent return parent == null; } /** * Get a child by its suffix. * * <p> * IMPORTANT: Calls to this method must be within a syncronized block on this * logger! * * @param suffix * @return */ HLogger getChildBySuffix(final String suffix) { if (childrenMap == null) { return null; } else { return (HLogger) childrenMap.get(suffix); } } public synchronized void setLevel(Level newLevel) { if (level == newLevel) { // nothing to do; return; } level = newLevel; effectiveLevel = newLevel; if (childrenMap != null) { for (Iterator<HLogger> i = childrenMap.values().iterator(); i.hasNext();) { HLogger child = (HLogger) i.next(); // tell child to handle parent levelInt change child.handleParentLevelChange(effectiveLevel); } } } /** * This method is invoked by parent logger to let this logger know that the * prent's levelInt changed. * * @param newParentLevel */ private synchronized void handleParentLevelChange(Level newParentLevel) { // changes in the parent levelInt affect children only if their levelInt is // null if (level == null) { effectiveLevel = newParentLevel; // propagate the parent levelInt change to this logger's children if (childrenMap != null) { for (Iterator<HLogger> i = childrenMap.values().iterator(); i.hasNext();) { HLogger child = (HLogger) i.next(); // tell child to handle parent levelInt change child.handleParentLevelChange(effectiveLevel); } } } } /** * Remove all previously added appenders from this logger instance. <p/> This * is useful when re-reading configuration information. */ public synchronized void removeAllAppenders() { if (appenderList != null) { int len = appenderList.size(); for (int i = 0; i < len; i++) { Appender<ILoggingEvent> a = appenderList.get(i); a.stop(); } appenderList.clear(); appenderList = null; } } /** * Invoke all the appenders of this logger. * * @param event * The event to log */ public void callAppenders(ILoggingEvent event) { int writes = 0; for (HLogger l = this; l != null; l = l.parent) { // Protected against simultaneous call to addAppender, removeAppender,... synchronized (l) { if (l.appenderList != null) { writes += l.appendLoopOnAppenders(event); } if (!l.additive) { break; } } } // No appenders in hierarchy, warn user only once. // if(!hierarchy.emittedNoAppenderWarning && writes == 0) { // LogLog.error("No appenders could be found for category (" + // this.getName() + ")."); // LogLog.error("Please initialize the log4j system properly."); // hierarchy.emittedNoAppenderWarning = true; // } } private int appendLoopOnAppenders(ILoggingEvent event) { int size = 0; Appender<ILoggingEvent> appender; if (appenderList != null) { size = appenderList.size(); for (int i = 0; i < size; i++) { appender = appenderList.get(i); appender.doAppend(event); } } return size; } /** * Remove the appender passed as parameter form the list of appenders. */ public synchronized void removeAppender(Appender<ILoggingEvent> appender) { if ((appender == null) || (appenderList == null)) { } appenderList.remove(appender); } /** * Create a child of this logger by suffix, that is, the part of the name * extending this logger. For example, if this logger is named "x.y" and the * lastPart is "z", then the created child logger will be named "x.y.z". * * <p> * IMPORTANT: Calls to this method must be within a syncronized block on this * logger. * * @param lastPart * the suffix (i.e. last part) of the child logger name. This * parameter may not include dots, i.e. the logger separator * character. * @return */ HLogger createChildByLastNamePart(final String lastPart) { int i_index = lastPart.indexOf(CoreConstants.DOT); if (i_index != -1) { throw new IllegalArgumentException("Child name [" + lastPart + " passed as parameter, may not include [" + CoreConstants.DOT + "]"); } if (childrenMap == null) { childrenMap = new HashMap<String, HLogger>(2); } HLogger childHLogger; if (this.isRootLogger()) { childHLogger = new HLogger(lastPart, this); } else { childHLogger = new HLogger(name + CoreConstants.DOT + lastPart, this); } childrenMap.put(lastPart, childHLogger); childHLogger.effectiveLevel = this.effectiveLevel; return childHLogger; } public final void trace(String msg) { if (effectiveLevel.levelInt <= Level.TRACE_INT) { throw new UnsupportedOperationException("not yet implemented"); } } public void trace(String msg, Throwable t) { // To change body of implemented methods use File | Settings | File // Templates. } public void trace(Object parameterizedMsg, Object param1) { // To change body of implemented methods use File | Settings | File // Templates. } public void trace(String parameterizedMsg, Object param1, Object param2) { // To change body of implemented methods use File | Settings | File // Templates. } public final void debug(String msg) { if (effectiveLevel.levelInt <= Level.DEBUG_INT) { throw new UnsupportedOperationException("not yet implemented"); } } public void debug(String msg, Throwable t) { // To change body of implemented methods use File | Settings | File // Templates. } public void debug(Object parameterizedMsg, Object param1) { // To change body of implemented methods use File | Settings | File // Templates. } public void debug(String parameterizedMsg, Object param1, Object param2) { // To change body of implemented methods use File | Settings | File // Templates. } public void error(String msg) { // To change body of implemented methods use File | Settings | File // Templates. } public void error(String msg, Throwable t) { // To change body of implemented methods use File | Settings | File // Templates. } public void error(String parameterizedMsg, Object param1) { // To change body of implemented methods use File | Settings | File // Templates. } public void error(String parameterizedMsg, Object param1, Object param2) { // To change body of implemented methods use File | Settings | File // Templates. } public void info(String msg) { // To change body of implemented methods use File | Settings | File // Templates. } public void info(String msg, Throwable t) { // To change body of implemented methods use File | Settings | File // Templates. } public void info(String parameterizedMsg, Object param1) { // To change body of implemented methods use File | Settings | File // Templates. } public void info(String parameterizedMsg, Object param1, Object param2) { // To change body of implemented methods use File | Settings | File // Templates. } public boolean isTraceEnabled() { return false; } public boolean isDebugEnabled() { return false; } public boolean isErrorEnabled() { return false; // To change body of implemented methods use File | Settings | // File Templates. } public boolean isInfoEnabled() { return false; // To change body of implemented methods use File | Settings | // File Templates. } public boolean isWarnEnabled() { return false; // To change body of implemented methods use File | Settings | // File Templates. } public void warn(String msg) { // To change body of implemented methods use File | Settings | File // Templates. } public void warn(String msg, Throwable t) { // To change body of implemented methods use File | Settings | File // Templates. } public void warn(String parameterizedMsg, Object param1) { // To change body of implemented methods use File | Settings | File // Templates. } public void warn(String parameterizedMsg, Object param1, Object param2) { // To change body of implemented methods use File | Settings | File // Templates. } public void trace(String format, Object arg) { } public void trace(String format, Object[] argArray) { } public void debug(String format, Object arg) { } public void debug(String format, Object[] argArray) { } public void info(String format, Object[] argArray) { } public void warn(String format, Object[] argArray) { } public void error(String format, Object[] argArray) { } }