emul/compact/src/main/java/java/util/logging/Level.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 07 Sep 2013 13:51:24 +0200
branchjdk7-b147
changeset 1258 724f3e1ea53e
permissions -rw-r--r--
Additional set of classes to make porting of lookup library more easier
     1 /*
     2  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.util.logging;
    27 import java.util.ResourceBundle;
    28 
    29 /**
    30  * The Level class defines a set of standard logging levels that
    31  * can be used to control logging output.  The logging Level objects
    32  * are ordered and are specified by ordered integers.  Enabling logging
    33  * at a given level also enables logging at all higher levels.
    34  * <p>
    35  * Clients should normally use the predefined Level constants such
    36  * as Level.SEVERE.
    37  * <p>
    38  * The levels in descending order are:
    39  * <ul>
    40  * <li>SEVERE (highest value)
    41  * <li>WARNING
    42  * <li>INFO
    43  * <li>CONFIG
    44  * <li>FINE
    45  * <li>FINER
    46  * <li>FINEST  (lowest value)
    47  * </ul>
    48  * In addition there is a level OFF that can be used to turn
    49  * off logging, and a level ALL that can be used to enable
    50  * logging of all messages.
    51  * <p>
    52  * It is possible for third parties to define additional logging
    53  * levels by subclassing Level.  In such cases subclasses should
    54  * take care to chose unique integer level values and to ensure that
    55  * they maintain the Object uniqueness property across serialization
    56  * by defining a suitable readResolve method.
    57  *
    58  * @since 1.4
    59  */
    60 
    61 public class Level implements java.io.Serializable {
    62     private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
    63     private static String defaultBundle = "sun.util.logging.resources.logging";
    64 
    65     /**
    66      * @serial  The non-localized name of the level.
    67      */
    68     private final String name;
    69 
    70     /**
    71      * @serial  The integer value of the level.
    72      */
    73     private final int value;
    74 
    75     /**
    76      * @serial The resource bundle name to be used in localizing the level name.
    77      */
    78     private final String resourceBundleName;
    79 
    80     /**
    81      * OFF is a special level that can be used to turn off logging.
    82      * This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
    83      */
    84     public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
    85 
    86     /**
    87      * SEVERE is a message level indicating a serious failure.
    88      * <p>
    89      * In general SEVERE messages should describe events that are
    90      * of considerable importance and which will prevent normal
    91      * program execution.   They should be reasonably intelligible
    92      * to end users and to system administrators.
    93      * This level is initialized to <CODE>1000</CODE>.
    94      */
    95     public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
    96 
    97     /**
    98      * WARNING is a message level indicating a potential problem.
    99      * <p>
   100      * In general WARNING messages should describe events that will
   101      * be of interest to end users or system managers, or which
   102      * indicate potential problems.
   103      * This level is initialized to <CODE>900</CODE>.
   104      */
   105     public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
   106 
   107     /**
   108      * INFO is a message level for informational messages.
   109      * <p>
   110      * Typically INFO messages will be written to the console
   111      * or its equivalent.  So the INFO level should only be
   112      * used for reasonably significant messages that will
   113      * make sense to end users and system administrators.
   114      * This level is initialized to <CODE>800</CODE>.
   115      */
   116     public static final Level INFO = new Level("INFO", 800, defaultBundle);
   117 
   118     /**
   119      * CONFIG is a message level for static configuration messages.
   120      * <p>
   121      * CONFIG messages are intended to provide a variety of static
   122      * configuration information, to assist in debugging problems
   123      * that may be associated with particular configurations.
   124      * For example, CONFIG message might include the CPU type,
   125      * the graphics depth, the GUI look-and-feel, etc.
   126      * This level is initialized to <CODE>700</CODE>.
   127      */
   128     public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
   129 
   130     /**
   131      * FINE is a message level providing tracing information.
   132      * <p>
   133      * All of FINE, FINER, and FINEST are intended for relatively
   134      * detailed tracing.  The exact meaning of the three levels will
   135      * vary between subsystems, but in general, FINEST should be used
   136      * for the most voluminous detailed output, FINER for somewhat
   137      * less detailed output, and FINE for the  lowest volume (and
   138      * most important) messages.
   139      * <p>
   140      * In general the FINE level should be used for information
   141      * that will be broadly interesting to developers who do not have
   142      * a specialized interest in the specific subsystem.
   143      * <p>
   144      * FINE messages might include things like minor (recoverable)
   145      * failures.  Issues indicating potential performance problems
   146      * are also worth logging as FINE.
   147      * This level is initialized to <CODE>500</CODE>.
   148      */
   149     public static final Level FINE = new Level("FINE", 500, defaultBundle);
   150 
   151     /**
   152      * FINER indicates a fairly detailed tracing message.
   153      * By default logging calls for entering, returning, or throwing
   154      * an exception are traced at this level.
   155      * This level is initialized to <CODE>400</CODE>.
   156      */
   157     public static final Level FINER = new Level("FINER", 400, defaultBundle);
   158 
   159     /**
   160      * FINEST indicates a highly detailed tracing message.
   161      * This level is initialized to <CODE>300</CODE>.
   162      */
   163     public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
   164 
   165     /**
   166      * ALL indicates that all messages should be logged.
   167      * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
   168      */
   169     public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
   170 
   171     /**
   172      * Create a named Level with a given integer value.
   173      * <p>
   174      * Note that this constructor is "protected" to allow subclassing.
   175      * In general clients of logging should use one of the constant Level
   176      * objects such as SEVERE or FINEST.  However, if clients need to
   177      * add new logging levels, they may subclass Level and define new
   178      * constants.
   179      * @param name  the name of the Level, for example "SEVERE".
   180      * @param value an integer value for the level.
   181      * @throws NullPointerException if the name is null
   182      */
   183     protected Level(String name, int value) {
   184         this(name, value, null);
   185     }
   186 
   187     /**
   188      * Create a named Level with a given integer value and a
   189      * given localization resource name.
   190      * <p>
   191      * @param name  the name of the Level, for example "SEVERE".
   192      * @param value an integer value for the level.
   193      * @param resourceBundleName name of a resource bundle to use in
   194      *    localizing the given name. If the resourceBundleName is null
   195      *    or an empty string, it is ignored.
   196      * @throws NullPointerException if the name is null
   197      */
   198     protected Level(String name, int value, String resourceBundleName) {
   199         if (name == null) {
   200             throw new NullPointerException();
   201         }
   202         this.name = name;
   203         this.value = value;
   204         this.resourceBundleName = resourceBundleName;
   205         synchronized (Level.class) {
   206             known.add(this);
   207         }
   208     }
   209 
   210     /**
   211      * Return the level's localization resource bundle name, or
   212      * null if no localization bundle is defined.
   213      *
   214      * @return localization resource bundle name
   215      */
   216     public String getResourceBundleName() {
   217         return resourceBundleName;
   218     }
   219 
   220     /**
   221      * Return the non-localized string name of the Level.
   222      *
   223      * @return non-localized name
   224      */
   225     public String getName() {
   226         return name;
   227     }
   228 
   229     /**
   230      * Return the localized string name of the Level, for
   231      * the current default locale.
   232      * <p>
   233      * If no localization information is available, the
   234      * non-localized name is returned.
   235      *
   236      * @return localized name
   237      */
   238     public String getLocalizedName() {
   239         try {
   240             ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
   241             return rb.getString(name);
   242         } catch (Exception ex) {
   243             return name;
   244         }
   245     }
   246 
   247     /**
   248      * Returns a string representation of this Level.
   249      *
   250      * @return the non-localized name of the Level, for example "INFO".
   251      */
   252     public final String toString() {
   253         return name;
   254     }
   255 
   256     /**
   257      * Get the integer value for this level.  This integer value
   258      * can be used for efficient ordering comparisons between
   259      * Level objects.
   260      * @return the integer value for this level.
   261      */
   262     public final int intValue() {
   263         return value;
   264     }
   265 
   266     private static final long serialVersionUID = -8176160795706313070L;
   267 
   268     // Serialization magic to prevent "doppelgangers".
   269     // This is a performance optimization.
   270     private Object readResolve() {
   271         synchronized (Level.class) {
   272             for (int i = 0; i < known.size(); i++) {
   273                 Level other = known.get(i);
   274                 if (this.name.equals(other.name) && this.value == other.value
   275                         && (this.resourceBundleName == other.resourceBundleName ||
   276                             (this.resourceBundleName != null &&
   277                             this.resourceBundleName.equals(other.resourceBundleName)))) {
   278                     return other;
   279                 }
   280             }
   281             // Woops.  Whoever sent us this object knows
   282             // about a new log level.  Add it to our list.
   283             known.add(this);
   284             return this;
   285         }
   286     }
   287 
   288     /**
   289      * Parse a level name string into a Level.
   290      * <p>
   291      * The argument string may consist of either a level name
   292      * or an integer value.
   293      * <p>
   294      * For example:
   295      * <ul>
   296      * <li>     "SEVERE"
   297      * <li>     "1000"
   298      * </ul>
   299      * @param  name   string to be parsed
   300      * @throws NullPointerException if the name is null
   301      * @throws IllegalArgumentException if the value is not valid.
   302      * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
   303      * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
   304      * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
   305      * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
   306      * appropriate package access, or new levels defined or created
   307      * by subclasses.
   308      *
   309      * @return The parsed value. Passing an integer that corresponds to a known name
   310      * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
   311      * Passing an integer that does not (e.g., 1) will return a new level name
   312      * initialized to that value.
   313      */
   314     public static synchronized Level parse(String name) throws IllegalArgumentException {
   315         // Check that name is not null.
   316         name.length();
   317 
   318         // Look for a known Level with the given non-localized name.
   319         for (int i = 0; i < known.size(); i++) {
   320             Level l = known.get(i);
   321             if (name.equals(l.name)) {
   322                 return l;
   323             }
   324         }
   325 
   326         // Now, check if the given name is an integer.  If so,
   327         // first look for a Level with the given value and then
   328         // if necessary create one.
   329         try {
   330             int x = Integer.parseInt(name);
   331             for (int i = 0; i < known.size(); i++) {
   332                 Level l = known.get(i);
   333                 if (l.value == x) {
   334                     return l;
   335                 }
   336             }
   337             // Create a new Level.
   338             return new Level(name, x);
   339         } catch (NumberFormatException ex) {
   340             // Not an integer.
   341             // Drop through.
   342         }
   343 
   344         // Finally, look for a known level with the given localized name,
   345         // in the current default locale.
   346         // This is relatively expensive, but not excessively so.
   347         for (int i = 0; i < known.size(); i++) {
   348             Level l =  known.get(i);
   349             if (name.equals(l.getLocalizedName())) {
   350                 return l;
   351             }
   352         }
   353 
   354         // OK, we've tried everything and failed
   355         throw new IllegalArgumentException("Bad level \"" + name + "\"");
   356     }
   357 
   358     /**
   359      * Compare two objects for value equality.
   360      * @return true if and only if the two objects have the same level value.
   361      */
   362     public boolean equals(Object ox) {
   363         try {
   364             Level lx = (Level)ox;
   365             return (lx.value == this.value);
   366         } catch (Exception ex) {
   367             return false;
   368         }
   369     }
   370 
   371     /**
   372      * Generate a hashcode.
   373      * @return a hashcode based on the level value
   374      */
   375     public int hashCode() {
   376         return this.value;
   377     }
   378 }