Author: markt Date: Fri Dec 5 17:39:06 2014 New Revision: 1643367 URL: http://svn.apache.org/r1643367 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=57309 Ensure that the current EL Resolver is given an opportunity to perform type coercion before applying the default EL coercion rules.
Modified: tomcat/tc8.0.x/trunk/ (props changed) tomcat/tc8.0.x/trunk/java/org/apache/el/ExpressionFactoryImpl.java tomcat/tc8.0.x/trunk/java/org/apache/el/lang/ELSupport.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstAnd.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstChoice.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstCompositeExpression.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstConcatenation.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstEqual.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstFunction.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThan.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThanEqual.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThan.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThanEqual.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNegative.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNot.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNotEqual.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstOr.java tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstValue.java tomcat/tc8.0.x/trunk/java/org/apache/el/stream/Stream.java tomcat/tc8.0.x/trunk/java/org/apache/el/util/ReflectionUtil.java tomcat/tc8.0.x/trunk/test/org/apache/el/TestELEvaluation.java tomcat/tc8.0.x/trunk/test/org/apache/el/lang/TestELSupport.java tomcat/tc8.0.x/trunk/test/org/apache/el/stream/TestCollectionOperations.java tomcat/tc8.0.x/trunk/test/org/apache/el/util/TestReflectionUtil.java tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc8.0.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Dec 5 17:39:06 2014 @@ -1 +1 @@ -/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642668,1642679,1642697,1642699,1643002,1643066,1643121,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323 +/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642668,1642679,1642697,1642699,1643002,1643066,1643121,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366 Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/ExpressionFactoryImpl.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/ExpressionFactoryImpl.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/ExpressionFactoryImpl.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/ExpressionFactoryImpl.java Fri Dec 5 17:39:06 2014 @@ -44,7 +44,7 @@ public class ExpressionFactoryImpl exten @Override public Object coerceToType(Object obj, Class<?> type) { - return ELSupport.coerceToType(obj, type); + return ELSupport.coerceToType(null, obj, type); } @Override Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/lang/ELSupport.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/lang/ELSupport.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/lang/ELSupport.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/lang/ELSupport.java Fri Dec 5 17:39:06 2014 @@ -28,8 +28,8 @@ 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; @@ -72,7 +72,7 @@ public class ELSupport { * Compare two objects, after coercing to the same type if appropriate. * * If the objects are identical, or they are equal according to - * {@link #equals(Object, Object)} then return 0. + * {@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). @@ -91,39 +91,40 @@ public class ELSupport { * <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 Object obj0, final Object obj1) + public static final int compare(final ELContext ctx, final Object obj0, final Object obj1) throws ELException { - if (obj0 == obj1 || equals(obj0, obj1)) { + if (obj0 == obj1 || equals(ctx, obj0, obj1)) { return 0; } if (isBigDecimalOp(obj0, obj1)) { - BigDecimal bd0 = (BigDecimal) coerceToNumber(obj0, BigDecimal.class); - BigDecimal bd1 = (BigDecimal) coerceToNumber(obj1, BigDecimal.class); + 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(obj0, Double.class); - Double d1 = (Double) coerceToNumber(obj1, Double.class); + 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(obj0, BigInteger.class); - BigInteger bi1 = (BigInteger) coerceToNumber(obj1, BigInteger.class); + 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(obj0, Long.class); - Long l1 = (Long) coerceToNumber(obj1, Long.class); + 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(obj0).compareTo(coerceToString(obj1)); + return coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1)); } if (obj0 instanceof Comparable<?>) { @SuppressWarnings("unchecked") // checked above @@ -147,41 +148,42 @@ public class ELSupport { * 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 Object obj0, final Object obj1) + 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(obj0, BigDecimal.class); - BigDecimal bd1 = (BigDecimal) coerceToNumber(obj1, BigDecimal.class); + 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(obj0, Double.class); - Double d1 = (Double) coerceToNumber(obj1, Double.class); + 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(obj0, BigInteger.class); - BigInteger bi1 = (BigInteger) coerceToNumber(obj1, BigInteger.class); + 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(obj0, Long.class); - Long l1 = (Long) coerceToNumber(obj1, Long.class); + 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(obj0, false).equals(coerceToBoolean(obj1, false)); + return coerceToBoolean(ctx, obj0, false).equals(coerceToBoolean(ctx, obj1, false)); } else if (obj0.getClass().isEnum()) { - return obj0.equals(coerceToEnum(obj1, obj0.getClass())); + return obj0.equals(coerceToEnum(ctx, obj1, obj0.getClass())); } else if (obj1.getClass().isEnum()) { - return obj1.equals(coerceToEnum(obj0, obj1.getClass())); + return obj1.equals(coerceToEnum(ctx, obj0, obj1.getClass())); } else if (obj0 instanceof String || obj1 instanceof String) { - int lexCompare = coerceToString(obj0).compareTo(coerceToString(obj1)); + int lexCompare = coerceToString(ctx, obj0).compareTo(coerceToString(ctx, obj1)); return (lexCompare == 0) ? true : false; } else { return obj0.equals(obj1); @@ -192,8 +194,21 @@ public class ELSupport { // 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 Object obj, + 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; } @@ -219,15 +234,28 @@ public class ELSupport { /** * 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 Object obj, + 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; @@ -248,8 +276,21 @@ public class ELSupport { obj, obj.getClass(), Boolean.class)); } - private static final Character coerceToCharacter(final Object obj) + 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); } @@ -314,9 +355,21 @@ public class ELSupport { number, number.getClass(), type)); } - public static final Number coerceToNumber(final Object obj, + 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; @@ -415,10 +468,24 @@ public class ELSupport { /** * 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 Object obj) { + 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) { @@ -430,9 +497,21 @@ public class ELSupport { } } - public static final Object coerceToType(final Object obj, + 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; @@ -446,19 +525,19 @@ public class ELSupport { } if (String.class.equals(type)) { - return coerceToString(obj); + return coerceToString(ctx, obj); } if (ELArithmetic.isNumberType(type)) { - return coerceToNumber(obj, type); + return coerceToNumber(ctx, obj, type); } if (Character.class.equals(type) || Character.TYPE == type) { - return coerceToCharacter(obj); + return coerceToCharacter(ctx, obj); } if (Boolean.class.equals(type) || Boolean.TYPE == type) { - return coerceToBoolean(obj, Boolean.TYPE == type); + return coerceToBoolean(ctx, obj, Boolean.TYPE == type); } if (type.isEnum()) { - return coerceToEnum(obj, type); + return coerceToEnum(ctx, obj, type); } // new to spec @@ -495,14 +574,14 @@ public class ELSupport { // Handle arrays if (type.isArray() && obj.getClass().isArray()) { - return coerceToArray(obj, type); + return coerceToArray(ctx, obj, type); } throw new ELException(MessageFactory.get("error.convert", obj, obj.getClass(), type)); } - private static Object coerceToArray(final Object obj, + private static Object coerceToArray(final ELContext ctx, final Object obj, final Class<?> type) { // Note: Nested arrays will result in nested calls to this method. @@ -517,7 +596,7 @@ public class ELSupport { Object result = Array.newInstance(componentType, size); // Coerce each element in turn. for (int i = 0; i < size; i++) { - Array.set(result, i, coerceToType(Array.get(obj, i), componentType)); + Array.set(result, i, coerceToType(ctx, Array.get(obj, i), componentType)); } return result; Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstAnd.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstAnd.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstAnd.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstAnd.java Fri Dec 5 17:39:06 2014 @@ -35,12 +35,12 @@ public final class AstAnd extends Boolea public Object getValue(EvaluationContext ctx) throws ELException { Object obj = children[0].getValue(ctx); - Boolean b = coerceToBoolean(obj, true); + Boolean b = coerceToBoolean(ctx, obj, true); if (!b.booleanValue()) { return b; } obj = children[1].getValue(ctx); - b = coerceToBoolean(obj, true); + b = coerceToBoolean(ctx, obj, true); return b; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstChoice.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstChoice.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstChoice.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstChoice.java Fri Dec 5 17:39:06 2014 @@ -42,7 +42,7 @@ public final class AstChoice extends Sim public Object getValue(EvaluationContext ctx) throws ELException { Object obj0 = this.children[0].getValue(ctx); - Boolean b0 = coerceToBoolean(obj0, true); + Boolean b0 = coerceToBoolean(ctx, obj0, true); return this.children[((b0.booleanValue() ? 1 : 2))].getValue(ctx); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstCompositeExpression.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstCompositeExpression.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstCompositeExpression.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstCompositeExpression.java Fri Dec 5 17:39:06 2014 @@ -48,7 +48,7 @@ public final class AstCompositeExpressio for (int i = 0; i < this.children.length; i++) { obj = this.children[i].getValue(ctx); if (obj != null) { - sb.append(ELSupport.coerceToString(obj)); + sb.append(ELSupport.coerceToString(ctx, obj)); } } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstConcatenation.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstConcatenation.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstConcatenation.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstConcatenation.java Fri Dec 5 17:39:06 2014 @@ -31,8 +31,8 @@ public class AstConcatenation extends Si @Override public Object getValue(EvaluationContext ctx) throws ELException { // Coerce the two child nodes to string and then concatenate - String s1 = coerceToString(children[0].getValue(ctx)); - String s2 = coerceToString(children[1].getValue(ctx)); + String s1 = coerceToString(ctx, children[0].getValue(ctx)); + String s2 = coerceToString(ctx, children[1].getValue(ctx)); return s1 + s2; } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstEqual.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstEqual.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstEqual.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstEqual.java Fri Dec 5 17:39:06 2014 @@ -36,6 +36,6 @@ public final class AstEqual extends Bool throws ELException { Object obj0 = this.children[0].getValue(ctx); Object obj1 = this.children[1].getValue(ctx); - return Boolean.valueOf(equals(obj0, obj1)); + return Boolean.valueOf(equals(ctx, obj0, obj1)); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstFunction.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstFunction.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstFunction.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstFunction.java Fri Dec 5 17:39:06 2014 @@ -176,12 +176,12 @@ public final class AstFunction extends S Class<?> target = paramTypes[i].getComponentType(); for (int j = i; j < inputParameterCount; j++) { varargs[j-i] = parameters.jjtGetChild(j).getValue(ctx); - varargs[j-i] = coerceToType(varargs[j-i], target); + varargs[j-i] = coerceToType(ctx, varargs[j-i], target); } } } else { params[i] = parameters.jjtGetChild(i).getValue(ctx); - params[i] = coerceToType(params[i], paramTypes[i]); + params[i] = coerceToType(ctx, params[i], paramTypes[i]); } } } catch (ELException ele) { Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThan.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThan.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThan.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThan.java Fri Dec 5 17:39:06 2014 @@ -42,6 +42,6 @@ public final class AstGreaterThan extend if (obj1 == null) { return Boolean.FALSE; } - return (compare(obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE; + return (compare(ctx, obj0, obj1) > 0) ? Boolean.TRUE : Boolean.FALSE; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThanEqual.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThanEqual.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThanEqual.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstGreaterThanEqual.java Fri Dec 5 17:39:06 2014 @@ -42,6 +42,6 @@ public final class AstGreaterThanEqual e if (obj0 == null || obj1 == null) { return Boolean.FALSE; } - return (compare(obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE; + return (compare(ctx, obj0, obj1) >= 0) ? Boolean.TRUE : Boolean.FALSE; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThan.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThan.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThan.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThan.java Fri Dec 5 17:39:06 2014 @@ -42,6 +42,6 @@ public final class AstLessThan extends B if (obj1 == null) { return Boolean.FALSE; } - return (compare(obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE; + return (compare(ctx, obj0, obj1) < 0) ? Boolean.TRUE : Boolean.FALSE; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThanEqual.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThanEqual.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThanEqual.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstLessThanEqual.java Fri Dec 5 17:39:06 2014 @@ -42,6 +42,6 @@ public final class AstLessThanEqual exte if (obj0 == null || obj1 == null) { return Boolean.FALSE; } - return (compare(obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE; + return (compare(ctx, obj0, obj1) <= 0) ? Boolean.TRUE : Boolean.FALSE; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNegative.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNegative.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNegative.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNegative.java Fri Dec 5 17:39:06 2014 @@ -78,7 +78,7 @@ public final class AstNegative extends S if (obj instanceof Byte) { return Byte.valueOf((byte) -((Byte) obj).byteValue()); } - Long num = (Long) coerceToNumber(obj, Long.class); + Long num = (Long) coerceToNumber(ctx, obj, Long.class); return Long.valueOf(-num.longValue()); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNot.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNot.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNot.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNot.java Fri Dec 5 17:39:06 2014 @@ -41,7 +41,7 @@ public final class AstNot extends Simple public Object getValue(EvaluationContext ctx) throws ELException { Object obj = this.children[0].getValue(ctx); - Boolean b = coerceToBoolean(obj, true); + Boolean b = coerceToBoolean(ctx, obj, true); return Boolean.valueOf(!b.booleanValue()); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNotEqual.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNotEqual.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNotEqual.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstNotEqual.java Fri Dec 5 17:39:06 2014 @@ -36,6 +36,6 @@ public final class AstNotEqual extends B throws ELException { Object obj0 = this.children[0].getValue(ctx); Object obj1 = this.children[1].getValue(ctx); - return Boolean.valueOf(!equals(obj0, obj1)); + return Boolean.valueOf(!equals(ctx, obj0, obj1)); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstOr.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstOr.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstOr.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstOr.java Fri Dec 5 17:39:06 2014 @@ -35,12 +35,12 @@ public final class AstOr extends Boolean public Object getValue(EvaluationContext ctx) throws ELException { Object obj = this.children[0].getValue(ctx); - Boolean b = coerceToBoolean(obj, true); + Boolean b = coerceToBoolean(ctx, obj, true); if (b.booleanValue()) { return b; } obj = this.children[1].getValue(ctx); - b = coerceToBoolean(obj, true); + b = coerceToBoolean(ctx, obj, true); return b; } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstValue.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstValue.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstValue.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/parser/AstValue.java Fri Dec 5 17:39:06 2014 @@ -198,7 +198,7 @@ public final class AstValue extends Simp // coerce to the expected type Class<?> targetClass = resolver.getType(ctx, t.base, t.property); resolver.setValue(ctx, t.base, t.property, - ELSupport.coerceToType(value, targetClass)); + ELSupport.coerceToType(ctx, value, targetClass)); if (!ctx.isPropertyResolved()) { throw new PropertyNotFoundException(MessageFactory.get( "error.resolver.unhandled", t.base, t.property)); @@ -212,7 +212,7 @@ public final class AstValue extends Simp throws ELException { Target t = getTarget(ctx); Method m = ReflectionUtil.getMethod( - t.base, t.property, paramTypes, null); + ctx, t.base, t.property, paramTypes, null); return new MethodInfo(m.getName(), m.getReturnType(), m .getParameterTypes()); } @@ -235,10 +235,10 @@ public final class AstValue extends Simp values = paramValues; types = paramTypes; } - m = ReflectionUtil.getMethod(t.base, t.property, types, values); + m = ReflectionUtil.getMethod(ctx, t.base, t.property, types, values); // Handle varArgs and any co-ercion required - values = convertArgs(values, m); + values = convertArgs(ctx, values, m); Object result = null; try { @@ -260,7 +260,7 @@ public final class AstValue extends Simp return result; } - private Object[] convertArgs(Object[] src, Method m) { + private Object[] convertArgs(EvaluationContext ctx, Object[] src, Method m) { Class<?>[] types = m.getParameterTypes(); if (types.length == 0) { return new Object[0]; @@ -271,7 +271,7 @@ public final class AstValue extends Simp Object[] dest = new Object[paramCount]; for (int i = 0; i < paramCount - 1; i++) { - dest[i] = ELSupport.coerceToType(src[i], types[i]); + dest[i] = ELSupport.coerceToType(ctx, src[i], types[i]); } if (m.isVarArgs()) { @@ -279,13 +279,13 @@ public final class AstValue extends Simp m.getParameterTypes()[paramCount - 1].getComponentType(), src.length - (paramCount - 1)); for (int i = 0; i < src.length - (paramCount - 1); i ++) { - varArgs[i] = ELSupport.coerceToType(src[paramCount - 1 + i], + varArgs[i] = ELSupport.coerceToType(ctx, src[paramCount - 1 + i], types[paramCount - 1].getComponentType()); } dest[paramCount - 1] = varArgs; } else { dest[paramCount - 1] = ELSupport.coerceToType( - src[paramCount - 1], types[paramCount - 1]); + ctx, src[paramCount - 1], types[paramCount - 1]); } return dest; Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/stream/Stream.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/stream/Stream.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/stream/Stream.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/stream/Stream.java Fri Dec 5 17:39:06 2014 @@ -48,7 +48,7 @@ public class Stream { protected void findNext() { while (iterator.hasNext()) { Object obj = iterator.next(); - if (ELSupport.coerceToBoolean(le.invoke(obj), + if (ELSupport.coerceToBoolean(null, le.invoke(obj), true).booleanValue()) { next = obj; foundNext = true; @@ -450,10 +450,10 @@ public class Stream { while (iterator.hasNext()) { Object obj = iterator.next(); - if (isMax && ELSupport.coerceToNumber(le.invoke(obj, result), + if (isMax && ELSupport.coerceToNumber(null, le.invoke(obj, result), Integer.class).intValue() > 0) { result = obj; - } else if (!isMax && ELSupport.coerceToNumber(le.invoke(obj, result), + } else if (!isMax && ELSupport.coerceToNumber(null, le.invoke(obj, result), Integer.class).intValue() < 0) { result = obj; } @@ -479,7 +479,7 @@ public class Stream { @Override public int compare(Object o1, Object o2) { return ELSupport.coerceToNumber( - le.invoke(o1, o2), Integer.class).intValue(); + null, le.invoke(o1, o2), Integer.class).intValue(); } } Modified: tomcat/tc8.0.x/trunk/java/org/apache/el/util/ReflectionUtil.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/el/util/ReflectionUtil.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/el/util/ReflectionUtil.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/el/util/ReflectionUtil.java Fri Dec 5 17:39:06 2014 @@ -28,6 +28,7 @@ import javax.el.ELException; import javax.el.MethodNotFoundException; import org.apache.el.lang.ELSupport; +import org.apache.el.lang.EvaluationContext; /** @@ -111,6 +112,7 @@ public class ReflectionUtil { /** * 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 @@ -124,7 +126,7 @@ public class ReflectionUtil { * the code in sync. */ @SuppressWarnings("null") - public static Method getMethod(Object base, Object property, + public static Method getMethod(EvaluationContext ctx, Object base, Object property, Class<?>[] paramTypes, Object[] paramValues) throws MethodNotFoundException { if (base == null || property == null) { @@ -186,7 +188,7 @@ public class ReflectionUtil { noMatch = true; break; } else { - if (isCoercibleFrom(paramValues[j], varType)) { + if (isCoercibleFrom(ctx, paramValues[j], varType)) { coercibleMatch++; } else { noMatch = true; @@ -205,7 +207,7 @@ public class ReflectionUtil { noMatch = true; break; } else { - if (isCoercibleFrom(paramValues[i], mParamTypes[i])) { + if (isCoercibleFrom(ctx, paramValues[i], mParamTypes[i])) { coercibleMatch++; } else { noMatch = true; @@ -381,11 +383,11 @@ public class ReflectionUtil { * This class duplicates code in javax.el.Util. When making changes keep * the code in sync. */ - private static boolean isCoercibleFrom(Object src, Class<?> target) { + 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(src, target); + ELSupport.coerceToType(ctx, src, target); } catch (ELException e) { return false; } Modified: tomcat/tc8.0.x/trunk/test/org/apache/el/TestELEvaluation.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/el/TestELEvaluation.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/el/TestELEvaluation.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/el/TestELEvaluation.java Fri Dec 5 17:39:06 2014 @@ -170,8 +170,8 @@ public class TestELEvaluation { } private void compareBoth(String msg, int expected, Object o1, Object o2){ - int i1 = ELSupport.compare(o1, o2); - int i2 = ELSupport.compare(o2, o1); + int i1 = ELSupport.compare(null, o1, o2); + int i2 = ELSupport.compare(null, o2, o1); assertEquals(msg,expected, i1); assertEquals(msg,expected, -i2); } Modified: tomcat/tc8.0.x/trunk/test/org/apache/el/lang/TestELSupport.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/el/lang/TestELSupport.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/el/lang/TestELSupport.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/el/lang/TestELSupport.java Fri Dec 5 17:39:06 2014 @@ -33,7 +33,7 @@ import org.junit.Test; public class TestELSupport { @Test public void testEquals() { - assertTrue(ELSupport.equals("01", Long.valueOf(1))); + assertTrue(ELSupport.equals(null, "01", Long.valueOf(1))); } @Test @@ -81,13 +81,13 @@ public class TestELSupport { @Test public void testCoerceIntegerToNumber() { Integer input = Integer.valueOf(4390241); - Object output = ELSupport.coerceToType(input, Number.class); + Object output = ELSupport.coerceToType(null, input, Number.class); assertEquals(input, output); } @Test public void testCoerceNullToNumber() { - Object output = ELSupport.coerceToType(null, Number.class); + Object output = ELSupport.coerceToType(null, null, Number.class); assertNull(output); } @@ -95,7 +95,7 @@ public class TestELSupport { public void testCoerceEnumAToEnumA() { Object output = null; try { - output = ELSupport.coerceToEnum(TestEnumA.VALA1, TestEnumA.class); + output = ELSupport.coerceToEnum(null, TestEnumA.VALA1, TestEnumA.class); } finally { assertEquals(TestEnumA.VALA1, output); } @@ -105,7 +105,7 @@ public class TestELSupport { public void testCoerceEnumAToEnumB() { Object output = null; try { - output = ELSupport.coerceToEnum(TestEnumA.VALA1, TestEnumB.class); + output = ELSupport.coerceToEnum(null, TestEnumA.VALA1, TestEnumB.class); } catch (ELException ele) { // Ignore } @@ -116,7 +116,7 @@ public class TestELSupport { public void testCoerceEnumAToEnumC() { Object output = null; try { - output = ELSupport.coerceToEnum(TestEnumA.VALA1, TestEnumC.class); + output = ELSupport.coerceToEnum(null, TestEnumA.VALA1, TestEnumC.class); } catch (ELException ele) { // Ignore } @@ -243,31 +243,31 @@ public class TestELSupport { @Test public void testCoerceToNumber01() { Object result = ELSupport.coerceToNumber( - (Object) null, Integer.class); + null, (Object) null, Integer.class); Assert.assertNull("Resut: " + result, result); } @Test public void testCoerceToNumber02() { Object result = ELSupport.coerceToNumber( - (Object) null, int.class); + null, (Object) null, int.class); Assert.assertEquals(Integer.valueOf(0), result); } @Test public void testCoerceToBoolean01() { - Object result = ELSupport.coerceToBoolean(null, true); + Object result = ELSupport.coerceToBoolean(null, null, true); Assert.assertEquals(Boolean.FALSE, result); } @Test public void testCoerceToBoolean02() { - Object result = ELSupport.coerceToBoolean(null, false); + Object result = ELSupport.coerceToBoolean(null, null, false); Assert.assertNull("Resut: " + result, result); } private static void testIsSame(Object value) { - assertEquals(value, ELSupport.coerceToNumber(value, value.getClass())); + assertEquals(value, ELSupport.coerceToNumber(null, value, value.getClass())); } private static enum TestEnumA { Modified: tomcat/tc8.0.x/trunk/test/org/apache/el/stream/TestCollectionOperations.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/el/stream/TestCollectionOperations.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/el/stream/TestCollectionOperations.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/el/stream/TestCollectionOperations.java Fri Dec 5 17:39:06 2014 @@ -505,7 +505,7 @@ public class TestCollectionOperations { Number average = (Number) ((Optional) result).get(); Assert.assertTrue("Result: " + average.toString(), - ELSupport.equals(Long.valueOf(3), average)); + ELSupport.equals(null, Long.valueOf(3), average)); } @@ -519,7 +519,7 @@ public class TestCollectionOperations { Number average = (Number) ((Optional) result).get(); Assert.assertTrue("Result: " + average.toString(), - ELSupport.equals(Double.valueOf(3.5), average)); + ELSupport.equals(null, Double.valueOf(3.5), average)); } @@ -578,7 +578,7 @@ public class TestCollectionOperations { Object.class); Assert.assertTrue("Result: " + result.toString(), - ELSupport.equals(Long.valueOf(15), result)); + ELSupport.equals(null, Long.valueOf(15), result)); } @@ -591,7 +591,7 @@ public class TestCollectionOperations { Object.class); Assert.assertTrue("Result: " + result.toString(), - ELSupport.equals(Long.valueOf(0), result)); + ELSupport.equals(null, Long.valueOf(0), result)); } @@ -604,7 +604,7 @@ public class TestCollectionOperations { Object.class); Assert.assertTrue("Result: " + result.toString(), - ELSupport.equals(Long.valueOf(5), result)); + ELSupport.equals(null, Long.valueOf(5), result)); } @@ -617,7 +617,7 @@ public class TestCollectionOperations { Object.class); Assert.assertTrue("Result: " + result.toString(), - ELSupport.equals(Long.valueOf(0), result)); + ELSupport.equals(null, Long.valueOf(0), result)); } Modified: tomcat/tc8.0.x/trunk/test/org/apache/el/util/TestReflectionUtil.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/el/util/TestReflectionUtil.java?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/el/util/TestReflectionUtil.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/el/util/TestReflectionUtil.java Fri Dec 5 17:39:06 2014 @@ -30,7 +30,7 @@ public class TestReflectionUtil { */ @Test(expected=MethodNotFoundException.class) public void testBug54370a() { - ReflectionUtil.getMethod(BASE, "testA", + ReflectionUtil.getMethod(null, BASE, "testA", new Class[] {null, String.class}, new Object[] {null, ""}); } @@ -42,21 +42,21 @@ public class TestReflectionUtil { */ @Test(expected=MethodNotFoundException.class) public void testBug54370b() { - ReflectionUtil.getMethod(BASE, "testB", + ReflectionUtil.getMethod(null, BASE, "testB", new Class[] {null, String.class}, new Object[] {null, ""}); } @Test public void testBug54370c() { - ReflectionUtil.getMethod(BASE, "testC", + ReflectionUtil.getMethod(null, BASE, "testC", new Class[] {null}, new Object[] {null}); } @Test public void testBug54370d() { - ReflectionUtil.getMethod(BASE, "testD", + ReflectionUtil.getMethod(null, BASE, "testD", new Class[] {null}, new Object[] {null}); } Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1643367&r1=1643366&r2=1643367&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Fri Dec 5 17:39:06 2014 @@ -140,6 +140,11 @@ <bug>57247</bug>: Correct the default Java source and target versions in the JspC usage message to <code>1.7</code> for Java 7. (markt) </fix> + <fix> + <bug>57309</bug>: Ensure that the current EL Resolver is given an + opportunity to perform type coercion before applying the default EL + coercion rules. (markt) + </fix> </changelog> </subsection> <subsection name="WebSocket"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org