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     /**
    101      * @since 2.1
    102      */
    103     public static final String CATEGORY = "Level";
    104
    105     private final String name;
    106     private final int intLevel;
    107     private final StandardLevel standardLevel;
    108
    109     private Level(final String name, final int intLevel) {
    110         if (name == null || name.isEmpty()) {
    111             throw new IllegalArgumentException("Illegal null Level constant");
    112         }
    113         if (intLevel < 0) {
    114             throw new IllegalArgumentException("Illegal Level int less than zero.");
    115         }
    116         this.name = name;
    117         this.intLevel = intLevel;
    118         this.standardLevel = StandardLevel.getStandardLevel(intLevel);
    119         if (levels.putIfAbsent(name, this) != null) {
    120             throw new IllegalStateException("Level " + name + " has already been defined.");
    121         }
    122     }
    123
    124     /**
    125      * Gets the integral value of this Level.
    126      *
    127      * @return the value of this Level.
    128      */
    129     public int intLevel() {
    130         return this.intLevel;
    131     }
    132
    133     /**
    134      * Gets the standard Level values as an enum.
    135      *
    136      * @return an enum of the standard Levels.
    137      */
    138     public StandardLevel getStandardLevel() {
    139         return standardLevel;
    140     }
    141
    142     /**
    143      * Compares this level against the level passed as an argument and returns true if this level is the same or is less
    144      * specific.T
    145      *
    146      * @param level
    147      *            The level to test.
    148      * @return True if this level Level is less specific or the same as the given Level.
    149      */
    150     public boolean isLessSpecificThan(final Level level) {
    151         return this.intLevel >= level.intLevel;
    152     }
    153
    154     /**
    155      * Compares this level against the level passed as an argument and returns true if this level is the same or is more
    156      * specific.
    157      *
    158      * @param level
    159      *            The level to test.
    160      * @return True if this level Level is more specific or the same as the given Level.
    161      */
    162     public boolean isMoreSpecificThan(final Level level) {
    163         return this.intLevel <= level.intLevel;
    164     }
    165
    166     @Override
    167     @SuppressWarnings("CloneDoesntCallSuperClone")
    168     public Level clone() throws CloneNotSupportedException {
    169         throw new CloneNotSupportedException();
    170     }
    171
    172     @Override
    173     public int compareTo(final Level other) {
    174         return intLevel < other.intLevel ? -1 : (intLevel > other.intLevel ? 1 : 0);
    175     }
    176
    177     @Override
    178     public boolean equals(final Object other) {
    179         return other instanceof Level && other == this;
    180     }
    181
    182     public Class<Level> getDeclaringClass() {
    183         return Level.class;
    184     }
    185
    186     @Override
    187     public int hashCode() {
    188         return this.name.hashCode();
    189     }
    190
    191     /**
    192      * Gets the symbolic name of this Level. Equivalent to calling {@link #toString()}.
    193      *
    194      * @return the name of this Level.
    195      */
    196     public String name() {
    197         return this.name;
    198     }
    199
    200     @Override
    201     public String toString() {
    202         return this.name;
    203     }
    204
    205     /**
    206      * Retrieves an existing Level or creates on if it didn't previously exist.
    207      * @param name The name of the level.
    208      * @param intValue The integer value for the Level. If the level was previously created this value is ignored.
    209      * @return The Level.
    210      * @throws java.lang.IllegalArgumentException if the name is null or intValue is less than zero.
    211      */
    212     public static Level forName(final String name, final int intValue) {
    213         final Level level = levels.get(name);
    214         if (level != null) {
    215             return level;
    216         }
    217         try {
    218             return new Level(name, intValue);
    219         } catch (final IllegalStateException ex) {
    220             // The level was added by something else so just return that one.
    221             return levels.get(name);
    222         }
    223     }
    224
    225     /**
    226      * Return the Level associated with the name or null if the Level cannot be found.
    227      * @param name The name of the Level.
    228      * @return The Level or null.
    229      */
    230     public static Level getLevel(final String name) {
    231         return levels.get(name);
    232     }
    233
    234     /**
    235      * Converts the string passed as argument to a level. If the
    236      * conversion fails, then this method returns {@link #DEBUG}.
    237      *
    238      * @param sArg The name of the desired Level.
    239      * @return The Level associated with the String.
    240      */
    241     public static Level toLevel(final String sArg) {
    242         return toLevel(sArg, Level.DEBUG);
    243     }
    244
    245     /**
    246      * Converts the string passed as argument to a level. If the
    247      * conversion fails, then this method returns the value of
    248      * <code>defaultLevel</code>.
    249      *
    250      * @param name The name of the desired Level.
    251      * @param defaultLevel The Level to use if the String is invalid.
    252      * @return The Level associated with the String.
    253      */
    254     public static Level toLevel(final String name, final Level defaultLevel) {
    255         if (name == null) {
    256             return defaultLevel;
    257         }
    258         final Level level = levels.get(name.toUpperCase(Locale.ENGLISH));
    259         return level == null ? defaultLevel : level;
    260     }
    261
    262     /**
    263      * Return an array of all the Levels that have been registered.
    264      * @return An array of Levels.
    265      */
    266     public static Level[] values() {
    267         final Collection<Level> values = Level.levels.values();
    268         return values.toArray(new Level[values.size()]);
    269     }
    270
    271     /**
    272      * Return the Level associated with the name.
    273      * @param name The name of the Level to return.
    274      * @return The Level.
    275      * @throws java.lang.NullPointerException if the Level name is {@code null}.
    276      * @throws java.lang.IllegalArgumentException if the Level name is not registered.
    277      */
    278     public static Level valueOf(final String name) {
    279         if (name == null) {
    280             throw new NullPointerException("No level name given.");
    281         }
    282         final String levelName = name.toUpperCase(Locale.ENGLISH);
    283         if (levels.containsKey(levelName)) {
    284             return levels.get(levelName);
    285         }
    286         throw new IllegalArgumentException("Unknown level constant [" + levelName + "].");
    287     }
    288
    289     /**
    290      * Returns the enum constant of the specified enum type with the specified name. The name must match exactly an
    291      * identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
    292      *
    293      * @param enumType the {@code Class} object of the enum type from which to return a constant
    294      * @param name     the name of the constant to return
    295      * @param <T>      The enum type whose constant is to be returned
    296      * @return the enum constant of the specified enum type with the specified name
    297      * @throws java.lang.IllegalArgumentException if the specified enum type has no constant with the specified name,
    298      *                                            or the specified class object does not represent an enum type
    299      * @throws java.lang.NullPointerException     if {@code enumType} or {@code name} are {@code null}
    300      * @see java.lang.Enum#valueOf(Class, String)
    301      */
    302     public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) {
    303         return Enum.valueOf(enumType, name);
    304     }
    305
    306     // for deserialization
    307     protected Object readResolve() {
    308         return Level.valueOf(this.name);
    309     }
    310 }
    311