return false;
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
if (target == null) {
throw new AccessException("Cannot read property of null target");
}
Class<?> type = (target instanceof Class ? (Class<?>) target : target.getClass());
if (type.isArray() && name.equals("length")) {
if (target instanceof Class) {
throw new AccessException("Cannot access length on array class itself");
}
return new TypedValue(Array.getLength(target),TypeDescriptor.valueOf(Integer.TYPE));
}
if (this.readerCache==null) {
this.readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>();
}
CacheKey cacheKey = new CacheKey(type, name);
InvokerPair invoker = this.readerCache.get(cacheKey);
if (invoker == null || invoker.member instanceof Method) {
Method method = (Method) (invoker==null?null:invoker.member);
if (method == null) {
method = findGetterForProperty(name, type, target instanceof Class);
if (method != null) {
// TODO remove the duplication here between canRead and read
// Treat it like a property
PropertyDescriptor propertyDescriptor = null;
try {
// The readerCache will only contain gettable properties (let's not worry about setters for now)
propertyDescriptor = new PropertyDescriptor(name,method,null);
} catch (IntrospectionException ex) {
throw new AccessException("Unable to access property '" + name + "' through getter "+method, ex);
}
TypeDescriptor typeDescriptor = new BeanTypeDescriptor(propertyDescriptor, new MethodParameter(method,-1), method.getReturnType());
invoker = new InvokerPair(method,typeDescriptor);
this.readerCache.put(cacheKey, invoker);
}
}
if (method != null) {
try {
ReflectionUtils.makeAccessible(method);
return new TypedValue(method.invoke(target),invoker.typeDescriptor);
}
catch (Exception ex) {
throw new AccessException("Unable to access property '" + name + "' through getter", ex);
}
}
}
if (invoker == null || invoker.member instanceof Field) {
Field field = (Field) (invoker==null?null:invoker.member);
if (field == null) {
field = findField(name, type, target instanceof Class);
if (field != null) {
invoker = new InvokerPair(field, new TypeDescriptor(field));
this.readerCache.put(cacheKey, invoker);
}
}
if (field != null) {
try {
ReflectionUtils.makeAccessible(field);
return new TypedValue(field.get(target),invoker.typeDescriptor);
}
catch (Exception ex) {
throw new AccessException("Unable to access field: " + name, ex);
}
}
}
throw new AccessException("Neither getter nor field found for property '" + name + "'");
}