Source for java.util.logging.Level

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