From 7da5cd0dd33f60e042883e944bcf4e8d6dca520e Mon Sep 17 00:00:00 2001 From: malenkov Date: Mon, 27 Sep 2010 13:38:49 +0400 Subject: [PATCH] 6976577: JCK7 api/java_beans/EventSetDescriptor/descriptions.html#Ctor1 fails since jdk7 b102 Reviewed-by: peterz --- .../java/beans/EventSetDescriptor.java | 5 +- .../java/beans/IndexedPropertyDescriptor.java | 10 +- .../classes/java/beans/Introspector.java | 100 ++++++++++++++---- .../classes/java/beans/MethodDescriptor.java | 4 +- .../java/beans/PropertyDescriptor.java | 10 +- .../Introspector/6976577/Test6976577.java | 71 +++++++++++++ .../Introspector/6976577/test/Accessor.java | 81 ++++++++++++++ 7 files changed, 251 insertions(+), 30 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/6976577/Test6976577.java create mode 100644 jdk/test/java/beans/Introspector/6976577/test/Accessor.java diff --git a/jdk/src/share/classes/java/beans/EventSetDescriptor.java b/jdk/src/share/classes/java/beans/EventSetDescriptor.java index db592aa8e3..83b5e0d8f1 100644 --- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java +++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java @@ -176,8 +176,9 @@ public class EventSetDescriptor extends FeatureDescriptor { setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1)); // Be more forgiving of not finding the getListener method. - if (getListenerMethodName != null) { - setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName)); + Method method = Introspector.findMethod(sourceClass, getListenerMethodName, 0); + if (method != null) { + setGetListenerMethod(method); } } diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index de439c7f91..5764bf49b7 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -189,11 +189,13 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); } } - indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); + + Class[] args = { int.class }; + indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args); if (indexedReadMethod == null) { // no "is" method, so look for a "get" method. indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); - indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); + indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args); } setIndexedReadMethod0(indexedReadMethod); } @@ -265,7 +267,9 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { if (indexedWriteMethodName == null) { indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName(); } - indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type); + + Class[] args = (type == null) ? null : new Class[] { int.class, type }; + indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, args); if (indexedWriteMethod != null) { if (!indexedWriteMethod.getReturnType().equals(void.class)) { indexedWriteMethod = null; diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index d7669bb7fd..23e91d98b3 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -28,7 +28,6 @@ package java.beans; import com.sun.beans.WeakCache; import com.sun.beans.finder.BeanInfoFinder; import com.sun.beans.finder.ClassFinder; -import com.sun.beans.finder.MethodFinder; import java.lang.ref.Reference; import java.lang.ref.SoftReference; @@ -843,8 +842,8 @@ public class Introspector { Method read = result.getReadMethod(); if (read == null && write != null) { - read = findInstanceMethod(result.getClass0(), - GET_PREFIX + NameGenerator.capitalize(result.getName())); + read = findMethod(result.getClass0(), + GET_PREFIX + NameGenerator.capitalize(result.getName()), 0); if (read != null) { try { result.setReadMethod(read); @@ -854,9 +853,9 @@ public class Introspector { } } if (write == null && read != null) { - write = findInstanceMethod(result.getClass0(), - SET_PREFIX + NameGenerator.capitalize(result.getName()), - FeatureDescriptor.getReturnType(result.getClass0(), read)); + write = findMethod(result.getClass0(), + SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, + new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); if (write != null) { try { result.setWriteMethod(write); @@ -1280,27 +1279,90 @@ public class Introspector { // Package private support methods. //====================================================================== - static Method findMethod(Class type, String name, int args) { - for (Method method : type.getMethods()) { - if (method.getName().equals(name) && (args == method.getParameterTypes().length)) { - try { - return MethodFinder.findAccessibleMethod(method); + /** + * Internal support for finding a target methodName with a given + * parameter list on a given class. + */ + private static Method internalFindMethod(Class start, String methodName, + int argCount, Class args[]) { + // For overriden methods we need to find the most derived version. + // So we start with the given class and walk up the superclass chain. + + Method method = null; + + for (Class cl = start; cl != null; cl = cl.getSuperclass()) { + Method methods[] = getPublicDeclaredMethods(cl); + for (int i = 0; i < methods.length; i++) { + method = methods[i]; + if (method == null) { + continue; } - catch (NoSuchMethodException exception) { - // continue search for a method with the specified count of parameters + + // make sure method signature matches. + Class params[] = FeatureDescriptor.getParameterTypes(start, method); + if (method.getName().equals(methodName) && + params.length == argCount) { + if (args != null) { + boolean different = false; + if (argCount > 0) { + for (int j = 0; j < argCount; j++) { + if (params[j] != args[j]) { + different = true; + continue; + } + } + if (different) { + continue; + } + } + } + return method; } } } - return null; + method = null; + + // Now check any inherited interfaces. This is necessary both when + // the argument class is itself an interface, and when the argument + // class is an abstract class. + Class ifcs[] = start.getInterfaces(); + for (int i = 0 ; i < ifcs.length; i++) { + // Note: The original implementation had both methods calling + // the 3 arg method. This is preserved but perhaps it should + // pass the args array instead of null. + method = internalFindMethod(ifcs[i], methodName, argCount, null); + if (method != null) { + break; + } + } + return method; } - static Method findInstanceMethod(Class type, String name, Class... args) { - try { - return MethodFinder.findInstanceMethod(type, name, args); - } - catch (NoSuchMethodException exception) { + /** + * Find a target methodName on a given class. + */ + static Method findMethod(Class cls, String methodName, int argCount) { + return findMethod(cls, methodName, argCount, null); + } + + /** + * Find a target methodName with specific parameter list on a given class. + *

+ * Used in the contructors of the EventSetDescriptor, + * PropertyDescriptor and the IndexedPropertyDescriptor. + *

+ * @param cls The Class object on which to retrieve the method. + * @param methodName Name of the method. + * @param argCount Number of arguments for the desired method. + * @param args Array of argument types for the method. + * @return the method or null if not found + */ + static Method findMethod(Class cls, String methodName, int argCount, + Class args[]) { + if (methodName == null) { return null; } + return internalFindMethod(cls, methodName, argCount, args); } /** diff --git a/jdk/src/share/classes/java/beans/MethodDescriptor.java b/jdk/src/share/classes/java/beans/MethodDescriptor.java index 74a7a16782..d9e78be516 100644 --- a/jdk/src/share/classes/java/beans/MethodDescriptor.java +++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java @@ -90,13 +90,13 @@ public class MethodDescriptor extends FeatureDescriptor { // Find methods for up to 2 params. We are guessing here. // This block should never execute unless the classloader // that loaded the argument classes disappears. - method = Introspector.findMethod(cls, name, i); + method = Introspector.findMethod(cls, name, i, null); if (method != null) { break; } } } else { - method = Statement.getMethod(cls, name, params); + method = Introspector.findMethod(cls, name, params.length, params); } setMethod(method); } diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index c7524e3026..429d2b4079 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -112,7 +112,8 @@ public class PropertyDescriptor extends FeatureDescriptor { // If this class or one of its base classes allow PropertyChangeListener, // then we assume that any properties we discover are "bound". // See Introspector.getTargetPropertyInfo() method. - this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class); + Class[] args = { PropertyChangeListener.class }; + this.bound = null != Introspector.findMethod(beanClass, "addPropertyChangeListener", args.length, args); } /** @@ -223,10 +224,10 @@ public class PropertyDescriptor extends FeatureDescriptor { // property type is. For booleans, there can be "is" and "get" // methods. If an "is" method exists, this is the official // reader method so look for this one first. - readMethod = Introspector.findInstanceMethod(cls, readMethodName); + readMethod = Introspector.findMethod(cls, readMethodName, 0); if (readMethod == null) { readMethodName = Introspector.GET_PREFIX + getBaseName(); - readMethod = Introspector.findInstanceMethod(cls, readMethodName); + readMethod = Introspector.findMethod(cls, readMethodName, 0); } try { setReadMethod(readMethod); @@ -291,7 +292,8 @@ public class PropertyDescriptor extends FeatureDescriptor { writeMethodName = Introspector.SET_PREFIX + getBaseName(); } - writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type); + Class[] args = (type == null) ? null : new Class[] { type }; + writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args); if (writeMethod != null) { if (!writeMethod.getReturnType().equals(void.class)) { writeMethod = null; diff --git a/jdk/test/java/beans/Introspector/6976577/Test6976577.java b/jdk/test/java/beans/Introspector/6976577/Test6976577.java new file mode 100644 index 0000000000..61e1771231 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6976577/Test6976577.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010, 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 6976577 + * @summary Tests public methods in non-public beans + * @author Sergey Malenkov + */ + +import test.Accessor; + +import java.beans.EventSetDescriptor; +import java.beans.IndexedPropertyDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; + +public class Test6976577 { + + public static void main(String[] args) throws Exception { + Class bt = Accessor.getBeanType(); + Class lt = Accessor.getListenerType(); + + // test PropertyDescriptor + PropertyDescriptor pd = new PropertyDescriptor("boolean", bt); + test(pd.getReadMethod()); + test(pd.getWriteMethod()); + + // test IndexedPropertyDescriptor + IndexedPropertyDescriptor ipd = new IndexedPropertyDescriptor("indexed", bt); + test(ipd.getReadMethod()); + test(ipd.getWriteMethod()); + test(ipd.getIndexedReadMethod()); + test(ipd.getIndexedWriteMethod()); + + // test EventSetDescriptor + EventSetDescriptor esd = new EventSetDescriptor(bt, "test", lt, "process"); + test(esd.getAddListenerMethod()); + test(esd.getRemoveListenerMethod()); + test(esd.getGetListenerMethod()); + test(esd.getListenerMethods()); + } + + private static void test(Method... methods) { + for (Method method : methods) { + if (method == null) { + throw new Error("public method is not found"); + } + } + } +} diff --git a/jdk/test/java/beans/Introspector/6976577/test/Accessor.java b/jdk/test/java/beans/Introspector/6976577/test/Accessor.java new file mode 100644 index 0000000000..a7a7090bc1 --- /dev/null +++ b/jdk/test/java/beans/Introspector/6976577/test/Accessor.java @@ -0,0 +1,81 @@ +package test; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.EventListener; +import java.util.TooManyListenersException; + +public class Accessor { + + public static Class getBeanType() { + return Bean.class; + } + + public static Class getListenerType() { + return TestListener.class; + } +} + +interface TestEvent { +} + +interface TestListener extends EventListener { + void process(TestEvent event); +} + +class Bean { + + private boolean b; + private int[] indexed; + private TestListener listener; + private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public void addPropertyChangeListener(PropertyChangeListener listener) { + this.pcs.addPropertyChangeListener(listener); + } + + public void addTestListener(TestListener listener) throws TooManyListenersException { + if (listener != null) { + if (this.listener != null) { + throw new TooManyListenersException(); + } + this.listener = listener; + } + } + + public void removeTestListener(TestListener listener) { + if (this.listener == listener) { + this.listener = null; + } + } + + public TestListener[] getTestListeners() { + return (this.listener != null) + ? new TestListener[] { this.listener } + : new TestListener[0]; + } + + public boolean isBoolean() { + return this.b; + } + + public void setBoolean(boolean b) { + this.b = b; + } + + public int[] getIndexed() { + return this.indexed; + } + + public void setIndexed(int[] values) { + this.indexed = values; + } + + public int getIndexed(int index) { + return this.indexed[index]; + } + + public void setIndexed(int index, int value) { + this.indexed[index] = value; + } +} -- GitLab