Frames | No Frames |
1: /* Level.java -- a class for indicating logging levels 2: Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util.logging; 40: 41: import java.io.Serializable; 42: import java.util.ResourceBundle; 43: 44: /** 45: * A class for indicating logging levels. A number of commonly used 46: * levels is pre-defined (such as <code>java.util.logging.Level.INFO</code>), 47: * and applications should utilize those whenever possible. For specialized 48: * purposes, however, applications can sub-class Level in order to define 49: * custom logging levels. 50: * 51: * @author Sascha Brawer (brawer@acm.org) 52: */ 53: public class Level implements Serializable 54: { 55: /* The integer values are the same as in the Sun J2SE 1.4. 56: * They have been obtained with a test program. In J2SE 1.4.1, 57: * Sun has amended the API documentation; these values are now 58: * publicly documented. 59: */ 60: 61: /** 62: * The <code>OFF</code> level is used as a threshold for filtering 63: * log records, meaning that no message should be logged. 64: * 65: * @see Logger#setLevel(java.util.logging.Level) 66: */ 67: public static final Level OFF = new Level ("OFF", Integer.MAX_VALUE); 68: 69: /** 70: * Log records whose level is <code>SEVERE</code> indicate a serious 71: * failure that prevents normal program execution. Messages at this 72: * level should be understandable to an inexperienced, non-technical 73: * end user. Ideally, they explain in simple words what actions the 74: * user can take in order to resolve the problem. 75: */ 76: public static final Level SEVERE = new Level ("SEVERE", 1000); 77: 78: 79: /** 80: * Log records whose level is <code>WARNING</code> indicate a 81: * potential problem that does not prevent normal program execution. 82: * Messages at this level should be understandable to an 83: * inexperienced, non-technical end user. Ideally, they explain in 84: * simple words what actions the user can take in order to resolve 85: * the problem. 86: */ 87: public static final Level WARNING = new Level ("WARNING", 900); 88: 89: 90: /** 91: * Log records whose level is <code>INFO</code> are used in purely 92: * informational situations that do not constitute serious errors or 93: * potential problems. In the default logging configuration, INFO 94: * messages will be written to the system console. For this reason, 95: * the INFO level should be used only for messages that are 96: * important to end users and system administrators. Messages at 97: * this level should be understandable to an inexperienced, 98: * non-technical user. 99: */ 100: public static final Level INFO = new Level ("INFO", 800); 101: 102: 103: /** 104: * Log records whose level is <code>CONFIG</code> are used for 105: * describing the static configuration, for example the windowing 106: * environment, the operating system version, etc. 107: */ 108: public static final Level CONFIG = new Level ("CONFIG", 700); 109: 110: 111: /** 112: * Log records whose level is <code>FINE</code> are typically used 113: * for messages that are relevant for developers using 114: * the component generating log messages. Examples include minor, 115: * recoverable failures, or possible inefficiencies. 116: */ 117: public static final Level FINE = new Level ("FINE", 500); 118: 119: 120: /** 121: * Log records whose level is <code>FINER</code> are intended for 122: * rather detailed tracing, for example entering a method, returning 123: * from a method, or throwing an exception. 124: */ 125: public static final Level FINER = new Level ("FINER", 400); 126: 127: 128: /** 129: * Log records whose level is <code>FINEST</code> are used for 130: * highly detailed tracing, for example to indicate that a certain 131: * point inside the body of a method has been reached. 132: */ 133: public static final Level FINEST = new Level ("FINEST", 300); 134: 135: 136: /** 137: * The <code>ALL</code> level is used as a threshold for filtering 138: * log records, meaning that every message should be logged. 139: * 140: * @see Logger#setLevel(java.util.logging.Level) 141: */ 142: public static final Level ALL = new Level ("ALL", Integer.MIN_VALUE); 143: 144: 145: private static final Level[] knownLevels = { 146: ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF 147: }; 148: 149: 150: /** 151: * The name of the Level without localizing it, for example 152: * "WARNING". 153: */ 154: private String name; 155: 156: 157: /** 158: * The integer value of this <code>Level</code>. 159: */ 160: private int value; 161: 162: 163: /** 164: * The name of the resource bundle used for localizing the level 165: * name, or <code>null</code> if the name does not undergo 166: * localization. 167: */ 168: private String resourceBundleName; 169: 170: 171: /** 172: * Creates a logging level given a name and an integer value. 173: * It rarely is necessary to create custom levels, 174: * as most applications should be well served with one of the 175: * standard levels such as <code>Level.CONFIG</code>, 176: * <code>Level.INFO</code>, or <code>Level.FINE</code>. 177: * 178: * @param name the name of the level. 179: * 180: * @param value the integer value of the level. Please note 181: * that the Java<small><sup>TM</sup></small> 182: * Logging API does not specify integer 183: * values for standard levels (such as 184: * Level.FINE). Therefore, a custom 185: * level should pass an integer value that 186: * is calculated at run-time, e.g. 187: * <code>(Level.FINE.intValue() + Level.CONFIG.intValue()) 188: * / 2</code> for a level between FINE and CONFIG. 189: */ 190: protected Level(String name, int value) 191: { 192: this(name, value, null); 193: } 194: 195: 196: /** 197: * Create a logging level given a name, an integer value and a name 198: * of a resource bundle for localizing the level name. It rarely 199: * is necessary to create custom levels, as most applications 200: * should be well served with one of the standard levels such as 201: * <code>Level.CONFIG</code>, <code>Level.INFO</code>, or 202: * <code>Level.FINE</code>. 203: * 204: * @param name the name of the level. 205: * 206: * @param value the integer value of the level. Please note 207: * that the Java<small><sup>TM</sup></small> 208: * Logging API does not specify integer 209: * values for standard levels (such as 210: * Level.FINE). Therefore, a custom 211: * level should pass an integer value that 212: * is calculated at run-time, e.g. 213: * <code>(Level.FINE.intValue() + Level.CONFIG.intValue()) 214: * / 2</code> for a level between FINE and CONFIG. 215: * 216: * @param resourceBundleName the name of a resource bundle 217: * for localizing the level name, or <code>null</code> 218: * if the name does not need to be localized. 219: */ 220: protected Level(String name, int value, String resourceBundleName) 221: { 222: this.name = name; 223: this.value = value; 224: this.resourceBundleName = resourceBundleName; 225: } 226: 227: 228: static final long serialVersionUID = -8176160795706313070L; 229: 230: 231: /** 232: * Checks whether the Level has the same intValue as one of the 233: * pre-defined levels. If so, the pre-defined level object is 234: * returned. 235: * 236: * <br/>Since the resource bundle name is not taken into 237: * consideration, it is possible to resolve Level objects that have 238: * been de-serialized by another implementation, even if the other 239: * implementation uses a different resource bundle for localizing 240: * the names of pre-defined levels. 241: */ 242: private Object readResolve() 243: { 244: for (int i = 0; i < knownLevels.length; i++) 245: if (value == knownLevels[i].intValue()) 246: return knownLevels[i]; 247: 248: return this; 249: } 250: 251: 252: /** 253: * Returns the name of the resource bundle used for localizing the 254: * level name. 255: * 256: * @return the name of the resource bundle used for localizing the 257: * level name, or <code>null</code> if the name does not undergo 258: * localization. 259: */ 260: public String getResourceBundleName() 261: { 262: return resourceBundleName; 263: } 264: 265: 266: /** 267: * Returns the name of the Level without localizing it, for example 268: * "WARNING". 269: */ 270: public String getName() 271: { 272: return name; 273: } 274: 275: 276: /** 277: * Returns the name of the Level after localizing it, for example 278: * "WARNUNG". 279: */ 280: public String getLocalizedName() 281: { 282: String localizedName = null; 283: 284: if (resourceBundleName != null) 285: { 286: try 287: { 288: ResourceBundle b = ResourceBundle.getBundle(resourceBundleName); 289: localizedName = b.getString(name); 290: } 291: catch (Exception _) 292: { 293: } 294: } 295: 296: if (localizedName != null) 297: return localizedName; 298: else 299: return name; 300: } 301: 302: 303: /** 304: * Returns the name of the Level without localizing it, for example 305: * "WARNING". 306: */ 307: public final String toString() 308: { 309: return getName(); 310: } 311: 312: 313: /** 314: * Returns the integer value of the Level. 315: */ 316: public final int intValue() 317: { 318: return value; 319: } 320: 321: 322: /** 323: * Returns one of the standard Levels given either its name or its 324: * integer value. Custom subclasses of Level will not be returned 325: * by this method. 326: * 327: * @throws IllegalArgumentException if <code>name</code> is neither 328: * the name nor the integer value of one of the pre-defined standard 329: * logging levels. 330: * 331: * @throws NullPointerException if <code>name</code> is null. 332: * 333: */ 334: public static Level parse(String name) 335: throws IllegalArgumentException 336: { 337: /* This will throw a NullPointerException if name is null, 338: * as required by the API specification. 339: */ 340: name = name.intern(); 341: 342: for (int i = 0; i < knownLevels.length; i++) 343: { 344: // It's safe to use == instead of .equals here because only the 345: // standard logging levels will be returned by this method, and 346: // they are all created using string literals. 347: if (name == knownLevels[i].name) 348: return knownLevels[i]; 349: } 350: 351: try 352: { 353: int num = Integer.parseInt(name); 354: for (int i = 0; i < knownLevels.length; i++) 355: if (num == knownLevels[i].value) 356: return knownLevels[i]; 357: } 358: catch (NumberFormatException _) 359: { 360: } 361: 362: String msg = "Not the name of a standard logging level: \"" + name + "\""; 363: throw new IllegalArgumentException(msg); 364: } 365: 366: 367: /** 368: * Checks whether this Level's integer value is equal to that of 369: * another object. 370: * 371: * @return <code>true</code> if <code>other</code> is an instance of 372: * <code>java.util.logging.Level</code> and has the same integer 373: * value, <code>false</code> otherwise. 374: */ 375: public boolean equals(Object other) 376: { 377: if (!(other instanceof Level)) 378: return false; 379: 380: return value == ((Level) other).value; 381: } 382: 383: 384: /** 385: * Returns a hash code for this Level which is based on its numeric 386: * value. 387: */ 388: public int hashCode() 389: { 390: return value; 391: } 392: 393: 394: /** 395: * Determines whether or not this Level is one of the standard 396: * levels specified in the Logging API. 397: * 398: * <p>This method is package-private because it is not part 399: * of the logging API specification. However, an XMLFormatter 400: * is supposed to emit the numeric value for a custom log 401: * level, but the name for a pre-defined level. It seems 402: * cleaner to put this method to Level than to write some 403: * procedural code for XMLFormatter. 404: * 405: * @return <code>true</code> if this Level is a standard level, 406: * <code>false</code> otherwise. 407: */ 408: final boolean isStandardLevel() 409: { 410: for (int i = 0; i < knownLevels.length; i++) 411: if (knownLevels[i] == this) 412: return true; 413: 414: return false; 415: } 416: }