View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.webapp;
20  
21  import java.util.logging.Level;
22  import java.util.logging.Logger;
23  
24  import javax.el.ELContext;
25  import javax.el.ExpressionFactory;
26  import javax.el.MethodExpression;
27  import javax.el.ValueExpression;
28  import javax.faces.FacesException;
29  import javax.faces.context.ExternalContext;
30  import javax.servlet.ServletContext;
31  
32  /**
33   * Initializes MyFaces in a JSP 2.0 (or less) environment.
34   * 
35   */
36  public class Jsp20FacesInitializer extends AbstractFacesInitializer
37  {
38      private static final Logger log = Logger.getLogger(Jsp20FacesInitializer.class.getName());
39  
40      /**
41       * The ExpressionFactory implementation of the EL-RI.
42       */
43      private static final String EL_RI_EXPRESSION_FACTORY_IMPL = "com.sun.el.ExpressionFactoryImpl";
44  
45      /**
46       * Jasper's ExpressionFactory implementation.
47       */
48      private static final String JASPER_EL_EXPRESSION_FACTORY_IMPL = "org.apache.el.ExpressionFactoryImpl";
49  
50      /**
51       * All known ExpressionFactory implementations.
52       */
53      private static final String[] KNOWN_EXPRESSION_FACTORIES =
54              new String[] { EL_RI_EXPRESSION_FACTORY_IMPL, JASPER_EL_EXPRESSION_FACTORY_IMPL };
55  
56      @Override
57      protected void initContainerIntegration(ServletContext servletContext, ExternalContext externalContext)
58      {
59          if (log.isLoggable(Level.INFO))
60          {
61              log.info("This application isn't running in a JSP 2.1 container.");
62          }
63  
64          // It's possible to run MyFaces in a JSP 2.0 Container, but the user has to provide
65          // the ExpressionFactory implementation to use as there is no JspApplicationContext
66          // we could ask for. Having said that, though, the user only has to provide it, if
67          // there is no known ExpressionFactory available (i.e. if neither
68          // "com.sun.el.ExpressionFactoryImpl" nor "org.apache.el.ExpressionFactoryImpl"
69          // are available).
70          ExpressionFactory expressionFactory = getUserDefinedExpressionFactory(externalContext);
71  
72          if (expressionFactory == null)
73          {
74              if (log.isLoggable(Level.INFO))
75              {
76                  log.info("Either you haven't specified the ExpressionFactory implementation, or an " 
77                          + "error occured while instantiating the implementation you've specified. "
78                          + "However, attempting to load a known implementation.");
79              }
80  
81              expressionFactory = findExpressionFactory(KNOWN_EXPRESSION_FACTORIES);
82              if (expressionFactory == null)
83              { // if we still haven't got a valid implementation
84                  if (log.isLoggable(Level.SEVERE))
85                  {
86                      log.severe("No valid ExpressionFactory implementation is available "
87                              + "but that's required as this application isn't running in a JSP 2.1 container.");
88                  }
89  
90                  // use a dummy implementation that reports the error again
91                  expressionFactory = new ErrorExpressionFactory();
92              }
93          }
94  
95          if (log.isLoggable(Level.FINE))
96          {
97              log.fine("The following ExpressionFactory implementation will " + "be used: '" + expressionFactory + "'.");
98          }
99  
100         buildConfiguration(servletContext, externalContext, expressionFactory);
101     }
102 
103     /**
104      * Attempts to find a valid ExpressionFactory implementation. Each of the given
105      * "ExpressionFactory implementation candidates" will be tried to instantiate. If an attempt succeeded, the
106      * ExpressionFactory implementation will be returned (i.e. the first valid ExpressionFactory implementation will be
107      * returned) and if no attempt succeeds, <code>null</code> will be returned.
108      * 
109      * @param expressionFactoryClassNames
110      *            "ExpresionFactory implementation candidates"
111      * 
112      * @return the newly created ExpressionFactory implementation, or <code>null</code>, if there is no valid
113      *         implementation
114      */
115     private static ExpressionFactory findExpressionFactory(String[] expressionFactoryClassNames)
116     {
117         for (String expressionFactoryClassName : expressionFactoryClassNames)
118         {
119             ExpressionFactory expressionFactory = loadExpressionFactory(expressionFactoryClassName);
120             if (expressionFactory != null)
121             {
122                 return expressionFactory;
123             }
124         }
125 
126         return null;
127     }
128 
129     /**
130      * Dummy implementation informing the user that there is no valid ExpressionFactory implementation available. This
131      * class makes it easier for the user to understand why the application crashes. Otherwise he would have to deal
132      * with NullPointerExceptions.
133      * 
134      */
135     private class ErrorExpressionFactory extends ExpressionFactory
136     {
137 
138         @Override
139         public Object coerceToType(Object obj, Class<?> targetType)
140         {
141             throw new FacesException("No valid ExpressionFactory implementation is available "
142                     + "but that's required as this application isn't running in a JSP 2.1 container.");
143         }
144 
145         @Override
146         public MethodExpression createMethodExpression(ELContext context, String expression,
147                                                        Class<?> expectedReturnType, Class<?>[] expectedParamTypes)
148         {
149             throw new FacesException("No valid ExpressionFactory implementation is available "
150                     + "but that's required as this application isn't running in a JSP 2.1 container.");
151         }
152 
153         @Override
154         public ValueExpression createValueExpression(Object instance, Class<?> expectedType)
155         {
156             throw new FacesException("No valid ExpressionFactory implementation is available "
157                     + "but that's required as this application isn't running in a JSP 2.1 container.");
158         }
159 
160         @Override
161         public ValueExpression createValueExpression(ELContext context, String expression, Class<?> expectedType)
162         {
163             throw new FacesException("No valid ExpressionFactory implementation is available "
164                     + "but that's required as this application isn't running in a JSP 2.1 container.");
165         }
166 
167     }
168 
169 }