1 /**
2 * Logback: the reliable, generic, fast and flexible logging framework.
3 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4 *
5 * This program and the accompanying materials are dual-licensed under
6 * either the terms of the Eclipse Public License v1.0 as published by
7 * the Eclipse Foundation
8 *
9 * or (per the licensee's choosing)
10 *
11 * under the terms of the GNU Lesser General Public License version 2.1
12 * as published by the Free Software Foundation.
13 */
14 package ch.qos.logback.classic;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.Map;
20
21 import org.slf4j.helpers.MarkerIgnoringBase;
22
23 import ch.qos.logback.classic.spi.ILoggingEvent;
24 import ch.qos.logback.core.Appender;
25 import ch.qos.logback.core.CoreConstants;
26
27 public class HLogger extends MarkerIgnoringBase {
28
29 private static final long serialVersionUID = 1L;
30
31 static int instanceCount = 0;
32
33 /**
34 * The name of this logger
35 */
36 private String name;
37
38 // The assigned levelInt of this logger. Can be null.
39 private Level level;
40
41 // The effective levelInt is the assigned levelInt and if null, a levelInt is
42 // inherited form a parent.
43 private Level effectiveLevel;
44
45 /**
46 * The parent of this category. All categories have at least one ancestor which
47 * is the root category.
48 */
49 HLogger parent;
50
51 /**
52 * The children of this logger. A logger may have zero or more children.
53 */
54 Map<String, HLogger> childrenMap;
55
56 /**
57 * Array of appenders.
58 */
59 private ArrayList<Appender<ILoggingEvent>> appenderList;
60
61 /**
62 * Additivity is set to true by default, that is children inherit the appenders
63 * of their ancestors by default. If this variable is set to <code>false</code>
64 * then the appenders located in the ancestors of this logger will not be used.
65 * However, the children of this logger will inherit its appenders, unless the
66 * children have their additivity flag set to <code>false</code> too. See the
67 * user manual for more details.
68 */
69 protected boolean additive = true;
70
71 HLogger(String name, HLogger parent) {
72 this.name = name;
73 this.parent = parent;
74 instanceCount++;
75 }
76
77 Level getEffectiveLevel() {
78 return effectiveLevel;
79 }
80
81 Level getLevel() {
82 return level;
83 }
84
85 public String getName() {
86 return name;
87 }
88
89 private boolean isRootLogger() {
90 // only the root logger has a null parent
91 return parent == null;
92 }
93
94 /**
95 * Get a child by its suffix.
96 *
97 * <p>
98 * IMPORTANT: Calls to this method must be within a synchronized block on this
99 * 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.
155 * <p/>
156 * This is useful when re-reading configuration information.
157 */
158 public synchronized void removeAllAppenders() {
159 if (appenderList != null) {
160 int len = appenderList.size();
161 for (int i = 0; i < len; i++) {
162 Appender<ILoggingEvent> a = appenderList.get(i);
163 a.stop();
164 }
165 appenderList.clear();
166 appenderList = null;
167 }
168 }
169
170 /**
171 * Invoke all the appenders of this logger.
172 *
173 * @param event 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 synchronized block on this
229 * logger.
230 *
231 * @param lastPart the suffix (i.e. last part) of the child logger name. This
232 * parameter may not include dots, i.e. the logger separator
233 * character.
234 * @return
235 */
236 HLogger createChildByLastNamePart(final String lastPart) {
237 int i_index = lastPart.indexOf(CoreConstants.DOT);
238 if (i_index != -1) {
239 throw new IllegalArgumentException(
240 "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 }