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: * 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
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
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
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
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
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
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: * 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: * 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: * 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: * 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: * 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: * 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: *
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: }