Index: modules/beans/src/main/java/java/beans/Statement.java =================================================================== --- modules/beans/src/main/java/java/beans/Statement.java (revision 420328) +++ modules/beans/src/main/java/java/beans/Statement.java (working copy) @@ -28,7 +28,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.StringTokenizer; /** * @author Maxim V. Berkultsev @@ -36,7 +35,7 @@ */ public class Statement { - + private Object target; private String methodName; private Object[] arguments; @@ -119,7 +118,7 @@ public void execute() throws Exception { invokeMethod(); } - + Object invokeMethod() throws Exception { Object result = null; @@ -142,7 +141,7 @@ { if(target instanceof Class) { Constructor constructor = findConstructor(); - + result = constructor.newInstance(arguments); } else { // XXX should be investigated, dead code? @@ -151,12 +150,25 @@ result = constructor.newInstance(arguments); } } else if(target instanceof Class) { - Method method = findStaticMethod(); + Method method = null; - result = method.invoke(null, arguments); + try { + // try to look for static method at first + method = + findMethod((Class) target, methodName, arguments, true); + result = method.invoke(null, arguments); + } catch (NoSuchMethodException e) { + // static method was not found + // try to invoke non-static method of Class object + method = findMethod(target.getClass(), methodName, + arguments, false); + result = method.invoke(target, arguments); + } } else { - final Method method = findMethod(); - + final Method method = + findMethod(target.getClass(), methodName, arguments, + false); + AccessController.doPrivileged(new PrivilegedAction() { public Object run() { method.setAccessible(true); @@ -173,7 +185,7 @@ } return result; } - + private Method findArrayMethod() throws NoSuchMethodException { if(!methodName.equals("set") && !methodName.equals("get")) { throw new NoSuchMethodException("Unknown method name for array"); @@ -188,14 +200,14 @@ "First parameter in array getter(setter) is not of " + "Integer type"); } - + Class[] argClasses = methodName.equals("get") ? new Class[] { Object.class, int.class } : new Class[] { Object.class, int.class, Object.class }; return Array.class.getMethod(methodName, argClasses ); } - + private Object[] getArrayMethodArguments() { Object[] args = new Object[arguments.length + 1]; args[0] = target; @@ -204,9 +216,9 @@ } return args; } - + private Constructor findConstructor() throws NoSuchMethodException { - Class[] argClasses = getClasses(); + Class[] argClasses = getClasses(arguments); Class targetClass = (Class) target; Constructor result = null; @@ -228,7 +240,7 @@ boolean paramIsAssignable = argIsNull ? false : parameterTypes[j].isAssignableFrom( argClasses[j]); - + if(!argIsNull && !paramIsAssignable && !argIsPrimitiveWrapper || argIsNull && paramIsPrimitive) { @@ -243,114 +255,84 @@ } } } - + if(result == null) { throw new NoSuchMethodException( "No constructor for class " + targetClass.getName() + " found"); } - + return result; } - - private Method findStaticMethod() throws NoSuchMethodException { - Class[] argClasses = getClasses(); - Class targetClass = (Class) target; - + + /** + * Method lookup is performed initially in the current class + * then in superclass, then in super class of super class and so on. + */ + private static Method findMethod(Class targetClass, String methodName, + Object[] arguments, boolean methodIsStatic) + throws NoSuchMethodException + { + Class[] argClasses = getClasses(arguments); + Method result = null; - - Method[] methods = targetClass.getMethods(); - for(int i = 0; i < methods.length; ++i) { + Method[] methods = targetClass.getDeclaredMethods(); + + for (int i = 0; i < methods.length; ++i) { Method method = methods[i]; - if(!method.getName().equals(methodName) || !Modifier.isStatic( - method.getModifiers())) { - continue; - } - Class[] parameterTypes = method.getParameterTypes(); - if(parameterTypes.length == argClasses.length) { - boolean found = true; - - for(int j = 0; j < parameterTypes.length; ++j) { - boolean argIsNull = (argClasses[j] == null); - boolean argIsPrimitiveWrapper = isPrimitiveWrapper( - argClasses[j], parameterTypes[j]); - boolean paramIsPrimitive = parameterTypes[j].isPrimitive(); - boolean paramIsAssignable = argIsNull ? false - : parameterTypes[j].isAssignableFrom(argClasses[j]); - - if(!argIsNull && !paramIsAssignable - && !argIsPrimitiveWrapper - || argIsNull && paramIsPrimitive) { - found = false; - break; - } - } - - if(found) { - result = method; - break; - } - } - } - - if(result == null) { - throw new NoSuchMethodException("No method with name " + methodName - + " is found"); - } - - return result; - } - - private Method findMethod() throws NoSuchMethodException { - Class[] argClasses = getClasses(); - Class targetClass = target.getClass(); - - Method result = null; - - Method[] methods = targetClass.getMethods(); - for(int i = 0; i < methods.length; ++i) { - Method method = methods[i]; - - if(method.getName().equals(methodName)) { + int mods = method.getModifiers(); + + if (method.getName().equals(methodName) && + Modifier.isPublic(mods) && + (methodIsStatic ? Modifier.isStatic(mods) : true)) { + Class[] parameterTypes = method.getParameterTypes(); - - if(parameterTypes.length == argClasses.length) { + + if (parameterTypes.length == argClasses.length) { boolean found = true; - - for(int j = 0; j < parameterTypes.length; ++j) { - boolean argIsNull = argClasses[j] == null; - boolean argIsPrimitiveWrapper = isPrimitiveWrapper( + + for (int j = 0; j < parameterTypes.length; ++j) { + boolean argIsNull = (argClasses[j] == null); + boolean argIsPrimitiveWrapper = isPrimitiveWrapper( argClasses[j], parameterTypes[j]); boolean paramIsPrimitive = parameterTypes[j].isPrimitive(); boolean paramIsAssignable = argIsNull ? false : parameterTypes[j].isAssignableFrom( argClasses[j]); - - if(!argIsNull && !paramIsAssignable + + if (!argIsNull && !paramIsAssignable && !argIsPrimitiveWrapper || argIsNull && paramIsPrimitive) { found = false; break; } } - - if(found) { + + if (found) { result = method; break; } } } } - - if(result == null) { - throw new NoSuchMethodException("No method with name " + methodName - + " is found"); + + if (result == null) { + // let's look for this method in the super class + Class parent = targetClass.getSuperclass(); + + if (parent != null) { + result = findMethod(parent, methodName, arguments, + methodIsStatic); + } else { + throw new NoSuchMethodException("No method with name " + + methodName + " is found"); + } } - + return result; } - + private static boolean isPrimitiveWrapper(Class wrapper, Class base) { return (base == boolean.class) && (wrapper == Boolean.class) || @@ -362,7 +344,7 @@ (base == float.class) && (wrapper == Float.class) || (base == double.class) && (wrapper == Double.class); } - + static String convertClassName(Class type) { Class componentType = type.getComponentType(); Class resultType = (componentType == null) ? type : componentType; @@ -379,19 +361,20 @@ return result; } - - private Class[] getClasses() { + + private static Class[] getClasses(Object[] arguments) { Class[] result = new Class[arguments.length]; - for(int i = 0; i < arguments.length; ++i) { + + for (int i = 0; i < arguments.length; ++i) { result[i] = (arguments[i] == null) ? null : arguments[i].getClass(); } return result; } - + public boolean equals(Object o) { if(o instanceof Statement) { Statement s = (Statement) o; - + Object[] otherArguments = s.getArguments(); boolean argsEqual = (otherArguments.length == arguments.length); if(argsEqual) { @@ -402,14 +385,14 @@ } } } - + if(!argsEqual) { return false; } else { return (s.getTarget() == this.getTarget() && s.getMethodName().equals(this.getMethodName())); } - + } else { return false; } Index: modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/StatementTest.java =================================================================== --- modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/StatementTest.java (revision 420328) +++ modules/beans/src/test/java/org/apache/harmony/beans/tests/java/beans/StatementTest.java (working copy) @@ -19,8 +19,6 @@ import java.beans.DefaultPersistenceDelegate; import java.util.Arrays; import java.util.Vector; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import junit.framework.Test; import junit.framework.TestCase; @@ -588,7 +586,7 @@ * a method of the same signature as Class.forName(String), a static method * name "forName" and valid argument "string". */ - public void testExecute_AmbitiousStaticMethod() throws Exception { + public void testExecute_AmbiguousStaticMethod() throws Exception { Object[] arguments = new String[] { "test" }; Statement t = new Statement(MockObject.class, "forName", arguments); t.execute();