KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > logging > LogRecord


1 /*
2  * @(#)LogRecord.java 1.23 04/01/12
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.logging;
9 import java.util.*;
10 import java.io.*;
11
12 /**
13  * LogRecord objects are used to pass logging requests between
14  * the logging framework and individual log Handlers.
15  * <p>
16  * When a LogRecord is passed into the logging framework it
17  * logically belongs to the framework and should no longer be
18  * used or updated by the client application.
19  * <p>
20  * Note that if the client application has not specified an
21  * explicit source method name and source class name, then the
22  * LogRecord class will infer them automatically when they are
23  * first accessed (due to a call on getSourceMethodName or
24  * getSourceClassName) by analyzing the call stack. Therefore,
25  * if a logging Handler wants to pass off a LogRecord to another
26  * thread, or to transmit it over RMI, and if it wishes to subsequently
27  * obtain method name or class name information it should call
28  * one of getSourceClassName or getSourceMethodName to force
29  * the values to be filled in.
30  * <p>
31  * <b> Serialization notes:</b>
32  * <ul>
33  * <li>The LogRecord class is serializable.
34  *
35  * <li> Because objects in the parameters array may not be serializable,
36  * during serialization all objects in the parameters array are
37  * written as the corresponding Strings (using Object.toString).
38  *
39  * <li> The ResourceBundle is not transmitted as part of the serialized
40  * form, but the resource bundle name is, and the recipient object's
41  * readObject method will attempt to locate a suitable resource bundle.
42  *
43  * </ul>
44  *
45  * @version 1.23, 01/12/04
46  * @since 1.4
47  */

48
49 public class LogRecord implements java.io.Serializable JavaDoc {
50     private static long globalSequenceNumber;
51     private static int nextThreadId=10;
52     private static ThreadLocal JavaDoc threadIds = new ThreadLocal JavaDoc();
53
54     /**
55      * @serial Logging message level
56      */

57     private Level JavaDoc level;
58
59     /**
60      * @serial Sequence number
61      */

62     private long sequenceNumber;
63
64     /**
65      * @serial Class that issued logging call
66      */

67     private String JavaDoc sourceClassName;
68
69     /**
70      * @serial Method that issued logging call
71      */

72     private String JavaDoc sourceMethodName;
73
74     /**
75      * @serial Non-localized raw message text
76      */

77     private String JavaDoc message;
78
79     /**
80      * @serial Thread ID for thread that issued logging call.
81      */

82     private int threadID;
83
84     /**
85      * @serial Event time in milliseconds since 1970
86      */

87     private long millis;
88
89     /**
90      * @serial The Throwable (if any) associated with log message
91      */

92     private Throwable JavaDoc thrown;
93
94     /**
95      * @serial Name of the source Logger.
96      */

97     private String JavaDoc loggerName;
98
99     /**
100      * @serial Resource bundle name to localized log message.
101      */

102     private String JavaDoc resourceBundleName;
103
104     private transient boolean needToInferCaller;
105     private transient Object JavaDoc parameters[];
106     private transient ResourceBundle resourceBundle;
107
108     /**
109      * Construct a LogRecord with the given level and message values.
110      * <p>
111      * The sequence property will be initialized with a new unique value.
112      * These sequence values are allocated in increasing order within a VM.
113      * <p>
114      * The millis property will be initialized to the current time.
115      * <p>
116      * The thread ID property will be initialized with a unique ID for
117      * the current thread.
118      * <p>
119      * All other properties will be initialized to "null".
120      *
121      * @param level a logging level value
122      * @param msg the raw non-localized logging message (may be null)
123      */

124     public LogRecord(Level JavaDoc level, String JavaDoc msg) {
125     // Make sure level isn't null, by calling random method.
126
level.getClass();
127     this.level = level;
128     message = msg;
129     // Assign a thread ID and a unique sequence number.
130
synchronized (LogRecord JavaDoc.class) {
131         sequenceNumber = globalSequenceNumber++;
132         Integer JavaDoc id = (Integer JavaDoc)threadIds.get();
133         if (id == null) {
134         id = new Integer JavaDoc(nextThreadId++);
135         threadIds.set(id);
136         }
137         threadID = id.intValue();
138     }
139     millis = System.currentTimeMillis();
140     needToInferCaller = true;
141    }
142
143     /**
144      * Get the source Logger name's
145      *
146      * @return source logger name (may be null)
147      */

148     public String JavaDoc getLoggerName() {
149     return loggerName;
150     }
151    
152     /**
153      * Set the source Logger name.
154      *
155      * @param name the source logger name (may be null)
156      */

157     public void setLoggerName(String JavaDoc name) {
158     loggerName = name;
159     }
160    
161     /**
162      * Get the localization resource bundle
163      * <p>
164      * This is the ResourceBundle that should be used to localize
165      * the message string before formatting it. The result may
166      * be null if the message is not localizable, or if no suitable
167      * ResourceBundle is available.
168      */

169     public ResourceBundle getResourceBundle() {
170     return resourceBundle;
171     }
172    
173     /**
174      * Set the localization resource bundle.
175      *
176      * @param bundle localization bundle (may be null)
177      */

178     public void setResourceBundle(ResourceBundle bundle) {
179     resourceBundle = bundle;
180     }
181    
182     /**
183      * Get the localization resource bundle name
184      * <p>
185      * This is the name for the ResourceBundle that should be
186      * used to localize the message string before formatting it.
187      * The result may be null if the message is not localizable.
188      */

189     public String JavaDoc getResourceBundleName() {
190     return resourceBundleName;
191     }
192    
193     /**
194      * Set the localization resource bundle name.
195      *
196      * @param name localization bundle name (may be null)
197      */

198     public void setResourceBundleName(String JavaDoc name) {
199     resourceBundleName = name;
200     }
201    
202     /**
203      * Get the logging message level, for example Level.SEVERE.
204      * @return the logging message level
205      */

206     public Level JavaDoc getLevel() {
207     return level;
208     }
209
210     /**
211      * Set the logging message level, for example Level.SEVERE.
212      * @param level the logging message level
213      */

214     public void setLevel(Level JavaDoc level) {
215     if (level == null) {
216         throw new NullPointerException JavaDoc();
217     }
218     this.level = level;
219     }
220
221     /**
222      * Get the sequence number.
223      * <p>
224      * Sequence numbers are normally assigned in the LogRecord
225      * constructor, which assigns unique sequence numbers to
226      * each new LogRecord in increasing order.
227      * @return the sequence number
228      */

229     public long getSequenceNumber() {
230     return sequenceNumber;
231     }
232
233     /**
234      * Set the sequence number.
235      * <p>
236      * Sequence numbers are normally assigned in the LogRecord constructor,
237      * so it should not normally be necessary to use this method.
238      */

239     public void setSequenceNumber(long seq) {
240     sequenceNumber = seq;
241     }
242
243     /**
244      * Get the name of the class that (allegedly) issued the logging request.
245      * <p>
246      * Note that this sourceClassName is not verified and may be spoofed.
247      * This information may either have been provided as part of the
248      * logging call, or it may have been inferred automatically by the
249      * logging framework. In the latter case, the information may only
250      * be approximate and may in fact describe an earlier call on the
251      * stack frame.
252      * <p>
253      * May be null if no information could be obtained.
254      *
255      * @return the source class name
256      */

257     public String JavaDoc getSourceClassName() {
258     if (needToInferCaller) {
259         inferCaller();
260     }
261     return sourceClassName;
262     }
263
264     /**
265      * Set the name of the class that (allegedly) issued the logging request.
266      *
267      * @param sourceClassName the source class name (may be null)
268      */

269     public void setSourceClassName(String JavaDoc sourceClassName) {
270     this.sourceClassName = sourceClassName;
271     needToInferCaller = false;
272     }
273
274     /**
275      * Get the name of the method that (allegedly) issued the logging request.
276      * <p>
277      * Note that this sourceMethodName is not verified and may be spoofed.
278      * This information may either have been provided as part of the
279      * logging call, or it may have been inferred automatically by the
280      * logging framework. In the latter case, the information may only
281      * be approximate and may in fact describe an earlier call on the
282      * stack frame.
283      * <p>
284      * May be null if no information could be obtained.
285      *
286      * @return the source method name
287      */

288     public String JavaDoc getSourceMethodName() {
289     if (needToInferCaller) {
290         inferCaller();
291     }
292     return sourceMethodName;
293     }
294
295     /**
296      * Set the name of the method that (allegedly) issued the logging request.
297      *
298      * @param sourceMethodName the source method name (may be null)
299      */

300     public void setSourceMethodName(String JavaDoc sourceMethodName) {
301     this.sourceMethodName = sourceMethodName;
302     needToInferCaller = false;
303     }
304
305     /**
306      * Get the "raw" log message, before localization or formatting.
307      * <p>
308      * May be null, which is equivalent to the empty string "".
309      * <p>
310      * This message may be either the final text or a localization key.
311      * <p>
312      * During formatting, if the source logger has a localization
313      * ResourceBundle and if that ResourceBundle has an entry for
314      * this message string, then the message string is replaced
315      * with the localized value.
316      *
317      * @return the raw message string
318      */

319     public String JavaDoc getMessage() {
320     return message;
321     }
322
323     /**
324      * Set the "raw" log message, before localization or formatting.
325      *
326      * @param message the raw message string (may be null)
327      */

328     public void setMessage(String JavaDoc message) {
329     this.message = message;
330     }
331
332     /**
333      * Get the parameters to the log message.
334      *
335      * @return the log message parameters. May be null if
336      * there are no parameters.
337      */

338     public Object JavaDoc[] getParameters() {
339     return parameters;
340     }
341
342     /**
343      * Set the parameters to the log message.
344      *
345      * @param parameters the log message parameters. (may be null)
346      */

347     public void setParameters(Object JavaDoc parameters[]) {
348     this.parameters = parameters;
349     }
350
351     /**
352      * Get an identifier for the thread where the message originated.
353      * <p>
354      * This is a thread identifier within the Java VM and may or
355      * may not map to any operating system ID.
356      *
357      * @return thread ID
358      */

359     public int getThreadID() {
360     return threadID;
361     }
362
363     /**
364      * Set an identifier for the thread where the message originated.
365      * @param threadID the thread ID
366      */

367     public void setThreadID(int threadID) {
368     this.threadID = threadID;
369     }
370
371     /**
372      * Get event time in milliseconds since 1970.
373      *
374      * @return event time in millis since 1970
375      */

376     public long getMillis() {
377     return millis;
378     }
379
380     /**
381      * Set event time.
382      *
383      * @param millis event time in millis since 1970
384      */

385     public void setMillis(long millis) {
386     this.millis = millis;
387     }
388
389     /**
390      * Get any throwable associated with the log record.
391      * <p>
392      * If the event involved an exception, this will be the
393      * exception object. Otherwise null.
394      *
395      * @return a throwable
396      */

397     public Throwable JavaDoc getThrown() {
398     return thrown;
399     }
400
401     /**
402      * Set a throwable associated with the log event.
403      *
404      * @param thrown a throwable (may be null)
405      */

406     public void setThrown(Throwable JavaDoc thrown) {
407     this.thrown = thrown;
408     }
409
410     private static final long serialVersionUID = 5372048053134512534L;
411
412     /**
413      * @serialData Default fields, followed by a two byte version number
414      * (major byte, followed by minor byte), followed by information on
415      * the log record parameter array. If there is no parameter array,
416      * then -1 is written. If there is a parameter array (possible of zero
417      * length) then the array length is written as an integer, followed
418      * by String values for each parameter. If a parameter is null, then
419      * a null String is written. Otherwise the output of Object.toString()
420      * is written.
421      */

422     private void writeObject(ObjectOutputStream out) throws IOException {
423     // We have to call defaultWriteObject first.
424
out.defaultWriteObject();
425
426     // Write our version number.
427
out.writeByte(1);
428     out.writeByte(0);
429     if (parameters == null) {
430         out.writeInt(-1);
431         return;
432     }
433     out.writeInt(parameters.length);
434     // Write string values for the parameters.
435
for (int i = 0; i < parameters.length; i++) {
436         if (parameters[i] == null) {
437             out.writeObject(null);
438         } else {
439             out.writeObject(parameters[i].toString());
440         }
441     }
442     }
443
444     private void readObject(ObjectInputStream in)
445             throws IOException, ClassNotFoundException JavaDoc {
446     // We have to call defaultReadObject first.
447
in.defaultReadObject();
448
449     // Read version number.
450
byte major = in.readByte();
451     byte minor = in.readByte();
452     if (major != 1) {
453         throw new IOException("LogRecord: bad version: " + major + "." + minor);
454     }
455     int len = in.readInt();
456     if (len == -1) {
457         parameters = null;
458     } else {
459         parameters = new Object JavaDoc[len];
460         for (int i = 0; i < parameters.length; i++) {
461             parameters[i] = in.readObject();
462         }
463     }
464     // If necessary, try to regenerate the resource bundle.
465
if (resourceBundleName != null) {
466         try {
467             resourceBundle = ResourceBundle.getBundle(resourceBundleName);
468         } catch (MissingResourceException ex) {
469         // This is not a good place to throw an exception,
470
// so we simply leave the resourceBundle null.
471
resourceBundle = null;
472         }
473     }
474
475     needToInferCaller = false;
476     }
477
478     // Private method to infer the caller's class and method names
479
private void inferCaller() {
480     needToInferCaller = false;
481     // Get the stack trace.
482
StackTraceElement JavaDoc stack[] = (new Throwable JavaDoc()).getStackTrace();
483     // First, search back to a method in the Logger class.
484
int ix = 0;
485     while (ix < stack.length) {
486         StackTraceElement JavaDoc frame = stack[ix];
487         String JavaDoc cname = frame.getClassName();
488         if (cname.equals("java.util.logging.Logger")) {
489         break;
490         }
491         ix++;
492     }
493     // Now search for the first frame before the "Logger" class.
494
while (ix < stack.length) {
495         StackTraceElement JavaDoc frame = stack[ix];
496         String JavaDoc cname = frame.getClassName();
497         if (!cname.equals("java.util.logging.Logger")) {
498         // We've found the relevant frame.
499
setSourceClassName(cname);
500             setSourceMethodName(frame.getMethodName());
501         return;
502         }
503         ix++;
504     }
505     // We haven't found a suitable frame, so just punt. This is
506
// OK as we are only committed to making a "best effort" here.
507
}
508 }
509
Popular Tags