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
try {
// The readerCache will only contain gettable properties (let's not worry about setters for now)
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, method, null);
TypeDescriptor typeDescriptor =
new PropertyTypeDescriptor(propertyDescriptor, new MethodParameter(method, -1));
invoker = new InvokerPair(method, typeDescriptor);
this.readerCache.put(cacheKey, invoker);
}
catch (IntrospectionException ex) {
throw new AccessException(
"Unable to access property '" + name + "' through getter " + method, ex);
}
}
}
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 + "'");
}