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 @Override
172 public void handle() throws FacesException
173 {
174 if (unhandled != null && !unhandled.isEmpty())
175 {
176 if (handled == null)
177 {
178 handled = new LinkedList<ExceptionQueuedEvent>();
179 }
180
181
182
183 String errorHandlerClass = FacesContext.getCurrentInstance()
184 .getExternalContext().getInitParameter(ERROR_HANDLER_PARAMETER);
185
186 FacesException toThrow = null;
187
188 do
189 {
190
191
192
193 ExceptionQueuedEvent event = unhandled.peek();
194 try
195 {
196
197 ExceptionQueuedEventContext context = event.getContext();
198
199
200 Throwable exception = context.getException();
201
202 if (errorHandlerClass != null)
203 {
204
205 try
206 {
207 Class<?> clazz = Class.forName(errorHandlerClass);
208
209 Object errorHandler = clazz.newInstance();
210
211 Method m = clazz.getMethod("handleException", new Class[] { FacesContext.class, Exception.class });
212 m.invoke(errorHandler, new Object[] { context.getContext(), exception });
213 }
214 catch (ClassNotFoundException ex)
215 {
216 throw new FacesException("Error-Handler : " + errorHandlerClass
217 + " was not found. Fix your web.xml-parameter : " + ERROR_HANDLER_PARAMETER, ex);
218 }
219 catch (IllegalAccessException ex)
220 {
221 throw new FacesException("Constructor of error-Handler : " + errorHandlerClass
222 + " is not accessible. Error-Handler is specified in web.xml-parameter : "
223 + ERROR_HANDLER_PARAMETER, ex);
224 }
225 catch (InstantiationException ex)
226 {
227 throw new FacesException("Error-Handler : " + errorHandlerClass
228 + " could not be instantiated. Error-Handler is specified in web.xml-parameter : "
229 + ERROR_HANDLER_PARAMETER, ex);
230 }
231 catch (NoSuchMethodException ex)
232 {
233 throw new FacesException("Error-Handler : " + errorHandlerClass
234 + " does not have a method with name : handleException and parameters : "
235 + "javax.faces.context.FacesContext, java.lang.Exception. Error-Handler is"
236 + "specified in web.xml-parameter : " + ERROR_HANDLER_PARAMETER, ex);
237 }
238 catch (InvocationTargetException ex)
239 {
240 throw new FacesException("Excecution of method handleException in Error-Handler : "
241 + errorHandlerClass
242 + " caused an exception. Error-Handler is specified in web.xml-parameter : "
243 + ERROR_HANDLER_PARAMETER, ex);
244 }
245 }
246 else
247 {
248
249
250
251 if (exception instanceof UpdateModelException)
252 {
253 FacesMessage message = ((UpdateModelException) exception).getFacesMessage();
254
255 log.log(Level.SEVERE, message.getSummary(), exception.getCause());
256
257 UIComponent component = context.getComponent();
258 String clientId = null;
259 if (component != null)
260 {
261 clientId = component.getClientId(context.getContext());
262 }
263 context.getContext().addMessage(clientId, message);
264 }
265 else if (!shouldSkip(exception) && !context.inBeforePhase() && !context.inAfterPhase())
266 {
267
268 handledAndThrown = event;
269
270
271
272
273
274 toThrow = wrap(getRethrownException(exception));
275 break;
276 }
277 else
278 {
279
280
281 log.log(Level.SEVERE, exception.getClass().getName() + " occured while processing " +
282 (context.inBeforePhase() ? "beforePhase() of " :
283 (context.inAfterPhase() ? "afterPhase() of " : "")) +
284 "phase " + context.getPhaseId() + ": " +
285 "UIComponent-ClientId=" +
286 (context.getComponent() != null ?
287 context.getComponent().getClientId(context.getContext()) : "") + ", " +
288 "Message=" + exception.getMessage());
289
290 log.log(Level.SEVERE, exception.getMessage(), exception);
291 }
292 }
293 }
294 catch (Throwable t)
295 {
296
297
298 throw new FacesException("Could not perform the algorithm to handle the Exception", t);
299 }
300 finally
301 {
302
303
304 handled.add(event);
305 unhandled.remove(event);
306 }
307 } while (!unhandled.isEmpty());
308
309
310 if (toThrow != null)
311 {
312 throw toThrow;
313 }
314 }
315 }
316
317
318
319
320 @Override
321 public boolean isListenerForSource(Object source)
322 {
323 return source instanceof ExceptionQueuedEventContext;
324 }
325
326
327
328
329 @Override
330 public void processEvent(SystemEvent exceptionQueuedEvent) throws AbortProcessingException
331 {
332 if (unhandled == null)
333 {
334 unhandled = new LinkedList<ExceptionQueuedEvent>();
335 }
336
337 unhandled.add((ExceptionQueuedEvent)exceptionQueuedEvent);
338 }
339
340 protected Throwable getRethrownException(Throwable exception)
341 {
342
343
344 Throwable toRethrow = getRootCause(exception);
345 if (toRethrow == null)
346 {
347 toRethrow = exception;
348 }
349
350 return toRethrow;
351 }
352
353 protected FacesException wrap(Throwable exception)
354 {
355 if (exception instanceof FacesException)
356 {
357 return (FacesException) exception;
358 }
359 return new FacesException(exception);
360 }
361
362 protected boolean shouldSkip(Throwable exception)
363 {
364 return exception instanceof AbortProcessingException;
365 }
366 }
367 }