in src/main/java/org/apache/commons/jexl3/internal/Interpreter.java [1818:1891]
protected Object visit(final ASTConstructorNode node, final Object data) {
if (isCancelled()) {
throw new JexlException.Cancel(node);
}
// first child is class or class name
final Object target = node.jjtGetChild(0).jjtAccept(this, data);
// get the ctor args
final int argc = node.jjtGetNumChildren() - 1;
Object[] argv = new Object[argc];
for (int i = 0; i < argc; i++) {
argv[i] = node.jjtGetChild(i + 1).jjtAccept(this, data);
}
try {
final boolean cacheable = cache;
// attempt to reuse last funcall cached in volatile JexlNode.value
if (cacheable) {
final Object cached = node.jjtGetValue();
if (cached instanceof Funcall) {
final Object eval = ((Funcall) cached).tryInvoke(this, null, target, argv);
if (JexlEngine.TRY_FAILED != eval) {
return eval;
}
}
}
boolean narrow = false;
Funcall funcall = null;
JexlMethod ctor;
while (true) {
// try as stated
ctor = uberspect.getConstructor(target, argv);
if (ctor != null) {
if (cacheable && ctor.isCacheable()) {
funcall = new Funcall(ctor, narrow);
}
break;
}
// try with prepending context as first argument
final Object[] nargv = callArguments(context, narrow, argv);
ctor = uberspect.getConstructor(target, nargv);
if (ctor != null) {
if (cacheable && ctor.isCacheable()) {
funcall = new ContextualCtor(ctor, narrow);
}
argv = nargv;
break;
}
// if we did not find an exact method by name and we haven't tried yet,
// attempt to narrow the parameters and if this succeeds, try again in next loop
if (!narrow && arithmetic.narrowArguments(argv)) {
narrow = true;
continue;
}
// we are done trying
break;
}
// we have either evaluated and returned or might have found a ctor
if (ctor != null) {
final Object eval = ctor.invoke(target, argv);
// cache executor in volatile JexlNode.value
if (funcall != null) {
node.jjtSetValue(funcall);
}
return eval;
}
final String tstr = target != null ? target.toString() : "?";
return unsolvableMethod(node, tstr, argv);
} catch (final JexlException.Method xmethod) {
throw xmethod;
} catch (final Exception xany) {
final String tstr = target != null ? target.toString() : "?";
throw invocationException(node, tstr, xany);
}
}