Search in sources :

Example 1 with MethodNotFoundException

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);
}
Also used : HashMap(java.util.HashMap) Method(java.lang.reflect.Method) MethodNotFoundException(jakarta.el.MethodNotFoundException) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with MethodNotFoundException

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()));
    }
}
Also used : VariableMapper(jakarta.el.VariableMapper) ValueExpression(jakarta.el.ValueExpression) ELException(jakarta.el.ELException) MethodExpression(jakarta.el.MethodExpression) MethodNotFoundException(jakarta.el.MethodNotFoundException)

Example 3 with MethodNotFoundException

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);
    }
}
Also used : PropertyNotFoundException(jakarta.el.PropertyNotFoundException) MethodReference(jakarta.el.MethodReference) ELException(jakarta.el.ELException) MethodNotFoundException(jakarta.el.MethodNotFoundException)

Example 4 with MethodNotFoundException

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);
    }
}
Also used : PropertyNotFoundException(jakarta.el.PropertyNotFoundException) MethodInfo(jakarta.el.MethodInfo) ELException(jakarta.el.ELException) MethodNotFoundException(jakarta.el.MethodNotFoundException)

Aggregations

MethodNotFoundException (jakarta.el.MethodNotFoundException)4 ELException (jakarta.el.ELException)3 PropertyNotFoundException (jakarta.el.PropertyNotFoundException)2 MethodExpression (jakarta.el.MethodExpression)1 MethodInfo (jakarta.el.MethodInfo)1 MethodReference (jakarta.el.MethodReference)1 ValueExpression (jakarta.el.ValueExpression)1 VariableMapper (jakarta.el.VariableMapper)1 Method (java.lang.reflect.Method)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1