1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
46
47
48
49
50 public final class FacesServlet
51 implements Servlet
52 {
53 private static final Log log = LogFactory.getLog(FacesServlet.class);
54
55
56
57
58
59
60 @JSFWebConfigParam(since="1.1")
61 public static final String CONFIG_FILES_ATTR = "javax.faces.CONFIG_FILES";
62
63
64
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
73
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
80
81
82
83
84
85
86
87
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 super();
101 }
102
103 public void destroy()
104 {
105 _servletConfig = null;
106 _facesContextFactory = null;
107 _lifecycle = null;
108 if(log.isTraceEnabled()) log.trace("destroy");
109 }
110
111 public ServletConfig getServletConfig()
112 {
113 return _servletConfig;
114 }
115
116 public String getServletInfo()
117 {
118 return SERVLET_INFO;
119 }
120
121 private String getLifecycleId()
122 {
123
124
125
126 String serLifecycleId = _servletConfig.getInitParameter(LIFECYCLE_ID_ATTR);
127 String appLifecycleId = _servletConfig.getServletContext().getInitParameter(LIFECYCLE_ID_ATTR);
128 appLifecycleId = serLifecycleId == null ? appLifecycleId : serLifecycleId;
129 return appLifecycleId != null ? appLifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
130 }
131
132 public void init(ServletConfig servletConfig)
133 throws ServletException
134 {
135 if(log.isTraceEnabled()) log.trace("init begin");
136 _servletConfig = servletConfig;
137 _facesContextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
138
139
140
141
142 LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
143 _lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
144 if(log.isTraceEnabled()) log.trace("init end");
145 }
146
147 public void service(ServletRequest request,
148 ServletResponse response)
149 throws IOException,
150 ServletException
151 {
152
153 HttpServletRequest httpRequest = ((HttpServletRequest) request);
154 String pathInfo = httpRequest.getPathInfo();
155
156
157 if (pathInfo != null
158 && (pathInfo.startsWith("/WEB-INF") || pathInfo
159 .startsWith("/META-INF")))
160 {
161 StringBuffer buffer = new StringBuffer();
162
163 buffer.append(" Someone is trying to access a secure resource : ").append(pathInfo);
164 buffer.append("\n remote address is ").append(httpRequest.getRemoteAddr());
165 buffer.append("\n remote host is ").append(httpRequest.getRemoteHost());
166 buffer.append("\n remote user is ").append(httpRequest.getRemoteUser());
167 buffer.append("\n request URI is ").append(httpRequest.getRequestURI());
168
169 log.warn(buffer.toString());
170
171
172
173 ((HttpServletResponse) response)
174 .sendError(HttpServletResponse.SC_NOT_FOUND);
175 return;
176 }
177
178 if(log.isTraceEnabled()) log.trace("service begin");
179
180 FacesContext facesContext = prepareFacesContext(request, response);
181
182 try {
183 _lifecycle.execute(facesContext);
184
185 if (!handleQueuedExceptions(facesContext))
186 {
187 _lifecycle.render(facesContext);
188 }
189 }
190 catch (Exception e)
191 {
192 handleLifecycleException(facesContext, e);
193 }
194 catch (Throwable e)
195 {
196 handleLifecycleThrowable(facesContext, e);
197 }
198 finally
199 {
200 facesContext.release();
201 }
202 if(log.isTraceEnabled()) log.trace("service end");
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217 private boolean handleQueuedExceptions(FacesContext facesContext) throws IOException, ServletException {
218 List li = (List)
219 facesContext.getExternalContext().getRequestMap().get(ERROR_HANDLING_EXCEPTION_LIST);
220
221 if(li != null && li.size()>=1) {
222
223
224
225 boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
226
227 if(errorHandling) {
228 String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
229 if(errorHandlerClass != null) {
230 try {
231 Class clazz = Class.forName(errorHandlerClass);
232
233 Object errorHandler = clazz.newInstance();
234
235 Method m = clazz.getMethod("handleExceptionList", new Class[]{FacesContext.class,List.class});
236 m.invoke(errorHandler, new Object[]{facesContext, li});
237 }
238 catch(ClassNotFoundException ex) {
239 throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
240 } catch (IllegalAccessException ex) {
241 throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
242 } catch (InstantiationException ex) {
243 throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
244 } catch (NoSuchMethodException ex) {
245
246
247 throw (FacesException) li.get(0);
248 } catch (InvocationTargetException ex) {
249 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 }
251 }
252 else {
253 _ErrorPageWriter.handleExceptionList(facesContext, li);
254 }
255 }
256 else {
257 _ErrorPageWriter.throwException((Exception) li.get(0));
258 }
259 return true;
260 }
261 return false;
262 }
263
264 private void handleLifecycleException(FacesContext facesContext, Exception e) throws IOException, ServletException {
265
266 boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
267
268 if(errorHandling) {
269 String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
270 if(errorHandlerClass != null) {
271 try {
272 Class clazz = Class.forName(errorHandlerClass);
273
274 Object errorHandler = clazz.newInstance();
275
276 Method m = clazz.getMethod("handleException", new Class[]{FacesContext.class,Exception.class});
277 m.invoke(errorHandler, new Object[]{facesContext, e});
278 }
279 catch(ClassNotFoundException ex) {
280 throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
281 } catch (IllegalAccessException ex) {
282 throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
283 } catch (InstantiationException ex) {
284 throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
285 } catch (NoSuchMethodException ex) {
286 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
288 handleLifecycleThrowable(facesContext, e);
289 } catch (InvocationTargetException ex) {
290 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 }
292 }
293 else {
294 _ErrorPageWriter.handleException(facesContext, e);
295 }
296 }
297 else {
298 _ErrorPageWriter.throwException(e);
299 }
300 }
301
302 private void handleLifecycleThrowable(FacesContext facesContext, Throwable e) throws IOException, ServletException {
303
304 boolean errorHandling = getBooleanValue(facesContext.getExternalContext().getInitParameter(ERROR_HANDLING_PARAMETER), true);
305
306 if(errorHandling) {
307 String errorHandlerClass = facesContext.getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
308 if(errorHandlerClass != null) {
309 try {
310 Class clazz = Class.forName(errorHandlerClass);
311
312 Object errorHandler = clazz.newInstance();
313
314 Method m = clazz.getMethod("handleThrowable", new Class[]{FacesContext.class,Throwable.class});
315 m.invoke(errorHandler, new Object[]{facesContext, e});
316 }
317 catch(ClassNotFoundException ex) {
318 throw new ServletException("Error-Handler : " +errorHandlerClass+ " was not found. Fix your web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
319 } catch (IllegalAccessException ex) {
320 throw new ServletException("Constructor of error-Handler : " +errorHandlerClass+ " is not accessible. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
321 } catch (InstantiationException ex) {
322 throw new ServletException("Error-Handler : " +errorHandlerClass+ " could not be instantiated. Error-Handler is specified in web.xml-parameter : "+ERROR_HANDLER_PARAMETER,ex);
323 } catch (NoSuchMethodException ex) {
324 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 } catch (InvocationTargetException ex) {
326 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 }
328 }
329 else {
330 _ErrorPageWriter.handleThrowable(facesContext, e);
331 }
332 }
333 else {
334 _ErrorPageWriter.throwException(e);
335 }
336 }
337
338 private static boolean getBooleanValue(String initParameter, boolean defaultVal) {
339
340 if(initParameter == null || initParameter.trim().length()==0)
341 return defaultVal;
342
343 return (initParameter.equalsIgnoreCase("on") || initParameter.equals("1") || initParameter.equalsIgnoreCase("true"));
344 }
345
346 private FacesContext prepareFacesContext(ServletRequest request, ServletResponse response) {
347 FacesContext facesContext
348 = _facesContextFactory.getFacesContext(_servletConfig.getServletContext(),
349 request,
350 response,
351 _lifecycle);
352 return facesContext;
353 }
354 }