1 /* 2 * Copyright (c) 2017, 2018, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 import java.io.IOException; 24 import java.nio.file.Files; 25 import java.nio.file.Path; 26 import java.nio.file.Paths; 27 import java.nio.file.StandardCopyOption; 28 import java.util.Collections; 29 import java.util.List; 30 import java.util.logging.Handler; 31 import java.util.logging.Level; 32 import java.util.logging.LogManager; 33 import java.util.logging.Logger; 34 import java.util.stream.Collectors; 35 import java.util.stream.Stream; 36 37 /** 38 * @test 39 * @bug 8191033 40 * @build custom.DotHandler custom.Handler 41 * @run main/othervm RootLoggerHandlers 42 * @run main/othervm/java.security.policy==test.policy RootLoggerHandlers 43 * @author danielfuchs 44 */ 45 public class RootLoggerHandlers { 46 47 public static final Path SRC_DIR = 48 Paths.get(System.getProperty("test.src", "src")); 49 public static final Path USER_DIR = 50 Paths.get(System.getProperty("user.dir", ".")); 51 public static final Path CONFIG_FILE = Paths.get("logging.properties"); 52 53 // Uncomment this to run the test on Java 8. Java 8 does not have 54 // List.of(...) 55 // static final class List { 56 // static <T> java.util.List<T> of(T... items) { 57 // return Collections.unmodifiableList(Arrays.asList(items)); 58 // } 59 // } 60 61 public static void main(String[] args) throws IOException { 62 Path initialProps = SRC_DIR.resolve(CONFIG_FILE); 63 Path loggingProps = USER_DIR.resolve(CONFIG_FILE); 64 System.setProperty("java.util.logging.config.file", loggingProps.toString()); 65 Files.copy(initialProps, loggingProps, StandardCopyOption.REPLACE_EXISTING); 66 System.out.println("Root level is: " + Logger.getLogger("").getLevel()); 67 if (Logger.getLogger("").getLevel() != Level.INFO) { 68 throw new RuntimeException("Expected root level INFO, got: " 69 + Logger.getLogger("").getLevel()); 70 } 71 // Verify that we have two handlers. One was configured with 72 // handlers=custom.Handler, the other with 73 // .handlers=custom.DotHandler 74 // Verify that exactly one of the two handlers is a custom.Handler 75 // Verify that exactly one of the two handlers is a custom.DotHandler 76 // Verify that the two handlers has an id of '1' 77 checkHandlers(Logger.getLogger(""), 78 Logger.getLogger("").getHandlers(), 79 1L, 80 custom.Handler.class, 81 custom.DotHandler.class); 82 checkHandlers(Logger.getLogger("global"), 83 Logger.getGlobal().getHandlers(), 84 1L, 85 custom.GlobalHandler.class); 86 87 // The log message "hi" should appear twice on the console. 88 // We don't check that. This is just for log analysis in case 89 // of test failure. 90 Logger.getAnonymousLogger().info("hi"); 91 92 // Change the root logger level to FINE in the properties file 93 // and reload the configuration. 94 Files.write(loggingProps, 95 Files.lines(initialProps) 96 .map((s) -> s.replace("INFO", "FINE")) 97 .collect(Collectors.toList())); 98 LogManager.getLogManager().readConfiguration(); 99 100 System.out.println("Root level is: " + Logger.getLogger("").getLevel()); 101 if (Logger.getLogger("").getLevel() != Level.FINE) { 102 throw new RuntimeException("Expected root level FINE, got: " 103 + Logger.getLogger("").getLevel()); 104 } 105 106 // Verify that we have now only one handler, configured with 107 // handlers=custom.Handler, and that the other configured with 108 // .handlers=custom.DotHandler was ignored. 109 // Verify that the handler is a custom.Handler 110 // Verify that the handler has an id of '2' 111 checkHandlers(Logger.getLogger(""), 112 Logger.getLogger("").getHandlers(), 113 2L, 114 custom.Handler.class); 115 checkHandlers(Logger.getGlobal(), 116 Logger.getGlobal().getHandlers(), 117 1L); 118 119 // The log message "there" should appear only once on the console. 120 // We don't check that. This is just for log analysis in case 121 // of test failure. 122 Logger.getAnonymousLogger().info("there!"); 123 124 // Change the root logger level to FINER in the properties file 125 // and reload the configuration. 126 Files.write(loggingProps, 127 Files.lines(initialProps) 128 .map((s) -> s.replace("INFO", "FINER")) 129 .collect(Collectors.toList())); 130 LogManager.getLogManager().readConfiguration(); 131 132 System.out.println("Root level is: " + Logger.getLogger("").getLevel()); 133 if (Logger.getLogger("").getLevel() != Level.FINER) { 134 throw new RuntimeException("Expected root level FINER, got: " 135 + Logger.getLogger("").getLevel()); 136 } 137 138 // Verify that we have only one handler, configured with 139 // handlers=custom.Handler, and that the other configured with 140 // .handlers=custom.DotHandler was ignored. 141 // Verify that the handler is a custom.Handler 142 // Verify that the handler has an id of '3' 143 checkHandlers(Logger.getLogger(""), 144 Logger.getLogger("").getHandlers(), 145 3L, 146 custom.Handler.class); 147 checkHandlers(Logger.getGlobal(), 148 Logger.getGlobal().getHandlers(), 149 1L); 150 151 LogManager.getLogManager().reset(); 152 LogManager.getLogManager().updateConfiguration((s) -> (o,n) -> n); 153 // Verify that we have only one handler, configured with 154 // handlers=custom.Handler, and that the other configured with 155 // .handlers=custom.DotHandler was ignored. 156 // Verify that the handler is a custom.Handler 157 // Verify that the handler has an id of '4' 158 checkHandlers(Logger.getLogger(""), 159 Logger.getLogger("").getHandlers(), 160 4L, 161 custom.Handler.class); 162 checkHandlers(Logger.getGlobal(), 163 Logger.getGlobal().getHandlers(), 164 2L, 165 custom.GlobalHandler.class); 166 167 LogManager.getLogManager().updateConfiguration((s) -> (o,n) -> n); 168 // Verify that we have only one handler, configured with 169 // handlers=custom.Handler, and that the other configured with 170 // .handlers=custom.DotHandler was ignored. 171 // Verify that the handler is a custom.Handler 172 // Verify that the handler has an id of '4' 173 checkHandlers(Logger.getLogger(""), 174 Logger.getLogger("").getHandlers(), 175 4L, 176 custom.Handler.class); 177 checkHandlers(Logger.getGlobal(), 178 Logger.getGlobal().getHandlers(), 179 2L, 180 custom.GlobalHandler.class); 181 182 183 // The log message "done" should appear only once on the console. 184 // We don't check that. This is just for log analysis in case 185 // of test failure. 186 Logger.getAnonymousLogger().info("done!"); 187 } 188 189 static void checkHandlers(Logger logger, Handler[] handlers, Long expectedID, Class<?>... clz) { 190 // Verify that we have the expected number of handlers. 191 if (Stream.of(handlers).count() != clz.length) { 192 throw new RuntimeException("Expected " + clz.length + " handlers, got: " 193 + List.of(logger.getHandlers())); 194 } 195 for (Class<?> cl : clz) { 196 // Verify that the handlers are of the expected class. 197 // For each class, we should have exactly one handler 198 // of that class. 199 if (Stream.of(handlers) 200 .map(Object::getClass) 201 .filter(cl::equals) 202 .count() != 1) { 203 throw new RuntimeException("Expected one " + cl +", got: " 204 + List.of(logger.getHandlers())); 205 } 206 } 207 // Verify that all handlers have the expected ID 208 if (Stream.of(logger.getHandlers()) 209 .map(RootLoggerHandlers::getId) 210 .filter(expectedID::equals) 211 .count() != clz.length) { 212 throw new RuntimeException("Expected ids to be " + expectedID + ", got: " 213 + List.of(logger.getHandlers())); 214 } 215 } 216 217 static long getId(Handler h) { 218 if (h instanceof custom.Handler) { 219 return ((custom.Handler)h).id; 220 } 221 if (h instanceof custom.DotHandler) { 222 return ((custom.DotHandler)h).id; 223 } 224 if (h instanceof custom.GlobalHandler) { 225 return ((custom.GlobalHandler)h).id; 226 } 227 return -1; 228 } 229 }