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