1 /*
   2  * Copyright (c) 2017, 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.util.Arrays;
  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  * @author danielfuchs
  43  */
  44 public class RootLoggerHandlers {
  45 
  46     public static final Path SRC_DIR =
  47             Paths.get(System.getProperty("test.src", "src"));
  48     public static final Path USER_DIR =
  49             Paths.get(System.getProperty("user.dir", "."));
  50     public static final Path CONFIG_FILE = Paths.get("logging.properties");
  51 
  52     // Uncomment this to run the test on Java 8. Java 8 does not have
  53     // List.of(...)
  54     //    static final class List {
  55     //        static <T> java.util.List<T> of(T... items) {
  56     //            return Collections.unmodifiableList(Arrays.asList(items));
  57     //        }
  58     //    }
  59 
  60     public static void main(String[] args) throws IOException {
  61         Path initialProps = SRC_DIR.resolve(CONFIG_FILE);
  62         Path loggingProps = USER_DIR.resolve(CONFIG_FILE);
  63         System.setProperty("java.util.logging.config.file", loggingProps.toString());
  64         Files.copy(initialProps, loggingProps);
  65         System.out.println("Root level is: " + Logger.getLogger("").getLevel());
  66         if (Logger.getLogger("").getLevel() != Level.INFO) {
  67             throw new RuntimeException("Expected root level INFO, got: "
  68                                         + Logger.getLogger("").getLevel());
  69         }
  70         // Verify that we have two handlers. One was configured with
  71         // handlers=custom.Handler, the other with
  72         // .handlers=custom.DotHandler
  73         // Verify that exactly one of the two handlers is a custom.Handler
  74         // Verify that exactly one of the two handlers is a custom.DotHandler
  75         // Verify that the two handlers has an id of '1'
  76         checkHandlers(Logger.getLogger("").getHandlers(),
  77                 1L,
  78                 custom.Handler.class,
  79                 custom.DotHandler.class);
  80 
  81         // The log message "hi" should appear twice on the console.
  82         // We don't check that. This is just for log analysis in case
  83         // of test failure.
  84         Logger.getAnonymousLogger().info("hi");
  85 
  86         // Change the root logger level to FINE in the properties file
  87         // and reload the configuration.
  88         Files.write(loggingProps,
  89                 Files.lines(initialProps)
  90                         .map((s) -> s.replace("INFO", "FINE"))
  91                         .collect(Collectors.toList()));
  92         LogManager.getLogManager().readConfiguration();
  93 
  94         System.out.println("Root level is: " + Logger.getLogger("").getLevel());
  95         if (Logger.getLogger("").getLevel() != Level.FINE) {
  96             throw new RuntimeException("Expected root level FINE, got: "
  97                     + Logger.getLogger("").getLevel());
  98         }
  99 
 100         // Verify that we have now only one handler, configured with
 101         // handlers=custom.Handler, and that the other configured with
 102         // .handlers=custom.DotHandler was ignored.
 103         // Verify that the handler is a custom.Handler
 104         // Verify that the handler has an id of '2'
 105         checkHandlers(Logger.getLogger("").getHandlers(),
 106                 2L,
 107                 custom.Handler.class);
 108 
 109         // The log message "there" should appear only once on the console.
 110         // We don't check that. This is just for log analysis in case
 111         // of test failure.
 112         Logger.getAnonymousLogger().info("there!");
 113 
 114         // Change the root logger level to FINER in the properties file
 115         // and reload the configuration.
 116         Files.write(loggingProps,
 117                 Files.lines(initialProps)
 118                         .map((s) -> s.replace("INFO", "FINER"))
 119                         .collect(Collectors.toList()));
 120         LogManager.getLogManager().readConfiguration();
 121 
 122         System.out.println("Root level is: " + Logger.getLogger("").getLevel());
 123         if (Logger.getLogger("").getLevel() != Level.FINER) {
 124             throw new RuntimeException("Expected root level FINER, got: "
 125                     + Logger.getLogger("").getLevel());
 126         }
 127 
 128         // Verify that we have only one handler, configured with
 129         // handlers=custom.Handler, and that the other configured with
 130         // .handlers=custom.DotHandler was ignored.
 131         // Verify that the handler is a custom.Handler
 132         // Verify that the handler has an id of '3'
 133         checkHandlers(Logger.getLogger("").getHandlers(),
 134                 3L,
 135                 custom.Handler.class);
 136 
 137         // The log message "done" should appear only once on the console.
 138         // We don't check that. This is just for log analysis in case
 139         // of test failure.
 140         Logger.getAnonymousLogger().info("done!");
 141     }
 142 
 143     static void checkHandlers(Handler[] handlers, Long expectedID, Class<?>... clz) {
 144         // Verify that we have the expected number of handlers.
 145         if (Stream.of(handlers).count() != clz.length) {
 146             throw new RuntimeException("Expected " + clz.length + " handlers, got: "
 147                     + List.of(Logger.getLogger("").getHandlers()));
 148         }
 149         for (Class<?> cl : clz) {
 150             // Verify that the handlers are of the expected class.
 151             // For each class, we should have exactly one handler
 152             // of that class.
 153             if (Stream.of(handlers)
 154                     .map(Object::getClass)
 155                     .filter(cl::equals)
 156                     .count() != 1) {
 157                 throw new RuntimeException("Expected one " + cl +", got: "
 158                         + List.of(Logger.getLogger("").getHandlers()));
 159             }
 160         }
 161         // Verify that all handlers have the expected ID
 162         if (Stream.of(Logger.getLogger("").getHandlers())
 163                 .map(RootLoggerHandlers::getId)
 164                 .filter(expectedID::equals)
 165                 .count() != clz.length) {
 166             throw new RuntimeException("Expected ids to be " + expectedID + ", got: "
 167                     + List.of(Logger.getLogger("").getHandlers()));
 168         }
 169     }
 170 
 171     static long getId(Handler h) {
 172         if (h instanceof custom.Handler) {
 173             return ((custom.Handler)h).id;
 174         }
 175         if (h instanceof custom.DotHandler) {
 176             return ((custom.DotHandler)h).id;
 177         }
 178         return -1;
 179     }
 180 }