Author: markt Date: Tue Jul 16 23:01:27 2013 New Revision: 1503937 URL: http://svn.apache.org/r1503937 Log: Implement non-backwards compatible change to the coercion rules.
Modified: tomcat/trunk/java/org/apache/el/lang/ELSupport.java tomcat/trunk/java/org/apache/el/parser/AstAnd.java tomcat/trunk/java/org/apache/el/parser/AstChoice.java tomcat/trunk/java/org/apache/el/parser/AstNot.java tomcat/trunk/java/org/apache/el/parser/AstOr.java tomcat/trunk/java/org/apache/el/parser/AstValue.java tomcat/trunk/java/org/apache/el/stream/Stream.java tomcat/trunk/test/org/apache/el/lang/TestELSupport.java tomcat/trunk/webapps/docs/config/systemprops.xml Modified: tomcat/trunk/java/org/apache/el/lang/ELSupport.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/lang/ELSupport.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/lang/ELSupport.java (original) +++ tomcat/trunk/java/org/apache/el/lang/ELSupport.java Tue Jul 16 23:01:27 2013 @@ -21,6 +21,8 @@ import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; 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; @@ -40,6 +42,32 @@ public class ELSupport { private static final Long ZERO = Long.valueOf(0L); + private static final boolean IS_SECURITY_ENABLED = + (System.getSecurityManager() != null); + + protected static final boolean COERCE_TO_ZERO; + + static { + if (IS_SECURITY_ENABLED) { + COERCE_TO_ZERO = AccessController.doPrivileged( + new PrivilegedAction<Boolean>(){ + @Override + public Boolean run() { + return Boolean.valueOf(System.getProperty( + "org.apache.el.parser.COERCE_TO_ZERO", + "false")); + } + + } + ).booleanValue(); + } else { + COERCE_TO_ZERO = Boolean.valueOf(System.getProperty( + "org.apache.el.parser.COERCE_TO_ZERO", + "false")).booleanValue(); + } + } + + /** * Compare two objects, after coercing to the same type if appropriate. * @@ -147,7 +175,7 @@ public class ELSupport { Long l1 = (Long) coerceToNumber(obj1, Long.class); return l0.equals(l1); } else if (obj0 instanceof Boolean || obj1 instanceof Boolean) { - return coerceToBoolean(obj0).equals(coerceToBoolean(obj1)); + return coerceToBoolean(obj0, false).equals(coerceToBoolean(obj1, false)); } else if (obj0.getClass().isEnum()) { return obj0.equals(coerceToEnum(obj1, obj0.getClass())); } else if (obj1.getClass().isEnum()) { @@ -195,8 +223,15 @@ public class ELSupport { * @return the Boolean value of the object * @throws ELException if object is not Boolean or String */ - public static final Boolean coerceToBoolean(final Object obj) - throws ELException { + public static final Boolean coerceToBoolean(final Object obj, + boolean primitive) throws ELException { + + if (!COERCE_TO_ZERO && !primitive) { + if (obj == null) { + return null; + } + } + if (obj == null || "".equals(obj)) { return Boolean.FALSE; } @@ -211,7 +246,7 @@ public class ELSupport { obj, obj.getClass(), Boolean.class)); } - public static final Character coerceToCharacter(final Object obj) + private static final Character coerceToCharacter(final Object obj) throws ELException { if (obj == null || "".equals(obj)) { return Character.valueOf((char) 0); @@ -279,6 +314,13 @@ public class ELSupport { public static final Number coerceToNumber(final Object obj, final Class<?> type) throws ELException { + + if (!COERCE_TO_ZERO) { + if (obj == null && !type.isPrimitive()) { + return null; + } + } + if (obj == null || "".equals(obj)) { return coerceToNumber(ZERO, type); } @@ -388,10 +430,19 @@ public class ELSupport { public static final Object coerceToType(final Object obj, final Class<?> type) throws ELException { + 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(obj); } @@ -402,7 +453,7 @@ public class ELSupport { return coerceToCharacter(obj); } if (Boolean.class.equals(type) || Boolean.TYPE == type) { - return coerceToBoolean(obj); + return coerceToBoolean(obj, Boolean.TYPE == type); } if (type.isEnum()) { return coerceToEnum(obj, type); Modified: tomcat/trunk/java/org/apache/el/parser/AstAnd.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstAnd.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstAnd.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstAnd.java Tue Jul 16 23:01:27 2013 @@ -36,12 +36,12 @@ public final class AstAnd extends Boolea public Object getValue(EvaluationContext ctx) throws ELException { Object obj = children[0].getValue(ctx); - Boolean b = coerceToBoolean(obj); + Boolean b = coerceToBoolean(obj, true); if (!b.booleanValue()) { return b; } obj = children[1].getValue(ctx); - b = coerceToBoolean(obj); + b = coerceToBoolean(obj, true); return b; } } Modified: tomcat/trunk/java/org/apache/el/parser/AstChoice.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstChoice.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstChoice.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstChoice.java Tue Jul 16 23:01:27 2013 @@ -43,7 +43,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); + Boolean b0 = coerceToBoolean(obj0, true); return this.children[((b0.booleanValue() ? 1 : 2))].getValue(ctx); } } Modified: tomcat/trunk/java/org/apache/el/parser/AstNot.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstNot.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstNot.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstNot.java Tue Jul 16 23:01:27 2013 @@ -42,7 +42,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); + Boolean b = coerceToBoolean(obj, true); return Boolean.valueOf(!b.booleanValue()); } } Modified: tomcat/trunk/java/org/apache/el/parser/AstOr.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstOr.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstOr.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstOr.java Tue Jul 16 23:01:27 2013 @@ -36,12 +36,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); + Boolean b = coerceToBoolean(obj, true); if (b.booleanValue()) { return b; } obj = this.children[1].getValue(ctx); - b = coerceToBoolean(obj); + b = coerceToBoolean(obj, true); return b; } } Modified: tomcat/trunk/java/org/apache/el/parser/AstValue.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstValue.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstValue.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstValue.java Tue Jul 16 23:01:27 2013 @@ -21,8 +21,6 @@ package org.apache.el.parser; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import javax.el.ELException; import javax.el.ELResolver; @@ -42,31 +40,6 @@ import org.apache.el.util.ReflectionUtil */ public final class AstValue extends SimpleNode { - private static final boolean IS_SECURITY_ENABLED = - (System.getSecurityManager() != null); - - protected static final boolean COERCE_TO_ZERO; - - static { - if (IS_SECURITY_ENABLED) { - COERCE_TO_ZERO = AccessController.doPrivileged( - new PrivilegedAction<Boolean>(){ - @Override - public Boolean run() { - return Boolean.valueOf(System.getProperty( - "org.apache.el.parser.COERCE_TO_ZERO", - "true")); - } - - } - ).booleanValue(); - } else { - COERCE_TO_ZERO = Boolean.valueOf(System.getProperty( - "org.apache.el.parser.COERCE_TO_ZERO", - "true")).booleanValue(); - } - } - protected static class Target { protected Object base; @@ -213,8 +186,7 @@ public final class AstValue extends Simp // coerce to the expected type Class<?> targetClass = resolver.getType(ctx, t.base, t.property); - if (COERCE_TO_ZERO == true - || !isAssignable(value, targetClass)) { + if (!isAssignable(value, targetClass)) { resolver.setValue(ctx, t.base, t.property, ELSupport.coerceToType(value, targetClass)); } else { Modified: tomcat/trunk/java/org/apache/el/stream/Stream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/stream/Stream.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/stream/Stream.java (original) +++ tomcat/trunk/java/org/apache/el/stream/Stream.java Tue Jul 16 23:01:27 2013 @@ -47,8 +47,8 @@ public class Stream { protected void findNext() { while (iterator.hasNext()) { Object obj = iterator.next(); - Boolean filter = ELSupport.coerceToBoolean(le.invoke(obj)); - if (filter != null && filter.booleanValue()) { + if (ELSupport.coerceToBoolean(le.invoke(obj), + true).booleanValue()) { next = obj; foundNext = true; break; Modified: tomcat/trunk/test/org/apache/el/lang/TestELSupport.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/lang/TestELSupport.java?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/lang/TestELSupport.java (original) +++ tomcat/trunk/test/org/apache/el/lang/TestELSupport.java Tue Jul 16 23:01:27 2013 @@ -20,11 +20,13 @@ import java.math.BigDecimal; import java.math.BigInteger; import javax.el.ELException; +import javax.el.ELManager; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import org.junit.Assert; import org.junit.Test; public class TestELSupport { @@ -85,7 +87,7 @@ public class TestELSupport { @Test public void testCoerceNullToNumber() { Object output = ELSupport.coerceToType(null, Number.class); - assertEquals(Long.valueOf(0), output); + assertNull(output); } @Test @@ -120,6 +122,116 @@ public class TestELSupport { assertNull(output); } + @Test + public void testCoerceToType01() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, Integer.class); + Assert.assertNull("Result: " + result, result); + } + + @Test + public void testCoerceToType02() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, int.class); + Assert.assertEquals(Integer.valueOf(0), result); + } + + @Test + public void testCoerceToType03() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, boolean.class); + Assert.assertEquals(Boolean.valueOf(null), result); + } + + @Test + public void testCoerceToType04() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, String.class); + Assert.assertEquals("", result); + } + + @Test + public void testCoerceToType05() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, Character.class); + Assert.assertNull("Result: " + result, result); + } + + @Test + public void testCoerceToType06() { + Object result = ELManager.getExpressionFactory().coerceToType( + "", Character.class); + Assert.assertEquals(Character.valueOf((char) 0), result); + } + + @Test + public void testCoerceToType07() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, char.class); + Assert.assertEquals(Character.valueOf((char) 0), result); + } + + @Test + public void testCoerceToType08() { + Object result = ELManager.getExpressionFactory().coerceToType( + "", char.class); + Assert.assertEquals(Character.valueOf((char) 0), result); + } + + @Test + public void testCoerceToType09() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, Boolean.class); + Assert.assertNull("Result: " + result, result); + } + + @Test + public void testCoerceToType10() { + Object result = ELManager.getExpressionFactory().coerceToType( + "", Boolean.class); + Assert.assertEquals(Boolean.FALSE, result); + } + + @Test + public void testCoerceToType11() { + Object result = ELManager.getExpressionFactory().coerceToType( + null, boolean.class); + Assert.assertEquals(Boolean.FALSE, result); + } + + @Test + public void testCoerceToType12() { + Object result = ELManager.getExpressionFactory().coerceToType( + "", boolean.class); + Assert.assertEquals(Boolean.FALSE, result); + } + + @Test + public void testCoerceToNumber01() { + Object result = ELSupport.coerceToNumber( + (Object) null, Integer.class); + Assert.assertNull("Resut: " + result, result); + } + + @Test + public void testCoerceToNumber02() { + Object result = ELSupport.coerceToNumber( + (Object) null, int.class); + Assert.assertEquals(Integer.valueOf(0), result); + } + + @Test + public void testCoerceToBoolean01() { + Object result = ELSupport.coerceToBoolean(null, true); + Assert.assertEquals(Boolean.FALSE, result); + } + + @Test + public void testCoerceToBoolean02() { + Object result = ELSupport.coerceToBoolean(null, false); + Assert.assertNull("Resut: " + result, result); + } + private static void testIsSame(Object value) { assertEquals(value, ELSupport.coerceToNumber(value, value.getClass())); } Modified: tomcat/trunk/webapps/docs/config/systemprops.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/systemprops.xml?rev=1503937&r1=1503936&r2=1503937&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/systemprops.xml (original) +++ tomcat/trunk/webapps/docs/config/systemprops.xml Tue Jul 16 23:01:27 2013 @@ -79,10 +79,14 @@ </property> <property name="org.apache.el.parser. COERCE_TO_ZERO"> - <p>If <code>true</code>, when coercing expressions to numbers - <code>""</code> and <code>null</code> will be coerced to zero as required - by the specification.</p> - <p>If not specified, the default value of <code>true</code> will be used.</p> + <p>If <code>true</code>, when coercing <code>null</code>s to objects of + type Number, Character or Boolean the result will be <code>0</code> for + Number and Character types and <code>false</code> for Boolean as required + by the EL 2.2 and earlier specifications. If this property is + <code>false</code> the result of the coercion will be <code>null</code> as + required by the EL 3.0 specification.</p> + <p>If not specified, the default value of <code>false</code> will be + used.</p> </property> <property name="org.apache.el.parser. SKIP_IDENTIFIER_CHECK"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org