Mercurial > hg > openjdk > jdk8 > jdk
changeset 6052:37a4b4892e8e
7159567: inconsistent configuration of MemoryHandler
Reviewed-by: mchung, alanb
author | jgish |
---|---|
date | Thu, 25 Oct 2012 15:04:09 -0700 |
parents | 909676adaefd |
children | 27677928a937 |
files | src/share/classes/java/util/logging/ConsoleHandler.java src/share/classes/java/util/logging/FileHandler.java src/share/classes/java/util/logging/MemoryHandler.java src/share/classes/java/util/logging/SocketHandler.java src/share/classes/java/util/logging/StreamHandler.java test/java/util/logging/MemoryHandlerTest.java test/java/util/logging/MemoryHandlerTest.props |
diffstat | 7 files changed, 321 insertions(+), 83 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/logging/ConsoleHandler.java Wed Oct 24 21:20:40 2012 +0100 +++ b/src/share/classes/java/util/logging/ConsoleHandler.java Thu Oct 25 15:04:09 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, 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 @@ -35,26 +35,39 @@ * <p> * <b>Configuration:</b> * By default each <tt>ConsoleHandler</tt> is initialized using the following - * <tt>LogManager</tt> configuration properties. If properties are not defined + * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> + * refers to the fully-qualified class name of the handler. + * If properties are not defined * (or have invalid values) then the specified default values are used. * <ul> - * <li> java.util.logging.ConsoleHandler.level + * <li> <handler-name>.level * specifies the default level for the <tt>Handler</tt> - * (defaults to <tt>Level.INFO</tt>). - * <li> java.util.logging.ConsoleHandler.filter + * (defaults to <tt>Level.INFO</tt>). </li> + * <li> <handler-name>.filter * specifies the name of a <tt>Filter</tt> class to use - * (defaults to no <tt>Filter</tt>). - * <li> java.util.logging.ConsoleHandler.formatter + * (defaults to no <tt>Filter</tt>). </li> + * <li> <handler-name>.formatter * specifies the name of a <tt>Formatter</tt> class to use - * (defaults to <tt>java.util.logging.SimpleFormatter</tt>). - * <li> java.util.logging.ConsoleHandler.encoding + * (defaults to <tt>java.util.logging.SimpleFormatter</tt>). </li> + * <li> <handler-name>.encoding * the name of the character set encoding to use (defaults to - * the default platform encoding). + * the default platform encoding). </li> + * </ul> + * <p> + * For example, the properties for {@code ConsoleHandler} would be: + * <ul> + * <li> java.util.logging.ConsoleHandler.level=INFO </li> + * <li> java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> + * <p> + * For a custom handler, e.g. com.foo.MyHandler, the properties would be: + * <ul> + * <li> com.foo.MyHandler.level=INFO </li> + * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> * </ul> * <p> * @since 1.4 */ - public class ConsoleHandler extends StreamHandler { // Private method to configure a ConsoleHandler from LogManager // properties and/or default values as specified in the class
--- a/src/share/classes/java/util/logging/FileHandler.java Wed Oct 24 21:20:40 2012 +0100 +++ b/src/share/classes/java/util/logging/FileHandler.java Thu Oct 25 15:04:09 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -48,45 +48,58 @@ * <p> * <b>Configuration:</b> * By default each <tt>FileHandler</tt> is initialized using the following - * <tt>LogManager</tt> configuration properties. If properties are not defined + * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> + * refers to the fully-qualified class name of the handler. + * If properties are not defined * (or have invalid values) then the specified default values are used. * <ul> - * <li> java.util.logging.FileHandler.level + * <li> <handler-name>.level * specifies the default level for the <tt>Handler</tt> - * (defaults to <tt>Level.ALL</tt>). - * <li> java.util.logging.FileHandler.filter + * (defaults to <tt>Level.ALL</tt>). </li> + * <li> <handler-name>.filter * specifies the name of a <tt>Filter</tt> class to use - * (defaults to no <tt>Filter</tt>). - * <li> java.util.logging.FileHandler.formatter + * (defaults to no <tt>Filter</tt>). </li> + * <li> <handler-name>.formatter * specifies the name of a <tt>Formatter</tt> class to use - * (defaults to <tt>java.util.logging.XMLFormatter</tt>) - * <li> java.util.logging.FileHandler.encoding + * (defaults to <tt>java.util.logging.XMLFormatter</tt>) </li> + * <li> <handler-name>.encoding * the name of the character set encoding to use (defaults to - * the default platform encoding). - * <li> java.util.logging.FileHandler.limit + * the default platform encoding). </li> + * <li> <handler-name>.limit * specifies an approximate maximum amount to write (in bytes) * to any one file. If this is zero, then there is no limit. - * (Defaults to no limit). - * <li> java.util.logging.FileHandler.count - * specifies how many output files to cycle through (defaults to 1). - * <li> java.util.logging.FileHandler.pattern + * (Defaults to no limit). </li> + * <li> <handler-name>.count + * specifies how many output files to cycle through (defaults to 1). </li> + * <li> <handler-name>.pattern * specifies a pattern for generating the output file name. See - * below for details. (Defaults to "%h/java%u.log"). - * <li> java.util.logging.FileHandler.append + * below for details. (Defaults to "%h/java%u.log"). </li> + * <li> <handler-name>.append * specifies whether the FileHandler should append onto - * any existing files (defaults to false). + * any existing files (defaults to false). </li> * </ul> * <p> + * For example, the properties for {@code FileHandler} would be: + * <ul> + * <li> java.util.logging.FileHandler.level=INFO </li> + * <li> java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> + * <p> + * For a custom handler, e.g. com.foo.MyHandler, the properties would be: + * <ul> + * <li> com.foo.MyHandler.level=INFO </li> + * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> * <p> * A pattern consists of a string that includes the following special * components that will be replaced at runtime: * <ul> - * <li> "/" the local pathname separator - * <li> "%t" the system temporary directory - * <li> "%h" the value of the "user.home" system property - * <li> "%g" the generation number to distinguish rotated logs - * <li> "%u" a unique number to resolve conflicts - * <li> "%%" translates to a single percent sign "%" + * <li> "/" the local pathname separator </li> + * <li> "%t" the system temporary directory </li> + * <li> "%h" the value of the "user.home" system property </li> + * <li> "%g" the generation number to distinguish rotated logs </li> + * <li> "%u" a unique number to resolve conflicts </li> + * <li> "%%" translates to a single percent sign "%" </li> * </ul> * If no "%g" field has been specified and the file count is greater * than one, then the generation number will be added to the end of
--- a/src/share/classes/java/util/logging/MemoryHandler.java Wed Oct 24 21:20:40 2012 +0100 +++ b/src/share/classes/java/util/logging/MemoryHandler.java Thu Oct 25 15:04:09 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, 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 @@ -39,36 +39,50 @@ * <ul> * <li> * An incoming <tt>LogRecord</tt> has a type that is greater than - * a pre-defined level, the <tt>pushLevel</tt>. + * a pre-defined level, the <tt>pushLevel</tt>. </li> * <li> - * An external class calls the <tt>push</tt> method explicitly. + * An external class calls the <tt>push</tt> method explicitly. </li> * <li> * A subclass overrides the <tt>log</tt> method and scans each incoming * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some - * desired criteria. + * desired criteria. </li> * </ul> * <p> * <b>Configuration:</b> * By default each <tt>MemoryHandler</tt> is initialized using the following - * LogManager configuration properties. If properties are not defined + * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> + * refers to the fully-qualified class name of the handler. + * If properties are not defined * (or have invalid values) then the specified default values are used. * If no default value is defined then a RuntimeException is thrown. * <ul> - * <li> java.util.logging.MemoryHandler.level + * <li> <handler-name>.level * specifies the level for the <tt>Handler</tt> - * (defaults to <tt>Level.ALL</tt>). - * <li> java.util.logging.MemoryHandler.filter + * (defaults to <tt>Level.ALL</tt>). </li> + * <li> <handler-name>.filter * specifies the name of a <tt>Filter</tt> class to use - * (defaults to no <tt>Filter</tt>). - * <li> java.util.logging.MemoryHandler.size - * defines the buffer size (defaults to 1000). - * <li> java.util.logging.MemoryHandler.push - * defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>). - * <li> java.util.logging.MemoryHandler.target + * (defaults to no <tt>Filter</tt>). </li> + * <li> <handler-name>.size + * defines the buffer size (defaults to 1000). </li> + * <li> <handler-name>.push + * defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>). </li> + * <li> <handler-name>.target * specifies the name of the target <tt>Handler </tt> class. - * (no default). + * (no default). </li> + * </ul> + * <p> + * For example, the properties for {@code MemoryHandler} would be: + * <ul> + * <li> java.util.logging.MemoryHandler.level=INFO </li> + * <li> java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter </li> * </ul> - * + * <p> + * For a custom handler, e.g. com.foo.MyHandler, the properties would be: + * <ul> + * <li> com.foo.MyHandler.level=INFO </li> + * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> + * <p> * @since 1.4 */ @@ -80,7 +94,7 @@ private LogRecord buffer[]; int start, count; - // Private method to configure a ConsoleHandler from LogManager + // Private method to configure a MemoryHandler from LogManager // properties and/or default values as specified in the class // javadoc. private void configure() { @@ -106,14 +120,19 @@ configure(); sealed = true; - String name = "???"; + LogManager manager = LogManager.getLogManager(); + String handlerName = getClass().getName(); + String targetName = manager.getProperty(handlerName+".target"); + if (targetName == null) { + throw new RuntimeException("The handler " + handlerName + + " does not specify a target"); + } + Class<?> clz; try { - LogManager manager = LogManager.getLogManager(); - name = manager.getProperty("java.util.logging.MemoryHandler.target"); - Class clz = ClassLoader.getSystemClassLoader().loadClass(name); + clz = ClassLoader.getSystemClassLoader().loadClass(targetName); target = (Handler) clz.newInstance(); - } catch (Exception ex) { - throw new RuntimeException("MemoryHandler can't load handler \"" + name + "\"" , ex); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e); } init(); }
--- a/src/share/classes/java/util/logging/SocketHandler.java Wed Oct 24 21:20:40 2012 +0100 +++ b/src/share/classes/java/util/logging/SocketHandler.java Thu Oct 25 15:04:09 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2003, 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 @@ -37,25 +37,39 @@ * <p> * <b>Configuration:</b> * By default each <tt>SocketHandler</tt> is initialized using the following - * <tt>LogManager</tt> configuration properties. If properties are not defined + * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> + * refers to the fully-qualified class name of the handler. + * If properties are not defined * (or have invalid values) then the specified default values are used. * <ul> - * <li> java.util.logging.SocketHandler.level + * <li> <handler-name>.level * specifies the default level for the <tt>Handler</tt> - * (defaults to <tt>Level.ALL</tt>). - * <li> java.util.logging.SocketHandler.filter + * (defaults to <tt>Level.ALL</tt>). </li> + * <li> <handler-name>.filter * specifies the name of a <tt>Filter</tt> class to use - * (defaults to no <tt>Filter</tt>). - * <li> java.util.logging.SocketHandler.formatter + * (defaults to no <tt>Filter</tt>). </li> + * <li> <handler-name>.formatter * specifies the name of a <tt>Formatter</tt> class to use - * (defaults to <tt>java.util.logging.XMLFormatter</tt>). - * <li> java.util.logging.SocketHandler.encoding + * (defaults to <tt>java.util.logging.XMLFormatter</tt>). </li> + * <li> <handler-name>.encoding * the name of the character set encoding to use (defaults to - * the default platform encoding). - * <li> java.util.logging.SocketHandler.host - * specifies the target host name to connect to (no default). - * <li> java.util.logging.SocketHandler.port - * specifies the target TCP port to use (no default). + * the default platform encoding). </li> + * <li> <handler-name>.host + * specifies the target host name to connect to (no default). </li> + * <li> <handler-name>.port + * specifies the target TCP port to use (no default). </li> + * </ul> + * <p> + * For example, the properties for {@code SocketHandler} would be: + * <ul> + * <li> java.util.logging.SocketHandler.level=INFO </li> + * <li> java.util.logging.SocketHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> + * <p> + * For a custom handler, e.g. com.foo.MyHandler, the properties would be: + * <ul> + * <li> com.foo.MyHandler.level=INFO </li> + * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> * </ul> * <p> * The output IO stream is buffered, but is flushed after each
--- a/src/share/classes/java/util/logging/StreamHandler.java Wed Oct 24 21:20:40 2012 +0100 +++ b/src/share/classes/java/util/logging/StreamHandler.java Thu Oct 25 15:04:09 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, 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 @@ -38,23 +38,37 @@ * <p> * <b>Configuration:</b> * By default each <tt>StreamHandler</tt> is initialized using the following - * <tt>LogManager</tt> configuration properties. If properties are not defined + * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> + * refers to the fully-qualified class name of the handler. + * If properties are not defined * (or have invalid values) then the specified default values are used. * <ul> - * <li> java.util.logging.StreamHandler.level + * <li> <handler-name>.level * specifies the default level for the <tt>Handler</tt> - * (defaults to <tt>Level.INFO</tt>). - * <li> java.util.logging.StreamHandler.filter + * (defaults to <tt>Level.INFO</tt>). </li> + * <li> <handler-name>.filter * specifies the name of a <tt>Filter</tt> class to use - * (defaults to no <tt>Filter</tt>). - * <li> java.util.logging.StreamHandler.formatter + * (defaults to no <tt>Filter</tt>). </li> + * <li> <handler-name>.formatter * specifies the name of a <tt>Formatter</tt> class to use - * (defaults to <tt>java.util.logging.SimpleFormatter</tt>). - * <li> java.util.logging.StreamHandler.encoding + * (defaults to <tt>java.util.logging.SimpleFormatter</tt>). </li> + * <li> <handler-name>.encoding * the name of the character set encoding to use (defaults to - * the default platform encoding). + * the default platform encoding). </li> + * </ul> + * <p> + * For example, the properties for {@code StreamHandler} would be: + * <ul> + * <li> java.util.logging.StreamHandler.level=INFO </li> + * <li> java.util.logging.StreamHandler.formatter=java.util.logging.SimpleFormatter </li> * </ul> - * + * <p> + * For a custom handler, e.g. com.foo.MyHandler, the properties would be: + * <ul> + * <li> com.foo.MyHandler.level=INFO </li> + * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> + * </ul> + * <p> * @since 1.4 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/MemoryHandlerTest.java Thu Oct 25 15:04:09 2012 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 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 + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7159567 + * @summary Test of configuring a MemoryHandler sub-class handler target via logging.properties + * @run main/othervm MemoryHandlerTest + */ +import java.io.File; +import java.io.IOException; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.logging.MemoryHandler; + +public class MemoryHandlerTest { + + static final String CFG_FILE_PROP = "java.util.logging.config.file"; + static final String LM_PROP_FNAME = "MemoryHandlerTest.props"; + static Logger logger; + + public static void main(String... args) throws 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(); + // create a logger + logger = Logger.getLogger(MemoryHandlerTest.class.getName()); + // don't have parent handlers get log messages + logger.setUseParentHandlers(false); + // + // Test 1,2: create a CustomMemoryHandler which in the config has + // specified a target of CustomTargetHandler. (1) Make sure that it + // is created and (2) that the target handler is loaded. + // + CustomMemoryHandler cmh = new CustomMemoryHandler(); + try { + logger.addHandler(cmh); + } catch (RuntimeException rte) { + throw new RuntimeException( + "Test Failed: did not load java.util.logging.ConsoleHandler as expected", + rte); + } + // if we get here and our config has been processed properly, then we + // should have loaded our target handler + if (CustomTargetHandler.numLoaded !=1) { + throw new RuntimeException( + "Test failed: did not load CustomTargetHandler as expected"); + } + // + // Test 3: try to add a handler with no target. This should fail with + // an exception + CustomMemoryHandlerNoTarget cmhnt = null; + try { + cmhnt = new CustomMemoryHandlerNoTarget(); + } catch (RuntimeException re) { + // expected -- no target specified + System.out.println("Info: " + re.getMessage() + " as expected."); + } + if (cmhnt != null) { + throw new RuntimeException( + "Test Failed: erroneously loaded CustomMemoryHandlerNoTarget"); + } + + // Test 4: log a message and check that the target handler is actually used + logger.log(Level.WARNING, "Unused"); + if (CustomTargetHandler.numPublished != 1) { + throw new RuntimeException("Test failed: CustomTargetHandler was not used"); + } + + // Test 5: make sure that SimpleTargetHandler hasn't been erroneously called + if (SimpleTargetHandler.numPublished != 0) { + throw new RuntimeException("Test failed: SimpleTargetHandler has been used"); + } + + // Test 6: try using SimpleTargetHanlder via standard MemoryHandler + // (which has target set to SimpleTargetHandler) + MemoryHandler mh = new MemoryHandler(); + mh.publish(new LogRecord(Level.INFO, "Unused msg to MemoryHandler")); + // see if it made it to the SimpleTargetHandler + if (SimpleTargetHandler.numPublished != 1) { + throw new RuntimeException("Test failed: SimpleTargetHandler was not used"); + } + } + + public static class CustomMemoryHandler extends MemoryHandler { + } + + public static class CustomMemoryHandlerNoTarget extends MemoryHandler { + } + + public static class CustomTargetHandler extends Handler { + + public static int numPublished; + public static int numLoaded; + + public CustomTargetHandler() { + numLoaded++; + } + + @Override + public void publish(LogRecord unused) { + numPublished++; + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + } + + public static class SimpleTargetHandler extends Handler { + public static int numPublished; + + @Override + public void publish(LogRecord unused) { + numPublished++; + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/MemoryHandlerTest.props Thu Oct 25 15:04:09 2012 -0700 @@ -0,0 +1,9 @@ +.level= INFO +MemoryHandlerTest$CustomMemoryHandler.push=WARNING +MemoryHandlerTest$CustomMemoryHandlerNoTarget.push=WARNING +MemoryHandlerTest$CustomMemoryHandler.target=MemoryHandlerTest$CustomTargetHandler +handlers=java.util.logging.ConsoleHandler,MemoryHandlerTest$CustomMemoryHandler,MemoryHandlerTest$CustomMemoryHandlerNoTarget +java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter +java.util.logging.ConsoleHandler.level = INFO +java.util.logging.MemoryHandler.target=MemoryHandlerTest$SimpleTargetHandler +java.util.logging.MemoryHandler.push = INFO