📄 beanswrapper.java
字号:
String name = md.getName();
Object previous = classMap.get(name);
if(previous instanceof Method)
{
// Overloaded method - replace method with a method map
MethodMap methodMap = new MethodMap(name);
methodMap.addMethod((Method)previous);
methodMap.addMethod(publicMethod);
classMap.put(name, methodMap);
// remove parameter type information
getArgTypes(classMap).remove(previous);
}
else if(previous instanceof MethodMap)
{
// Already overloaded method - add new overload
((MethodMap)previous).addMethod(publicMethod);
}
else
{
// Simple method (this far)
classMap.put(name, publicMethod);
getArgTypes(classMap).put(publicMethod,
publicMethod.getParameterTypes());
}
}
}
}
return classMap;
}
catch(IntrospectionException e)
{
logger.warn("Couldn't properly perform introspection", e);
return new HashMap();
}
}
private static Map getArgTypes(Map classMap) {
Map argTypes = (Map)classMap.get(ARGTYPES);
if(argTypes == null) {
argTypes = new HashMap();
classMap.put(ARGTYPES, argTypes);
}
return argTypes;
}
static Class[] getArgTypes(Map classMap, AccessibleObject methodOrCtor) {
return (Class[])((Map)classMap.get(ARGTYPES)).get(methodOrCtor);
}
private static Method getAccessibleMethod(Method m, Map accessibles)
{
return m == null ? null : (Method)accessibles.get(new MethodSignature(m));
}
boolean isSafeMethod(Method method)
{
return exposureLevel < EXPOSE_SAFE || !UNSAFE_METHODS.contains(method);
}
/**
* Retrieves mapping of methods to accessible methods for a class.
* In case the class is not public, retrieves methods with same
* signature as its public methods from public superclasses and
* interfaces (if they exist). Basically upcasts every method to the
* nearest accessible method.
*/
private static Map discoverAccessibleMethods(Class clazz)
{
Map map = new HashMap();
discoverAccessibleMethods(clazz, map);
return map;
}
private static void discoverAccessibleMethods(Class clazz, Map map)
{
if(Modifier.isPublic(clazz.getModifiers()))
{
try
{
Method[] methods = clazz.getMethods();
for(int i = 0; i < methods.length; i++)
{
Method method = methods[i];
MethodSignature sig = new MethodSignature(method);
map.put(sig, method);
}
return;
}
catch(SecurityException e)
{
logger.warn("Could not discover accessible methods of class " +
clazz.getName() +
", attemping superclasses/interfaces.", e);
// Fall through and attempt to discover superclass/interface
// methods
}
}
Class[] interfaces = clazz.getInterfaces();
for(int i = 0; i < interfaces.length; i++)
{
discoverAccessibleMethods(interfaces[i], map);
}
Class superclass = clazz.getSuperclass();
if(superclass != null)
{
discoverAccessibleMethods(superclass, map);
}
}
private static final class MethodSignature
{
private static final MethodSignature GET_STRING_SIGNATURE =
new MethodSignature("get", new Class[] { STRING_CLASS });
private static final MethodSignature GET_OBJECT_SIGNATURE =
new MethodSignature("get", new Class[] { OBJECT_CLASS });
private final String name;
private final Class[] args;
private MethodSignature(String name, Class[] args)
{
this.name = name;
this.args = args;
}
MethodSignature(Method method)
{
this(method.getName(), method.getParameterTypes());
}
public boolean equals(Object o)
{
if(o instanceof MethodSignature)
{
MethodSignature ms = (MethodSignature)o;
return ms.name.equals(name) && Arrays.equals(args, ms.args);
}
return false;
}
public int hashCode()
{
return name.hashCode() ^ args.length;
}
}
private static final Set createUnsafeMethodsSet()
{
Properties props = new Properties();
InputStream in = BeansWrapper.class.getResourceAsStream("unsafeMethods.txt");
if(in != null)
{
String methodSpec = null;
try
{
try
{
props.load(in);
}
finally
{
in.close();
}
Set set = new HashSet(props.size() * 4/3, .75f);
Map primClasses = createPrimitiveClassesMap();
for (Iterator iterator = props.keySet().iterator(); iterator.hasNext();)
{
methodSpec = (String) iterator.next();
try {
set.add(parseMethodSpec(methodSpec, primClasses));
}
catch(ClassNotFoundException e) {
if(DEVELOPMENT) {
throw e;
}
}
catch(NoSuchMethodException e) {
if(DEVELOPMENT) {
throw e;
}
}
}
}
catch(Exception e)
{
throw new RuntimeException("Could not load unsafe method " + methodSpec + " " + e.getClass().getName() + " " + e.getMessage());
}
}
return Collections.EMPTY_SET;
}
private static Method parseMethodSpec(String methodSpec, Map primClasses)
throws
ClassNotFoundException,
NoSuchMethodException
{
int brace = methodSpec.indexOf('(');
int dot = methodSpec.lastIndexOf('.', brace);
Class clazz = ClassUtil.forName(methodSpec.substring(0, dot));
String methodName = methodSpec.substring(dot + 1, brace);
String argSpec = methodSpec.substring(brace + 1, methodSpec.length() - 1);
StringTokenizer tok = new StringTokenizer(argSpec, ",");
int argcount = tok.countTokens();
Class[] argTypes = new Class[argcount];
for (int i = 0; i < argcount; i++)
{
String argClassName = tok.nextToken();
argTypes[i] = (Class)primClasses.get(argClassName);
if(argTypes[i] == null)
{
argTypes[i] = ClassUtil.forName(argClassName);
}
}
return clazz.getMethod(methodName, argTypes);
}
private static Map createPrimitiveClassesMap()
{
Map map = new HashMap();
map.put("boolean", Boolean.TYPE);
map.put("byte", Byte.TYPE);
map.put("char", Character.TYPE);
map.put("short", Short.TYPE);
map.put("int", Integer.TYPE);
map.put("long", Long.TYPE);
map.put("float", Float.TYPE);
map.put("double", Double.TYPE);
return map;
}
/**
* Converts any {@link BigDecimal}s in the passed array to the type of
* the corresponding formal argument of the method.
*/
public static void coerceBigDecimals(AccessibleObject callable, Object[] args)
{
Class[] formalTypes = null;
for(int i = 0, l = args.length; i < l; ++i)
{
Object arg = args[i];
if(arg instanceof BigDecimal)
{
BigDecimal bd = (BigDecimal)arg;
if(formalTypes == null)
{
if(callable instanceof Method) {
formalTypes = ((Method)callable).getParameterTypes();
}
else if(callable instanceof Constructor) {
formalTypes = ((Constructor)callable).getParameterTypes();
}
else {
// Cannot happen
throw new Error();
}
if(formalTypes.length != l)
{
// This will die anyway due to incorrect number of
// arguments, so there's no point in checking
return;
}
}
Class formalType = formalTypes[i];
// int is expected in most situations, so we check it first
if(formalType == Integer.TYPE || formalType == Integer.class)
{
args[i] = new Integer(bd.intValue());
}
else if(formalType == Double.TYPE || formalType == Double.class)
{
args[i] = new Double(bd.doubleValue());
}
else if(formalType == Long.TYPE || formalType == Long.class)
{
args[i] = new Long(bd.longValue());
}
else if(formalType == Float.TYPE || formalType == Float.class)
{
args[i] = new Float(bd.floatValue());
}
else if(formalType == Short.TYPE || formalType == Short.class)
{
args[i] = new Short(bd.shortValue());
}
else if(formalType == Byte.TYPE || formalType == Byte.class)
{
args[i] = new Byte(bd.byteValue());
}
else if(BIGINTEGER_CLASS.isAssignableFrom(formalType))
{
args[i] = bd.toBigInteger();
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -