You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/07/17 01:01:28 UTC

svn commit: r1503937 - in /tomcat/trunk: java/org/apache/el/lang/ java/org/apache/el/parser/ java/org/apache/el/stream/ test/org/apache/el/lang/ webapps/docs/config/

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org