init
This commit is contained in:
84
java/org/apache/el/ExpressionFactoryImpl.java
Normal file
84
java/org/apache/el/ExpressionFactoryImpl.java
Normal 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();
|
||||
}
|
||||
}
|
||||
63
java/org/apache/el/Messages.properties
Normal file
63
java/org/apache/el/Messages.properties
Normal 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
|
||||
36
java/org/apache/el/Messages_es.properties
Normal file
36
java/org/apache/el/Messages_es.properties
Normal 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).
|
||||
331
java/org/apache/el/MethodExpressionImpl.java
Normal file
331
java/org/apache/el/MethodExpressionImpl.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
112
java/org/apache/el/MethodExpressionLiteral.java
Normal file
112
java/org/apache/el/MethodExpressionLiteral.java
Normal 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));
|
||||
}
|
||||
}
|
||||
293
java/org/apache/el/ValueExpressionImpl.java
Normal file
293
java/org/apache/el/ValueExpressionImpl.java
Normal 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;
|
||||
}
|
||||
}
|
||||
136
java/org/apache/el/ValueExpressionLiteral.java
Normal file
136
java/org/apache/el/ValueExpressionLiteral.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
401
java/org/apache/el/lang/ELArithmetic.java
Normal file
401
java/org/apache/el/lang/ELArithmetic.java
Normal 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);
|
||||
|
||||
}
|
||||
655
java/org/apache/el/lang/ELSupport.java
Normal file
655
java/org/apache/el/lang/ELSupport.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
157
java/org/apache/el/lang/EvaluationContext.java
Normal file
157
java/org/apache/el/lang/EvaluationContext.java
Normal 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);
|
||||
}
|
||||
}
|
||||
337
java/org/apache/el/lang/ExpressionBuilder.java
Normal file
337
java/org/apache/el/lang/ExpressionBuilder.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
69
java/org/apache/el/lang/FunctionMapperFactory.java
Normal file
69
java/org/apache/el/lang/FunctionMapperFactory.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
188
java/org/apache/el/lang/FunctionMapperImpl.java
Normal file
188
java/org/apache/el/lang/FunctionMapperImpl.java
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
55
java/org/apache/el/lang/VariableMapperFactory.java
Normal file
55
java/org/apache/el/lang/VariableMapperFactory.java
Normal 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");
|
||||
}
|
||||
}
|
||||
66
java/org/apache/el/lang/VariableMapperImpl.java
Normal file
66
java/org/apache/el/lang/VariableMapperImpl.java
Normal 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);
|
||||
}
|
||||
}
|
||||
37
java/org/apache/el/parser/ArithmeticNode.java
Normal file
37
java/org/apache/el/parser/ArithmeticNode.java
Normal 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;
|
||||
}
|
||||
}
|
||||
46
java/org/apache/el/parser/AstAnd.java
Normal file
46
java/org/apache/el/parser/AstAnd.java
Normal 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;
|
||||
}
|
||||
}
|
||||
50
java/org/apache/el/parser/AstAssign.java
Normal file
50
java/org/apache/el/parser/AstAssign.java
Normal 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) */
|
||||
39
java/org/apache/el/parser/AstBracketSuffix.java
Normal file
39
java/org/apache/el/parser/AstBracketSuffix.java
Normal 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);
|
||||
}
|
||||
}
|
||||
48
java/org/apache/el/parser/AstChoice.java
Normal file
48
java/org/apache/el/parser/AstChoice.java
Normal 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);
|
||||
}
|
||||
}
|
||||
57
java/org/apache/el/parser/AstCompositeExpression.java
Normal file
57
java/org/apache/el/parser/AstCompositeExpression.java
Normal 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();
|
||||
}
|
||||
}
|
||||
45
java/org/apache/el/parser/AstConcatenation.java
Normal file
45
java/org/apache/el/parser/AstConcatenation.java
Normal 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) */
|
||||
57
java/org/apache/el/parser/AstDeferredExpression.java
Normal file
57
java/org/apache/el/parser/AstDeferredExpression.java
Normal 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);
|
||||
}
|
||||
}
|
||||
42
java/org/apache/el/parser/AstDiv.java
Normal file
42
java/org/apache/el/parser/AstDiv.java
Normal 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);
|
||||
}
|
||||
}
|
||||
50
java/org/apache/el/parser/AstDotSuffix.java
Normal file
50
java/org/apache/el/parser/AstDotSuffix.java
Normal 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;
|
||||
}
|
||||
}
|
||||
57
java/org/apache/el/parser/AstDynamicExpression.java
Normal file
57
java/org/apache/el/parser/AstDynamicExpression.java
Normal 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);
|
||||
}
|
||||
}
|
||||
60
java/org/apache/el/parser/AstEmpty.java
Normal file
60
java/org/apache/el/parser/AstEmpty.java
Normal 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;
|
||||
}
|
||||
}
|
||||
41
java/org/apache/el/parser/AstEqual.java
Normal file
41
java/org/apache/el/parser/AstEqual.java
Normal 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));
|
||||
}
|
||||
}
|
||||
39
java/org/apache/el/parser/AstFalse.java
Normal file
39
java/org/apache/el/parser/AstFalse.java
Normal 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;
|
||||
}
|
||||
}
|
||||
60
java/org/apache/el/parser/AstFloatingPoint.java
Normal file
60
java/org/apache/el/parser/AstFloatingPoint.java
Normal 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();
|
||||
}
|
||||
}
|
||||
231
java/org/apache/el/parser/AstFunction.java
Normal file
231
java/org/apache/el/parser/AstFunction.java
Normal 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() + "]";
|
||||
}
|
||||
}
|
||||
47
java/org/apache/el/parser/AstGreaterThan.java
Normal file
47
java/org/apache/el/parser/AstGreaterThan.java
Normal 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;
|
||||
}
|
||||
}
|
||||
47
java/org/apache/el/parser/AstGreaterThanEqual.java
Normal file
47
java/org/apache/el/parser/AstGreaterThanEqual.java
Normal 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;
|
||||
}
|
||||
}
|
||||
238
java/org/apache/el/parser/AstIdentifier.java
Normal file
238
java/org/apache/el/parser/AstIdentifier.java
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
60
java/org/apache/el/parser/AstInteger.java
Normal file
60
java/org/apache/el/parser/AstInteger.java
Normal 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();
|
||||
}
|
||||
}
|
||||
182
java/org/apache/el/parser/AstLambdaExpression.java
Normal file
182
java/org/apache/el/parser/AstLambdaExpression.java
Normal 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) */
|
||||
43
java/org/apache/el/parser/AstLambdaParameters.java
Normal file
43
java/org/apache/el/parser/AstLambdaParameters.java
Normal 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) */
|
||||
47
java/org/apache/el/parser/AstLessThan.java
Normal file
47
java/org/apache/el/parser/AstLessThan.java
Normal 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;
|
||||
}
|
||||
}
|
||||
47
java/org/apache/el/parser/AstLessThanEqual.java
Normal file
47
java/org/apache/el/parser/AstLessThanEqual.java
Normal 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;
|
||||
}
|
||||
}
|
||||
50
java/org/apache/el/parser/AstListData.java
Normal file
50
java/org/apache/el/parser/AstListData.java
Normal 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) */
|
||||
66
java/org/apache/el/parser/AstLiteralExpression.java
Normal file
66
java/org/apache/el/parser/AstLiteralExpression.java
Normal 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();
|
||||
}
|
||||
}
|
||||
56
java/org/apache/el/parser/AstMapData.java
Normal file
56
java/org/apache/el/parser/AstMapData.java
Normal 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) */
|
||||
26
java/org/apache/el/parser/AstMapEntry.java
Normal file
26
java/org/apache/el/parser/AstMapEntry.java
Normal 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) */
|
||||
53
java/org/apache/el/parser/AstMethodParameters.java
Normal file
53
java/org/apache/el/parser/AstMethodParameters.java
Normal 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();
|
||||
}
|
||||
}
|
||||
42
java/org/apache/el/parser/AstMinus.java
Normal file
42
java/org/apache/el/parser/AstMinus.java
Normal 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);
|
||||
}
|
||||
}
|
||||
42
java/org/apache/el/parser/AstMod.java
Normal file
42
java/org/apache/el/parser/AstMod.java
Normal 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);
|
||||
}
|
||||
}
|
||||
42
java/org/apache/el/parser/AstMult.java
Normal file
42
java/org/apache/el/parser/AstMult.java
Normal 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);
|
||||
}
|
||||
}
|
||||
84
java/org/apache/el/parser/AstNegative.java
Normal file
84
java/org/apache/el/parser/AstNegative.java
Normal 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());
|
||||
}
|
||||
}
|
||||
47
java/org/apache/el/parser/AstNot.java
Normal file
47
java/org/apache/el/parser/AstNot.java
Normal 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());
|
||||
}
|
||||
}
|
||||
41
java/org/apache/el/parser/AstNotEqual.java
Normal file
41
java/org/apache/el/parser/AstNotEqual.java
Normal 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));
|
||||
}
|
||||
}
|
||||
45
java/org/apache/el/parser/AstNull.java
Normal file
45
java/org/apache/el/parser/AstNull.java
Normal 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;
|
||||
}
|
||||
}
|
||||
46
java/org/apache/el/parser/AstOr.java
Normal file
46
java/org/apache/el/parser/AstOr.java
Normal 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;
|
||||
}
|
||||
}
|
||||
42
java/org/apache/el/parser/AstPlus.java
Normal file
42
java/org/apache/el/parser/AstPlus.java
Normal 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);
|
||||
}
|
||||
}
|
||||
49
java/org/apache/el/parser/AstSemicolon.java
Normal file
49
java/org/apache/el/parser/AstSemicolon.java
Normal 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) */
|
||||
51
java/org/apache/el/parser/AstSetData.java
Normal file
51
java/org/apache/el/parser/AstSetData.java
Normal 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) */
|
||||
76
java/org/apache/el/parser/AstString.java
Normal file
76
java/org/apache/el/parser/AstString.java
Normal 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();
|
||||
}
|
||||
}
|
||||
39
java/org/apache/el/parser/AstTrue.java
Normal file
39
java/org/apache/el/parser/AstTrue.java
Normal 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;
|
||||
}
|
||||
}
|
||||
369
java/org/apache/el/parser/AstValue.java
Normal file
369
java/org/apache/el/parser/AstValue.java
Normal 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;
|
||||
}
|
||||
}
|
||||
37
java/org/apache/el/parser/BooleanNode.java
Normal file
37
java/org/apache/el/parser/BooleanNode.java
Normal 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;
|
||||
}
|
||||
}
|
||||
223
java/org/apache/el/parser/ELParser.html
Normal file
223
java/org/apache/el/parser/ELParser.html
Normal 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> )* <EOF></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><LITERAL_EXPRESSION></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><START_DEFERRED_EXPRESSION> <A HREF="#prod5">Expression</A> <END_EXPRESSION></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><START_DYNAMIC_EXPRESSION> <A HREF="#prod5">Expression</A> <END_EXPRESSION></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> ( <QUESTIONMARK> <A HREF="#prod6">Choice</A> <COLON> <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> ( ( <OR0> | <OR1> ) <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> ( ( <AND0> | <AND1> ) <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> ( ( ( <EQ0> | <EQ1> ) <A HREF="#prod10">Compare</A> ) | ( ( <NE0> | <NE1> ) <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> ( ( ( <LT0> | <LT1> ) <A HREF="#prod11">Math</A> ) | ( ( <GT0> | <GT1> ) <A HREF="#prod11">Math</A> ) | ( ( <LE0> | <LE1> ) <A HREF="#prod11">Math</A> ) | ( ( <GE0> | <GE1> ) <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> ( ( <PLUS> <A HREF="#prod12">Multiplication</A> ) | ( <MINUS> <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> ( ( <MULT> <A HREF="#prod13">Unary</A> ) | ( <DIV> <A HREF="#prod13">Unary</A> ) | ( ( <MOD0> | <MOD1> ) <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><MINUS> <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>( <NOT0> | <NOT1> ) <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><EMPTY> <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><DOT> <IDENTIFIER></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><LBRACK> <A HREF="#prod5">Expression</A> <RBRACK></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><LPAREN> <A HREF="#prod5">Expression</A> <RPAREN></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><IDENTIFIER></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><IDENTIFIER> ( <FUNCTIONSUFFIX> )? <LPAREN> ( <A HREF="#prod5">Expression</A> ( <COMMA> <A HREF="#prod5">Expression</A> )* )? <RPAREN></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><TRUE></TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN=RIGHT VALIGN=BASELINE></TD>
|
||||
<TD ALIGN=CENTER VALIGN=BASELINE>|</TD>
|
||||
<TD ALIGN=LEFT VALIGN=BASELINE><FALSE></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><FLOATING_POINT_LITERAL></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><INTEGER_LITERAL></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><STRING_LITERAL></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><NULL></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
3143
java/org/apache/el/parser/ELParser.java
Normal file
3143
java/org/apache/el/parser/ELParser.java
Normal file
File diff suppressed because it is too large
Load Diff
587
java/org/apache/el/parser/ELParser.jjt
Normal file
587
java/org/apache/el/parser/ELParser.jjt
Normal 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: (~[]) >
|
||||
}
|
||||
201
java/org/apache/el/parser/ELParserConstants.java
Normal file
201
java/org/apache/el/parser/ELParserConstants.java
Normal 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>",
|
||||
};
|
||||
|
||||
}
|
||||
2134
java/org/apache/el/parser/ELParserTokenManager.java
Normal file
2134
java/org/apache/el/parser/ELParserTokenManager.java
Normal file
File diff suppressed because it is too large
Load Diff
97
java/org/apache/el/parser/ELParserTreeConstants.java
Normal file
97
java/org/apache/el/parser/ELParserTreeConstants.java
Normal 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) */
|
||||
124
java/org/apache/el/parser/JJTELParserState.java
Normal file
124
java/org/apache/el/parser/JJTELParserState.java
Normal 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) */
|
||||
84
java/org/apache/el/parser/Node.java
Normal file
84
java/org/apache/el/parser/Node.java
Normal 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();
|
||||
}
|
||||
24
java/org/apache/el/parser/NodeVisitor.java
Normal file
24
java/org/apache/el/parser/NodeVisitor.java
Normal 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;
|
||||
}
|
||||
182
java/org/apache/el/parser/ParseException.java
Normal file
182
java/org/apache/el/parser/ParseException.java
Normal 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) */
|
||||
472
java/org/apache/el/parser/SimpleCharStream.java
Normal file
472
java/org/apache/el/parser/SimpleCharStream.java
Normal 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) */
|
||||
213
java/org/apache/el/parser/SimpleNode.java
Normal file
213
java/org/apache/el/parser/SimpleNode.java
Normal 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;
|
||||
}
|
||||
}
|
||||
132
java/org/apache/el/parser/Token.java
Normal file
132
java/org/apache/el/parser/Token.java
Normal 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) */
|
||||
148
java/org/apache/el/parser/TokenMgrError.java
Normal file
148
java/org/apache/el/parser/TokenMgrError.java
Normal 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) */
|
||||
76
java/org/apache/el/stream/Optional.java
Normal file
76
java/org/apache/el/stream/Optional.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
522
java/org/apache/el/stream/Stream.java
Normal file
522
java/org/apache/el/stream/Stream.java
Normal 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();
|
||||
}
|
||||
}
|
||||
113
java/org/apache/el/stream/StreamELResolverImpl.java
Normal file
113
java/org/apache/el/stream/StreamELResolverImpl.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
java/org/apache/el/util/ConcurrentCache.java
Normal file
59
java/org/apache/el/util/ConcurrentCache.java
Normal 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);
|
||||
}
|
||||
}
|
||||
58
java/org/apache/el/util/Jre9Compat.java
Normal file
58
java/org/apache/el/util/Jre9Compat.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
java/org/apache/el/util/JreCompat.java
Normal file
60
java/org/apache/el/util/JreCompat.java
Normal 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;
|
||||
}
|
||||
}
|
||||
49
java/org/apache/el/util/MessageFactory.java
Normal file
49
java/org/apache/el/util/MessageFactory.java
Normal 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();
|
||||
}
|
||||
}
|
||||
585
java/org/apache/el/util/ReflectionUtil.java
Normal file
585
java/org/apache/el/util/ReflectionUtil.java
Normal 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()
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
117
java/org/apache/el/util/Validation.java
Normal file
117
java/org/apache/el/util/Validation.java
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user