History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/logging/LogRecord.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/util/logging/LogRecord.java+566−0
@@ -0,0 +1,566 @@
1+/*
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.
4+ *
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.
10+ *
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).
16+ *
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.
20+ *
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
23+ * questions.
24+ */
25+
26+package java.util.logging;
27+import java.util.*;
28+import java.util.concurrent.atomic.AtomicInteger;
29+import java.util.concurrent.atomic.AtomicLong;
30+import java.io.*;
31+
32+import sun.misc.JavaLangAccess;
33+import sun.misc.SharedSecrets;
34+
35+/**
36+ * LogRecord objects are used to pass logging requests between
37+ * the logging framework and individual log Handlers.
38+ * <p>
39+ * When a LogRecord is passed into the logging framework it
40+ * logically belongs to the framework and should no longer be
41+ * used or updated by the client application.
42+ * <p>
43+ * Note that if the client application has not specified an
44+ * explicit source method name and source class name, then the
45+ * LogRecord class will infer them automatically when they are
46+ * first accessed (due to a call on getSourceMethodName or
47+ * getSourceClassName) by analyzing the call stack. Therefore,
48+ * if a logging Handler wants to pass off a LogRecord to another
49+ * thread, or to transmit it over RMI, and if it wishes to subsequently
50+ * obtain method name or class name information it should call
51+ * one of getSourceClassName or getSourceMethodName to force
52+ * the values to be filled in.
53+ * <p>
54+ * <b> Serialization notes:</b>
55+ * <ul>
56+ * <li>The LogRecord class is serializable.
57+ *
58+ * <li> Because objects in the parameters array may not be serializable,
59+ * during serialization all objects in the parameters array are
60+ * written as the corresponding Strings (using Object.toString).
61+ *
62+ * <li> The ResourceBundle is not transmitted as part of the serialized
63+ * form, but the resource bundle name is, and the recipient object's
64+ * readObject method will attempt to locate a suitable resource bundle.
65+ *
66+ * </ul>
67+ *
68+ * @since 1.4
69+ */
70+
71+public class LogRecord implements java.io.Serializable {
72+ private static final AtomicLong globalSequenceNumber
73+ = new AtomicLong(0);
74+
75+ /**
76+ * The default value of threadID will be the current thread's
77+ * thread id, for ease of correlation, unless it is greater than
78+ * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
79+ * our promise to keep threadIDs unique by avoiding collisions due
80+ * to 32-bit wraparound. Unfortunately, LogRecord.getThreadID()
81+ * returns int, while Thread.getId() returns long.
82+ */
83+ private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
84+
85+ private static final AtomicInteger nextThreadId
86+ = new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID);
87+
88+ private static final ThreadLocal<Integer> threadIds = new ThreadLocal<>();
89+
90+ /**
91+ * @serial Logging message level
92+ */
93+ private Level level;
94+
95+ /**
96+ * @serial Sequence number
97+ */
98+ private long sequenceNumber;
99+
100+ /**
101+ * @serial Class that issued logging call
102+ */
103+ private String sourceClassName;
104+
105+ /**
106+ * @serial Method that issued logging call
107+ */
108+ private String sourceMethodName;
109+
110+ /**
111+ * @serial Non-localized raw message text
112+ */
113+ private String message;
114+
115+ /**
116+ * @serial Thread ID for thread that issued logging call.
117+ */
118+ private int threadID;
119+
120+ /**
121+ * @serial Event time in milliseconds since 1970
122+ */
123+ private long millis;
124+
125+ /**
126+ * @serial The Throwable (if any) associated with log message
127+ */
128+ private Throwable thrown;
129+
130+ /**
131+ * @serial Name of the source Logger.
132+ */
133+ private String loggerName;
134+
135+ /**
136+ * @serial Resource bundle name to localized log message.
137+ */
138+ private String resourceBundleName;
139+
140+ private transient boolean needToInferCaller;
141+ private transient Object parameters[];
142+ private transient ResourceBundle resourceBundle;
143+
144+ /**
145+ * Returns the default value for a new LogRecord's threadID.
146+ */
147+ private int defaultThreadID() {
148+ long tid = Thread.currentThread().getId();
149+ if (tid < MIN_SEQUENTIAL_THREAD_ID) {
150+ return (int) tid;
151+ } else {
152+ Integer id = threadIds.get();
153+ if (id == null) {
154+ id = nextThreadId.getAndIncrement();
155+ threadIds.set(id);
156+ }
157+ return id;
158+ }
159+ }
160+
161+ /**
162+ * Construct a LogRecord with the given level and message values.
163+ * <p>
164+ * The sequence property will be initialized with a new unique value.
165+ * These sequence values are allocated in increasing order within a VM.
166+ * <p>
167+ * The millis property will be initialized to the current time.
168+ * <p>
169+ * The thread ID property will be initialized with a unique ID for
170+ * the current thread.
171+ * <p>
172+ * All other properties will be initialized to "null".
173+ *
174+ * @param level a logging level value
175+ * @param msg the raw non-localized logging message (may be null)
176+ */
177+ public LogRecord(Level level, String msg) {
178+ // Make sure level isn't null, by calling random method.
179+ level.getClass();
180+ this.level = level;
181+ message = msg;
182+ // Assign a thread ID and a unique sequence number.
183+ sequenceNumber = globalSequenceNumber.getAndIncrement();
184+ threadID = defaultThreadID();
185+ millis = System.currentTimeMillis();
186+ needToInferCaller = true;
187+ }
188+
189+ /**
190+ * Get the source Logger's name.
191+ *
192+ * @return source logger name (may be null)
193+ */
194+ public String getLoggerName() {
195+ return loggerName;
196+ }
197+
198+ /**
199+ * Set the source Logger's name.
200+ *
201+ * @param name the source logger name (may be null)
202+ */
203+ public void setLoggerName(String name) {
204+ loggerName = name;
205+ }
206+
207+ /**
208+ * Get the localization resource bundle
209+ * <p>
210+ * This is the ResourceBundle that should be used to localize
211+ * the message string before formatting it. The result may
212+ * be null if the message is not localizable, or if no suitable
213+ * ResourceBundle is available.
214+ */
215+ public ResourceBundle getResourceBundle() {
216+ return resourceBundle;
217+ }
218+
219+ /**
220+ * Set the localization resource bundle.
221+ *
222+ * @param bundle localization bundle (may be null)
223+ */
224+ public void setResourceBundle(ResourceBundle bundle) {
225+ resourceBundle = bundle;
226+ }
227+
228+ /**
229+ * Get the localization resource bundle name
230+ * <p>
231+ * This is the name for the ResourceBundle that should be
232+ * used to localize the message string before formatting it.
233+ * The result may be null if the message is not localizable.
234+ */
235+ public String getResourceBundleName() {
236+ return resourceBundleName;
237+ }
238+
239+ /**
240+ * Set the localization resource bundle name.
241+ *
242+ * @param name localization bundle name (may be null)
243+ */
244+ public void setResourceBundleName(String name) {
245+ resourceBundleName = name;
246+ }
247+
248+ /**
249+ * Get the logging message level, for example Level.SEVERE.
250+ * @return the logging message level
251+ */
252+ public Level getLevel() {
253+ return level;
254+ }
255+
256+ /**
257+ * Set the logging message level, for example Level.SEVERE.
258+ * @param level the logging message level
259+ */
260+ public void setLevel(Level level) {
261+ if (level == null) {
262+ throw new NullPointerException();
263+ }
264+ this.level = level;
265+ }
266+
267+ /**
268+ * Get the sequence number.
269+ * <p>
270+ * Sequence numbers are normally assigned in the LogRecord
271+ * constructor, which assigns unique sequence numbers to
272+ * each new LogRecord in increasing order.
273+ * @return the sequence number
274+ */
275+ public long getSequenceNumber() {
276+ return sequenceNumber;
277+ }
278+
279+ /**
280+ * Set the sequence number.
281+ * <p>
282+ * Sequence numbers are normally assigned in the LogRecord constructor,
283+ * so it should not normally be necessary to use this method.
284+ */
285+ public void setSequenceNumber(long seq) {
286+ sequenceNumber = seq;
287+ }
288+
289+ /**
290+ * Get the name of the class that (allegedly) issued the logging request.
291+ * <p>
292+ * Note that this sourceClassName is not verified and may be spoofed.
293+ * This information may either have been provided as part of the
294+ * logging call, or it may have been inferred automatically by the
295+ * logging framework. In the latter case, the information may only
296+ * be approximate and may in fact describe an earlier call on the
297+ * stack frame.
298+ * <p>
299+ * May be null if no information could be obtained.
300+ *
301+ * @return the source class name
302+ */
303+ public String getSourceClassName() {
304+ if (needToInferCaller) {
305+ inferCaller();
306+ }
307+ return sourceClassName;
308+ }
309+
310+ /**
311+ * Set the name of the class that (allegedly) issued the logging request.
312+ *
313+ * @param sourceClassName the source class name (may be null)
314+ */
315+ public void setSourceClassName(String sourceClassName) {
316+ this.sourceClassName = sourceClassName;
317+ needToInferCaller = false;
318+ }
319+
320+ /**
321+ * Get the name of the method that (allegedly) issued the logging request.
322+ * <p>
323+ * Note that this sourceMethodName is not verified and may be spoofed.
324+ * This information may either have been provided as part of the
325+ * logging call, or it may have been inferred automatically by the
326+ * logging framework. In the latter case, the information may only
327+ * be approximate and may in fact describe an earlier call on the
328+ * stack frame.
329+ * <p>
330+ * May be null if no information could be obtained.
331+ *
332+ * @return the source method name
333+ */
334+ public String getSourceMethodName() {
335+ if (needToInferCaller) {
336+ inferCaller();
337+ }
338+ return sourceMethodName;
339+ }
340+
341+ /**
342+ * Set the name of the method that (allegedly) issued the logging request.
343+ *
344+ * @param sourceMethodName the source method name (may be null)
345+ */
346+ public void setSourceMethodName(String sourceMethodName) {
347+ this.sourceMethodName = sourceMethodName;
348+ needToInferCaller = false;
349+ }
350+
351+ /**
352+ * Get the "raw" log message, before localization or formatting.
353+ * <p>
354+ * May be null, which is equivalent to the empty string "".
355+ * <p>
356+ * This message may be either the final text or a localization key.
357+ * <p>
358+ * During formatting, if the source logger has a localization
359+ * ResourceBundle and if that ResourceBundle has an entry for
360+ * this message string, then the message string is replaced
361+ * with the localized value.
362+ *
363+ * @return the raw message string
364+ */
365+ public String getMessage() {
366+ return message;
367+ }
368+
369+ /**
370+ * Set the "raw" log message, before localization or formatting.
371+ *
372+ * @param message the raw message string (may be null)
373+ */
374+ public void setMessage(String message) {
375+ this.message = message;
376+ }
377+
378+ /**
379+ * Get the parameters to the log message.
380+ *
381+ * @return the log message parameters. May be null if
382+ * there are no parameters.
383+ */
384+ public Object[] getParameters() {
385+ return parameters;
386+ }
387+
388+ /**
389+ * Set the parameters to the log message.
390+ *
391+ * @param parameters the log message parameters. (may be null)
392+ */
393+ public void setParameters(Object parameters[]) {
394+ this.parameters = parameters;
395+ }
396+
397+ /**
398+ * Get an identifier for the thread where the message originated.
399+ * <p>
400+ * This is a thread identifier within the Java VM and may or
401+ * may not map to any operating system ID.
402+ *
403+ * @return thread ID
404+ */
405+ public int getThreadID() {
406+ return threadID;
407+ }
408+
409+ /**
410+ * Set an identifier for the thread where the message originated.
411+ * @param threadID the thread ID
412+ */
413+ public void setThreadID(int threadID) {
414+ this.threadID = threadID;
415+ }
416+
417+ /**
418+ * Get event time in milliseconds since 1970.
419+ *
420+ * @return event time in millis since 1970
421+ */
422+ public long getMillis() {
423+ return millis;
424+ }
425+
426+ /**
427+ * Set event time.
428+ *
429+ * @param millis event time in millis since 1970
430+ */
431+ public void setMillis(long millis) {
432+ this.millis = millis;
433+ }
434+
435+ /**
436+ * Get any throwable associated with the log record.
437+ * <p>
438+ * If the event involved an exception, this will be the
439+ * exception object. Otherwise null.
440+ *
441+ * @return a throwable
442+ */
443+ public Throwable getThrown() {
444+ return thrown;
445+ }
446+
447+ /**
448+ * Set a throwable associated with the log event.
449+ *
450+ * @param thrown a throwable (may be null)
451+ */
452+ public void setThrown(Throwable thrown) {
453+ this.thrown = thrown;
454+ }
455+
456+ private static final long serialVersionUID = 5372048053134512534L;
457+
458+ /**
459+ * @serialData Default fields, followed by a two byte version number
460+ * (major byte, followed by minor byte), followed by information on
461+ * the log record parameter array. If there is no parameter array,
462+ * then -1 is written. If there is a parameter array (possible of zero
463+ * length) then the array length is written as an integer, followed
464+ * by String values for each parameter. If a parameter is null, then
465+ * a null String is written. Otherwise the output of Object.toString()
466+ * is written.
467+ */
468+ private void writeObject(ObjectOutputStream out) throws IOException {
469+ // We have to call defaultWriteObject first.
470+ out.defaultWriteObject();
471+
472+ // Write our version number.
473+ out.writeByte(1);
474+ out.writeByte(0);
475+ if (parameters == null) {
476+ out.writeInt(-1);
477+ return;
478+ }
479+ out.writeInt(parameters.length);
480+ // Write string values for the parameters.
481+ for (int i = 0; i < parameters.length; i++) {
482+ if (parameters[i] == null) {
483+ out.writeObject(null);
484+ } else {
485+ out.writeObject(parameters[i].toString());
486+ }
487+ }
488+ }
489+
490+ private void readObject(ObjectInputStream in)
491+ throws IOException, ClassNotFoundException {
492+ // We have to call defaultReadObject first.
493+ in.defaultReadObject();
494+
495+ // Read version number.
496+ byte major = in.readByte();
497+ byte minor = in.readByte();
498+ if (major != 1) {
499+ throw new IOException("LogRecord: bad version: " + major + "." + minor);
500+ }
501+ int len = in.readInt();
502+ if (len == -1) {
503+ parameters = null;
504+ } else {
505+ parameters = new Object[len];
506+ for (int i = 0; i < parameters.length; i++) {
507+ parameters[i] = in.readObject();
508+ }
509+ }
510+ // If necessary, try to regenerate the resource bundle.
511+ if (resourceBundleName != null) {
512+ try {
513+ resourceBundle = ResourceBundle.getBundle(resourceBundleName);
514+ } catch (MissingResourceException ex) {
515+ // This is not a good place to throw an exception,
516+ // so we simply leave the resourceBundle null.
517+ resourceBundle = null;
518+ }
519+ }
520+
521+ needToInferCaller = false;
522+ }
523+
524+ // Private method to infer the caller's class and method names
525+ private void inferCaller() {
526+ needToInferCaller = false;
527+ JavaLangAccess access = SharedSecrets.getJavaLangAccess();
528+ Throwable throwable = new Throwable();
529+ int depth = access.getStackTraceDepth(throwable);
530+
531+ boolean lookingForLogger = true;
532+ for (int ix = 0; ix < depth; ix++) {
533+ // Calling getStackTraceElement directly prevents the VM
534+ // from paying the cost of building the entire stack frame.
535+ StackTraceElement frame =
536+ access.getStackTraceElement(throwable, ix);
537+ String cname = frame.getClassName();
538+ boolean isLoggerImpl = isLoggerImplFrame(cname);
539+ if (lookingForLogger) {
540+ // Skip all frames until we have found the first logger frame.
541+ if (isLoggerImpl) {
542+ lookingForLogger = false;
543+ }
544+ } else {
545+ if (!isLoggerImpl) {
546+ // skip reflection call
547+ if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
548+ // We've found the relevant frame.
549+ setSourceClassName(cname);
550+ setSourceMethodName(frame.getMethodName());
551+ return;
552+ }
553+ }
554+ }
555+ }
556+ // We haven't found a suitable frame, so just punt. This is
557+ // OK as we are only committed to making a "best effort" here.
558+ }
559+
560+ private boolean isLoggerImplFrame(String cname) {
561+ // the log record could be created for a platform logger
562+ return (cname.equals("java.util.logging.Logger") ||
563+ cname.startsWith("java.util.logging.LoggingProxyImpl") ||
564+ cname.startsWith("sun.util.logging."));
565+ }
566+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t