6788531: java.beans.Statement imposes excessive access control
Reviewed-by: peterz, rupashka
This commit is contained in:
parent
02e741f275
commit
d36d789593
@ -24,10 +24,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.sun.beans.finder;
|
package com.sun.beans.finder;
|
||||||
|
|
||||||
|
import com.sun.beans.TypeResolver;
|
||||||
import com.sun.beans.WeakCache;
|
import com.sun.beans.WeakCache;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This utility class provides {@code static} methods
|
* This utility class provides {@code static} methods
|
||||||
@ -122,30 +126,52 @@ public final class MethodFinder extends AbstractFinder<Method> {
|
|||||||
if (Modifier.isStatic(method.getModifiers())) {
|
if (Modifier.isStatic(method.getModifiers())) {
|
||||||
throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
|
throw new NoSuchMethodException("Method '" + method.getName() + "' is not accessible");
|
||||||
}
|
}
|
||||||
for (Class<?> face : type.getInterfaces()) {
|
for (Type generic : type.getGenericInterfaces()) {
|
||||||
try {
|
try {
|
||||||
return findAccessibleMethod(method, face);
|
return findAccessibleMethod(method, generic);
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException exception) {
|
catch (NoSuchMethodException exception) {
|
||||||
// try to find in superclass or another interface
|
// try to find in superclass or another interface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return findAccessibleMethod(method, type.getSuperclass());
|
return findAccessibleMethod(method, type.getGenericSuperclass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds method that accessible from specified class.
|
* Finds method that accessible from specified class.
|
||||||
*
|
*
|
||||||
* @param method object that represents found method
|
* @param method object that represents found method
|
||||||
* @param type class that is used to find accessible method
|
* @param generic generic type that is used to find accessible method
|
||||||
* @return object that represents accessible method
|
* @return object that represents accessible method
|
||||||
* @throws NoSuchMethodException if method is not accessible or is not found
|
* @throws NoSuchMethodException if method is not accessible or is not found
|
||||||
* in specified superclass or interface
|
* in specified superclass or interface
|
||||||
*/
|
*/
|
||||||
private static Method findAccessibleMethod(Method method, Class<?> type) throws NoSuchMethodException {
|
private static Method findAccessibleMethod(Method method, Type generic) throws NoSuchMethodException {
|
||||||
String name = method.getName();
|
String name = method.getName();
|
||||||
Class<?>[] params = method.getParameterTypes();
|
Class<?>[] params = method.getParameterTypes();
|
||||||
return findAccessibleMethod(type.getMethod(name, params));
|
if (generic instanceof Class) {
|
||||||
|
Class<?> type = (Class<?>) generic;
|
||||||
|
return findAccessibleMethod(type.getMethod(name, params));
|
||||||
|
}
|
||||||
|
if (generic instanceof ParameterizedType) {
|
||||||
|
ParameterizedType pt = (ParameterizedType) generic;
|
||||||
|
Class<?> type = (Class<?>) pt.getRawType();
|
||||||
|
for (Method m : type.getMethods()) {
|
||||||
|
if (m.getName().equals(name)) {
|
||||||
|
Class<?>[] pts = m.getParameterTypes();
|
||||||
|
if (pts.length == params.length) {
|
||||||
|
if (Arrays.equals(params, pts)) {
|
||||||
|
return findAccessibleMethod(m);
|
||||||
|
}
|
||||||
|
Type[] gpts = m.getGenericParameterTypes();
|
||||||
|
if (Arrays.equals(params, TypeResolver.erase(TypeResolver.resolve(pt, gpts)))) {
|
||||||
|
return findAccessibleMethod(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NoSuchMethodException("Method '" + name + "' is not accessible");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -385,16 +385,16 @@ public class EventHandler implements InvocationHandler {
|
|||||||
try {
|
try {
|
||||||
Method getter = null;
|
Method getter = null;
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
getter = ReflectionUtils.getMethod(target.getClass(),
|
getter = Statement.getMethod(target.getClass(),
|
||||||
"get" + NameGenerator.capitalize(first),
|
"get" + NameGenerator.capitalize(first),
|
||||||
new Class[]{});
|
new Class[]{});
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
getter = ReflectionUtils.getMethod(target.getClass(),
|
getter = Statement.getMethod(target.getClass(),
|
||||||
"is" + NameGenerator.capitalize(first),
|
"is" + NameGenerator.capitalize(first),
|
||||||
new Class[]{});
|
new Class[]{});
|
||||||
}
|
}
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
getter = ReflectionUtils.getMethod(target.getClass(), first, new Class[]{});
|
getter = Statement.getMethod(target.getClass(), first, new Class[]{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
@ -462,10 +462,10 @@ public class EventHandler implements InvocationHandler {
|
|||||||
target = applyGetters(target, action.substring(0, lastDot));
|
target = applyGetters(target, action.substring(0, lastDot));
|
||||||
action = action.substring(lastDot + 1);
|
action = action.substring(lastDot + 1);
|
||||||
}
|
}
|
||||||
Method targetMethod = ReflectionUtils.getMethod(
|
Method targetMethod = Statement.getMethod(
|
||||||
target.getClass(), action, argTypes);
|
target.getClass(), action, argTypes);
|
||||||
if (targetMethod == null) {
|
if (targetMethod == null) {
|
||||||
targetMethod = ReflectionUtils.getMethod(target.getClass(),
|
targetMethod = Statement.getMethod(target.getClass(),
|
||||||
"set" + NameGenerator.capitalize(action), argTypes);
|
"set" + NameGenerator.capitalize(action), argTypes);
|
||||||
}
|
}
|
||||||
if (targetMethod == null) {
|
if (targetMethod == null) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -24,21 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package java.beans;
|
package java.beans;
|
||||||
|
|
||||||
import com.sun.beans.finder.PrimitiveWrapperMap;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
import java.lang.ref.Reference;
|
|
||||||
import java.lang.ref.SoftReference;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import sun.reflect.misc.MethodUtil;
|
|
||||||
import sun.reflect.misc.ConstructorUtil;
|
|
||||||
import sun.reflect.misc.ReflectUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class for reflectively finding methods, constuctors and fields
|
* A utility class for reflectively finding methods, constuctors and fields
|
||||||
@ -46,8 +32,6 @@ import sun.reflect.misc.ReflectUtil;
|
|||||||
*/
|
*/
|
||||||
class ReflectionUtils {
|
class ReflectionUtils {
|
||||||
|
|
||||||
private static Reference methodCacheRef;
|
|
||||||
|
|
||||||
public static boolean isPrimitive(Class type) {
|
public static boolean isPrimitive(Class type) {
|
||||||
return primitiveTypeFor(type) != null;
|
return primitiveTypeFor(type) != null;
|
||||||
}
|
}
|
||||||
@ -65,346 +49,6 @@ class ReflectionUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests each element on the class arrays for assignability.
|
|
||||||
*
|
|
||||||
* @param argClasses arguments to be tested
|
|
||||||
* @param argTypes arguments from Method
|
|
||||||
* @return true if each class in argTypes is assignable from the
|
|
||||||
* corresponding class in argClasses.
|
|
||||||
*/
|
|
||||||
private static boolean matchArguments(Class[] argClasses, Class[] argTypes) {
|
|
||||||
return matchArguments(argClasses, argTypes, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests each element on the class arrays for equality.
|
|
||||||
*
|
|
||||||
* @param argClasses arguments to be tested
|
|
||||||
* @param argTypes arguments from Method
|
|
||||||
* @return true if each class in argTypes is equal to the
|
|
||||||
* corresponding class in argClasses.
|
|
||||||
*/
|
|
||||||
private static boolean matchExplicitArguments(Class[] argClasses, Class[] argTypes) {
|
|
||||||
return matchArguments(argClasses, argTypes, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean matchArguments(Class[] argClasses,
|
|
||||||
Class[] argTypes, boolean explicit) {
|
|
||||||
|
|
||||||
boolean match = (argClasses.length == argTypes.length);
|
|
||||||
for(int j = 0; j < argClasses.length && match; j++) {
|
|
||||||
Class argType = argTypes[j];
|
|
||||||
if (argType.isPrimitive()) {
|
|
||||||
argType = PrimitiveWrapperMap.getType(argType.getName());
|
|
||||||
}
|
|
||||||
if (explicit) {
|
|
||||||
// Test each element for equality
|
|
||||||
if (argClasses[j] != argType) {
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Consider null an instance of all classes.
|
|
||||||
if (argClasses[j] != null &&
|
|
||||||
!(argType.isAssignableFrom(argClasses[j]))) {
|
|
||||||
match = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the method which best matches the signature or throw an exception
|
|
||||||
* if it can't be found or the method is ambiguous.
|
|
||||||
*/
|
|
||||||
static Method getPublicMethod(Class declaringClass, String methodName,
|
|
||||||
Class[] argClasses) throws NoSuchMethodException {
|
|
||||||
Method m;
|
|
||||||
|
|
||||||
m = findPublicMethod(declaringClass, methodName, argClasses);
|
|
||||||
if (m == null)
|
|
||||||
throw new NoSuchMethodException(declaringClass.getName() + "." + methodName);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the method which best matches the signature or null if it cant be found or
|
|
||||||
* the method is ambiguous.
|
|
||||||
*/
|
|
||||||
public static Method findPublicMethod(Class declaringClass, String methodName,
|
|
||||||
Class[] argClasses) {
|
|
||||||
// Many methods are "getters" which take no arguments.
|
|
||||||
// This permits the following optimisation which
|
|
||||||
// avoids the expensive call to getMethods().
|
|
||||||
if (argClasses.length == 0) {
|
|
||||||
try {
|
|
||||||
return MethodUtil.getMethod(declaringClass, methodName, argClasses);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException e) {
|
|
||||||
return null;
|
|
||||||
} catch (SecurityException se) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Method[] methods = MethodUtil.getPublicMethods(declaringClass);
|
|
||||||
List list = new ArrayList();
|
|
||||||
for(int i = 0; i < methods.length; i++) {
|
|
||||||
// Collect all the methods which match the signature.
|
|
||||||
Method method = methods[i];
|
|
||||||
if (method.getName().equals(methodName)) {
|
|
||||||
if (matchArguments(argClasses, method.getParameterTypes())) {
|
|
||||||
list.add(method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (list.size() > 0) {
|
|
||||||
if (list.size() == 1) {
|
|
||||||
return (Method)list.get(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ListIterator iterator = list.listIterator();
|
|
||||||
Method method;
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
method = (Method)iterator.next();
|
|
||||||
if (matchExplicitArguments(argClasses, method.getParameterTypes())) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// There are more than one method which matches this signature.
|
|
||||||
// try to return the most specific method.
|
|
||||||
return getMostSpecificMethod(list, argClasses);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the most specific method from the list of methods which
|
|
||||||
* matches the args. The most specific method will have the most
|
|
||||||
* number of equal parameters or will be closest in the inheritance
|
|
||||||
* heirarchy to the runtime execution arguments.
|
|
||||||
* <p>
|
|
||||||
* See the JLS section 15.12
|
|
||||||
* http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#20448
|
|
||||||
*
|
|
||||||
* @param methods List of methods which already have the same param length
|
|
||||||
* and arg types are assignable to param types
|
|
||||||
* @param args an array of param types to match
|
|
||||||
* @return method or null if a specific method cannot be determined
|
|
||||||
*/
|
|
||||||
private static Method getMostSpecificMethod(List methods, Class[] args) {
|
|
||||||
Method method = null;
|
|
||||||
|
|
||||||
int matches = 0;
|
|
||||||
int lastMatch = matches;
|
|
||||||
|
|
||||||
ListIterator iterator = methods.listIterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Method m = (Method)iterator.next();
|
|
||||||
Class[] mArgs = m.getParameterTypes();
|
|
||||||
matches = 0;
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
Class mArg = mArgs[i];
|
|
||||||
if (mArg.isPrimitive()) {
|
|
||||||
mArg = PrimitiveWrapperMap.getType(mArg.getName());
|
|
||||||
}
|
|
||||||
if (args[i] == mArg) {
|
|
||||||
matches++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matches == 0 && lastMatch == 0) {
|
|
||||||
if (method == null) {
|
|
||||||
method = m;
|
|
||||||
} else {
|
|
||||||
// Test existing method. We already know that the args can
|
|
||||||
// be assigned to all the method params. However, if the
|
|
||||||
// current method parameters is higher in the inheritance
|
|
||||||
// hierarchy then replace it.
|
|
||||||
if (!matchArguments(method.getParameterTypes(),
|
|
||||||
m.getParameterTypes())) {
|
|
||||||
method = m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (matches > lastMatch) {
|
|
||||||
lastMatch = matches;
|
|
||||||
method = m;
|
|
||||||
} else if (matches == lastMatch) {
|
|
||||||
// ambiguous method selection.
|
|
||||||
method = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the method or null if it can't be found or is ambiguous.
|
|
||||||
*/
|
|
||||||
public static Method findMethod(Class targetClass, String methodName,
|
|
||||||
Class[] argClasses) {
|
|
||||||
Method m = findPublicMethod(targetClass, methodName, argClasses);
|
|
||||||
if (m != null && Modifier.isPublic(m.getDeclaringClass().getModifiers())) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Search the interfaces for a public version of this method.
|
|
||||||
|
|
||||||
Example: the getKeymap() method of a JTextField
|
|
||||||
returns a package private implementation of the
|
|
||||||
of the public Keymap interface. In the Keymap
|
|
||||||
interface there are a number of "properties" one
|
|
||||||
being the "resolveParent" property implied by the
|
|
||||||
getResolveParent() method. This getResolveParent()
|
|
||||||
cannot be called reflectively because the class
|
|
||||||
itself is not public. Instead we search the class's
|
|
||||||
interfaces and find the getResolveParent()
|
|
||||||
method of the Keymap interface - on which invoke
|
|
||||||
may be applied without error.
|
|
||||||
|
|
||||||
So in :-
|
|
||||||
|
|
||||||
JTextField o = new JTextField("Hello, world");
|
|
||||||
Keymap km = o.getKeymap();
|
|
||||||
Method m1 = km.getClass().getMethod("getResolveParent", new Class[0]);
|
|
||||||
Method m2 = Keymap.class.getMethod("getResolveParent", new Class[0]);
|
|
||||||
|
|
||||||
Methods m1 and m2 are different. The invocation of method
|
|
||||||
m1 unconditionally throws an IllegalAccessException where
|
|
||||||
the invocation of m2 will invoke the implementation of the
|
|
||||||
method. Note that (ignoring the overloading of arguments)
|
|
||||||
there is only one implementation of the named method which
|
|
||||||
may be applied to this target.
|
|
||||||
*/
|
|
||||||
for(Class type = targetClass; type != null; type = type.getSuperclass()) {
|
|
||||||
Class[] interfaces = type.getInterfaces();
|
|
||||||
for(int i = 0; i < interfaces.length; i++) {
|
|
||||||
m = findPublicMethod(interfaces[i], methodName, argClasses);
|
|
||||||
if (m != null) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class that represents the unique elements of a method that will be a
|
|
||||||
* key in the method cache.
|
|
||||||
*/
|
|
||||||
private static class Signature {
|
|
||||||
private Class targetClass;
|
|
||||||
private String methodName;
|
|
||||||
private Class[] argClasses;
|
|
||||||
|
|
||||||
private volatile int hashCode = 0;
|
|
||||||
|
|
||||||
public Signature(Class targetClass, String methodName, Class[] argClasses) {
|
|
||||||
this.targetClass = targetClass;
|
|
||||||
this.methodName = methodName;
|
|
||||||
this.argClasses = argClasses;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o2) {
|
|
||||||
if (this == o2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Signature that = (Signature)o2;
|
|
||||||
if (!(targetClass == that.targetClass)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(methodName.equals(that.methodName))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (argClasses.length != that.argClasses.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < argClasses.length; i++) {
|
|
||||||
if (!(argClasses[i] == that.argClasses[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash code computed using algorithm suggested in
|
|
||||||
* Effective Java, Item 8.
|
|
||||||
*/
|
|
||||||
public int hashCode() {
|
|
||||||
if (hashCode == 0) {
|
|
||||||
int result = 17;
|
|
||||||
result = 37 * result + targetClass.hashCode();
|
|
||||||
result = 37 * result + methodName.hashCode();
|
|
||||||
if (argClasses != null) {
|
|
||||||
for (int i = 0; i < argClasses.length; i++) {
|
|
||||||
result = 37 * result + ((argClasses[i] == null) ? 0 :
|
|
||||||
argClasses[i].hashCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hashCode = result;
|
|
||||||
}
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper to findMethod(), which will search or populate the method
|
|
||||||
* in a cache.
|
|
||||||
* @throws exception if the method is ambiguios.
|
|
||||||
*/
|
|
||||||
public static synchronized Method getMethod(Class targetClass,
|
|
||||||
String methodName,
|
|
||||||
Class[] argClasses) {
|
|
||||||
Object signature = new Signature(targetClass, methodName, argClasses);
|
|
||||||
|
|
||||||
Method method = null;
|
|
||||||
Map methodCache = null;
|
|
||||||
boolean cache = false;
|
|
||||||
if (ReflectUtil.isPackageAccessible(targetClass)) {
|
|
||||||
cache = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cache && methodCacheRef != null &&
|
|
||||||
(methodCache = (Map)methodCacheRef.get()) != null) {
|
|
||||||
method = (Method)methodCache.get(signature);
|
|
||||||
if (method != null) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
method = findMethod(targetClass, methodName, argClasses);
|
|
||||||
if (cache && method != null) {
|
|
||||||
if (methodCache == null) {
|
|
||||||
methodCache = new HashMap();
|
|
||||||
methodCacheRef = new SoftReference(methodCache);
|
|
||||||
}
|
|
||||||
methodCache.put(signature, method);
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a constructor on the class with the arguments.
|
|
||||||
*
|
|
||||||
* @throws exception if the method is ambiguios.
|
|
||||||
*/
|
|
||||||
public static Constructor getConstructor(Class cls, Class[] args) {
|
|
||||||
Constructor constructor = null;
|
|
||||||
|
|
||||||
// PENDING: Implement the resolutuion of ambiguities properly.
|
|
||||||
Constructor[] ctors = ConstructorUtil.getConstructors(cls);
|
|
||||||
for(int i = 0; i < ctors.length; i++) {
|
|
||||||
if (matchArguments(args, ctors[i].getParameterTypes())) {
|
|
||||||
constructor = ctors[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return constructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object getPrivateField(Object instance, Class cls, String name) {
|
|
||||||
return getPrivateField(instance, cls, name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of a private field.
|
* Returns the value of a private field.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -31,6 +31,8 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import com.sun.beans.finder.ClassFinder;
|
import com.sun.beans.finder.ClassFinder;
|
||||||
|
import com.sun.beans.finder.ConstructorFinder;
|
||||||
|
import com.sun.beans.finder.MethodFinder;
|
||||||
import sun.reflect.misc.MethodUtil;
|
import sun.reflect.misc.MethodUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,13 +197,18 @@ public class Statement {
|
|||||||
argClasses[0] == String.class) {
|
argClasses[0] == String.class) {
|
||||||
return new Character(((String)arguments[0]).charAt(0));
|
return new Character(((String)arguments[0]).charAt(0));
|
||||||
}
|
}
|
||||||
m = ReflectionUtils.getConstructor((Class)target, argClasses);
|
try {
|
||||||
|
m = ConstructorFinder.findConstructor((Class)target, argClasses);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException exception) {
|
||||||
|
m = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m == null && target != Class.class) {
|
if (m == null && target != Class.class) {
|
||||||
m = ReflectionUtils.getMethod((Class)target, methodName, argClasses);
|
m = getMethod((Class)target, methodName, argClasses);
|
||||||
}
|
}
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
m = ReflectionUtils.getMethod(Class.class, methodName, argClasses);
|
m = getMethod(Class.class, methodName, argClasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -224,7 +231,7 @@ public class Statement {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m = ReflectionUtils.getMethod(target.getClass(), methodName, argClasses);
|
m = getMethod(target.getClass(), methodName, argClasses);
|
||||||
}
|
}
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
try {
|
try {
|
||||||
@ -289,4 +296,13 @@ public class Statement {
|
|||||||
result.append(");");
|
result.append(");");
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Method getMethod(Class<?> type, String name, Class<?>... args) {
|
||||||
|
try {
|
||||||
|
return MethodFinder.findMethod(type, name, args);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException exception) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
66
jdk/test/java/beans/EventHandler/Test6788531.java
Normal file
66
jdk/test/java/beans/EventHandler/Test6788531.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6788531
|
||||||
|
* @summary Tests public method lookup problem in EventHandler
|
||||||
|
* @author Sergey Malenkov
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.beans.EventHandler;
|
||||||
|
|
||||||
|
public class Test6788531 {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
JButton button = new JButton("hi");
|
||||||
|
button.addActionListener(EventHandler.create(ActionListener.class, new Private(), "run"));
|
||||||
|
button.addActionListener(EventHandler.create(ActionListener.class, new PrivateGeneric(), "run", "generic"));
|
||||||
|
button.doClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Public {
|
||||||
|
public void run() {
|
||||||
|
throw new Error("method is overridden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Private extends Public {
|
||||||
|
public void run() {
|
||||||
|
System.out.println("default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PublicGeneric<T> {
|
||||||
|
public void run(T object) {
|
||||||
|
throw new Error("method is overridden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PrivateGeneric extends PublicGeneric<String> {
|
||||||
|
public void run(String string) {
|
||||||
|
System.out.println(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
62
jdk/test/java/beans/Statement/Test6788531.java
Normal file
62
jdk/test/java/beans/Statement/Test6788531.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6788531
|
||||||
|
* @summary Tests public method lookup problem in Statement
|
||||||
|
* @author Sergey Malenkov
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.beans.Statement;
|
||||||
|
|
||||||
|
public class Test6788531 {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new Statement(new Private(), "run", null).execute();
|
||||||
|
new Statement(new PrivateGeneric(), "run", new Object[] {"generic"}).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Public {
|
||||||
|
public void run() {
|
||||||
|
throw new Error("method is overridden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Private extends Public {
|
||||||
|
public void run() {
|
||||||
|
System.out.println("default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PublicGeneric<T> {
|
||||||
|
public void run(T object) {
|
||||||
|
throw new Error("method is overridden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PrivateGeneric extends PublicGeneric<String> {
|
||||||
|
public void run(String string) {
|
||||||
|
System.out.println(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user