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.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.util.Collections;
24 import java.util.LinkedList;
25 import java.util.Queue;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import javax.el.ELException;
30 import javax.faces.FacesException;
31 import javax.faces.application.FacesMessage;
32 import javax.faces.component.UIComponent;
33 import javax.faces.component.UpdateModelException;
34 import javax.faces.context.ExceptionHandler;
35 import javax.faces.context.ExceptionHandlerFactory;
36 import javax.faces.context.FacesContext;
37 import javax.faces.event.AbortProcessingException;
38 import javax.faces.event.ExceptionQueuedEvent;
39 import javax.faces.event.ExceptionQueuedEventContext;
40 import javax.faces.event.SystemEvent;
41
42 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
43
44
45
46
47
48
49
50
51 public class PreJsf2ExceptionHandlerFactory extends ExceptionHandlerFactory
52 {
53
54 private static final Logger log = Logger.getLogger(PreJsf2ExceptionHandlerFactory.class.getName());
55
56
57
58
59 public PreJsf2ExceptionHandlerFactory()
60 {
61 }
62
63
64
65
66 @Override
67 public ExceptionHandler getExceptionHandler()
68 {
69 return new PreJsf2ExceptionHandlerImpl();
70 }
71
72 private static class PreJsf2ExceptionHandlerImpl extends ExceptionHandler
73 {
74
75
76
77
78
79
80
81
82
83
84
85
86 private static final Logger log = Logger.getLogger(PreJsf2ExceptionHandlerImpl.class.getName());
87
88
89
90
91
92
93
94
95
96
97
98 @JSFWebConfigParam(since="1.2.4",desc="Deprecated: use JSF 2.0 ExceptionHandler", deprecated=true)
99 private static final String ERROR_HANDLER_PARAMETER = "org.apache.myfaces.ERROR_HANDLER";
100
101 private Queue<ExceptionQueuedEvent> handled;
102 private Queue<ExceptionQueuedEvent> unhandled;
103 private ExceptionQueuedEvent handledAndThrown;
104
105 public PreJsf2ExceptionHandlerImpl()
106 {
107 }
108
109
110
111
112 @Override
113 public ExceptionQueuedEvent getHandledExceptionQueuedEvent()
114 {
115 return handledAndThrown;
116 }
117
118
119
120
121 @Override
122 public Iterable<ExceptionQueuedEvent> getHandledExceptionQueuedEvents()
123 {
124 return handled == null ? Collections.<ExceptionQueuedEvent>emptyList() : handled;
125 }
126
127
128
129
130 @Override
131 public Throwable getRootCause(Throwable t)
132 {
133 if (t == null)
134 {
135 throw new NullPointerException("t");
136 }
137
138 while (t != null)
139 {
140 Class<?> clazz = t.getClass();
141 if (!clazz.equals(FacesException.class) && !clazz.equals(ELException.class))
142 {
143 return t;
144 }
145
146 t = t.getCause();
147 }
148
149 return null;
150 }
151
152
153
154
155 @Override
156 public Iterable<ExceptionQueuedEvent> getUnhandledExceptionQueuedEvents()
157 {
158 return unhandled == null ? Collections.<ExceptionQueuedEvent>emptyList() : unhandled;
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173 @Override
174 public void handle() throws FacesException
175 {
176 if (unhandled != null && !unhandled.isEmpty())
177 {
178 if (handled == null)
179 {
180 handled = new LinkedList<ExceptionQueuedEvent>();
181 }
182
183
184
185 String errorHandlerClass = FacesContext.getCurrentInstance()
186 .getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
187
188 FacesException toThrow = null;
189
190 do
191 {
192
193
194
195 ExceptionQueuedEvent event = unhandled.peek();
196 try
197 {
198
199 ExceptionQueuedEventContext context = event.getContext();
200
201
202 Throwable exception = context.getException();
203
204 if (errorHandlerClass != null)
205 {
206
207 try
208 {
209 Class<?> clazz = Class.forName(errorHandlerClass);
210
211 Object errorHandler = clazz.newInstance();
212
213 Method m = clazz.getMethod("handleException",
214 new Class[] { FacesContext.class, Exception.class });
215 m.invoke(errorHandler, new Object[] { context.getContext(), exception });
216 }
217 catch (ClassNotFoundException ex)
218 {
219 throw new FacesException("Error-Handler : " + errorHandlerClass
220 + " was not found. Fix your web.xml-parameter : "
221 + ERROR_HANDLER_PARAMETER, ex);
222 }
223 catch (IllegalAccessException ex)
224 {
225 throw new FacesException("Constructor of error-Handler : " + errorHandlerClass
226 + " is not accessible. Error-Handler is specified in web.xml-parameter : "
227 + ERROR_HANDLER_PARAMETER, ex);
228 }
229 catch (InstantiationException ex)
230 {
231 throw new FacesException("Error-Handler : " + errorHandlerClass
232 + " could not be instantiated. Error-Handler is specified in web.xml-parameter : "
233 + ERROR_HANDLER_PARAMETER, ex);
234 }
235 catch (NoSuchMethodException ex)
236 {
237 throw new FacesException("Error-Handler : " + errorHandlerClass
238 + " does not have a method with name : handleException and parameters : "
239 + "javax.faces.context.FacesContext, java.lang.Exception. Error-Handler is"
240 + "specified in web.xml-parameter : " + ERROR_HANDLER_PARAMETER, ex);
241 }
242 catch (InvocationTargetException ex)
243 {
244 throw new FacesException("Excecution of method handleException in Error-Handler : "
245 + errorHandlerClass
246 + " caused an exception. Error-Handler is specified in web.xml-parameter : "
247 + ERROR_HANDLER_PARAMETER, ex);
248 }
249 }
250 else
251 {
252
253
254
255 if (exception instanceof UpdateModelException)
256 {
257 FacesMessage message = ((UpdateModelException) exception).getFacesMessage();
258
259 log.log(Level.SEVERE, message.getSummary(), exception.getCause());
260
261 UIComponent component = context.getComponent();
262 String clientId = null;
263 if (component != null)
264 {
265 clientId = component.getClientId(context.getContext());
266 }
267 context.getContext().addMessage(clientId, message);
268 }
269 else if (!shouldSkip(exception) && !context.inBeforePhase() && !context.inAfterPhase())
270 {
271
272 handledAndThrown = event;
273
274
275
276
277
278
279
280 toThrow = wrap(getRethrownException(exception));
281 break;
282 }
283 else
284 {
285
286
287 log.log(Level.SEVERE, exception.getClass().getName() + " occured while processing " +
288 (context.inBeforePhase() ? "beforePhase() of " :
289 (context.inAfterPhase() ? "afterPhase() of " : "")) +
290 "phase " + context.getPhaseId() + ": " +
291 "UIComponent-ClientId=" +
292 (context.getComponent() != null ?
293 context.getComponent().getClientId(context.getContext()) : "") + ", " +
294 "Message=" + exception.getMessage());
295
296 log.log(Level.SEVERE, exception.getMessage(), exception);
297 }
298 }
299 }
300 catch (Throwable t)
301 {
302
303
304 throw new FacesException("Could not perform the algorithm to handle the Exception", t);
305 }
306 finally
307 {
308
309
310 handled.add(event);
311 unhandled.remove(event);
312 }
313 } while (!unhandled.isEmpty());
314
315
316 if (toThrow != null)
317 {
318 throw toThrow;
319 }
320 }
321 }
322
323
324
325
326 @Override
327 public boolean isListenerForSource(Object source)
328 {
329 return source instanceof ExceptionQueuedEventContext;
330 }
331
332
333
334
335 @Override
336 public void processEvent(SystemEvent exceptionQueuedEvent) throws AbortProcessingException
337 {
338 if (unhandled == null)
339 {
340 unhandled = new LinkedList<ExceptionQueuedEvent>();
341 }
342
343 unhandled.add((ExceptionQueuedEvent)exceptionQueuedEvent);
344 }
345
346 protected Throwable getRethrownException(Throwable exception)
347 {
348
349
350 Throwable toRethrow = getRootCause(exception);
351 if (toRethrow == null)
352 {
353 toRethrow = exception;
354 }
355
356 return toRethrow;
357 }
358
359 protected FacesException wrap(Throwable exception)
360 {
361 if (exception instanceof FacesException)
362 {
363 return (FacesException) exception;
364 }
365 return new FacesException(exception);
366 }
367
368 protected boolean shouldSkip(Throwable exception)
369 {
370 return exception instanceof AbortProcessingException;
371 }
372 }
373 }