in src/main/java/org/apache/commons/jexl3/internal/InterpreterBase.java [971:1023]
protected Object getAttribute(final Object object, final Object attribute, final JexlNode node) {
if (object == null) {
throw new JexlException(node, "object is null");
}
cancelCheck(node);
final JexlOperator operator = node != null && node.jjtGetParent() instanceof ASTArrayAccess
? JexlOperator.ARRAY_GET : JexlOperator.PROPERTY_GET;
final Object result = operators.tryOverload(node, operator, object, attribute);
if (result != JexlEngine.TRY_FAILED) {
return result;
}
Exception xcause = null;
try {
// attempt to reuse last executor cached in volatile JexlNode.value
if (node != null && cache) {
final Object cached = node.jjtGetValue();
if (cached instanceof JexlPropertyGet) {
final JexlPropertyGet vg = (JexlPropertyGet) cached;
final Object value = vg.tryInvoke(object, attribute);
if (!vg.tryFailed(value)) {
return value;
}
}
}
// resolve that property
final List<JexlUberspect.PropertyResolver> resolvers = uberspect.getResolvers(operator, object);
final JexlPropertyGet vg = uberspect.getPropertyGet(resolvers, object, attribute);
if (vg != null) {
final Object value = vg.invoke(object);
// cache executor in volatile JexlNode.value
if (node != null && cache && vg.isCacheable()) {
node.jjtSetValue(vg);
}
return value;
}
} catch (final Exception xany) {
xcause = xany;
}
// lets fail
if (node == null) {
// direct call
final String error = "unable to get object property"
+ ", class: " + object.getClass().getName()
+ ", property: " + attribute;
throw new UnsupportedOperationException(error, xcause);
}
final boolean safe = (node instanceof ASTIdentifierAccess) && ((ASTIdentifierAccess) node).isSafe();
if (safe) {
return null;
}
final String attrStr = attribute != null ? attribute.toString() : null;
return unsolvableProperty(node, attrStr, true, xcause);
}