2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
26 package java.util.logging;
30 * LogRecord objects are used to pass logging requests between
31 * the logging framework and individual log Handlers.
33 * When a LogRecord is passed into the logging framework it
34 * logically belongs to the framework and should no longer be
35 * used or updated by the client application.
37 * Note that if the client application has not specified an
38 * explicit source method name and source class name, then the
39 * LogRecord class will infer them automatically when they are
40 * first accessed (due to a call on getSourceMethodName or
41 * getSourceClassName) by analyzing the call stack. Therefore,
42 * if a logging Handler wants to pass off a LogRecord to another
43 * thread, or to transmit it over RMI, and if it wishes to subsequently
44 * obtain method name or class name information it should call
45 * one of getSourceClassName or getSourceMethodName to force
46 * the values to be filled in.
48 * <b> Serialization notes:</b>
50 * <li>The LogRecord class is serializable.
52 * <li> Because objects in the parameters array may not be serializable,
53 * during serialization all objects in the parameters array are
54 * written as the corresponding Strings (using Object.toString).
56 * <li> The ResourceBundle is not transmitted as part of the serialized
57 * form, but the resource bundle name is, and the recipient object's
58 * readObject method will attempt to locate a suitable resource bundle.
65 public class LogRecord implements java.io.Serializable {
66 private static long globalSequenceNumber = 0;
69 * The default value of threadID will be the current thread's
70 * thread id, for ease of correlation, unless it is greater than
71 * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
72 * our promise to keep threadIDs unique by avoiding collisions due
73 * to 32-bit wraparound. Unfortunately, LogRecord.getThreadID()
74 * returns int, while Thread.getId() returns long.
76 private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
79 * @serial Logging message level
84 * @serial Sequence number
86 private long sequenceNumber;
89 * @serial Class that issued logging call
91 private String sourceClassName;
94 * @serial Method that issued logging call
96 private String sourceMethodName;
99 * @serial Non-localized raw message text
101 private String message;
104 * @serial Thread ID for thread that issued logging call.
106 private int threadID;
109 * @serial Event time in milliseconds since 1970
114 * @serial The Throwable (if any) associated with log message
116 private Throwable thrown;
119 * @serial Name of the source Logger.
121 private String loggerName;
124 * @serial Resource bundle name to localized log message.
126 private String resourceBundleName;
128 private transient boolean needToInferCaller;
129 private transient Object parameters[];
132 * Returns the default value for a new LogRecord's threadID.
134 private int defaultThreadID() {
139 * Construct a LogRecord with the given level and message values.
141 * The sequence property will be initialized with a new unique value.
142 * These sequence values are allocated in increasing order within a VM.
144 * The millis property will be initialized to the current time.
146 * The thread ID property will be initialized with a unique ID for
147 * the current thread.
149 * All other properties will be initialized to "null".
151 * @param level a logging level value
152 * @param msg the raw non-localized logging message (may be null)
154 public LogRecord(Level level, String msg) {
155 // Make sure level isn't null, by calling random method.
159 // Assign a thread ID and a unique sequence number.
160 sequenceNumber = globalSequenceNumber++;
161 threadID = defaultThreadID();
162 millis = System.currentTimeMillis();
163 needToInferCaller = true;
167 * Get the source Logger's name.
169 * @return source logger name (may be null)
171 public String getLoggerName() {
176 * Set the source Logger's name.
178 * @param name the source logger name (may be null)
180 public void setLoggerName(String name) {
185 * Get the localization resource bundle
187 * This is the ResourceBundle that should be used to localize
188 * the message string before formatting it. The result may
189 * be null if the message is not localizable, or if no suitable
190 * ResourceBundle is available.
192 // public ResourceBundle getResourceBundle() {
193 // return resourceBundle;
197 * Set the localization resource bundle.
199 * @param bundle localization bundle (may be null)
201 // public void setResourceBundle(ResourceBundle bundle) {
202 // resourceBundle = bundle;
206 * Get the localization resource bundle name
208 * This is the name for the ResourceBundle that should be
209 * used to localize the message string before formatting it.
210 * The result may be null if the message is not localizable.
212 public String getResourceBundleName() {
213 return resourceBundleName;
217 * Set the localization resource bundle name.
219 * @param name localization bundle name (may be null)
221 public void setResourceBundleName(String name) {
222 resourceBundleName = name;
226 * Get the logging message level, for example Level.SEVERE.
227 * @return the logging message level
229 public Level getLevel() {
234 * Set the logging message level, for example Level.SEVERE.
235 * @param level the logging message level
237 public void setLevel(Level level) {
239 throw new NullPointerException();
245 * Get the sequence number.
247 * Sequence numbers are normally assigned in the LogRecord
248 * constructor, which assigns unique sequence numbers to
249 * each new LogRecord in increasing order.
250 * @return the sequence number
252 public long getSequenceNumber() {
253 return sequenceNumber;
257 * Set the sequence number.
259 * Sequence numbers are normally assigned in the LogRecord constructor,
260 * so it should not normally be necessary to use this method.
262 public void setSequenceNumber(long seq) {
263 sequenceNumber = seq;
267 * Get the name of the class that (allegedly) issued the logging request.
269 * Note that this sourceClassName is not verified and may be spoofed.
270 * This information may either have been provided as part of the
271 * logging call, or it may have been inferred automatically by the
272 * logging framework. In the latter case, the information may only
273 * be approximate and may in fact describe an earlier call on the
276 * May be null if no information could be obtained.
278 * @return the source class name
280 public String getSourceClassName() {
281 return sourceClassName;
285 * Set the name of the class that (allegedly) issued the logging request.
287 * @param sourceClassName the source class name (may be null)
289 public void setSourceClassName(String sourceClassName) {
290 this.sourceClassName = sourceClassName;
291 needToInferCaller = false;
295 * Get the name of the method that (allegedly) issued the logging request.
297 * Note that this sourceMethodName is not verified and may be spoofed.
298 * This information may either have been provided as part of the
299 * logging call, or it may have been inferred automatically by the
300 * logging framework. In the latter case, the information may only
301 * be approximate and may in fact describe an earlier call on the
304 * May be null if no information could be obtained.
306 * @return the source method name
308 public String getSourceMethodName() {
309 return sourceMethodName;
313 * Set the name of the method that (allegedly) issued the logging request.
315 * @param sourceMethodName the source method name (may be null)
317 public void setSourceMethodName(String sourceMethodName) {
318 this.sourceMethodName = sourceMethodName;
319 needToInferCaller = false;
323 * Get the "raw" log message, before localization or formatting.
325 * May be null, which is equivalent to the empty string "".
327 * This message may be either the final text or a localization key.
329 * During formatting, if the source logger has a localization
330 * ResourceBundle and if that ResourceBundle has an entry for
331 * this message string, then the message string is replaced
332 * with the localized value.
334 * @return the raw message string
336 public String getMessage() {
341 * Set the "raw" log message, before localization or formatting.
343 * @param message the raw message string (may be null)
345 public void setMessage(String message) {
346 this.message = message;
350 * Get the parameters to the log message.
352 * @return the log message parameters. May be null if
353 * there are no parameters.
355 public Object[] getParameters() {
360 * Set the parameters to the log message.
362 * @param parameters the log message parameters. (may be null)
364 public void setParameters(Object parameters[]) {
365 this.parameters = parameters;
369 * Get an identifier for the thread where the message originated.
371 * This is a thread identifier within the Java VM and may or
372 * may not map to any operating system ID.
376 public int getThreadID() {
381 * Set an identifier for the thread where the message originated.
382 * @param threadID the thread ID
384 public void setThreadID(int threadID) {
385 this.threadID = threadID;
389 * Get event time in milliseconds since 1970.
391 * @return event time in millis since 1970
393 public long getMillis() {
400 * @param millis event time in millis since 1970
402 public void setMillis(long millis) {
403 this.millis = millis;
407 * Get any throwable associated with the log record.
409 * If the event involved an exception, this will be the
410 * exception object. Otherwise null.
412 * @return a throwable
414 public Throwable getThrown() {
419 * Set a throwable associated with the log event.
421 * @param thrown a throwable (may be null)
423 public void setThrown(Throwable thrown) {
424 this.thrown = thrown;
427 private static final long serialVersionUID = 5372048053134512534L;
430 * @serialData Default fields, followed by a two byte version number
431 * (major byte, followed by minor byte), followed by information on
432 * the log record parameter array. If there is no parameter array,
433 * then -1 is written. If there is a parameter array (possible of zero
434 * length) then the array length is written as an integer, followed
435 * by String values for each parameter. If a parameter is null, then
436 * a null String is written. Otherwise the output of Object.toString()
439 private void writeObject(ObjectOutputStream out) throws IOException {
440 // We have to call defaultWriteObject first.
441 out.defaultWriteObject();
443 // Write our version number.
446 if (parameters == null) {
450 out.writeInt(parameters.length);
451 // Write string values for the parameters.
452 for (int i = 0; i < parameters.length; i++) {
453 if (parameters[i] == null) {
454 out.writeObject(null);
456 out.writeObject(parameters[i].toString());
462 private boolean isLoggerImplFrame(String cname) {
463 // the log record could be created for a platform logger
464 return (cname.equals("java.util.logging.Logger") ||
465 cname.startsWith("java.util.logging.LoggingProxyImpl") ||
466 cname.startsWith("sun.util.logging."));