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 2009/12/30 23:20:31 UTC

svn commit: r894720 - in /tomcat/trunk/java: javax/el/ org/apache/jasper/compiler/ org/apache/jasper/runtime/

Author: markt
Date: Wed Dec 30 22:20:30 2009
New Revision: 894720

URL: http://svn.apache.org/viewvc?rev=894720&view=rev
Log:
Implement ExpressionFactory.newInstance() and ensure that Jasper does not refer to org.apache.el directly
JSP 2.1 TCK passes with these changes applied

Modified:
    tomcat/trunk/java/javax/el/ExpressionFactory.java
    tomcat/trunk/java/org/apache/jasper/compiler/JspUtil.java
    tomcat/trunk/java/org/apache/jasper/compiler/PageInfo.java
    tomcat/trunk/java/org/apache/jasper/compiler/Validator.java
    tomcat/trunk/java/org/apache/jasper/runtime/JspApplicationContextImpl.java

Modified: tomcat/trunk/java/javax/el/ExpressionFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/el/ExpressionFactory.java?rev=894720&r1=894719&r2=894720&view=diff
==============================================================================
--- tomcat/trunk/java/javax/el/ExpressionFactory.java (original)
+++ tomcat/trunk/java/javax/el/ExpressionFactory.java Wed Dec 30 22:20:30 2009
@@ -17,6 +17,16 @@
 
 package javax.el;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.Properties;
 
 /**
@@ -25,6 +35,15 @@
  */
 public abstract class ExpressionFactory {
 
+    private static final String SERVICE_RESOURCE_NAME =
+        "META-INF/services/javax.el.ExpressionFactory";
+
+    private static final String SEP = System.getProperty("file.separator");
+    private static final String PROPERTY_FILE =
+        System.getProperty("java.home") + "jre" + SEP + "lib" + SEP +
+        "el.properties";
+    private static final String PROPERTY_NAME = "javax.el.ExpressionFactory";
+
     public abstract Object coerceToType(Object obj, Class<?> expectedType)
             throws ELException;
 
@@ -39,13 +58,172 @@
             String expression, Class<?> expectedReturnType,
             Class<?>[] expectedParamTypes) throws ELException,
             NullPointerException;
-    
+
+    /**
+     * Create a new {@link ExpressionFactory}. The class to use is determined by
+     * the following search order:
+     * <ol>
+     * <li>services API (META-INF/services/javax.el.ExpressionFactory)</li>
+     * <li>$JRE_HOME/lib/el.properties - key javax.el.ExpressionFactory</li>
+     * <li>javax.el.ExpressionFactory</li>
+     * <li>Platform default implementation -
+     *     org.apache.el.ExpressionFactoryImpl</li>
+     * </ol>
+     * @return
+     */
     public static ExpressionFactory newInstance() {
         return newInstance(null);
     }
 
+    /**
+     * Create a new {@link ExpressionFactory} passing in the provided
+     * {@link Properties}. Search order is the same as {@link #newInstance()}.
+     * 
+     * @param properties
+     * @return
+     */
     public static ExpressionFactory newInstance(Properties properties) {
-        // TODO
+        String className = null;
+        ExpressionFactory result = null;
+        
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+
+        // First services API
+        className = getClassNameServices(tccl);
+        if (className == null) {
+            // Second el.properties file
+            className = getClassNameJreDir();
+        }
+        if (className == null) {
+            // Third system property 
+            className = getClassNameSysProp();
+        }
+        if (className == null) {
+            // Fourth - default
+            className = "org.apache.el.ExpressionFactoryImpl";
+        }
+        
+        try {
+            Class<?> clazz = null;
+            if (tccl == null) {
+                clazz = Class.forName(className);
+            } else {
+                clazz = tccl.loadClass(className);
+            }
+            Constructor<?> constructor = null;
+            // Do we need to look for a constructor that will take properties?
+            if (properties != null) {
+                try {
+                    constructor = clazz.getConstructor(Properties.class);
+                } catch (SecurityException se) {
+                    throw new ELException(se);
+                } catch (NoSuchMethodException nsme) {
+                    // This can be ignored
+                    // This is OK for this constructor not to exist
+                }
+            }
+            if (constructor == null) {
+                result = (ExpressionFactory) clazz.newInstance();
+            } else {
+                result =
+                    (ExpressionFactory) constructor.newInstance(properties);
+            }
+            
+        } catch (ClassNotFoundException e) {
+            throw new ELException(
+                    "Unable to find ExpressionFactory of type: " + className,
+                    e);
+        } catch (InstantiationException e) {
+            throw new ELException(
+                    "Unable to create ExpressionFactory of type: " + className,
+                    e);
+        } catch (IllegalAccessException e) {
+            throw new ELException(
+                    "Unable to create ExpressionFactory of type: " + className,
+                    e);
+        } catch (IllegalArgumentException e) {
+            throw new ELException(
+                    "Unable to create ExpressionFactory of type: " + className,
+                    e);
+        } catch (InvocationTargetException e) {
+            throw new ELException(
+                    "Unable to create ExpressionFactory of type: " + className,
+                    e);
+        }
+        
+        return result;
+    }
+    
+    private static String getClassNameServices(ClassLoader tccl) {
+        InputStream is = null;
+        
+        if (tccl == null) {
+            is = ClassLoader.getSystemResourceAsStream(SERVICE_RESOURCE_NAME);
+        } else {
+            is = tccl.getResourceAsStream(SERVICE_RESOURCE_NAME);
+        }
+
+        if (is != null) {
+            String line = null;
+            try {
+                BufferedReader br =
+                    new BufferedReader(new InputStreamReader(is, "UTF-8"));
+                line = br.readLine();
+                if (line != null && line.trim().length() > 0) {
+                    return line.trim();
+                }
+            } catch (UnsupportedEncodingException e) {
+                // Should never happen with UTF-8
+                // If it does - ignore & return null
+            } catch (IOException e) {
+                throw new ELException("Failed to read " + SERVICE_RESOURCE_NAME,
+                        e);
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException ioe) {
+                    // Ignore
+                }
+            }
+        }
+        
+        return null;
+    }
+    
+    private static String getClassNameJreDir() {
+        File file = new File(PROPERTY_FILE);
+        if (file.canRead()) {
+            InputStream is = null;
+            try {
+                is = new FileInputStream(file);
+                Properties props = new Properties();
+                props.load(is);
+                String value = props.getProperty(PROPERTY_NAME);
+                if (value != null && value.trim().length() > 0) {
+                    return value.trim();
+                }
+            } catch (FileNotFoundException e) {
+                // Should not happen - ignore it if it does
+            } catch (IOException e) {
+                throw new ELException("Failed to read " + PROPERTY_FILE, e);
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    
+    private static final String getClassNameSysProp() {
+        String value = System.getProperty(PROPERTY_NAME);
+        if (value != null && value.trim().length() > 0) {
+            return value.trim();
+        }
         return null;
     }
 }

Modified: tomcat/trunk/java/org/apache/jasper/compiler/JspUtil.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/JspUtil.java?rev=894720&r1=894719&r2=894720&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/JspUtil.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/JspUtil.java Wed Dec 30 22:20:30 2009
@@ -49,9 +49,6 @@
     private static final String OPEN_EXPR = "<%=";
     private static final String CLOSE_EXPR = "%>";
 
-    // private static ExpressionEvaluatorImpl expressionEvaluator
-    // = new ExpressionEvaluatorImpl();
-
     private static final String javaKeywords[] = { "abstract", "assert",
             "boolean", "break", "byte", "case", "catch", "char", "class",
             "const", "continue", "default", "do", "double", "else", "enum",

Modified: tomcat/trunk/java/org/apache/jasper/compiler/PageInfo.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/PageInfo.java?rev=894720&r1=894719&r2=894720&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/PageInfo.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/PageInfo.java Wed Dec 30 22:20:30 2009
@@ -24,7 +24,6 @@
 import java.util.Set;
 import java.util.Vector;
 
-import org.apache.el.ExpressionFactoryImpl;
 import org.apache.jasper.Constants;
 import org.apache.jasper.JasperException;
 
@@ -76,7 +75,8 @@
     // JSP 2.1
     private String deferredSyntaxAllowedAsLiteralValue;
     private boolean deferredSyntaxAllowedAsLiteral = false;
-    private ExpressionFactory expressionFactory = new ExpressionFactoryImpl();
+    private ExpressionFactory expressionFactory =
+        ExpressionFactory.newInstance();
     private String trimDirectiveWhitespacesValue;
     private boolean trimDirectiveWhitespaces = false;
     

Modified: tomcat/trunk/java/org/apache/jasper/compiler/Validator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Validator.java?rev=894720&r1=894719&r2=894720&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/compiler/Validator.java (original)
+++ tomcat/trunk/java/org/apache/jasper/compiler/Validator.java Wed Dec 30 22:20:30 2009
@@ -35,7 +35,6 @@
 import javax.servlet.jsp.tagext.TagLibraryInfo;
 import javax.servlet.jsp.tagext.ValidationMessage;
 
-import org.apache.el.lang.ELSupport;
 import org.apache.jasper.JasperException;
 import org.apache.jasper.el.ELContextImpl;
 import org.xml.sax.Attributes;
@@ -502,6 +501,9 @@
                 new JspUtil.ValidAttribute("doctype-public"),
                 new JspUtil.ValidAttribute("doctype-system") };
 
+        private static final ExpressionFactory EXPRESSION_FACTORY =
+            ExpressionFactory.newInstance();
+
         /*
          * Constructor
          */
@@ -1160,7 +1162,7 @@
                                     }
                                     // Check casting
                                     try {
-                                        ELSupport.checkType(attrs.getValue(i), expectedClass);
+                                        EXPRESSION_FACTORY.coerceToType(attrs.getValue(i), expectedClass);
                                     } catch (Exception e) {
                                         err.jspError
                                             (n, "jsp.error.coerce_to_type",

Modified: tomcat/trunk/java/org/apache/jasper/runtime/JspApplicationContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/runtime/JspApplicationContextImpl.java?rev=894720&r1=894719&r2=894720&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/runtime/JspApplicationContextImpl.java (original)
+++ tomcat/trunk/java/org/apache/jasper/runtime/JspApplicationContextImpl.java Wed Dec 30 22:20:30 2009
@@ -38,7 +38,6 @@
 import javax.servlet.jsp.el.ImplicitObjectELResolver;
 import javax.servlet.jsp.el.ScopedAttributeELResolver;
 
-import org.apache.el.ExpressionFactoryImpl;
 import org.apache.jasper.Constants;
 import org.apache.jasper.el.ELContextImpl;
 
@@ -51,7 +50,8 @@
 
 	private final static String KEY = JspApplicationContextImpl.class.getName();
 
-	private final static ExpressionFactory expressionFactory = new ExpressionFactoryImpl();
+	private final static ExpressionFactory expressionFactory =
+	    ExpressionFactory.newInstance();
 
 	private final List<ELContextListener> contextListeners = new ArrayList<ELContextListener>();
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org