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 org.slf4j.event.EventConstants;
17  import org.slf4j.spi.LocationAwareLogger;
18  
19  /**
20   * Defines the set of levels recognized by logback-classic, that is
21   * {@link #OFF}, {@link #ERROR}, {@link #WARN}, {@link #INFO}, {@link #DEBUG},
22   * {@link #TRACE} and {@link #ALL}.
23   * <p/>
24   * The <code>Level</code> class is final and cannot be sub-classed.
25   * </p>
26   */
27  public final class Level implements java.io.Serializable {
28  
29      private static final long serialVersionUID = -814092767334282137L;
30  
31      public static final int OFF_INT = Integer.MAX_VALUE;
32      public static final int ERROR_INT = 40000;
33      public static final int WARN_INT = 30000;
34      public static final int INFO_INT = 20000;
35      public static final int DEBUG_INT = 10000;
36      public static final int TRACE_INT = 5000;
37      public static final int ALL_INT = Integer.MIN_VALUE;
38  
39      public static final Integer OFF_INTEGER = OFF_INT;
40      public static final Integer ERROR_INTEGER = ERROR_INT;
41      public static final Integer WARN_INTEGER = WARN_INT;
42      public static final Integer INFO_INTEGER = INFO_INT;
43      public static final Integer DEBUG_INTEGER = DEBUG_INT;
44      public static final Integer TRACE_INTEGER = TRACE_INT;
45      public static final Integer ALL_INTEGER = ALL_INT;
46  
47      /**
48       * The <code>OFF</code> is used to turn off logging. It is intended to be used
49       * for logging system configuration.
50       *
51       * Warning: it should never be passed as an argument to logger methods
52       * in a regular log statement.
53       */
54      public static final Level OFF = new Level(OFF_INT, "OFF");
55  
56      /**
57       * The <code>ERROR</code> level designates error events which may or not be
58       * fatal to the application.
59       */
60      public static final Level ERROR = new Level(ERROR_INT, "ERROR");
61  
62      /**
63       * The <code>WARN</code> level designates potentially harmful situations.
64       */
65      public static final Level WARN = new Level(WARN_INT, "WARN");
66  
67      /**
68       * The <code>INFO</code> level designates informational messages highlighting
69       * overall progress of the application.
70       */
71      public static final Level INFO = new Level(INFO_INT, "INFO");
72  
73      /**
74       * The <code>DEBUG</code> level designates informational events of lower
75       * importance.
76       */
77      public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG");
78  
79      /**
80       * The <code>TRACE</code> level designates informational events of very low
81       * importance.
82       */
83      public static final Level TRACE = new Level(TRACE_INT, "TRACE");
84  
85      /**
86       * <p>The <code>ALL</code> is used to turn on all logging. The <code>ALL</code> level is vestigial from
87       * log4j 1.x.
88       * </p>
89       *
90       * <p>In logback, where the Level class is final, logging can be turned on for all levels by setting
91       * a logger's level to <code>TRACE</code>.
92       * </p>
93       *
94       * <p>Thus, the <code>ALL</code> level is marked as deprecated.
95       * </p>
96       *
97       * @deprecated with no replacement
98       */
99      public static final Level ALL = new Level(ALL_INT, "ALL");
100 
101     public final int levelInt;
102     public final String levelStr;
103 
104     /**
105      * Instantiate a Level object.
106      */
107     private Level(int levelInt, String levelStr) {
108         this.levelInt = levelInt;
109         this.levelStr = levelStr;
110     }
111 
112     /**
113      * Returns the string representation of this Level.
114      */
115     public String toString() {
116         return levelStr;
117     }
118 
119     /**
120      * Returns the integer representation of this Level.
121      */
122     public int toInt() {
123         return levelInt;
124     }
125 
126     static public Level convertAnSLF4JLevel(org.slf4j.event.Level slf4jLevel) {
127         final int levelInt = slf4jLevel.toInt();
128         return fromLocationAwareLoggerInteger(levelInt);
129     }
130 
131     /**
132      * Convert a Level to an Integer object.
133      *
134      * @return This level's Integer mapping.
135      */
136     public Integer toInteger() {
137         switch (levelInt) {
138         case ALL_INT:
139             return ALL_INTEGER;
140         case TRACE_INT:
141             return TRACE_INTEGER;
142         case DEBUG_INT:
143             return DEBUG_INTEGER;
144         case INFO_INT:
145             return INFO_INTEGER;
146         case WARN_INT:
147             return WARN_INTEGER;
148         case ERROR_INT:
149             return ERROR_INTEGER;
150         case OFF_INT:
151             return OFF_INTEGER;
152         default:
153             throw new IllegalStateException("Level " + levelStr + ", " + levelInt + " is unknown.");
154         }
155     }
156 
157     /**
158      * Returns <code>true</code> if this Level has a higher or equal Level than the
159      * Level passed as argument, <code>false</code> otherwise.
160      */
161     public boolean isGreaterOrEqual(Level r) {
162         return levelInt >= r.levelInt;
163     }
164 
165     /**
166      * Convert the string passed as argument to a Level. If the conversion fails,
167      * then this method returns {@link #DEBUG}.
168      */
169     public static Level toLevel(String sArg) {
170         return toLevel(sArg, Level.DEBUG);
171     }
172 
173     /**
174      * This method exists in order to comply with Joran's valueOf convention.
175      *
176      * @param sArg
177      * @return
178      */
179     public static Level valueOf(String sArg) {
180         return toLevel(sArg, Level.DEBUG);
181     }
182 
183     /**
184      * Convert an integer passed as argument to a Level. If the conversion fails,
185      * then this method returns {@link #DEBUG}.
186      */
187     public static Level toLevel(int val) {
188         return toLevel(val, Level.DEBUG);
189     }
190 
191     /**
192      * Convert an integer passed as argument to a Level. If the conversion fails,
193      * then this method returns the specified default.
194      */
195     public static Level toLevel(int val, Level defaultLevel) {
196         switch (val) {
197         case ALL_INT:
198             return ALL;
199         case TRACE_INT:
200             return TRACE;
201         case DEBUG_INT:
202             return DEBUG;
203         case INFO_INT:
204             return INFO;
205         case WARN_INT:
206             return WARN;
207         case ERROR_INT:
208             return ERROR;
209         case OFF_INT:
210             return OFF;
211         default:
212             return defaultLevel;
213         }
214     }
215 
216     /**
217      * Convert the string passed as argument to a Level. If the conversion fails,
218      * then this method returns the value of <code>defaultLevel</code>.
219      */
220     public static Level toLevel(final String sArg, Level defaultLevel) {
221         if (sArg == null) {
222             return defaultLevel;
223         }
224 
225         // see LOGBACK-1288
226         final String in = sArg.trim();
227 
228         if (in.equalsIgnoreCase("ALL")) {
229             return Level.ALL;
230         }
231         if (in.equalsIgnoreCase("TRACE")) {
232             return Level.TRACE;
233         }
234         if (in.equalsIgnoreCase("DEBUG")) {
235             return Level.DEBUG;
236         }
237         if (in.equalsIgnoreCase("INFO")) {
238             return Level.INFO;
239         }
240         if (in.equalsIgnoreCase("WARN")) {
241             return Level.WARN;
242         }
243         if (in.equalsIgnoreCase("ERROR")) {
244             return Level.ERROR;
245         }
246         if (in.equalsIgnoreCase("OFF")) {
247             return Level.OFF;
248         }
249         return defaultLevel;
250     }
251 
252     /**
253      * Return the flyweight instance of the level received through serialization,
254      * i.e. 'this'.
255      *
256      * @return The appropriate flyweight instance
257      */
258     private Object readResolve() {
259         return toLevel(this.levelInt);
260     }
261 
262     /**
263      * Convert one of the integer values defined in {@link LocationAwareLogger}
264      * interface to an instance of this class, i.e. a Level.
265      *
266      * @param levelInt An integer value representing a level as defined in
267      *                 LocationAwareLogger
268      * @return an instance of this class, i.e. a Level.
269      * @since 1.0.1
270      */
271     public static Level fromLocationAwareLoggerInteger(int levelInt) {
272         Level level;
273         switch (levelInt) {
274         case EventConstants.TRACE_INT:
275             level = TRACE;
276             break;
277         case EventConstants.DEBUG_INT:
278             level = DEBUG;
279             break;
280         case EventConstants.INFO_INT:
281             level = INFO;
282             break;
283         case EventConstants.WARN_INT:
284             level = WARN;
285             break;
286         case EventConstants.ERROR_INT:
287             level = ERROR;
288             break;
289         default:
290             throw new IllegalArgumentException(levelInt + " not a valid level value");
291         }
292         return level;
293     }
294 
295     /**
296      * Convert this level instance to an integer value defined in the
297      * {@link LocationAwareLogger} interface.
298      *
299      * @param level The level to convert to LocationAwareLogger integer
300      * @return int An integer corresponding to this level as defined in
301      *         LocationAwareLogger
302      * @since 1.0.1
303      */
304     public static int toLocationAwareLoggerInteger(Level level) {
305         if (level == null)
306             throw new IllegalArgumentException("null level parameter is not admitted");
307         switch (level.toInt()) {
308         case Level.TRACE_INT:
309             return EventConstants.TRACE_INT;
310         case Level.DEBUG_INT:
311             return EventConstants.DEBUG_INT;
312         case Level.INFO_INT:
313             return EventConstants.INFO_INT;
314         case Level.WARN_INT:
315             return EventConstants.WARN_INT;
316         case Level.ERROR_INT:
317             return EventConstants.ERROR_INT;
318         default:
319             throw new IllegalArgumentException(level + " not a valid level value");
320         }
321     }
322 }