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/sun/util/logging/PlatformLogger.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/util/logging/PlatformLogger.java+571−0
@@ -0,0 +1,571 @@
1+/*
2+ * Copyright (c) 2009, 2011, 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+
27+package sun.util.logging;
28+
29+import java.lang.ref.WeakReference;
30+import java.lang.reflect.InvocationTargetException;
31+import java.lang.reflect.Method;
32+import java.io.PrintStream;
33+import java.io.PrintWriter;
34+import java.io.StringWriter;
35+import java.security.AccessController;
36+import java.security.PrivilegedAction;
37+import java.text.MessageFormat;
38+import java.util.Date;
39+import java.util.HashMap;
40+import java.util.Map;
41+import sun.misc.JavaLangAccess;
42+import sun.misc.SharedSecrets;
43+
44+/**
45+ * Platform logger provides an API for the JRE components to log
46+ * messages. This enables the runtime components to eliminate the
47+ * static dependency of the logging facility and also defers the
48+ * java.util.logging initialization until it is enabled.
49+ * In addition, the PlatformLogger API can be used if the logging
50+ * module does not exist.
51+ *
52+ * If the logging facility is not enabled, the platform loggers
53+ * will output log messages per the default logging configuration
54+ * (see below). In this implementation, it does not log the
55+ * the stack frame information issuing the log message.
56+ *
57+ * When the logging facility is enabled (at startup or runtime),
58+ * the java.util.logging.Logger will be created for each platform
59+ * logger and all log messages will be forwarded to the Logger
60+ * to handle.
61+ *
62+ * Logging facility is "enabled" when one of the following
63+ * conditions is met:
64+ * 1) a system property "java.util.logging.config.class" or
65+ * "java.util.logging.config.file" is set
66+ * 2) java.util.logging.LogManager or java.util.logging.Logger
67+ * is referenced that will trigger the logging initialization.
68+ *
69+ * Default logging configuration:
70+ * global logging level = INFO
71+ * handlers = java.util.logging.ConsoleHandler
72+ * java.util.logging.ConsoleHandler.level = INFO
73+ * java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
74+ *
75+ * Limitation:
76+ * <JAVA_HOME>/lib/logging.properties is the system-wide logging
77+ * configuration defined in the specification and read in the
78+ * default case to configure any java.util.logging.Logger instances.
79+ * Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
80+ * is modified. In other words, unless the java.util.logging API
81+ * is used at runtime or the logging system properties is set,
82+ * the platform loggers will use the default setting described above.
83+ * The platform loggers are designed for JDK developers use and
84+ * this limitation can be workaround with setting
85+ * -Djava.util.logging.config.file system property.
86+ *
87+ * @since 1.7
88+ */
89+public class PlatformLogger {
90+ // Same values as java.util.logging.Level for easy mapping
91+ public static final int OFF = Integer.MAX_VALUE;
92+ public static final int SEVERE = 1000;
93+ public static final int WARNING = 900;
94+ public static final int INFO = 800;
95+ public static final int CONFIG = 700;
96+ public static final int FINE = 500;
97+ public static final int FINER = 400;
98+ public static final int FINEST = 300;
99+ public static final int ALL = Integer.MIN_VALUE;
100+
101+ private static final int defaultLevel = INFO;
102+ private static boolean loggingEnabled;
103+ static {
104+ loggingEnabled = AccessController.doPrivileged(
105+ new PrivilegedAction<Boolean>() {
106+ public Boolean run() {
107+ String cname = System.getProperty("java.util.logging.config.class");
108+ String fname = System.getProperty("java.util.logging.config.file");
109+ return (cname != null || fname != null);
110+ }
111+ });
112+ }
113+
114+ // Table of known loggers. Maps names to PlatformLoggers.
115+ private static Map<String,WeakReference<PlatformLogger>> loggers =
116+ new HashMap<>();
117+
118+ /**
119+ * Returns a PlatformLogger of a given name.
120+ */
121+ public static synchronized PlatformLogger getLogger(String name) {
122+ PlatformLogger log = null;
123+ WeakReference<PlatformLogger> ref = loggers.get(name);
124+ if (ref != null) {
125+ log = ref.get();
126+ }
127+ if (log == null) {
128+ log = new PlatformLogger(name);
129+ loggers.put(name, new WeakReference<>(log));
130+ }
131+ return log;
132+ }
133+
134+ /**
135+ * Initialize java.util.logging.Logger objects for all platform loggers.
136+ * This method is called from LogManager.readPrimordialConfiguration().
137+ */
138+ public static synchronized void redirectPlatformLoggers() {
139+ if (loggingEnabled || !LoggingSupport.isAvailable()) return;
140+
141+ loggingEnabled = true;
142+ for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
143+ WeakReference<PlatformLogger> ref = entry.getValue();
144+ PlatformLogger plog = ref.get();
145+ if (plog != null) {
146+ plog.newJavaLogger();
147+ }
148+ }
149+ }
150+
151+ /**
152+ * Creates a new JavaLogger that the platform logger uses
153+ */
154+ private void newJavaLogger() {
155+ logger = new JavaLogger(logger.name, logger.effectiveLevel);
156+ }
157+
158+ // logger may be replaced with a JavaLogger object
159+ // when the logging facility is enabled
160+ private volatile LoggerProxy logger;
161+
162+ private PlatformLogger(String name) {
163+ if (loggingEnabled) {
164+ this.logger = new JavaLogger(name);
165+ } else {
166+ this.logger = new LoggerProxy(name);
167+ }
168+ }
169+
170+ /**
171+ * A convenience method to test if the logger is turned off.
172+ * (i.e. its level is OFF).
173+ */
174+ public boolean isEnabled() {
175+ return logger.isEnabled();
176+ }
177+
178+ /**
179+ * Gets the name for this platform logger.
180+ */
181+ public String getName() {
182+ return logger.name;
183+ }
184+
185+ /**
186+ * Returns true if a message of the given level would actually
187+ * be logged by this logger.
188+ */
189+ public boolean isLoggable(int level) {
190+ return logger.isLoggable(level);
191+ }
192+
193+ /**
194+ * Gets the current log level. Returns 0 if the current effective level
195+ * is not set (equivalent to Logger.getLevel() returns null).
196+ */
197+ public int getLevel() {
198+ return logger.getLevel();
199+ }
200+
201+ /**
202+ * Sets the log level.
203+ */
204+ public void setLevel(int newLevel) {
205+ logger.setLevel(newLevel);
206+ }
207+
208+ /**
209+ * Logs a SEVERE message.
210+ */
211+ public void severe(String msg) {
212+ logger.doLog(SEVERE, msg);
213+ }
214+
215+ public void severe(String msg, Throwable t) {
216+ logger.doLog(SEVERE, msg, t);
217+ }
218+
219+ public void severe(String msg, Object... params) {
220+ logger.doLog(SEVERE, msg, params);
221+ }
222+
223+ /**
224+ * Logs a WARNING message.
225+ */
226+ public void warning(String msg) {
227+ logger.doLog(WARNING, msg);
228+ }
229+
230+ public void warning(String msg, Throwable t) {
231+ logger.doLog(WARNING, msg, t);
232+ }
233+
234+ public void warning(String msg, Object... params) {
235+ logger.doLog(WARNING, msg, params);
236+ }
237+
238+ /**
239+ * Logs an INFO message.
240+ */
241+ public void info(String msg) {
242+ logger.doLog(INFO, msg);
243+ }
244+
245+ public void info(String msg, Throwable t) {
246+ logger.doLog(INFO, msg, t);
247+ }
248+
249+ public void info(String msg, Object... params) {
250+ logger.doLog(INFO, msg, params);
251+ }
252+
253+ /**
254+ * Logs a CONFIG message.
255+ */
256+ public void config(String msg) {
257+ logger.doLog(CONFIG, msg);
258+ }
259+
260+ public void config(String msg, Throwable t) {
261+ logger.doLog(CONFIG, msg, t);
262+ }
263+
264+ public void config(String msg, Object... params) {
265+ logger.doLog(CONFIG, msg, params);
266+ }
267+
268+ /**
269+ * Logs a FINE message.
270+ */
271+ public void fine(String msg) {
272+ logger.doLog(FINE, msg);
273+ }
274+
275+ public void fine(String msg, Throwable t) {
276+ logger.doLog(FINE, msg, t);
277+ }
278+
279+ public void fine(String msg, Object... params) {
280+ logger.doLog(FINE, msg, params);
281+ }
282+
283+ /**
284+ * Logs a FINER message.
285+ */
286+ public void finer(String msg) {
287+ logger.doLog(FINER, msg);
288+ }
289+
290+ public void finer(String msg, Throwable t) {
291+ logger.doLog(FINER, msg, t);
292+ }
293+
294+ public void finer(String msg, Object... params) {
295+ logger.doLog(FINER, msg, params);
296+ }
297+
298+ /**
299+ * Logs a FINEST message.
300+ */
301+ public void finest(String msg) {
302+ logger.doLog(FINEST, msg);
303+ }
304+
305+ public void finest(String msg, Throwable t) {
306+ logger.doLog(FINEST, msg, t);
307+ }
308+
309+ public void finest(String msg, Object... params) {
310+ logger.doLog(FINEST, msg, params);
311+ }
312+
313+ /**
314+ * Default platform logging support - output messages to
315+ * System.err - equivalent to ConsoleHandler with SimpleFormatter.
316+ */
317+ static class LoggerProxy {
318+ private static final PrintStream defaultStream = System.err;
319+
320+ final String name;
321+ volatile int levelValue;
322+ volatile int effectiveLevel = 0; // current effective level value
323+
324+ LoggerProxy(String name) {
325+ this(name, defaultLevel);
326+ }
327+
328+ LoggerProxy(String name, int level) {
329+ this.name = name;
330+ this.levelValue = level == 0 ? defaultLevel : level;
331+ }
332+
333+ boolean isEnabled() {
334+ return levelValue != OFF;
335+ }
336+
337+ int getLevel() {
338+ return effectiveLevel;
339+ }
340+
341+ void setLevel(int newLevel) {
342+ levelValue = newLevel;
343+ effectiveLevel = newLevel;
344+ }
345+
346+ void doLog(int level, String msg) {
347+ if (level < levelValue || levelValue == OFF) {
348+ return;
349+ }
350+ defaultStream.print(format(level, msg, null));
351+ }
352+
353+ void doLog(int level, String msg, Throwable thrown) {
354+ if (level < levelValue || levelValue == OFF) {
355+ return;
356+ }
357+ defaultStream.print(format(level, msg, thrown));
358+ }
359+
360+ void doLog(int level, String msg, Object... params) {
361+ if (level < levelValue || levelValue == OFF) {
362+ return;
363+ }
364+ String newMsg = formatMessage(msg, params);
365+ defaultStream.print(format(level, newMsg, null));
366+ }
367+
368+ public boolean isLoggable(int level) {
369+ if (level < levelValue || levelValue == OFF) {
370+ return false;
371+ }
372+ return true;
373+ }
374+
375+ // Copied from java.util.logging.Formatter.formatMessage
376+ private String formatMessage(String format, Object... parameters) {
377+ // Do the formatting.
378+ try {
379+ if (parameters == null || parameters.length == 0) {
380+ // No parameters. Just return format string.
381+ return format;
382+ }
383+ // Is it a java.text style format?
384+ // Ideally we could match with
385+ // Pattern.compile("\\{\\d").matcher(format).find())
386+ // However the cost is 14% higher, so we cheaply check for
387+ // 1 of the first 4 parameters
388+ if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
389+ format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
390+ return java.text.MessageFormat.format(format, parameters);
391+ }
392+ return format;
393+ } catch (Exception ex) {
394+ // Formatting failed: use format string.
395+ return format;
396+ }
397+ }
398+
399+ private static final String formatString =
400+ LoggingSupport.getSimpleFormat(false); // don't check logging.properties
401+
402+ // minimize memory allocation
403+ private Date date = new Date();
404+ private synchronized String format(int level, String msg, Throwable thrown) {
405+ date.setTime(System.currentTimeMillis());
406+ String throwable = "";
407+ if (thrown != null) {
408+ StringWriter sw = new StringWriter();
409+ PrintWriter pw = new PrintWriter(sw);
410+ pw.println();
411+ thrown.printStackTrace(pw);
412+ pw.close();
413+ throwable = sw.toString();
414+ }
415+
416+ return String.format(formatString,
417+ date,
418+ getCallerInfo(),
419+ name,
420+ PlatformLogger.getLevelName(level),
421+ msg,
422+ throwable);
423+ }
424+
425+ // Returns the caller's class and method's name; best effort
426+ // if cannot infer, return the logger's name.
427+ private String getCallerInfo() {
428+ String sourceClassName = null;
429+ String sourceMethodName = null;
430+
431+ JavaLangAccess access = SharedSecrets.getJavaLangAccess();
432+ Throwable throwable = new Throwable();
433+ int depth = access.getStackTraceDepth(throwable);
434+
435+ String logClassName = "sun.util.logging.PlatformLogger";
436+ boolean lookingForLogger = true;
437+ for (int ix = 0; ix < depth; ix++) {
438+ // Calling getStackTraceElement directly prevents the VM
439+ // from paying the cost of building the entire stack frame.
440+ StackTraceElement frame =
441+ access.getStackTraceElement(throwable, ix);
442+ String cname = frame.getClassName();
443+ if (lookingForLogger) {
444+ // Skip all frames until we have found the first logger frame.
445+ if (cname.equals(logClassName)) {
446+ lookingForLogger = false;
447+ }
448+ } else {
449+ if (!cname.equals(logClassName)) {
450+ // We've found the relevant frame.
451+ sourceClassName = cname;
452+ sourceMethodName = frame.getMethodName();
453+ break;
454+ }
455+ }
456+ }
457+
458+ if (sourceClassName != null) {
459+ return sourceClassName + " " + sourceMethodName;
460+ } else {
461+ return name;
462+ }
463+ }
464+ }
465+
466+ /**
467+ * JavaLogger forwards all the calls to its corresponding
468+ * java.util.logging.Logger object.
469+ */
470+ static class JavaLogger extends LoggerProxy {
471+ private static final Map<Integer, Object> levelObjects =
472+ new HashMap<>();
473+
474+ static {
475+ if (LoggingSupport.isAvailable()) {
476+ // initialize the map to Level objects
477+ getLevelObjects();
478+ }
479+ }
480+
481+ private static void getLevelObjects() {
482+ // get all java.util.logging.Level objects
483+ int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
484+ for (int l : levelArray) {
485+ Object level = LoggingSupport.parseLevel(getLevelName(l));
486+ levelObjects.put(l, level);
487+ }
488+ }
489+
490+ private final Object javaLogger;
491+ JavaLogger(String name) {
492+ this(name, 0);
493+ }
494+
495+ JavaLogger(String name, int level) {
496+ super(name, level);
497+ this.javaLogger = LoggingSupport.getLogger(name);
498+ if (level != 0) {
499+ // level has been updated and so set the Logger's level
500+ LoggingSupport.setLevel(javaLogger, levelObjects.get(level));
501+ }
502+ }
503+
504+ /**
505+ * Let Logger.log() do the filtering since if the level of a
506+ * platform logger is altered directly from
507+ * java.util.logging.Logger.setLevel(), the levelValue will
508+ * not be updated.
509+ */
510+ void doLog(int level, String msg) {
511+ LoggingSupport.log(javaLogger, levelObjects.get(level), msg);
512+ }
513+
514+ void doLog(int level, String msg, Throwable t) {
515+ LoggingSupport.log(javaLogger, levelObjects.get(level), msg, t);
516+ }
517+
518+ void doLog(int level, String msg, Object... params) {
519+ // only pass String objects to the j.u.l.Logger which may
520+ // be created by untrusted code
521+ int len = (params != null) ? params.length : 0;
522+ Object[] sparams = new String[len];
523+ for (int i = 0; i < len; i++) {
524+ sparams [i] = String.valueOf(params[i]);
525+ }
526+ LoggingSupport.log(javaLogger, levelObjects.get(level), msg, sparams);
527+ }
528+
529+ boolean isEnabled() {
530+ Object level = LoggingSupport.getLevel(javaLogger);
531+ return level == null || level.equals(levelObjects.get(OFF)) == false;
532+ }
533+
534+ int getLevel() {
535+ Object level = LoggingSupport.getLevel(javaLogger);
536+ if (level != null) {
537+ for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) {
538+ if (level == l.getValue()) {
539+ return l.getKey();
540+ }
541+ }
542+ }
543+ return 0;
544+ }
545+
546+ void setLevel(int newLevel) {
547+ levelValue = newLevel;
548+ LoggingSupport.setLevel(javaLogger, levelObjects.get(newLevel));
549+ }
550+
551+ public boolean isLoggable(int level) {
552+ return LoggingSupport.isLoggable(javaLogger, levelObjects.get(level));
553+ }
554+ }
555+
556+ private static String getLevelName(int level) {
557+ switch (level) {
558+ case OFF : return "OFF";
559+ case SEVERE : return "SEVERE";
560+ case WARNING : return "WARNING";
561+ case INFO : return "INFO";
562+ case CONFIG : return "CONFIG";
563+ case FINE : return "FINE";
564+ case FINER : return "FINER";
565+ case FINEST : return "FINEST";
566+ case ALL : return "ALL";
567+ default : return "UNKNOWN";
568+ }
569+ }
570+
571+}