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)</li>
31   * <li>{@link #FATAL}</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}</li>
37   * <li>{@link #ALL} (least specific)</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 = 3077535362528045615L;
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(String name, int intLevel) {
105         if (name == null || name.length() == 0) {
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
129      * level is the same or more specific.
130      *
131      * @param level The level to check.
132      * @return True if the passed Level is more specific or the same as this Level.
133      */
134     public boolean isAtLeastAsSpecificAs(final Level level) {
135         return this.intLevel <= level.intLevel;
136     }
137 
138     /**
139      * Compares this level against the level passed as an argument and returns true if this
140      * level is the same or more specific.
141      *
142      * @param level The level to check.
143      * @return True if the passed Level is more specific or the same as this Level.
144      */
145     public boolean isAtLeastAsSpecificAs(final int level) {
146         return this.intLevel <= level;
147     }
148 
149     /**
150      * Compares the specified Level against this one.
151      * @param level The level to check.
152      * @return True if the passed Level is more specific or the same as this Level.
153      */
154     public boolean lessOrEqual(final Level level) {
155         return this.intLevel <= level.intLevel;
156     }
157 
158     /**
159      * Compares the specified Level against this one.
160      * @param level The level to check.
161      * @return True if the passed Level is more specific or the same as this Level.
162      */
163     public boolean lessOrEqual(final int level) {
164         return this.intLevel <= level;
165     }
166 
167     @Override
168     @SuppressWarnings("CloneDoesntCallSuperClone")
169     public Level clone() throws CloneNotSupportedException {
170         throw new CloneNotSupportedException();
171     }
172 
173     @Override
174     public int compareTo(Level other) {
175         return intLevel < other.intLevel ? -1 : (intLevel > other.intLevel ? 1 : 0);
176     }
177 
178     @Override
179     public boolean equals(Object other) {
180         return other instanceof Level && other == this;
181     }
182 
183     public Class<Level> getDeclaringClass() {
184         return Level.class;
185     }
186 
187     @Override
188     public int hashCode() {
189         return this.name.hashCode();
190     }
191 
192 
193     public String name() {
194         return this.name;
195     }
196 
197     @Override
198     public String toString() {
199         return this.name;
200     }
201 
202     /**
203      * Retrieves an existing Level or creates on if it didn't previously exist.
204      * @param name The name of the level.
205      * @param intValue The integer value for the Level. If the level was previously created this value is ignored.
206      * @return The Level.
207      * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero.
208      */
209     public static Level forName(String name, int intValue) {
210         Level level = levels.get(name);
211         if (level != null) {
212             return level;
213         }
214         try {
215             return new Level(name, intValue);
216         } catch (IllegalStateException ex) {
217             // The level was added by something else so just return that one.
218             return levels.get(name);
219         }
220     }
221 
222     /**
223      * Return the Level assoicated with the name or null if the Level cannot be found.
224      * @param name The name of the Level.
225      * @return The Level or null.
226      */
227     public static Level getLevel(String name) {
228         return levels.get(name);
229     }
230 
231     /**
232      * Converts the string passed as argument to a level. If the
233      * conversion fails, then this method returns {@link #DEBUG}.
234      *
235      * @param sArg The name of the desired Level.
236      * @return The Level associated with the String.
237      */
238     public static Level toLevel(final String sArg) {
239         return toLevel(sArg, Level.DEBUG);
240     }
241 
242     /**
243      * Converts the string passed as argument to a level. If the
244      * conversion fails, then this method returns the value of
245      * <code>defaultLevel</code>.
246      *
247      * @param name The name of the desired Level.
248      * @param defaultLevel The Level to use if the String is invalid.
249      * @return The Level associated with the String.
250      */
251     public static Level toLevel(final String name, final Level defaultLevel) {
252         if (name == null) {
253             return defaultLevel;
254         }
255         Level level = levels.get(name.toUpperCase(Locale.ENGLISH));
256         return level == null ? defaultLevel : level;
257     }
258 
259     /**
260      * Return an array of all the Levels that have been registered.
261      * @return An array of Levels.
262      */
263     public static Level[] values() {
264         Collection<Level> values = Level.levels.values();
265         return values.toArray(new Level[values.size()]);
266     }
267 
268     /**
269      * Return the Level associated with the name.
270      * @param name The name of the Level to return.
271      * @return The Level.
272      * @throws java.lang.IllegalArgumentException if the Level name is not registered.
273      */
274     public static Level valueOf(String name) {
275         if (name == null) {
276             throw new IllegalArgumentException("Unknown level constant [" + name + "].");
277         }
278         name = name.toUpperCase();
279         if (levels.containsKey(name)) {
280             return levels.get(name);
281         }
282         throw new IllegalArgumentException("Unknown level constant [" + name + "].");
283     }
284 
285     public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
286         return Enum.valueOf(enumType, name);
287     }
288 
289     // for deserialization
290     protected Object readResolve() {
291         return Level.valueOf(this.name);
292     }
293 }
294