001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.log4j;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.io.ObjectStreamException;
023import java.io.Serializable;
024
025/**
026 * Defines the minimum set of levels recognized by the system, that is
027 * <code>OFF</code>, <code>FATAL</code>, <code>ERROR</code>,
028 * <code>WARN</code>, <code>INFO</code, <code>DEBUG</code>
029 * and
030 * <code>ALL</code>.
031 * <p/>
032 * <p>The <code>Level</code> class may be subclassed to define a larger
033 * level set.
034 */
035public class Level extends Priority implements Serializable {
036
037    /**
038     * TRACE level integer value.
039     *
040     * @since 1.2.12
041     */
042    public static final int TRACE_INT = 5000;
043
044    /**
045     * The <code>OFF</code> has the highest possible rank and is
046     * intended to turn off logging.
047     */
048    public static final Level OFF = new Level(OFF_INT, "OFF", 0);
049
050    /**
051     * The <code>FATAL</code> level designates very severe error
052     * events that will presumably lead the application to abort.
053     */
054    public static final Level FATAL = new Level(FATAL_INT, "FATAL", 0);
055
056    /**
057     * The <code>ERROR</code> level designates error events that
058     * might still allow the application to continue running.
059     */
060    public static final Level ERROR = new Level(ERROR_INT, "ERROR", 3);
061
062    /**
063     * The <code>WARN</code> level designates potentially harmful situations.
064     */
065    public static final Level WARN = new Level(WARN_INT, "WARN", 4);
066
067    /**
068     * The <code>INFO</code> level designates informational messages
069     * that highlight the progress of the application at coarse-grained
070     * level.
071     */
072    public static final Level INFO = new Level(INFO_INT, "INFO", 6);
073
074    /**
075     * The <code>DEBUG</code> Level designates fine-grained
076     * informational events that are most useful to debug an
077     * application.
078     */
079    public static final Level DEBUG = new Level(DEBUG_INT, "DEBUG", 7);
080
081    /**
082     * The <code>TRACE</code> Level designates finer-grained
083     * informational events than the <code>DEBUG</code> level.
084     */
085    public static final Level TRACE = new Level(TRACE_INT, "TRACE", 7);
086
087    /**
088     * The <code>ALL</code> has the lowest possible rank and is intended to
089     * turn on all logging.
090     */
091    public static final Level ALL = new Level(ALL_INT, "ALL", 7);
092
093    /**
094     * Serialization version id.
095     */
096    private static final long serialVersionUID = 3491141966387921974L;
097
098    /**
099     * Instantiate a Level object.
100     *
101     * @param level            The logging level.
102     * @param levelStr         The level name.
103     * @param syslogEquivalent The matching syslog level.
104     */
105    protected Level(final int level, final String levelStr, final int syslogEquivalent) {
106        super(level, levelStr, syslogEquivalent);
107    }
108
109
110    /**
111     * Convert the string passed as argument to a level. If the
112     * conversion fails, then this method returns {@link #DEBUG}.
113     *
114     * @param sArg The level name.
115     * @return The Level.
116     */
117    public static Level toLevel(final String sArg) {
118        return toLevel(sArg, Level.DEBUG);
119    }
120
121    /**
122     * Convert an integer passed as argument to a level. If the
123     * conversion fails, then this method returns {@link #DEBUG}.
124     *
125     * @param val The integer value of the Level.
126     * @return The Level.
127     */
128    public static Level toLevel(final int val) {
129        return toLevel(val, Level.DEBUG);
130    }
131
132    /**
133     * Convert an integer passed as argument to a level. If the
134     * conversion fails, then this method returns the specified default.
135     *
136     * @param val          The integer value of the Level.
137     * @param defaultLevel the default level if the integer doesn't match.
138     * @return The matching Level.
139     */
140    public static Level toLevel(final int val, final Level defaultLevel) {
141        switch (val) {
142            case ALL_INT:
143                return ALL;
144            case DEBUG_INT:
145                return Level.DEBUG;
146            case INFO_INT:
147                return Level.INFO;
148            case WARN_INT:
149                return Level.WARN;
150            case ERROR_INT:
151                return Level.ERROR;
152            case FATAL_INT:
153                return Level.FATAL;
154            case OFF_INT:
155                return OFF;
156            case TRACE_INT:
157                return Level.TRACE;
158            default:
159                return defaultLevel;
160        }
161    }
162
163    /**
164     * Convert the string passed as argument to a level. If the
165     * conversion fails, then this method returns the value of
166     * <code>defaultLevel</code>.
167     * @param sArg The name of the Level.
168     * @param defaultLevel The default Level to use.
169     * @return the matching Level.
170     */
171    public static Level toLevel(final String sArg, final Level defaultLevel) {
172        if (sArg == null) {
173            return defaultLevel;
174        }
175
176        final String s = sArg.toUpperCase();
177
178        if (s.equals("ALL")) {
179            return Level.ALL;
180        }
181        if (s.equals("DEBUG")) {
182            return Level.DEBUG;
183        }
184        if (s.equals("INFO")) {
185            return Level.INFO;
186        }
187        if (s.equals("WARN")) {
188            return Level.WARN;
189        }
190        if (s.equals("ERROR")) {
191            return Level.ERROR;
192        }
193        if (s.equals("FATAL")) {
194            return Level.FATAL;
195        }
196        if (s.equals("OFF")) {
197            return Level.OFF;
198        }
199        if (s.equals("TRACE")) {
200            return Level.TRACE;
201        }
202        //
203        //   For Turkish i problem, see bug 40937
204        //
205        if (s.equals("\u0130NFO")) {
206            return Level.INFO;
207        }
208        return defaultLevel;
209    }
210
211    /**
212     * Custom deserialization of Level.
213     *
214     * @param s serialization stream.
215     * @throws IOException            if IO exception.
216     * @throws ClassNotFoundException if class not found.
217     */
218    private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
219        s.defaultReadObject();
220        level = s.readInt();
221        syslogEquivalent = s.readInt();
222        levelStr = s.readUTF();
223        if (levelStr == null) {
224            levelStr = "";
225        }
226    }
227
228    /**
229     * Serialize level.
230     *
231     * @param s serialization stream.
232     * @throws IOException if exception during serialization.
233     */
234    private void writeObject(final ObjectOutputStream s) throws IOException {
235        s.defaultWriteObject();
236        s.writeInt(level);
237        s.writeInt(syslogEquivalent);
238        s.writeUTF(levelStr);
239    }
240
241    /**
242     * Resolved deserialized level to one of the stock instances.
243     * May be overridden in classes derived from Level.
244     *
245     * @return resolved object.
246     * @throws ObjectStreamException if exception during resolution.
247     */
248    protected Object readResolve() throws ObjectStreamException {
249        //
250        //  if the deserialized object is exactly an instance of Level
251        //
252        if (getClass() == Level.class) {
253            return toLevel(level);
254        }
255        //
256        //   extension of Level can't substitute stock item
257        //
258        return this;
259    }
260
261}
262