001 /* LogRecord.java -- 002 A class for the state associated with individual logging events 003 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. 004 005 This file is part of GNU Classpath. 006 007 GNU Classpath is free software; you can redistribute it and/or modify 008 it under the terms of the GNU General Public License as published by 009 the Free Software Foundation; either version 2, or (at your option) 010 any later version. 011 012 GNU Classpath is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of 014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 General Public License for more details. 016 017 You should have received a copy of the GNU General Public License 018 along with GNU Classpath; see the file COPYING. If not, write to the 019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 020 02110-1301 USA. 021 022 Linking this library statically or dynamically with other modules is 023 making a combined work based on this library. Thus, the terms and 024 conditions of the GNU General Public License cover the whole 025 combination. 026 027 As a special exception, the copyright holders of this library give you 028 permission to link this library with independent modules to produce an 029 executable, regardless of the license terms of these independent 030 modules, and to copy and distribute the resulting executable under 031 terms of your choice, provided that you also meet, for each linked 032 independent module, the terms and conditions of the license of that 033 module. An independent module is a module which is not derived from 034 or based on this library. If you modify this library, you may extend 035 this exception to your version of the library, but you are not 036 obligated to do so. If you do not wish to do so, delete this 037 exception statement from your version. */ 038 039 040 package java.util.logging; 041 042 import java.util.ResourceBundle; 043 044 045 /** 046 * A <code>LogRecord</code> contains the state for an individual 047 * event to be logged. 048 * 049 * <p>As soon as a LogRecord instance has been handed over to the 050 * logging framework, applications should not manipulate it anymore. 051 * 052 * @author Sascha Brawer (brawer@acm.org) 053 */ 054 public class LogRecord 055 implements java.io.Serializable 056 { 057 /** 058 * The severity level of this <code>LogRecord</code>. 059 */ 060 private Level level; 061 062 063 /** 064 * The sequence number of this <code>LogRecord</code>. 065 */ 066 private long sequenceNumber; 067 068 069 /** 070 * The name of the class that issued the logging request, or 071 * <code>null</code> if this information could not be obtained. 072 */ 073 private String sourceClassName; 074 075 076 /** 077 * The name of the method that issued the logging request, or 078 * <code>null</code> if this information could not be obtained. 079 */ 080 private String sourceMethodName; 081 082 083 /** 084 * The message for this <code>LogRecord</code> before 085 * any localization or formatting. 086 */ 087 private String message; 088 089 090 /** 091 * An identifier for the thread in which this <code>LogRecord</code> 092 * was created. The identifier is not necessarily related to any 093 * thread identifiers used by the operating system. 094 */ 095 private int threadID; 096 097 098 /** 099 * 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 }