Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
FacesServlet |
|
| 3.5;3.5 |
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.util.logging.Level; | |
23 | import java.util.logging.Logger; | |
24 | ||
25 | import javax.faces.FacesException; | |
26 | import javax.faces.FactoryFinder; | |
27 | import javax.faces.application.ResourceHandler; | |
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.annotation.MultipartConfig; | |
38 | import javax.servlet.http.HttpServletRequest; | |
39 | import javax.servlet.http.HttpServletResponse; | |
40 | ||
41 | import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam; | |
42 | /** | |
43 | * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> | |
44 | */ | |
45 | @MultipartConfig | |
46 | public final class FacesServlet implements Servlet | |
47 | { | |
48 | //private static final Log log = LogFactory.getLog(FacesServlet.class); | |
49 | 0 | private static final Logger log = Logger.getLogger(FacesServlet.class.getName()); |
50 | ||
51 | /** | |
52 | * Comma separated list of URIs of (additional) faces config files. | |
53 | * (e.g. /WEB-INF/my-config.xml)See JSF 1.0 PRD2, 10.3.2 | |
54 | * Attention: You do not need to put /WEB-INF/faces-config.xml in here. | |
55 | */ | |
56 | @JSFWebConfigParam(since="1.1") | |
57 | public static final String CONFIG_FILES_ATTR = "javax.faces.CONFIG_FILES"; | |
58 | ||
59 | /** | |
60 | * Identify the Lifecycle instance to be used. | |
61 | */ | |
62 | @JSFWebConfigParam(since="1.1") | |
63 | public static final String LIFECYCLE_ID_ATTR = "javax.faces.LIFECYCLE_ID"; | |
64 | ||
65 | private static final String SERVLET_INFO = "FacesServlet of the MyFaces API implementation"; | |
66 | ||
67 | private ServletConfig _servletConfig; | |
68 | private FacesContextFactory _facesContextFactory; | |
69 | private Lifecycle _lifecycle; | |
70 | ||
71 | public FacesServlet() | |
72 | { | |
73 | 0 | super(); |
74 | 0 | } |
75 | ||
76 | public void destroy() | |
77 | { | |
78 | 0 | _servletConfig = null; |
79 | 0 | _facesContextFactory = null; |
80 | 0 | _lifecycle = null; |
81 | 0 | if (log.isLoggable(Level.FINEST)) |
82 | { | |
83 | 0 | log.finest("destroy"); |
84 | } | |
85 | 0 | } |
86 | ||
87 | public ServletConfig getServletConfig() | |
88 | { | |
89 | 0 | return _servletConfig; |
90 | } | |
91 | ||
92 | public String getServletInfo() | |
93 | { | |
94 | 0 | return SERVLET_INFO; |
95 | } | |
96 | ||
97 | private String getLifecycleId() | |
98 | { | |
99 | // 1. check for Servlet's init-param | |
100 | // 2. check for global context parameter | |
101 | // 3. use default Lifecycle Id, if none of them was provided | |
102 | 0 | String serLifecycleId = _servletConfig.getInitParameter(LIFECYCLE_ID_ATTR); |
103 | 0 | String appLifecycleId = _servletConfig.getServletContext().getInitParameter(LIFECYCLE_ID_ATTR); |
104 | 0 | appLifecycleId = serLifecycleId == null ? appLifecycleId : serLifecycleId; |
105 | 0 | return appLifecycleId != null ? appLifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE; |
106 | } | |
107 | ||
108 | public void init(ServletConfig servletConfig) throws ServletException | |
109 | { | |
110 | 0 | if (log.isLoggable(Level.FINEST)) |
111 | { | |
112 | 0 | log.finest("init begin"); |
113 | } | |
114 | 0 | _servletConfig = servletConfig; |
115 | 0 | _facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); |
116 | // TODO: null-check for Weblogic, that tries to initialize Servlet before ContextListener | |
117 | ||
118 | // Javadoc says: Lifecycle instance is shared across multiple simultaneous requests, it must be implemented in a | |
119 | // thread-safe manner. | |
120 | // So we can acquire it here once: | |
121 | 0 | LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); |
122 | 0 | _lifecycle = lifecycleFactory.getLifecycle(getLifecycleId()); |
123 | 0 | if (log.isLoggable(Level.FINEST)) |
124 | { | |
125 | 0 | log.finest("init end"); |
126 | } | |
127 | 0 | } |
128 | ||
129 | public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException | |
130 | { | |
131 | // If the request and response arguments to this method are not instances of HttpServletRequest and | |
132 | // HttpServletResponse, respectively, the results of invoking this method are undefined. | |
133 | // In this case ClassCastException | |
134 | 0 | HttpServletRequest httpRequest = (HttpServletRequest)request; |
135 | 0 | String pathInfo = httpRequest.getPathInfo(); |
136 | ||
137 | // if it is a prefix mapping ... | |
138 | ||
139 | /* | |
140 | * This method must respond to requests that start with the following strings by invoking the sendError | |
141 | * method on the response argument (cast to HttpServletResponse), passing the code | |
142 | * HttpServletResponse.SC_NOT_FOUND as the argument. | |
143 | * | |
144 | * /WEB-INF/ | |
145 | * /WEB-INF | |
146 | * /META-INF/ | |
147 | * /META-INF | |
148 | */ | |
149 | 0 | if (pathInfo != null && (pathInfo.startsWith("/WEB-INF") || pathInfo.startsWith("/META-INF"))) |
150 | { | |
151 | 0 | StringBuffer buffer = new StringBuffer(); |
152 | ||
153 | 0 | buffer.append(" Someone is trying to access a secure resource : ").append(pathInfo); |
154 | 0 | buffer.append("\n remote address is ").append(httpRequest.getRemoteAddr()); |
155 | 0 | buffer.append("\n remote host is ").append(httpRequest.getRemoteHost()); |
156 | 0 | buffer.append("\n remote user is ").append(httpRequest.getRemoteUser()); |
157 | 0 | buffer.append("\n request URI is ").append(httpRequest.getRequestURI()); |
158 | ||
159 | 0 | log.warning(buffer.toString()); |
160 | ||
161 | // Why does RI return a 404 and not a 403, SC_FORBIDDEN ? | |
162 | ||
163 | 0 | ((HttpServletResponse)response).sendError(HttpServletResponse.SC_NOT_FOUND); |
164 | 0 | return; |
165 | } | |
166 | ||
167 | // If none of the cases described above in the specification for this method apply to the servicing of this | |
168 | // request, the following action must be taken to service the request: | |
169 | 0 | if (log.isLoggable(Level.FINEST)) |
170 | { | |
171 | 0 | log.finest("service begin"); |
172 | } | |
173 | ||
174 | // Acquire a FacesContext instance for this request. | |
175 | 0 | FacesContext facesContext = prepareFacesContext(request, response); |
176 | ||
177 | try | |
178 | { | |
179 | // jsf 2.0 : get the current ResourceHandler and | |
180 | // check if it is a resource request, if true | |
181 | // delegate to ResourceHandler, else continue with | |
182 | // the lifecycle. | |
183 | // Acquire the ResourceHandler for this request by calling Application.getResourceHandler(). | |
184 | 0 | ResourceHandler resourceHandler = facesContext.getApplication().getResourceHandler(); |
185 | ||
186 | // Call ResourceHandler.isResourceRequest(javax.faces.context.FacesContext). | |
187 | 0 | if (resourceHandler.isResourceRequest(facesContext)) |
188 | { | |
189 | // If this returns true call ResourceHandler.handleResourceRequest(javax.faces.context.FacesContext). | |
190 | 0 | resourceHandler.handleResourceRequest(facesContext); |
191 | } | |
192 | else | |
193 | { | |
194 | //JSF 2.2: attach window | |
195 | 0 | _lifecycle.attachWindow(facesContext); |
196 | // If this returns false, handle as follows: | |
197 | // call Lifecycle.execute(javax.faces.context.FacesContext) | |
198 | 0 | _lifecycle.execute(facesContext); |
199 | // followed by Lifecycle.render(javax.faces.context.FacesContext). | |
200 | 0 | _lifecycle.render(facesContext); |
201 | } | |
202 | } | |
203 | 0 | catch (FacesException e) |
204 | { | |
205 | // If a FacesException is thrown in either case | |
206 | ||
207 | // extract the cause from the FacesException | |
208 | 0 | Throwable cause = e.getCause(); |
209 | 0 | if (cause == null) |
210 | { | |
211 | // If the cause is null extract the message from the FacesException, put it inside of a new | |
212 | // ServletException instance, and pass the FacesException instance as the root cause, then | |
213 | // rethrow the ServletException instance. | |
214 | 0 | throw new ServletException(e.getLocalizedMessage(), e); |
215 | } | |
216 | 0 | else if (cause instanceof ServletException) |
217 | { | |
218 | // If the cause is an instance of ServletException, rethrow the cause. | |
219 | 0 | throw (ServletException)cause; |
220 | } | |
221 | 0 | else if (cause instanceof IOException) |
222 | { | |
223 | // If the cause is an instance of IOException, rethrow the cause. | |
224 | 0 | throw (IOException)cause; |
225 | } | |
226 | else | |
227 | { | |
228 | // Otherwise, create a new ServletException instance, passing the message from the cause, | |
229 | // as the first argument, and the cause itself as the second argument. | |
230 | 0 | throw new ServletException(cause.getLocalizedMessage(), cause); |
231 | } | |
232 | } | |
233 | finally | |
234 | { | |
235 | // In a finally block, FacesContext.release() must be called. | |
236 | 0 | facesContext.release(); |
237 | 0 | } |
238 | 0 | if (log.isLoggable(Level.FINEST)) |
239 | { | |
240 | 0 | log.finest("service end"); |
241 | } | |
242 | 0 | } |
243 | ||
244 | private FacesContext prepareFacesContext(ServletRequest request, ServletResponse response) | |
245 | { | |
246 | 0 | FacesContext facesContext = |
247 | _facesContextFactory.getFacesContext(_servletConfig.getServletContext(), request, response, _lifecycle); | |
248 | 0 | return facesContext; |
249 | } | |
250 | } |