Frames | No Frames |
1: /* LogRecord.java -- 2: A class for the state associated with individual logging events 3: Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: 40: package java.util.logging; 41: 42: import java.util.ResourceBundle; 43: 44: 45: /** 46: * A <code>LogRecord</code> contains the state for an individual 47: * event to be logged. 48: * 49: * <p>As soon as a LogRecord instance has been handed over to the 50: * logging framework, applications should not manipulate it anymore. 51: * 52: * @author Sascha Brawer (brawer@acm.org) 53: */ 54: public class LogRecord 55: implements java.io.Serializable 56: { 57: /** 58: * The severity level of this <code>LogRecord</code>. 59: */ 60: private Level level; 61: 62: 63: /** 64: * The sequence number of this <code>LogRecord</code>. 65: */ 66: private long sequenceNumber; 67: 68: 69: /** 70: * The name of the class that issued the logging request, or 71: * <code>null</code> if this information could not be obtained. 72: */ 73: private String sourceClassName; 74: 75: 76: /** 77: * The name of the method that issued the logging request, or 78: * <code>null</code> if this information could not be obtained. 79: */ 80: private String sourceMethodName; 81: 82: 83: /** 84: * The message for this <code>LogRecord</code> before 85: * any localization or formatting. 86: */ 87: private String message; 88: 89: 90: /** 91: * An identifier for the thread in which this <code>LogRecord</code> 92: * was created. The identifier is not necessarily related to any 93: * thread identifiers used by the operating system. 94: */ 95: private int threadID; 96: 97: 98: /** 99: * The time when this <code>LogRecord</code> was created, 100: * in milliseconds since the beginning of January 1, 1970. 101: */ 102: private long millis; 103: 104: 105: /** 106: * The Throwable associated with this <code>LogRecord</code>, or 107: * <code>null</code> if the logged event is not related to an 108: * exception or error. 109: */ 110: private Throwable thrown; 111: 112: 113: /** 114: * The name of the logger where this <code>LogRecord</code> has 115: * originated, or <code>null</code> if this <code>LogRecord</code> 116: * does not originate from a <code>Logger</code>. 117: */ 118: private String loggerName; 119: 120: 121: /** 122: * The name of the resource bundle used for localizing log messages, 123: * or <code>null</code> if no bundle has been specified. 124: */ 125: private String resourceBundleName; 126: 127: private transient Object[] parameters; 128: 129: private transient ResourceBundle bundle; 130: 131: 132: /** 133: * Constructs a <code>LogRecord</code> given a severity level and 134: * an unlocalized message text. In addition, the sequence number, 135: * creation time (as returned by <code>getMillis()</code>) and 136: * thread ID are assigned. All other properties are set to 137: * <code>null</code>. 138: * 139: * @param level the severity level, for example <code>Level.WARNING</code>. 140: * 141: * @param message the message text (which will be used as key 142: * for looking up the localized message text 143: * if a resource bundle has been associated). 144: */ 145: public LogRecord(Level level, String message) 146: { 147: this.level = level; 148: this.message = message; 149: this.millis = System.currentTimeMillis(); 150: 151: /* A subclass of java.lang.Thread could override hashCode(), 152: * in which case the result would not be guaranteed anymore 153: * to be unique among all threads. While System.identityHashCode 154: * is not necessarily unique either, it at least cannot be 155: * overridden by user code. However, is might be a good idea 156: * to use something better for generating thread IDs. 157: */ 158: this.threadID = System.identityHashCode(Thread.currentThread()); 159: 160: sequenceNumber = allocateSeqNum(); 161: } 162: 163: 164: /** 165: * Determined with the serialver tool of the Sun J2SE 1.4. 166: */ 167: static final long serialVersionUID = 5372048053134512534L; 168: 169: private void readObject(java.io.ObjectInputStream in) 170: throws java.io.IOException, java.lang.ClassNotFoundException 171: { 172: in.defaultReadObject(); 173: 174: /* We assume that future versions will be downwards compatible, 175: * so we can ignore the versions. 176: */ 177: byte majorVersion = in.readByte(); 178: byte minorVersion = in.readByte(); 179: 180: int numParams = in.readInt(); 181: if (numParams >= 0) 182: { 183: parameters = new Object[numParams]; 184: for (int i = 0; i < numParams; i++) 185: parameters[i] = in.readObject(); 186: } 187: } 188: 189: 190: /** 191: * @serialData The default fields, followed by a major byte version 192: * number, followed by a minor byte version number, followed by 193: * information about the log record parameters. If 194: * <code>parameters</code> is <code>null</code>, the integer -1 is 195: * written, otherwise the length of the <code>parameters</code> 196: * array (which can be zero), followed by the result of calling 197: * {@link Object#toString() toString()} on the parameter (or 198: * <code>null</code> if the parameter is <code>null</code>). 199: * 200: * <p><strong>Specification Note:</strong> The Javadoc for the 201: * Sun reference implementation does not specify the version 202: * number. FIXME: Reverse-engineer the JDK and file a bug 203: * report with Sun, asking for amendment of the specification. 204: */ 205: private void writeObject(java.io.ObjectOutputStream out) 206: throws java.io.IOException 207: { 208: out.defaultWriteObject(); 209: 210: /* Major, minor version number: The Javadoc for J2SE1.4 does not 211: * specify the values. 212: */ 213: out.writeByte(0); 214: out.writeByte(0); 215: 216: if (parameters == null) 217: out.writeInt(-1); 218: else 219: { 220: out.writeInt(parameters.length); 221: for (int i = 0; i < parameters.length; i++) 222: { 223: if (parameters[i] == null) 224: out.writeObject(null); 225: else 226: out.writeObject(parameters[i].toString()); 227: } 228: } 229: } 230: 231: 232: /** 233: * Returns the name of the logger where this <code>LogRecord</code> 234: * has originated. 235: * 236: * @return the name of the source {@link Logger}, or 237: * <code>null</code> if this <code>LogRecord</code> 238: * does not originate from a <code>Logger</code>. 239: */ 240: public String getLoggerName() 241: { 242: return loggerName; 243: } 244: 245: 246: /** 247: * Sets the name of the logger where this <code>LogRecord</code> 248: * has originated. 249: * 250: * <p>As soon as a <code>LogRecord</code> has been handed over 251: * to the logging framework, applications should not modify it 252: * anymore. Therefore, this method should only be called on 253: * freshly constructed LogRecords. 254: * 255: * @param name the name of the source logger, or <code>null</code> to 256: * indicate that this <code>LogRecord</code> does not 257: * originate from a <code>Logger</code>. 258: */ 259: public void setLoggerName(String name) 260: { 261: loggerName = name; 262: } 263: 264: 265: /** 266: * Returns the resource bundle that is used when the message 267: * of this <code>LogRecord</code> needs to be localized. 268: * 269: * @return the resource bundle used for localization, 270: * or <code>null</code> if this message does not need 271: * to be localized. 272: */ 273: public ResourceBundle getResourceBundle() 274: { 275: return bundle; 276: } 277: 278: 279: /** 280: * Sets the resource bundle that is used when the message 281: * of this <code>LogRecord</code> needs to be localized. 282: * 283: * <p>As soon as a <code>LogRecord</code> has been handed over 284: * to the logging framework, applications should not modify it 285: * anymore. Therefore, this method should only be called on 286: * freshly constructed LogRecords. 287: * 288: * @param bundle the resource bundle to be used, or 289: * <code>null</code> to indicate that this 290: * message does not need to be localized. 291: */ 292: public void setResourceBundle(ResourceBundle bundle) 293: { 294: this.bundle = bundle; 295: 296: /* FIXME: Is there a way to infer the name 297: * of a resource bundle from a ResourceBundle object? 298: */ 299: this.resourceBundleName = null; 300: } 301: 302: 303: /** 304: * Returns the name of the resource bundle that is used when the 305: * message of this <code>LogRecord</code> needs to be localized. 306: * 307: * @return the name of the resource bundle used for localization, 308: * or <code>null</code> if this message does not need 309: * to be localized. 310: */ 311: public String getResourceBundleName() 312: { 313: return resourceBundleName; 314: } 315: 316: 317: /** 318: * Sets the name of the resource bundle that is used when the 319: * message of this <code>LogRecord</code> needs to be localized. 320: * 321: * <p>As soon as a <code>LogRecord</code> has been handed over 322: * to the logging framework, applications should not modify it 323: * anymore. Therefore, this method should only be called on 324: * freshly constructed LogRecords. 325: * 326: * @param name the name of the resource bundle to be used, or 327: * <code>null</code> to indicate that this message 328: * does not need to be localized. 329: */ 330: public void setResourceBundleName(String name) 331: { 332: resourceBundleName = name; 333: bundle = null; 334: 335: try 336: { 337: if (resourceBundleName != null) 338: bundle = ResourceBundle.getBundle(resourceBundleName); 339: } 340: catch (java.util.MissingResourceException _) 341: { 342: } 343: } 344: 345: 346: /** 347: * Returns the level of the LogRecord. 348: * 349: * <p>Applications should be aware of the possibility that the 350: * result is not necessarily one of the standard logging levels, 351: * since the logging framework allows to create custom subclasses 352: * of <code>java.util.logging.Level</code>. Therefore, filters 353: * should perform checks like <code>theRecord.getLevel().intValue() 354: * == Level.INFO.intValue()</code> instead of <code>theRecord.getLevel() 355: * == Level.INFO</code>. 356: */ 357: public Level getLevel() 358: { 359: return level; 360: } 361: 362: 363: /** 364: * Sets the severity level of this <code>LogRecord</code> to a new 365: * value. 366: * 367: * <p>As soon as a <code>LogRecord</code> has been handed over 368: * to the logging framework, applications should not modify it 369: * anymore. Therefore, this method should only be called on 370: * freshly constructed LogRecords. 371: * 372: * @param level the new severity level, for example 373: * <code>Level.WARNING</code>. 374: */ 375: public void setLevel(Level level) 376: { 377: this.level = level; 378: } 379: 380: 381: /** 382: * The last used sequence number for any LogRecord. 383: */ 384: private static long lastSeqNum; 385: 386: 387: /** 388: * Allocates a sequence number for a new LogRecord. This class 389: * method is only called by the LogRecord constructor. 390: */ 391: private static synchronized long allocateSeqNum() 392: { 393: lastSeqNum += 1; 394: return lastSeqNum; 395: } 396: 397: 398: /** 399: * Returns the sequence number of this <code>LogRecord</code>. 400: */ 401: public long getSequenceNumber() 402: { 403: return sequenceNumber; 404: } 405: 406: 407: /** 408: * Sets the sequence number of this <code>LogRecord</code> to a new 409: * value. 410: * 411: * <p>As soon as a <code>LogRecord</code> has been handed over 412: * to the logging framework, applications should not modify it 413: * anymore. Therefore, this method should only be called on 414: * freshly constructed LogRecords. 415: * 416: * @param seqNum the new sequence number. 417: */ 418: public void setSequenceNumber(long seqNum) 419: { 420: this.sequenceNumber = seqNum; 421: } 422: 423: 424: /** 425: * Returns the name of the class where the event being logged 426: * has had its origin. This information can be passed as 427: * parameter to some logging calls, and in certain cases, the 428: * logging framework tries to determine an approximation 429: * (which may or may not be accurate). 430: * 431: * @return the name of the class that issued the logging request, 432: * or <code>null</code> if this information could not 433: * be obtained. 434: */ 435: public String getSourceClassName() 436: { 437: if (sourceClassName != null) 438: return sourceClassName; 439: 440: /* FIXME: Should infer this information from the call stack. */ 441: return null; 442: } 443: 444: 445: /** 446: * Sets the name of the class where the event being logged 447: * has had its origin. 448: * 449: * <p>As soon as a <code>LogRecord</code> has been handed over 450: * to the logging framework, applications should not modify it 451: * anymore. Therefore, this method should only be called on 452: * freshly constructed LogRecords. 453: * 454: * @param sourceClassName the name of the class that issued the 455: * logging request, or <code>null</code> to indicate that 456: * this information could not be obtained. 457: */ 458: public void setSourceClassName(String sourceClassName) 459: { 460: this.sourceClassName = sourceClassName; 461: } 462: 463: 464: /** 465: * Returns the name of the method where the event being logged 466: * has had its origin. This information can be passed as 467: * parameter to some logging calls, and in certain cases, the 468: * logging framework tries to determine an approximation 469: * (which may or may not be accurate). 470: * 471: * @return the name of the method that issued the logging request, 472: * or <code>null</code> if this information could not 473: * be obtained. 474: */ 475: public String getSourceMethodName() 476: { 477: if (sourceMethodName != null) 478: return sourceMethodName; 479: 480: /* FIXME: Should infer this information from the call stack. */ 481: return null; 482: } 483: 484: 485: /** 486: * Sets the name of the method where the event being logged 487: * has had its origin. 488: * 489: * <p>As soon as a <code>LogRecord</code> has been handed over 490: * to the logging framework, applications should not modify it 491: * anymore. Therefore, this method should only be called on 492: * freshly constructed LogRecords. 493: * 494: * @param sourceMethodName the name of the method that issued the 495: * logging request, or <code>null</code> to indicate that 496: * this information could not be obtained. 497: */ 498: public void setSourceMethodName(String sourceMethodName) 499: { 500: this.sourceMethodName = sourceMethodName; 501: } 502: 503: 504: /** 505: * Returns the message for this <code>LogRecord</code> before 506: * any localization or parameter substitution. 507: * 508: * <p>A {@link Logger} will try to localize the message 509: * if a resource bundle has been associated with this 510: * <code>LogRecord</code>. In this case, the logger will call 511: * <code>getMessage()</code> and use the result as the key 512: * for looking up the localized message in the bundle. 513: * If no bundle has been associated, or if the result of 514: * <code>getMessage()</code> is not a valid key in the 515: * bundle, the logger will use the raw message text as 516: * returned by this method. 517: * 518: * @return the message text, or <code>null</code> if there 519: * is no message text. 520: */ 521: public String getMessage() 522: { 523: return message; 524: } 525: 526: 527: /** 528: * Sets the message for this <code>LogRecord</code>. 529: * 530: * <p>A <code>Logger</code> will try to localize the message 531: * if a resource bundle has been associated with this 532: * <code>LogRecord</code>. In this case, the logger will call 533: * <code>getMessage()</code> and use the result as the key 534: * for looking up the localized message in the bundle. 535: * If no bundle has been associated, or if the result of 536: * <code>getMessage()</code> is not a valid key in the 537: * bundle, the logger will use the raw message text as 538: * returned by this method. 539: * 540: * <p>It is possible to set the message to either an empty String or 541: * <code>null</code>, although this does not make the the message 542: * very helpful to human users. 543: * 544: * @param message the message text (which will be used as key 545: * for looking up the localized message text 546: * if a resource bundle has been associated). 547: */ 548: public void setMessage(String message) 549: { 550: this.message = message; 551: } 552: 553: 554: /** 555: * Returns the parameters to the log message. 556: * 557: * @return the parameters to the message, or <code>null</code> if 558: * the message has no parameters. 559: */ 560: public Object[] getParameters() 561: { 562: return parameters; 563: } 564: 565: 566: /** 567: * Sets the parameters to the log message. 568: * 569: * <p>As soon as a <code>LogRecord</code> has been handed over 570: * to the logging framework, applications should not modify it 571: * anymore. Therefore, this method should only be called on 572: * freshly constructed LogRecords. 573: * 574: * @param parameters the parameters to the message, or <code>null</code> 575: * to indicate that the message has no parameters. 576: */ 577: public void setParameters(Object[] parameters) 578: { 579: this.parameters = parameters; 580: } 581: 582: 583: /** 584: * Returns an identifier for the thread in which this 585: * <code>LogRecord</code> was created. The identifier is not 586: * necessarily related to any thread identifiers used by the 587: * operating system. 588: * 589: * @return an identifier for the source thread. 590: */ 591: public int getThreadID() 592: { 593: return threadID; 594: } 595: 596: 597: /** 598: * Sets the identifier indicating in which thread this 599: * <code>LogRecord</code> was created. The identifier is not 600: * necessarily related to any thread identifiers used by the 601: * operating system. 602: * 603: * <p>As soon as a <code>LogRecord</code> has been handed over 604: * to the logging framework, applications should not modify it 605: * anymore. Therefore, this method should only be called on 606: * freshly constructed LogRecords. 607: * 608: * @param threadID the identifier for the source thread. 609: */ 610: public void setThreadID(int threadID) 611: { 612: this.threadID = threadID; 613: } 614: 615: 616: /** 617: * Returns the time when this <code>LogRecord</code> was created. 618: * 619: * @return the time of creation in milliseconds since the beginning 620: * of January 1, 1970. 621: */ 622: public long getMillis() 623: { 624: return millis; 625: } 626: 627: 628: /** 629: * Sets the time when this <code>LogRecord</code> was created. 630: * 631: * <p>As soon as a <code>LogRecord</code> has been handed over 632: * to the logging framework, applications should not modify it 633: * anymore. Therefore, this method should only be called on 634: * freshly constructed LogRecords. 635: * 636: * @param millis the time of creation in milliseconds since the 637: * beginning of January 1, 1970. 638: */ 639: public void setMillis(long millis) 640: { 641: this.millis = millis; 642: } 643: 644: 645: /** 646: * Returns the Throwable associated with this <code>LogRecord</code>, 647: * or <code>null</code> if the logged event is not related to an exception 648: * or error. 649: */ 650: public Throwable getThrown() 651: { 652: return thrown; 653: } 654: 655: 656: /** 657: * Associates this <code>LogRecord</code> with an exception or error. 658: * 659: * <p>As soon as a <code>LogRecord</code> has been handed over 660: * to the logging framework, applications should not modify it 661: * anymore. Therefore, this method should only be called on 662: * freshly constructed LogRecords. 663: * 664: * @param thrown the exception or error to associate with, or 665: * <code>null</code> if this <code>LogRecord</code> 666: * should be made unrelated to an exception or error. 667: */ 668: public void setThrown(Throwable thrown) 669: { 670: this.thrown = thrown; 671: } 672: }