📄 elparser.java
字号:
/* * Copyright 2002-2004 the original author or authors. * * Licensed 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 de.mindmatters.faces.el;import java.io.StringReader;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.el.PropertyResolver;import javax.faces.el.ReferenceSyntaxException;import javax.servlet.jsp.el.ELException;import javax.servlet.jsp.el.FunctionMapper;import javax.servlet.jsp.el.VariableResolver;import org.apache.commons.el.ArraySuffix;import org.apache.commons.el.BinaryOperatorExpression;import org.apache.commons.el.Coercions;import org.apache.commons.el.ComplexValue;import org.apache.commons.el.ConditionalExpression;import org.apache.commons.el.Expression;import org.apache.commons.el.ExpressionString;import org.apache.commons.el.FunctionInvocation;import org.apache.commons.el.Literal;import org.apache.commons.el.Logger;import org.apache.commons.el.NamedValue;import org.apache.commons.el.PropertySuffix;import org.apache.commons.el.UnaryOperatorExpression;import org.apache.commons.el.ValueSuffix;import org.apache.commons.el.parser.ParseException;import org.springframework.util.Assert;import org.springframework.util.StringUtils;/** * Utility class to implement support functionality to "morph" JSP EL into JSF * EL. * * @author Andreas Kuhrwahl * */public final class ELParser { /** * Evaluates the expression in the given context, operating on the given * value, using JSF property resolver. * * @author Andreas Kuhrwahl * */ private class PropertyResolverBasedArraySuffix extends ArraySuffix { /** The PropertyResolver of the underlying JSF implementation. */ private final PropertyResolver propertyResolver; /** * Constructor. * * @param arraySuffix * <code>ArraySuffix</code> instance */ public PropertyResolverBasedArraySuffix(final ArraySuffix arraySuffix) { super(arraySuffix.getIndex()); replaceSuffixes(getIndex()); this.propertyResolver = FacesContext.getCurrentInstance() .getApplication().getPropertyResolver(); } /** * {@inheritDoc} */ public Object evaluate(final Object base, final VariableResolver variableResolver, final FunctionMapper functions, final Logger logger) throws ELException { Object result = null; if (base != null) { Object indexVal = getIndex().evaluate(variableResolver, functions, logger); if (indexVal != null) { Integer index = toIndex(base, indexVal); if (index == null) { result = this.propertyResolver.getValue(base, indexVal); } else { result = this.propertyResolver.getValue(base, index .intValue()); } } } return result; } } /** * Evaluates the expression in the given context, operating on the given * value, using JSF property resolver. * * @author Andreas Kuhrwahl * */ private class PropertyResolverBasedPropertySuffix extends PropertySuffix { /** The PropertyResolver of the underlying JSF implementation. */ private final PropertyResolver propertyResolver; /** * Constructor. * * @param propertySuffix * <code>PropertySuffix</code> instance */ public PropertyResolverBasedPropertySuffix( final PropertySuffix propertySuffix) { super(propertySuffix.getName()); this.propertyResolver = FacesContext.getCurrentInstance() .getApplication().getPropertyResolver(); } /** * {@inheritDoc} */ public Object evaluate(final Object base, final VariableResolver variableResolver, final FunctionMapper functions, final Logger logger) throws ELException { Object result = null; if (base != null) { String indexVal = getName(); if (indexVal != null) { Integer index = toIndex(base, indexVal); if (index == null) { result = this.propertyResolver.getValue(base, indexVal); } else { result = this.propertyResolver.getValue(base, index .intValue()); } } } return result; } } /** The singleton instance. */ private static final ELParser INSTANCE = new ELParser(); /** The cache for parsed expressions. */ private final Map expressionCache = new HashMap(); /** For logging. */ static final Logger LOGGER = new Logger(System.out); /** * Default Constructor. */ private ELParser() { super(); } /** * Returns an instance of ELParser. * * @return The singleton of this class. */ public static ELParser getCurrentInstance() { return INSTANCE; } /** * Coerces <code>index</code> to Integer for array types, or returns * <code>null</code> for non-array types. * * @param base * Object for the base * @param index * Object for the index * @return A valid Integer index, or null if not an array type * * @throws ELException * if exception occurs trying to coerce to Integer * @throws javax.faces.el.EvaluationException * if base is array type but cannot convert index to Integer */ private Integer toIndex(final Object base, final Object index) throws ELException { Integer result = null; if ((base instanceof List) || base.getClass().isArray()) { result = coerceToIntegerWrapper(base, index); } if (base instanceof UIComponent) { try { result = coerceToIntegerWrapper(base, index); } catch (Throwable t) { result = null; } } return result; } /** * Coerces <code>index</code> to Integer. * * @param base * Object for the base * @param index * Object for the index * @return A valid Integer index * @throws ELException * if exception occurs trying to coerce to Integer * @throws ReferenceSyntaxException * if base is array type but cannot convert index to Integer */ private Integer coerceToIntegerWrapper(final Object base, final Object index) throws ELException { Integer integer = Coercions.coerceToInteger(index, LOGGER); if (integer == null) { throw new ReferenceSyntaxException( "Cannot convert index to int for base " + base.getClass().getName() + " and index " + index); } return integer; } /** * Convert ValueBinding syntax #{ } to JSP EL syntax ${ }. * * @param expressionString * <code>ValueBinding</code> reference expression * @return JSP EL compatible expression */ public String convertToJspElExpression(final String expressionString) { Assert.notNull(expressionString); String result = StringUtils.replace(expressionString, "${", "${'${'}"); return StringUtils.replace(result, "#{", "${"); } /** * Returns the parsed form of the given expression string. Returns either an * {@link Expression} or {@link ExpressionString}. * * @param expressionString * <code>ValueBinding</code> reference expression * @return The parsed expression. * @throws ReferenceSyntaxException * in cases of parsing errors */ public Object parseExpression(final String expressionString) { Object expression = expressionCache.get(expressionString); if (expression == null) { String jspExpressionString = convertToJspElExpression(expressionString); org.apache.commons.el.parser.ELParser parser = new org.apache.commons.el.parser.ELParser( new StringReader(jspExpressionString)); try { expression = parser.ExpressionString(); if (expression instanceof Expression) { replaceSuffixes((Expression) expression); } else if (expression instanceof ExpressionString) { replaceSuffixes((ExpressionString) expression); } else { throw new ReferenceSyntaxException("Invalid expression: '" + expressionString + "'. Parsed Expression of unexpected type " + expression.getClass().getName()); } expressionCache.put(expressionString, expression); } catch (ParseException ex) { throw new ReferenceSyntaxException("Invalid expression: '" + expressionString + "'", ex); } } return expression; } /** * Replaces all <code>ValueSuffix</code>es with custom implementation * ValueSuffexes that use JSF <code>PropertyResolver</code> insted of JSP * EL one. * * @param expression * <code>Expression</code> instance */ private void replaceSuffixes(final Expression expression) { if (expression instanceof BinaryOperatorExpression) { replaceSuffixes(((BinaryOperatorExpression) expression) .getExpression()); } else if (expression instanceof ComplexValue) { replaceSuffixes((ComplexValue) expression); } else if (expression instanceof ConditionalExpression) { ConditionalExpression conditionalExpression = (ConditionalExpression) expression; replaceSuffixes(conditionalExpression.getTrueBranch()); replaceSuffixes(conditionalExpression.getFalseBranch()); } else if (expression instanceof UnaryOperatorExpression) { replaceSuffixes(((UnaryOperatorExpression) expression) .getExpression()); } else { Assert.isTrue(expression instanceof FunctionInvocation || expression instanceof Literal || expression instanceof NamedValue); } } /** * Replaces all <code>ValueSuffix</code>es with custom implementation * ValueSuffexes that use JSF <code>PropertyResolver</code> insted of JSP * EL one. * * @param expressionString * <code>ExpressionString</code> instance */ private void replaceSuffixes(final ExpressionString expressionString) { Object[] expressions = expressionString.getElements(); for (int i = 0; i < expressions.length; i++) { Object expression = expressions[i]; if (expression instanceof Expression) { replaceSuffixes((Expression) expression); } else if (expression instanceof ExpressionString) { replaceSuffixes((ExpressionString) expression); } else { Assert.isTrue(expression instanceof String); } } } /** * Replaces all <code>ValueSuffix</code>es with custom implementation * ValueSuffexes that use JSF <code>PropertyResolver</code> insted of JSP * EL one. * * @param complexValue * <code>ComplexValue</code> instance */ private void replaceSuffixes(final ComplexValue complexValue) { List suffixes = complexValue.getSuffixes(); for (int i = 0; i < suffixes.size(); i++) { final ValueSuffix suffix = (ValueSuffix) suffixes.get(i); if (suffix instanceof PropertySuffix) { suffixes.set(i, new PropertyResolverBasedPropertySuffix( (PropertySuffix) suffix)); } else if (suffix instanceof ArraySuffix) { suffixes.set(i, new PropertyResolverBasedArraySuffix( (ArraySuffix) suffix)); } else { throw new IllegalStateException("Unknown suffix class: " + suffix.getClass().getName()); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -