6882376: Add internal support for JRE implementation to eliminate the dependency on logging
Added sun.util.logging.PlatformLogger for JRE implementation to log messages. Reviewed-by: alanb, naoto
This commit is contained in:
parent
b43c00d17d
commit
70bee45623
@ -31,7 +31,7 @@ include $(BUILDDIR)/common/Defs.gmk
|
||||
#
|
||||
# Files to compile.
|
||||
#
|
||||
AUTO_FILES_JAVA_DIRS = java/util/logging
|
||||
AUTO_FILES_JAVA_DIRS = java/util/logging sun/util/logging
|
||||
|
||||
#
|
||||
# Resources
|
||||
@ -46,7 +46,6 @@ RESOURCE_BUNDLES_COMPILED_PROPERTIES = \
|
||||
include $(BUILDDIR)/common/Classes.gmk
|
||||
|
||||
properties: $(LIBDIR)/logging.properties
|
||||
|
||||
$(LIBDIR)/logging.properties: $(SHARE_SRC)/lib/logging.properties
|
||||
$(install-file)
|
||||
|
||||
|
@ -35,12 +35,12 @@ import java.io.Serializable;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import sun.util.LocaleServiceProviderPool;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
|
||||
@ -244,7 +244,7 @@ public final class Currency implements Serializable {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log(Level.INFO, "currency.properties is ignored because of an IOException", e);
|
||||
info("currency.properties is ignored because of an IOException", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -686,7 +686,7 @@ public final class Currency implements Serializable {
|
||||
.append("The entry in currency.properties for ")
|
||||
.append(ctry).append(" is ignored because of the invalid country code.")
|
||||
.toString();
|
||||
log(Level.INFO, message, null);
|
||||
info(message, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -698,7 +698,7 @@ public final class Currency implements Serializable {
|
||||
.append(ctry)
|
||||
.append(" is ignored because the value format is not recognized.")
|
||||
.toString();
|
||||
log(Level.INFO, message, null);
|
||||
info(message, null);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -726,13 +726,13 @@ public final class Currency implements Serializable {
|
||||
setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
|
||||
}
|
||||
|
||||
private static void log(Level level, String message, Throwable t) {
|
||||
Logger logger = Logger.getLogger("java.util.Currency");
|
||||
if (logger.isLoggable(level)) {
|
||||
private static void info(String message, Throwable t) {
|
||||
PlatformLogger logger = PlatformLogger.getLogger("java.util.Currency");
|
||||
if (logger.isLoggable(PlatformLogger.INFO)) {
|
||||
if (t != null) {
|
||||
logger.log(level, message, t);
|
||||
logger.info(message, t);
|
||||
} else {
|
||||
logger.log(level, message);
|
||||
logger.info(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Logger;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import java.util.Comparator;
|
||||
import sun.misc.ASCIICaseInsensitiveComparator;
|
||||
|
||||
@ -419,7 +419,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
|
||||
}
|
||||
try {
|
||||
if ((putValue(name, value) != null) && (!lineContinued)) {
|
||||
Logger.getLogger("java.util.jar").warning(
|
||||
PlatformLogger.getLogger("java.util.jar").warning(
|
||||
"Duplicate name in Manifest: " + name
|
||||
+ ".\n"
|
||||
+ "Ensure that the manifest does not "
|
||||
|
@ -283,6 +283,10 @@ public class LogManager {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
public Object run() throws Exception {
|
||||
readConfiguration();
|
||||
|
||||
// Platform loggers begin to delegate to java.util.logging.Logger
|
||||
sun.util.logging.PlatformLogger.redirectPlatformLoggers();
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
@ -530,6 +530,7 @@ public class LogRecord implements java.io.Serializable {
|
||||
int depth = access.getStackTraceDepth(throwable);
|
||||
|
||||
String logClassName = "java.util.logging.Logger";
|
||||
String plogClassName = "sun.util.logging.PlatformLogger";
|
||||
boolean lookingForLogger = true;
|
||||
for (int ix = 0; ix < depth; ix++) {
|
||||
// Calling getStackTraceElement directly prevents the VM
|
||||
@ -539,15 +540,18 @@ public class LogRecord implements java.io.Serializable {
|
||||
String cname = frame.getClassName();
|
||||
if (lookingForLogger) {
|
||||
// Skip all frames until we have found the first logger frame.
|
||||
if (cname.equals(logClassName)) {
|
||||
if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
|
||||
lookingForLogger = false;
|
||||
}
|
||||
} else {
|
||||
if (!cname.equals(logClassName)) {
|
||||
// We've found the relevant frame.
|
||||
setSourceClassName(cname);
|
||||
setSourceMethodName(frame.getMethodName());
|
||||
return;
|
||||
if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
|
||||
// skip reflection call
|
||||
if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
|
||||
// We've found the relevant frame.
|
||||
setSourceClassName(cname);
|
||||
setSourceMethodName(frame.getMethodName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ import java.util.ServiceLoader;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
|
||||
@ -122,10 +122,15 @@ public final class LocaleServiceProviderPool {
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
Logger.getLogger("sun.util.LocaleServiceProviderPool").config(e.toString());
|
||||
config(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void config(String message) {
|
||||
PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool");
|
||||
logger.config(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy loaded set of available locales.
|
||||
* Loading all locales is a very long operation.
|
||||
@ -337,7 +342,7 @@ public final class LocaleServiceProviderPool {
|
||||
if (providersObj != null) {
|
||||
return providersObj;
|
||||
} else if (isObjectProvider) {
|
||||
Logger.getLogger("sun.util.LocaleServiceProviderPool").config(
|
||||
config(
|
||||
"A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + requested);
|
||||
}
|
||||
}
|
||||
|
629
jdk/src/share/classes/sun/util/logging/PlatformLogger.java
Normal file
629
jdk/src/share/classes/sun/util/logging/PlatformLogger.java
Normal file
@ -0,0 +1,629 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
|
||||
package sun.util.logging;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.*;
|
||||
import sun.misc.JavaLangAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* Platform logger provides an API for the JRE components to log
|
||||
* messages. This enables the runtime components to eliminate the
|
||||
* static dependency of the logging facility and also defers the
|
||||
* java.util.logging initialization until it is enabled.
|
||||
* In addition, the PlatformLogger API can be used if the logging
|
||||
* module does not exist.
|
||||
*
|
||||
* If the logging facility is not enabled, the platform loggers
|
||||
* will output log messages per the default logging configuration
|
||||
* (see below). In this implementation, it does not log the
|
||||
* the stack frame information issuing the log message.
|
||||
*
|
||||
* When the logging facility is enabled (at startup or runtime),
|
||||
* the java.util.logging.Logger will be created for each platform
|
||||
* logger and all log messages will be forwarded to the Logger
|
||||
* to handle.
|
||||
*
|
||||
* Logging facility is "enabled" when one of the following
|
||||
* conditions is met:
|
||||
* 1) a system property "java.util.logging.config.class" or
|
||||
* "java.util.logging.config.file" is set
|
||||
* 2) java.util.logging.LogManager or java.util.logging.Logger
|
||||
* is referenced that will trigger the logging initialization.
|
||||
*
|
||||
* Default logging configuration:
|
||||
* global logging level = INFO
|
||||
* handlers = java.util.logging.ConsoleHandler
|
||||
* java.util.logging.ConsoleHandler.level = INFO
|
||||
* java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
|
||||
*
|
||||
* Limitation:
|
||||
* <JAVA_HOME>/lib/logging.properties is the system-wide logging
|
||||
* configuration defined in the specification and read in the
|
||||
* default case to configure any java.util.logging.Logger instances.
|
||||
* Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
|
||||
* is modified. In other words, unless the java.util.logging API
|
||||
* is used at runtime or the logging system properties is set,
|
||||
* the platform loggers will use the default setting described above.
|
||||
* The platform loggers are designed for JDK developers use and
|
||||
* this limitation can be workaround with setting
|
||||
* -Djava.util.logging.config.file system property.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public class PlatformLogger {
|
||||
// Same values as java.util.logging.Level for easy mapping
|
||||
public static final int OFF = Integer.MAX_VALUE;
|
||||
public static final int SEVERE = 1000;
|
||||
public static final int WARNING = 900;
|
||||
public static final int INFO = 800;
|
||||
public static final int CONFIG = 700;
|
||||
public static final int FINE = 500;
|
||||
public static final int FINER = 400;
|
||||
public static final int FINEST = 300;
|
||||
public static final int ALL = Integer.MIN_VALUE;
|
||||
|
||||
private static final int defaultLevel = INFO;
|
||||
private static boolean loggingEnabled;
|
||||
static {
|
||||
loggingEnabled = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
String cname = System.getProperty("java.util.logging.config.class");
|
||||
String fname = System.getProperty("java.util.logging.config.file");
|
||||
return (cname != null || fname != null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Table of known loggers. Maps names to PlatformLoggers.
|
||||
private static Map<String,WeakReference<PlatformLogger>> loggers =
|
||||
new HashMap<String,WeakReference<PlatformLogger>>();
|
||||
|
||||
/**
|
||||
* Returns a PlatformLogger of a given name.
|
||||
*/
|
||||
public static synchronized PlatformLogger getLogger(String name) {
|
||||
PlatformLogger log = null;
|
||||
WeakReference<PlatformLogger> ref = loggers.get(name);
|
||||
if (ref != null) {
|
||||
log = ref.get();
|
||||
}
|
||||
if (log == null) {
|
||||
log = new PlatformLogger(name);
|
||||
loggers.put(name, new WeakReference<PlatformLogger>(log));
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize java.util.logging.Logger objects for all platform loggers.
|
||||
* This method is called from LogManager.readPrimordialConfiguration().
|
||||
*/
|
||||
public static synchronized void redirectPlatformLoggers() {
|
||||
if (loggingEnabled || !JavaLogger.supported) return;
|
||||
|
||||
loggingEnabled = true;
|
||||
for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
|
||||
WeakReference<PlatformLogger> ref = entry.getValue();
|
||||
PlatformLogger plog = ref.get();
|
||||
if (plog != null) {
|
||||
plog.newJavaLogger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JavaLogger that the platform logger uses
|
||||
*/
|
||||
private void newJavaLogger() {
|
||||
logger = new JavaLogger(logger.name, logger.effectiveLevel);
|
||||
}
|
||||
|
||||
// logger may be replaced with a JavaLogger object
|
||||
// when the logging facility is enabled
|
||||
private volatile LoggerProxy logger;
|
||||
|
||||
private PlatformLogger(String name) {
|
||||
if (loggingEnabled) {
|
||||
this.logger = new JavaLogger(name);
|
||||
} else {
|
||||
this.logger = new LoggerProxy(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to test if the logger is turned off.
|
||||
* (i.e. its level is OFF).
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return logger.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name for this platform logger.
|
||||
*/
|
||||
public String getName() {
|
||||
return logger.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a message of the given level would actually
|
||||
* be logged by this logger.
|
||||
*/
|
||||
public boolean isLoggable(int level) {
|
||||
return logger.isLoggable(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current log level. Returns 0 if the current effective level
|
||||
* is not set (equivalent to Logger.getLevel() returns null).
|
||||
*/
|
||||
public int getLevel() {
|
||||
return logger.getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the log level.
|
||||
*/
|
||||
public void setLevel(int newLevel) {
|
||||
logger.setLevel(newLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a SEVERE message.
|
||||
*/
|
||||
public void severe(String msg) {
|
||||
logger.doLog(SEVERE, msg);
|
||||
}
|
||||
|
||||
public void severe(String msg, Throwable t) {
|
||||
logger.doLog(SEVERE, msg, t);
|
||||
}
|
||||
|
||||
public void severe(String msg, Object... params) {
|
||||
logger.doLog(SEVERE, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a WARNING message.
|
||||
*/
|
||||
public void warning(String msg) {
|
||||
logger.doLog(WARNING, msg);
|
||||
}
|
||||
|
||||
public void warning(String msg, Throwable t) {
|
||||
logger.doLog(WARNING, msg, t);
|
||||
}
|
||||
|
||||
public void warning(String msg, Object... params) {
|
||||
logger.doLog(WARNING, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an INFO message.
|
||||
*/
|
||||
public void info(String msg) {
|
||||
logger.doLog(INFO, msg);
|
||||
}
|
||||
|
||||
public void info(String msg, Throwable t) {
|
||||
logger.doLog(INFO, msg, t);
|
||||
}
|
||||
|
||||
public void info(String msg, Object... params) {
|
||||
logger.doLog(INFO, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a CONFIG message.
|
||||
*/
|
||||
public void config(String msg) {
|
||||
logger.doLog(CONFIG, msg);
|
||||
}
|
||||
|
||||
public void config(String msg, Throwable t) {
|
||||
logger.doLog(CONFIG, msg, t);
|
||||
}
|
||||
|
||||
public void config(String msg, Object... params) {
|
||||
logger.doLog(CONFIG, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINE message.
|
||||
*/
|
||||
public void fine(String msg) {
|
||||
logger.doLog(FINE, msg);
|
||||
}
|
||||
|
||||
public void fine(String msg, Throwable t) {
|
||||
logger.doLog(FINE, msg, t);
|
||||
}
|
||||
|
||||
public void fine(String msg, Object... params) {
|
||||
logger.doLog(FINE, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINER message.
|
||||
*/
|
||||
public void finer(String msg) {
|
||||
logger.doLog(FINER, msg);
|
||||
}
|
||||
|
||||
public void finer(String msg, Throwable t) {
|
||||
logger.doLog(FINER, msg, t);
|
||||
}
|
||||
|
||||
public void finer(String msg, Object... params) {
|
||||
logger.doLog(FINER, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a FINEST message.
|
||||
*/
|
||||
public void finest(String msg) {
|
||||
logger.doLog(FINEST, msg);
|
||||
}
|
||||
|
||||
public void finest(String msg, Throwable t) {
|
||||
logger.doLog(FINEST, msg, t);
|
||||
}
|
||||
|
||||
public void finest(String msg, Object... params) {
|
||||
logger.doLog(FINEST, msg, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default platform logging support - output messages to
|
||||
* System.err - equivalent to ConsoleHandler with SimpleFormatter.
|
||||
*/
|
||||
static class LoggerProxy {
|
||||
private static final PrintStream defaultStream = System.err;
|
||||
private static final String lineSeparator = AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return System.getProperty("line.separator");
|
||||
}
|
||||
});
|
||||
|
||||
final String name;
|
||||
volatile int levelValue;
|
||||
volatile int effectiveLevel = 0; // current effective level value
|
||||
|
||||
LoggerProxy(String name) {
|
||||
this(name, defaultLevel);
|
||||
}
|
||||
|
||||
LoggerProxy(String name, int level) {
|
||||
this.name = name;
|
||||
this.levelValue = level == 0 ? defaultLevel : level;
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
return levelValue != OFF;
|
||||
}
|
||||
|
||||
int getLevel() {
|
||||
return effectiveLevel;
|
||||
}
|
||||
|
||||
void setLevel(int newLevel) {
|
||||
levelValue = newLevel;
|
||||
effectiveLevel = newLevel;
|
||||
}
|
||||
|
||||
void doLog(int level, String msg) {
|
||||
if (level < levelValue || levelValue == OFF) {
|
||||
return;
|
||||
}
|
||||
defaultStream.println(format(level, msg, null));
|
||||
}
|
||||
|
||||
void doLog(int level, String msg, Throwable thrown) {
|
||||
if (level < levelValue || levelValue == OFF) {
|
||||
return;
|
||||
}
|
||||
defaultStream.println(format(level, msg, thrown));
|
||||
}
|
||||
|
||||
void doLog(int level, String msg, Object... params) {
|
||||
if (level < levelValue || levelValue == OFF) {
|
||||
return;
|
||||
}
|
||||
String newMsg = formatMessage(msg, params);
|
||||
defaultStream.println(format(level, newMsg, null));
|
||||
}
|
||||
|
||||
public boolean isLoggable(int level) {
|
||||
if (level < levelValue || levelValue == OFF) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String format = "{0,date} {0,time}";
|
||||
|
||||
private Object args[] = new Object[1];
|
||||
private MessageFormat formatter;
|
||||
private Date dat;
|
||||
|
||||
// Copied from java.util.logging.Formatter.formatMessage
|
||||
private String formatMessage(String format, Object... parameters) {
|
||||
// Do the formatting.
|
||||
try {
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
// No parameters. Just return format string.
|
||||
return format;
|
||||
}
|
||||
// Is it a java.text style format?
|
||||
// Ideally we could match with
|
||||
// Pattern.compile("\\{\\d").matcher(format).find())
|
||||
// However the cost is 14% higher, so we cheaply check for
|
||||
// 1 of the first 4 parameters
|
||||
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
|
||||
format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
|
||||
return java.text.MessageFormat.format(format, parameters);
|
||||
}
|
||||
return format;
|
||||
} catch (Exception ex) {
|
||||
// Formatting failed: use format string.
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized String format(int level, String msg, Throwable thrown) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
// Minimize memory allocations here.
|
||||
if (dat == null) {
|
||||
dat = new Date();
|
||||
formatter = new MessageFormat(format);
|
||||
}
|
||||
dat.setTime(System.currentTimeMillis());
|
||||
args[0] = dat;
|
||||
StringBuffer text = new StringBuffer();
|
||||
formatter.format(args, text, null);
|
||||
sb.append(text);
|
||||
sb.append(" ");
|
||||
sb.append(getCallerInfo());
|
||||
sb.append(lineSeparator);
|
||||
sb.append(PlatformLogger.getLevelName(level));
|
||||
sb.append(": ");
|
||||
sb.append(msg);
|
||||
if (thrown != null) {
|
||||
try {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
thrown.printStackTrace(pw);
|
||||
pw.close();
|
||||
sb.append(sw.toString());
|
||||
} catch (Exception ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// Returns the caller's class and method's name; best effort
|
||||
// if cannot infer, return the logger's name.
|
||||
private String getCallerInfo() {
|
||||
String sourceClassName = null;
|
||||
String sourceMethodName = null;
|
||||
|
||||
JavaLangAccess access = SharedSecrets.getJavaLangAccess();
|
||||
Throwable throwable = new Throwable();
|
||||
int depth = access.getStackTraceDepth(throwable);
|
||||
|
||||
String logClassName = "sun.util.logging.PlatformLogger";
|
||||
boolean lookingForLogger = true;
|
||||
for (int ix = 0; ix < depth; ix++) {
|
||||
// Calling getStackTraceElement directly prevents the VM
|
||||
// from paying the cost of building the entire stack frame.
|
||||
StackTraceElement frame =
|
||||
access.getStackTraceElement(throwable, ix);
|
||||
String cname = frame.getClassName();
|
||||
if (lookingForLogger) {
|
||||
// Skip all frames until we have found the first logger frame.
|
||||
if (cname.equals(logClassName)) {
|
||||
lookingForLogger = false;
|
||||
}
|
||||
} else {
|
||||
if (!cname.equals(logClassName)) {
|
||||
// We've found the relevant frame.
|
||||
sourceClassName = cname;
|
||||
sourceMethodName = frame.getMethodName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceClassName != null) {
|
||||
return sourceClassName + " " + sourceMethodName;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JavaLogger forwards all the calls to its corresponding
|
||||
* java.util.logging.Logger object.
|
||||
*/
|
||||
static class JavaLogger extends LoggerProxy {
|
||||
private static final boolean supported;
|
||||
private static final Class<?> loggerClass;
|
||||
private static final Class<?> levelClass;
|
||||
private static final Method getLoggerMethod;
|
||||
private static final Method setLevelMethod;
|
||||
private static final Method getLevelMethod;
|
||||
private static final Method logMethod;
|
||||
private static final Method logThrowMethod;
|
||||
private static final Method logParamsMethod;
|
||||
private static final Map<Integer, Object> levelObjects =
|
||||
new HashMap<Integer, Object>();
|
||||
|
||||
static {
|
||||
loggerClass = getClass("java.util.logging.Logger");
|
||||
levelClass = getClass("java.util.logging.Level");
|
||||
getLoggerMethod = getMethod(loggerClass, "getLogger", String.class);
|
||||
setLevelMethod = getMethod(loggerClass, "setLevel", levelClass);
|
||||
getLevelMethod = getMethod(loggerClass, "getLevel");
|
||||
logMethod = getMethod(loggerClass, "log", levelClass, String.class);
|
||||
logThrowMethod = getMethod(loggerClass, "log", levelClass, String.class, Throwable.class);
|
||||
logParamsMethod = getMethod(loggerClass, "log", levelClass, String.class, Object[].class);
|
||||
supported = (loggerClass != null && levelClass != null && getLoggerMethod != null &&
|
||||
getLevelMethod != null && setLevelMethod != null &&
|
||||
logMethod != null && logThrowMethod != null && logParamsMethod != null);
|
||||
if (supported) {
|
||||
// initialize the map to Level objects
|
||||
getLevelObjects();
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getClass(String name) {
|
||||
try {
|
||||
return Class.forName(name, true, null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
|
||||
if (cls == null) return null;
|
||||
|
||||
try {
|
||||
return cls.getMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object invoke(Method m, Object obj, Object... params) {
|
||||
try {
|
||||
return m.invoke(obj, params);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void getLevelObjects() {
|
||||
// get all java.util.logging.Level objects
|
||||
Method parseLevelMethod = getMethod(levelClass, "parse", String.class);
|
||||
int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
|
||||
for (int l : levelArray) {
|
||||
Object o = invoke(parseLevelMethod, null, getLevelName(l));
|
||||
levelObjects.put(l, o);
|
||||
}
|
||||
}
|
||||
|
||||
private final Object javaLogger;
|
||||
JavaLogger(String name) {
|
||||
this(name, 0);
|
||||
}
|
||||
|
||||
JavaLogger(String name, int level) {
|
||||
super(name, level);
|
||||
this.javaLogger = invoke(getLoggerMethod, null, name);
|
||||
if (level != 0) {
|
||||
// level has been updated and so set the Logger's level
|
||||
invoke(setLevelMethod, javaLogger, levelObjects.get(level));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Let Logger.log() do the filtering since if the level of a
|
||||
* platform logger is altered directly from
|
||||
* java.util.logging.Logger.setLevel(), the levelValue will
|
||||
* not be updated.
|
||||
*/
|
||||
void doLog(int level, String msg) {
|
||||
invoke(logMethod, javaLogger, levelObjects.get(level), msg);
|
||||
}
|
||||
|
||||
void doLog(int level, String msg, Throwable t) {
|
||||
invoke(logThrowMethod, javaLogger, levelObjects.get(level), msg, t);
|
||||
}
|
||||
|
||||
void doLog(int level, String msg, Object... params) {
|
||||
invoke(logParamsMethod, javaLogger, levelObjects.get(level), msg, params);
|
||||
}
|
||||
|
||||
boolean isEnabled() {
|
||||
Object level = invoke(getLevelMethod, javaLogger);
|
||||
return level == null || level.equals(levelObjects.get(OFF)) == false;
|
||||
}
|
||||
|
||||
int getLevel() {
|
||||
Object level = invoke(getLevelMethod, javaLogger);
|
||||
if (level != null) {
|
||||
for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) {
|
||||
if (level == l.getValue()) {
|
||||
return l.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setLevel(int newLevel) {
|
||||
levelValue = newLevel;
|
||||
invoke(setLevelMethod, javaLogger, levelObjects.get(newLevel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String getLevelName(int level) {
|
||||
switch (level) {
|
||||
case OFF : return "OFF";
|
||||
case SEVERE : return "SEVERE";
|
||||
case WARNING : return "WARNING";
|
||||
case INFO : return "INFO";
|
||||
case CONFIG : return "CONFIG";
|
||||
case FINE : return "FINE";
|
||||
case FINER : return "FINER";
|
||||
case FINEST : return "FINEST";
|
||||
case ALL : return "ALL";
|
||||
default : return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,7 @@ import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.StringTokenizer;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.logging.Logger;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
/**
|
||||
* Windows registry based implementation of <tt>Preferences</tt>.
|
||||
@ -48,7 +48,7 @@ class WindowsPreferences extends AbstractPreferences{
|
||||
/**
|
||||
* Logger for error messages
|
||||
*/
|
||||
private static Logger logger;
|
||||
private static PlatformLogger logger;
|
||||
|
||||
/**
|
||||
* Windows registry path to <tt>Preferences</tt>'s root nodes.
|
||||
@ -1102,9 +1102,9 @@ class WindowsPreferences extends AbstractPreferences{
|
||||
// assert false;
|
||||
}
|
||||
|
||||
private static synchronized Logger logger() {
|
||||
private static synchronized PlatformLogger logger() {
|
||||
if (logger == null) {
|
||||
logger = Logger.getLogger("java.util.prefs");
|
||||
logger = PlatformLogger.getLogger("java.util.prefs");
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
111
jdk/test/sun/util/logging/PlatformLoggerTest.java
Normal file
111
jdk/test/sun/util/logging/PlatformLoggerTest.java
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6882376
|
||||
* @summary Test if java.util.logging.Logger is created before and after
|
||||
* logging is enabled. Also validate some basic PlatformLogger
|
||||
* operations.
|
||||
*
|
||||
* @build PlatformLoggerTest
|
||||
* @run main PlatformLoggerTest
|
||||
*/
|
||||
|
||||
import java.util.logging.*;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
public class PlatformLoggerTest {
|
||||
private static final int defaultEffectiveLevel = 0;
|
||||
public static void main(String[] args) throws Exception {
|
||||
final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo";
|
||||
final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar";
|
||||
final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo";
|
||||
final String BAR_LOGGER = "test.logger.bar";
|
||||
PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
|
||||
|
||||
// Create a platform logger using the default
|
||||
PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
|
||||
checkPlatformLogger(foo, FOO_PLATFORM_LOGGER);
|
||||
|
||||
// create a java.util.logging.Logger
|
||||
// now java.util.logging.Logger should be created for each platform logger
|
||||
Logger logger = Logger.getLogger(BAR_LOGGER);
|
||||
logger.setLevel(Level.WARNING);
|
||||
|
||||
PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
|
||||
checkPlatformLogger(bar, BAR_PLATFORM_LOGGER);
|
||||
|
||||
checkLogger(FOO_PLATFORM_LOGGER, Level.FINER);
|
||||
checkLogger(BAR_PLATFORM_LOGGER, Level.FINER);
|
||||
|
||||
checkLogger(GOO_PLATFORM_LOGGER, null);
|
||||
checkLogger(BAR_LOGGER, Level.WARNING);
|
||||
|
||||
foo.setLevel(PlatformLogger.SEVERE);
|
||||
checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE);
|
||||
}
|
||||
|
||||
private static void checkPlatformLogger(PlatformLogger logger, String name) {
|
||||
if (!logger.getName().equals(name)) {
|
||||
throw new RuntimeException("Invalid logger's name " +
|
||||
logger.getName() + " but expected " + name);
|
||||
}
|
||||
|
||||
if (logger.getLevel() != defaultEffectiveLevel) {
|
||||
throw new RuntimeException("Invalid default level for logger " +
|
||||
logger.getName());
|
||||
}
|
||||
|
||||
if (logger.isLoggable(PlatformLogger.FINE) != false) {
|
||||
throw new RuntimeException("isLoggerable(FINE) returns true for logger " +
|
||||
logger.getName() + " but expected false");
|
||||
}
|
||||
|
||||
logger.setLevel(PlatformLogger.FINER);
|
||||
if (logger.getLevel() != Level.FINER.intValue()) {
|
||||
throw new RuntimeException("Invalid level for logger " +
|
||||
logger.getName() + " " + logger.getLevel());
|
||||
}
|
||||
|
||||
if (logger.isLoggable(PlatformLogger.FINE) != true) {
|
||||
throw new RuntimeException("isLoggerable(FINE) returns false for logger " +
|
||||
logger.getName() + " but expected true");
|
||||
}
|
||||
|
||||
logger.info("OK: Testing log message");
|
||||
}
|
||||
|
||||
private static void checkLogger(String name, Level level) {
|
||||
Logger logger = LogManager.getLogManager().getLogger(name);
|
||||
if (logger == null) {
|
||||
throw new RuntimeException("Logger " + name +
|
||||
" does not exist");
|
||||
}
|
||||
|
||||
if (logger.getLevel() != level) {
|
||||
throw new RuntimeException("Invalid level for logger " +
|
||||
logger.getName() + " " + logger.getLevel());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user