Coverage Report - javax.faces.webapp.FacesServlet
 
Classes in this File Line Coverage Branch Coverage Complexity
FacesServlet
0%
0/124
0%
0/48
0
 
 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 javax.faces.webapp;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.lang.reflect.Method;
 23  
 import java.lang.reflect.InvocationTargetException;
 24  
 import java.util.List;
 25  
 
 26  
 import javax.faces.FactoryFinder;
 27  
 import javax.faces.FacesException;
 28  
 import javax.faces.context.FacesContext;
 29  
 import javax.faces.context.FacesContextFactory;
 30  
 import javax.faces.lifecycle.Lifecycle;
 31  
 import javax.faces.lifecycle.LifecycleFactory;
 32  
 import javax.servlet.Servlet;
 33  
 import javax.servlet.ServletConfig;
 34  
 import javax.servlet.ServletException;
 35  
 import javax.servlet.ServletRequest;
 36  
 import javax.servlet.ServletResponse;
 37  
 import javax.servlet.http.HttpServletRequest;
 38  
 import javax.servlet.http.HttpServletResponse;
 39  
 
 40  
 import org.apache.commons.logging.Log;
 41  
 import org.apache.commons.logging.LogFactory;
 42  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 43  
 
 44  
 /**
 45  
  * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
 46  
  *
 47  
  * @author Manfred Geiler (latest modification by $Author: lu4242 $)
 48  
  * @version $Revision: 888211 $ $Date: 2009-12-07 20:07:19 -0500 (Mon, 07 Dec 2009) $
 49  
  */
 50  
 public final class FacesServlet
 51  
         implements Servlet
 52  
 {
 53  0
     private static final Log log = LogFactory.getLog(FacesServlet.class);
 54  
     
 55  
     /**
 56  
      * Comma separated list of URIs of (additional) faces config files.
 57  
      * (e.g. /WEB-INF/my-config.xml)See JSF 1.0 PRD2, 10.3.2
 58  
      * Attention: You do not need to put /WEB-INF/faces-config.xml in here.
 59  
      */
 60  
     @JSFWebConfigParam(since="1.1")
 61  
     public static final String CONFIG_FILES_ATTR = "javax.faces.CONFIG_FILES";
 62  
 
 63  
     /**
 64  
      * Identify the Lifecycle instance to be used.
 65  
      */
 66  
     @JSFWebConfigParam(since="1.1")
 67  
     public static final String LIFECYCLE_ID_ATTR = "javax.faces.LIFECYCLE_ID";
 68  
 
 69  
     private static final String SERVLET_INFO = "FacesServlet of the MyFaces API implementation";
 70  
     
 71  
     /**
 72  
      * Indicate if myfaces is responsible to handle errors. 
 73  
      * See http://wiki.apache.org/myfaces/Handling_Server_Errors for details. 
 74  
      */
 75  
     @JSFWebConfigParam(defaultValue="true",expectedValues="true,false", since="1.2.4")
 76  
     private static final String ERROR_HANDLING_PARAMETER = "org.apache.myfaces.ERROR_HANDLING";
 77  
     
 78  
     /**
 79  
      * If you want to choose a different class for handling the exception.
 80  
      * <p> 
 81  
      * The error-handler needs to include the following methods:
 82  
      * </p>
 83  
      * <ul>
 84  
      * <li>handleException(FacesContext fc, Exception ex)</li>
 85  
      * <li>handleExceptionList(FacesContext facesContext, List exceptionList)</li>
 86  
      * <li>handleThrowable(FacesContext facesContext, Throwable ex)</li>
 87  
      * </ul>
 88  
      */
 89  
     @JSFWebConfigParam(since="1.2.4")
 90  
     private static final String ERROR_HANDLER_PARAMETER = "org.apache.myfaces.ERROR_HANDLER";
 91  
     private static final String ERROR_HANDLING_EXCEPTION_LIST = "org.apache.myfaces.errorHandling.exceptionList";
 92  
 
 93  
 
 94  
     private ServletConfig _servletConfig;
 95  
     private FacesContextFactory _facesContextFactory;
 96  
     private Lifecycle _lifecycle;
 97  
 
 98  
     public FacesServlet()
 99  
     {
 100  0
         super();
 101  0
     }
 102  
 
 103  
     public void destroy()
 104  
     {
 105  0
         _servletConfig = null;
 106  0
         _facesContextFactory = null;
 107  0
         _lifecycle = null;
 108  0
         if(log.isTraceEnabled()) log.trace("destroy");
 109  0
     }
 110  
 
 111  
     public ServletConfig getServletConfig()
 112  
     {
 113  0
         return _servletConfig;
 114  
     }
 115  
 
 116  
     public String getServletInfo()
 117  
     {
 118  0
         return SERVLET_INFO;
 119  
     }
 120  
 
 121  
     private String getLifecycleId()
 122  
     {
 123  
         //1. check for Servlet's init-param
 124  
         //2. check for global context parameter
 125  
         //3. use default Lifecycle Id, if none of them was provided
 126  0
         String serLifecycleId = _servletConfig.getInitParameter(LIFECYCLE_ID_ATTR);
 127  0
         String appLifecycleId = _servletConfig.getServletContext().getInitParameter(LIFECYCLE_ID_ATTR);
 128  0
         appLifecycleId = serLifecycleId == null ? appLifecycleId : serLifecycleId;
 129  0
         return appLifecycleId != null ? appLifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
 130  
     }
 131  
 
 132  
     public void init(ServletConfig servletConfig)
 133  
             throws ServletException
 134  
     {
 135  0
         if(log.isTraceEnabled()) log.trace("init begin");
 136  0
         _servletConfig = servletConfig;
 137  0
         _facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
 138  
         //TODO: null-check for Weblogic, that tries to initialize Servlet before ContextListener
 139  
 
 140  
         //Javadoc says: Lifecycle instance is shared across multiple simultaneous requests, it must be implemented in a thread-safe manner.
 141  
         //So we can acquire it here once:
 142  0
         LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
 143  0
         _lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
 144  0
         if(log.isTraceEnabled()) log.trace("init end");
 145  0
     }
 146  
 
 147  
     public void service(ServletRequest request,
 148  
                         ServletResponse response)
 149  
             throws IOException,
 150  
                    ServletException
 151  
     {
 152  
 
 153  0
         HttpServletRequest httpRequest = ((HttpServletRequest) request);
 154  0
         String pathInfo = httpRequest.getPathInfo();
 155  
 
 156  
         // if it is a prefix mapping ...
 157  0
         if (pathInfo != null
 158  
                 && (pathInfo.startsWith("/WEB-INF") || pathInfo
 159  
                         .startsWith("/META-INF")))
 160  
         {
 161  0
             StringBuffer buffer = new StringBuffer();
 162  
 
 163  0
             buffer.append(" Someone is trying to access a secure resource : ").append(pathInfo);
 164  0
             buffer.append("\n remote address is ").append(httpRequest.getRemoteAddr());
 165  0
             buffer.append("\n remote host is ").append(httpRequest.getRemoteHost());
 166  0
             buffer.append("\n remote user is ").append(httpRequest.getRemoteUser());
 167  0
             buffer.append("\n request URI is ").append(httpRequest.getRequestURI());
 168  
 
 169  0
             log.warn(buffer.toString());
 170  
 
 171  
             // Why does RI return a 404 and not a 403, SC_FORBIDDEN ?
 172  
 
 173  0
             ((HttpServletResponse) response)
 174  
                     .sendError(HttpServletResponse.SC_NOT_FOUND);
 175  0
             return;
 176  
         }
 177  
 
 178  0
         if(log.isTraceEnabled()) log.trace("service begin");
 179  
 
 180  0
         FacesContext facesContext = prepareFacesContext(request, response);
 181  
 
 182  
         try {
 183  0
             _lifecycle.execute(facesContext);
 184  
 
 185  0
             if (!handleQueuedExceptions(facesContext))
 186  
             {
 187  0
                 _lifecycle.render(facesContext);
 188  
             }
 189  
         }
 190  0
         catch (Exception e)
 191  
         {
 192  0
             handleLifecycleException(facesContext, e);
 193  
         }
 194  0
         catch (Throwable e)
 195  
         {
 196  0
             handleLifecycleThrowable(facesContext, e);
 197  
         }
 198  
         finally
 199  
         {
 200  0
             facesContext.release();
 201  0
         }
 202  0
         if(log.isTraceEnabled()) log.trace("service end");
 203  0
     }
 204  
 
 205  
     /**This method makes sure we see an exception page also
 206  
      * if an exception has been thrown in UIInput.updateModel();
 207  
      * In this method, according to the spec, we may not rethrow the
 208  
      * exception, so we add it to a list and process it here.
 209  
      *
 210  
      * Attention: if you use redirects, the exceptions will get lost - exactly
 211  
      * like in the case of FacesMessages. If you want them to be taken over to the
 212  
      * next request, you should try the redirect-tracker of MyFaces.
 213  
      *
 214  
      * @param facesContext
 215  
      * @throws FacesException
 216  
      */
 217  
     private boolean handleQueuedExceptions(FacesContext facesContext) throws IOException, ServletException {
 218  0
         List li = (List)
 219  
                 facesContext.getExternalContext().getRequestMap().get(ERROR_HANDLING_EXCEPTION_LIST);
 220  
 
 221  0
         if(li != null && li.size()>=1)  {
 222  
             //todo: for now, we only handle the first exception out of the list - we just rethrow this
 223  
             //first exception.
 224  
             //in the end, we should enable the error handler to show all the exceptions at once
 225  0
             boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
 226  
 
 227  0
             if(errorHandling) {
 228  0
                 String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);            
 229  0
                 if(errorHandlerClass != null) {
 230  
                     try {
 231  0
                         Class clazz = Class.forName(errorHandlerClass);
 232  
 
 233  0
                         Object errorHandler = clazz.newInstance();
 234  
 
 235  0
                         Method m = clazz.getMethod("handleExceptionList", new Class[]{FacesContext.class,List.class});
 236  0
                         m.invoke(errorHandler, new Object[]{facesContext, li});
 237  
                     }
 238  0
                     catch(ClassNotFoundException ex) {
 239  0
                         throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 240  0
                     } catch (IllegalAccessException ex) {
 241  0
                         throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 242  0
                     } catch (InstantiationException ex) {
 243  0
                         throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 244  0
                     } catch (NoSuchMethodException ex) {
 245  
                         //Handle in the old way, since no custom method handleExceptionList found,
 246  
                         //throwing the first FacesException on the list.
 247  0
                         throw (FacesException) li.get(0);
 248  0
                     } catch (InvocationTargetException ex) {
 249  0
                         throw new ServletException("Excecution of method handleException in Error-Handler : " +errorHandlerClass+ " threw an exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 250  0
                     }
 251  
                 }
 252  
                 else {
 253  0
                     _ErrorPageWriter.handleExceptionList(facesContext, li);
 254  
                 }
 255  0
             }
 256  
             else {
 257  0
                 _ErrorPageWriter.throwException((Exception) li.get(0));
 258  
             }
 259  0
             return true;
 260  
         }
 261  0
         return false;
 262  
     }
 263  
 
 264  
     private void handleLifecycleException(FacesContext facesContext, Exception e) throws IOException, ServletException {
 265  
 
 266  0
         boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
 267  
 
 268  0
         if(errorHandling) {
 269  0
             String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
 270  0
             if(errorHandlerClass != null) {
 271  
                 try {
 272  0
                     Class clazz = Class.forName(errorHandlerClass);
 273  
 
 274  0
                     Object errorHandler = clazz.newInstance();
 275  
 
 276  0
                     Method m = clazz.getMethod("handleException", new Class[]{FacesContext.class,Exception.class});
 277  0
                     m.invoke(errorHandler, new Object[]{facesContext, e});
 278  
                 }
 279  0
                 catch(ClassNotFoundException ex) {
 280  0
                     throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 281  0
                 } catch (IllegalAccessException ex) {
 282  0
                     throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 283  0
                 } catch (InstantiationException ex) {
 284  0
                     throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 285  0
                 } catch (NoSuchMethodException ex) {
 286  0
                     log.error("Error-Handler : " +errorHandlerClass+ " did not have a method with name : handleException and parameters : javax.faces.context.FacesContext, java.lang.Exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 287  
                     //Try to look if it is implemented more general method handleThrowable
 288  0
                     handleLifecycleThrowable(facesContext, e);
 289  0
                 } catch (InvocationTargetException ex) {
 290  0
                     throw new ServletException("Excecution of method handleException in Error-Handler : " +errorHandlerClass+ " caused an exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 291  0
                 }
 292  
             }
 293  
             else {
 294  0
                 _ErrorPageWriter.handleException(facesContext, e);
 295  
             }
 296  0
         }
 297  
         else {
 298  0
             _ErrorPageWriter.throwException(e);
 299  
         }
 300  0
     }
 301  
     
 302  
     private void handleLifecycleThrowable(FacesContext facesContext, Throwable e) throws IOException, ServletException {
 303  
 
 304  0
         boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
 305  
 
 306  0
         if(errorHandling) {
 307  0
             String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);            
 308  0
             if(errorHandlerClass != null) {
 309  
                 try {
 310  0
                     Class clazz = Class.forName(errorHandlerClass);
 311  
 
 312  0
                     Object errorHandler = clazz.newInstance();
 313  
 
 314  0
                     Method m = clazz.getMethod("handleThrowable", new Class[]{FacesContext.class,Throwable.class});
 315  0
                     m.invoke(errorHandler, new Object[]{facesContext, e});
 316  
                 }
 317  0
                 catch(ClassNotFoundException ex) {
 318  0
                     throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 319  0
                 } catch (IllegalAccessException ex) {
 320  0
                     throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 321  0
                 } catch (InstantiationException ex) {
 322  0
                     throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 323  0
                 } catch (NoSuchMethodException ex) {
 324  0
                     throw new ServletException("Error-Handler : " +errorHandlerClass+ " did not have a method with name : handleException and parameters : javax.faces.context.FacesContext, java.lang.Exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 325  0
                 } catch (InvocationTargetException ex) {
 326  0
                     throw new ServletException("Excecution of method handleException in Error-Handler : " +errorHandlerClass+ " threw an exception. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
 327  0
                 }
 328  
             }
 329  
             else {
 330  0
                 _ErrorPageWriter.handleThrowable(facesContext, e);
 331  
             }
 332  0
         }
 333  
         else {
 334  0
             _ErrorPageWriter.throwException(e);
 335  
         }
 336  0
     }
 337  
 
 338  
     private static boolean getBooleanValue(String initParameter, boolean defaultVal) {
 339  
 
 340  0
         if(initParameter == null || initParameter.trim().length()==0)
 341  0
             return defaultVal;
 342  
 
 343  0
         return (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true"));
 344  
     }
 345  
 
 346  
     private FacesContext prepareFacesContext(ServletRequest request, ServletResponse response) {
 347  0
         FacesContext facesContext
 348  
                 = _facesContextFactory.getFacesContext(_servletConfig.getServletContext(),
 349  
                                                        request,
 350  
                                                        response,
 351  
                                                        _lifecycle);
 352  0
         return facesContext;
 353  
     }
 354  
 }