# HG changeset patch # User malenkov # Date 1277193993 -14400 # Node ID 0e6f2837eeca4fa9ec0378a37200d4dbd7b9405c # Parent 2a390122edffa1b56cbd75967150748ec3b63041 6707234: Method returned by Introspector.internalFindMethod not necessarily most specific Reviewed-by: peterz diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java --- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Tue Jun 22 12:06:33 2010 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -118,7 +118,7 @@ * @throws NoSuchMethodException if method is not accessible or is not found * in specified superclass or interface */ - private static Method findAccessibleMethod(Method method) throws NoSuchMethodException { + public static Method findAccessibleMethod(Method method) throws NoSuchMethodException { Class> type = method.getDeclaringClass(); if (Modifier.isPublic(type.getModifiers())) { return method; diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/java/beans/EventSetDescriptor.java --- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java Tue Jun 22 12:06:33 2010 +0400 @@ -27,6 +27,7 @@ import java.lang.ref.Reference; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * An EventSetDescriptor describes a group of events that a given Java @@ -175,10 +176,8 @@ setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1)); // Be more forgiving of not finding the getListener method. - Method method = Introspector.findMethod(sourceClass, - getListenerMethodName, 0); - if (method != null) { - setGetListenerMethod(method); + if (getListenerMethodName != null) { + setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName)); } } @@ -188,7 +187,7 @@ return null; } Method method = Introspector.findMethod(cls, name, args); - if (method == null) { + if ((method == null) || Modifier.isStatic(method.getModifiers())) { throw new IntrospectionException("Method not found: " + name + " on class " + cls.getName()); } diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java Tue Jun 22 12:06:33 2010 +0400 @@ -189,16 +189,11 @@ indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); } } - - Class[] args = { int.class }; - - indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, - 1, args); + indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); if (indexedReadMethod == null) { // no "is" method, so look for a "get" method. indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); - indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, - 1, args); + indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); } setIndexedReadMethod0(indexedReadMethod); } @@ -270,8 +265,7 @@ if (indexedWriteMethodName == null) { indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName(); } - indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, - 2, (type == null) ? null : new Class[] { int.class, type }); + indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type); if (indexedWriteMethod != null) { if (!indexedWriteMethod.getReturnType().equals(void.class)) { indexedWriteMethod = null; diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/java/beans/Introspector.java --- a/jdk/src/share/classes/java/beans/Introspector.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/java/beans/Introspector.java Tue Jun 22 12:06:33 2010 +0400 @@ -28,6 +28,7 @@ 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; @@ -849,8 +850,8 @@ Method read = result.getReadMethod(); if (read == null && write != null) { - read = findMethod(result.getClass0(), - GET_PREFIX + NameGenerator.capitalize(result.getName()), 0); + read = findInstanceMethod(result.getClass0(), + GET_PREFIX + NameGenerator.capitalize(result.getName())); if (read != null) { try { result.setReadMethod(read); @@ -860,9 +861,9 @@ } } if (write == null && read != null) { - write = findMethod(result.getClass0(), - SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, - new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); + write = findInstanceMethod(result.getClass0(), + SET_PREFIX + NameGenerator.capitalize(result.getName()), + FeatureDescriptor.getReturnType(result.getClass0(), read)); if (write != null) { try { result.setWriteMethod(write); @@ -1286,90 +1287,27 @@ // Package private support methods. //====================================================================== - /** - * 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; + 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); } - - // 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; + catch (NoSuchMethodException exception) { + // continue search for a method with the specified count of parameters } } } - 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; + return null; } - /** - * 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) { + static Method findInstanceMethod(Class> type, String name, Class>... args) { + try { + return MethodFinder.findInstanceMethod(type, name, args); + } + catch (NoSuchMethodException exception) { return null; } - return internalFindMethod(cls, methodName, argCount, args); } /** diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/java/beans/MethodDescriptor.java --- a/jdk/src/share/classes/java/beans/MethodDescriptor.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java Tue Jun 22 12:06:33 2010 +0400 @@ -82,21 +82,21 @@ Method method = getMethod0(); if (method == null) { Class cls = getClass0(); - if (cls != null) { + String name = getName(); + if ((cls != null) && (name != null)) { Class[] params = getParams(); if (params == null) { for (int i = 0; i < 3; i++) { // 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, getName(), i, null); + method = Introspector.findMethod(cls, name, i); if (method != null) { break; } } } else { - method = Introspector.findMethod(cls, getName(), - params.length, params); + method = Statement.getMethod(cls, name, params); } setMethod(method); } diff -r 2a390122edff -r 0e6f2837eeca jdk/src/share/classes/java/beans/PropertyDescriptor.java --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java Tue Jun 15 21:32:59 2010 +0400 +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java Tue Jun 22 12:06:33 2010 +0400 @@ -112,9 +112,7 @@ // 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. - String name = "addPropertyChangeListener"; - Class[] args = {PropertyChangeListener.class}; - this.bound = (null != Introspector.findMethod(beanClass, name, args.length, args)); + this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class); } /** @@ -225,10 +223,10 @@ // 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.findMethod(cls, readMethodName, 0); + readMethod = Introspector.findInstanceMethod(cls, readMethodName); if (readMethod == null) { readMethodName = Introspector.GET_PREFIX + getBaseName(); - readMethod = Introspector.findMethod(cls, readMethodName, 0); + readMethod = Introspector.findInstanceMethod(cls, readMethodName); } try { setReadMethod(readMethod); @@ -293,8 +291,7 @@ writeMethodName = Introspector.SET_PREFIX + getBaseName(); } - writeMethod = Introspector.findMethod(cls, writeMethodName, 1, - (type == null) ? null : new Class[] { type }); + writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type); if (writeMethod != null) { if (!writeMethod.getReturnType().equals(void.class)) { writeMethod = null; diff -r 2a390122edff -r 0e6f2837eeca jdk/test/java/beans/Introspector/Test6707234.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/beans/Introspector/Test6707234.java Tue Jun 22 12:06:33 2010 +0400 @@ -0,0 +1,52 @@ +/* + * 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 6707234 + * @summary Tests setter in a complex bean + * @author Sergey Malenkov + */ + +public class Test6707234 { + public static void main(String[] args) { + if (null == BeanUtils.getPropertyDescriptor(C.class, "number").getWriteMethod()) { + throw new Error("no write method"); + } + } + + public interface I { + void setNumber(Object number); + Number getNumber(); + } + + public class C implements I { + public void setNumber(Object value) { + } + public void setNumber(Long value) { + } + public Long getNumber() { + return null; + } + } +}