View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Locale;
22  import java.util.concurrent.ConcurrentHashMap;
23  import java.util.concurrent.ConcurrentMap;
24  
25  import org.apache.logging.log4j.spi.StandardLevel;
26  
27  /**
28   * Levels used for identifying the severity of an event. Levels are organized from most specific to least:
29   * <ul>
30   * <li>{@link #OFF} (most specific, no logging)</li>
31   * <li>{@link #FATAL} (most specific, little data)</li>
32   * <li>{@link #ERROR}</li>
33   * <li>{@link #WARN}</li>
34   * <li>{@link #INFO}</li>
35   * <li>{@link #DEBUG}</li>
36   * <li>{@link #TRACE} (least specific, a lot of data)</li>
37   * <li>{@link #ALL} (least specific, all data)</li>
38   * </ul>
39   *
40   * Typically, configuring a level in a filter or on a logger will cause logging events of that level and those
41   * that are more specific to pass through the filter.
42   * A special level, {@link #ALL}, is guaranteed to capture all levels when used in logging configurations.
43   */
44  public final class Level implements Comparable<Level>, Serializable {
45  
46      private static final long serialVersionUID = 1581082L;
47      private static final ConcurrentMap<String, Level> levels = new ConcurrentHashMap<String, Level>();
48  
49      /**
50       * No events will be logged.
51       */
52      public static final Level OFF;
53  
54      /**
55       * A severe error that will prevent the application from continuing.
56       */
57      public static final Level FATAL;
58  
59      /**
60       * An error in the application, possibly recoverable.
61       */
62      public static final Level ERROR;
63  
64      /**
65       * An event that might possible lead to an error.
66       */
67      public static final Level WARN;
68  
69      /**
70       * An event for informational purposes.
71       */
72      public static final Level INFO;
73  
74      /**
75       * A general debugging event.
76       */
77      public static final Level DEBUG;
78  
79      /**
80       * A fine-grained debug message, typically capturing the flow through the application.
81       */
82      public static final Level TRACE;
83  
84      /**
85       * All events should be logged.
86       */
87      public static final Level ALL;
88  
89      static {
90          OFF = new Level("OFF", StandardLevel.OFF.intLevel());
91          FATAL = new Level("FATAL", StandardLevel.FATAL.intLevel());
92          ERROR = new Level("ERROR", StandardLevel.ERROR.intLevel());
93          WARN = new Level("WARN", StandardLevel.WARN.intLevel());
94          INFO = new Level("INFO", StandardLevel.INFO.intLevel());
95          DEBUG = new Level("DEBUG", StandardLevel.DEBUG.intLevel());
96          TRACE = new Level("TRACE", StandardLevel.TRACE.intLevel());
97          ALL = new Level("ALL", StandardLevel.ALL.intLevel());
98      }
99  
100     private final String name;
101     private final int intLevel;
102     private final StandardLevel standardLevel;
103 
104     private Level(final String name, final int intLevel) {
105         if (name == null || name.isEmpty()) {
106             throw new IllegalArgumentException("Illegal null Level constant");
107         }
108         if (intLevel < 0) {
109             throw new IllegalArgumentException("Illegal Level int less than zero.");
110         }
111         this.name = name;
112         this.intLevel = intLevel;
113         this.standardLevel = StandardLevel.getStandardLevel(intLevel);
114         if (levels.putIfAbsent(name, this) != null) {
115             throw new IllegalStateException("Level " + name + " has already been defined.");
116         }
117     }
118 
119     public int intLevel() {
120         return this.intLevel;
121     }
122 
123     public StandardLevel getStandardLevel() {
124         return standardLevel;
125     }
126 
127     /**
128      * Compares this level against the level passed as an argument and returns true if this level is the same or is less
129      * specific.T
130      *
131      * @param level
132      *            The level to test.
133      * @return True if this level Level is less specific or the same as the given Level.
134      */
135     public boolean isLessSpecificThan(final Level level) {
136         return this.intLevel >= level.intLevel;
137     }
138 
139     /**
140      * Compares this level against the level passed as an argument and returns true if this level is the same or is more
141      * specific.
142      *
143      * @param level
144      *            The level to test.
145      * @return True if this level Level is more specific or the same as the given Level.
146      */
147     public boolean isMoreSpecificThan(final Level level) {
148         return this.intLevel <= level.intLevel;
149     }
150 
151     @Override
152     @SuppressWarnings("CloneDoesntCallSuperClone")
153     public Level clone() throws CloneNotSupportedException {
154         throw new CloneNotSupportedException();
155     }
156 
157     @Override
158     public int compareTo(Level other) {
159         return intLevel < other.intLevel ? -1 : (intLevel > other.intLevel ? 1 : 0);
160     }
161 
162     @Override
163     public boolean equals(Object other) {
164         return other instanceof Level && other == this;
165     }
166 
167     public Class<Level> getDeclaringClass() {
168         return Level.class;
169     }
170 
171     @Override
172     public int hashCode() {
173         return this.name.hashCode();
174     }
175 
176 
177     public String name() {
178         return this.name;
179     }
180 
181     @Override
182     public String toString() {
183         return this.name;
184     }
185 
186     /**
187      * Retrieves an existing Level or creates on if it didn't previously exist.
188      * @param name The name of the level.
189      * @param intValue The integer value for the Level. If the level was previously created this value is ignored.
190      * @return The Level.
191      * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero.
192      */
193     public static Level forName(final String name, final int intValue) {
194         Level level = levels.get(name);
195         if (level != null) {
196             return level;
197         }
198         try {
199             return new Level(name, intValue);
200         } catch (IllegalStateException ex) {
201             // The level was added by something else so just return that one.
202             return levels.get(name);
203         }
204     }
205 
206     /**
207      * Return the Level associated with the name or null if the Level cannot be found.
208      * @param name The name of the Level.
209      * @return The Level or null.
210      */
211     public static Level getLevel(final String name) {
212         return levels.get(name);
213     }
214 
215     /**
216      * Converts the string passed as argument to a level. If the
217      * conversion fails, then this method returns {@link #DEBUG}.
218      *
219      * @param sArg The name of the desired Level.
220      * @return The Level associated with the String.
221      */
222     public static Level toLevel(final String sArg) {
223         return toLevel(sArg, Level.DEBUG);
224     }
225 
226     /**
227      * Converts the string passed as argument to a level. If the
228      * conversion fails, then this method returns the value of
229      * <code>defaultLevel</code>.
230      *
231      * @param name The name of the desired Level.
232      * @param defaultLevel The Level to use if the String is invalid.
233      * @return The Level associated with the String.
234      */
235     public static Level toLevel(final String name, final Level defaultLevel) {
236         if (name == null) {
237             return defaultLevel;
238         }
239         Level level = levels.get(name.toUpperCase(Locale.ENGLISH));
240         return level == null ? defaultLevel : level;
241     }
242 
243     /**
244      * Return an array of all the Levels that have been registered.
245      * @return An array of Levels.
246      */
247     public static Level[] values() {
248         Collection<Level> values = Level.levels.values();
249         return values.toArray(new Level[values.size()]);
250     }
251 
252     /**
253      * Return the Level associated with the name.
254      * @param name The name of the Level to return.
255      * @return The Level.
256      * @throws java.lang.NullPointerException if the Level name is {@code null}.
257      * @throws java.lang.IllegalArgumentException if the Level name is not registered.
258      */
259     public static Level valueOf(final String name) {
260         if (name == null) {
261             throw new NullPointerException("No level name given.");
262         }
263         final String levelName = name.toUpperCase();
264         if (levels.containsKey(levelName)) {
265             return levels.get(levelName);
266         }
267         throw new IllegalArgumentException("Unknown level constant [" + levelName + "].");
268     }
269 
270     public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) {
271         return Enum.valueOf(enumType, name);
272     }
273 
274     // for deserialization
275     protected Object readResolve() {
276         return Level.valueOf(this.name);
277     }
278 }
279