001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic; 015 016import java.util.ArrayList; 017import java.util.HashMap; 018import java.util.Iterator; 019import java.util.Map; 020 021import org.slf4j.helpers.MarkerIgnoringBase; 022 023import ch.qos.logback.classic.spi.ILoggingEvent; 024import ch.qos.logback.core.Appender; 025import ch.qos.logback.core.CoreConstants; 026 027public class HLogger extends MarkerIgnoringBase { 028 029 private static final long serialVersionUID = 1L; 030 031 static int instanceCount = 0; 032 033 /** 034 * The name of this logger 035 */ 036 private String name; 037 038 // The assigned levelInt of this logger. Can be null. 039 private Level level; 040 041 // The effective levelInt is the assigned levelInt and if null, a levelInt is 042 // inherited form a parent. 043 private Level effectiveLevel; 044 045 /** 046 * The parent of this category. All categories have at least one ancestor 047 * which is the root category. 048 */ 049 HLogger parent; 050 051 /** 052 * The children of this logger. A logger may have zero or more children. 053 */ 054 Map<String, HLogger> childrenMap; 055 056 /** 057 * Array of appenders. 058 */ 059 private ArrayList<Appender<ILoggingEvent>> appenderList; 060 061 /** 062 * Additivity is set to true by default, that is children inherit the 063 * appenders of their ancestors by default. If this variable is set to 064 * <code>false</code> then the appenders located in the ancestors of this 065 * logger will not be used. However, the children of this logger will inherit 066 * its appenders, unless the children have their additivity flag set to 067 * <code>false</code> too. See the user manual for more details. 068 */ 069 protected boolean additive = true; 070 071 HLogger(String name, HLogger parent) { 072 this.name = name; 073 this.parent = parent; 074 instanceCount++; 075 } 076 077 Level getEffectiveLevel() { 078 return effectiveLevel; 079 } 080 081 Level getLevel() { 082 return level; 083 } 084 085 public String getName() { 086 return name; 087 } 088 089 private boolean isRootLogger() { 090 // only the root logger has a null parent 091 return parent == null; 092 } 093 094 /** 095 * Get a child by its suffix. 096 * 097 * <p> 098 * IMPORTANT: Calls to this method must be within a syncronized block on this 099 * logger! 100 * 101 * @param suffix 102 * @return 103 */ 104 HLogger getChildBySuffix(final String suffix) { 105 if (childrenMap == null) { 106 return null; 107 } else { 108 return (HLogger) childrenMap.get(suffix); 109 } 110 } 111 112 public synchronized void setLevel(Level newLevel) { 113 if (level == newLevel) { 114 // nothing to do; 115 return; 116 } 117 118 level = newLevel; 119 effectiveLevel = newLevel; 120 if (childrenMap != null) { 121 for (Iterator<HLogger> i = childrenMap.values().iterator(); i.hasNext();) { 122 HLogger child = (HLogger) i.next(); 123 124 // tell child to handle parent levelInt change 125 child.handleParentLevelChange(effectiveLevel); 126 } 127 } 128 } 129 130 /** 131 * This method is invoked by parent logger to let this logger know that the 132 * prent's levelInt changed. 133 * 134 * @param newParentLevel 135 */ 136 private synchronized void handleParentLevelChange(Level newParentLevel) { 137 // changes in the parent levelInt affect children only if their levelInt is 138 // null 139 if (level == null) { 140 effectiveLevel = newParentLevel; 141 142 // propagate the parent levelInt change to this logger's children 143 if (childrenMap != null) { 144 for (Iterator<HLogger> i = childrenMap.values().iterator(); i.hasNext();) { 145 HLogger child = (HLogger) i.next(); 146 // tell child to handle parent levelInt change 147 child.handleParentLevelChange(effectiveLevel); 148 } 149 } 150 } 151 } 152 153 /** 154 * Remove all previously added appenders from this logger instance. <p/> This 155 * is useful when re-reading configuration information. 156 */ 157 public synchronized void removeAllAppenders() { 158 if (appenderList != null) { 159 int len = appenderList.size(); 160 for (int i = 0; i < len; i++) { 161 Appender<ILoggingEvent> a = appenderList.get(i); 162 a.stop(); 163 } 164 appenderList.clear(); 165 appenderList = null; 166 } 167 } 168 169 /** 170 * Invoke all the appenders of this logger. 171 * 172 * @param event 173 * The event to log 174 */ 175 public void callAppenders(ILoggingEvent event) { 176 ///int writes = 0; 177 178 for (HLogger l = this; l != null; l = l.parent) { 179 // Protected against simultaneous call to addAppender, removeAppender,... 180 synchronized (l) { 181 if (l.appenderList != null) { 182 l.appendLoopOnAppenders(event); 183 } 184 if (!l.additive) { 185 break; 186 } 187 } 188 } 189 190 // No appenders in hierarchy, warn user only once. 191 // if(!hierarchy.emittedNoAppenderWarning && writes == 0) { 192 // LogLog.error("No appenders could be found for category (" + 193 // this.getName() + ")."); 194 // LogLog.error("Please initialize the log4j system properly."); 195 // hierarchy.emittedNoAppenderWarning = true; 196 // } 197 } 198 199 private int appendLoopOnAppenders(ILoggingEvent event) { 200 int size = 0; 201 Appender<ILoggingEvent> appender; 202 203 if (appenderList != null) { 204 size = appenderList.size(); 205 for (int i = 0; i < size; i++) { 206 appender = appenderList.get(i); 207 appender.doAppend(event); 208 } 209 } 210 return size; 211 } 212 213 /** 214 * Remove the appender passed as parameter form the list of appenders. 215 */ 216 public synchronized void removeAppender(Appender<ILoggingEvent> appender) { 217 if ((appender == null) || (appenderList == null)) { 218 } 219 appenderList.remove(appender); 220 } 221 222 /** 223 * Create a child of this logger by suffix, that is, the part of the name 224 * extending this logger. For example, if this logger is named "x.y" and the 225 * lastPart is "z", then the created child logger will be named "x.y.z". 226 * 227 * <p> 228 * IMPORTANT: Calls to this method must be within a syncronized block on this 229 * logger. 230 * 231 * @param lastPart 232 * the suffix (i.e. last part) of the child logger name. This 233 * parameter may not include dots, i.e. the logger separator 234 * character. 235 * @return 236 */ 237 HLogger createChildByLastNamePart(final String lastPart) { 238 int i_index = lastPart.indexOf(CoreConstants.DOT); 239 if (i_index != -1) { 240 throw new IllegalArgumentException("Child name [" + lastPart + " passed as parameter, may not include [" + CoreConstants.DOT + "]"); 241 } 242 243 if (childrenMap == null) { 244 childrenMap = new HashMap<String, HLogger>(2); 245 } 246 HLogger childHLogger; 247 if (this.isRootLogger()) { 248 childHLogger = new HLogger(lastPart, this); 249 } else { 250 childHLogger = new HLogger(name + CoreConstants.DOT + lastPart, this); 251 } 252 childrenMap.put(lastPart, childHLogger); 253 childHLogger.effectiveLevel = this.effectiveLevel; 254 return childHLogger; 255 } 256 257 public final void trace(String msg) { 258 if (effectiveLevel.levelInt <= Level.TRACE_INT) { 259 throw new UnsupportedOperationException("not yet implemented"); 260 } 261 } 262 263 public void trace(String msg, Throwable t) { 264 // To change body of implemented methods use File | Settings | File 265 // Templates. 266 } 267 268 public void trace(Object parameterizedMsg, Object param1) { 269 // To change body of implemented methods use File | Settings | File 270 // Templates. 271 } 272 273 public void trace(String parameterizedMsg, Object param1, Object param2) { 274 // To change body of implemented methods use File | Settings | File 275 // Templates. 276 } 277 278 public final void debug(String msg) { 279 if (effectiveLevel.levelInt <= Level.DEBUG_INT) { 280 throw new UnsupportedOperationException("not yet implemented"); 281 } 282 } 283 284 public void debug(String msg, Throwable t) { 285 // To change body of implemented methods use File | Settings | File 286 // Templates. 287 } 288 289 public void debug(Object parameterizedMsg, Object param1) { 290 // To change body of implemented methods use File | Settings | File 291 // Templates. 292 } 293 294 public void debug(String parameterizedMsg, Object param1, Object param2) { 295 // To change body of implemented methods use File | Settings | File 296 // Templates. 297 } 298 299 public void error(String msg) { 300 // To change body of implemented methods use File | Settings | File 301 // Templates. 302 } 303 304 public void error(String msg, Throwable t) { 305 // To change body of implemented methods use File | Settings | File 306 // Templates. 307 } 308 309 public void error(String parameterizedMsg, Object param1) { 310 // To change body of implemented methods use File | Settings | File 311 // Templates. 312 } 313 314 public void error(String parameterizedMsg, Object param1, Object param2) { 315 // To change body of implemented methods use File | Settings | File 316 // Templates. 317 } 318 319 public void info(String msg) { 320 // To change body of implemented methods use File | Settings | File 321 // Templates. 322 } 323 324 public void info(String msg, Throwable t) { 325 // To change body of implemented methods use File | Settings | File 326 // Templates. 327 } 328 329 public void info(String parameterizedMsg, Object param1) { 330 // To change body of implemented methods use File | Settings | File 331 // Templates. 332 } 333 334 public void info(String parameterizedMsg, Object param1, Object param2) { 335 // To change body of implemented methods use File | Settings | File 336 // Templates. 337 } 338 339 public boolean isTraceEnabled() { 340 return false; 341 } 342 343 public boolean isDebugEnabled() { 344 return false; 345 } 346 347 public boolean isErrorEnabled() { 348 return false; // To change body of implemented methods use File | Settings | 349 // File Templates. 350 } 351 352 public boolean isInfoEnabled() { 353 return false; // To change body of implemented methods use File | Settings | 354 // File Templates. 355 } 356 357 public boolean isWarnEnabled() { 358 return false; // To change body of implemented methods use File | Settings | 359 // File Templates. 360 } 361 362 public void warn(String msg) { 363 // To change body of implemented methods use File | Settings | File 364 // Templates. 365 } 366 367 public void warn(String msg, Throwable t) { 368 // To change body of implemented methods use File | Settings | File 369 // Templates. 370 } 371 372 public void warn(String parameterizedMsg, Object param1) { 373 // To change body of implemented methods use File | Settings | File 374 // Templates. 375 } 376 377 public void warn(String parameterizedMsg, Object param1, Object param2) { 378 // To change body of implemented methods use File | Settings | File 379 // Templates. 380 } 381 382 public void trace(String format, Object arg) { 383 } 384 385 public void trace(String format, Object... argArray) { 386 } 387 388 public void debug(String format, Object arg) { 389 } 390 391 public void debug(String format, Object... argArray) { 392 } 393 394 public void info(String format, Object... argArray) { 395 } 396 397 public void warn(String format, Object... argArray) { 398 } 399 400 public void error(String format, Object... argArray) { 401 } 402}