changeset 55057:8bc3d3eeaa53

8216363: NullPointerException in java.util.logging.Handler#isLoggable Summary: The implementation is changed to match the spec: isLoggable(null) returns false. Reviewed-by: mchung, lancea
author dfuchs
date Thu, 21 Feb 2019 16:57:47 +0000
parents 7a6fb8a48434
children dfea18758dfa
files src/java.logging/share/classes/java/util/logging/Handler.java src/java.logging/share/classes/java/util/logging/MemoryHandler.java src/java.logging/share/classes/java/util/logging/StreamHandler.java test/jdk/java/util/logging/IsLoggableHandlerTest.java
diffstat 4 files changed, 103 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.logging/share/classes/java/util/logging/Handler.java	Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/Handler.java	Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -329,12 +329,13 @@
      * handler from logging the {@code LogRecord}. It will return false if
      * the {@code LogRecord} is null.
      *
-     * @param record  a {@code LogRecord}
+     * @param record  a {@code LogRecord} (may be null).
      * @return true if the {@code LogRecord} would be logged.
      *
      */
     public boolean isLoggable(LogRecord record) {
         final int levelValue = getLevel().intValue();
+        if (record == null) return false;
         if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
             return false;
         }
--- a/src/java.logging/share/classes/java/util/logging/MemoryHandler.java	Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/MemoryHandler.java	Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -270,7 +270,7 @@
      * check whether the {@code LogRecord} would result in a "push" of the
      * buffer contents. It will return false if the {@code LogRecord} is null.
      *
-     * @param record  a {@code LogRecord}
+     * @param record  a {@code LogRecord} (may be null).
      * @return true if the {@code LogRecord} would be logged.
      *
      */
--- a/src/java.logging/share/classes/java/util/logging/StreamHandler.java	Mon Feb 18 17:41:31 2019 +0100
+++ b/src/java.logging/share/classes/java/util/logging/StreamHandler.java	Thu Feb 21 16:57:47 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,7 +225,7 @@
      * whether it satisfies any {@code Filter}.  It will also return false if
      * no output stream has been assigned yet or the LogRecord is null.
      *
-     * @param record  a {@code LogRecord}
+     * @param record  a {@code LogRecord} (may be null).
      * @return true if the {@code LogRecord} would be logged.
      *
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/logging/IsLoggableHandlerTest.java	Thu Feb 21 16:57:47 2019 +0000
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8216363
+ * @summary Test that Handler.isLoggable(null) returns false
+ * @run main/othervm IsLoggableHandlerTest
+ */
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.MemoryHandler;
+import java.util.logging.StreamHandler;
+import java.util.stream.Stream;
+
+public class IsLoggableHandlerTest {
+
+
+    public static void main(String... args) throws IOException {
+        String userDir = System.getProperty("user.dir", ".");
+        File logfile = new File(userDir, "IsLoggableHandlerTest_" + UUID.randomUUID() + ".log");
+        try {
+            System.out.println("Dummy logfile: " + logfile.getAbsolutePath());
+            Handler h = new CustomHandler();
+            testIsLoggable(h);
+            testIsLoggable(new MemoryHandler(h, 1, Level.ALL));
+            testIsLoggable(new StreamHandler(System.out, new java.util.logging.SimpleFormatter()));
+            testIsLoggable(new FileHandler(logfile.getAbsolutePath()));
+            testIsLoggable(new ConsoleHandler());
+        } finally {
+            if (logfile.canRead()) {
+                try {
+                    System.out.println("Deleting dummy logfile: " + logfile.getAbsolutePath());
+                    logfile.delete();
+                } catch (Throwable t) {
+                    System.out.println("Warning: failed to delete dummy logfile: " + t);
+                    t.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public static void testIsLoggable(Handler h) {
+        System.out.println("Testing " + h.getClass().getName());
+        // should not throw NPE but return false
+        if (h.isLoggable(null)) {
+            throw new AssertionError(h.getClass().getName()
+                    + ": null record should not be loggable");
+        }
+        h.setLevel(Level.ALL);
+        // should still not throw NPE but return false
+        if (h.isLoggable(null)) {
+            throw new AssertionError(h.getClass().getName()
+                    + ": null record should not be loggable");
+        }
+        // should not throw NPE
+        h.publish(null);
+    }
+
+    public static final class CustomHandler extends Handler {
+        @Override
+        public void publish(LogRecord record) { }
+        @Override
+        public void flush() { }
+        @Override
+        public void close() throws SecurityException { }
+    }
+
+
+}