1 /* 2 * Copyright (c) 2013, 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 24 /* 25 * @test 26 * @bug 8029781 8030801 27 * @summary Test which verifies that various JDK logging Handlers are 28 * configured correctly from defaults and/or LogManager properties 29 * as specified in javadoc and that no special 30 * logging permission is required for instantiating them. 31 * @modules java.logging/java.util.logging:open 32 * @run main/othervm HandlersConfigTest default 33 * @run main/othervm HandlersConfigTest configured 34 */ 35 36 import java.io.IOException; 37 import java.io.OutputStream; 38 import java.lang.reflect.Field; 39 import java.net.ServerSocket; 40 import java.net.URL; 41 import java.util.Objects; 42 import java.util.logging.ConsoleHandler; 43 import java.util.logging.Filter; 44 import java.util.logging.Formatter; 45 import java.util.logging.Handler; 46 import java.util.logging.Level; 47 import java.util.logging.LogManager; 48 import java.util.logging.LogRecord; 49 import java.util.logging.MemoryHandler; 50 import java.util.logging.SimpleFormatter; 51 import java.util.logging.SocketHandler; 52 import java.util.logging.StreamHandler; 53 import java.util.logging.XMLFormatter; 54 55 public abstract class HandlersConfigTest implements Runnable { 56 main(String[] args)57 public static void main(String[] args) { 58 switch (args.length == 1 ? args[0] : "usage") { 59 case "default": 60 new Default().run(); 61 break; 62 case "configured": 63 new Configured().run(); 64 break; 65 default: 66 System.err.println("Usage: HandlersConfigTest [default|configured]"); 67 break; 68 } 69 } 70 71 static final String CONFIG_FILE_PROPERTY = "java.util.logging.config.file"; 72 final Field memoryHandlerTarget, memoryHandlerSize, streamHandlerOutput; 73 final ServerSocket serverSocket; 74 HandlersConfigTest()75 HandlersConfigTest() { 76 // establish access to private fields 77 try { 78 memoryHandlerTarget = MemoryHandler.class.getDeclaredField("target"); 79 memoryHandlerTarget.setAccessible(true); 80 memoryHandlerSize = MemoryHandler.class.getDeclaredField("size"); 81 memoryHandlerSize.setAccessible(true); 82 streamHandlerOutput = StreamHandler.class.getDeclaredField("output"); 83 streamHandlerOutput.setAccessible(true); 84 } catch (NoSuchFieldException e) { 85 throw new AssertionError(e); 86 } 87 88 // load logging.propertes for the test 89 String rname = getClass().getName().replace('.', '/') + ".props"; 90 URL url = getClass().getClassLoader().getResource(rname); 91 if (url == null || !"file".equals(url.getProtocol())) { 92 throw new IllegalStateException("Resource: " + rname + " not found or not on file: " + url); 93 } 94 System.setProperty(CONFIG_FILE_PROPERTY, url.getFile()); 95 96 // create ServerSocket as a target for SocketHandler 97 try { 98 serverSocket = new ServerSocket(0); // auto allocated port 99 } catch (IOException e) { 100 throw new AssertionError(e); 101 } 102 103 // activate security 104 System.setSecurityManager(new SecurityManager() { 105 @Override 106 public void checkConnect(String host, int port) { 107 // allow socket connections 108 } 109 }); 110 111 // initialize logging system 112 LogManager.getLogManager(); 113 } 114 115 // check that defaults are used as specified by javadoc 116 117 public static class Default extends HandlersConfigTest { main(String[] args)118 public static void main(String[] args) { 119 new Default().run(); 120 } 121 122 @Override run()123 public void run() { 124 // MemoryHandler 125 126 check(new MemoryHandler(), 127 Level.ALL, null, null, SimpleFormatter.class, 128 ConfiguredHandler.class, 1000, Level.SEVERE); 129 130 check(new MemoryHandler(new SpecifiedHandler(), 100, Level.WARNING), 131 Level.ALL, null, null, SimpleFormatter.class, 132 SpecifiedHandler.class, 100, Level.WARNING); 133 134 // StreamHandler 135 136 check(new StreamHandler(), 137 Level.INFO, null, null, SimpleFormatter.class, 138 null); 139 140 check(new StreamHandler(System.out, new SpecifiedFormatter()), 141 Level.INFO, null, null, SpecifiedFormatter.class, 142 System.out); 143 144 // ConsoleHandler 145 146 check(new ConsoleHandler(), 147 Level.INFO, null, null, SimpleFormatter.class, 148 System.err); 149 150 // SocketHandler (use the ServerSocket's port) 151 152 try { 153 check(new SocketHandler("localhost", serverSocket.getLocalPort()), 154 Level.ALL, null, null, XMLFormatter.class); 155 } catch (IOException e) { 156 throw new RuntimeException("Can't connect to localhost:" + serverSocket.getLocalPort(), e); 157 } 158 } 159 } 160 161 // check that LogManager properties configuration is respected 162 163 public static class Configured extends HandlersConfigTest { main(String[] args)164 public static void main(String[] args) { 165 new Configured().run(); 166 } 167 168 @Override run()169 public void run() { 170 // MemoryHandler 171 172 check(new MemoryHandler(), 173 Level.FINE, null, ConfiguredFilter.class, ConfiguredFormatter.class, 174 ConfiguredHandler.class, 123, Level.FINE); 175 176 check(new MemoryHandler(new SpecifiedHandler(), 100, Level.WARNING), 177 Level.FINE, null, ConfiguredFilter.class, ConfiguredFormatter.class, 178 SpecifiedHandler.class, 100, Level.WARNING); 179 180 // StreamHandler 181 182 check(new StreamHandler(), 183 Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class, 184 null); 185 186 check(new StreamHandler(System.out, new SpecifiedFormatter()), 187 Level.FINE, "ASCII", ConfiguredFilter.class, SpecifiedFormatter.class, 188 System.out); 189 190 // ConsoleHandler 191 192 check(new ConsoleHandler(), 193 Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class, 194 System.err); 195 196 // SocketHandler (use the ServerSocket's port) 197 198 try { 199 check(new SocketHandler("localhost", serverSocket.getLocalPort()), 200 Level.FINE, "ASCII", ConfiguredFilter.class, ConfiguredFormatter.class); 201 } catch (Exception e) { 202 throw new RuntimeException("Can't connect to localhost:" + serverSocket.getLocalPort(), e); 203 } 204 } 205 } 206 207 // test infrastructure 208 check(Handler handler, Level expectedLevel, String expectedEncoding, Class<? extends Filter> expectedFilterType, Class<? extends Formatter> expectedFormatterType)209 void check(Handler handler, 210 Level expectedLevel, 211 String expectedEncoding, 212 Class<? extends Filter> expectedFilterType, 213 Class<? extends Formatter> expectedFormatterType) { 214 checkEquals(handler, "level", handler.getLevel(), expectedLevel); 215 checkEquals(handler, "encoding", handler.getEncoding(), expectedEncoding); 216 checkType(handler, "filter", handler.getFilter(), expectedFilterType); 217 checkType(handler, "formatter", handler.getFormatter(), expectedFormatterType); 218 } 219 check(MemoryHandler handler, Level expectedLevel, String expectedEncoding, Class<? extends Filter> expectedFilterType, Class<? extends Formatter> expectedFormatterType, Class<? extends Handler> expextedTargetType, int expextedSize, Level expectedPushLevel)220 void check(MemoryHandler handler, 221 Level expectedLevel, 222 String expectedEncoding, 223 Class<? extends Filter> expectedFilterType, 224 Class<? extends Formatter> expectedFormatterType, 225 Class<? extends Handler> expextedTargetType, 226 int expextedSize, 227 Level expectedPushLevel) { 228 checkType(handler, "target", getTarget(handler), expextedTargetType); 229 checkEquals(handler, "size", getSize(handler), expextedSize); 230 checkEquals(handler, "pushLevel", handler.getPushLevel(), expectedPushLevel); 231 check(handler, expectedLevel, expectedEncoding, expectedFilterType, expectedFormatterType); 232 } 233 check(StreamHandler handler, Level expectedLevel, String expectedEncoding, Class<? extends Filter> expectedFilterType, Class<? extends Formatter> expectedFormatterType, OutputStream expectedOutputStream)234 void check(StreamHandler handler, 235 Level expectedLevel, 236 String expectedEncoding, 237 Class<? extends Filter> expectedFilterType, 238 Class<? extends Formatter> expectedFormatterType, 239 OutputStream expectedOutputStream) { 240 checkEquals(handler, "outputStream", getOutput(handler), expectedOutputStream); 241 check(handler, expectedLevel, expectedEncoding, expectedFilterType, expectedFormatterType); 242 } 243 checkEquals(Handler handler, String property, T value, T expectedValue)244 <T> void checkEquals(Handler handler, String property, T value, T expectedValue) { 245 if (!Objects.equals(value, expectedValue)) { 246 fail(handler, property + ": " + value + ", expected " + property + ": " + expectedValue); 247 } 248 } 249 checkType(Handler handler, String property, T value, Class<? extends T> expectedType)250 <T> void checkType(Handler handler, String property, T value, Class<? extends T> expectedType) { 251 if (!(expectedType == null && value == null || expectedType != null && expectedType.isInstance(value))) { 252 Class<?> type = value == null ? null : value.getClass(); 253 fail(handler, property + " type: " + type + ", expected " + property + " type: " + expectedType); 254 } 255 } 256 fail(Handler handler, String message)257 void fail(Handler handler, String message) { 258 throw new AssertionError("Handler: " + handler.getClass().getName() + 259 ", configured with: " + getClass().getName() + 260 ", " + message); 261 } 262 getTarget(MemoryHandler memoryHandler)263 Handler getTarget(MemoryHandler memoryHandler) { 264 try { 265 return (Handler) memoryHandlerTarget.get(memoryHandler); 266 } catch (IllegalAccessException e) { 267 throw new IllegalAccessError(e.getMessage()); 268 } 269 } 270 getSize(MemoryHandler memoryHandler)271 int getSize(MemoryHandler memoryHandler) { 272 try { 273 return (int) memoryHandlerSize.get(memoryHandler); 274 } catch (IllegalAccessException e) { 275 throw new IllegalAccessError(e.getMessage()); 276 } 277 } 278 getOutput(StreamHandler streamHandler)279 OutputStream getOutput(StreamHandler streamHandler) { 280 try { 281 return (OutputStream) streamHandlerOutput.get(streamHandler); 282 } catch (IllegalAccessException e) { 283 throw new IllegalAccessError(e.getMessage()); 284 } 285 } 286 287 // various independent types of Formatters, Filters, Handlers... 288 289 public static class SpecifiedFormatter extends Formatter { 290 @Override format(LogRecord record)291 public String format(LogRecord record) { 292 return String.valueOf(record); 293 } 294 } 295 296 public static class SpecifiedHandler extends Handler { 297 @Override publish(LogRecord record)298 public void publish(LogRecord record) { } 299 300 @Override flush()301 public void flush() { } 302 303 @Override close()304 public void close() throws SecurityException { } 305 } 306 307 public static class ConfiguredFormatter extends Formatter { 308 @Override format(LogRecord record)309 public String format(LogRecord record) { 310 return String.valueOf(record); 311 } 312 } 313 314 public static class ConfiguredFilter implements Filter { 315 @Override isLoggable(LogRecord record)316 public boolean isLoggable(LogRecord record) { 317 return true; 318 } 319 } 320 321 public static class ConfiguredHandler extends Handler { 322 @Override publish(LogRecord record)323 public void publish(LogRecord record) { } 324 325 @Override flush()326 public void flush() { } 327 328 @Override close()329 public void close() throws SecurityException { } 330 } 331 } 332