| /* | |
| * Copyright (c) 2013, 2024, 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 8029781 8030801 | |
| * @summary Test which verifies that various JDK logging Handlers are | |
| * configured correctly from defaults and/or LogManager properties | |
| * as specified in javadoc and that no special | |
| * logging permission is required for instantiating them. | |
| * @modules java.logging/java.util.logging:open | |
| * @run main/othervm HandlersConfigTest default | |
| * @run main/othervm HandlersConfigTest configured | |
| */ | |
| import java.io.IOException; | |
| import java.io.OutputStream; | |
| import java.lang.reflect.Field; | |
| import java.net.ServerSocket; | |
| import java.net.URL; | |
| import java.util.Objects; | |
| import java.util.logging.ConsoleHandler; | |
| import java.util.logging.Filter; | |
| import java.util.logging.Formatter; | |
| import java.util.logging.Handler; | |
| import java.util.logging.Level; | |
| import java.util.logging.LogManager; | |
| import java.util.logging.LogRecord; | |
| import java.util.logging.MemoryHandler; | |
| import java.util.logging.SimpleFormatter; | |
| import java.util.logging.SocketHandler; | |
| import java.util.logging.StreamHandler; | |
| import java.util.logging.XMLFormatter; | |
| public abstract class HandlersConfigTest implements Runnable { | |
| public static void main(String[] args) { | |
| switch (args.length == 1 ? args[0] : "usage") { | |
| case "default": | |
| new Default().run(); | |
| break; | |
| case "configured": | |
| new Configured().run(); | |
| break; | |
| default: | |
| System.err.println("Usage: HandlersConfigTest [default|configured]"); | |
| break; | |
| } | |
| } | |
| static final String CONFIG_FILE_PROPERTY = "java.util.logging.config.file"; | |
| final Field memoryHandlerTarget, memoryHandlerSize, streamHandlerOutput; | |
| final ServerSocket serverSocket; | |
| HandlersConfigTest() { | |
| // establish access to private fields | |
| try { | |
| memoryHandlerTarget = MemoryHandler.class.getDeclaredField("target"); | |
| memoryHandlerTarget.setAccessible(true); | |
| memoryHandlerSize = MemoryHandler.class.getDeclaredField("size"); | |
| memoryHandlerSize.setAccessible(true); | |
| streamHandlerOutput = StreamHandler.class.getDeclaredField("output"); | |
| streamHandlerOutput.setAccessible(true); | |
| } catch (NoSuchFieldException e) { | |
| throw new AssertionError(e); | |
| } | |
| // load logging.propertes for the test | |
| String rname = getClass().getName().replace('.', '/') + ".props"; | |
| URL url = getClass().getClassLoader().getResource(rname); | |
| if (url == null || !"file".equals(url.getProtocol())) { | |
| throw new IllegalStateException("Resource: " + rname + " not found or not on file: " + url); | |
| } | |
| System.setProperty(CONFIG_FILE_PROPERTY, url.getFile()); | |
| // create ServerSocket as a target for SocketHandler | |
| try { | |
| serverSocket = new ServerSocket(0); // auto allocated port | |
| } catch (IOException e) { | |
| throw new AssertionError(e); | |
| } | |
| // initialize logging system | |
| LogManager.getLogManager(); | |
| } | |
| // check that defaults are used as specified by javadoc | |
| public static class Default extends HandlersConfigTest { | |
| public static void main(String[] args) { | |
| new Default().run(); | |
| } | |
| @Override | |
| public void run() { | |
| // MemoryHandler | |
| check(new MemoryHandler(), | |
| Level.ALL, null, null, SimpleFormatter.class, | |
| ConfiguredHandler.class, 1000, Level.SEVERE); | |
| check(new MemoryHandler(new SpecifiedHandler(), 100, Level.WARNING), | |
| Level.ALL, null, null, SimpleFormatter.class, | |
| SpecifiedHandler.class, 100, Level.WARNING); | |
| // StreamHandler | |
| check(new StreamHandler(), | |
| Level.INFO, null, null, SimpleFormatter.class, | |
| null); | |
| check(new StreamHandler(System.out, new SpecifiedFormatter()), | |
| Level.INFO, null, null, SpecifiedFormatter.class, | |
| System.out); | |
| // ConsoleHandler | |
| check(new ConsoleHandler(), | |
| Level.INFO, null, null, SimpleFormatter.class, | |
| System.err); | |
| // SocketHandler (use the ServerSocket's port) | |
| try { | |
| check(new SocketHandler("localhost", serverSocket.getLocalPort()), | |
| Level.ALL, null, null, XMLFormatter.class); | |
| } catch (IOException e) { | |
| throw new RuntimeException("Can't connect to localhost:" + serverSocket.getLocalPort(), e); | |
| } | |
| } | |
| } | |
| // check that LogManager properties configuration is respected | |
| public static class Configured extends HandlersConfigTest { | |
| public static void main(String[] args) { | |
| new Configured().run(); | |
| } | |
| @Override | |
| public void run() { | |
| // MemoryHandler | |
| check(new MemoryHandler(), | |
| Level.FINE, null, ConfiguredFilter.class, ConfiguredFormatter.class, | |
| ConfiguredHandler.class, 123, Level.FINE); | |
| check(new MemoryHandler(new SpecifiedHandler(), 100, Level.WARNING), | |
| Level.FINE, null, ConfiguredFilter.class, ConfiguredFormatter.class, | |
| SpecifiedHandler.class, 100, Level.WARNING); | |
| // StreamHandler | |
| check(new StreamHandler(), | |
| Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class, | |
| null); | |
| check(new StreamHandler(System.out, new SpecifiedFormatter()), | |
| Level.FINE, "ASCII", ConfiguredFilter.class, SpecifiedFormatter.class, | |
| System.out); | |
| // ConsoleHandler | |
| check(new ConsoleHandler(), | |
| Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class, | |
| System.err); | |
| // SocketHandler (use the ServerSocket's port) | |
| try { | |
| check(new SocketHandler("localhost", serverSocket.getLocalPort()), | |
| Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class); | |
| } catch (Exception e) { | |
| throw new RuntimeException("Can't connect to localhost:" + serverSocket.getLocalPort(), e); | |
| } | |
| } | |
| } | |
| // test infrastructure | |
| void check(Handler handler, | |
| Level expectedLevel, | |
| String expectedEncoding, | |
| Class<? extends Filter> expectedFilterType, | |
| Class<? extends Formatter> expectedFormatterType) { | |
| checkEquals(handler, "level", handler.getLevel(), expectedLevel); | |
| checkEquals(handler, "encoding", handler.getEncoding(), expectedEncoding); | |
| checkType(handler, "filter", handler.getFilter(), expectedFilterType); | |
| checkType(handler, "formatter", handler.getFormatter(), expectedFormatterType); | |
| } | |
| void check(MemoryHandler handler, | |
| Level expectedLevel, | |
| String expectedEncoding, | |
| Class<? extends Filter> expectedFilterType, | |
| Class<? extends Formatter> expectedFormatterType, | |
| Class<? extends Handler> expextedTargetType, | |
| int expextedSize, | |
| Level expectedPushLevel) { | |
| checkType(handler, "target", getTarget(handler), expextedTargetType); | |
| checkEquals(handler, "size", getSize(handler), expextedSize); | |
| checkEquals(handler, "pushLevel", handler.getPushLevel(), expectedPushLevel); | |
| check(handler, expectedLevel, expectedEncoding, expectedFilterType, expectedFormatterType); | |
| } | |
| void check(StreamHandler handler, | |
| Level expectedLevel, | |
| String expectedEncoding, | |
| Class<? extends Filter> expectedFilterType, | |
| Class<? extends Formatter> expectedFormatterType, | |
| OutputStream expectedOutputStream) { | |
| checkEquals(handler, "outputStream", getOutput(handler), expectedOutputStream); | |
| check(handler, expectedLevel, expectedEncoding, expectedFilterType, expectedFormatterType); | |
| } | |
| <T> void checkEquals(Handler handler, String property, T value, T expectedValue) { | |
| if (!Objects.equals(value, expectedValue)) { | |
| fail(handler, property + ": " + value + ", expected " + property + ": " + expectedValue); | |
| } | |
| } | |
| <T> void checkType(Handler handler, String property, T value, Class<? extends T> expectedType) { | |
| if (!(expectedType == null && value == null || expectedType != null && expectedType.isInstance(value))) { | |
| Class<?> type = value == null ? null : value.getClass(); | |
| fail(handler, property + " type: " + type + ", expected " + property + " type: " + expectedType); | |
| } | |
| } | |
| void fail(Handler handler, String message) { | |
| throw new AssertionError("Handler: " + handler.getClass().getName() + | |
| ", configured with: " + getClass().getName() + | |
| ", " + message); | |
| } | |
| Handler getTarget(MemoryHandler memoryHandler) { | |
| try { | |
| return (Handler) memoryHandlerTarget.get(memoryHandler); | |
| } catch (IllegalAccessException e) { | |
| throw new IllegalAccessError(e.getMessage()); | |
| } | |
| } | |
| int getSize(MemoryHandler memoryHandler) { | |
| try { | |
| return (int) memoryHandlerSize.get(memoryHandler); | |
| } catch (IllegalAccessException e) { | |
| throw new IllegalAccessError(e.getMessage()); | |
| } | |
| } | |
| OutputStream getOutput(StreamHandler streamHandler) { | |
| try { | |
| return (OutputStream) streamHandlerOutput.get(streamHandler); | |
| } catch (IllegalAccessException e) { | |
| throw new IllegalAccessError(e.getMessage()); | |
| } | |
| } | |
| // various independent types of Formatters, Filters, Handlers... | |
| public static class SpecifiedFormatter extends Formatter { | |
| @Override | |
| public String format(LogRecord record) { | |
| return String.valueOf(record); | |
| } | |
| } | |
| public static class SpecifiedHandler extends Handler { | |
| @Override | |
| public void publish(LogRecord record) { } | |
| @Override | |
| public void flush() { } | |
| @Override | |
| public void close() throws SecurityException { } | |
| } | |
| public static class ConfiguredFormatter extends Formatter { | |
| @Override | |
| public String format(LogRecord record) { | |
| return String.valueOf(record); | |
| } | |
| } | |
| public static class ConfiguredFilter implements Filter { | |
| @Override | |
| public boolean isLoggable(LogRecord record) { | |
| return true; | |
| } | |
| } | |
| public static class ConfiguredHandler extends Handler { | |
| @Override | |
| public void publish(LogRecord record) { } | |
| @Override | |
| public void flush() { } | |
| @Override | |
| public void close() throws SecurityException { } | |
| } | |
| } |