View Javadoc
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 syncronized 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 syncronized 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 }