243 lines
8.8 KiB
Java
243 lines
8.8 KiB
Java
package org.apache.commons.beanutils;
|
|
|
|
import java.beans.IntrospectionException;
|
|
import java.beans.PropertyDescriptor;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Modifier;
|
|
import java.security.AccessController;
|
|
import java.security.PrivilegedAction;
|
|
import java.util.Hashtable;
|
|
|
|
public class MappedPropertyDescriptor extends PropertyDescriptor {
|
|
private Class mappedPropertyType;
|
|
|
|
private Method mappedReadMethod;
|
|
|
|
private Method mappedWriteMethod;
|
|
|
|
private static final Class[] stringClassArray = new Class[] { String.class };
|
|
|
|
public MappedPropertyDescriptor(String propertyName, Class beanClass) throws IntrospectionException {
|
|
super(propertyName, (Method)null, (Method)null);
|
|
if (propertyName == null || propertyName.length() == 0)
|
|
throw new IntrospectionException("bad property name: " + propertyName + " on class: " + beanClass.getClass().getName());
|
|
setName(propertyName);
|
|
String base = capitalizePropertyName(propertyName);
|
|
try {
|
|
this.mappedReadMethod = findMethod(beanClass, "get" + base, 1, stringClassArray);
|
|
Class[] params = { String.class, this.mappedReadMethod.getReturnType() };
|
|
this.mappedWriteMethod = findMethod(beanClass, "set" + base, 2, params);
|
|
} catch (IntrospectionException e) {}
|
|
if (this.mappedReadMethod == null)
|
|
this.mappedWriteMethod = findMethod(beanClass, "set" + base, 2);
|
|
if (this.mappedReadMethod == null && this.mappedWriteMethod == null)
|
|
throw new IntrospectionException("Property '" + propertyName + "' not found on " + beanClass.getName());
|
|
findMappedPropertyType();
|
|
}
|
|
|
|
public MappedPropertyDescriptor(String propertyName, Class beanClass, String mappedGetterName, String mappedSetterName) throws IntrospectionException {
|
|
super(propertyName, (Method)null, (Method)null);
|
|
if (propertyName == null || propertyName.length() == 0)
|
|
throw new IntrospectionException("bad property name: " + propertyName);
|
|
setName(propertyName);
|
|
this.mappedReadMethod = findMethod(beanClass, mappedGetterName, 1, stringClassArray);
|
|
if (this.mappedReadMethod != null) {
|
|
Class[] params = { String.class, this.mappedReadMethod.getReturnType() };
|
|
this.mappedWriteMethod = findMethod(beanClass, mappedSetterName, 2, params);
|
|
} else {
|
|
this.mappedWriteMethod = findMethod(beanClass, mappedSetterName, 2);
|
|
}
|
|
findMappedPropertyType();
|
|
}
|
|
|
|
public MappedPropertyDescriptor(String propertyName, Method mappedGetter, Method mappedSetter) throws IntrospectionException {
|
|
super(propertyName, mappedGetter, mappedSetter);
|
|
if (propertyName == null || propertyName.length() == 0)
|
|
throw new IntrospectionException("bad property name: " + propertyName);
|
|
setName(propertyName);
|
|
this.mappedReadMethod = mappedGetter;
|
|
this.mappedWriteMethod = mappedSetter;
|
|
findMappedPropertyType();
|
|
}
|
|
|
|
public Class getMappedPropertyType() {
|
|
return this.mappedPropertyType;
|
|
}
|
|
|
|
public Method getMappedReadMethod() {
|
|
return this.mappedReadMethod;
|
|
}
|
|
|
|
public void setMappedReadMethod(Method mappedGetter) throws IntrospectionException {
|
|
this.mappedReadMethod = mappedGetter;
|
|
findMappedPropertyType();
|
|
}
|
|
|
|
public Method getMappedWriteMethod() {
|
|
return this.mappedWriteMethod;
|
|
}
|
|
|
|
public void setMappedWriteMethod(Method mappedSetter) throws IntrospectionException {
|
|
this.mappedWriteMethod = mappedSetter;
|
|
findMappedPropertyType();
|
|
}
|
|
|
|
private void findMappedPropertyType() throws IntrospectionException {
|
|
try {
|
|
this.mappedPropertyType = null;
|
|
if (this.mappedReadMethod != null) {
|
|
if ((this.mappedReadMethod.getParameterTypes()).length != 1)
|
|
throw new IntrospectionException("bad mapped read method arg count");
|
|
this.mappedPropertyType = this.mappedReadMethod.getReturnType();
|
|
if (this.mappedPropertyType == void.class)
|
|
throw new IntrospectionException("mapped read method " + this.mappedReadMethod.getName() + " returns void");
|
|
}
|
|
if (this.mappedWriteMethod != null) {
|
|
Class[] params = this.mappedWriteMethod.getParameterTypes();
|
|
if (params.length != 2)
|
|
throw new IntrospectionException("bad mapped write method arg count");
|
|
if (this.mappedPropertyType != null && this.mappedPropertyType != params[1])
|
|
throw new IntrospectionException("type mismatch between mapped read and write methods");
|
|
this.mappedPropertyType = params[1];
|
|
}
|
|
} catch (IntrospectionException ex) {
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
private static String capitalizePropertyName(String s) {
|
|
if (s.length() == 0)
|
|
return s;
|
|
char[] chars = s.toCharArray();
|
|
chars[0] = Character.toUpperCase(chars[0]);
|
|
return new String(chars);
|
|
}
|
|
|
|
private static Hashtable declaredMethodCache = new Hashtable();
|
|
|
|
private static synchronized Method[] getPublicDeclaredMethods(Class clz) {
|
|
Class fclz = clz;
|
|
Method[] result = (Method[])declaredMethodCache.get(fclz);
|
|
if (result != null)
|
|
return result;
|
|
result = AccessController.<Method[]>doPrivileged(new PrivilegedAction(fclz) {
|
|
private final Class val$fclz;
|
|
|
|
public Object run() {
|
|
return this.val$fclz.getDeclaredMethods();
|
|
}
|
|
});
|
|
for (int i = 0; i < result.length; i++) {
|
|
Method method = result[i];
|
|
int mods = method.getModifiers();
|
|
if (!Modifier.isPublic(mods))
|
|
result[i] = null;
|
|
}
|
|
declaredMethodCache.put(clz, result);
|
|
return result;
|
|
}
|
|
|
|
private static Method internalFindMethod(Class start, String methodName, int argCount) {
|
|
for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
|
|
Method[] methods = getPublicDeclaredMethods(cl);
|
|
for (int j = 0; j < methods.length; j++) {
|
|
Method method = methods[j];
|
|
if (method != null) {
|
|
int mods = method.getModifiers();
|
|
if (!Modifier.isStatic(mods))
|
|
if (method.getName().equals(methodName) && (method.getParameterTypes()).length == argCount)
|
|
return method;
|
|
}
|
|
}
|
|
}
|
|
Class[] ifcs = start.getInterfaces();
|
|
for (int i = 0; i < ifcs.length; i++) {
|
|
Method m = internalFindMethod(ifcs[i], methodName, argCount);
|
|
if (m != null)
|
|
return m;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static Method internalFindMethod(Class start, String methodName, int argCount, Class[] args) {
|
|
for (Class cl = start; cl != null; cl = cl.getSuperclass()) {
|
|
Method[] methods = getPublicDeclaredMethods(cl);
|
|
for (int j = 0; j < methods.length; j++) {
|
|
Method method = methods[j];
|
|
if (method == null)
|
|
continue;
|
|
int mods = method.getModifiers();
|
|
if (Modifier.isStatic(mods))
|
|
continue;
|
|
Class[] params = method.getParameterTypes();
|
|
if (method.getName().equals(methodName) && params.length == argCount) {
|
|
boolean different = false;
|
|
if (argCount > 0) {
|
|
for (int k = 0; k < argCount; k++) {
|
|
if (params[k] != args[k])
|
|
different = true;
|
|
}
|
|
if (different)
|
|
continue;
|
|
}
|
|
return method;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
Class[] ifcs = start.getInterfaces();
|
|
for (int i = 0; i < ifcs.length; i++) {
|
|
Method m = internalFindMethod(ifcs[i], methodName, argCount);
|
|
if (m != null)
|
|
return m;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
static Method findMethod(Class cls, String methodName, int argCount) throws IntrospectionException {
|
|
if (methodName == null)
|
|
return null;
|
|
Method m = internalFindMethod(cls, methodName, argCount);
|
|
if (m != null)
|
|
return m;
|
|
throw new IntrospectionException("No method \"" + methodName + "\" with " + argCount + " arg(s)");
|
|
}
|
|
|
|
static Method findMethod(Class cls, String methodName, int argCount, Class[] args) throws IntrospectionException {
|
|
if (methodName == null)
|
|
return null;
|
|
Method m = internalFindMethod(cls, methodName, argCount, args);
|
|
if (m != null)
|
|
return m;
|
|
throw new IntrospectionException("No method \"" + methodName + "\" with " + argCount + " arg(s) of matching types.");
|
|
}
|
|
|
|
static boolean isSubclass(Class a, Class b) {
|
|
if (a == b)
|
|
return true;
|
|
if (a == null || b == null)
|
|
return false;
|
|
for (Class x = a; x != null; x = x.getSuperclass()) {
|
|
if (x == b)
|
|
return true;
|
|
if (b.isInterface()) {
|
|
Class[] interfaces = x.getInterfaces();
|
|
for (int i = 0; i < interfaces.length; i++) {
|
|
if (isSubclass(interfaces[i], b))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean throwsException(Method method, Class exception) {
|
|
Class[] exs = method.getExceptionTypes();
|
|
for (int i = 0; i < exs.length; i++) {
|
|
if (exs[i] == exception)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|