jaroslav@1258: /* jaroslav@1258: * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. jaroslav@1258: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1258: * jaroslav@1258: * This code is free software; you can redistribute it and/or modify it jaroslav@1258: * under the terms of the GNU General Public License version 2 only, as jaroslav@1258: * published by the Free Software Foundation. Oracle designates this jaroslav@1258: * particular file as subject to the "Classpath" exception as provided jaroslav@1258: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1258: * jaroslav@1258: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1258: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1258: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1258: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1258: * accompanied this code). jaroslav@1258: * jaroslav@1258: * You should have received a copy of the GNU General Public License version jaroslav@1258: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1258: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1258: * jaroslav@1258: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1258: * or visit www.oracle.com if you need additional information or have any jaroslav@1258: * questions. jaroslav@1258: */ jaroslav@1258: jaroslav@1258: package java.util.logging; jaroslav@1258: import java.util.ResourceBundle; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * The Level class defines a set of standard logging levels that jaroslav@1258: * can be used to control logging output. The logging Level objects jaroslav@1258: * are ordered and are specified by ordered integers. Enabling logging jaroslav@1258: * at a given level also enables logging at all higher levels. jaroslav@1258: *

jaroslav@1258: * Clients should normally use the predefined Level constants such jaroslav@1258: * as Level.SEVERE. jaroslav@1258: *

jaroslav@1258: * The levels in descending order are: jaroslav@1258: *

jaroslav@1258: * In addition there is a level OFF that can be used to turn jaroslav@1258: * off logging, and a level ALL that can be used to enable jaroslav@1258: * logging of all messages. jaroslav@1258: *

jaroslav@1258: * It is possible for third parties to define additional logging jaroslav@1258: * levels by subclassing Level. In such cases subclasses should jaroslav@1258: * take care to chose unique integer level values and to ensure that jaroslav@1258: * they maintain the Object uniqueness property across serialization jaroslav@1258: * by defining a suitable readResolve method. jaroslav@1258: * jaroslav@1258: * @since 1.4 jaroslav@1258: */ jaroslav@1258: jaroslav@1258: public class Level implements java.io.Serializable { jaroslav@1258: private static java.util.ArrayList known = new java.util.ArrayList<>(); jaroslav@1258: private static String defaultBundle = "sun.util.logging.resources.logging"; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * @serial The non-localized name of the level. jaroslav@1258: */ jaroslav@1258: private final String name; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * @serial The integer value of the level. jaroslav@1258: */ jaroslav@1258: private final int value; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * @serial The resource bundle name to be used in localizing the level name. jaroslav@1258: */ jaroslav@1258: private final String resourceBundleName; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * OFF is a special level that can be used to turn off logging. jaroslav@1258: * This level is initialized to Integer.MAX_VALUE. jaroslav@1258: */ jaroslav@1258: public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * SEVERE is a message level indicating a serious failure. jaroslav@1258: *

jaroslav@1258: * In general SEVERE messages should describe events that are jaroslav@1258: * of considerable importance and which will prevent normal jaroslav@1258: * program execution. They should be reasonably intelligible jaroslav@1258: * to end users and to system administrators. jaroslav@1258: * This level is initialized to 1000. jaroslav@1258: */ jaroslav@1258: public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * WARNING is a message level indicating a potential problem. jaroslav@1258: *

jaroslav@1258: * In general WARNING messages should describe events that will jaroslav@1258: * be of interest to end users or system managers, or which jaroslav@1258: * indicate potential problems. jaroslav@1258: * This level is initialized to 900. jaroslav@1258: */ jaroslav@1258: public static final Level WARNING = new Level("WARNING", 900, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * INFO is a message level for informational messages. jaroslav@1258: *

jaroslav@1258: * Typically INFO messages will be written to the console jaroslav@1258: * or its equivalent. So the INFO level should only be jaroslav@1258: * used for reasonably significant messages that will jaroslav@1258: * make sense to end users and system administrators. jaroslav@1258: * This level is initialized to 800. jaroslav@1258: */ jaroslav@1258: public static final Level INFO = new Level("INFO", 800, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * CONFIG is a message level for static configuration messages. jaroslav@1258: *

jaroslav@1258: * CONFIG messages are intended to provide a variety of static jaroslav@1258: * configuration information, to assist in debugging problems jaroslav@1258: * that may be associated with particular configurations. jaroslav@1258: * For example, CONFIG message might include the CPU type, jaroslav@1258: * the graphics depth, the GUI look-and-feel, etc. jaroslav@1258: * This level is initialized to 700. jaroslav@1258: */ jaroslav@1258: public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * FINE is a message level providing tracing information. jaroslav@1258: *

jaroslav@1258: * All of FINE, FINER, and FINEST are intended for relatively jaroslav@1258: * detailed tracing. The exact meaning of the three levels will jaroslav@1258: * vary between subsystems, but in general, FINEST should be used jaroslav@1258: * for the most voluminous detailed output, FINER for somewhat jaroslav@1258: * less detailed output, and FINE for the lowest volume (and jaroslav@1258: * most important) messages. jaroslav@1258: *

jaroslav@1258: * In general the FINE level should be used for information jaroslav@1258: * that will be broadly interesting to developers who do not have jaroslav@1258: * a specialized interest in the specific subsystem. jaroslav@1258: *

jaroslav@1258: * FINE messages might include things like minor (recoverable) jaroslav@1258: * failures. Issues indicating potential performance problems jaroslav@1258: * are also worth logging as FINE. jaroslav@1258: * This level is initialized to 500. jaroslav@1258: */ jaroslav@1258: public static final Level FINE = new Level("FINE", 500, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * FINER indicates a fairly detailed tracing message. jaroslav@1258: * By default logging calls for entering, returning, or throwing jaroslav@1258: * an exception are traced at this level. jaroslav@1258: * This level is initialized to 400. jaroslav@1258: */ jaroslav@1258: public static final Level FINER = new Level("FINER", 400, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * FINEST indicates a highly detailed tracing message. jaroslav@1258: * This level is initialized to 300. jaroslav@1258: */ jaroslav@1258: public static final Level FINEST = new Level("FINEST", 300, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * ALL indicates that all messages should be logged. jaroslav@1258: * This level is initialized to Integer.MIN_VALUE. jaroslav@1258: */ jaroslav@1258: public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Create a named Level with a given integer value. jaroslav@1258: *

jaroslav@1258: * Note that this constructor is "protected" to allow subclassing. jaroslav@1258: * In general clients of logging should use one of the constant Level jaroslav@1258: * objects such as SEVERE or FINEST. However, if clients need to jaroslav@1258: * add new logging levels, they may subclass Level and define new jaroslav@1258: * constants. jaroslav@1258: * @param name the name of the Level, for example "SEVERE". jaroslav@1258: * @param value an integer value for the level. jaroslav@1258: * @throws NullPointerException if the name is null jaroslav@1258: */ jaroslav@1258: protected Level(String name, int value) { jaroslav@1258: this(name, value, null); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Create a named Level with a given integer value and a jaroslav@1258: * given localization resource name. jaroslav@1258: *

jaroslav@1258: * @param name the name of the Level, for example "SEVERE". jaroslav@1258: * @param value an integer value for the level. jaroslav@1258: * @param resourceBundleName name of a resource bundle to use in jaroslav@1258: * localizing the given name. If the resourceBundleName is null jaroslav@1258: * or an empty string, it is ignored. jaroslav@1258: * @throws NullPointerException if the name is null jaroslav@1258: */ jaroslav@1258: protected Level(String name, int value, String resourceBundleName) { jaroslav@1258: if (name == null) { jaroslav@1258: throw new NullPointerException(); jaroslav@1258: } jaroslav@1258: this.name = name; jaroslav@1258: this.value = value; jaroslav@1258: this.resourceBundleName = resourceBundleName; jaroslav@1258: synchronized (Level.class) { jaroslav@1258: known.add(this); jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Return the level's localization resource bundle name, or jaroslav@1258: * null if no localization bundle is defined. jaroslav@1258: * jaroslav@1258: * @return localization resource bundle name jaroslav@1258: */ jaroslav@1258: public String getResourceBundleName() { jaroslav@1258: return resourceBundleName; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Return the non-localized string name of the Level. jaroslav@1258: * jaroslav@1258: * @return non-localized name jaroslav@1258: */ jaroslav@1258: public String getName() { jaroslav@1258: return name; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Return the localized string name of the Level, for jaroslav@1258: * the current default locale. jaroslav@1258: *

jaroslav@1258: * If no localization information is available, the jaroslav@1258: * non-localized name is returned. jaroslav@1258: * jaroslav@1258: * @return localized name jaroslav@1258: */ jaroslav@1258: public String getLocalizedName() { jaroslav@1258: try { jaroslav@1258: ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); jaroslav@1258: return rb.getString(name); jaroslav@1258: } catch (Exception ex) { jaroslav@1258: return name; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Returns a string representation of this Level. jaroslav@1258: * jaroslav@1258: * @return the non-localized name of the Level, for example "INFO". jaroslav@1258: */ jaroslav@1258: public final String toString() { jaroslav@1258: return name; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Get the integer value for this level. This integer value jaroslav@1258: * can be used for efficient ordering comparisons between jaroslav@1258: * Level objects. jaroslav@1258: * @return the integer value for this level. jaroslav@1258: */ jaroslav@1258: public final int intValue() { jaroslav@1258: return value; jaroslav@1258: } jaroslav@1258: jaroslav@1258: private static final long serialVersionUID = -8176160795706313070L; jaroslav@1258: jaroslav@1258: // Serialization magic to prevent "doppelgangers". jaroslav@1258: // This is a performance optimization. jaroslav@1258: private Object readResolve() { jaroslav@1258: synchronized (Level.class) { jaroslav@1258: for (int i = 0; i < known.size(); i++) { jaroslav@1258: Level other = known.get(i); jaroslav@1258: if (this.name.equals(other.name) && this.value == other.value jaroslav@1258: && (this.resourceBundleName == other.resourceBundleName || jaroslav@1258: (this.resourceBundleName != null && jaroslav@1258: this.resourceBundleName.equals(other.resourceBundleName)))) { jaroslav@1258: return other; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: // Woops. Whoever sent us this object knows jaroslav@1258: // about a new log level. Add it to our list. jaroslav@1258: known.add(this); jaroslav@1258: return this; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Parse a level name string into a Level. jaroslav@1258: *

jaroslav@1258: * The argument string may consist of either a level name jaroslav@1258: * or an integer value. jaroslav@1258: *

jaroslav@1258: * For example: jaroslav@1258: *

jaroslav@1258: * @param name string to be parsed jaroslav@1258: * @throws NullPointerException if the name is null jaroslav@1258: * @throws IllegalArgumentException if the value is not valid. jaroslav@1258: * Valid values are integers between Integer.MIN_VALUE jaroslav@1258: * and Integer.MAX_VALUE, and all known level names. jaroslav@1258: * Known names are the levels defined by this class (e.g., FINE, jaroslav@1258: * FINER, FINEST), or created by this class with jaroslav@1258: * appropriate package access, or new levels defined or created jaroslav@1258: * by subclasses. jaroslav@1258: * jaroslav@1258: * @return The parsed value. Passing an integer that corresponds to a known name jaroslav@1258: * (e.g., 700) will return the associated name (e.g., CONFIG). jaroslav@1258: * Passing an integer that does not (e.g., 1) will return a new level name jaroslav@1258: * initialized to that value. jaroslav@1258: */ jaroslav@1258: public static synchronized Level parse(String name) throws IllegalArgumentException { jaroslav@1258: // Check that name is not null. jaroslav@1258: name.length(); jaroslav@1258: jaroslav@1258: // Look for a known Level with the given non-localized name. jaroslav@1258: for (int i = 0; i < known.size(); i++) { jaroslav@1258: Level l = known.get(i); jaroslav@1258: if (name.equals(l.name)) { jaroslav@1258: return l; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: // Now, check if the given name is an integer. If so, jaroslav@1258: // first look for a Level with the given value and then jaroslav@1258: // if necessary create one. jaroslav@1258: try { jaroslav@1258: int x = Integer.parseInt(name); jaroslav@1258: for (int i = 0; i < known.size(); i++) { jaroslav@1258: Level l = known.get(i); jaroslav@1258: if (l.value == x) { jaroslav@1258: return l; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: // Create a new Level. jaroslav@1258: return new Level(name, x); jaroslav@1258: } catch (NumberFormatException ex) { jaroslav@1258: // Not an integer. jaroslav@1258: // Drop through. jaroslav@1258: } jaroslav@1258: jaroslav@1258: // Finally, look for a known level with the given localized name, jaroslav@1258: // in the current default locale. jaroslav@1258: // This is relatively expensive, but not excessively so. jaroslav@1258: for (int i = 0; i < known.size(); i++) { jaroslav@1258: Level l = known.get(i); jaroslav@1258: if (name.equals(l.getLocalizedName())) { jaroslav@1258: return l; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: // OK, we've tried everything and failed jaroslav@1258: throw new IllegalArgumentException("Bad level \"" + name + "\""); jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Compare two objects for value equality. jaroslav@1258: * @return true if and only if the two objects have the same level value. jaroslav@1258: */ jaroslav@1258: public boolean equals(Object ox) { jaroslav@1258: try { jaroslav@1258: Level lx = (Level)ox; jaroslav@1258: return (lx.value == this.value); jaroslav@1258: } catch (Exception ex) { jaroslav@1258: return false; jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Generate a hashcode. jaroslav@1258: * @return a hashcode based on the level value jaroslav@1258: */ jaroslav@1258: public int hashCode() { jaroslav@1258: return this.value; jaroslav@1258: } jaroslav@1258: }