This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import org.apache.el.lang.ELSupport;
import org.apache.el.lang.ExpressionBuilder;
import org.apache.el.stream.StreamELResolverImpl;
import org.apache.el.util.MessageFactory;
/**
* @see javax.el.ExpressionFactory
*
* @author Jacob Hookom [jacob@hookom.net]
*/
public class ExpressionFactoryImpl extends ExpressionFactory {
/**
*
*/
public ExpressionFactoryImpl() {
super();
}
@Override
public Object coerceToType(Object obj, Class<?> type) {
return ELSupport.coerceToType(null, obj, type);
}
@Override
public MethodExpression createMethodExpression(ELContext context,
String expression, Class<?> expectedReturnType,
Class<?>[] expectedParamTypes) {
ExpressionBuilder builder = new ExpressionBuilder(expression, context);
return builder.createMethodExpression(expectedReturnType,
expectedParamTypes);
}
@Override
public ValueExpression createValueExpression(ELContext context,
String expression, Class<?> expectedType) {
if (expectedType == null) {
throw new NullPointerException(MessageFactory
.get("error.value.expectedType"));
}
ExpressionBuilder builder = new ExpressionBuilder(expression, context);
return builder.createValueExpression(expectedType);
}
@Override
public ValueExpression createValueExpression(Object instance,
Class<?> expectedType) {
if (expectedType == null) {
throw new NullPointerException(MessageFactory
.get("error.value.expectedType"));
}
return new ValueExpressionLiteral(instance, expectedType);
}
@Override
public ELResolver getStreamELResolver() {
return new StreamELResolverImpl();
}
}

View File

@@ -0,0 +1,63 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# General Errors
error.convert=Cannot convert [{0}] of type [{1}] to [{2}]
error.compare=Cannot compare [{0}] to [{1}]
error.function=Problems calling function [{0}]
error.unreachable.base=Target Unreachable, identifier [{0}] resolved to null
error.unreachable.property=Target Unreachable, [{0}] returned null
error.resolver.unhandled=ELResolver did not handle type: [{0}] with property of [{1}]
error.resolver.unhandled.null=ELResolver cannot handle a null base Object with identifier [{0}]
error.invoke.wrongParams=The method [{0}] was called with [{1}] parameter(s) when it expected [{2}]
error.invoke.tooFewParams=The method [{0}] was called with [{1}] parameter(s) when it expected at least [{2}]
# ValueExpressionLiteral
error.value.literal.write=ValueExpression is a literal and not writable: [{0}]
# ExpressionFactoryImpl
error.null=Expression cannot be null
error.mixed=Expression cannot contain both '#{...}' and '${...}' : [{0}]
error.method=Not a valid MethodExpression : [{0}]
error.method.nullParms=Parameter types cannot be null
error.value.expectedType=Expected type cannot be null
# ExpressionBuilder
error.parseFail=Failed to parse the expression [{0}]
# ValueSetVisitor
error.syntax.set=Illegal Syntax for Set Operation
# ReflectionUtil
error.method.notfound=Method not found: {0}.{1}({2})
error.method.ambiguous=Unable to find unambiguous method: {0}.{1}({2})
# ValidatingVisitor
error.fnMapper.null=Expression uses functions, but no FunctionMapper was provided
error.fnMapper.method=Function [{0}] not found
error.fnMapper.paramcount=Function [{0}] specifies [{1}] params, but [{2}] were declared
# ExpressionImpl
error.context.null=ELContext was null
# Parser
error.funciton.tooManyMethodParameterSets=There are multiple sets of parameters specified for function [{0}]
error.identifier.notjava=The identifier [{0}] is not a valid Java identifier as required by section 1.19 of the EL specification (Identifier ::= Java language identifier). This check can be disabled by setting the system property org.apache.el.parser.SKIP_IDENTIFIER_CHECK to true.
error.lambda.tooManyMethodParameterSets=There are more sets of method parameters specified than there are nested lambda expressions
# Stream
stream.compare.notComparable=Stream elements must implement Comparable
stream.optional.empty=It is illegal to call get() on an empty optional
stream.optional.paramNotLambda=The parameter for the method [{0}] should be a lambda expression

View File

@@ -0,0 +1,36 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
error.convert = No puedo convertir [{0}] desde tipo [{1}] a [{2}]
error.compare = No puedo comparar [{0}] con [{1}]
error.function = Problemas llamando a funci\u00F3n [{0}]
error.unreachable.base = Objetivo inalcanzable, identificador [{0}] resuelto a nulo
error.unreachable.property = Objetivo inalcanzable, [{0}] devolvi\u00F3 nulo
error.resolver.unhandled = ELResolver no manej\u00F3 el tipo: [{0}] con propiedad de [{1}]
error.resolver.unhandled.null = ELResolver no puede manejar un Objeto base nulo con identificador de [{0}]
error.value.literal.write = ValueExpression es un literal y no un grabable: [{0}]
error.null = La expresi\u00F3n no puede ser nula
error.mixed = La expresi\u00F3n no puede contenera la vez ''#{..}'' y ''${..}'' : [{0}]
error.method = No es una MethodExpression v\u00E1lida: [{0}]
error.method.nullParms = Los tipos de par\u00E1metro no pueden ser nulo
error.value.expectedType = El tipo esperado no puede ser nulo
error.syntax.set = Sit\u00E1xis ilegal para Operaci\u00F3n de Poner Valor
error.method.notfound = M\u00E9todo no hallado: {0}.{1}({2})
error.method.ambiguous = No pude hallar m\u00E9todo ambiguo: {0}.{1}({2})
error.fnMapper.null = La expresi\u00F3n usa funciones, pero no se ha suministrado FunctionMapper
error.fnMapper.method = Funci\u00F3n [{0}] no hallada
error.fnMapper.paramcount = La funci\u00F3n [{0}] especifica [{1}] par\u00E9metros, pero [{2}] fueron declarados
error.context.null = ELContext era nulo
error.identifier.notjava = El identificador [{0}] no es un identificado Java v\u00E1lido seg\u00FAn se requiere en la secci\u00F3n 1.9 de la especificaci\u00F3n EL (Identificador ::= identificador de lenguaje Java). Este chequeo se puede desactivar poniendo la propiedad del sistema org.apache.el.parser.SKIP_IDENTIFIER_CHECK a verdad (true).

View File

@@ -0,0 +1,331 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.FunctionMapper;
import javax.el.MethodExpression;
import javax.el.MethodInfo;
import javax.el.MethodNotFoundException;
import javax.el.PropertyNotFoundException;
import javax.el.VariableMapper;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.lang.ExpressionBuilder;
import org.apache.el.parser.Node;
import org.apache.el.util.ReflectionUtil;
/**
* An <code>Expression</code> that refers to a method on an object.
*
* <p>
* The {@link javax.el.ExpressionFactory#createMethodExpression} method
* can be used to parse an expression string and return a concrete instance
* of <code>MethodExpression</code> that encapsulates the parsed expression.
* The {@link FunctionMapper} is used at parse time, not evaluation time,
* so one is not needed to evaluate an expression using this class.
* However, the {@link ELContext} is needed at evaluation time.</p>
*
* <p>The {@link #getMethodInfo} and {@link #invoke} methods will evaluate the
* expression each time they are called. The {@link javax.el.ELResolver} in the
* <code>ELContext</code> is used to resolve the top-level variables and to
* determine the behavior of the <code>.</code> and <code>[]</code>
* operators. For any of the two methods, the
* {@link javax.el.ELResolver#getValue} method is used to resolve all properties
* up to but excluding the last one. This provides the <code>base</code> object
* on which the method appears. If the <code>base</code> object is null, a
* <code>NullPointerException</code> must be thrown. At the last resolution,
* the final <code>property</code> is then coerced to a <code>String</code>,
* which provides the name of the method to be found. A method matching the
* name and expected parameters provided at parse time is found and it is
* either queried or invoked (depending on the method called on this
* <code>MethodExpression</code>).</p>
*
* <p>See the notes about comparison, serialization and immutability in
* the {@link javax.el.Expression} javadocs.
*
* @see javax.el.ELResolver
* @see javax.el.Expression
* @see javax.el.ExpressionFactory
* @see javax.el.MethodExpression
*
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class MethodExpressionImpl extends MethodExpression implements
Externalizable {
private Class<?> expectedType;
private String expr;
private FunctionMapper fnMapper;
private VariableMapper varMapper;
private transient Node node;
private Class<?>[] paramTypes;
public MethodExpressionImpl() {
super();
}
public MethodExpressionImpl(String expr, Node node,
FunctionMapper fnMapper, VariableMapper varMapper,
Class<?> expectedType, Class<?>[] paramTypes) {
super();
this.expr = expr;
this.node = node;
this.fnMapper = fnMapper;
this.varMapper = varMapper;
this.expectedType = expectedType;
this.paramTypes = paramTypes;
}
/**
* Determines whether the specified object is equal to this
* <code>Expression</code>.
*
* <p>
* The result is <code>true</code> if and only if the argument is not
* <code>null</code>, is an <code>Expression</code> object that is the
* of the same type (<code>ValueExpression</code> or
* <code>MethodExpression</code>), and has an identical parsed
* representation.
* </p>
*
* <p>
* Note that two expressions can be equal if their expression Strings are
* different. For example, <code>${fn1:foo()}</code> and
* <code>${fn2:foo()}</code> are equal if their corresponding
* <code>FunctionMapper</code>s mapped <code>fn1:foo</code> and
* <code>fn2:foo</code> to the same method.
* </p>
*
* @param obj
* the <code>Object</code> to test for equality.
* @return <code>true</code> if <code>obj</code> equals this
* <code>Expression</code>; <code>false</code> otherwise.
* @see java.util.Hashtable
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return (obj instanceof MethodExpressionImpl && obj.hashCode() == this
.hashCode());
}
/**
* Returns the original String used to create this <code>Expression</code>,
* unmodified.
*
* <p>
* This is used for debugging purposes but also for the purposes of
* comparison (e.g. to ensure the expression in a configuration file has not
* changed).
* </p>
*
* <p>
* This method does not provide sufficient information to re-create an
* expression. Two different expressions can have exactly the same
* expression string but different function mappings. Serialization should
* be used to save and restore the state of an <code>Expression</code>.
* </p>
*
* @return The original expression String.
*
* @see javax.el.Expression#getExpressionString()
*/
@Override
public String getExpressionString() {
return this.expr;
}
/**
* Evaluates the expression relative to the provided context, and returns
* information about the actual referenced method.
*
* @param context
* The context of this evaluation
* @return an instance of <code>MethodInfo</code> containing information
* about the method the expression evaluated to.
* @throws NullPointerException
* if context is <code>null</code> or the base object is
* <code>null</code> on the last resolution.
* @throws PropertyNotFoundException
* if one of the property resolutions failed because a specified
* variable or property does not exist or is not readable.
* @throws MethodNotFoundException
* if no suitable method can be found.
* @throws ELException
* if an exception was thrown while performing property or
* variable resolution. The thrown exception must be included as
* the cause property of this exception, if available.
* @see javax.el.MethodExpression#getMethodInfo(javax.el.ELContext)
*/
@Override
public MethodInfo getMethodInfo(ELContext context)
throws PropertyNotFoundException, MethodNotFoundException,
ELException {
Node n = this.getNode();
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
ctx.notifyBeforeEvaluation(getExpressionString());
MethodInfo result = n.getMethodInfo(ctx, this.paramTypes);
ctx.notifyAfterEvaluation(getExpressionString());
return result;
}
private Node getNode() throws ELException {
if (this.node == null) {
this.node = ExpressionBuilder.createNode(this.expr);
}
return this.node;
}
/**
* Returns the hash code for this <code>Expression</code>.
*
* <p>
* See the note in the {@link #equals} method on how two expressions can be
* equal if their expression Strings are different. Recall that if two
* objects are equal according to the <code>equals(Object)</code> method,
* then calling the <code>hashCode</code> method on each of the two
* objects must produce the same integer result. Implementations must take
* special note and implement <code>hashCode</code> correctly.
* </p>
*
* @return The hash code for this <code>Expression</code>.
* @see #equals
* @see java.util.Hashtable
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.expr.hashCode();
}
/**
* Evaluates the expression relative to the provided context, invokes the
* method that was found using the supplied parameters, and returns the
* result of the method invocation.
*
* @param context
* The context of this evaluation.
* @param params
* The parameters to pass to the method, or <code>null</code>
* if no parameters.
* @return the result of the method invocation (<code>null</code> if the
* method has a <code>void</code> return type).
* @throws NullPointerException
* if context is <code>null</code> or the base object is
* <code>null</code> on the last resolution.
* @throws PropertyNotFoundException
* if one of the property resolutions failed because a specified
* variable or property does not exist or is not readable.
* @throws MethodNotFoundException
* if no suitable method can be found.
* @throws ELException
* if an exception was thrown while performing property or
* variable resolution. The thrown exception must be included as
* the cause property of this exception, if available. If the
* exception thrown is an <code>InvocationTargetException</code>,
* extract its <code>cause</code> and pass it to the
* <code>ELException</code> constructor.
* @see javax.el.MethodExpression#invoke(javax.el.ELContext,
* java.lang.Object[])
*/
@Override
public Object invoke(ELContext context, Object[] params)
throws PropertyNotFoundException, MethodNotFoundException,
ELException {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
ctx.notifyBeforeEvaluation(getExpressionString());
Object result = this.getNode().invoke(ctx, this.paramTypes, params);
ctx.notifyAfterEvaluation(getExpressionString());
return result;
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.paramTypes = ReflectionUtil.toTypeArray(((String[]) in
.readObject()));
this.fnMapper = (FunctionMapper) in.readObject();
this.varMapper = (VariableMapper) in.readObject();
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
out.writeObject(this.fnMapper);
out.writeObject(this.varMapper);
}
@Override
public boolean isLiteralText() {
return false;
}
/**
* @since EL 3.0
*/
@Override
public boolean isParametersProvided() {
return this.getNode().isParametersProvided();
}
/**
* @since EL 2.2
* Note: The spelling mistake is deliberate.
* isParmetersProvided() - Specification definition
* isParametersProvided() - Corrected spelling
*/
@Override
public boolean isParmetersProvided() {
return this.getNode().isParametersProvided();
}
}

View File

@@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.MethodExpression;
import javax.el.MethodInfo;
import org.apache.el.util.ReflectionUtil;
public class MethodExpressionLiteral extends MethodExpression implements Externalizable {
private Class<?> expectedType;
private String expr;
private Class<?>[] paramTypes;
public MethodExpressionLiteral() {
// do nothing
}
public MethodExpressionLiteral(String expr, Class<?> expectedType,
Class<?>[] paramTypes) {
this.expr = expr;
this.expectedType = expectedType;
this.paramTypes = paramTypes;
}
@Override
public MethodInfo getMethodInfo(ELContext context) throws ELException {
context.notifyBeforeEvaluation(getExpressionString());
MethodInfo result =
new MethodInfo(this.expr, this.expectedType, this.paramTypes);
context.notifyAfterEvaluation(getExpressionString());
return result;
}
@Override
public Object invoke(ELContext context, Object[] params) throws ELException {
context.notifyBeforeEvaluation(getExpressionString());
Object result;
if (this.expectedType != null) {
result = context.convertToType(this.expr, this.expectedType);
} else {
result = this.expr;
}
context.notifyAfterEvaluation(getExpressionString());
return result;
}
@Override
public String getExpressionString() {
return this.expr;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof MethodExpressionLiteral && this.hashCode() == obj.hashCode());
}
@Override
public int hashCode() {
return this.expr.hashCode();
}
@Override
public boolean isLiteralText() {
return true;
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.paramTypes = ReflectionUtil.toTypeArray(((String[]) in
.readObject()));
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(ReflectionUtil.toTypeNameArray(this.paramTypes));
}
}

View File

@@ -0,0 +1,293 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.FunctionMapper;
import javax.el.PropertyNotFoundException;
import javax.el.PropertyNotWritableException;
import javax.el.ValueExpression;
import javax.el.ValueReference;
import javax.el.VariableMapper;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.lang.ExpressionBuilder;
import org.apache.el.parser.AstLiteralExpression;
import org.apache.el.parser.Node;
import org.apache.el.util.ReflectionUtil;
/**
* An <code>Expression</code> that can get or set a value.
*
* <p>
* In previous incarnations of this API, expressions could only be read.
* <code>ValueExpression</code> objects can now be used both to retrieve a
* value and to set a value. Expressions that can have a value set on them are
* referred to as l-value expressions. Those that cannot are referred to as
* r-value expressions. Not all r-value expressions can be used as l-value
* expressions (e.g. <code>"${1+1}"</code> or
* <code>"${firstName} ${lastName}"</code>). See the EL Specification for
* details. Expressions that cannot be used as l-values must always return
* <code>true</code> from <code>isReadOnly()</code>.
* </p>
*
* <p>
* The {@link javax.el.ExpressionFactory#createValueExpression} method
* can be used to parse an expression string and return a concrete instance
* of <code>ValueExpression</code> that encapsulates the parsed expression.
* The {@link FunctionMapper} is used at parse time, not evaluation time,
* so one is not needed to evaluate an expression using this class.
* However, the {@link ELContext} is needed at evaluation time.</p>
*
* <p>The {@link #getValue}, {@link #setValue}, {@link #isReadOnly} and
* {@link #getType} methods will evaluate the expression each time they are
* called. The {@link javax.el.ELResolver} in the <code>ELContext</code> is used
* to resolve the top-level variables and to determine the behavior of the
* <code>.</code> and <code>[]</code> operators. For any of the four methods,
* the {@link javax.el.ELResolver#getValue} method is used to resolve all
* properties up to but excluding the last one. This provides the
* <code>base</code> object. At the last resolution, the
* <code>ValueExpression</code> will call the corresponding
* {@link javax.el.ELResolver#getValue}, {@link javax.el.ELResolver#setValue},
* {@link javax.el.ELResolver#isReadOnly} or {@link javax.el.ELResolver#getType}
* method, depending on which was called on the <code>ValueExpression</code>.
* </p>
*
* <p>See the notes about comparison, serialization and immutability in
* the {@link javax.el.Expression} javadocs.
*
* @see javax.el.ELResolver
* @see javax.el.Expression
* @see javax.el.ExpressionFactory
* @see javax.el.ValueExpression
*
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class ValueExpressionImpl extends ValueExpression implements
Externalizable {
private Class<?> expectedType;
private String expr;
private FunctionMapper fnMapper;
private VariableMapper varMapper;
private transient Node node;
public ValueExpressionImpl() {
super();
}
public ValueExpressionImpl(String expr, Node node, FunctionMapper fnMapper,
VariableMapper varMapper, Class<?> expectedType) {
this.expr = expr;
this.node = node;
this.fnMapper = fnMapper;
this.varMapper = varMapper;
this.expectedType = expectedType;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ValueExpressionImpl)) {
return false;
}
if (obj.hashCode() != this.hashCode()) {
return false;
}
return this.getNode().equals(((ValueExpressionImpl) obj).getNode());
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#getExpectedType()
*/
@Override
public Class<?> getExpectedType() {
return this.expectedType;
}
/**
* Returns the type the result of the expression will be coerced to after
* evaluation.
*
* @return the <code>expectedType</code> passed to the
* <code>ExpressionFactory.createValueExpression</code> method
* that created this <code>ValueExpression</code>.
*
* @see javax.el.Expression#getExpressionString()
*/
@Override
public String getExpressionString() {
return this.expr;
}
private Node getNode() throws ELException {
if (this.node == null) {
this.node = ExpressionBuilder.createNode(this.expr);
}
return this.node;
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#getType(javax.el.ELContext)
*/
@Override
public Class<?> getType(ELContext context) throws PropertyNotFoundException,
ELException {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
context.notifyBeforeEvaluation(getExpressionString());
Class<?> result = this.getNode().getType(ctx);
context.notifyAfterEvaluation(getExpressionString());
return result;
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#getValue(javax.el.ELContext)
*/
@Override
public Object getValue(ELContext context) throws PropertyNotFoundException,
ELException {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
context.notifyBeforeEvaluation(getExpressionString());
Object value = this.getNode().getValue(ctx);
if (this.expectedType != null) {
value = context.convertToType(value, this.expectedType);
}
context.notifyAfterEvaluation(getExpressionString());
return value;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.getNode().hashCode();
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#isLiteralText()
*/
@Override
public boolean isLiteralText() {
try {
return this.getNode() instanceof AstLiteralExpression;
} catch (ELException ele) {
return false;
}
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#isReadOnly(javax.el.ELContext)
*/
@Override
public boolean isReadOnly(ELContext context)
throws PropertyNotFoundException, ELException {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
context.notifyBeforeEvaluation(getExpressionString());
boolean result = this.getNode().isReadOnly(ctx);
context.notifyAfterEvaluation(getExpressionString());
return result;
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.expr = in.readUTF();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
this.fnMapper = (FunctionMapper) in.readObject();
this.varMapper = (VariableMapper) in.readObject();
}
/*
* (non-Javadoc)
*
* @see javax.el.ValueExpression#setValue(javax.el.ELContext,
* java.lang.Object)
*/
@Override
public void setValue(ELContext context, Object value)
throws PropertyNotFoundException, PropertyNotWritableException,
ELException {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
context.notifyBeforeEvaluation(getExpressionString());
this.getNode().setValue(ctx, value);
context.notifyAfterEvaluation(getExpressionString());
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.expr);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
out.writeObject(this.fnMapper);
out.writeObject(this.varMapper);
}
@Override
public String toString() {
return "ValueExpression["+this.expr+"]";
}
/**
* @since EL 2.2
*/
@Override
public ValueReference getValueReference(ELContext context) {
EvaluationContext ctx = new EvaluationContext(context, this.fnMapper,
this.varMapper);
context.notifyBeforeEvaluation(getExpressionString());
ValueReference result = this.getNode().getValueReference(ctx);
context.notifyAfterEvaluation(getExpressionString());
return result;
}
}

View File

@@ -0,0 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.el.ELContext;
import javax.el.PropertyNotWritableException;
import javax.el.ValueExpression;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.ReflectionUtil;
public final class ValueExpressionLiteral extends ValueExpression implements
Externalizable {
private static final long serialVersionUID = 1L;
private Object value;
private String valueString;
private Class<?> expectedType;
public ValueExpressionLiteral() {
super();
}
public ValueExpressionLiteral(Object value, Class<?> expectedType) {
this.value = value;
this.expectedType = expectedType;
}
@Override
public Object getValue(ELContext context) {
context.notifyBeforeEvaluation(getExpressionString());
Object result;
if (this.expectedType != null) {
result = context.convertToType(this.value, this.expectedType);
} else {
result = this.value;
}
context.notifyAfterEvaluation(getExpressionString());
return result;
}
@Override
public void setValue(ELContext context, Object value) {
context.notifyBeforeEvaluation(getExpressionString());
throw new PropertyNotWritableException(MessageFactory.get(
"error.value.literal.write", this.value));
}
@Override
public boolean isReadOnly(ELContext context) {
context.notifyBeforeEvaluation(getExpressionString());
context.notifyAfterEvaluation(getExpressionString());
return true;
}
@Override
public Class<?> getType(ELContext context) {
context.notifyBeforeEvaluation(getExpressionString());
Class<?> result = (this.value != null) ? this.value.getClass() : null;
context.notifyAfterEvaluation(getExpressionString());
return result;
}
@Override
public Class<?> getExpectedType() {
return this.expectedType;
}
@Override
public String getExpressionString() {
if (this.valueString == null) {
this.valueString = (this.value != null) ? this.value.toString() : null;
}
return this.valueString;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof ValueExpressionLiteral && this
.equals((ValueExpressionLiteral) obj));
}
public boolean equals(ValueExpressionLiteral ve) {
return (ve != null && (this.value != null && ve.value != null && (this.value == ve.value || this.value
.equals(ve.value))));
}
@Override
public int hashCode() {
return (this.value != null) ? this.value.hashCode() : 0;
}
@Override
public boolean isLiteralText() {
return true;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.value);
out.writeUTF((this.expectedType != null) ? this.expectedType.getName()
: "");
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.value = in.readObject();
String type = in.readUTF();
if (!"".equals(type)) {
this.expectedType = ReflectionUtil.forName(type);
}
}
}

View File

@@ -0,0 +1,401 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import org.apache.el.util.MessageFactory;
/**
* A helper class of Arithmetic defined by the EL Specification
* @author Jacob Hookom [jacob@hookom.net]
*/
public abstract class ELArithmetic {
public static final class BigDecimalDelegate extends ELArithmetic {
@Override
protected Number add(Number num0, Number num1) {
return ((BigDecimal) num0).add((BigDecimal) num1);
}
@Override
protected Number coerce(Number num) {
if (num instanceof BigDecimal)
return num;
if (num instanceof BigInteger)
return new BigDecimal((BigInteger) num);
return new BigDecimal(num.doubleValue());
}
@Override
protected Number coerce(String str) {
return new BigDecimal(str);
}
@Override
protected Number divide(Number num0, Number num1) {
return ((BigDecimal) num0).divide((BigDecimal) num1,
RoundingMode.HALF_UP);
}
@Override
protected Number subtract(Number num0, Number num1) {
return ((BigDecimal) num0).subtract((BigDecimal) num1);
}
@Override
protected Number mod(Number num0, Number num1) {
return Double.valueOf(num0.doubleValue() % num1.doubleValue());
}
@Override
protected Number multiply(Number num0, Number num1) {
return ((BigDecimal) num0).multiply((BigDecimal) num1);
}
@Override
public boolean matches(Object obj0, Object obj1) {
return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
}
}
public static final class BigIntegerDelegate extends ELArithmetic {
@Override
protected Number add(Number num0, Number num1) {
return ((BigInteger) num0).add((BigInteger) num1);
}
@Override
protected Number coerce(Number num) {
if (num instanceof BigInteger)
return num;
return new BigInteger(num.toString());
}
@Override
protected Number coerce(String str) {
return new BigInteger(str);
}
@Override
protected Number divide(Number num0, Number num1) {
return (new BigDecimal((BigInteger) num0)).divide(new BigDecimal((BigInteger) num1), RoundingMode.HALF_UP);
}
@Override
protected Number multiply(Number num0, Number num1) {
return ((BigInteger) num0).multiply((BigInteger) num1);
}
@Override
protected Number mod(Number num0, Number num1) {
return ((BigInteger) num0).mod((BigInteger) num1);
}
@Override
protected Number subtract(Number num0, Number num1) {
return ((BigInteger) num0).subtract((BigInteger) num1);
}
@Override
public boolean matches(Object obj0, Object obj1) {
return (obj0 instanceof BigInteger || obj1 instanceof BigInteger);
}
}
public static final class DoubleDelegate extends ELArithmetic {
@Override
protected Number add(Number num0, Number num1) {
// could only be one of these
if (num0 instanceof BigDecimal) {
return ((BigDecimal) num0).add(new BigDecimal(num1.doubleValue()));
} else if (num1 instanceof BigDecimal) {
return ((new BigDecimal(num0.doubleValue()).add((BigDecimal) num1)));
}
return Double.valueOf(num0.doubleValue() + num1.doubleValue());
}
@Override
protected Number coerce(Number num) {
if (num instanceof Double)
return num;
if (num instanceof BigInteger)
return new BigDecimal((BigInteger) num);
return Double.valueOf(num.doubleValue());
}
@Override
protected Number coerce(String str) {
return Double.valueOf(str);
}
@Override
protected Number divide(Number num0, Number num1) {
return Double.valueOf(num0.doubleValue() / num1.doubleValue());
}
@Override
protected Number mod(Number num0, Number num1) {
return Double.valueOf(num0.doubleValue() % num1.doubleValue());
}
@Override
protected Number subtract(Number num0, Number num1) {
// could only be one of these
if (num0 instanceof BigDecimal) {
return ((BigDecimal) num0).subtract(new BigDecimal(num1.doubleValue()));
} else if (num1 instanceof BigDecimal) {
return ((new BigDecimal(num0.doubleValue()).subtract((BigDecimal) num1)));
}
return Double.valueOf(num0.doubleValue() - num1.doubleValue());
}
@Override
protected Number multiply(Number num0, Number num1) {
// could only be one of these
if (num0 instanceof BigDecimal) {
return ((BigDecimal) num0).multiply(new BigDecimal(num1.doubleValue()));
} else if (num1 instanceof BigDecimal) {
return ((new BigDecimal(num0.doubleValue()).multiply((BigDecimal) num1)));
}
return Double.valueOf(num0.doubleValue() * num1.doubleValue());
}
@Override
public boolean matches(Object obj0, Object obj1) {
return (obj0 instanceof Double
|| obj1 instanceof Double
|| obj0 instanceof Float
|| obj1 instanceof Float
|| (obj0 instanceof String && ELSupport
.isStringFloat((String) obj0)) || (obj1 instanceof String && ELSupport
.isStringFloat((String) obj1)));
}
}
public static final class LongDelegate extends ELArithmetic {
@Override
protected Number add(Number num0, Number num1) {
return Long.valueOf(num0.longValue() + num1.longValue());
}
@Override
protected Number coerce(Number num) {
if (num instanceof Long)
return num;
return Long.valueOf(num.longValue());
}
@Override
protected Number coerce(String str) {
return Long.valueOf(str);
}
@Override
protected Number divide(Number num0, Number num1) {
return Long.valueOf(num0.longValue() / num1.longValue());
}
@Override
protected Number mod(Number num0, Number num1) {
return Long.valueOf(num0.longValue() % num1.longValue());
}
@Override
protected Number subtract(Number num0, Number num1) {
return Long.valueOf(num0.longValue() - num1.longValue());
}
@Override
protected Number multiply(Number num0, Number num1) {
return Long.valueOf(num0.longValue() * num1.longValue());
}
@Override
public boolean matches(Object obj0, Object obj1) {
return (obj0 instanceof Long || obj1 instanceof Long);
}
}
public static final BigDecimalDelegate BIGDECIMAL = new BigDecimalDelegate();
public static final BigIntegerDelegate BIGINTEGER = new BigIntegerDelegate();
public static final DoubleDelegate DOUBLE = new DoubleDelegate();
public static final LongDelegate LONG = new LongDelegate();
private static final Long ZERO = Long.valueOf(0);
public static final Number add(final Object obj0, final Object obj1) {
final ELArithmetic delegate = findDelegate(obj0, obj1);
if (delegate == null) {
return Long.valueOf(0);
}
Number num0 = delegate.coerce(obj0);
Number num1 = delegate.coerce(obj1);
return delegate.add(num0, num1);
}
public static final Number mod(final Object obj0, final Object obj1) {
if (obj0 == null && obj1 == null) {
return Long.valueOf(0);
}
final ELArithmetic delegate;
if (BIGDECIMAL.matches(obj0, obj1))
delegate = DOUBLE;
else if (DOUBLE.matches(obj0, obj1))
delegate = DOUBLE;
else if (BIGINTEGER.matches(obj0, obj1))
delegate = BIGINTEGER;
else
delegate = LONG;
Number num0 = delegate.coerce(obj0);
Number num1 = delegate.coerce(obj1);
return delegate.mod(num0, num1);
}
public static final Number subtract(final Object obj0, final Object obj1) {
final ELArithmetic delegate = findDelegate(obj0, obj1);
if (delegate == null) {
return Long.valueOf(0);
}
Number num0 = delegate.coerce(obj0);
Number num1 = delegate.coerce(obj1);
return delegate.subtract(num0, num1);
}
public static final Number divide(final Object obj0, final Object obj1) {
if (obj0 == null && obj1 == null) {
return ZERO;
}
final ELArithmetic delegate;
if (BIGDECIMAL.matches(obj0, obj1))
delegate = BIGDECIMAL;
else if (BIGINTEGER.matches(obj0, obj1))
delegate = BIGDECIMAL;
else
delegate = DOUBLE;
Number num0 = delegate.coerce(obj0);
Number num1 = delegate.coerce(obj1);
return delegate.divide(num0, num1);
}
public static final Number multiply(final Object obj0, final Object obj1) {
final ELArithmetic delegate = findDelegate(obj0, obj1);
if (delegate == null) {
return Long.valueOf(0);
}
Number num0 = delegate.coerce(obj0);
Number num1 = delegate.coerce(obj1);
return delegate.multiply(num0, num1);
}
private static ELArithmetic findDelegate(final Object obj0, final Object obj1) {
if (obj0 == null && obj1 == null) {
return null;
}
if (BIGDECIMAL.matches(obj0, obj1)) {
return BIGDECIMAL;
} else if (DOUBLE.matches(obj0, obj1)) {
if (BIGINTEGER.matches(obj0, obj1)) {
return BIGDECIMAL;
} else {
return DOUBLE;
}
} else if (BIGINTEGER.matches(obj0, obj1)) {
return BIGINTEGER;
} else {
return LONG;
}
}
public static final boolean isNumber(final Object obj) {
return (obj != null && isNumberType(obj.getClass()));
}
public static final boolean isNumberType(final Class<?> type) {
return type == Long.TYPE || type == Double.TYPE ||
type == Byte.TYPE || type == Short.TYPE ||
type == Integer.TYPE || type == Float.TYPE ||
Number.class.isAssignableFrom(type);
}
/**
*
*/
protected ELArithmetic() {
super();
}
protected abstract Number add(final Number num0, final Number num1);
protected abstract Number multiply(final Number num0, final Number num1);
protected abstract Number subtract(final Number num0, final Number num1);
protected abstract Number mod(final Number num0, final Number num1);
protected abstract Number coerce(final Number num);
protected final Number coerce(final Object obj) {
if (isNumber(obj)) {
return coerce((Number) obj);
}
if (obj == null || "".equals(obj)) {
return coerce(ZERO);
}
if (obj instanceof String) {
return coerce((String) obj);
}
if (obj instanceof Character) {
return coerce(Short.valueOf((short) ((Character) obj).charValue()));
}
throw new IllegalArgumentException(MessageFactory.get("error.convert",
obj, obj.getClass(), "Number"));
}
protected abstract Number coerce(final String str);
protected abstract Number divide(final Number num0, final Number num1);
protected abstract boolean matches(final Object obj0, final Object obj1);
}

View File

@@ -0,0 +1,655 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import javax.el.ELContext;
import javax.el.ELException;
import org.apache.el.util.MessageFactory;
/**
* A helper class that implements the EL Specification
*
* @author Jacob Hookom [jacob@hookom.net]
*/
public class ELSupport {
private static final Long ZERO = Long.valueOf(0L);
protected static final boolean COERCE_TO_ZERO;
static {
String coerceToZeroStr;
if (System.getSecurityManager() != null) {
coerceToZeroStr = AccessController.doPrivileged(
new PrivilegedAction<String>(){
@Override
public String run() {
return System.getProperty(
"org.apache.el.parser.COERCE_TO_ZERO", "false");
}
}
);
} else {
coerceToZeroStr = System.getProperty(
"org.apache.el.parser.COERCE_TO_ZERO", "false");
}
COERCE_TO_ZERO = Boolean.parseBoolean(coerceToZeroStr);
}
/**
* Compare two objects, after coercing to the same type if appropriate.
*
* If the objects are identical, or they are equal according to
* {@link #equals(ELContext, Object, Object)} then return 0.
*
* If either object is a BigDecimal, then coerce both to BigDecimal first.
* Similarly for Double(Float), BigInteger, and Long(Integer, Char, Short, Byte).
*
* Otherwise, check that the first object is an instance of Comparable, and compare
* against the second object. If that is null, return 1, otherwise
* return the result of comparing against the second object.
*
* Similarly, if the second object is Comparable, if the first is null, return -1,
* else return the result of comparing against the first object.
*
* A null object is considered as:
* <ul>
* <li>ZERO when compared with Numbers</li>
* <li>the empty string for String compares</li>
* <li>Otherwise null is considered to be lower than anything else.</li>
* </ul>
*
* @param ctx the context in which this comparison is taking place
* @param obj0 first object
* @param obj1 second object
* @return -1, 0, or 1 if this object is less than, equal to, or greater than val.
* @throws ELException if neither object is Comparable
* @throws ClassCastException if the objects are not mutually comparable
*/
public static final int compare(final ELContext ctx, final Object obj0, final Object obj1)
throws ELException {
if (obj0 == obj1 || equals(ctx, obj0, obj1)) {
return 0;
}
if (isBigDecimalOp(obj0, obj1)) {
BigDecimal bd0 = (BigDecimal) coerceToNumber(ctx, obj0, BigDecimal.class);
BigDecimal bd1 = (BigDecimal) coerceToNumber(ctx, obj1, BigDecimal.class);
return bd0.compareTo(bd1);
}
if (isDoubleOp(obj0, obj1)) {
Double d0 = (Double) coerceToNumber(ctx, obj0, Double.class);
Double d1 = (Double) coerceToNumber(ctx, obj1, Double.class);
return d0.compareTo(d1);
}
if (isBigIntegerOp(obj0, obj1)) {
BigInteger bi0 = (BigInteger) coerceToNumber(ctx, obj0, BigInteger.class);
BigInteger bi1 = (BigInteger) coerceToNumber(ctx, obj1, BigInteger.class);
return bi0.compareTo(bi1);
}
if (isLongOp(obj0, obj1)) {
Long l0 = (Long) coerceToNumber(ctx, obj0, Long.class);
Long l1 = (Long) coerceToNumber(ctx, obj1, Long.class);
return l0.compareTo(l1);
}
if (obj0 instanceof String || obj1 instanceof String) {
return coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1));
}
if (obj0 instanceof Comparable<?>) {
@SuppressWarnings("unchecked") // checked above
final Comparable<Object> comparable = (Comparable<Object>) obj0;
return (obj1 != null) ? comparable.compareTo(obj1) : 1;
}
if (obj1 instanceof Comparable<?>) {
@SuppressWarnings("unchecked") // checked above
final Comparable<Object> comparable = (Comparable<Object>) obj1;
return (obj0 != null) ? -comparable.compareTo(obj0) : -1;
}
throw new ELException(MessageFactory.get("error.compare", obj0, obj1));
}
/**
* Compare two objects for equality, after coercing to the same type if appropriate.
*
* If the objects are identical (including both null) return true.
* If either object is null, return false.
* If either object is Boolean, coerce both to Boolean and check equality.
* Similarly for Enum, String, BigDecimal, Double(Float), Long(Integer, Short, Byte, Character)
* Otherwise default to using Object.equals().
*
* @param ctx the context in which this equality test is taking place
* @param obj0 the first object
* @param obj1 the second object
* @return true if the objects are equal
* @throws ELException if one of the coercion fails
*/
public static final boolean equals(final ELContext ctx, final Object obj0, final Object obj1)
throws ELException {
if (obj0 == obj1) {
return true;
} else if (obj0 == null || obj1 == null) {
return false;
} else if (isBigDecimalOp(obj0, obj1)) {
BigDecimal bd0 = (BigDecimal) coerceToNumber(ctx, obj0, BigDecimal.class);
BigDecimal bd1 = (BigDecimal) coerceToNumber(ctx, obj1, BigDecimal.class);
return bd0.equals(bd1);
} else if (isDoubleOp(obj0, obj1)) {
Double d0 = (Double) coerceToNumber(ctx, obj0, Double.class);
Double d1 = (Double) coerceToNumber(ctx, obj1, Double.class);
return d0.equals(d1);
} else if (isBigIntegerOp(obj0, obj1)) {
BigInteger bi0 = (BigInteger) coerceToNumber(ctx, obj0, BigInteger.class);
BigInteger bi1 = (BigInteger) coerceToNumber(ctx, obj1, BigInteger.class);
return bi0.equals(bi1);
} else if (isLongOp(obj0, obj1)) {
Long l0 = (Long) coerceToNumber(ctx, obj0, Long.class);
Long l1 = (Long) coerceToNumber(ctx, obj1, Long.class);
return l0.equals(l1);
} else if (obj0 instanceof Boolean || obj1 instanceof Boolean) {
return coerceToBoolean(ctx, obj0, false).equals(coerceToBoolean(ctx, obj1, false));
} else if (obj0.getClass().isEnum()) {
return obj0.equals(coerceToEnum(ctx, obj1, obj0.getClass()));
} else if (obj1.getClass().isEnum()) {
return obj1.equals(coerceToEnum(ctx, obj0, obj1.getClass()));
} else if (obj0 instanceof String || obj1 instanceof String) {
int lexCompare = coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1));
return (lexCompare == 0) ? true : false;
} else {
return obj0.equals(obj1);
}
}
// Going to have to have some casts /raw types somewhere so doing it here
// keeps them all in one place. There might be a neater / better solution
// but I couldn't find it
@SuppressWarnings("unchecked")
public static final Enum<?> coerceToEnum(final ELContext ctx, final Object obj,
@SuppressWarnings("rawtypes") Class type) {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object result = ctx.getELResolver().convertToType(ctx, obj, type);
if (ctx.isPropertyResolved()) {
return (Enum<?>) result;
}
} finally {
ctx.setPropertyResolved(originalIsPropertyResolved);
}
}
if (obj == null || "".equals(obj)) {
return null;
}
if (type.isAssignableFrom(obj.getClass())) {
return (Enum<?>) obj;
}
if (!(obj instanceof String)) {
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), type));
}
Enum<?> result;
try {
result = Enum.valueOf(type, (String) obj);
} catch (IllegalArgumentException iae) {
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), type));
}
return result;
}
/**
* Convert an object to Boolean.
* Null and empty string are false.
* @param ctx the context in which this conversion is taking place
* @param obj the object to convert
* @param primitive is the target a primitive in which case coercion to null
* is not permitted
* @return the Boolean value of the object
* @throws ELException if object is not Boolean or String
*/
public static final Boolean coerceToBoolean(final ELContext ctx, final Object obj,
boolean primitive) throws ELException {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object result = ctx.getELResolver().convertToType(ctx, obj, Boolean.class);
if (ctx.isPropertyResolved()) {
return (Boolean) result;
}
} finally {
ctx.setPropertyResolved(originalIsPropertyResolved);
}
}
if (!COERCE_TO_ZERO && !primitive) {
if (obj == null) {
return null;
}
}
if (obj == null || "".equals(obj)) {
return Boolean.FALSE;
}
if (obj instanceof Boolean) {
return (Boolean) obj;
}
if (obj instanceof String) {
return Boolean.valueOf((String) obj);
}
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), Boolean.class));
}
private static final Character coerceToCharacter(final ELContext ctx, final Object obj)
throws ELException {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object result = ctx.getELResolver().convertToType(ctx, obj, Character.class);
if (ctx.isPropertyResolved()) {
return (Character) result;
}
} finally {
ctx.setPropertyResolved(originalIsPropertyResolved);
}
}
if (obj == null || "".equals(obj)) {
return Character.valueOf((char) 0);
}
if (obj instanceof String) {
return Character.valueOf(((String) obj).charAt(0));
}
if (ELArithmetic.isNumber(obj)) {
return Character.valueOf((char) ((Number) obj).shortValue());
}
Class<?> objType = obj.getClass();
if (obj instanceof Character) {
return (Character) obj;
}
throw new ELException(MessageFactory.get("error.convert",
obj, objType, Character.class));
}
protected static final Number coerceToNumber(final Number number,
final Class<?> type) throws ELException {
if (Long.TYPE == type || Long.class.equals(type)) {
return Long.valueOf(number.longValue());
}
if (Double.TYPE == type || Double.class.equals(type)) {
return Double.valueOf(number.doubleValue());
}
if (Integer.TYPE == type || Integer.class.equals(type)) {
return Integer.valueOf(number.intValue());
}
if (BigInteger.class.equals(type)) {
if (number instanceof BigDecimal) {
return ((BigDecimal) number).toBigInteger();
}
if (number instanceof BigInteger) {
return number;
}
return BigInteger.valueOf(number.longValue());
}
if (BigDecimal.class.equals(type)) {
if (number instanceof BigDecimal) {
return number;
}
if (number instanceof BigInteger) {
return new BigDecimal((BigInteger) number);
}
return new BigDecimal(number.doubleValue());
}
if (Byte.TYPE == type || Byte.class.equals(type)) {
return Byte.valueOf(number.byteValue());
}
if (Short.TYPE == type || Short.class.equals(type)) {
return Short.valueOf(number.shortValue());
}
if (Float.TYPE == type || Float.class.equals(type)) {
return Float.valueOf(number.floatValue());
}
if (Number.class.equals(type)) {
return number;
}
throw new ELException(MessageFactory.get("error.convert",
number, number.getClass(), type));
}
public static final Number coerceToNumber(final ELContext ctx, final Object obj,
final Class<?> type) throws ELException {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object result = ctx.getELResolver().convertToType(ctx, obj, type);
if (ctx.isPropertyResolved()) {
return (Number) result;
}
} finally {
ctx.setPropertyResolved(originalIsPropertyResolved);
}
}
if (!COERCE_TO_ZERO) {
if (obj == null && !type.isPrimitive()) {
return null;
}
}
if (obj == null || "".equals(obj)) {
return coerceToNumber(ZERO, type);
}
if (obj instanceof String) {
return coerceToNumber((String) obj, type);
}
if (ELArithmetic.isNumber(obj)) {
return coerceToNumber((Number) obj, type);
}
if (obj instanceof Character) {
return coerceToNumber(Short.valueOf((short) ((Character) obj)
.charValue()), type);
}
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), type));
}
protected static final Number coerceToNumber(final String val,
final Class<?> type) throws ELException {
if (Long.TYPE == type || Long.class.equals(type)) {
try {
return Long.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (Integer.TYPE == type || Integer.class.equals(type)) {
try {
return Integer.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (Double.TYPE == type || Double.class.equals(type)) {
try {
return Double.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (BigInteger.class.equals(type)) {
try {
return new BigInteger(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (BigDecimal.class.equals(type)) {
try {
return new BigDecimal(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (Byte.TYPE == type || Byte.class.equals(type)) {
try {
return Byte.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (Short.TYPE == type || Short.class.equals(type)) {
try {
return Short.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
if (Float.TYPE == type || Float.class.equals(type)) {
try {
return Float.valueOf(val);
} catch (NumberFormatException nfe) {
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
}
throw new ELException(MessageFactory.get("error.convert",
val, String.class, type));
}
/**
* Coerce an object to a string.
* @param ctx the context in which this conversion is taking place
* @param obj the object to convert
* @return the String value of the object
*/
public static final String coerceToString(final ELContext ctx, final Object obj) {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object result = ctx.getELResolver().convertToType(ctx, obj, String.class);
if (ctx.isPropertyResolved()) {
return (String) result;
}
} finally {
ctx.setPropertyResolved(originalIsPropertyResolved);
}
}
if (obj == null) {
return "";
} else if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof Enum<?>) {
return ((Enum<?>) obj).name();
} else {
return obj.toString();
}
}
public static final Object coerceToType(final ELContext ctx, final Object obj,
final Class<?> type) throws ELException {
if (ctx != null) {
boolean originalIsPropertyResolved = ctx.isPropertyResolved();
try {
Object 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()))) {
return obj;
}
if (!COERCE_TO_ZERO) {
if (obj == null && !type.isPrimitive() &&
!String.class.isAssignableFrom(type)) {
return null;
}
}
if (String.class.equals(type)) {
return coerceToString(ctx, obj);
}
if (ELArithmetic.isNumberType(type)) {
return coerceToNumber(ctx, obj, type);
}
if (Character.class.equals(type) || Character.TYPE == type) {
return coerceToCharacter(ctx, obj);
}
if (Boolean.class.equals(type) || Boolean.TYPE == type) {
return coerceToBoolean(ctx, obj, Boolean.TYPE == type);
}
if (type.isEnum()) {
return coerceToEnum(ctx, obj, type);
}
// new to spec
if (obj == null)
return null;
if (obj instanceof String) {
PropertyEditor editor = PropertyEditorManager.findEditor(type);
if (editor == null) {
if ("".equals(obj)) {
return null;
}
throw new ELException(MessageFactory.get("error.convert", obj,
obj.getClass(), type));
} else {
try {
editor.setAsText((String) obj);
return editor.getValue();
} catch (RuntimeException e) {
if ("".equals(obj)) {
return null;
}
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), type), e);
}
}
}
// Handle special case because the syntax for the empty set is the same
// for an empty map. The parser will always parse {} as an empty set.
if (obj instanceof Set && type == Map.class &&
((Set<?>) obj).isEmpty()) {
return Collections.EMPTY_MAP;
}
// Handle arrays
if (type.isArray() && obj.getClass().isArray()) {
return coerceToArray(ctx, obj, type);
}
throw new ELException(MessageFactory.get("error.convert",
obj, obj.getClass(), type));
}
private static Object coerceToArray(final ELContext ctx, final Object obj,
final Class<?> type) {
// Note: Nested arrays will result in nested calls to this method.
// Note: Calling method has checked the obj is an array.
int size = Array.getLength(obj);
// Cast the input object to an array (calling method has checked it is
// an array)
// Get the target type for the array elements
Class<?> componentType = type.getComponentType();
// Create a new array of the correct type
Object result = Array.newInstance(componentType, size);
// Coerce each element in turn.
for (int i = 0; i < size; i++) {
Array.set(result, i, coerceToType(ctx, Array.get(obj, i), componentType));
}
return result;
}
public static final boolean isBigDecimalOp(final Object obj0,
final Object obj1) {
return (obj0 instanceof BigDecimal || obj1 instanceof BigDecimal);
}
public static final boolean isBigIntegerOp(final Object obj0,
final Object obj1) {
return (obj0 instanceof BigInteger || obj1 instanceof BigInteger);
}
public static final boolean isDoubleOp(final Object obj0, final Object obj1) {
return (obj0 instanceof Double
|| obj1 instanceof Double
|| obj0 instanceof Float
|| obj1 instanceof Float);
}
public static final boolean isLongOp(final Object obj0, final Object obj1) {
return (obj0 instanceof Long
|| obj1 instanceof Long
|| obj0 instanceof Integer
|| obj1 instanceof Integer
|| obj0 instanceof Character
|| obj1 instanceof Character
|| obj0 instanceof Short
|| obj1 instanceof Short
|| obj0 instanceof Byte
|| obj1 instanceof Byte);
}
public static final boolean isStringFloat(final String str) {
int len = str.length();
if (len > 1) {
for (int i = 0; i < len; i++) {
switch (str.charAt(i)) {
case 'E':
return true;
case 'e':
return true;
case '.':
return true;
}
}
}
return false;
}
/**
*
*/
public ELSupport() {
super();
}
}

View File

@@ -0,0 +1,157 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.EvaluationListener;
import javax.el.FunctionMapper;
import javax.el.ImportHandler;
import javax.el.VariableMapper;
public final class EvaluationContext extends ELContext {
private final ELContext elContext;
private final FunctionMapper fnMapper;
private final VariableMapper varMapper;
public EvaluationContext(ELContext elContext, FunctionMapper fnMapper,
VariableMapper varMapper) {
this.elContext = elContext;
this.fnMapper = fnMapper;
this.varMapper = varMapper;
}
public ELContext getELContext() {
return elContext;
}
@Override
public FunctionMapper getFunctionMapper() {
return fnMapper;
}
@Override
public VariableMapper getVariableMapper() {
return varMapper;
}
@Override
// Can't use Class<?> because API needs to match specification in superclass
public Object getContext(@SuppressWarnings("rawtypes") Class key) {
return elContext.getContext(key);
}
@Override
public ELResolver getELResolver() {
return elContext.getELResolver();
}
@Override
public boolean isPropertyResolved() {
return elContext.isPropertyResolved();
}
@Override
// Can't use Class<?> because API needs to match specification in superclass
public void putContext(@SuppressWarnings("rawtypes") Class key,
Object contextObject) {
elContext.putContext(key, contextObject);
}
@Override
public void setPropertyResolved(boolean resolved) {
elContext.setPropertyResolved(resolved);
}
@Override
public Locale getLocale() {
return elContext.getLocale();
}
@Override
public void setLocale(Locale locale) {
elContext.setLocale(locale);
}
@Override
public void setPropertyResolved(Object base, Object property) {
elContext.setPropertyResolved(base, property);
}
@Override
public ImportHandler getImportHandler() {
return elContext.getImportHandler();
}
@Override
public void addEvaluationListener(EvaluationListener listener) {
elContext.addEvaluationListener(listener);
}
@Override
public List<EvaluationListener> getEvaluationListeners() {
return elContext.getEvaluationListeners();
}
@Override
public void notifyBeforeEvaluation(String expression) {
elContext.notifyBeforeEvaluation(expression);
}
@Override
public void notifyAfterEvaluation(String expression) {
elContext.notifyAfterEvaluation(expression);
}
@Override
public void notifyPropertyResolved(Object base, Object property) {
elContext.notifyPropertyResolved(base, property);
}
@Override
public boolean isLambdaArgument(String name) {
return elContext.isLambdaArgument(name);
}
@Override
public Object getLambdaArgument(String name) {
return elContext.getLambdaArgument(name);
}
@Override
public void enterLambdaScope(Map<String, Object> arguments) {
elContext.enterLambdaScope(arguments);
}
@Override
public void exitLambdaScope() {
elContext.exitLambdaScope();
}
@Override
public Object convertToType(Object obj, Class<?> type) {
return elContext.convertToType(obj, type);
}
}

View File

@@ -0,0 +1,337 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.FunctionMapper;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import org.apache.el.MethodExpressionImpl;
import org.apache.el.MethodExpressionLiteral;
import org.apache.el.ValueExpressionImpl;
import org.apache.el.parser.AstDeferredExpression;
import org.apache.el.parser.AstDynamicExpression;
import org.apache.el.parser.AstFunction;
import org.apache.el.parser.AstIdentifier;
import org.apache.el.parser.AstLiteralExpression;
import org.apache.el.parser.AstValue;
import org.apache.el.parser.ELParser;
import org.apache.el.parser.Node;
import org.apache.el.parser.NodeVisitor;
import org.apache.el.util.ConcurrentCache;
import org.apache.el.util.MessageFactory;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class ExpressionBuilder implements NodeVisitor {
private static final SynchronizedStack<ELParser> parserCache = new SynchronizedStack<>();
private static final int CACHE_SIZE;
private static final String CACHE_SIZE_PROP =
"org.apache.el.ExpressionBuilder.CACHE_SIZE";
static {
String cacheSizeStr;
if (System.getSecurityManager() == null) {
cacheSizeStr = System.getProperty(CACHE_SIZE_PROP, "5000");
} else {
cacheSizeStr = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty(CACHE_SIZE_PROP, "5000");
}
});
}
CACHE_SIZE = Integer.parseInt(cacheSizeStr);
}
private static final ConcurrentCache<String, Node> expressionCache =
new ConcurrentCache<>(CACHE_SIZE);
private FunctionMapper fnMapper;
private VariableMapper varMapper;
private final String expression;
public ExpressionBuilder(String expression, ELContext ctx)
throws ELException {
this.expression = expression;
FunctionMapper ctxFn = ctx.getFunctionMapper();
VariableMapper ctxVar = ctx.getVariableMapper();
if (ctxFn != null) {
this.fnMapper = new FunctionMapperFactory(ctxFn);
}
if (ctxVar != null) {
this.varMapper = new VariableMapperFactory(ctxVar);
}
}
public static final Node createNode(String expr) throws ELException {
Node n = createNodeInternal(expr);
return n;
}
private static final Node createNodeInternal(String expr)
throws ELException {
if (expr == null) {
throw new ELException(MessageFactory.get("error.null"));
}
Node n = expressionCache.get(expr);
if (n == null) {
ELParser parser = parserCache.pop();
try {
if (parser == null) {
parser = new ELParser(new StringReader(expr));
} else {
parser.ReInit(new StringReader(expr));
}
n = parser.CompositeExpression();
// validate composite expression
int numChildren = n.jjtGetNumChildren();
if (numChildren == 1) {
n = n.jjtGetChild(0);
} else {
Class<?> type = null;
Node child = null;
for (int i = 0; i < numChildren; i++) {
child = n.jjtGetChild(i);
if (child instanceof AstLiteralExpression)
continue;
if (type == null)
type = child.getClass();
else {
if (!type.equals(child.getClass())) {
throw new ELException(MessageFactory.get(
"error.mixed", expr));
}
}
}
}
if (n instanceof AstDeferredExpression
|| n instanceof AstDynamicExpression) {
n = n.jjtGetChild(0);
}
expressionCache.put(expr, n);
} catch (Exception e) {
throw new ELException(
MessageFactory.get("error.parseFail", expr), e);
} finally {
if (parser != null) {
parserCache.push(parser);
}
}
}
return n;
}
private void prepare(Node node) throws ELException {
try {
node.accept(this);
} catch (Exception e) {
if (e instanceof ELException) {
throw (ELException) e;
} else {
throw (new ELException(e));
}
}
if (this.fnMapper instanceof FunctionMapperFactory) {
this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create();
}
if (this.varMapper instanceof VariableMapperFactory) {
this.varMapper = ((VariableMapperFactory) this.varMapper).create();
}
}
private Node build() throws ELException {
Node n = createNodeInternal(this.expression);
this.prepare(n);
if (n instanceof AstDeferredExpression
|| n instanceof AstDynamicExpression) {
n = n.jjtGetChild(0);
}
return n;
}
/*
* (non-Javadoc)
*
* @see com.sun.el.parser.NodeVisitor#visit(com.sun.el.parser.Node)
*/
@Override
public void visit(Node node) throws ELException {
if (node instanceof AstFunction) {
AstFunction funcNode = (AstFunction) node;
Method m = null;
if (this.fnMapper != null) {
m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode
.getLocalName());
}
// References to variables that refer to lambda expressions will be
// parsed as functions. This is handled at runtime but at this point
// need to treat it as a variable rather than a function.
if (m == null && this.varMapper != null &&
funcNode.getPrefix().length() == 0) {
this.varMapper.resolveVariable(funcNode.getLocalName());
return;
}
if (this.fnMapper == null) {
throw new ELException(MessageFactory.get("error.fnMapper.null"));
}
if (m == null) {
throw new ELException(MessageFactory.get(
"error.fnMapper.method", funcNode.getOutputName()));
}
int methodParameterCount = m.getParameterTypes().length;
// AstFunction->MethodParameters->Parameters()
int inputParameterCount = node.jjtGetChild(0).jjtGetNumChildren();
if (m.isVarArgs() && inputParameterCount < methodParameterCount - 1 ||
!m.isVarArgs() && inputParameterCount != methodParameterCount) {
throw new ELException(MessageFactory.get(
"error.fnMapper.paramcount", funcNode.getOutputName(),
"" + methodParameterCount, "" + node.jjtGetChild(0).jjtGetNumChildren()));
}
} else if (node instanceof AstIdentifier && this.varMapper != null) {
String variable = ((AstIdentifier) node).getImage();
// simply capture it
this.varMapper.resolveVariable(variable);
}
}
public ValueExpression createValueExpression(Class<?> expectedType)
throws ELException {
Node n = this.build();
return new ValueExpressionImpl(this.expression, n, this.fnMapper,
this.varMapper, expectedType);
}
public MethodExpression createMethodExpression(Class<?> expectedReturnType,
Class<?>[] expectedParamTypes) throws ELException {
Node n = this.build();
if (!n.isParametersProvided() && expectedParamTypes == null) {
throw new NullPointerException(MessageFactory
.get("error.method.nullParms"));
}
if (n instanceof AstValue || n instanceof AstIdentifier) {
return new MethodExpressionImpl(expression, n, this.fnMapper,
this.varMapper, expectedReturnType, expectedParamTypes);
} else if (n instanceof AstLiteralExpression) {
return new MethodExpressionLiteral(expression, expectedReturnType,
expectedParamTypes);
} else {
throw new ELException("Not a Valid Method Expression: "
+ expression);
}
}
/*
* Copied from org.apache.tomcat.util.collections.SynchronizedStack since
* we don't want the EL implementation to depend on the JAR where that
* class resides.
*/
private static class SynchronizedStack<T> {
public static final int DEFAULT_SIZE = 128;
private static final int DEFAULT_LIMIT = -1;
private int size;
private final int limit;
/*
* Points to the next available object in the stack
*/
private int index = -1;
private Object[] stack;
public SynchronizedStack() {
this(DEFAULT_SIZE, DEFAULT_LIMIT);
}
public SynchronizedStack(int size, int limit) {
this.size = size;
this.limit = limit;
stack = new Object[size];
}
public synchronized boolean push(T obj) {
index++;
if (index == size) {
if (limit == -1 || size < limit) {
expand();
} else {
index--;
return false;
}
}
stack[index] = obj;
return true;
}
@SuppressWarnings("unchecked")
public synchronized T pop() {
if (index == -1) {
return null;
}
T result = (T) stack[index];
stack[index--] = null;
return result;
}
private void expand() {
int newSize = size * 2;
if (limit != -1 && newSize > limit) {
newSize = limit;
}
Object[] newStack = new Object[newSize];
System.arraycopy(stack, 0, newStack, 0, size);
// This is the only point where garbage is created by throwing away the
// old array. Note it is only the array, not the contents, that becomes
// garbage.
stack = newStack;
size = newSize;
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.lang.reflect.Method;
import javax.el.FunctionMapper;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public class FunctionMapperFactory extends FunctionMapper {
protected FunctionMapperImpl memento = null;
protected final FunctionMapper target;
public FunctionMapperFactory(FunctionMapper mapper) {
if (mapper == null) {
throw new NullPointerException("FunctionMapper target cannot be null");
}
this.target = mapper;
}
/* (non-Javadoc)
* @see javax.el.FunctionMapper#resolveFunction(java.lang.String, java.lang.String)
*/
@Override
public Method resolveFunction(String prefix, String localName) {
if (this.memento == null) {
this.memento = new FunctionMapperImpl();
}
Method m = this.target.resolveFunction(prefix, localName);
if (m != null) {
this.memento.mapFunction(prefix, localName, m);
}
return m;
}
@Override
public void mapFunction(String prefix, String localName, Method method) {
if (this.memento == null) {
this.memento = new FunctionMapperImpl();
}
memento.mapFunction(prefix, localName, method);
}
public FunctionMapper create() {
return this.memento;
}
}

View File

@@ -0,0 +1,188 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.el.FunctionMapper;
import org.apache.el.util.ReflectionUtil;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public class FunctionMapperImpl extends FunctionMapper implements
Externalizable {
private static final long serialVersionUID = 1L;
protected ConcurrentMap<String, Function> functions = new ConcurrentHashMap<>();
/*
* (non-Javadoc)
*
* @see javax.el.FunctionMapper#resolveFunction(java.lang.String,
* java.lang.String)
*/
@Override
public Method resolveFunction(String prefix, String localName) {
Function f = this.functions.get(prefix + ":" + localName);
if (f == null) {
return null;
}
return f.getMethod();
}
@Override
public void mapFunction(String prefix, String localName, Method m) {
String key = prefix + ":" + localName;
if (m == null) {
functions.remove(key);
} else {
Function f = new Function(prefix, localName, m);
functions.put(key, f);
}
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.functions);
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
@SuppressWarnings("unchecked")
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.functions = (ConcurrentMap<String, Function>) in.readObject();
}
public static class Function implements Externalizable {
protected transient Method m;
protected String owner;
protected String name;
protected String[] types;
protected String prefix;
protected String localName;
public Function(String prefix, String localName, Method m) {
if (localName == null) {
throw new NullPointerException("LocalName cannot be null");
}
if (m == null) {
throw new NullPointerException("Method cannot be null");
}
this.prefix = prefix;
this.localName = localName;
this.m = m;
}
public Function() {
// for serialization
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF((this.prefix != null) ? this.prefix : "");
out.writeUTF(this.localName);
// make sure m isn't null
getMethod();
out.writeUTF((this.owner != null) ?
this.owner :
this.m.getDeclaringClass().getName());
out.writeUTF((this.name != null) ?
this.name :
this.m.getName());
out.writeObject((this.types != null) ?
this.types :
ReflectionUtil.toTypeNameArray(this.m.getParameterTypes()));
}
/*
* (non-Javadoc)
*
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
*/
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.prefix = in.readUTF();
if ("".equals(this.prefix)) this.prefix = null;
this.localName = in.readUTF();
this.owner = in.readUTF();
this.name = in.readUTF();
this.types = (String[]) in.readObject();
}
public Method getMethod() {
if (this.m == null) {
try {
Class<?> t = ReflectionUtil.forName(this.owner);
Class<?>[] p = ReflectionUtil.toTypeArray(this.types);
this.m = t.getMethod(this.name, p);
} catch (Exception e) {
e.printStackTrace();
}
}
return this.m;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Function) {
return this.hashCode() == obj.hashCode();
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return (this.prefix + this.localName).hashCode();
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
public class VariableMapperFactory extends VariableMapper {
private final VariableMapper target;
private VariableMapper momento;
public VariableMapperFactory(VariableMapper target) {
if (target == null) {
throw new NullPointerException("Target VariableMapper cannot be null");
}
this.target = target;
}
public VariableMapper create() {
return this.momento;
}
@Override
public ValueExpression resolveVariable(String variable) {
ValueExpression expr = this.target.resolveVariable(variable);
if (expr != null) {
if (this.momento == null) {
this.momento = new VariableMapperImpl();
}
this.momento.setVariable(variable, expr);
}
return expr;
}
@Override
public ValueExpression setVariable(String variable, ValueExpression expression) {
throw new UnsupportedOperationException("Cannot Set Variables on Factory");
}
}

View File

@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.lang;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Map;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
public class VariableMapperImpl extends VariableMapper implements Externalizable {
private static final long serialVersionUID = 1L;
private Map<String, ValueExpression> vars = new HashMap<>();
public VariableMapperImpl() {
super();
}
@Override
public ValueExpression resolveVariable(String variable) {
return this.vars.get(variable);
}
@Override
public ValueExpression setVariable(String variable,
ValueExpression expression) {
if (expression == null) {
return vars.remove(variable);
} else {
return vars.put(variable, expression);
}
}
@SuppressWarnings("unchecked")
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
this.vars = (Map<String, ValueExpression>) in.readObject();
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.vars);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public abstract class ArithmeticNode extends SimpleNode {
public ArithmeticNode(int i) {
super(i);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return Number.class;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstAnd.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstAnd extends BooleanNode {
public AstAnd(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj = children[0].getValue(ctx);
Boolean b = coerceToBoolean(ctx, obj, true);
if (!b.booleanValue()) {
return b;
}
obj = children[1].getValue(ctx);
b = coerceToBoolean(ctx, obj, true);
return b;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstAssign.java Version 4.3 */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstAssign extends SimpleNode {
public AstAssign(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
Object value = children[1].getValue(ctx);
children[0].setValue(ctx, value);
return value;
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
Object value = children[1].getValue(ctx);
children[0].setValue(ctx, value);
return children[1].getType(ctx);
}
}
/* JavaCC - OriginalChecksum=151e58546054b618e758d7dc172cc7b5 (do not edit this line) */

View File

@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstBracketSuffix.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstBracketSuffix extends SimpleNode {
public AstBracketSuffix(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.children[0].getValue(ctx);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstChoice.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstChoice extends SimpleNode {
public AstChoice(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
Object val = this.getValue(ctx);
return (val != null) ? val.getClass() : null;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Boolean b0 = coerceToBoolean(ctx, obj0, true);
return this.children[((b0.booleanValue() ? 1 : 2))].getValue(ctx);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstCompositeExpression.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstCompositeExpression extends SimpleNode {
public AstCompositeExpression(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return String.class;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
StringBuilder sb = new StringBuilder(16);
Object obj = null;
if (this.children != null) {
for (int i = 0; i < this.children.length; i++) {
obj = this.children[i].getValue(ctx);
if (obj != null) {
sb.append(ELSupport.coerceToString(ctx, obj));
}
}
}
return sb.toString();
}
}

View File

@@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstConcatenation.java Version 4.3 */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstConcatenation extends SimpleNode {
public AstConcatenation(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
// Coerce the two child nodes to string and then concatenate
String s1 = coerceToString(ctx, children[0].getValue(ctx));
String s2 = coerceToString(ctx, children[1].getValue(ctx));
return s1 + s2;
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
return String.class;
}
}
/* JavaCC - OriginalChecksum=a95de353974c2c05fa5c7d695a1d50fd (do not edit this line) */

View File

@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstDeferredExpression.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstDeferredExpression extends SimpleNode {
public AstDeferredExpression(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return this.children[0].getType(ctx);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.children[0].getValue(ctx);
}
@Override
public boolean isReadOnly(EvaluationContext ctx)
throws ELException {
return this.children[0].isReadOnly(ctx);
}
@Override
public void setValue(EvaluationContext ctx, Object value)
throws ELException {
this.children[0].setValue(ctx, value);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstDiv.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstDiv extends ArithmeticNode {
public AstDiv(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return ELArithmetic.divide(obj0, obj1);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstDotSuffix.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.Validation;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstDotSuffix extends SimpleNode {
public AstDotSuffix(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.image;
}
@Override
public void setImage(String image) {
if (!Validation.isIdentifier(image)) {
throw new ELException(MessageFactory.get("error.identifier.notjava",
image));
}
this.image = image;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstDynamicExpression.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstDynamicExpression extends SimpleNode {
public AstDynamicExpression(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return this.children[0].getType(ctx);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.children[0].getValue(ctx);
}
@Override
public boolean isReadOnly(EvaluationContext ctx)
throws ELException {
return this.children[0].isReadOnly(ctx);
}
@Override
public void setValue(EvaluationContext ctx, Object value)
throws ELException {
this.children[0].setValue(ctx, value);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstEmpty.java */
package org.apache.el.parser;
import java.util.Collection;
import java.util.Map;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstEmpty extends SimpleNode {
public AstEmpty(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return Boolean.class;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj = this.children[0].getValue(ctx);
if (obj == null) {
return Boolean.TRUE;
} else if (obj instanceof String) {
return Boolean.valueOf(((String) obj).length() == 0);
} else if (obj instanceof Object[]) {
return Boolean.valueOf(((Object[]) obj).length == 0);
} else if (obj instanceof Collection<?>) {
return Boolean.valueOf(((Collection<?>) obj).isEmpty());
} else if (obj instanceof Map<?,?>) {
return Boolean.valueOf(((Map<?,?>) obj).isEmpty());
}
return Boolean.FALSE;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstEqual.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstEqual extends BooleanNode {
public AstEqual(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return Boolean.valueOf(equals(ctx, obj0, obj1));
}
}

View File

@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstFalse.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstFalse extends BooleanNode {
public AstFalse(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return Boolean.FALSE;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstFloatingPoint.java */
package org.apache.el.parser;
import java.math.BigDecimal;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstFloatingPoint extends SimpleNode {
public AstFloatingPoint(int id) {
super(id);
}
private volatile Number number;
public Number getFloatingPoint() {
if (this.number == null) {
try {
this.number = Double.valueOf(this.image);
} catch (ArithmeticException e0) {
this.number = new BigDecimal(this.image);
}
}
return this.number;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.getFloatingPoint();
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return this.getFloatingPoint().getClass();
}
}

View File

@@ -0,0 +1,231 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstFunction.java */
package org.apache.el.parser;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.el.ELClass;
import javax.el.ELException;
import javax.el.FunctionMapper;
import javax.el.LambdaExpression;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.util.MessageFactory;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstFunction extends SimpleNode {
protected String localName = "";
protected String prefix = "";
public AstFunction(int id) {
super(id);
}
public String getLocalName() {
return localName;
}
public String getOutputName() {
if (this.prefix == null) {
return this.localName;
} else {
return this.prefix + ":" + this.localName;
}
}
public String getPrefix() {
return prefix;
}
@Override
public Class<?> getType(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) {
throw new ELException(MessageFactory.get("error.fnMapper.method",
this.getOutputName()));
}
return m.getReturnType();
}
@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()) {
// Haven't consumed all the sets of parameters therefore
// 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()));
}
// Not a lambda expression so must be a function. Check there is just a
// single set of method parameters
if (this.jjtGetNumChildren() != 1) {
throw new ELException(MessageFactory.get(
"error.funciton.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] = coerceToType(ctx, varargs[j-i], target);
}
params[i] = varargs;
}
} else {
params[i] = parameters.jjtGetChild(i).getValue(ctx);
}
params[i] = 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;
}
public void setLocalName(String localName) {
this.localName = localName;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
@Override
public String toString()
{
return ELParserTreeConstants.jjtNodeName[id] + "[" + this.getOutputName() + "]";
}
}

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstGreaterThan.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstGreaterThan extends BooleanNode {
public AstGreaterThan(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
if (obj0 == null) {
return Boolean.FALSE;
}
Object obj1 = this.children[1].getValue(ctx);
if (obj1 == null) {
return Boolean.FALSE;
}
return (compare(ctx, obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstGreaterThanEqual.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstGreaterThanEqual extends BooleanNode {
public AstGreaterThanEqual(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
if (obj0 == obj1) {
return Boolean.TRUE;
}
if (obj0 == null || obj1 == null) {
return Boolean.FALSE;
}
return (compare(ctx, obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE;
}
}

View File

@@ -0,0 +1,238 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstIdentifier.java */
package org.apache.el.parser;
import javax.el.ELClass;
import javax.el.ELException;
import javax.el.MethodExpression;
import javax.el.MethodInfo;
import javax.el.MethodNotFoundException;
import javax.el.PropertyNotFoundException;
import javax.el.ValueExpression;
import javax.el.ValueReference;
import javax.el.VariableMapper;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.Validation;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstIdentifier extends SimpleNode {
public AstIdentifier(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
VariableMapper varMapper = ctx.getVariableMapper();
if (varMapper != null) {
ValueExpression expr = varMapper.resolveVariable(this.image);
if (expr != null) {
return expr.getType(ctx.getELContext());
}
}
ctx.setPropertyResolved(false);
Class<?> result = ctx.getELResolver().getType(ctx, null, this.image);
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled.null", this.image));
}
return result;
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
// Lambda parameters
if (ctx.isLambdaArgument(this.image)) {
return ctx.getLambdaArgument(this.image);
}
// Variable mapper
VariableMapper varMapper = ctx.getVariableMapper();
if (varMapper != null) {
ValueExpression expr = varMapper.resolveVariable(this.image);
if (expr != null) {
return expr.getValue(ctx.getELContext());
}
}
// EL Resolvers
ctx.setPropertyResolved(false);
Object result;
/* Putting the Boolean into the ELContext is part of a performance
* optimisation for ScopedAttributeELResolver. When looking up "foo",
* the resolver can't differentiate between ${ foo } and ${ foo.bar }.
* This is important because the expensive class lookup only needs to
* be performed in the later case. This flag tells the resolver if the
* lookup can be skipped.
*/
if (parent instanceof AstValue) {
ctx.putContext(this.getClass(), Boolean.FALSE);
} else {
ctx.putContext(this.getClass(), Boolean.TRUE);
}
try {
result = ctx.getELResolver().getValue(ctx, null, this.image);
} finally {
// Always reset the flag to false so the optimisation is not applied
// inappropriately
ctx.putContext(this.getClass(), Boolean.FALSE);
}
if (ctx.isPropertyResolved()) {
return result;
}
// Import
result = ctx.getImportHandler().resolveClass(this.image);
if (result != null) {
return new ELClass((Class<?>) result);
}
result = ctx.getImportHandler().resolveStatic(this.image);
if (result != null) {
try {
return ((Class<?>) result).getField(this.image).get(null);
} catch (IllegalArgumentException | IllegalAccessException
| NoSuchFieldException | SecurityException e) {
throw new ELException(e);
}
}
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled.null", this.image));
}
@Override
public boolean isReadOnly(EvaluationContext ctx) throws ELException {
VariableMapper varMapper = ctx.getVariableMapper();
if (varMapper != null) {
ValueExpression expr = varMapper.resolveVariable(this.image);
if (expr != null) {
return expr.isReadOnly(ctx.getELContext());
}
}
ctx.setPropertyResolved(false);
boolean result = ctx.getELResolver().isReadOnly(ctx, null, this.image);
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled.null", this.image));
}
return result;
}
@Override
public void setValue(EvaluationContext ctx, Object value)
throws ELException {
VariableMapper varMapper = ctx.getVariableMapper();
if (varMapper != null) {
ValueExpression expr = varMapper.resolveVariable(this.image);
if (expr != null) {
expr.setValue(ctx.getELContext(), value);
return;
}
}
ctx.setPropertyResolved(false);
ctx.getELResolver().setValue(ctx, null, this.image, value);
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled.null", this.image));
}
}
@Override
public Object invoke(EvaluationContext ctx, Class<?>[] paramTypes,
Object[] paramValues) throws ELException {
return this.getMethodExpression(ctx).invoke(ctx.getELContext(), paramValues);
}
@Override
public MethodInfo getMethodInfo(EvaluationContext ctx,
Class<?>[] paramTypes) throws ELException {
return this.getMethodExpression(ctx).getMethodInfo(ctx.getELContext());
}
@Override
public void setImage(String image) {
if (!Validation.isIdentifier(image)) {
throw new ELException(MessageFactory.get("error.identifier.notjava",
image));
}
this.image = image;
}
@Override
public ValueReference getValueReference(EvaluationContext ctx) {
VariableMapper varMapper = ctx.getVariableMapper();
if (varMapper == null) {
return null;
}
ValueExpression expr = varMapper.resolveVariable(this.image);
if (expr == null) {
return null;
}
return expr.getValueReference(ctx);
}
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);
}
}
// case B: evaluate the identity against the ELResolver, again, must be
// 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("Identity '" + this.image
+ "' was null and was unable to invoke");
} else {
throw new ELException(
"Identity '"
+ this.image
+ "' does not reference a MethodExpression instance, returned type: "
+ obj.getClass().getName());
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstInteger.java */
package org.apache.el.parser;
import java.math.BigInteger;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstInteger extends SimpleNode {
public AstInteger(int id) {
super(id);
}
private volatile Number number;
protected Number getInteger() {
if (this.number == null) {
try {
this.number = Long.valueOf(this.image);
} catch (ArithmeticException e1) {
this.number = new BigInteger(this.image);
}
}
return number;
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return this.getInteger().getClass();
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.getInteger();
}
}

View File

@@ -0,0 +1,182 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstLambdaExpression.java Version 4.3 */
package org.apache.el.parser;
import java.util.ArrayList;
import java.util.List;
import javax.el.ELException;
import javax.el.LambdaExpression;
import org.apache.el.ValueExpressionImpl;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.util.MessageFactory;
public class AstLambdaExpression extends SimpleNode {
private NestedState nestedState = null;
public AstLambdaExpression(int id) {
super(id);
}
@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) {
// 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;
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;
}
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
// is not efficient. Be sure not to call this from 'real' code.
StringBuilder result = new StringBuilder();
for (Node n : children) {
result.append(n.toString());
}
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) */

View File

@@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstLambdaParameters.java Version 4.3 */
package org.apache.el.parser;
public class AstLambdaParameters extends SimpleNode {
public AstLambdaParameters(int id) {
super(id);
}
@Override
public String toString() {
// Purely for debug purposes. May not be complete or correct. Certainly
// is not efficient. Be sure not to call this from 'real' code.
StringBuilder result = new StringBuilder();
result.append('(');
if (children != null) {
for (Node n : children) {
result.append(n.toString());
result.append(',');
}
}
result.append(")->");
return result.toString();
}
}
/* JavaCC - OriginalChecksum=a8c1609257dac59e41c43d6ed91072c6 (do not edit this line) */

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstLessThan.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstLessThan extends BooleanNode {
public AstLessThan(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
if (obj0 == null) {
return Boolean.FALSE;
}
Object obj1 = this.children[1].getValue(ctx);
if (obj1 == null) {
return Boolean.FALSE;
}
return (compare(ctx, obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstLessThanEqual.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstLessThanEqual extends BooleanNode {
public AstLessThanEqual(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
if (obj0 == obj1) {
return Boolean.TRUE;
}
if (obj0 == null || obj1 == null) {
return Boolean.FALSE;
}
return (compare(ctx, obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstListData.java Version 4.3 */
package org.apache.el.parser;
import java.util.ArrayList;
import java.util.List;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstListData extends SimpleNode {
public AstListData(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
List<Object> result = new ArrayList<>();
if (children != null) {
for (Node child : children) {
result.add(child.getValue(ctx));
}
}
return result;
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
return List.class;
}
}
/* JavaCC - OriginalChecksum=7f2694086a9ba64558ee39d1cd719db1 (do not edit this line) */

View File

@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstLiteralExpression.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstLiteralExpression extends SimpleNode {
public AstLiteralExpression(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
return String.class;
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
return this.image;
}
@Override
public void setImage(String image) {
if (image.indexOf('\\') == -1) {
this.image = image;
return;
}
int size = image.length();
StringBuilder buf = new StringBuilder(size);
for (int i = 0; i < size; i++) {
char c = image.charAt(i);
if (c == '\\' && i + 2 < size) {
char c1 = image.charAt(i + 1);
char c2 = image.charAt(i + 2);
if ((c1 == '#' || c1 == '$') && c2 == '{') {
c = c1;
i++;
}
}
buf.append(c);
}
this.image = buf.toString();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstMapData.java Version 4.3 */
package org.apache.el.parser;
import java.util.HashMap;
import java.util.Map;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstMapData extends SimpleNode {
public AstMapData(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
Map<Object,Object> result = new HashMap<>();
if (children != null) {
for (Node child : children) {
AstMapEntry mapEntry = (AstMapEntry) child;
Object key = mapEntry.children[0].getValue(ctx);
Object value = mapEntry.children[1].getValue(ctx);
result.put(key, value);
}
}
return result;
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
return Map.class;
}
}
/* JavaCC - OriginalChecksum=a68b5c6f0a0708f478fdf8c0e6e1263e (do not edit this line) */

View File

@@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstMapEntry.java Version 4.3 */
package org.apache.el.parser;
public
class AstMapEntry extends SimpleNode {
public AstMapEntry(int id) {
super(id);
}
}
/* JavaCC - OriginalChecksum=6a7910e58a583371769800554113a8d3 (do not edit this line) */

View File

@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstDotSuffix.java */
package org.apache.el.parser;
import java.util.ArrayList;
import org.apache.el.lang.EvaluationContext;
public final class AstMethodParameters extends SimpleNode {
public AstMethodParameters(int id) {
super(id);
}
public Object[] getParameters(EvaluationContext ctx) {
ArrayList<Object> params = new ArrayList<>();
for (int i = 0; i < this.jjtGetNumChildren(); i++) {
params.add(this.jjtGetChild(i).getValue(ctx));
}
return params.toArray(new Object[params.size()]);
}
@Override
public String toString() {
// Purely for debug purposes. May not be complete or correct. Certainly
// is not efficient. Be sure not to call this from 'real' code.
StringBuilder result = new StringBuilder();
result.append('(');
if (children != null) {
for (Node n : children) {
result.append(n.toString());
result.append(',');
}
}
result.append(')');
return result.toString();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstMinus.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstMinus extends ArithmeticNode {
public AstMinus(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return ELArithmetic.subtract(obj0, obj1);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstMod.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstMod extends ArithmeticNode {
public AstMod(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return ELArithmetic.mod(obj0, obj1);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstMult.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstMult extends ArithmeticNode {
public AstMult(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return ELArithmetic.multiply(obj0, obj1);
}
}

View File

@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstNegative.java */
package org.apache.el.parser;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstNegative extends SimpleNode {
public AstNegative(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return Number.class;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj = this.children[0].getValue(ctx);
if (obj == null) {
return Long.valueOf(0);
}
if (obj instanceof BigDecimal) {
return ((BigDecimal) obj).negate();
}
if (obj instanceof BigInteger) {
return ((BigInteger) obj).negate();
}
if (obj instanceof String) {
if (isStringFloat((String) obj)) {
return Double.valueOf(-Double.parseDouble((String) obj));
}
return Long.valueOf(-Long.parseLong((String) obj));
}
if (obj instanceof Long) {
return Long.valueOf(-((Long) obj).longValue());
}
if (obj instanceof Double) {
return Double.valueOf(-((Double) obj).doubleValue());
}
if (obj instanceof Integer) {
return Integer.valueOf(-((Integer) obj).intValue());
}
if (obj instanceof Float) {
return Float.valueOf(-((Float) obj).floatValue());
}
if (obj instanceof Short) {
return Short.valueOf((short) -((Short) obj).shortValue());
}
if (obj instanceof Byte) {
return Byte.valueOf((byte) -((Byte) obj).byteValue());
}
Long num = (Long) coerceToNumber(ctx, obj, Long.class);
return Long.valueOf(-num.longValue());
}
}

View File

@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstNot.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstNot extends SimpleNode {
public AstNot(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return Boolean.class;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj = this.children[0].getValue(ctx);
Boolean b = coerceToBoolean(ctx, obj, true);
return Boolean.valueOf(!b.booleanValue());
}
}

View File

@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstNotEqual.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstNotEqual extends BooleanNode {
public AstNotEqual(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return Boolean.valueOf(!equals(ctx, obj0, obj1));
}
}

View File

@@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstNull.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstNull extends SimpleNode {
public AstNull(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return null;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return null;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstOr.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstOr extends BooleanNode {
public AstOr(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj = this.children[0].getValue(ctx);
Boolean b = coerceToBoolean(ctx, obj, true);
if (b.booleanValue()) {
return b;
}
obj = this.children[1].getValue(ctx);
b = coerceToBoolean(ctx, obj, true);
return b;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstPlus.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstPlus extends ArithmeticNode {
public AstPlus(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
Object obj0 = this.children[0].getValue(ctx);
Object obj1 = this.children[1].getValue(ctx);
return ELArithmetic.add(obj0, obj1);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstSemicolon.java Version 4.3 */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstSemicolon extends SimpleNode {
public AstSemicolon(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
// Evaluate and throw away
children[0].getValue(ctx);
return children[1].getValue(ctx);
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
// Evaluate and throw away
children[0].getType(ctx);
return children[1].getType(ctx);
}
}
/* JavaCC - OriginalChecksum=ce956594ca572a4e452fe4f084a03099 (do not edit this line) */

View File

@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstSetData.java Version 4.3 */
package org.apache.el.parser;
import java.util.HashSet;
import java.util.Set;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
public class AstSetData extends SimpleNode {
public AstSetData(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx) throws ELException {
Set<Object> result = new HashSet<>();
if (children != null) {
for (Node child : children) {
result.add(child.getValue(ctx));
}
}
return result;
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
return Set.class;
}
}
/* JavaCC - OriginalChecksum=e1dc4e2011eee313491decfa9e0152fe (do not edit this line) */

View File

@@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstString.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstString extends SimpleNode {
public AstString(int id) {
super(id);
}
private volatile String string;
public String getString() {
if (this.string == null) {
this.string = this.image.substring(1, this.image.length() - 1);
}
return this.string;
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return String.class;
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return this.getString();
}
@Override
public void setImage(String image) {
if (image.indexOf('\\') == -1) {
this.image = image;
return;
}
int size = image.length();
StringBuilder buf = new StringBuilder(size);
for (int i = 0; i < size; i++) {
char c = image.charAt(i);
if (c == '\\' && i + 1 < size) {
char c1 = image.charAt(i + 1);
if (c1 == '\\' || c1 == '"' || c1 == '\'') {
c = c1;
i++;
}
}
buf.append(c);
}
this.image = buf.toString();
}
}

View File

@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstTrue.java */
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstTrue extends BooleanNode {
public AstTrue(int id) {
super(id);
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
return Boolean.TRUE;
}
}

View File

@@ -0,0 +1,369 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. AstValue.java */
package org.apache.el.parser;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.LambdaExpression;
import javax.el.MethodInfo;
import javax.el.PropertyNotFoundException;
import javax.el.ValueReference;
import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.stream.Optional;
import org.apache.el.util.MessageFactory;
import org.apache.el.util.ReflectionUtil;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class AstValue extends SimpleNode {
private static final Object[] EMPTY_ARRAY = new Object[0];
protected static class Target {
protected Object base;
protected Object property;
}
public AstValue(int id) {
super(id);
}
@Override
public Class<?> getType(EvaluationContext ctx) throws ELException {
Target t = getTarget(ctx);
ctx.setPropertyResolved(false);
Class<?> result = ctx.getELResolver().getType(ctx, t.base, t.property);
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled", t.base, t.property));
}
return result;
}
private final Target getTarget(EvaluationContext ctx) throws ELException {
// evaluate expr-a to value-a
Object base = this.children[0].getValue(ctx);
// if our base is null (we know there are more properties to evaluate)
if (base == null) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.unreachable.base", this.children[0].getImage()));
}
// set up our start/end
Object property = null;
int propCount = this.jjtGetNumChildren();
int i = 1;
// Evaluate any properties or methods before our target
ELResolver resolver = ctx.getELResolver();
while (i < propCount) {
if (i + 2 < propCount &&
this.children[i + 1] instanceof AstMethodParameters) {
// Method call not at end of expression
base = resolver.invoke(ctx, base,
this.children[i].getValue(ctx), null,
((AstMethodParameters)
this.children[i + 1]).getParameters(ctx));
i += 2;
} else if (i + 2 == propCount &&
this.children[i + 1] instanceof AstMethodParameters) {
// Method call at end of expression
ctx.setPropertyResolved(false);
property = this.children[i].getValue(ctx);
i += 2;
if (property == null) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.unreachable.property", property));
}
} else if (i + 1 < propCount) {
// Object with property not at end of expression
property = this.children[i].getValue(ctx);
ctx.setPropertyResolved(false);
base = resolver.getValue(ctx, base, property);
i++;
} else {
// Object with property at end of expression
ctx.setPropertyResolved(false);
property = this.children[i].getValue(ctx);
i++;
if (property == null) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.unreachable.property", property));
}
}
if (base == null) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.unreachable.property", property));
}
}
Target t = new Target();
t.base = base;
t.property = property;
return t;
}
@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;
}
@Override
public boolean isReadOnly(EvaluationContext ctx) throws ELException {
Target t = getTarget(ctx);
ctx.setPropertyResolved(false);
boolean result =
ctx.getELResolver().isReadOnly(ctx, t.base, t.property);
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled", t.base, t.property));
}
return result;
}
@Override
public void setValue(EvaluationContext ctx, Object value)
throws ELException {
Target t = getTarget(ctx);
ctx.setPropertyResolved(false);
ELResolver resolver = ctx.getELResolver();
// coerce to the expected type
Class<?> targetClass = resolver.getType(ctx, t.base, t.property);
resolver.setValue(ctx, t.base, t.property,
ELSupport.coerceToType(ctx, value, targetClass));
if (!ctx.isPropertyResolved()) {
throw new PropertyNotFoundException(MessageFactory.get(
"error.resolver.unhandled", t.base, t.property));
}
}
@Override
// Interface el.parser.Node uses raw types (and is auto-generated)
public MethodInfo getMethodInfo(EvaluationContext ctx,
@SuppressWarnings("rawtypes") Class[] paramTypes)
throws ELException {
Target t = getTarget(ctx);
Method m = ReflectionUtil.getMethod(
ctx, t.base, t.property, paramTypes, null);
return new MethodInfo(m.getName(), m.getReturnType(), m
.getParameterTypes());
}
@Override
// Interface el.parser.Node uses a raw type (and is auto-generated)
public Object invoke(EvaluationContext ctx,
@SuppressWarnings("rawtypes") Class[] paramTypes,
Object[] paramValues) throws ELException {
Target t = getTarget(ctx);
Method m = null;
Object[] values = null;
Class<?>[] types = null;
if (isParametersProvided()) {
values = ((AstMethodParameters) this.jjtGetChild(
this.jjtGetNumChildren() - 1)).getParameters(ctx);
types = getTypesFromValues(values);
} else {
values = paramValues;
types = paramTypes;
}
m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, values);
// Handle varArgs and any coercion required
values = convertArgs(ctx, values, m);
Object result = null;
try {
result = m.invoke(t.base, values);
} catch (IllegalAccessException iae) {
throw new ELException(iae);
} catch (IllegalArgumentException iae) {
throw new ELException(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(cause);
}
return result;
}
private Object[] convertArgs(EvaluationContext ctx, Object[] src, Method m) {
Class<?>[] types = m.getParameterTypes();
if (types.length == 0) {
// Treated as if parameters have been provided so src is ignored
return EMPTY_ARRAY;
}
int paramCount = types.length;
if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) ||
!m.isVarArgs() && (paramCount > 0 && src == null ||
src != null && src.length != paramCount)) {
String srcCount = null;
if (src != null) {
srcCount = Integer.toString(src.length);
}
String msg;
if (m.isVarArgs()) {
msg = MessageFactory.get("error.invoke.tooFewParams",
m.getName(), srcCount, Integer.toString(paramCount));
} else {
msg = MessageFactory.get("error.invoke.wrongParams",
m.getName(), srcCount, Integer.toString(paramCount));
}
throw new IllegalArgumentException(msg);
}
if (src == null) {
// Must be a varargs method with a single parameter.
// Use a new array every time since the called code could modify the
// contents of the array
return new Object[1];
}
Object[] dest = new Object[paramCount];
for (int i = 0; i < paramCount - 1; i++) {
dest[i] = ELSupport.coerceToType(ctx, src[i], types[i]);
}
if (m.isVarArgs()) {
Class<?> varArgType = m.getParameterTypes()[paramCount - 1].getComponentType();
Object[] varArgs =
(Object[]) Array.newInstance(varArgType, src.length - (paramCount - 1));
for (int i = 0; i < src.length - (paramCount - 1); i ++) {
varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], varArgType);
}
dest[paramCount - 1] = varArgs;
} else {
dest[paramCount - 1] = ELSupport.coerceToType(
ctx, src[paramCount - 1], types[paramCount - 1]);
}
return dest;
}
private Class<?>[] getTypesFromValues(Object[] values) {
if (values == null) {
return null;
}
Class<?> result[] = new Class<?>[values.length];
for (int i = 0; i < values.length; i++) {
if (values[i] == null) {
result[i] = null;
} else {
result[i] = values[i].getClass();
}
}
return result;
}
/**
* @since EL 2.2
*/
@Override
public ValueReference getValueReference(EvaluationContext ctx) {
// Check this is a reference to a base and a property
if (this.children.length > 2 &&
this.jjtGetChild(2) instanceof AstMethodParameters) {
// This is a method call
return null;
}
Target t = getTarget(ctx);
return new ValueReference(t.base, t.property);
}
/**
* @since EL 2.2
*/
@Override
public boolean isParametersProvided() {
// Assumption is that method parameters, if present, will be the last
// child
int len = children.length;
if (len > 2) {
if (this.jjtGetChild(len - 1) instanceof AstMethodParameters) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.parser;
import javax.el.ELException;
import org.apache.el.lang.EvaluationContext;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public abstract class BooleanNode extends SimpleNode {
public BooleanNode(int i) {
super(i);
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
return Boolean.class;
}
}

View File

@@ -0,0 +1,223 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>BNF for ELParser.jj</TITLE>
</HEAD>
<BODY>
<H1 ALIGN=CENTER>BNF for ELParser.jj</H1>
<H2 ALIGN=CENTER>NON-TERMINALS</H2>
<TABLE>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod1">CompositeExpression</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod2">DeferredExpression</A> | <A HREF="#prod3">DynamicExpression</A> | <A HREF="#prod4">LiteralExpression</A> )* &lt;EOF&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod4">LiteralExpression</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;LITERAL_EXPRESSION&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod2">DeferredExpression</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;START_DEFERRED_EXPRESSION&gt; <A HREF="#prod5">Expression</A> &lt;END_EXPRESSION&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod3">DynamicExpression</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;START_DYNAMIC_EXPRESSION&gt; <A HREF="#prod5">Expression</A> &lt;END_EXPRESSION&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod5">Expression</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod6">Choice</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod6">Choice</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod7">Or</A> ( &lt;QUESTIONMARK&gt; <A HREF="#prod6">Choice</A> &lt;COLON&gt; <A HREF="#prod6">Choice</A> )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod7">Or</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod8">And</A> ( ( &lt;OR0&gt; | &lt;OR1&gt; ) <A HREF="#prod8">And</A> )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod8">And</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod9">Equality</A> ( ( &lt;AND0&gt; | &lt;AND1&gt; ) <A HREF="#prod9">Equality</A> )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod9">Equality</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod10">Compare</A> ( ( ( &lt;EQ0&gt; | &lt;EQ1&gt; ) <A HREF="#prod10">Compare</A> ) | ( ( &lt;NE0&gt; | &lt;NE1&gt; ) <A HREF="#prod10">Compare</A> ) )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod10">Compare</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod11">Math</A> ( ( ( &lt;LT0&gt; | &lt;LT1&gt; ) <A HREF="#prod11">Math</A> ) | ( ( &lt;GT0&gt; | &lt;GT1&gt; ) <A HREF="#prod11">Math</A> ) | ( ( &lt;LE0&gt; | &lt;LE1&gt; ) <A HREF="#prod11">Math</A> ) | ( ( &lt;GE0&gt; | &lt;GE1&gt; ) <A HREF="#prod11">Math</A> ) )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod11">Math</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod12">Multiplication</A> ( ( &lt;PLUS&gt; <A HREF="#prod12">Multiplication</A> ) | ( &lt;MINUS&gt; <A HREF="#prod12">Multiplication</A> ) )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod12">Multiplication</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod13">Unary</A> ( ( &lt;MULT&gt; <A HREF="#prod13">Unary</A> ) | ( &lt;DIV&gt; <A HREF="#prod13">Unary</A> ) | ( ( &lt;MOD0&gt; | &lt;MOD1&gt; ) <A HREF="#prod13">Unary</A> ) )*</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod13">Unary</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;MINUS&gt; <A HREF="#prod13">Unary</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>( &lt;NOT0&gt; | &lt;NOT1&gt; ) <A HREF="#prod13">Unary</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;EMPTY&gt; <A HREF="#prod13">Unary</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod14">Value</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod14">Value</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>( <A HREF="#prod15">ValuePrefix</A> ( <A HREF="#prod16">ValueSuffix</A> )* )</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod15">ValuePrefix</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod17">Literal</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod18">NonLiteral</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod16">ValueSuffix</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod19">DotSuffix</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod20">BracketSuffix</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod19">DotSuffix</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;DOT&gt; &lt;IDENTIFIER&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod20">BracketSuffix</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;LBRACK&gt; <A HREF="#prod5">Expression</A> &lt;RBRACK&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod18">NonLiteral</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;LPAREN&gt; <A HREF="#prod5">Expression</A> &lt;RPAREN&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod21">Function</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod22">Identifier</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod22">Identifier</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;IDENTIFIER&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod21">Function</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;IDENTIFIER&gt; ( &lt;FUNCTIONSUFFIX&gt; )? &lt;LPAREN&gt; ( <A HREF="#prod5">Expression</A> ( &lt;COMMA&gt; <A HREF="#prod5">Expression</A> )* )? &lt;RPAREN&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod17">Literal</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod23">Boolean</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod24">FloatingPoint</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod25">Integer</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod26">String</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE><A HREF="#prod27">Null</A></TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod23">Boolean</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;TRUE&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;FALSE&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod24">FloatingPoint</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;FLOATING_POINT_LITERAL&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod25">Integer</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;INTEGER_LITERAL&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod26">String</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;STRING_LITERAL&gt;</TD>
</TR>
<TR>
<TD ALIGN=RIGHT VALIGN=BASELINE><A NAME="prod27">Null</A></TD>
<TD ALIGN=CENTER VALIGN=BASELINE>::=</TD>
<TD ALIGN=LEFT VALIGN=BASELINE>&lt;NULL&gt;</TD>
</TR>
</TABLE>
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
Author: Jacob Hookom
Email: jacob at hookom.net
*/
/* == Option Declaration == */
options
{
STATIC=false;
NODE_PREFIX="Ast";
VISITOR_EXCEPTION="javax.el.ELException";
VISITOR=false;
MULTI=true;
NODE_DEFAULT_VOID=true;
JAVA_UNICODE_ESCAPE=false;
UNICODE_INPUT=true;
BUILD_NODE_FILES=true;
}
/* == Parser Declaration == */
PARSER_BEGIN( ELParser )
package org.apache.el.parser;
import java.io.StringReader;
import javax.el.ELException;
public class ELParser {
public static Node parse(String ref) throws ELException {
try {
return new ELParser(new StringReader(ref)).CompositeExpression();
} catch (ParseException pe) {
throw new ELException(pe.getMessage());
}
}
}
PARSER_END( ELParser )
/*
* CompositeExpression
* Allow most flexible parsing, restrict by examining
* type of returned node
*/
AstCompositeExpression CompositeExpression() #CompositeExpression : {}
{
(DeferredExpression() |
DynamicExpression() |
LiteralExpression())* <EOF> { return jjtThis; }
}
/*
* LiteralExpression
* Non-EL Expression blocks
*/
void LiteralExpression() #LiteralExpression : { Token t = null; }
{
t=<LITERAL_EXPRESSION> { jjtThis.setImage(t.image); }
}
/*
* DeferredExpression
* #{...} Expressions
*/
void DeferredExpression() #DeferredExpression : {}
{
<START_DEFERRED_EXPRESSION> Expression() <RBRACE>
}
/*
* DynamicExpression
* ${...} Expressions
*/
void DynamicExpression() #DynamicExpression : {}
{
<START_DYNAMIC_EXPRESSION> Expression() <RBRACE>
}
/*
* Expression
* EL Expression Language Root
*/
void Expression() : {}
{
Semicolon()
}
/*
* Semicolon
*/
void Semicolon() : {}
{
Assignment() ( <SEMICOLON> Assignment() #Semicolon(2) )*
}
/*
* Assignment
*/
void Assignment() : {}
{
LOOKAHEAD(4) LambdaExpression() |
Choice() ( LOOKAHEAD(2) <ASSIGN> Assignment() #Assign(2) )*
}
/*
* Lambda expression
*/
void LambdaExpression() #LambdaExpression : {}
{
LambdaParameters() <ARROW> ( LOOKAHEAD(3) LambdaExpression() | Choice() )
}
/*
* Lambda parameters
*/
void LambdaParameters() #LambdaParameters : {}
{
Identifier() | <LPAREN> ( Identifier() ( <COMMA> Identifier() )* )? <RPAREN>
}
/*
* Possible invocation of lambda expression. Invocations must be bracketed but
* being bracketed does not mean it is an invocation.
*/
void LambdaExpressionOrInvocation() #LambdaExpression : {}
{
<LPAREN>
LambdaParameters()
<ARROW>
( LOOKAHEAD(3) LambdaExpression() | Choice() )
<RPAREN>
( MethodParameters() )*
}
/*
* Choice
* For Choice markup a ? b : c, then Or
*/
void Choice() : {}
{
Or() (LOOKAHEAD(3) <QUESTIONMARK> Choice() <COLON> Choice() #Choice(3))*
}
/*
* Or
* For 'or' '||', then And
*/
void Or() : {}
{
And() ((<OR0>|<OR1>) And() #Or(2))*
}
/*
* And
* For 'and' '&&', then Equality
*/
void And() : {}
{
Equality() ((<AND0>|<AND1>) Equality() #And(2))*
}
/*
* Equality
* For '==' 'eq' '!=' 'ne', then Compare
*/
void Equality() : {}
{
Compare()
(
((<EQ0>|<EQ1>) Compare() #Equal(2))
|
((<NE0>|<NE1>) Compare() #NotEqual(2))
)*
}
/*
* Compare
* For a bunch of them, then +=
*/
void Compare() : {}
{
Concatenation()
(
((<LT0>|<LT1>) Concatenation() #LessThan(2))
|
((<GT0>|<GT1>) Concatenation() #GreaterThan(2))
|
((<LE0>|<LE1>) Concatenation() #LessThanEqual(2))
|
((<GE0>|<GE1>) Concatenation() #GreaterThanEqual(2))
)*
}
/*
* Concatenation
* For +=, then Math
*
*/
void Concatenation() : {}
{
Math()
(
<CONCAT> Math() #Concatenation(2)
)*
}
/*
* Math
* For '+' '-', then Multiplication
*/
void Math() : {}
{
Multiplication()
(
(<PLUS> Multiplication() #Plus(2))
|
(<MINUS> Multiplication() #Minus(2))
)*
}
/*
* Multiplication
* For a bunch of them, then Unary
*/
void Multiplication() : {}
{
Unary()
(
(<MULT> Unary() #Mult(2))
|
((<DIV0>|<DIV1>) Unary() #Div(2))
|
((<MOD0>|<MOD1>) Unary() #Mod(2))
)*
}
/*
* Unary
* For '-' '!' 'not' 'empty', then Value
*/
void Unary() : {}
{
<MINUS> Unary() #Negative
|
(<NOT0>|<NOT1>) Unary() #Not
|
<EMPTY> Unary() #Empty
|
Value()
}
/*
* Value
* Defines Prefix plus zero or more Suffixes
*/
void Value() : {}
{
(ValuePrefix() (ValueSuffix())*) #Value(>1)
}
/*
* ValuePrefix
* For Literals, Variables, and Functions
*/
void ValuePrefix() : {}
{
Literal()
| NonLiteral()
}
/*
* ValueSuffix
* Either dot or bracket notation
*/
void ValueSuffix() : {}
{
( DotSuffix() | BracketSuffix() ) ( MethodParameters())?
}
/*
* DotSuffix
* Dot Property
*/
void DotSuffix() #DotSuffix : { Token t = null; }
{
<DOT> t=<IDENTIFIER> { jjtThis.setImage(t.image); }
}
/*
* BracketSuffix
* Sub Expression Suffix
*/
void BracketSuffix() #BracketSuffix : {}
{
<LBRACK> Expression() <RBRACK>
}
/*
* MethodParameters
*/
void MethodParameters() #MethodParameters : {}
{
<LPAREN> ( Expression() ( <COMMA> Expression())* )? <RPAREN>
}
/*
* NonLiteral
* For Grouped Operations, Identifiers, and Functions
*/
void NonLiteral() : {}
{
LOOKAHEAD(5) LambdaExpressionOrInvocation()
| <LPAREN> Expression() <RPAREN>
| LOOKAHEAD((<IDENTIFIER> <COLON>)? <IDENTIFIER> <LPAREN>) Function()
| Identifier()
| LOOKAHEAD(3)SetData()
| ListData()
| MapData()
}
/*
* Note that both an empty Set and an empty Map are represented by {}. The
* parser will always parse {} as an empty Set and special handling is required
* to convert it to an empty Map when appropriate.
*/
void SetData() #SetData: {}
{
<START_SET_OR_MAP>
( Expression() ( <COMMA> Expression() )* )?
<RBRACE>
}
void ListData() #ListData: {}
{
<LBRACK>
( Expression() ( <COMMA> Expression() )* )?
<RBRACK>
}
/*
* Note that both an empty Set and an empty Map are represented by {}. The
* parser will always parse {} as an empty Set and special handling is required
* to convert it to an empty Map when appropriate.
*/
void MapData() #MapData: {}
{
<START_SET_OR_MAP>
( MapEntry() ( <COMMA> MapEntry() )* )?
<RBRACE>
}
void MapEntry() #MapEntry: {}
{
Expression() <COLON> Expression()
}
/*
* Identifier
* Java Language Identifier
*/
void Identifier() #Identifier : { Token t = null; }
{
t=<IDENTIFIER> { jjtThis.setImage(t.image); }
}
/*
* Function
* Namespace:Name(a,b,c)
*/
void Function() #Function :
{
Token t0 = null;
Token t1 = null;
}
{
t0=<IDENTIFIER> ( <COLON> t1=<IDENTIFIER> )?
{
if (t1 != null) {
jjtThis.setPrefix(t0.image);
jjtThis.setLocalName(t1.image);
} else {
jjtThis.setLocalName(t0.image);
}
}
( MethodParameters() )+
}
/*
* Literal
* Reserved Keywords
*/
void Literal() : {}
{
Boolean()
| FloatingPoint()
| Integer()
| String()
| Null()
}
/*
* Boolean
* For 'true' 'false'
*/
void Boolean() : {}
{
<TRUE> #True
| <FALSE> #False
}
/*
* FloatingPoint
* For Decimal and Floating Point Literals
*/
void FloatingPoint() #FloatingPoint : { Token t = null; }
{
t=<FLOATING_POINT_LITERAL> { jjtThis.setImage(t.image); }
}
/*
* Integer
* For Simple Numeric Literals
*/
void Integer() #Integer : { Token t = null; }
{
t=<INTEGER_LITERAL> { jjtThis.setImage(t.image); }
}
/*
* String
* For Quoted Literals
*/
void String() #String : { Token t = null; }
{
t=<STRING_LITERAL> { jjtThis.setImage(t.image); }
}
/*
* Null
* For 'null'
*/
void Null() #Null : {}
{
<NULL>
}
/* ========================================================================== */
TOKEN_MGR_DECLS:
{
java.util.Deque<Integer> deque = new java.util.ArrayDeque<Integer>();
}
<DEFAULT> TOKEN :
{
/*
* The following definition uses + rather than * in two places to prevent
* LITERAL_EXPRESSION matching the empty string that could result in the
* Parser entering an infinite loop.
*/
< LITERAL_EXPRESSION:
( (~["$", "#", "\\"])* "\\" (["$", "#"])?
| (~["$", "#"])* (["$", "#"] ~["{", "$", "#", "\\"])
| (~["$", "#"])+
)+
| "$"
| "#"
>
|
< START_DYNAMIC_EXPRESSION: "${" > {deque.push(DEFAULT);}: IN_EXPRESSION
|
< START_DEFERRED_EXPRESSION: "#{" > {deque.push(DEFAULT);}: IN_EXPRESSION
}
<IN_EXPRESSION, IN_SET_OR_MAP> SKIP : { " " | "\t" | "\n" | "\r" }
<IN_EXPRESSION, IN_SET_OR_MAP> TOKEN :
{
< START_SET_OR_MAP : "{" > {deque.push(curLexState);}: IN_SET_OR_MAP
| < RBRACE: "}" > {SwitchTo(deque.pop());}
| < INTEGER_LITERAL: ["0"-"9"] (["0"-"9"])* >
| < FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)?
| "." (["0"-"9"])+ (<EXPONENT>)?
| (["0"-"9"])+ <EXPONENT>
>
| < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
| < STRING_LITERAL: ("\"" ((~["\"","\\"])
| ("\\" ( ["\\","\"","\'"] )))* "\"")
| ("\'" ((~["\'","\\"])
| ("\\" ( ["\\","\"","\'"] )))* "\'")
>
| < TRUE : "true" >
| < FALSE : "false" >
| < NULL : "null" >
| < DOT : "." >
| < LPAREN : "(" >
| < RPAREN : ")" >
| < LBRACK : "[" >
| < RBRACK : "]" >
| < COLON : ":" >
| < SEMICOLON : ";" >
| < COMMA : "," >
| < GT0 : ">" >
| < GT1 : "gt" >
| < LT0 : "<" >
| < LT1 : "lt" >
| < GE0 : ">=" >
| < GE1 : "ge" >
| < LE0 : "<=" >
| < LE1 : "le" >
| < EQ0 : "==" >
| < EQ1 : "eq" >
| < NE0 : "!=" >
| < NE1 : "ne" >
| < NOT0 : "!" >
| < NOT1 : "not" >
| < AND0 : "&&" >
| < AND1 : "and" >
| < OR0 : "||" >
| < OR1 : "or" >
| < EMPTY : "empty" >
| < INSTANCEOF : "instanceof" >
| < MULT : "*" >
| < PLUS : "+" >
| < MINUS : "-" >
| < QUESTIONMARK : "?" >
| < DIV0 : "/" >
| < DIV1 : "div" >
| < MOD0 : "%" >
| < MOD1 : "mod" >
| < CONCAT : "+=" >
| < ASSIGN : "=" >
| < ARROW : "->" >
| < IDENTIFIER : (<LETTER>|<IMPL_OBJ_START>) (<LETTER>|<DIGIT>)* >
| < FUNCTIONSUFFIX : (<IDENTIFIER>) >
| < #IMPL_OBJ_START: "#" >
| < #LETTER:
[
"\u0024",
"\u0041"-"\u005a",
"\u005f",
"\u0061"-"\u007a",
"\u00c0"-"\u00d6",
"\u00d8"-"\u00f6",
"\u00f8"-"\u00ff",
"\u0100"-"\u1fff",
"\u3040"-"\u318f",
"\u3300"-"\u337f",
"\u3400"-"\u3d2d",
"\u4e00"-"\u9fff",
"\uf900"-"\ufaff"
]
>
| < #DIGIT:
[
"\u0030"-"\u0039",
"\u0660"-"\u0669",
"\u06f0"-"\u06f9",
"\u0966"-"\u096f",
"\u09e6"-"\u09ef",
"\u0a66"-"\u0a6f",
"\u0ae6"-"\u0aef",
"\u0b66"-"\u0b6f",
"\u0be7"-"\u0bef",
"\u0c66"-"\u0c6f",
"\u0ce6"-"\u0cef",
"\u0d66"-"\u0d6f",
"\u0e50"-"\u0e59",
"\u0ed0"-"\u0ed9",
"\u1040"-"\u1049"
]
>
| < ILLEGAL_CHARACTER: (~[]) >
}

View File

@@ -0,0 +1,201 @@
/* Generated By:JJTree&JavaCC: Do not edit this line. ELParserConstants.java */
package org.apache.el.parser;
/**
* Token literal values and constants.
* Generated by org.javacc.parser.OtherFilesGen#start()
*/
public interface ELParserConstants {
/** End of File. */
int EOF = 0;
/** RegularExpression Id. */
int LITERAL_EXPRESSION = 1;
/** RegularExpression Id. */
int START_DYNAMIC_EXPRESSION = 2;
/** RegularExpression Id. */
int START_DEFERRED_EXPRESSION = 3;
/** RegularExpression Id. */
int START_SET_OR_MAP = 8;
/** RegularExpression Id. */
int RBRACE = 9;
/** RegularExpression Id. */
int INTEGER_LITERAL = 10;
/** RegularExpression Id. */
int FLOATING_POINT_LITERAL = 11;
/** RegularExpression Id. */
int EXPONENT = 12;
/** RegularExpression Id. */
int STRING_LITERAL = 13;
/** RegularExpression Id. */
int TRUE = 14;
/** RegularExpression Id. */
int FALSE = 15;
/** RegularExpression Id. */
int NULL = 16;
/** RegularExpression Id. */
int DOT = 17;
/** RegularExpression Id. */
int LPAREN = 18;
/** RegularExpression Id. */
int RPAREN = 19;
/** RegularExpression Id. */
int LBRACK = 20;
/** RegularExpression Id. */
int RBRACK = 21;
/** RegularExpression Id. */
int COLON = 22;
/** RegularExpression Id. */
int SEMICOLON = 23;
/** RegularExpression Id. */
int COMMA = 24;
/** RegularExpression Id. */
int GT0 = 25;
/** RegularExpression Id. */
int GT1 = 26;
/** RegularExpression Id. */
int LT0 = 27;
/** RegularExpression Id. */
int LT1 = 28;
/** RegularExpression Id. */
int GE0 = 29;
/** RegularExpression Id. */
int GE1 = 30;
/** RegularExpression Id. */
int LE0 = 31;
/** RegularExpression Id. */
int LE1 = 32;
/** RegularExpression Id. */
int EQ0 = 33;
/** RegularExpression Id. */
int EQ1 = 34;
/** RegularExpression Id. */
int NE0 = 35;
/** RegularExpression Id. */
int NE1 = 36;
/** RegularExpression Id. */
int NOT0 = 37;
/** RegularExpression Id. */
int NOT1 = 38;
/** RegularExpression Id. */
int AND0 = 39;
/** RegularExpression Id. */
int AND1 = 40;
/** RegularExpression Id. */
int OR0 = 41;
/** RegularExpression Id. */
int OR1 = 42;
/** RegularExpression Id. */
int EMPTY = 43;
/** RegularExpression Id. */
int INSTANCEOF = 44;
/** RegularExpression Id. */
int MULT = 45;
/** RegularExpression Id. */
int PLUS = 46;
/** RegularExpression Id. */
int MINUS = 47;
/** RegularExpression Id. */
int QUESTIONMARK = 48;
/** RegularExpression Id. */
int DIV0 = 49;
/** RegularExpression Id. */
int DIV1 = 50;
/** RegularExpression Id. */
int MOD0 = 51;
/** RegularExpression Id. */
int MOD1 = 52;
/** RegularExpression Id. */
int CONCAT = 53;
/** RegularExpression Id. */
int ASSIGN = 54;
/** RegularExpression Id. */
int ARROW = 55;
/** RegularExpression Id. */
int IDENTIFIER = 56;
/** RegularExpression Id. */
int FUNCTIONSUFFIX = 57;
/** RegularExpression Id. */
int IMPL_OBJ_START = 58;
/** RegularExpression Id. */
int LETTER = 59;
/** RegularExpression Id. */
int DIGIT = 60;
/** RegularExpression Id. */
int ILLEGAL_CHARACTER = 61;
/** Lexical state. */
int DEFAULT = 0;
/** Lexical state. */
int IN_EXPRESSION = 1;
/** Lexical state. */
int IN_SET_OR_MAP = 2;
/** Literal token values. */
String[] tokenImage = {
"<EOF>",
"<LITERAL_EXPRESSION>",
"\"${\"",
"\"#{\"",
"\" \"",
"\"\\t\"",
"\"\\n\"",
"\"\\r\"",
"\"{\"",
"\"}\"",
"<INTEGER_LITERAL>",
"<FLOATING_POINT_LITERAL>",
"<EXPONENT>",
"<STRING_LITERAL>",
"\"true\"",
"\"false\"",
"\"null\"",
"\".\"",
"\"(\"",
"\")\"",
"\"[\"",
"\"]\"",
"\":\"",
"\";\"",
"\",\"",
"\">\"",
"\"gt\"",
"\"<\"",
"\"lt\"",
"\">=\"",
"\"ge\"",
"\"<=\"",
"\"le\"",
"\"==\"",
"\"eq\"",
"\"!=\"",
"\"ne\"",
"\"!\"",
"\"not\"",
"\"&&\"",
"\"and\"",
"\"||\"",
"\"or\"",
"\"empty\"",
"\"instanceof\"",
"\"*\"",
"\"+\"",
"\"-\"",
"\"?\"",
"\"/\"",
"\"div\"",
"\"%\"",
"\"mod\"",
"\"+=\"",
"\"=\"",
"\"->\"",
"<IDENTIFIER>",
"<FUNCTIONSUFFIX>",
"\"#\"",
"<LETTER>",
"<DIGIT>",
"<ILLEGAL_CHARACTER>",
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
/* Generated By:JavaCC: Do not edit this line. ELParserTreeConstants.java Version 5.0 */
package org.apache.el.parser;
public interface ELParserTreeConstants
{
public int JJTCOMPOSITEEXPRESSION = 0;
public int JJTLITERALEXPRESSION = 1;
public int JJTDEFERREDEXPRESSION = 2;
public int JJTDYNAMICEXPRESSION = 3;
public int JJTVOID = 4;
public int JJTSEMICOLON = 5;
public int JJTASSIGN = 6;
public int JJTLAMBDAEXPRESSION = 7;
public int JJTLAMBDAPARAMETERS = 8;
public int JJTCHOICE = 9;
public int JJTOR = 10;
public int JJTAND = 11;
public int JJTEQUAL = 12;
public int JJTNOTEQUAL = 13;
public int JJTLESSTHAN = 14;
public int JJTGREATERTHAN = 15;
public int JJTLESSTHANEQUAL = 16;
public int JJTGREATERTHANEQUAL = 17;
public int JJTCONCATENATION = 18;
public int JJTPLUS = 19;
public int JJTMINUS = 20;
public int JJTMULT = 21;
public int JJTDIV = 22;
public int JJTMOD = 23;
public int JJTNEGATIVE = 24;
public int JJTNOT = 25;
public int JJTEMPTY = 26;
public int JJTVALUE = 27;
public int JJTDOTSUFFIX = 28;
public int JJTBRACKETSUFFIX = 29;
public int JJTMETHODPARAMETERS = 30;
public int JJTSETDATA = 31;
public int JJTLISTDATA = 32;
public int JJTMAPDATA = 33;
public int JJTMAPENTRY = 34;
public int JJTIDENTIFIER = 35;
public int JJTFUNCTION = 36;
public int JJTTRUE = 37;
public int JJTFALSE = 38;
public int JJTFLOATINGPOINT = 39;
public int JJTINTEGER = 40;
public int JJTSTRING = 41;
public int JJTNULL = 42;
public String[] jjtNodeName = {
"CompositeExpression",
"LiteralExpression",
"DeferredExpression",
"DynamicExpression",
"void",
"Semicolon",
"Assign",
"LambdaExpression",
"LambdaParameters",
"Choice",
"Or",
"And",
"Equal",
"NotEqual",
"LessThan",
"GreaterThan",
"LessThanEqual",
"GreaterThanEqual",
"Concatenation",
"Plus",
"Minus",
"Mult",
"Div",
"Mod",
"Negative",
"Not",
"Empty",
"Value",
"DotSuffix",
"BracketSuffix",
"MethodParameters",
"SetData",
"ListData",
"MapData",
"MapEntry",
"Identifier",
"Function",
"True",
"False",
"FloatingPoint",
"Integer",
"String",
"Null",
};
}
/* JavaCC - OriginalChecksum=96680d397165a1214a1ad1f24011d5c1 (do not edit this line) */

View File

@@ -0,0 +1,124 @@
/* Generated By:JavaCC: Do not edit this line. JJTELParserState.java Version 5.0 */
package org.apache.el.parser;
@SuppressWarnings("all") // Ignore warnings in generated code
public class JJTELParserState {
private java.util.List<Node> nodes;
private java.util.List<Integer> marks;
private int sp; // number of nodes on stack
private int mk; // current mark
private boolean node_created;
public JJTELParserState() {
nodes = new java.util.ArrayList<Node>();
marks = new java.util.ArrayList<Integer>();
sp = 0;
mk = 0;
}
/* Determines whether the current node was actually closed and
pushed. This should only be called in the final user action of a
node scope. */
public boolean nodeCreated() {
return node_created;
}
/* Call this to reinitialize the node stack. It is called
automatically by the parser's ReInit() method. */
public void reset() {
nodes.clear();
marks.clear();
sp = 0;
mk = 0;
}
/* Returns the root node of the AST. It only makes sense to call
this after a successful parse. */
public Node rootNode() {
return nodes.get(0);
}
/* Pushes a node on to the stack. */
public void pushNode(Node n) {
nodes.add(n);
++sp;
}
/* Returns the node on the top of the stack, and remove it from the
stack. */
public Node popNode() {
if (--sp < mk) {
mk = marks.remove(marks.size()-1);
}
return nodes.remove(nodes.size()-1);
}
/* Returns the node currently on the top of the stack. */
public Node peekNode() {
return nodes.get(nodes.size()-1);
}
/* Returns the number of children on the stack in the current node
scope. */
public int nodeArity() {
return sp - mk;
}
public void clearNodeScope(Node n) {
while (sp > mk) {
popNode();
}
mk = marks.remove(marks.size()-1);
}
public void openNodeScope(Node n) {
marks.add(mk);
mk = sp;
n.jjtOpen();
}
/* A definite node is constructed from a specified number of
children. That number of nodes are popped from the stack and
made the children of the definite node. Then the definite node
is pushed on to the stack. */
public void closeNodeScope(Node n, int num) {
mk = marks.remove(marks.size()-1);
while (num-- > 0) {
Node c = popNode();
c.jjtSetParent(n);
n.jjtAddChild(c, num);
}
n.jjtClose();
pushNode(n);
node_created = true;
}
/* A conditional node is constructed if its condition is true. All
the nodes that have been pushed since the node was opened are
made children of the conditional node, which is then pushed
on to the stack. If the condition is false the node is not
constructed and they are left on the stack. */
public void closeNodeScope(Node n, boolean condition) {
if (condition) {
int a = nodeArity();
mk = marks.remove(marks.size()-1);
while (a-- > 0) {
Node c = popNode();
c.jjtSetParent(n);
n.jjtAddChild(c, a);
}
n.jjtClose();
pushNode(n);
node_created = true;
} else {
mk = marks.remove(marks.size()-1);
node_created = false;
}
}
}
/* JavaCC - OriginalChecksum=70ac39f1e0e1eed7476e1dae2dfa25fa (do not edit this line) */

View File

@@ -0,0 +1,84 @@
/* Generated By:JJTree: Do not edit this line. Node.java */
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.parser;
import javax.el.ELException;
import javax.el.MethodInfo;
import javax.el.ValueReference;
import org.apache.el.lang.EvaluationContext;
/* All AST nodes must implement this interface. It provides basic
machinery for constructing the parent and child relationships
between nodes. */
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
@SuppressWarnings("all") // Ignore warnings in generated code
public interface Node {
/** This method is called after the node has been made the current
node. It indicates that child nodes can now be added to it. */
public void jjtOpen();
/** This method is called after all the child nodes have been
added. */
public void jjtClose();
/** This pair of methods are used to inform the node of its
parent. */
public void jjtSetParent(Node n);
public Node jjtGetParent();
/** This method tells the node to add its argument to the node's
list of children. */
public void jjtAddChild(Node n, int i);
/** This method returns a child node. The children are numbered
from zero, left to right. */
public Node jjtGetChild(int i);
/** Return the number of children the node has. */
public int jjtGetNumChildren();
public String getImage();
public Object getValue(EvaluationContext ctx) throws ELException;
public void setValue(EvaluationContext ctx, Object value) throws ELException;
public Class<?> getType(EvaluationContext ctx) throws ELException;
public boolean isReadOnly(EvaluationContext ctx) throws ELException;
public void accept(NodeVisitor visitor) throws Exception;
public MethodInfo getMethodInfo(EvaluationContext ctx, Class<?>[] paramTypes)
throws ELException;
public Object invoke(EvaluationContext ctx, Class<?>[] paramTypes,
Object[] paramValues) throws ELException;
/**
* @since EL 2.2
*/
public ValueReference getValueReference(EvaluationContext ctx);
/**
* @since EL 2.2
*/
public boolean isParametersProvided();
}

View File

@@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.parser;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public interface NodeVisitor {
public void visit(Node node) throws Exception;
}

View File

@@ -0,0 +1,182 @@
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
/* JavaCCOptions:KEEP_LINE_COL=null */
package org.apache.el.parser;
/**
* This exception is thrown when parse errors are encountered.
* You can explicitly create objects of this exception type by
* calling the method generateParseException in the generated
* parser.
*
* You can modify this class to customize your error reporting
* mechanisms so long as you retain the public fields.
*/
@SuppressWarnings("all") // Ignore warnings in generated code
public class ParseException extends Exception {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/**
* This constructor is used by the method "generateParseException"
* in the generated parser. Calling this constructor generates
* a new object of this type with the fields "currentToken",
* "expectedTokenSequences", and "tokenImage" set.
*/
public ParseException(Token currentTokenVal,
int[][] expectedTokenSequencesVal,
String[] tokenImageVal
)
{
super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
currentToken = currentTokenVal;
expectedTokenSequences = expectedTokenSequencesVal;
tokenImage = tokenImageVal;
}
/**
* The following constructors are for use by you for whatever
* purpose you can think of. Constructing the exception in this
* manner makes the exception behave in the normal way - i.e., as
* documented in the class "Throwable". The fields "errorToken",
* "expectedTokenSequences", and "tokenImage" do not contain
* relevant information. The JavaCC generated code does not use
* these constructors.
*/
public ParseException() {
super();
}
/** Constructor with message. */
public ParseException(String message) {
super(message);
}
/**
* This is the last token that has been consumed successfully. If
* this object has been created due to a parse error, the token
* followng this token will (therefore) be the first error token.
*/
public Token currentToken;
/**
* Each entry in this array is an array of integers. Each array
* of integers represents a sequence of tokens (by their ordinal
* values) that is expected at this point of the parse.
*/
public int[][] expectedTokenSequences;
/**
* This is a reference to the "tokenImage" array of the generated
* parser within which the parse error occurred. This array is
* defined in the generated ...Constants interface.
*/
public String[] tokenImage;
/**
* It uses "currentToken" and "expectedTokenSequences" to generate a parse
* error message and returns it. If this object has been created
* due to a parse error, and you do not catch it (it gets thrown
* from the parser) the correct error message
* gets displayed.
*/
private static String initialise(Token currentToken,
int[][] expectedTokenSequences,
String[] tokenImage) {
StringBuffer expected = new StringBuffer();
int maxSize = 0;
for (int i = 0; i < expectedTokenSequences.length; i++) {
if (maxSize < expectedTokenSequences[i].length) {
maxSize = expectedTokenSequences[i].length;
}
for (int j = 0; j < expectedTokenSequences[i].length; j++) {
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
}
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
expected.append("...");
}
expected.append(System.lineSeparator()).append(" ");
}
String retval = "Encountered \"";
Token tok = currentToken.next;
for (int i = 0; i < maxSize; i++) {
if (i != 0) retval += " ";
if (tok.kind == 0) {
retval += tokenImage[0];
break;
}
retval += " " + tokenImage[tok.kind];
retval += " \"";
retval += add_escapes(tok.image);
retval += " \"";
tok = tok.next;
}
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
retval += "." + System.lineSeparator();
if (expectedTokenSequences.length == 1) {
retval += "Was expecting:" + System.lineSeparator() + " ";
} else {
retval += "Was expecting one of:" + System.lineSeparator() + " ";
}
retval += expected.toString();
return retval;
}
/**
* Used to convert raw characters to their escaped version
* when these raw version cannot be used as part of an ASCII
* string literal.
*/
static String add_escapes(String str) {
StringBuffer retval = new StringBuffer();
char ch;
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i))
{
case 0 :
continue;
case '\b':
retval.append("\\b");
continue;
case '\t':
retval.append("\\t");
continue;
case '\n':
retval.append("\\n");
continue;
case '\f':
retval.append("\\f");
continue;
case '\r':
retval.append("\\r");
continue;
case '\"':
retval.append("\\\"");
continue;
case '\'':
retval.append("\\\'");
continue;
case '\\':
retval.append("\\\\");
continue;
default:
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
String s = "0000" + Integer.toString(ch, 16);
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
} else {
retval.append(ch);
}
continue;
}
}
return retval.toString();
}
}
/* JavaCC - OriginalChecksum=87586a39aa89f164889cc59bc6a7e7ad (do not edit this line) */

View File

@@ -0,0 +1,472 @@
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package org.apache.el.parser;
/**
* An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing).
*/
@SuppressWarnings("all") // Ignore warnings in generated code
public class SimpleCharStream
{
/** Whether parser is static. */
public static final boolean staticFlag = false;
int bufsize;
int available;
int tokenBegin;
/** Position in buffer. */
public int bufpos = -1;
protected int bufline[];
protected int bufcolumn[];
protected int column = 0;
protected int line = 1;
protected boolean prevCharIsCR = false;
protected boolean prevCharIsLF = false;
protected java.io.Reader inputStream;
protected char[] buffer;
protected int maxNextCharInd = 0;
protected int inBuf = 0;
protected int tabSize = 8;
protected void setTabSize(int i) { tabSize = i; }
protected int getTabSize(int i) { return tabSize; }
protected void ExpandBuff(boolean wrapAround)
{
char[] newbuffer = new char[bufsize + 2048];
int newbufline[] = new int[bufsize + 2048];
int newbufcolumn[] = new int[bufsize + 2048];
try
{
if (wrapAround)
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
}
else
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
bufline = newbufline;
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
bufcolumn = newbufcolumn;
maxNextCharInd = (bufpos -= tokenBegin);
}
}
catch (Throwable t)
{
throw new Error(t.getMessage());
}
bufsize += 2048;
available = bufsize;
tokenBegin = 0;
}
protected void FillBuff() throws java.io.IOException
{
if (maxNextCharInd == available)
{
if (available == bufsize)
{
if (tokenBegin > 2048)
{
bufpos = maxNextCharInd = 0;
available = tokenBegin;
}
else if (tokenBegin < 0)
bufpos = maxNextCharInd = 0;
else
ExpandBuff(false);
}
else if (available > tokenBegin)
available = bufsize;
else if ((tokenBegin - available) < 2048)
ExpandBuff(true);
else
available = tokenBegin;
}
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
}
else
maxNextCharInd += i;
return;
}
catch(java.io.IOException e) {
--bufpos;
backup(0);
if (tokenBegin == -1)
tokenBegin = bufpos;
throw e;
}
}
/** Start. */
public char BeginToken() throws java.io.IOException
{
tokenBegin = -1;
char c = readChar();
tokenBegin = bufpos;
return c;
}
protected void UpdateLineColumn(char c)
{
column++;
if (prevCharIsLF)
{
prevCharIsLF = false;
line += (column = 1);
}
else if (prevCharIsCR)
{
prevCharIsCR = false;
if (c == '\n')
{
prevCharIsLF = true;
}
else
line += (column = 1);
}
switch (c)
{
case '\r' :
prevCharIsCR = true;
break;
case '\n' :
prevCharIsLF = true;
break;
case '\t' :
column--;
column += (tabSize - (column % tabSize));
break;
default :
break;
}
bufline[bufpos] = line;
bufcolumn[bufpos] = column;
}
/** Read a character. */
public char readChar() throws java.io.IOException
{
if (inBuf > 0)
{
--inBuf;
if (++bufpos == bufsize)
bufpos = 0;
return buffer[bufpos];
}
if (++bufpos >= maxNextCharInd)
FillBuff();
char c = buffer[bufpos];
UpdateLineColumn(c);
return c;
}
@Deprecated
/**
* @deprecated
* @see #getEndColumn
*/
public int getColumn() {
return bufcolumn[bufpos];
}
@Deprecated
/**
* @deprecated
* @see #getEndLine
*/
public int getLine() {
return bufline[bufpos];
}
/** Get token end column number. */
public int getEndColumn() {
return bufcolumn[bufpos];
}
/** Get token end line number. */
public int getEndLine() {
return bufline[bufpos];
}
/** Get token beginning column number. */
public int getBeginColumn() {
return bufcolumn[tokenBegin];
}
/** Get token beginning line number. */
public int getBeginLine() {
return bufline[tokenBegin];
}
/** Backup a number of characters. */
public void backup(int amount) {
inBuf += amount;
if ((bufpos -= amount) < 0)
bufpos += bufsize;
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream)
{
this(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
inputStream = dstream;
line = startline;
column = startcolumn - 1;
if (buffer == null || buffersize != buffer.length)
{
available = bufsize = buffersize;
buffer = new char[buffersize];
bufline = new int[buffersize];
bufcolumn = new int[buffersize];
}
prevCharIsLF = prevCharIsCR = false;
tokenBegin = inBuf = maxNextCharInd = 0;
bufpos = -1;
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream)
{
ReInit(dstream, 1, 1, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException
{
this(dstream, encoding, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{
this(dstream, encoding, 1, 1, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream)
{
this(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{
ReInit(dstream, encoding, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream)
{
ReInit(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException
{
ReInit(dstream, encoding, startline, startcolumn, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
/** Get token literal value. */
public String GetImage()
{
if (bufpos >= tokenBegin)
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
else
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
new String(buffer, 0, bufpos + 1);
}
/** Get the suffix. */
public char[] GetSuffix(int len)
{
char[] ret = new char[len];
if ((bufpos + 1) >= len)
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
else
{
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
len - bufpos - 1);
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
}
return ret;
}
/** Reset buffer when finished. */
public void Done()
{
buffer = null;
bufline = null;
bufcolumn = null;
}
/**
* Method to adjust line and column numbers for the start of a token.
*/
public void adjustBeginLineColumn(int newLine, int newCol)
{
int start = tokenBegin;
int len;
if (bufpos >= tokenBegin)
{
len = bufpos - tokenBegin + inBuf + 1;
}
else
{
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
}
int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0;
while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
{
bufline[j] = newLine;
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
bufcolumn[j] = newCol + columnDiff;
columnDiff = nextColDiff;
i++;
}
if (i < len)
{
bufline[j] = newLine++;
bufcolumn[j] = newCol + columnDiff;
while (i++ < len)
{
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
bufline[j] = newLine++;
else
bufline[j] = newLine;
}
}
line = bufline[j];
column = bufcolumn[j];
}
}
/* JavaCC - OriginalChecksum=9ba0db3918bffb8019f00da1e421f339 (do not edit this line) */

View File

@@ -0,0 +1,213 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Generated By:JJTree: Do not edit this line. SimpleNode.java */
package org.apache.el.parser;
import java.util.Arrays;
import javax.el.ELException;
import javax.el.MethodInfo;
import javax.el.PropertyNotWritableException;
import javax.el.ValueReference;
import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
import org.apache.el.util.MessageFactory;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public abstract class SimpleNode extends ELSupport implements Node {
protected Node parent;
protected Node[] children;
protected final int id;
protected String image;
public SimpleNode(int i) {
id = i;
}
@Override
public void jjtOpen() {
// NOOP by default
}
@Override
public void jjtClose() {
// NOOP by default
}
@Override
public void jjtSetParent(Node n) {
parent = n;
}
@Override
public Node jjtGetParent() {
return parent;
}
@Override
public void jjtAddChild(Node n, int i) {
if (children == null) {
children = new Node[i + 1];
} else if (i >= children.length) {
Node c[] = new Node[i + 1];
System.arraycopy(children, 0, c, 0, children.length);
children = c;
}
children[i] = n;
}
@Override
public Node jjtGetChild(int i) {
return children[i];
}
@Override
public int jjtGetNumChildren() {
return (children == null) ? 0 : children.length;
}
/*
* You can override these two methods in subclasses of SimpleNode to
* customize the way the node appears when the tree is dumped. If your
* output uses more than one line you should override toString(String),
* otherwise overriding toString() is probably all you need to do.
*/
@Override
public String toString() {
if (this.image != null) {
return ELParserTreeConstants.jjtNodeName[id] + "[" + this.image
+ "]";
}
return ELParserTreeConstants.jjtNodeName[id];
}
@Override
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@Override
public Class<?> getType(EvaluationContext ctx)
throws ELException {
throw new UnsupportedOperationException();
}
@Override
public Object getValue(EvaluationContext ctx)
throws ELException {
throw new UnsupportedOperationException();
}
@Override
public boolean isReadOnly(EvaluationContext ctx)
throws ELException {
return true;
}
@Override
public void setValue(EvaluationContext ctx, Object value)
throws ELException {
throw new PropertyNotWritableException(MessageFactory.get("error.syntax.set"));
}
@Override
public void accept(NodeVisitor visitor) throws Exception {
visitor.visit(this);
if (this.children != null && this.children.length > 0) {
for (int i = 0; i < this.children.length; i++) {
this.children[i].accept(visitor);
}
}
}
@Override
public Object invoke(EvaluationContext ctx, Class<?>[] paramTypes,
Object[] paramValues) throws ELException {
throw new UnsupportedOperationException();
}
@Override
public MethodInfo getMethodInfo(EvaluationContext ctx,
Class<?>[] paramTypes) throws ELException {
throw new UnsupportedOperationException();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(children);
result = prime * result + id;
result = prime * result + ((image == null) ? 0 : image.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof SimpleNode)) {
return false;
}
SimpleNode other = (SimpleNode) obj;
if (id != other.id) {
return false;
}
if (image == null) {
if (other.image != null) {
return false;
}
} else if (!image.equals(other.image)) {
return false;
}
if (!Arrays.equals(children, other.children)) {
return false;
}
return true;
}
/**
* @since EL 2.2
*/
@Override
public ValueReference getValueReference(EvaluationContext ctx) {
return null;
}
/**
* @since EL 2.2
*/
@Override
public boolean isParametersProvided() {
return false;
}
}

View File

@@ -0,0 +1,132 @@
/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package org.apache.el.parser;
/**
* Describes the input token stream.
*/
@SuppressWarnings("all") // Ignore warnings in generated code
public class Token implements java.io.Serializable {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/**
* An integer that describes the kind of this token. This numbering
* system is determined by JavaCCParser, and a table of these numbers is
* stored in the file ...Constants.java.
*/
public int kind;
/** The line number of the first character of this Token. */
public int beginLine;
/** The column number of the first character of this Token. */
public int beginColumn;
/** The line number of the last character of this Token. */
public int endLine;
/** The column number of the last character of this Token. */
public int endColumn;
/**
* The string image of the token.
*/
public String image;
/**
* A reference to the next regular (non-special) token from the input
* stream. If this is the last token from the input stream, or if the
* token manager has not read tokens beyond this one, this field is
* set to null. This is true only if this token is also a regular
* token. Otherwise, see below for a description of the contents of
* this field.
*/
public Token next;
/**
* This field is used to access special tokens that occur prior to this
* token, but after the immediately preceding regular (non-special) token.
* If there are no such special tokens, this field is set to null.
* When there are more than one such special token, this field refers
* to the last of these special tokens, which in turn refers to the next
* previous special token through its specialToken field, and so on
* until the first special token (whose specialToken field is null).
* The next fields of special tokens refer to other special tokens that
* immediately follow it (without an intervening regular token). If there
* is no such token, this field is null.
*/
public Token specialToken;
/**
* An optional attribute value of the Token.
* Tokens which are not used as syntactic sugar will often contain
* meaningful values that will be used later on by the compiler or
* interpreter. This attribute value is often different from the image.
* Any subclass of Token that actually wants to return a non-null value can
* override this method as appropriate.
*/
public Object getValue() {
return null;
}
/**
* No-argument constructor
*/
public Token() {}
/**
* Constructs a new token for the specified Image.
*/
public Token(int kind)
{
this(kind, null);
}
/**
* Constructs a new token for the specified Image and Kind.
*/
public Token(int kind, String image)
{
this.kind = kind;
this.image = image;
}
/**
* Returns the image.
*/
public String toString()
{
return image;
}
/**
* Returns a new Token object, by default. However, if you want, you
* can create and return subclass objects based on the value of ofKind.
* Simply add the cases to the switch for all those special cases.
* For example, if you have a subclass of Token called IDToken that
* you want to create if ofKind is ID, simply add something like :
*
* case MyParserConstants.ID : return new IDToken(ofKind, image);
*
* to the following switch statement. Then you can cast matchedToken
* variable to the appropriate type and use sit in your lexical actions.
*/
public static Token newToken(int ofKind, String image)
{
switch(ofKind)
{
default : return new Token(ofKind, image);
}
}
public static Token newToken(int ofKind)
{
return newToken(ofKind, null);
}
}
/* JavaCC - OriginalChecksum=3fc97649fffa8b13e1e03af022020b2f (do not edit this line) */

View File

@@ -0,0 +1,148 @@
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
/* JavaCCOptions: */
package org.apache.el.parser;
/** Token Manager Error. */
@SuppressWarnings("all") // Ignore warnings in generated code
public class TokenMgrError extends Error
{
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/*
* Ordinals for various reasons why an Error of this type can be thrown.
*/
/**
* Lexical error occurred.
*/
static final int LEXICAL_ERROR = 0;
/**
* An attempt was made to create a second instance of a static token manager.
*/
static final int STATIC_LEXER_ERROR = 1;
/**
* Tried to change to an invalid lexical state.
*/
static final int INVALID_LEXICAL_STATE = 2;
/**
* Detected (and bailed out of) an infinite loop in the token manager.
*/
static final int LOOP_DETECTED = 3;
/**
* Indicates the reason why the exception is thrown. It will have
* one of the above 4 values.
*/
int errorCode;
/**
* Replaces unprintable characters by their escaped (or unicode escaped)
* equivalents in the given string
*/
protected static final String addEscapes(String str) {
StringBuffer retval = new StringBuffer();
char ch;
for (int i = 0; i < str.length(); i++) {
switch (str.charAt(i))
{
case 0 :
continue;
case '\b':
retval.append("\\b");
continue;
case '\t':
retval.append("\\t");
continue;
case '\n':
retval.append("\\n");
continue;
case '\f':
retval.append("\\f");
continue;
case '\r':
retval.append("\\r");
continue;
case '\"':
retval.append("\\\"");
continue;
case '\'':
retval.append("\\\'");
continue;
case '\\':
retval.append("\\\\");
continue;
default:
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
String s = "0000" + Integer.toString(ch, 16);
retval.append("\\u" + s.substring(s.length() - 4, s.length()));
} else {
retval.append(ch);
}
continue;
}
}
return retval.toString();
}
/**
* Returns a detailed message for the Error when it is thrown by the
* token manager to indicate a lexical error.
* Parameters :
* EOFSeen : indicates if EOF caused the lexical error
* curLexState : lexical state in which this error occurred
* errorLine : line number when the error occurred
* errorColumn : column number when the error occurred
* errorAfter : prefix that was seen before this error occurred
* curchar : the offending character
* Note: You can customize the lexical error message by modifying this method.
*/
protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
return("Lexical error at line " +
errorLine + ", column " +
errorColumn + ". Encountered: " +
(EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
"after : \"" + addEscapes(errorAfter) + "\"");
}
/**
* You can also modify the body of this method to customize your error messages.
* For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
* of end-users concern, so you can return something like :
*
* "Internal Error : Please file a bug report .... "
*
* from this method for such cases in the release version of your parser.
*/
public String getMessage() {
return super.getMessage();
}
/*
* Constructors of various flavors follow.
*/
/** No arg constructor. */
public TokenMgrError() {
}
/** Constructor with message and reason. */
public TokenMgrError(String message, int reason) {
super(message);
errorCode = reason;
}
/** Full Constructor. */
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
}
}
/* JavaCC - OriginalChecksum=de3ff0bacfb0fe749cc8eaf56ae82fea (do not edit this line) */

View File

@@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.stream;
import javax.el.ELException;
import javax.el.LambdaExpression;
import org.apache.el.util.MessageFactory;
public class Optional {
private final Object obj;
static final Optional EMPTY = new Optional(null);
Optional(Object obj) {
this.obj = obj;
}
public Object get() throws ELException {
if (obj == null) {
throw new ELException(MessageFactory.get("stream.optional.empty"));
} else {
return obj;
}
}
public void ifPresent(LambdaExpression le) {
if (obj != null) {
le.invoke(obj);
}
}
public Object orElse(Object other) {
if (obj == null) {
return other;
} else {
return obj;
}
}
public Object orElseGet(Object le) {
if (obj == null) {
// EL 3.0 specification says parameter is LambdaExpression but it
// may already have been evaluated. If that is the case, the
// original parameter will have been checked to ensure it was a
// LambdaExpression before it was evaluated.
if (le instanceof LambdaExpression) {
return ((LambdaExpression) le).invoke((Object[]) null);
} else {
return le;
}
} else {
return obj;
}
}
}

View File

@@ -0,0 +1,522 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.el.ELException;
import javax.el.LambdaExpression;
import org.apache.el.lang.ELArithmetic;
import org.apache.el.lang.ELSupport;
import org.apache.el.util.MessageFactory;
public class Stream {
private final Iterator<Object> iterator;
public Stream(Iterator<Object> iterator) {
this.iterator = iterator;
}
public Stream filter(final LambdaExpression le) {
Iterator<Object> downStream = new OpIterator() {
@Override
protected void findNext() {
while (iterator.hasNext()) {
Object obj = iterator.next();
if (ELSupport.coerceToBoolean(null, le.invoke(obj),
true).booleanValue()) {
next = obj;
foundNext = true;
break;
}
}
}
};
return new Stream(downStream);
}
public Stream map(final LambdaExpression le) {
Iterator<Object> downStream = new OpIterator() {
@Override
protected void findNext() {
if (iterator.hasNext()) {
Object obj = iterator.next();
next = le.invoke(obj);
foundNext = true;
}
}
};
return new Stream(downStream);
}
public Stream flatMap(final LambdaExpression le) {
Iterator<Object> downStream = new OpIterator() {
private Iterator<?> inner;
@Override
protected void findNext() {
while (iterator.hasNext() ||
(inner != null && inner.hasNext())) {
if (inner == null || !inner.hasNext()) {
inner = ((Stream) le.invoke(iterator.next())).iterator;
}
if (inner.hasNext()) {
next = inner.next();
foundNext = true;
break;
}
}
}
};
return new Stream(downStream);
}
public Stream distinct() {
Iterator<Object> downStream = new OpIterator() {
private Set<Object> values = new HashSet<>();
@Override
protected void findNext() {
while (iterator.hasNext()) {
Object obj = iterator.next();
if (values.add(obj)) {
next = obj;
foundNext = true;
break;
}
}
}
};
return new Stream(downStream);
}
public Stream sorted() {
Iterator<Object> downStream = new OpIterator() {
private Iterator<Object> sorted = null;
@Override
protected void findNext() {
if (sorted == null) {
sort();
}
if (sorted.hasNext()) {
next = sorted.next();
foundNext = true;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private final void sort() {
List list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
Collections.sort(list);
sorted = list.iterator();
}
};
return new Stream(downStream);
}
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());
}
Collections.sort(list, c);
sorted = list.iterator();
}
};
return new Stream(downStream);
}
public Object forEach(final LambdaExpression le) {
while (iterator.hasNext()) {
le.invoke(iterator.next());
}
return null;
}
public Stream peek(final LambdaExpression le) {
Iterator<Object> downStream = new OpIterator() {
@Override
protected void findNext() {
if (iterator.hasNext()) {
Object obj = iterator.next();
le.invoke(obj);
next = obj;
foundNext = true;
}
}
};
return new Stream(downStream);
}
public Iterator<?> iterator() {
return iterator;
}
public Stream limit(final Number count) {
return substream(Integer.valueOf(0), count);
}
public Stream substream(final Number start) {
return substream(start, Integer.valueOf(Integer.MAX_VALUE));
}
public Stream substream(final Number start, final Number end) {
Iterator<Object> downStream = new OpIterator() {
private final int startPos = start.intValue();
private final int endPos = end.intValue();
private int itemCount = 0;
@Override
protected void findNext() {
while (itemCount < startPos && iterator.hasNext()) {
iterator.next();
itemCount++;
}
if (itemCount < endPos && iterator.hasNext()) {
itemCount++;
next = iterator.next();
foundNext = true;
}
}
};
return new Stream(downStream);
}
public List<Object> toList() {
List<Object> result = new ArrayList<>();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return result;
}
public Object[] toArray() {
List<Object> result = new ArrayList<>();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return result.toArray(new Object[result.size()]);
}
public Optional reduce(LambdaExpression le) {
Object seed = null;
if (iterator.hasNext()) {
seed = iterator.next();
}
if (seed == null) {
return Optional.EMPTY;
} else {
return new Optional(reduce(seed, le));
}
}
public Object reduce(Object seed, LambdaExpression le) {
Object result = seed;
while (iterator.hasNext()) {
result = le.invoke(result, iterator.next());
}
return result;
}
public Optional max() {
return compare(true);
}
public Optional max(LambdaExpression le) {
return compare(true, le);
}
public Optional min() {
return compare(false);
}
public Optional min(LambdaExpression le) {
return compare(false, le);
}
public Optional average() {
long count = 0;
Number sum = Long.valueOf(0);
while (iterator.hasNext()) {
count++;
sum = ELArithmetic.add(sum, iterator.next());
}
if (count == 0) {
return Optional.EMPTY;
} else {
return new Optional(ELArithmetic.divide(sum, Long.valueOf(count)));
}
}
public Number sum() {
Number sum = Long.valueOf(0);
while (iterator.hasNext()) {
sum = ELArithmetic.add(sum, iterator.next());
}
return sum;
}
public Long count() {
long count = 0;
while (iterator.hasNext()) {
iterator.next();
count ++;
}
return Long.valueOf(count);
}
public Optional anyMatch(LambdaExpression le) {
if (!iterator.hasNext()) {
return Optional.EMPTY;
}
Boolean match = Boolean.FALSE;
while (!match.booleanValue() && iterator.hasNext()) {
match = (Boolean) le.invoke(iterator.next());
}
return new Optional(match);
}
public Optional allMatch(LambdaExpression le) {
if (!iterator.hasNext()) {
return Optional.EMPTY;
}
Boolean match = Boolean.TRUE;
while (match.booleanValue() && iterator.hasNext()) {
match = (Boolean) le.invoke(iterator.next());
}
return new Optional(match);
}
public Optional noneMatch(LambdaExpression le) {
if (!iterator.hasNext()) {
return Optional.EMPTY;
}
Boolean match = Boolean.FALSE;
while (!match.booleanValue() && iterator.hasNext()) {
match = (Boolean) le.invoke(iterator.next());
}
return new Optional(Boolean.valueOf(!match.booleanValue()));
}
public Optional findFirst() {
if (iterator.hasNext()) {
return new Optional(iterator.next());
} else {
return Optional.EMPTY;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Optional compare(boolean isMax) {
Comparable result = null;
if (iterator.hasNext()) {
Object obj = iterator.next();
if ((obj instanceof Comparable)) {
result = (Comparable) obj;
} else {
throw new ELException(
MessageFactory.get("stream.compare.notComparable"));
}
}
while (iterator.hasNext()) {
Object obj = iterator.next();
if ((obj instanceof Comparable)) {
if (isMax && ((Comparable) obj).compareTo(result) > 0) {
result = (Comparable) obj;
} else if (!isMax && ((Comparable) obj).compareTo(result) < 0) {
result = (Comparable) obj;
}
} else {
throw new ELException(
MessageFactory.get("stream.compare.notComparable"));
}
}
if (result == null) {
return Optional.EMPTY;
} else {
return new Optional(result);
}
}
private Optional compare(boolean isMax, LambdaExpression le) {
Object result = null;
if (iterator.hasNext()) {
Object obj = iterator.next();
result = obj;
}
while (iterator.hasNext()) {
Object obj = iterator.next();
if (isMax && ELSupport.coerceToNumber(null, le.invoke(obj, result),
Integer.class).intValue() > 0) {
result = obj;
} else if (!isMax && ELSupport.coerceToNumber(null, le.invoke(obj, result),
Integer.class).intValue() < 0) {
result = obj;
}
}
if (result == null) {
return Optional.EMPTY;
} else {
return new Optional(result);
}
}
private static class LambdaExpressionComparator
implements Comparator<Object> {
private final LambdaExpression le;
public LambdaExpressionComparator(LambdaExpression le) {
this.le = le;
}
@Override
public int compare(Object o1, Object o2) {
return ELSupport.coerceToNumber(
null, le.invoke(o1, o2), Integer.class).intValue();
}
}
private abstract static class OpIterator implements Iterator<Object> {
protected boolean foundNext = false;
protected Object next;
@Override
public boolean hasNext() {
if (foundNext) {
return true;
}
findNext();
return foundNext;
}
@Override
public Object next() {
if (foundNext) {
foundNext = false;
return next;
}
findNext();
if (foundNext) {
foundNext = false;
return next;
} else {
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
protected abstract void findNext();
}
}

View File

@@ -0,0 +1,113 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.stream;
import java.beans.FeatureDescriptor;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.el.ELContext;
import javax.el.ELResolver;
public class StreamELResolverImpl extends ELResolver {
@Override
public Object getValue(ELContext context, Object base, Object property) {
return null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
@Override
public void setValue(ELContext context, Object base, Object property,
Object value) {
// NO-OP
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return false;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context,
Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
@Override
public Object invoke(ELContext context, Object base, Object method,
Class<?>[] paramTypes, Object[] params) {
if ("stream".equals(method) && params.length == 0) {
if (base.getClass().isArray()) {
context.setPropertyResolved(true);
return new Stream(new ArrayIterator(base));
} else if (base instanceof Collection) {
context.setPropertyResolved(true);
@SuppressWarnings("unchecked")
Collection<Object> collection = (Collection<Object>) base;
return new Stream(collection.iterator());
}
}
// Not for handling by this resolver
return null;
}
private static class ArrayIterator implements Iterator<Object> {
private final Object base;
private final int size;
private int index = 0;
public ArrayIterator(Object base) {
this.base = base;
size = Array.getLength(base);
}
@Override
public boolean hasNext() {
return size > index;
}
@Override
public Object next() {
try {
return Array.get(base, index++);
} catch (ArrayIndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
public final class ConcurrentCache<K,V> {
private final int size;
private final Map<K,V> eden;
private final Map<K,V> longterm;
public ConcurrentCache(int size) {
this.size = size;
this.eden = new ConcurrentHashMap<>(size);
this.longterm = new WeakHashMap<>(size);
}
public V get(K k) {
V v = this.eden.get(k);
if (v == null) {
synchronized (longterm) {
v = this.longterm.get(k);
}
if (v != null) {
this.eden.put(k, v);
}
}
return v;
}
public void put(K k, V v) {
if (this.eden.size() >= size) {
synchronized (longterm) {
this.longterm.putAll(this.eden);
}
this.eden.clear();
}
this.eden.put(k, v);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
/*
* This is a cut down version of org.apache.tomcat.util.Jre9Compat that provides
* only the methods required by the EL implementation.
*
* This class is duplicated in javax.el
* When making changes keep the two in sync.
*/
class Jre9Compat extends JreCompat {
private static final Method canAccessMethod;
static {
Method m1 = null;
try {
m1 = AccessibleObject.class.getMethod("canAccess", new Class<?>[] { Object.class });
} catch (NoSuchMethodException e) {
// Expected for Java 8
}
canAccessMethod = m1;
}
public static boolean isSupported() {
return canAccessMethod != null;
}
@Override
public boolean canAcccess(Object base, AccessibleObject accessibleObject) {
try {
return ((Boolean) canAccessMethod.invoke(accessibleObject, base)).booleanValue();
} catch (ReflectiveOperationException | IllegalArgumentException e) {
return false;
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.lang.reflect.AccessibleObject;
/*
* This is a cut down version of org.apache.tomcat.util.JreCompat that provides
* only the methods required by the EL implementation.
*
* This class is duplicated in javax.el
* When making changes keep the two in sync.
*/
public class JreCompat {
private static final JreCompat instance;
static {
if (Jre9Compat.isSupported()) {
instance = new Jre9Compat();
} else {
instance = new JreCompat();
}
}
public static JreCompat getInstance() {
return instance;
}
/**
* Is the accessibleObject accessible (as a result of appropriate module
* exports) on the provided instance?
*
* @param base The specific instance to be tested.
* @param accessibleObject The method/field/constructor to be tested.
*
* @return {code true} if the AccessibleObject can be accessed otherwise
* {code false}
*/
public boolean canAcccess(Object base, AccessibleObject accessibleObject) {
// Java 8 doesn't support modules so default to true
return true;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* @author Jacob Hookom [jacob@hookom.net]
*/
public final class MessageFactory {
static final ResourceBundle bundle =
ResourceBundle.getBundle("org.apache.el.Messages");
public MessageFactory() {
super();
}
public static String get(final String key) {
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
}
public static String get(final String key, final Object... args) {
String value = get(key);
MessageFormat mf = new MessageFormat(value);
return mf.format(args, new StringBuffer(), null).toString();
}
}

View File

@@ -0,0 +1,585 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.el.ELException;
import javax.el.MethodNotFoundException;
import org.apache.el.lang.ELSupport;
import org.apache.el.lang.EvaluationContext;
/**
* Utilities for Managing Serialization and Reflection
*
* @author Jacob Hookom [jacob@hookom.net]
*/
public class ReflectionUtil {
protected static final String[] PRIMITIVE_NAMES = new String[] { "boolean",
"byte", "char", "double", "float", "int", "long", "short", "void" };
protected static final Class<?>[] PRIMITIVES = new Class[] { boolean.class,
byte.class, char.class, double.class, float.class, int.class,
long.class, short.class, Void.TYPE };
private ReflectionUtil() {
super();
}
public static Class<?> forName(String name) throws ClassNotFoundException {
if (null == name || "".equals(name)) {
return null;
}
Class<?> c = forNamePrimitive(name);
if (c == null) {
if (name.endsWith("[]")) {
String nc = name.substring(0, name.length() - 2);
c = Class.forName(nc, true, getContextClassLoader());
c = Array.newInstance(c, 0).getClass();
} else {
c = Class.forName(name, true, getContextClassLoader());
}
}
return c;
}
protected static Class<?> forNamePrimitive(String name) {
if (name.length() <= 8) {
int p = Arrays.binarySearch(PRIMITIVE_NAMES, name);
if (p >= 0) {
return PRIMITIVES[p];
}
}
return null;
}
/**
* Converts an array of Class names to Class types.
* @param s The array of class names
* @return An array of Class instance where the element at index i in the
* result is an instance of the class with the name at index i in
* the input
* @throws ClassNotFoundException If a class of a given name cannot be found
*/
public static Class<?>[] toTypeArray(String[] s) throws ClassNotFoundException {
if (s == null)
return null;
Class<?>[] c = new Class[s.length];
for (int i = 0; i < s.length; i++) {
c[i] = forName(s[i]);
}
return c;
}
/**
* Converts an array of Class types to Class names.
* @param c The array of class instances
* @return An array of Class names where the element at index i in the
* result is the name of the class instance at index i in the input
*/
public static String[] toTypeNameArray(Class<?>[] c) {
if (c == null)
return null;
String[] s = new String[c.length];
for (int i = 0; i < c.length; i++) {
s[i] = c[i].getName();
}
return s;
}
/**
* 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 javax.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;
if (mParamTypes == null) {
mParamCount = 0;
} else {
mParamCount = mParamTypes.length;
}
// Check the number of parameters
// 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;
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)) {
// Nothing is passed as varargs
assignableMatch++;
break;
}
Class<?> varType = mParamTypes[i].getComponentType();
for (int j = i; j < paramCount; j++) {
if (isAssignableFrom(paramTypes[j], varType)) {
assignableMatch++;
} else {
if (paramValues == null) {
noMatch = true;
break;
} else {
if (isCoercibleFrom(ctx, paramValues[j], varType)) {
coercibleMatch++;
} 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;
}
// If a method is found where every parameter matches exactly,
// return it
if (exactMatch == paramCount) {
return getMethod(base.getClass(), base, m);
}
candidates.put(m, new MatchResult(
exactMatch, assignableMatch, coercibleMatch, m.isBridge()));
}
// Look for the method that has the highest number of parameters where
// the type matches exactly
MatchResult bestMatch = new MatchResult(0, 0, 0, false);
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.getExact() == 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) {
// If multiple methods have the same matching number of parameters
// 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);
}
/*
* This class duplicates code in javax.el.Util. When making changes keep
* the code in sync.
*/
private static Method resolveAmbiguousMethod(Set<Method> candidates,
Class<?>[] paramTypes) {
// Identify which parameter isn't an exact match
Method m = candidates.iterator().next();
int nonMatchIndex = 0;
Class<?> nonMatchClass = null;
for (int i = 0; i < paramTypes.length; i++) {
if (m.getParameterTypes()[i] != paramTypes[i]) {
nonMatchIndex = i;
nonMatchClass = paramTypes[i];
break;
}
}
if (nonMatchClass == null) {
// Null will always be ambiguous
return null;
}
for (Method c : candidates) {
if (c.getParameterTypes()[nonMatchIndex] ==
paramTypes[nonMatchIndex]) {
// Methods have different non-matching parameters
// Result is ambiguous
return null;
}
}
// Can't be null
Class<?> superClass = nonMatchClass.getSuperclass();
while (superClass != null) {
for (Method c : candidates) {
if (c.getParameterTypes()[nonMatchIndex].equals(superClass)) {
// Found a match
return c;
}
}
superClass = superClass.getSuperclass();
}
// Treat instances of Number as a special case
Method match = null;
if (Number.class.isAssignableFrom(nonMatchClass)) {
for (Method c : candidates) {
Class<?> candidateType = c.getParameterTypes()[nonMatchIndex];
if (Number.class.isAssignableFrom(candidateType) ||
candidateType.isPrimitive()) {
if (match == null) {
match = c;
} else {
// Match still ambiguous
match = null;
break;
}
}
}
}
return match;
}
/*
* This class duplicates code in javax.el.Util. When making changes keep
* the code in sync.
*/
private static boolean isAssignableFrom(Class<?> src, Class<?> target) {
// src will always be an object
// Short-cut. null is always assignable to an object and in EL null
// can always be coerced to a valid value for a primitive
if (src == null) {
return true;
}
Class<?> targetClass;
if (target.isPrimitive()) {
if (target == Boolean.TYPE) {
targetClass = Boolean.class;
} else if (target == Character.TYPE) {
targetClass = Character.class;
} else if (target == Byte.TYPE) {
targetClass = Byte.class;
} else if (target == Short.TYPE) {
targetClass = Short.class;
} else if (target == Integer.TYPE) {
targetClass = Integer.class;
} else if (target == Long.TYPE) {
targetClass = Long.class;
} else if (target == Float.TYPE) {
targetClass = Float.class;
} else {
targetClass = Double.class;
}
} else {
targetClass = target;
}
return targetClass.isAssignableFrom(src);
}
/*
* This class duplicates code in javax.el.Util. When making changes keep
* the code in sync.
*/
private static boolean isCoercibleFrom(EvaluationContext ctx, Object src, Class<?> target) {
// TODO: This isn't pretty but it works. Significant refactoring would
// be required to avoid the exception.
try {
ELSupport.coerceToType(ctx, src, target);
} catch (ELException e) {
return false;
}
return true;
}
/*
* This class duplicates code in javax.el.Util. When making changes keep
* the code in sync.
*/
private static Method getMethod(Class<?> type, Object base, Method m) {
JreCompat jreCompat = JreCompat.getInstance();
// If base is null, method MUST be static
// If base is non-null, method may be static or non-static
if (m == null ||
(Modifier.isPublic(type.getModifiers()) &&
(jreCompat.canAcccess(base, m) || base != null && jreCompat.canAcccess(null, m)))) {
return m;
}
Class<?>[] inf = type.getInterfaces();
Method mp = null;
for (int i = 0; i < inf.length; i++) {
try {
mp = inf[i].getMethod(m.getName(), m.getParameterTypes());
mp = getMethod(mp.getDeclaringClass(), base, mp);
if (mp != null) {
return mp;
}
} catch (NoSuchMethodException e) {
// Ignore
}
}
Class<?> sup = type.getSuperclass();
if (sup != null) {
try {
mp = sup.getMethod(m.getName(), m.getParameterTypes());
mp = getMethod(mp.getDeclaringClass(), base, mp);
if (mp != null) {
return mp;
}
} catch (NoSuchMethodException e) {
// Ignore
}
}
return null;
}
private static final String paramString(Class<?>[] types) {
if (types != null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < types.length; i++) {
if (types[i] == null) {
sb.append("null, ");
} else {
sb.append(types[i].getName()).append(", ");
}
}
if (sb.length() > 2) {
sb.setLength(sb.length() - 2);
}
return sb.toString();
}
return null;
}
private static ClassLoader getContextClassLoader() {
ClassLoader tccl;
if (System.getSecurityManager() != null) {
PrivilegedAction<ClassLoader> pa = new PrivilegedGetTccl();
tccl = AccessController.doPrivileged(pa);
} else {
tccl = Thread.currentThread().getContextClassLoader();
}
return tccl;
}
private static class PrivilegedGetTccl implements PrivilegedAction<ClassLoader> {
@Override
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
}
/*
* This class duplicates code in javax.el.Util. When making changes keep
* the code in sync.
*/
private static class MatchResult implements Comparable<MatchResult> {
private final int exact;
private final int assignable;
private final int coercible;
private final boolean bridge;
public MatchResult(int exact, int assignable, int coercible, boolean bridge) {
this.exact = exact;
this.assignable = assignable;
this.coercible = coercible;
this.bridge = bridge;
}
public int getExact() {
return exact;
}
public int getAssignable() {
return assignable;
}
public int getCoercible() {
return coercible;
}
public boolean isBridge() {
return bridge;
}
@Override
public int compareTo(MatchResult o) {
int cmp = Integer.compare(this.getExact(), o.getExact());
if (cmp == 0) {
cmp = Integer.compare(this.getAssignable(), o.getAssignable());
if (cmp == 0) {
cmp = Integer.compare(this.getCoercible(), o.getCoercible());
if (cmp == 0) {
// The nature of bridge methods is such that it actually
// doesn't matter which one we pick as long as we pick
// one. That said, pick the 'right' one (the non-bridge
// one) anyway.
cmp = Boolean.compare(o.isBridge(), this.isBridge());
}
}
}
return cmp;
}
@Override
public boolean equals(Object o)
{
return o == this
|| (null != o
&& this.getClass().equals(o.getClass())
&& ((MatchResult)o).getExact() == this.getExact()
&& ((MatchResult)o).getAssignable() == this.getAssignable()
&& ((MatchResult)o).getCoercible() == this.getCoercible()
&& ((MatchResult)o).isBridge() == this.isBridge()
)
;
}
@Override
public int hashCode()
{
return (this.isBridge() ? 1 << 24 : 0)
^ this.getExact() << 16
^ this.getAssignable() << 8
^ this.getCoercible()
;
}
}
}

View File

@@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.el.util;
import java.security.AccessController;
import java.security.PrivilegedAction;
public class Validation {
// Java keywords, boolean literals & the null literal in alphabetical order
private static final String invalidIdentifiers[] = { "abstract", "assert",
"boolean", "break", "byte", "case", "catch", "char", "class", "const",
"continue", "default", "do", "double", "else", "enum", "extends",
"false", "final", "finally", "float", "for", "goto", "if", "implements",
"import", "instanceof", "int", "interface", "long", "native", "new",
"null", "package", "private", "protected", "public", "return", "short",
"static", "strictfp", "super", "switch", "synchronized", "this",
"throw", "throws", "transient", "true", "try", "void", "volatile",
"while" };
private static final boolean IS_SECURITY_ENABLED =
(System.getSecurityManager() != null);
private static final boolean SKIP_IDENTIFIER_CHECK;
static {
String skipIdentifierCheckStr;
if (IS_SECURITY_ENABLED) {
skipIdentifierCheckStr = AccessController.doPrivileged(
new PrivilegedAction<String>(){
@Override
public String run() {
return System.getProperty(
"org.apache.el.parser.SKIP_IDENTIFIER_CHECK",
"false");
}
}
);
} else {
skipIdentifierCheckStr = System.getProperty(
"org.apache.el.parser.SKIP_IDENTIFIER_CHECK", "false");
}
SKIP_IDENTIFIER_CHECK = Boolean.parseBoolean(skipIdentifierCheckStr);
}
private Validation() {
// Utility class. Hide default constructor
}
/**
* Test whether a string is a Java identifier. Note that the behaviour of
* this method depend on the system property
* {@code org.apache.el.parser.SKIP_IDENTIFIER_CHECK}
*
* @param key The string to test
*
* @return {@code true} if the provided String should be treated as a Java
* identifier, otherwise false
*/
public static boolean isIdentifier(String key) {
if (SKIP_IDENTIFIER_CHECK) {
return true;
}
// Should not be the case but check to be sure
if (key == null || key.length() == 0) {
return false;
}
// Check the list of known invalid values
int i = 0;
int j = invalidIdentifiers.length;
while (i < j) {
int k = (i + j) >>> 1; // Avoid overflow
int result = invalidIdentifiers[k].compareTo(key);
if (result == 0) {
return false;
}
if (result < 0) {
i = k + 1;
} else {
j = k;
}
}
// Check the start character that has more restrictions
if (!Character.isJavaIdentifierStart(key.charAt(0))) {
return false;
}
// Check each remaining character used is permitted
for (int idx = 1; idx < key.length(); idx++) {
if (!Character.isJavaIdentifierPart(key.charAt(idx))) {
return false;
}
}
return true;
}
}