diff --git a/jdk/src/share/classes/java/util/PriorityQueue.java b/jdk/src/share/classes/java/util/PriorityQueue.java index ac87d9fb569..931c287c0c2 100644 --- a/jdk/src/share/classes/java/util/PriorityQueue.java +++ b/jdk/src/share/classes/java/util/PriorityQueue.java @@ -170,17 +170,21 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified collection or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(Collection c) { - initFromCollection(c); - if (c instanceof SortedSet) - comparator = (Comparator) - ((SortedSet)c).comparator(); - else if (c instanceof PriorityQueue) - comparator = (Comparator) - ((PriorityQueue)c).comparator(); + if (c instanceof SortedSet) { + SortedSet ss = (SortedSet) c; + this.comparator = (Comparator) ss.comparator(); + initElementsFromCollection(ss); + } + else if (c instanceof PriorityQueue) { + PriorityQueue pq = (PriorityQueue) c; + this.comparator = (Comparator) pq.comparator(); + initFromPriorityQueue(pq); + } else { - comparator = null; - heapify(); + this.comparator = null; + initFromCollection(c); } } @@ -198,9 +202,10 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified priority queue or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(PriorityQueue c) { - comparator = (Comparator)c.comparator(); - initFromCollection(c); + this.comparator = (Comparator) c.comparator(); + initFromPriorityQueue(c); } /** @@ -216,9 +221,33 @@ public class PriorityQueue extends AbstractQueue * @throws NullPointerException if the specified sorted set or any * of its elements are null */ + @SuppressWarnings("unchecked") public PriorityQueue(SortedSet c) { - comparator = (Comparator)c.comparator(); - initFromCollection(c); + this.comparator = (Comparator) c.comparator(); + initElementsFromCollection(c); + } + + private void initFromPriorityQueue(PriorityQueue c) { + if (c.getClass() == PriorityQueue.class) { + this.queue = c.toArray(); + this.size = c.size(); + } else { + initFromCollection(c); + } + } + + private void initElementsFromCollection(Collection c) { + Object[] a = c.toArray(); + // If c.toArray incorrectly doesn't return Object[], copy it. + if (a.getClass() != Object[].class) + a = Arrays.copyOf(a, a.length, Object[].class); + int len = a.length; + if (len == 1 || this.comparator != null) + for (int i = 0; i < len; i++) + if (a[i] == null) + throw new NullPointerException(); + this.queue = a; + this.size = a.length; } /** @@ -227,12 +256,8 @@ public class PriorityQueue extends AbstractQueue * @param c the collection */ private void initFromCollection(Collection c) { - Object[] a = c.toArray(); - // If c.toArray incorrectly doesn't return Object[], copy it. - if (a.getClass() != Object[].class) - a = Arrays.copyOf(a, a.length, Object[].class); - queue = a; - size = a.length; + initElementsFromCollection(c); + heapify(); } /** diff --git a/jdk/test/java/util/PriorityQueue/NoNulls.java b/jdk/test/java/util/PriorityQueue/NoNulls.java new file mode 100644 index 00000000000..c40c93be893 --- /dev/null +++ b/jdk/test/java/util/PriorityQueue/NoNulls.java @@ -0,0 +1,204 @@ +/* + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @bug 6950540 + * @summary Attempt to add a null throws NullPointerException + */ + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Collection; +import java.util.Collections; +import java.util.PriorityQueue; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; + +public class NoNulls { + void test(String[] args) throws Throwable { + final Comparator nullTolerantComparator + = new Comparator<>() { + public int compare(String x, String y) { + return (x == null ? -1 : + y == null ? 1 : + x.compareTo(y)); + }}; + + final SortedSet nullSortedSet + = new TreeSet<>(nullTolerantComparator); + nullSortedSet.add(null); + + final PriorityQueue nullPriorityQueue + = new PriorityQueue<>() { + public Object[] toArray() { return new Object[] { null };}}; + + final Collection nullCollection = new ArrayList<>(); + nullCollection.add(null); + + THROWS(NullPointerException.class, + new F() { void f() { + new PriorityQueue(nullCollection); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullCollection); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, false, nullCollection); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, true, nullCollection); + }}, + new F() { void f() { + new LinkedBlockingQueue(nullCollection); + }}, + new F() { void f() { + new LinkedBlockingDeque(nullCollection); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue(nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue(nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue().add(null); + }}, + new F() { void f() { + new PriorityBlockingQueue().add(null); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, false).add(null); + }}, + new F() { void f() { + new ArrayBlockingQueue(10, true).add(null); + }}, + new F() { void f() { + new LinkedBlockingQueue().add(null); + }}, + new F() { void f() { + new LinkedBlockingDeque().add(null); + }}, + + new F() { void f() { + new PriorityQueue().offer(null); + }}, + new F() { void f() { + new PriorityBlockingQueue().offer(null); + }}); + + nullSortedSet.add("foo"); + nullCollection.add("foo"); + THROWS(NullPointerException.class, + new F() { void f() { + new PriorityQueue(nullCollection); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullCollection); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullPriorityQueue); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullPriorityQueue); + }}, + + new F() { void f() { + new PriorityQueue(nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue(nullSortedSet); + }}, + + new F() { void f() { + new PriorityQueue((Collection) nullSortedSet); + }}, + new F() { void f() { + new PriorityBlockingQueue((Collection) nullSortedSet); + }}); + + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new NoNulls().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + abstract class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +}