1   /**
2    * LOGBack: the reliable, fast and flexible logging library for Java.
3    *
4    * Copyright (C) 1999-2005, QOS.ch, LOGBack.com
5    *
6    * This library is free software, you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation.
9    */
10  
11  package ch.qos.logback.classic;
12  
13  import java.util.ArrayList;
14  import java.util.HashMap;
15  import java.util.Iterator;
16  import java.util.Map;
17  
18  import org.slf4j.helpers.MarkerIgnoringBase;
19  
20  import ch.qos.logback.classic.ClassicGlobal;
21  import ch.qos.logback.classic.Level;
22  import ch.qos.logback.classic.spi.LoggingEvent;
23  import ch.qos.logback.core.Appender;
24  
25  
26  public class HLogger extends MarkerIgnoringBase {
27  
28    private static final long serialVersionUID = 1L;
29  
30    static int instanceCount = 0;
31  
32    /**
33     * The name of this logger
34     */
35    private String name;
36  
37    // The assigned levelInt of this logger. Can be null.
38    private Level level;
39  
40    // The effective levelInt is the assigned levelInt and if null, a levelInt is
41    // inherited form a parent.
42    private Level effectiveLevel;
43  
44    /**
45     * The parent of this category. All categories have at least one ancestor
46     * which is the root category.
47     */
48    HLogger parent;
49  
50    /**
51     * The children of this logger. A logger may have zero or more children.
52     */
53    Map<String, HLogger> childrenMap;
54  
55    /**
56     * Array of appenders.
57     */
58    private ArrayList<Appender<LoggingEvent>> appenderList;
59  
60    /**
61     * Additivity is set to true by default, that is children inherit the
62     * appenders of their ancestors by default. If this variable is set to
63     * <code>false</code> then the appenders located in the ancestors of this
64     * logger will not be used. However, the children of this logger will inherit
65     * its appenders, unless the children have their additivity flag set to
66     * <code>false</code> too. See the user manual for more details.
67     */
68    protected boolean additive = true;
69  
70    HLogger(String name, HLogger parent) {
71      this.name = name;
72      this.parent = parent;
73      instanceCount++;
74    }
75  
76    Level getEffectiveLevel() {
77      return effectiveLevel;
78    }
79  
80    Level getLevel() {
81      return level;
82    }
83  
84    public String getName() {
85      return name;
86    }
87  
88    private final boolean isRootLogger() {
89      // only the root logger has a null parent
90      return parent == null;
91    }
92  
93    /**
94     * Get a child by its suffix.
95     * 
96     * <p>
97     * IMPORTANT: Calls to this method must be within a syncronized block on this
98     * logger!
99     * 
100    * @param suffix
101    * @return
102    */
103   HLogger getChildBySuffix(final String suffix) {
104     if (childrenMap == null) {
105       return null;
106     } else {
107       return (HLogger) childrenMap.get(suffix);
108     }
109   }
110 
111   public synchronized void setLevel(Level newLevel) {
112     if (level == newLevel) {
113       // nothing to do;
114       return;
115     }
116 
117     level = newLevel;
118     effectiveLevel = newLevel;
119     if (childrenMap != null) {
120       for (Iterator i = childrenMap.values().iterator(); i.hasNext();) {
121         HLogger child = (HLogger) i.next();
122 
123         // tell child to handle parent levelInt change
124         child.handleParentLevelChange(effectiveLevel);
125       }
126     }
127   }
128 
129   /**
130    * This method is invoked by parent logger to let this logger know that the
131    * prent's levelInt changed.
132    * 
133    * @param newParentLevel
134    */
135   private synchronized void handleParentLevelChange(Level newParentLevel) {
136     // changes in the parent levelInt affect children only if their levelInt is
137     // null
138     if (level == null) {
139       effectiveLevel = newParentLevel;
140 
141       // propagate the parent levelInt change to this logger's children
142       if (childrenMap != null) {
143         for (Iterator i = childrenMap.values().iterator(); i.hasNext();) {
144           HLogger child = (HLogger) i.next();
145           // tell child to handle parent levelInt change
146           child.handleParentLevelChange(effectiveLevel);
147         }
148       }
149     }
150   }
151 
152   /**
153    * Remove all previously added appenders from this logger instance. <p/> This
154    * is useful when re-reading configuration information.
155    */
156   public synchronized void removeAllAppenders() {
157     if (appenderList != null) {
158       int len = appenderList.size();
159       for (int i = 0; i < len; i++) {
160         Appender a = appenderList.get(i);
161         a.stop();
162       }
163       appenderList.clear();
164       appenderList = null;
165     }
166   }
167 
168   /**
169    * Invoke all the appenders of this logger.
170    * 
171    * @param event
172    *          The event to log
173    */
174   public void callAppenders(LoggingEvent event) {
175     int writes = 0;
176 
177     for (HLogger l = this; l != null; l = l.parent) {
178       // Protected against simultaneous call to addAppender, removeAppender,...
179       synchronized (l) {
180         if (l.appenderList != null) {
181           writes += l.appendLoopOnAppenders(event);
182         }
183         if (!l.additive) {
184           break;
185         }
186       }
187     }
188 
189     // No appenders in hierarchy, warn user only once.
190     // if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
191     // LogLog.error("No appenders could be found for category (" +
192     // this.getName() + ").");
193     // LogLog.error("Please initialize the log4j system properly.");
194     // hierarchy.emittedNoAppenderWarning = true;
195     // }
196   }
197 
198   private int appendLoopOnAppenders(LoggingEvent event) {
199     int size = 0;
200     Appender<LoggingEvent> appender;
201 
202     if (appenderList != null) {
203       size = appenderList.size();
204       for (int i = 0; i < size; i++) {
205         appender = appenderList.get(i);
206         appender.doAppend(event);
207       }
208     }
209     return size;
210   }
211 
212   /**
213    * Remove the appender passed as parameter form the list of appenders.
214    */
215   public synchronized void removeAppender(Appender appender) {
216     if ((appender == null) || (appenderList == null)) {
217     }
218     appenderList.remove(appender);
219   }
220 
221   /**
222    * Create a child of this logger by suffix, that is, the part of the name
223    * extending this logger. For example, if this logger is named "x.y" and the
224    * lastPart is "z", then the created child logger will be named "x.y.z".
225    * 
226    * <p>
227    * IMPORTANT: Calls to this method must be within a syncronized block on this
228    * logger.
229    * 
230    * @param lastPart
231    *          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(ClassicGlobal.LOGGER_SEPARATOR);
238     if (i_index != -1) {
239       throw new IllegalArgumentException("Child name [" + lastPart
240           + " passed as parameter, may not include [" + ClassicGlobal.LOGGER_SEPARATOR
241           + "]");
242     }
243 
244     if (childrenMap == null) {
245       childrenMap = new HashMap<String, HLogger>(2);
246     }
247     HLogger childHLogger;
248     if (this.isRootLogger()) {
249       childHLogger = new HLogger(lastPart, this);
250     } else {
251       childHLogger = new HLogger(name + ClassicGlobal.LOGGER_SEPARATOR + lastPart,
252           this);
253     }
254     childrenMap.put(lastPart, childHLogger);
255     childHLogger.effectiveLevel = this.effectiveLevel;
256     return childHLogger;
257   }
258   
259   public final void trace(String msg) {
260     if (effectiveLevel.levelInt <= Level.TRACE_INT) {
261       throw new UnsupportedOperationException("not yet implemented");
262     }
263   }
264 
265   public void trace(String msg, Throwable t) {
266     // To change body of implemented methods use File | Settings | File
267     // Templates.
268   }
269 
270   public void trace(Object parameterizedMsg, Object param1) {
271     // To change body of implemented methods use File | Settings | File
272     // Templates.
273   }
274 
275   public void trace(String parameterizedMsg, Object param1, Object param2) {
276     // To change body of implemented methods use File | Settings | File
277     // Templates.
278   }
279 
280   
281 
282   public final void debug(String msg) {
283     if (effectiveLevel.levelInt <= Level.DEBUG_INT) {
284       throw new UnsupportedOperationException("not yet implemented");
285     }
286   }
287 
288   public void debug(String msg, Throwable t) {
289     // To change body of implemented methods use File | Settings | File
290     // Templates.
291   }
292 
293   public void debug(Object parameterizedMsg, Object param1) {
294     // To change body of implemented methods use File | Settings | File
295     // Templates.
296   }
297 
298   public void debug(String parameterizedMsg, Object param1, Object param2) {
299     // To change body of implemented methods use File | Settings | File
300     // Templates.
301   }
302 
303   public void error(String msg) {
304     // To change body of implemented methods use File | Settings | File
305     // Templates.
306   }
307 
308   public void error(String msg, Throwable t) {
309     // To change body of implemented methods use File | Settings | File
310     // Templates.
311   }
312 
313   public void error(String parameterizedMsg, Object param1) {
314     // To change body of implemented methods use File | Settings | File
315     // Templates.
316   }
317 
318   public void error(String parameterizedMsg, Object param1, Object param2) {
319     // To change body of implemented methods use File | Settings | File
320     // Templates.
321   }
322 
323   public void info(String msg) {
324     // To change body of implemented methods use File | Settings | File
325     // Templates.
326   }
327 
328   public void info(String msg, Throwable t) {
329     // To change body of implemented methods use File | Settings | File
330     // Templates.
331   }
332 
333   public void info(String parameterizedMsg, Object param1) {
334     // To change body of implemented methods use File | Settings | File
335     // Templates.
336   }
337 
338   public void info(String parameterizedMsg, Object param1, Object param2) {
339     // To change body of implemented methods use File | Settings | File
340     // Templates.
341   }
342 
343   public boolean isTraceEnabled() {
344     return false; 
345   }
346   
347   public boolean isDebugEnabled() {
348     return false; 
349   }
350 
351   public boolean isErrorEnabled() {
352     return false; // To change body of implemented methods use File | Settings |
353     // File Templates.
354   }
355 
356   public boolean isInfoEnabled() {
357     return false; // To change body of implemented methods use File | Settings |
358     // File Templates.
359   }
360 
361   public boolean isWarnEnabled() {
362     return false; // To change body of implemented methods use File | Settings |
363     // File Templates.
364   }
365 
366   public void warn(String msg) {
367     // To change body of implemented methods use File | Settings | File
368     // Templates.
369   }
370 
371   public void warn(String msg, Throwable t) {
372     // To change body of implemented methods use File | Settings | File
373     // Templates.
374   }
375 
376   public void warn(String parameterizedMsg, Object param1) {
377     // To change body of implemented methods use File | Settings | File
378     // Templates.
379   }
380 
381   public void warn(String parameterizedMsg, Object param1, Object param2) {
382     // To change body of implemented methods use File | Settings | File
383     // Templates.
384   }
385 
386   public void trace(String format, Object arg) {
387   }
388 
389   public void trace(String format, Object[] argArray) {
390   }
391   
392   public void debug(String format, Object arg) {
393   }
394 
395   public void debug(String format, Object[] argArray) {
396   }
397 
398   public void info(String format, Object[] argArray) {
399   }
400 
401   public void warn(String format, Object[] argArray) {
402   }
403 
404   public void error(String format, Object[] argArray) {
405   }
406 }