--- old/src/share/classes/java/util/logging/Logger.java 2012-10-30 16:26:53.848484578 -0400 +++ new/src/share/classes/java/util/logging/Logger.java 2012-10-30 16:26:53.712487323 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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 @@ -26,10 +26,13 @@ package java.util.logging; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; -import java.security.*; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.concurrent.CopyOnWriteArrayList; /** * A Logger object is used to log messages for a specific @@ -117,25 +120,25 @@ *
* There are a set of "log" methods that take a log level, a message - * string, and optionally some parameters to the message string. + * string, and optionally some parameters to the message string.
* There are a set of "logp" methods (for "log precise") that are * like the "log" methods, but also take an explicit source class name - * and method name. + * and method name.
* There are a set of "logrb" method (for "log with resource bundle") * that are like the "logp" method, but also take an explicit resource - * bundle name for use in localizing the log message. + * bundle name for use in localizing the log message.
* There are convenience methods for tracing method entries (the * "entering" methods), method returns (the "exiting" methods) and - * throwing exceptions (the "throwing" methods). + * throwing exceptions (the "throwing" methods).
* Finally, there are a set of convenience methods for use in the * very simplest cases, when a developer simply wants to log a * simple string at a given log level. These methods are named * after the standard Level names ("severe", "warning", "info", etc.) - * and take a single argument, a message string. + * and take a single argument, a message string.
* For the methods that do not take an explicit source name and @@ -632,6 +635,36 @@ doLog(lr); } + /** + * Log a message with parameters, and associated Throwable information. + *
+ * If the logger is currently enabled for the given message + * level then the given arguments are stored in a LogRecord + * which is forwarded to all registered output handlers. + *
+ * Note that the thrown argument is stored in the LogRecord thrown + * property, rather than the LogRecord parameters property. Thus is it + * processed specially by output Formatters and is not treated + * as a formatting parameter to the LogRecord message property. + *
+ * @param level One of the message level identifiers, e.g., SEVERE + * @param thrown Throwable associated with log message. + * @param msg The string message (or a key in the message catalog) + * @param params Array of parameters to the message + * + * @since 1.8 + * + */ + public void log(Level level, Throwable thrown, String msg, Object... params) { + if (level.intValue() < levelValue || levelValue == offValue) { + return; + } + LogRecord lr = new LogRecord(level, msg); + lr.setParameters(params); + lr.setThrown(thrown); + doLog(lr); + } + //================================================================ // Start of convenience methods WITH className and methodName //================================================================ @@ -743,6 +776,41 @@ doLog(lr); } + /** + * Log a message with parameters, source class and method, + * and associated Throwable information. + *
+ * If the logger is currently enabled for the given message + * level then the given arguments are stored in a LogRecord + * which is forwarded to all registered output handlers. + *
+ * Note that the thrown argument is stored in the LogRecord thrown + * property, rather than the LogRecord parameters property. Thus is it + * processed specially by output Formatters and is not treated + * as a formatting parameter to the LogRecord message property. + *
+ * @param level One of the message level identifiers, e.g., SEVERE + * @param sourceClass name of class that issued the logging request + * @param sourceMethod name of method that issued the logging request + * @param msg The string message (or a key in the message catalog) + * @param thrown Throwable associated with log message. + * @param params Array of parameters to the message + * + * @since 1.8 + * + */ + public void logp(Level level, String sourceClass, String sourceMethod, + Throwable thrown, String msg, Object... params) { + if (level.intValue() < levelValue || levelValue == offValue) { + return; + } + LogRecord lr = new LogRecord(level, msg); + lr.setSourceClassName(sourceClass); + lr.setSourceMethodName(sourceMethod); + lr.setParameters(params); + lr.setThrown(thrown); + doLog(lr); + } //========================================================================= // Start of convenience methods WITH className, methodName and bundle name. @@ -893,6 +961,47 @@ doLog(lr, bundleName); } + /** + * Log a message with parameters, source class, method, and + * resource bundle name, with associated Throwable information. + *
+ * If the logger is currently enabled for the given message + * level then the given arguments are stored in a LogRecord + * which is forwarded to all registered output handlers. + *
+ * The msg string is localized using the named resource bundle. If the + * resource bundle name is null, or an empty String or invalid + * then the msg string is not localized. + *
+ * Note that the thrown argument is stored in the LogRecord thrown + * property, rather than the LogRecord parameters property. Thus is it + * processed specially by output Formatters and is not treated + * as a formatting parameter to the LogRecord message property. + *
+ * @param level One of the message level identifiers, e.g., SEVERE + * @param sourceClass name of class that issued the logging request + * @param sourceMethod name of method that issued the logging request + * @param bundleName name of resource bundle to localize msg, + * can be null + * @param thrown Throwable associated with log message. + * @param msg The string message (or a key in the message catalog) + * @param params Array of parameters to the message + * + * @since 1.8 + * + */ + public void logrb(Level level, String sourceClass, String sourceMethod, + String bundleName, Throwable thrown, String msg, Object... params) { + if (level.intValue() < levelValue || levelValue == offValue) { + return; + } + LogRecord lr = new LogRecord(level, msg); + lr.setSourceClassName(sourceClass); + lr.setSourceMethodName(sourceMethod); + lr.setParameters(params); + lr.setThrown(thrown); + doLog(lr, bundleName); + } //====================================================================== // Start of convenience methods for logging method entries and returns. --- /dev/null 2012-10-30 09:53:59.269725701 -0400 +++ new/test/java/util/logging/LogThrowablesTest.java 2012-10-30 16:26:54.296475537 -0400 @@ -0,0 +1,117 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +/** + * + * @test + * @bug 6594697 + * @summary Test of logging methods that have Throwable and message parameters + * @run main/othervm LogThrowablesTest + */ + +/** + * @author jgish + * @since 1.8 + * + */ +public class LogThrowablesTest { + private static Logger logger; + static final String CFG_FILE_PROP = "java.util.logging.config.file"; + static final String LM_PROP_FNAME = "LogThrowablesTest.props"; + + + public static void main(String[] args) throws SecurityException, IOException { + // load logging.propertes for the test + String tstSrc = System.getProperty("test.src", "."); + File fname = new File(tstSrc, LM_PROP_FNAME); + String prop = fname.getCanonicalPath(); + System.setProperty(CFG_FILE_PROP, prop); + LogManager logMgr = LogManager.getLogManager(); + String loggerName = LogThrowablesTest.class.getName(); + logger = Logger.getLogger(loggerName); + testLogrb(); + testLogp(); + testLog(); + // now check to make sure the right stuff was logged + // first, make sure that all the loggers/handlers are closed. + logMgr.reset(); + // open the log file for reading + try (BufferedReader br = new BufferedReader( + new FileReader("LogThrowablesTest.log"))) + { + // The log file should look like this (except for + // different stack trace depending on whether run directly or + // from jtreg, etc. and different line numbers depending on + // code changes + /* + testLogrb p1 + java.lang.Throwable: testLogrb + at LogThrowablesTest.testLogrb(LogThrowablesTest.java:42) + at LogThrowablesTest.main(LogThrowablesTest.java:35) + testLogp q1 q2 + java.lang.Throwable: testLogp + at LogThrowablesTest.testLogp(LogThrowablesTest.java:46) + at LogThrowablesTest.main(LogThrowablesTest.java:36) + testLog r1 r2 r3 + java.lang.Throwable: testLog + at LogThrowablesTest.testLog(LogThrowablesTest.java:50) + at LogThrowablesTest.main(LogThrowablesTest.java:37) + */ + String msg = br.readLine(); + String throwable = br.readLine(); + if (!(msg.equals("start:testLogrb p1") && + throwable.equals("java.lang.Throwable: testLogrb"))) { + throw new RuntimeException( + "Test failed: logrb() did not create correct log records."+ + " message was '" + msg + "' and Throwable was '" + throwable + "'"); + } + + msg = skipPastStackTrace(br); + throwable = br.readLine(); + if (!(msg.equals("start:testLogp q1 q2") && + throwable.equals("java.lang.Throwable: testLogp"))) { + throw new RuntimeException( + "Test failed: logp() did not create correct log records."+ + " message was '" + msg + "' and Throwable was '" + throwable + "'"); + } + + msg = skipPastStackTrace(br); + throwable = br.readLine(); + if (!(msg.equals("start:testLog r1 r2 r3") && + throwable.equals("java.lang.Throwable: testLog"))) { + throw new RuntimeException( + "Test failed: log() did not create correct log records."+ + " message was '" + msg + "' and Throwable was '" + throwable + "'"); + } + } + } + + private static String skipPastStackTrace(BufferedReader br) throws IOException { + String line; + do { + line = br.readLine(); + } while (!line.startsWith("start:")); + return line; + } + + private static void testLogrb() { + logger.log(Level.INFO, new Throwable("testLogrb"), "start:testLogrb {0}", "p1"); + } + + private static void testLogp() { + logger.logp(Level.INFO, LogThrowablesTest.class.getName(), "testLogp", + new Throwable("testLogp"), "start:testLogp {0} {1}", "q1", "q2"); + } + + private static void testLog() { + logger.logrb(Level.INFO, LogThrowablesTest.class.getName(), "testLog", + "bundleName", new Throwable("testLog"), "start:testLog {0} {1} {2}", + "r1", "r2", "r3"); + + } +}