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 org.slf4j.event.EventConstants;
017import org.slf4j.spi.LocationAwareLogger;
018
019/**
020 * Defines the set of levels recognized by logback-classic, that is
021 * {@link #OFF}, {@link #ERROR}, {@link #WARN}, {@link #INFO}, {@link #DEBUG},
022 * {@link #TRACE} and {@link #ALL}.
023 * <p/>
024 * The <code>Level</code> class is final and cannot be sub-classed.
025 * </p>
026 */
027public final class Level implements java.io.Serializable {
028
029    private static final long serialVersionUID = -814092767334282137L;
030
031    public static final int OFF_INT = Integer.MAX_VALUE;
032    public static final int ERROR_INT = 40000;
033    public static final int WARN_INT = 30000;
034    public static final int INFO_INT = 20000;
035    public static final int DEBUG_INT = 10000;
036    public static final int TRACE_INT = 5000;
037    public static final int ALL_INT = Integer.MIN_VALUE;
038
039    public static final Integer OFF_INTEGER = OFF_INT;
040    public static final Integer ERROR_INTEGER = ERROR_INT;
041    public static final Integer WARN_INTEGER = WARN_INT;
042    public static final Integer INFO_INTEGER = INFO_INT;
043    public static final Integer DEBUG_INTEGER = DEBUG_INT;
044    public static final Integer TRACE_INTEGER = TRACE_INT;
045    public static final Integer ALL_INTEGER = ALL_INT;
046
047    /**
048     * The <code>OFF</code> is used to turn off logging. It is intended to be used
049     * for logging system configuration.
050     *
051     * Warning: it should never be passed as an argument to logger methods
052     * in a regular log statement.
053     */
054    public static final Level OFF = new Level(OFF_INT, "OFF");
055
056    /**
057     * The <code>ERROR</code> level designates error events which may or not be
058     * fatal to the application.
059     */
060    public static final Level ERROR = new Level(ERROR_INT, "ERROR");
061
062    /**
063     * The <code>WARN</code> level designates potentially harmful situations.
064     */
065    public static final Level WARN = new Level(WARN_INT, "WARN");
066
067    /**
068     * The <code>INFO</code> level designates informational messages highlighting
069     * overall progress of the application.
070     */
071    public static final Level INFO = new Level(INFO_INT, "INFO");
072
073    /**
074     * The <code>DEBUG</code> level designates informational events of lower
075     * importance.
076     */
077    public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG");
078
079    /**
080     * The <code>TRACE</code> level designates informational events of very low
081     * importance.
082     */
083    public static final Level TRACE = new Level(TRACE_INT, "TRACE");
084
085    /**
086     * <p>The <code>ALL</code> is used to turn on all logging. The <code>ALL</code> level is vestigial from
087     * log4j 1.x.
088     * </p>
089     *
090     * <p>In logback, where the Level class is final, logging can be turned on for all levels by setting
091     * a logger's level to <code>TRACE</code>.
092     * </p>
093     *
094     * <p>Thus, the <code>ALL</code> level is marked as deprecated.
095     * </p>
096     *
097     * @deprecated with no replacement
098     */
099    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}