use of jakarta.el.MethodNotFoundException in project tomcat by apache.
the class ReflectionUtil method getMethod.
/**
* Returns a method based on the criteria.
* @param ctx the context in which the expression is being evaluated
* @param base the object that owns the method
* @param property the name of the method
* @param paramTypes the parameter types to use
* @param paramValues the parameter values
* @return the method specified
* @throws MethodNotFoundException If a method cannot be found that matches
* the given criteria
*/
/*
* This class duplicates code in jakarta.el.Util. When making changes keep
* the code in sync.
*/
@SuppressWarnings("null")
public static Method getMethod(EvaluationContext ctx, Object base, Object property, Class<?>[] paramTypes, Object[] paramValues) throws MethodNotFoundException {
if (base == null || property == null) {
throw new MethodNotFoundException(MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
}
String methodName = (property instanceof String) ? (String) property : property.toString();
int paramCount;
if (paramTypes == null) {
paramCount = 0;
} else {
paramCount = paramTypes.length;
}
Method[] methods = base.getClass().getMethods();
Map<Method, MatchResult> candidates = new HashMap<>();
for (Method m : methods) {
if (!m.getName().equals(methodName)) {
// Method name doesn't match
continue;
}
Class<?>[] mParamTypes = m.getParameterTypes();
int mParamCount = mParamTypes.length;
// Multiple tests to improve readability
if (!m.isVarArgs() && paramCount != mParamCount) {
// Method has wrong number of parameters
continue;
}
if (m.isVarArgs() && paramCount < mParamCount - 1) {
// Method has wrong number of parameters
continue;
}
if (m.isVarArgs() && paramCount == mParamCount && paramValues != null && paramValues.length > paramCount && !paramTypes[mParamCount - 1].isArray()) {
// Method arguments don't match
continue;
}
if (m.isVarArgs() && paramCount > mParamCount && paramValues != null && paramValues.length != paramCount) {
// Might match a different varargs method
continue;
}
if (!m.isVarArgs() && paramValues != null && paramCount != paramValues.length) {
// Might match a different varargs method
continue;
}
// Check the parameters match
int exactMatch = 0;
int assignableMatch = 0;
int coercibleMatch = 0;
int varArgsMatch = 0;
boolean noMatch = false;
for (int i = 0; i < mParamCount; i++) {
// Can't be null
if (m.isVarArgs() && i == (mParamCount - 1)) {
if (i == paramCount || (paramValues != null && paramValues.length == i)) {
// Var args defined but nothing is passed as varargs
// Use MAX_VALUE so this matches only if nothing else does
varArgsMatch = Integer.MAX_VALUE;
break;
}
Class<?> varType = mParamTypes[i].getComponentType();
for (int j = i; j < paramCount; j++) {
if (isAssignableFrom(paramTypes[j], varType)) {
assignableMatch++;
varArgsMatch++;
} else {
if (paramValues == null) {
noMatch = true;
break;
} else {
if (isCoercibleFrom(ctx, paramValues[j], varType)) {
coercibleMatch++;
varArgsMatch++;
} else {
noMatch = true;
break;
}
}
}
// Don't treat a varArgs match as an exact match, it can
// lead to a varArgs method matching when the result
// should be ambiguous
}
} else {
if (mParamTypes[i].equals(paramTypes[i])) {
exactMatch++;
} else if (paramTypes[i] != null && isAssignableFrom(paramTypes[i], mParamTypes[i])) {
assignableMatch++;
} else {
if (paramValues == null) {
noMatch = true;
break;
} else {
if (isCoercibleFrom(ctx, paramValues[i], mParamTypes[i])) {
coercibleMatch++;
} else {
noMatch = true;
break;
}
}
}
}
}
if (noMatch) {
continue;
}
// and no vars args are present, return it
if (exactMatch == paramCount && varArgsMatch == 0) {
return getMethod(base.getClass(), base, m);
}
candidates.put(m, new MatchResult(m.isVarArgs(), exactMatch, assignableMatch, coercibleMatch, varArgsMatch, m.isBridge()));
}
// Look for the method that has the highest number of parameters where
// the type matches exactly
MatchResult bestMatch = new MatchResult(true, 0, 0, 0, 0, true);
Method match = null;
boolean multiple = false;
for (Map.Entry<Method, MatchResult> entry : candidates.entrySet()) {
int cmp = entry.getValue().compareTo(bestMatch);
if (cmp > 0 || match == null) {
bestMatch = entry.getValue();
match = entry.getKey();
multiple = false;
} else if (cmp == 0) {
multiple = true;
}
}
if (multiple) {
if (bestMatch.getExactCount() == paramCount - 1) {
// Only one parameter is not an exact match - try using the
// super class
match = resolveAmbiguousMethod(candidates.keySet(), paramTypes);
} else {
match = null;
}
if (match == null) {
// the match is ambiguous so throw an exception
throw new MethodNotFoundException(MessageFactory.get("error.method.ambiguous", base, property, paramString(paramTypes)));
}
}
// Handle case where no match at all was found
if (match == null) {
throw new MethodNotFoundException(MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)));
}
return getMethod(base.getClass(), base, match);
}
use of jakarta.el.MethodNotFoundException in project tomcat by apache.
the class AstIdentifier method getMethodExpression.
private final MethodExpression getMethodExpression(EvaluationContext ctx) throws ELException {
Object obj = null;
// case A: ValueExpression exists, getValue which must
// be a MethodExpression
VariableMapper varMapper = ctx.getVariableMapper();
ValueExpression ve = null;
if (varMapper != null) {
ve = varMapper.resolveVariable(this.image);
if (ve != null) {
obj = ve.getValue(ctx);
}
}
// a MethodExpression to be able to invoke
if (ve == null) {
ctx.setPropertyResolved(false);
obj = ctx.getELResolver().getValue(ctx, null, this.image);
}
// finally provide helpful hints
if (obj instanceof MethodExpression) {
return (MethodExpression) obj;
} else if (obj == null) {
throw new MethodNotFoundException(MessageFactory.get("error.identifier.noMethod", this.image));
} else {
throw new ELException(MessageFactory.get("error.identifier.notMethodExpression", this.image, obj.getClass().getName()));
}
}
use of jakarta.el.MethodNotFoundException in project tomcat by apache.
the class JspMethodExpression method getMethodReference.
@Override
public MethodReference getMethodReference(ELContext context) {
context.notifyBeforeEvaluation(getExpressionString());
try {
MethodReference result = this.target.getMethodReference(context);
context.notifyAfterEvaluation(getExpressionString());
return result;
} catch (MethodNotFoundException e) {
if (e instanceof JspMethodNotFoundException) {
throw e;
}
throw new JspMethodNotFoundException(this.mark, e);
} catch (PropertyNotFoundException e) {
if (e instanceof JspPropertyNotFoundException) {
throw e;
}
throw new JspPropertyNotFoundException(this.mark, e);
} catch (ELException e) {
if (e instanceof JspELException) {
throw e;
}
throw new JspELException(this.mark, e);
}
}
use of jakarta.el.MethodNotFoundException in project tomcat by apache.
the class JspMethodExpression method getMethodInfo.
@Override
public MethodInfo getMethodInfo(ELContext context) throws NullPointerException, PropertyNotFoundException, MethodNotFoundException, ELException {
context.notifyBeforeEvaluation(getExpressionString());
try {
MethodInfo result = this.target.getMethodInfo(context);
context.notifyAfterEvaluation(getExpressionString());
return result;
} catch (MethodNotFoundException e) {
if (e instanceof JspMethodNotFoundException) {
throw e;
}
throw new JspMethodNotFoundException(this.mark, e);
} catch (PropertyNotFoundException e) {
if (e instanceof JspPropertyNotFoundException) {
throw e;
}
throw new JspPropertyNotFoundException(this.mark, e);
} catch (ELException e) {
if (e instanceof JspELException) {
throw e;
}
throw new JspELException(this.mark, e);
}
}
Aggregations