From 50904f1076597f81286cd9a021bdfe047f9fea9f Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 17 Jun 2025 17:49:22 +0100 Subject: [PATCH 1/8] test/jdk/javax/management/generified/ListTypeCheckTest.java --- .../javax/management/AttributeList.java | 55 ++------- .../javax/management/relation/RoleList.java | 108 ++++++----------- .../relation/RoleUnresolvedList.java | 109 ++++++------------ .../AttributeListTypeSafeTest.java | 28 ++--- .../generified/ListTypeCheckTest.java | 8 +- 5 files changed, 93 insertions(+), 215 deletions(-) diff --git a/src/java.management/share/classes/javax/management/AttributeList.java b/src/java.management/share/classes/javax/management/AttributeList.java index 932c4974244f3..7077a23875463 100644 --- a/src/java.management/share/classes/javax/management/AttributeList.java +++ b/src/java.management/share/classes/javax/management/AttributeList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -37,13 +37,9 @@ * {@link MBeanServerConnection#setAttributes setAttributes} methods of * {@link MBeanServer} and {@link MBeanServerConnection}.

* - *

For compatibility reasons, it is possible, though - * highly discouraged, to add objects to an {@code AttributeList} that are - * not instances of {@code Attribute}. However, an {@code AttributeList} - * can be made type-safe, which means that an attempt to add - * an object that is not an {@code Attribute} will produce an {@code - * IllegalArgumentException}. An {@code AttributeList} becomes type-safe - * when the method {@link #asList()} is called on it.

+ *

It is not permitted to add objects to an {@code AttributeList} that are + * not instances of {@code Attribute}. This will produce an {@code + * IllegalArgumentException}.

* * @since 1.5 */ @@ -64,9 +60,6 @@ the asList() method so you can write */ public class AttributeList extends ArrayList { - private transient volatile boolean typeSafe; - private transient volatile boolean tainted; - /* Serial version */ private static final long serialVersionUID = -4077085769279709076L; @@ -145,14 +138,6 @@ public AttributeList(List list) { * @return a {@code List} whose contents * reflect the contents of this {@code AttributeList}. * - *

If this method has ever been called on a given - * {@code AttributeList} instance, a subsequent attempt to add - * an object to that instance which is not an {@code Attribute} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, an {@code AttributeList} on which this method has never - * been called does allow objects other than {@code Attribute}s to - * be added.

- * * @throws IllegalArgumentException if this {@code AttributeList} contains * an element that is not an {@code Attribute}. * @@ -160,9 +145,7 @@ public AttributeList(List list) { */ @SuppressWarnings("unchecked") public List asList() { - typeSafe = true; - if (tainted) - adding((Collection) this); // will throw IllegalArgumentException + adding((Collection) this); return (List) (List) this; } @@ -257,15 +240,12 @@ public boolean addAll(int index, AttributeList list) { /* * Override all of the methods from ArrayList that might add - * a non-Attribute to the List, and disallow that if asList has ever - * been called on this instance. + * a non-Attribute to the List, and disallow. */ /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public boolean add(Object element) { @@ -275,9 +255,7 @@ public boolean add(Object element) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public void add(int index, Object element) { @@ -287,9 +265,7 @@ public void add(int index, Object element) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code c} contains an - * element that is not an {@code Attribute}. + * @throws IllegalArgumentException if {@code c} contains an element that is not an {@code Attribute}. */ @Override public boolean addAll(Collection c) { @@ -299,9 +275,7 @@ public boolean addAll(Collection c) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code c} contains an - * element that is not an {@code Attribute}. + * @throws IllegalArgumentException if {@code c} contains an element that is not an {@code Attribute}. */ @Override public boolean addAll(int index, Collection c) { @@ -311,9 +285,7 @@ public boolean addAll(int index, Collection c) { /** * {@inheritDoc} - * @throws IllegalArgumentException if this {@code AttributeList} is - * type-safe and {@code element} is not an - * {@code Attribute}. + * @throws IllegalArgumentException if {@code element} is not an {@code Attribute}. */ @Override public Object set(int index, Object element) { @@ -324,10 +296,7 @@ public Object set(int index, Object element) { private void adding(Object x) { if (x == null || x instanceof Attribute) return; - if (typeSafe) - throw new IllegalArgumentException("Not an Attribute: " + x); - else - tainted = true; + throw new IllegalArgumentException("Not an Attribute: " + x); } private void adding(Collection c) { diff --git a/src/java.management/share/classes/javax/management/relation/RoleList.java b/src/java.management/share/classes/javax/management/relation/RoleList.java index fbbc3df64364b..ae2393d029c96 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -55,9 +55,6 @@ the asList() method so you can write */ public class RoleList extends ArrayList { - private transient boolean typeSafe; - private transient boolean tainted; - /* Serial version */ private static final long serialVersionUID = 5568344346499649313L; @@ -121,25 +118,13 @@ public RoleList(List list) throws IllegalArgumentException { * @return a {@code List} whose contents * reflect the contents of this {@code RoleList}. * - *

If this method has ever been called on a given - * {@code RoleList} instance, a subsequent attempt to add - * an object to that instance which is not a {@code Role} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, a {@code RoleList} on which this method has never - * been called does allow objects other than {@code Role}s to - * be added.

- * * @throws IllegalArgumentException if this {@code RoleList} contains * an element that is not a {@code Role}. * * @since 1.6 */ public List asList() { - if (!typeSafe) { - if (tainted) - checkTypeSafe(this); - typeSafe = true; - } + checkTypeSafe(this); return Util.cast(this); } @@ -158,9 +143,9 @@ public void add(Role role) throws IllegalArgumentException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } + checkTypeSafe(role); super.add(role); } @@ -183,10 +168,9 @@ public void add(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - + checkTypeSafe(role); super.add(index, role); } @@ -208,11 +192,9 @@ public void set(int index, IndexOutOfBoundsException { if (role == null) { - // Revisit [cebro] Localize message - String excMsg = "Invalid parameter."; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - + checkTypeSafe(role); super.set(index, role); } @@ -236,7 +218,6 @@ public boolean addAll(RoleList roleList) if (roleList == null) { return true; } - return (super.addAll(roleList)); } @@ -263,9 +244,7 @@ public boolean addAll(int index, IndexOutOfBoundsException { if (roleList == null) { - // Revisit [cebro] Localize message - String excMsg = "Invalid parameter."; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } return (super.addAll(index, roleList)); @@ -277,48 +256,53 @@ public boolean addAll(int index, * been called on this instance. */ + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code o} is not a {@code Role}. + */ @Override public boolean add(Object o) { - if (!tainted) - tainted = isTainted(o); - if (typeSafe) - checkTypeSafe(o); + checkTypeSafe(o); return super.add(o); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code Role}. + */ @Override public void add(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); super.add(index, element); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code Role}. + */ @Override public boolean addAll(Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code Role}. + */ @Override public boolean addAll(int index, Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(index, c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code Role}. + */ @Override public Object set(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); return super.set(index, element); } @@ -345,28 +329,4 @@ private static void checkTypeSafe(Collection c) { throw new IllegalArgumentException(e); } } - - /** - * Returns true if o is a non-Role object. - */ - private static boolean isTainted(Object o) { - try { - checkTypeSafe(o); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } - - /** - * Returns true if c contains any non-Role objects. - */ - private static boolean isTainted(Collection c) { - try { - checkTypeSafe(c); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } } diff --git a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java index dae506e5e5f2b..1115151c788be 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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 @@ -54,9 +54,6 @@ the asList() method so you can write */ public class RoleUnresolvedList extends ArrayList { - private transient boolean typeSafe; - private transient boolean tainted; - /* Serial version */ private static final long serialVersionUID = 4054902803091433324L; @@ -121,25 +118,13 @@ public RoleUnresolvedList(List list) * @return a {@code List} whose contents * reflect the contents of this {@code RoleUnresolvedList}. * - *

If this method has ever been called on a given - * {@code RoleUnresolvedList} instance, a subsequent attempt to add - * an object to that instance which is not a {@code RoleUnresolved} - * will fail with an {@code IllegalArgumentException}. For compatibility - * reasons, a {@code RoleUnresolvedList} on which this method has never - * been called does allow objects other than {@code RoleUnresolved}s to - * be added.

- * * @throws IllegalArgumentException if this {@code RoleUnresolvedList} * contains an element that is not a {@code RoleUnresolved}. * * @since 1.6 */ public List asList() { - if (!typeSafe) { - if (tainted) - checkTypeSafe(this); - typeSafe = true; - } + checkTypeSafe(this); return Util.cast(this); } @@ -158,9 +143,9 @@ public void add(RoleUnresolved role) throws IllegalArgumentException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } + checkTypeSafe(role); super.add(role); } @@ -184,10 +169,9 @@ public void add(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - + checkTypeSafe(role); super.add(index, role); } @@ -210,10 +194,9 @@ public void set(int index, IndexOutOfBoundsException { if (role == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - + checkTypeSafe(role); super.set(index, role); } @@ -236,7 +219,7 @@ public boolean addAll(RoleUnresolvedList roleList) if (roleList == null) { return true; } - + checkTypeSafe(roleList); return (super.addAll(roleList)); } @@ -261,10 +244,9 @@ public boolean addAll(int index, IndexOutOfBoundsException { if (roleList == null) { - String excMsg = "Invalid parameter"; - throw new IllegalArgumentException(excMsg); + throw new IllegalArgumentException("Invalid parameter"); } - + checkTypeSafe(roleList); return (super.addAll(index, roleList)); } @@ -274,48 +256,53 @@ public boolean addAll(int index, * ever been called on this instance. */ + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code o} is not a {@code RoleUnresolved}. + */ @Override public boolean add(Object o) { - if (!tainted) - tainted = isTainted(o); - if (typeSafe) - checkTypeSafe(o); + checkTypeSafe(o); return super.add(o); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code RoleUnresolved}. + */ @Override public void add(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); super.add(index, element); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code RoleUnresolved}. + */ @Override public boolean addAll(Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code c} contains a member that is not a {@code RoleUnresolved}. + */ @Override public boolean addAll(int index, Collection c) { - if (!tainted) - tainted = isTainted(c); - if (typeSafe) - checkTypeSafe(c); + checkTypeSafe(c); return super.addAll(index, c); } + /** + * {@inheritDoc} + * @throws IllegalArgumentException if {@code element} is not a {@code RoleUnresolved}. + */ @Override public Object set(int index, Object element) { - if (!tainted) - tainted = isTainted(element); - if (typeSafe) - checkTypeSafe(element); + checkTypeSafe(element); return super.set(index, element); } @@ -342,28 +329,4 @@ private static void checkTypeSafe(Collection c) { throw new IllegalArgumentException(e); } } - - /** - * Returns true if o is a non-RoleUnresolved object. - */ - private static boolean isTainted(Object o) { - try { - checkTypeSafe(o); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } - - /** - * Returns true if c contains any non-RoleUnresolved objects. - */ - private static boolean isTainted(Collection c) { - try { - checkTypeSafe(c); - } catch (IllegalArgumentException e) { - return true; - } - return false; - } } diff --git a/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java b/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java index 602e1f2ebd288..219632784f0a5 100644 --- a/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java +++ b/test/jdk/javax/management/MBeanServer/AttributeListTypeSafeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6336968 + * @bug 6336968 8359809 * @summary Test adding non-Attribute values to an AttributeList. * @author Eamonn McManus */ @@ -38,28 +38,14 @@ public class AttributeListTypeSafeTest { private static String failure; public static void main(String[] args) throws Exception { - // Test calling asList after adding non-Attribute by various means + // Test adding non-Attribute by various means for (Op op : Op.values()) { AttributeList alist = new AttributeList(); - alist.add(new Attribute("foo", "bar")); - doOp(alist, op); - String what = "asList() after calling " + op + " with non-Attribute"; + alist.add(new Attribute("foo", "bar")); // Add actual Attribute + alist.add(null); + String what = "Using " + op + " with non-Attribute"; try { - List lista = alist.asList(); - fail(what + ": succeeded but should not have"); - } catch (IllegalArgumentException e) { - System.out.println("OK: " + what + ": got IllegalArgumentException"); - } - } - - // Test adding non-Attribute by various means after calling asList - for (Op op : Op.values()) { - AttributeList alist = new AttributeList(); - List lista = alist.asList(); - lista.add(new Attribute("foo", "bar")); - String what = op + " with non-Attribute after calling asList()"; - try { - doOp(alist, op); + doOp(alist, op); // Add some other non-Attribute, should fail fail(what + ": succeeded but should not have"); } catch (IllegalArgumentException e) { System.out.println("OK: " + what + ": got IllegalArgumentException"); diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index a28ffba92d407..98d8266325b77 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -23,8 +23,8 @@ /* * @test - * @bug 6250772 - * @summary Test that *List objects are checked after asList is called. + * @bug 6250772 8359809 + * @summary Test that *List objects are checked * @author Eamonn McManus * * @run clean ListTypeCheckTest @@ -60,7 +60,7 @@ private static void test(Class c) throws Exception { } private static void test(ArrayList al) throws Exception { - test(al, true); + test(al, false); al.clear(); Method m = al.getClass().getMethod("asList"); m.invoke(al); @@ -90,7 +90,7 @@ private static void test(ArrayList al, boolean allowsBogus) throws Exception { throw new Exception("test wrong"); } if (!allowsBogus) - throw new Exception("op allowed but should fail"); + throw new Exception("op " + i + " allowed but should fail on " + al.getClass()); } catch (IllegalArgumentException e) { if (allowsBogus) throw new Exception("got exception but should not", e); From afb0543427eba56fc25fbaecf3958459dfc31ebf Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 25 Jun 2025 17:56:58 +0100 Subject: [PATCH 2/8] fewer checkTypeSafe calls in RoleList and RoleUnresolvedList --- .../share/classes/javax/management/relation/RoleList.java | 3 --- .../javax/management/relation/RoleUnresolvedList.java | 5 ----- 2 files changed, 8 deletions(-) diff --git a/src/java.management/share/classes/javax/management/relation/RoleList.java b/src/java.management/share/classes/javax/management/relation/RoleList.java index ae2393d029c96..2047d09028f7e 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleList.java @@ -145,7 +145,6 @@ public void add(Role role) if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.add(role); } @@ -170,7 +169,6 @@ public void add(int index, if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.add(index, role); } @@ -194,7 +192,6 @@ public void set(int index, if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.set(index, role); } diff --git a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java index 1115151c788be..975b51568e4a2 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java @@ -145,7 +145,6 @@ public void add(RoleUnresolved role) if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.add(role); } @@ -171,7 +170,6 @@ public void add(int index, if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.add(index, role); } @@ -196,7 +194,6 @@ public void set(int index, if (role == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(role); super.set(index, role); } @@ -219,7 +216,6 @@ public boolean addAll(RoleUnresolvedList roleList) if (roleList == null) { return true; } - checkTypeSafe(roleList); return (super.addAll(roleList)); } @@ -246,7 +242,6 @@ public boolean addAll(int index, if (roleList == null) { throw new IllegalArgumentException("Invalid parameter"); } - checkTypeSafe(roleList); return (super.addAll(index, roleList)); } From ab4fef2f76307dd302538a23a9d5741607e43058 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 30 Jun 2025 14:04:16 +0100 Subject: [PATCH 3/8] (C) --- test/jdk/javax/management/generified/ListTypeCheckTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index 98d8266325b77..96849f9f340ae 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 From 8b36d3e5566929609331bee57524a6f31fdd6587 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 30 Jun 2025 18:28:31 +0100 Subject: [PATCH 4/8] Test update, over listIterator and iterator.set() --- .../generified/ListTypeCheckTest.java | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index 96849f9f340ae..69fd29565fd65 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -39,36 +39,41 @@ /* For compatibility reasons, the classes AttributeList, RoleList, * and RoleUnresolvedList all extend ArrayList even though - * logically they should extend ArrayList etc. They are - * all specified to have a method asList() with return type - * List etc, and to refuse to add any object other than - * an Attribute etc once this method has been called, but not before. + * logically they should extend ArrayList etc. + * + * Before JDK-8359809, their method asList() had to be called, to make + * the class refuse to add any object other than the intended type. */ public class ListTypeCheckTest { public static void main(String[] args) throws Exception { Class[] classes = { AttributeList.class, RoleList.class, RoleUnresolvedList.class, }; - for (Class c : classes) - test((Class) c); + Object[] objects = { + new Attribute("myAttr", "myVal"), new Role("myRole", new ArrayList()), + new RoleUnresolved("myRoleUnresolved", new ArrayList(), RoleStatus.NO_ROLE_WITH_NAME) + }; + for (int i = 0; i < classes.length; i++) { + test((Class) classes[i], objects[i]); + } } - private static void test(Class c) throws Exception { + private static void test(Class c, Object o) throws Exception { System.out.println("Testing " + c.getName()); ArrayList al = c.newInstance(); - test(al); + test(al, o); } - private static void test(ArrayList al) throws Exception { - test(al, false); + private static void test(ArrayList al, Object o) throws Exception { + test0(al, o); al.clear(); Method m = al.getClass().getMethod("asList"); - m.invoke(al); - test(al, false); + m.invoke(al); // Calling asList() does not change behaviour + test0(al, o); } - private static void test(ArrayList al, boolean allowsBogus) throws Exception { - for (int i = 0; i < 5; i++) { + private static void test0(ArrayList al, Object o) throws Exception { + for (int i = 0; i < 6; i++) { try { switch (i) { case 0: @@ -86,14 +91,19 @@ private static void test(ArrayList al, boolean allowsBogus) throws Exception { case 4: al.set(0, "foo"); break; + case 5: + // Add the correct kind of element, so we can iterate. + al.add(o); + ListIterator iter = al.listIterator(); + Object x = iter.next(); + iter.set("blah"); // Should fail like the others + break; default: throw new Exception("test wrong"); } - if (!allowsBogus) - throw new Exception("op " + i + " allowed but should fail on " + al.getClass()); + throw new Exception("op " + i + " allowed but should fail on " + al.getClass()); } catch (IllegalArgumentException e) { - if (allowsBogus) - throw new Exception("got exception but should not", e); + System.out.println("op " + i + " got expected " + e + " on " + al.getClass()); } } } From b1f88acdbd5fa9114617f050eccdcf8f4b842687 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 1 Jul 2025 09:49:26 +0100 Subject: [PATCH 5/8] Test udpate (listIterator) --- .../javax/management/generified/ListTypeCheckTest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index 69fd29565fd65..7054ec64812b1 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -73,7 +73,7 @@ private static void test(ArrayList al, Object o) throws Exception { } private static void test0(ArrayList al, Object o) throws Exception { - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 7; i++) { try { switch (i) { case 0: @@ -98,6 +98,12 @@ private static void test0(ArrayList al, Object o) throws Exception { Object x = iter.next(); iter.set("blah"); // Should fail like the others break; + case 6: + al.add(o); + ListIterator iter2 = al.listIterator(); + Object x2 = iter2.next(); + iter2.add("blah"); + break; default: throw new Exception("test wrong"); } From a2a28ddeeea2cfbff2dfa0b1f018c56b4db7b74f Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 1 Jul 2025 09:49:37 +0100 Subject: [PATCH 6/8] Further doc update --- .../share/classes/javax/management/AttributeList.java | 4 ++-- .../share/classes/javax/management/relation/RoleList.java | 4 ++++ .../classes/javax/management/relation/RoleUnresolvedList.java | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.management/share/classes/javax/management/AttributeList.java b/src/java.management/share/classes/javax/management/AttributeList.java index 7077a23875463..c85b119f3a06c 100644 --- a/src/java.management/share/classes/javax/management/AttributeList.java +++ b/src/java.management/share/classes/javax/management/AttributeList.java @@ -38,8 +38,8 @@ * {@link MBeanServer} and {@link MBeanServerConnection}.

* *

It is not permitted to add objects to an {@code AttributeList} that are - * not instances of {@code Attribute}. This will produce an {@code - * IllegalArgumentException}.

+ * not instances of {@code Attribute}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

* * @since 1.5 */ diff --git a/src/java.management/share/classes/javax/management/relation/RoleList.java b/src/java.management/share/classes/javax/management/relation/RoleList.java index 2047d09028f7e..f16a441ad462b 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleList.java @@ -35,6 +35,10 @@ * parameter when creating a relation, and when trying to set several roles in * a relation (via 'setRoles()' method). It is returned as part of a * RoleResult, to provide roles successfully retrieved. + + *

It is not permitted to add objects to a {@code RoleList} that are + * not instances of {@code Role}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

* * @since 1.5 */ diff --git a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java index 975b51568e4a2..3d1e4223cbae8 100644 --- a/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java +++ b/src/java.management/share/classes/javax/management/relation/RoleUnresolvedList.java @@ -35,6 +35,10 @@ * representing roles not retrieved from a relation due to a problem * encountered when trying to access (read or write) the roles. * + *

It is not permitted to add objects to a {@code RoleUnresolvedList} that are + * not instances of {@code RoleUnresolved}. This will produce an {@code IllegalArgumentException} + * when calling methods in this class, or when using {@code listIterator} and {@code add} or {@code set}.

+ * * @since 1.5 */ /* We cannot extend ArrayList because our legacy From e7654936d45c0cd1dbe353dc66e4f20e653f053f Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 10 Jul 2025 08:53:26 +0100 Subject: [PATCH 7/8] Test comment update --- .../javax/management/generified/ListTypeCheckTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index 7054ec64812b1..9528335e9b9f5 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -77,6 +77,7 @@ private static void test0(ArrayList al, Object o) throws Exception { try { switch (i) { case 0: + // Add the wrong kind of element, will fail: al.add("yo"); break; case 1: @@ -92,21 +93,23 @@ private static void test0(ArrayList al, Object o) throws Exception { al.set(0, "foo"); break; case 5: - // Add the correct kind of element, so we can iterate. + // Add the correct kind of element, so we can test ListIterator. al.add(o); ListIterator iter = al.listIterator(); Object x = iter.next(); - iter.set("blah"); // Should fail like the others + iter.set("blah"); // Test "set", should fail like the others. break; case 6: + // Add the correct kind of element, so we can test ListIterator. al.add(o); ListIterator iter2 = al.listIterator(); Object x2 = iter2.next(); - iter2.add("blah"); + iter2.add("blah"); // "Test "add", should fail like the others. break; default: throw new Exception("test wrong"); } + // All cases above should have caused an Exception: throw new Exception("op " + i + " allowed but should fail on " + al.getClass()); } catch (IllegalArgumentException e) { System.out.println("op " + i + " got expected " + e + " on " + al.getClass()); From 7d3728d487bd6c4d29068161891fc998a1eaac78 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 10 Jul 2025 08:55:22 +0100 Subject: [PATCH 8/8] Test comment update --- test/jdk/javax/management/generified/ListTypeCheckTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/javax/management/generified/ListTypeCheckTest.java b/test/jdk/javax/management/generified/ListTypeCheckTest.java index 9528335e9b9f5..c1e312d22a0ac 100644 --- a/test/jdk/javax/management/generified/ListTypeCheckTest.java +++ b/test/jdk/javax/management/generified/ListTypeCheckTest.java @@ -104,7 +104,7 @@ private static void test0(ArrayList al, Object o) throws Exception { al.add(o); ListIterator iter2 = al.listIterator(); Object x2 = iter2.next(); - iter2.add("blah"); // "Test "add", should fail like the others. + iter2.add("blah"); // Test "add", should fail like the others. break; default: throw new Exception("test wrong");