Search in sources :

Example 1 with LambdaExpression

use of jakarta.el.LambdaExpression in project tomcat by apache.

the class AstFunction method getValue.

@Override
public Object getValue(EvaluationContext ctx) throws ELException {
    FunctionMapper fnMapper = ctx.getFunctionMapper();
    // quickly validate again for this request
    if (fnMapper == null) {
        throw new ELException(MessageFactory.get("error.fnMapper.null"));
    }
    Method m = fnMapper.resolveFunction(this.prefix, this.localName);
    if (m == null && this.prefix.length() == 0) {
        // TODO: Do we need to think about precedence of the various ways
        // a lambda expression may be obtained from something that
        // the parser thinks is a function?
        Object obj = null;
        if (ctx.isLambdaArgument(this.localName)) {
            obj = ctx.getLambdaArgument(this.localName);
        }
        if (obj == null) {
            VariableMapper varMapper = ctx.getVariableMapper();
            if (varMapper != null) {
                obj = varMapper.resolveVariable(this.localName);
                if (obj instanceof ValueExpression) {
                    // See if this returns a LambdaExpression
                    obj = ((ValueExpression) obj).getValue(ctx);
                }
            }
        }
        if (obj == null) {
            obj = ctx.getELResolver().getValue(ctx, null, this.localName);
        }
        if (obj instanceof LambdaExpression) {
            // Build arguments
            int i = 0;
            while (obj instanceof LambdaExpression && i < jjtGetNumChildren()) {
                Node args = jjtGetChild(i);
                obj = ((LambdaExpression) obj).invoke(((AstMethodParameters) args).getParameters(ctx));
                i++;
            }
            if (i < jjtGetNumChildren()) {
                // there were too many sets of parameters
                throw new ELException(MessageFactory.get("error.lambda.tooManyMethodParameterSets"));
            }
            return obj;
        }
        // Call to a constructor or a static method
        obj = ctx.getImportHandler().resolveClass(this.localName);
        if (obj != null) {
            return ctx.getELResolver().invoke(ctx, new ELClass((Class<?>) obj), "<init>", null, ((AstMethodParameters) this.children[0]).getParameters(ctx));
        }
        obj = ctx.getImportHandler().resolveStatic(this.localName);
        if (obj != null) {
            return ctx.getELResolver().invoke(ctx, new ELClass((Class<?>) obj), this.localName, null, ((AstMethodParameters) this.children[0]).getParameters(ctx));
        }
    }
    if (m == null) {
        throw new ELException(MessageFactory.get("error.fnMapper.method", this.getOutputName()));
    }
    // single set of method parameters
    if (this.jjtGetNumChildren() != 1) {
        throw new ELException(MessageFactory.get("error.function.tooManyMethodParameterSets", getOutputName()));
    }
    Node parameters = jjtGetChild(0);
    Class<?>[] paramTypes = m.getParameterTypes();
    Object[] params = null;
    Object result = null;
    int inputParameterCount = parameters.jjtGetNumChildren();
    int methodParameterCount = paramTypes.length;
    if (inputParameterCount == 0 && methodParameterCount == 1 && m.isVarArgs()) {
        params = new Object[] { null };
    } else if (inputParameterCount > 0) {
        params = new Object[methodParameterCount];
        try {
            for (int i = 0; i < methodParameterCount; i++) {
                if (m.isVarArgs() && i == methodParameterCount - 1) {
                    if (inputParameterCount < methodParameterCount) {
                        params[i] = new Object[] { null };
                    } else if (inputParameterCount == methodParameterCount && paramTypes[i].isArray()) {
                        params[i] = parameters.jjtGetChild(i).getValue(ctx);
                    } else {
                        Object[] varargs = new Object[inputParameterCount - methodParameterCount + 1];
                        Class<?> target = paramTypes[i].getComponentType();
                        for (int j = i; j < inputParameterCount; j++) {
                            varargs[j - i] = parameters.jjtGetChild(j).getValue(ctx);
                            varargs[j - i] = ELSupport.coerceToType(ctx, varargs[j - i], target);
                        }
                        params[i] = varargs;
                    }
                } else {
                    params[i] = parameters.jjtGetChild(i).getValue(ctx);
                }
                params[i] = ELSupport.coerceToType(ctx, params[i], paramTypes[i]);
            }
        } catch (ELException ele) {
            throw new ELException(MessageFactory.get("error.function", this.getOutputName()), ele);
        }
    }
    try {
        result = m.invoke(null, params);
    } catch (IllegalAccessException iae) {
        throw new ELException(MessageFactory.get("error.function", this.getOutputName()), iae);
    } catch (InvocationTargetException ite) {
        Throwable cause = ite.getCause();
        if (cause instanceof ThreadDeath) {
            throw (ThreadDeath) cause;
        }
        if (cause instanceof VirtualMachineError) {
            throw (VirtualMachineError) cause;
        }
        throw new ELException(MessageFactory.get("error.function", this.getOutputName()), cause);
    }
    return result;
}
Also used : VariableMapper(jakarta.el.VariableMapper) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException) ELClass(jakarta.el.ELClass) ValueExpression(jakarta.el.ValueExpression) ELClass(jakarta.el.ELClass) ELException(jakarta.el.ELException) LambdaExpression(jakarta.el.LambdaExpression) FunctionMapper(jakarta.el.FunctionMapper)

Example 2 with LambdaExpression

use of jakarta.el.LambdaExpression in project tomcat by apache.

the class AstValue method getValue.

@Override
public Object getValue(EvaluationContext ctx) throws ELException {
    Object base = this.children[0].getValue(ctx);
    int propCount = this.jjtGetNumChildren();
    int i = 1;
    Object suffix = null;
    ELResolver resolver = ctx.getELResolver();
    while (base != null && i < propCount) {
        suffix = this.children[i].getValue(ctx);
        if (i + 1 < propCount && (this.children[i + 1] instanceof AstMethodParameters)) {
            AstMethodParameters mps = (AstMethodParameters) this.children[i + 1];
            if (base instanceof Optional && "orElseGet".equals(suffix) && mps.jjtGetNumChildren() == 1) {
                Node paramFoOptional = mps.jjtGetChild(0);
                if (!(paramFoOptional instanceof AstLambdaExpression || paramFoOptional instanceof LambdaExpression)) {
                    throw new ELException(MessageFactory.get("stream.optional.paramNotLambda", suffix));
                }
            }
            // This is a method
            Object[] paramValues = mps.getParameters(ctx);
            base = resolver.invoke(ctx, base, suffix, getTypesFromValues(paramValues), paramValues);
            i += 2;
        } else {
            // This is a property
            if (suffix == null) {
                return null;
            }
            ctx.setPropertyResolved(false);
            base = resolver.getValue(ctx, base, suffix);
            i++;
        }
    }
    if (!ctx.isPropertyResolved()) {
        throw new PropertyNotFoundException(MessageFactory.get("error.resolver.unhandled", base, suffix));
    }
    return base;
}
Also used : ELResolver(jakarta.el.ELResolver) PropertyNotFoundException(jakarta.el.PropertyNotFoundException) Optional(org.apache.el.stream.Optional) ELException(jakarta.el.ELException) LambdaExpression(jakarta.el.LambdaExpression)

Example 3 with LambdaExpression

use of jakarta.el.LambdaExpression in project tomcat by apache.

the class ELSupport method coerceToType.

public static final <T> T coerceToType(final ELContext ctx, final Object obj, final Class<T> type) throws ELException {
    if (ctx != null) {
        boolean originalIsPropertyResolved = ctx.isPropertyResolved();
        try {
            T result = ctx.getELResolver().convertToType(ctx, obj, type);
            if (ctx.isPropertyResolved()) {
                return result;
            }
        } finally {
            ctx.setPropertyResolved(originalIsPropertyResolved);
        }
    }
    if (type == null || Object.class.equals(type) || (obj != null && type.isAssignableFrom(obj.getClass()))) {
        @SuppressWarnings("unchecked") T result = (T) obj;
        return result;
    }
    if (!COERCE_TO_ZERO) {
        if (obj == null && !type.isPrimitive() && !String.class.isAssignableFrom(type)) {
            return null;
        }
    }
    if (String.class.equals(type)) {
        @SuppressWarnings("unchecked") T result = (T) coerceToString(ctx, obj);
        return result;
    }
    if (ELArithmetic.isNumberType(type)) {
        @SuppressWarnings("unchecked") T result = (T) coerceToNumber(ctx, obj, type);
        return result;
    }
    if (Character.class.equals(type) || Character.TYPE == type) {
        @SuppressWarnings("unchecked") T result = (T) coerceToCharacter(ctx, obj);
        return result;
    }
    if (Boolean.class.equals(type) || Boolean.TYPE == type) {
        @SuppressWarnings("unchecked") T result = (T) coerceToBoolean(ctx, obj, Boolean.TYPE == type);
        return result;
    }
    if (type.isEnum()) {
        @SuppressWarnings("unchecked") T result = (T) coerceToEnum(ctx, obj, type);
        return result;
    }
    // new to spec
    if (obj == null) {
        return null;
    }
    if (obj instanceof String) {
        String str = (String) obj;
        PropertyEditor editor = PropertyEditorManager.findEditor(type);
        if (editor == null) {
            if (str.isEmpty()) {
                return null;
            }
            throw new ELException(MessageFactory.get("error.convert", obj, obj.getClass(), type));
        } else {
            try {
                editor.setAsText(str);
                @SuppressWarnings("unchecked") T result = (T) editor.getValue();
                return result;
            } catch (RuntimeException e) {
                if (str.isEmpty()) {
                    return null;
                }
                throw new ELException(MessageFactory.get("error.convert", obj, obj.getClass(), type), e);
            }
        }
    }
    // for an empty map. The parser will always parse {} as an empty set.
    if (obj instanceof Set && type == Map.class && ((Set<?>) obj).isEmpty()) {
        @SuppressWarnings("unchecked") T result = (T) Collections.EMPTY_MAP;
        return result;
    }
    // Handle arrays
    if (type.isArray() && obj.getClass().isArray()) {
        @SuppressWarnings("unchecked") T result = (T) coerceToArray(ctx, obj, type);
        return result;
    }
    if (obj instanceof LambdaExpression && isFunctionalInterface(type)) {
        T result = coerceToFunctionalInterface(ctx, (LambdaExpression) obj, type);
        return result;
    }
    throw new ELException(MessageFactory.get("error.convert", obj, obj.getClass(), type));
}
Also used : Set(java.util.Set) PropertyEditor(java.beans.PropertyEditor) ELException(jakarta.el.ELException) LambdaExpression(jakarta.el.LambdaExpression)

Example 4 with LambdaExpression

use of jakarta.el.LambdaExpression in project tomcat by apache.

the class AstLambdaExpression method getValue.

@Override
public Object getValue(EvaluationContext ctx) throws ELException {
    // Correct evaluation requires knowledge of the whole set of nested
    // expressions, not just the current expression
    NestedState state = getNestedState();
    // Check that there are not more sets of parameters than there are
    // nested expressions.
    int methodParameterSetCount = jjtGetNumChildren() - 2;
    if (methodParameterSetCount > state.getNestingCount()) {
        throw new ELException(MessageFactory.get("error.lambda.tooManyMethodParameterSets"));
    }
    // First child is always parameters even if there aren't any
    AstLambdaParameters formalParametersNode = (AstLambdaParameters) children[0];
    Node[] formalParamNodes = formalParametersNode.children;
    // Second child is a value expression
    ValueExpressionImpl ve = new ValueExpressionImpl("", children[1], ctx.getFunctionMapper(), ctx.getVariableMapper(), null);
    // Build a LambdaExpression
    List<String> formalParameters = new ArrayList<>();
    if (formalParamNodes != null) {
        for (Node formalParamNode : formalParamNodes) {
            formalParameters.add(formalParamNode.getImage());
        }
    }
    LambdaExpression le = new LambdaExpression(formalParameters, ve);
    le.setELContext(ctx);
    if (jjtGetNumChildren() == 2) {
        // in the nesting declare parameters
        if (state.getHasFormalParameters()) {
            return le;
        } else {
            return le.invoke(ctx, (Object[]) null);
        }
    }
    /*
         * This is a (possibly nested) lambda expression with one or more sets
         * of parameters provided.
         *
         * If there are more nested expressions than sets of parameters this may
         * return a LambdaExpression.
         *
         * If there are more sets of parameters than nested expressions an
         * ELException will have been thrown by the check at the start of this
         * method.
         */
    // Always have to invoke the outer-most expression
    int methodParameterIndex = 2;
    Object result = le.invoke(((AstMethodParameters) children[methodParameterIndex]).getParameters(ctx));
    methodParameterIndex++;
    while (result instanceof LambdaExpression && methodParameterIndex < jjtGetNumChildren()) {
        result = ((LambdaExpression) result).invoke(((AstMethodParameters) children[methodParameterIndex]).getParameters(ctx));
        methodParameterIndex++;
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) ELException(jakarta.el.ELException) ValueExpressionImpl(org.apache.el.ValueExpressionImpl) LambdaExpression(jakarta.el.LambdaExpression)

Example 5 with LambdaExpression

use of jakarta.el.LambdaExpression in project tomcat by apache.

the class Stream method sorted.

public Stream sorted(final LambdaExpression le) {
    Iterator<Object> downStream = new OpIterator() {

        private Iterator<Object> sorted = null;

        @Override
        protected void findNext() {
            if (sorted == null) {
                sort(le);
            }
            if (sorted.hasNext()) {
                next = sorted.next();
                foundNext = true;
            }
        }

        @SuppressWarnings({ "rawtypes", "unchecked" })
        private final void sort(LambdaExpression le) {
            List list = new ArrayList<>();
            Comparator<Object> c = new LambdaExpressionComparator(le);
            while (iterator.hasNext()) {
                list.add(iterator.next());
            }
            list.sort(c);
            sorted = list.iterator();
        }
    };
    return new Stream(downStream);
}
Also used : Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) LambdaExpression(jakarta.el.LambdaExpression)

Aggregations

LambdaExpression (jakarta.el.LambdaExpression)5 ELException (jakarta.el.ELException)4 ArrayList (java.util.ArrayList)2 ELClass (jakarta.el.ELClass)1 ELResolver (jakarta.el.ELResolver)1 FunctionMapper (jakarta.el.FunctionMapper)1 PropertyNotFoundException (jakarta.el.PropertyNotFoundException)1 ValueExpression (jakarta.el.ValueExpression)1 VariableMapper (jakarta.el.VariableMapper)1 PropertyEditor (java.beans.PropertyEditor)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Set (java.util.Set)1 ValueExpressionImpl (org.apache.el.ValueExpressionImpl)1 Optional (org.apache.el.stream.Optional)1