Author: markt Date: Fri Jul 19 11:23:37 2013 New Revision: 1504834 URL: http://svn.apache.org/r1504834 Log: Do the scanning to count nesting levels and presence of formal parameters just once. Simplify the checks during getValue() using the results of this new scan.
Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java?rev=1504834&r1=1504833&r2=1504834&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Fri Jul 19 11:23:37 2013 @@ -29,6 +29,8 @@ import org.apache.el.util.MessageFactory public class AstLambdaExpression extends SimpleNode { + private NestedState nestedState = null; + public AstLambdaExpression(int id) { super(id); } @@ -36,40 +38,17 @@ public class AstLambdaExpression extends @Override public Object getValue(EvaluationContext ctx) throws ELException { - // Check; - // - that there are not more sets of method parameters than there are - // nested lambda expressions - // - if any of the nested expressions declare formal parameters + // 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; - boolean declaresParameters = false; - // We know this node is an expression - int lambdaExpressionCount = 1; - // child at index 1 is the expression - Node n = jjtGetChild(1); - while (n instanceof AstLambdaExpression) { - lambdaExpressionCount++; - if (n.jjtGetChild(0) instanceof AstLambdaParameters) { - if (!declaresParameters && - n.jjtGetChild(0).jjtGetNumChildren() > 0) { - declaresParameters = true; - } - n = n.jjtGetChild(1); - } else { - n = null; - } - } - if (methodParameterSetCount > lambdaExpressionCount) { + if (methodParameterSetCount > state.getNestingCount()) { throw new ELException(MessageFactory.get( "error.lambda.tooManyMethodParameterSets")); } - // Also need to check parents for declaration of formal parameters - n = parent; - while (!declaresParameters && n instanceof AstLambdaExpression) { - if (n.jjtGetChild(0).jjtGetNumChildren() > 0) { - declaresParameters = true; - } - n = n.jjtGetParent(); - } // First child is always parameters even if there aren't any AstLambdaParameters formalParametersNode = @@ -91,17 +70,27 @@ public class AstLambdaExpression extends le.setELContext(ctx); if (jjtGetNumChildren() == 2) { - if (formalParameters.isEmpty() && !declaresParameters) { - // No formal parameters or method parameters and not nested - // inside another lambda expression so invoke the expression. - return le.invoke(ctx, (Object[]) null); - } else { - // Has formal parameters but no method parameters or is a nested - // expression so return the expression for later evaluation + // No method parameters + // Can only invoke the expression if none of the lambda expressions + // 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; @@ -109,21 +98,6 @@ public class AstLambdaExpression extends children[methodParameterIndex]).getParameters(ctx)); methodParameterIndex++; - /* - * If there are multiple sets of method parameters there should be at - * least that many nested expressions. - * - * If there are more nested expressions than sets of method parameters - * this may return a LambdaExpression. - * - * If there are more sets of method parameters than nested expressions - * an ELException will have been thrown by the check at the start of - * this method. - * - * If the inner most expression(s) do not require parameters then a - * value will be returned once the outermost expression that does - * require a parameter has been evaluated. - */ while (result instanceof LambdaExpression && methodParameterIndex < jjtGetNumChildren()) { result = ((LambdaExpression) result).invoke(((AstMethodParameters) @@ -135,6 +109,42 @@ public class AstLambdaExpression extends } + private NestedState getNestedState() { + if (nestedState == null) { + setNestedState(new NestedState()); + } + return nestedState; + } + + + private void setNestedState(NestedState nestedState) { + if (this.nestedState != null) { + // Should never happen + throw new IllegalStateException("nestedState may only be set once"); + } + this.nestedState = nestedState; + + // Increment the nesting count for the current expression + nestedState.incrementNestingCount(); + + if (jjtGetNumChildren() > 1) { + Node firstChild = jjtGetChild(0); + if (firstChild instanceof AstLambdaParameters) { + if (firstChild.jjtGetNumChildren() > 0) { + nestedState.setHasFormalParameters(); + } + } else { + // Can't be a lambda expression + return; + } + Node secondChild = jjtGetChild(1); + if (secondChild instanceof AstLambdaExpression) { + ((AstLambdaExpression) secondChild).setNestedState(nestedState); + } + } + } + + @Override public String toString() { // Purely for debug purposes. May not be complete or correct. Certainly @@ -145,5 +155,28 @@ public class AstLambdaExpression extends } return result.toString(); } + + + private static class NestedState { + + private int nestingCount = 0; + private boolean hasFormalParameters = false; + + private void incrementNestingCount() { + nestingCount++; + } + + private int getNestingCount() { + return nestingCount; + } + + private void setHasFormalParameters() { + hasFormalParameters = true; + } + + private boolean getHasFormalParameters() { + return hasFormalParameters; + } + } } /* JavaCC - OriginalChecksum=071159eff10c8e15ec612c765ae4480a (do not edit this line) */ --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org