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