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