diff --git a/src/java.desktop/share/classes/java/beans/Introspector.java b/src/java.desktop/share/classes/java/beans/Introspector.java index f73444a54ef..c3a0dd92e95 100644 --- a/src/java.desktop/share/classes/java/beans/Introspector.java +++ b/src/java.desktop/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2023, 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 @@ -1158,6 +1158,8 @@ private static Method internalFindMethod(Class start, String methodName, // For overriden methods we need to find the most derived version. // So we start with the given class and walk up the superclass chain. for (Class cl = start; cl != null; cl = cl.getSuperclass()) { + Class type = null; + Method foundMethod = null; for (Method method : ClassInfo.get(cl).getMethods()) { // make sure method signature matches. if (method.getName().equals(methodName)) { @@ -1177,10 +1179,17 @@ private static Method internalFindMethod(Class start, String methodName, } } } - return method; + Class rt = method.getReturnType(); + if (foundMethod == null || type.isAssignableFrom(rt)) { + foundMethod = method; + type = rt; + } } } } + if (foundMethod != null) { + return foundMethod; + } } // Now check any inherited interfaces. This is necessary both when // the argument class is itself an interface, and when the argument diff --git a/test/jdk/java/beans/PropertyDescriptor/OverriddenGetter.java b/test/jdk/java/beans/PropertyDescriptor/OverriddenGetter.java new file mode 100644 index 00000000000..c6f5368a48d --- /dev/null +++ b/test/jdk/java/beans/PropertyDescriptor/OverriddenGetter.java @@ -0,0 +1,96 @@ +/* + * Copyright Amazon.com Inc. 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. + */ + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import javax.swing.JPanel; + +/** + * @test + * @bug 8308152 + * @summary PropertyDescriptor should work with overridden generic getter method + */ +public class OverriddenGetter { + + static class Parent { + private T value; + public T getValue() {return value;} + public final void setValue(T value) {this.value = value;} + } + + static class ChildO extends Parent { + public ChildO() {} + @Override + public Object getValue() {return super.getValue();} + } + + static class ChildA extends Parent { + public ChildA() {} + @Override + public ArithmeticException getValue() {return super.getValue();} + } + + static class ChildS extends Parent { + public ChildS() {} + @Override + public String getValue() {return super.getValue();} + } + + public static void main(String[] args) throws Exception { + test("UI", JPanel.class, "getUI", "setUI"); + test("value", ChildO.class, "getValue", "setValue"); + test("value", ChildA.class, "getValue", "setValue"); + test("value", ChildS.class, "getValue", "setValue"); + } + + private static void test(String name, Class beanClass, + String read, String write) throws Exception + { + var gold = new PropertyDescriptor(name, beanClass, read, write); + BeanInfo beanInfo = Introspector.getBeanInfo(beanClass); + PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); + for (PropertyDescriptor pd : pds) { + if (pd.getName().equals(gold.getName())) { + if (pd.getReadMethod() != gold.getReadMethod()) { + System.err.println("Expected: " + gold.getReadMethod()); + System.err.println("Actual: " + pd.getReadMethod()); + throw new RuntimeException("Wrong read method"); + } + if (pd.getWriteMethod() != gold.getWriteMethod()) { + System.err.println("Expected: " + gold.getWriteMethod()); + System.err.println("Actual: " + pd.getWriteMethod()); + throw new RuntimeException("Wrong write method"); + } + if (pd.getPropertyType() != gold.getPropertyType()) { + System.err.println("Expected: " + gold.getPropertyType()); + System.err.println("Actual: " + pd.getPropertyType()); + throw new RuntimeException("Wrong property type"); + } + return; + } + } + throw new RuntimeException("The PropertyDescriptor is not found"); + } +}