1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.context;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Queue;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29 import jakarta.faces.FacesException;
30 import jakarta.faces.application.ProjectStage;
31 import jakarta.faces.component.UIComponent;
32 import jakarta.faces.context.ExceptionHandler;
33 import jakarta.faces.context.ExceptionHandlerWrapper;
34 import jakarta.faces.context.FacesContext;
35 import jakarta.faces.event.AbortProcessingException;
36 import jakarta.faces.event.ExceptionQueuedEvent;
37 import jakarta.faces.event.ExceptionQueuedEventContext;
38 import jakarta.faces.event.SystemEvent;
39 import jakarta.servlet.http.HttpServletResponse;
40
41 import org.apache.myfaces.lifecycle.ViewNotFoundException;
42 import org.apache.myfaces.renderkit.ErrorPageWriter;
43 import org.apache.myfaces.shared.util.WebConfigParamUtils;
44 import org.apache.myfaces.spi.WebConfigProvider;
45 import org.apache.myfaces.spi.WebConfigProviderFactory;
46
47
48
49
50
51
52
53 public class MyFacesExceptionHandlerWrapperImpl extends ExceptionHandlerWrapper
54 {
55 private static final Logger log = Logger.getLogger(MyFacesExceptionHandlerWrapperImpl.class.getName());
56
57 private Queue<ExceptionQueuedEvent> handled;
58 private Queue<ExceptionQueuedEvent> unhandled;
59 private ExceptionQueuedEvent handledAndThrown;
60
61
62 private ExceptionHandler _delegate;
63 private boolean _isErrorPagePresent;
64 private boolean _useMyFacesErrorHandling;
65 private boolean _inited;
66
67 public MyFacesExceptionHandlerWrapperImpl(ExceptionHandler delegate)
68 {
69 this._delegate = delegate;
70 this._inited = false;
71 }
72
73 protected void init()
74 {
75 if (!_inited)
76 {
77 FacesContext facesContext = FacesContext.getCurrentInstance();
78 WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
79 facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
80
81 _isErrorPagePresent = webConfigProvider.isErrorPagePresent(facesContext.getExternalContext());
82 _useMyFacesErrorHandling = WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
83 ErrorPageWriter.ERROR_HANDLING_PARAMETER, facesContext.isProjectStage(ProjectStage.Development));
84 _inited = true;
85 }
86 }
87
88 protected void init(FacesContext facesContext)
89 {
90 if (!_inited)
91 {
92 if (facesContext == null)
93 {
94 facesContext = FacesContext.getCurrentInstance();
95 }
96 WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
97 facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
98
99 _isErrorPagePresent = webConfigProvider.isErrorPagePresent(facesContext.getExternalContext());
100 _useMyFacesErrorHandling = WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
101 ErrorPageWriter.ERROR_HANDLING_PARAMETER, facesContext.isProjectStage(ProjectStage.Development));
102 _inited = true;
103 }
104 }
105
106 protected void init(SystemEvent exceptionQueuedEvent)
107 {
108 if (!_inited)
109 {
110 if (exceptionQueuedEvent instanceof ExceptionQueuedEvent)
111 {
112 ExceptionQueuedEvent eqe = (ExceptionQueuedEvent)exceptionQueuedEvent;
113 ExceptionQueuedEventContext eqec = eqe.getContext();
114 if (eqec != null)
115 {
116 FacesContext facesContext = eqec.getContext();
117 if (facesContext != null)
118 {
119 init(facesContext);
120 return;
121 }
122 }
123 }
124 init(FacesContext.getCurrentInstance());
125 }
126 }
127
128 protected boolean isUseMyFacesErrorHandling()
129 {
130 return _useMyFacesErrorHandling;
131 }
132
133 protected boolean isErrorPagePresent()
134 {
135 return _isErrorPagePresent;
136 }
137
138
139
140
141 @Override
142 public ExceptionQueuedEvent getHandledExceptionQueuedEvent()
143 {
144 init();
145 if (!isUseMyFacesErrorHandling())
146 {
147 return super.getHandledExceptionQueuedEvent();
148 }
149 else
150 {
151 return handledAndThrown;
152 }
153 }
154
155
156
157
158 @Override
159 public Iterable<ExceptionQueuedEvent> getHandledExceptionQueuedEvents()
160 {
161 init();
162 if (!isUseMyFacesErrorHandling())
163 {
164 return super.getHandledExceptionQueuedEvents();
165 }
166 else
167 {
168 return handled == null ? Collections.<ExceptionQueuedEvent>emptyList() : handled;
169 }
170 }
171
172
173
174
175 @Override
176 public Iterable<ExceptionQueuedEvent> getUnhandledExceptionQueuedEvents()
177 {
178 init();
179 if (!isUseMyFacesErrorHandling())
180 {
181 return super.getUnhandledExceptionQueuedEvents();
182 }
183 else
184 {
185 return unhandled == null ? Collections.<ExceptionQueuedEvent>emptyList() : unhandled;
186 }
187 }
188
189
190
191
192 @Override
193 public void handle() throws FacesException
194 {
195 init();
196 if (!isUseMyFacesErrorHandling())
197 {
198 if (isErrorPagePresent())
199 {
200 FacesContext facesContext = FacesContext.getCurrentInstance();
201
202 facesContext.getExternalContext().getRequestMap().put(ErrorPageWriter.VIEW_KEY,
203 facesContext.getViewRoot());
204 }
205 try
206 {
207 super.handle();
208 }
209 catch (FacesException e)
210 {
211 FacesContext facesContext = FacesContext.getCurrentInstance();
212 if (e.getCause() instanceof ViewNotFoundException)
213 {
214 facesContext.getExternalContext().setResponseStatus(HttpServletResponse.SC_NOT_FOUND);
215 }
216 else
217 {
218 facesContext.getExternalContext().setResponseStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
219 }
220 throw e;
221 }
222 return;
223 }
224 else
225 {
226 if (unhandled != null && !unhandled.isEmpty())
227 {
228 if (handled == null)
229 {
230 handled = new LinkedList<ExceptionQueuedEvent>();
231 }
232
233 List<Throwable> throwableList = new ArrayList<Throwable>();
234 List<UIComponent> components = new ArrayList<UIComponent>();
235 FacesContext facesContext = null;
236
237 do
238 {
239
240
241
242 ExceptionQueuedEvent event = unhandled.peek();
243 try
244 {
245
246 ExceptionQueuedEventContext context = event.getContext();
247
248 if (facesContext == null)
249 {
250 facesContext = event.getContext().getContext();
251 }
252
253
254 Throwable exception = context.getException();
255
256
257
258 if (!shouldSkip(exception))
259 {
260
261 handledAndThrown = event;
262
263 Throwable rootCause = getRootCause(exception);
264
265 throwableList.add(rootCause == null ? exception : rootCause);
266 components.add(event.getContext().getComponent());
267
268
269 }
270 else
271 {
272
273
274 log.log(Level.SEVERE, exception.getClass().getName() + " occured while processing " +
275 (context.inBeforePhase() ? "beforePhase() of " :
276 (context.inAfterPhase() ? "afterPhase() of " : "")) +
277 "phase " + context.getPhaseId() + ": " +
278 "UIComponent-ClientId=" +
279 (context.getComponent() != null ?
280 context.getComponent().getClientId(context.getContext()) : "") + ", " +
281 "Message=" + exception.getMessage());
282
283 log.log(Level.SEVERE, exception.getMessage(), exception);
284 }
285 }
286 finally
287 {
288
289
290 handled.add(event);
291 unhandled.remove(event);
292 }
293 } while (!unhandled.isEmpty());
294
295 if (facesContext == null)
296 {
297 facesContext = FacesContext.getCurrentInstance();
298 }
299 if (throwableList.size() == 1)
300 {
301 ErrorPageWriter.handle(facesContext, components, throwableList.get(0));
302 }
303 else if (throwableList.size() > 1)
304 {
305 ErrorPageWriter.handle(facesContext, components,
306 throwableList.toArray(new Throwable[throwableList.size()]));
307 }
308 }
309 }
310 }
311
312
313
314
315 @Override
316 public void processEvent(SystemEvent exceptionQueuedEvent) throws AbortProcessingException
317 {
318 init(exceptionQueuedEvent);
319
320 if (!isUseMyFacesErrorHandling())
321 {
322 super.processEvent(exceptionQueuedEvent);
323 }
324 else
325 {
326 if (unhandled == null)
327 {
328 unhandled = new LinkedList<ExceptionQueuedEvent>();
329 }
330
331 unhandled.add((ExceptionQueuedEvent)exceptionQueuedEvent);
332 }
333 }
334
335 protected Throwable getRethrownException(Throwable exception)
336 {
337
338
339 Throwable toRethrow = getRootCause(exception);
340 if (toRethrow == null)
341 {
342 toRethrow = exception;
343 }
344
345 return toRethrow;
346 }
347
348 protected FacesException wrap(Throwable exception)
349 {
350 if (exception instanceof FacesException)
351 {
352 return (FacesException) exception;
353 }
354 return new FacesException(exception);
355 }
356
357 protected boolean shouldSkip(Throwable exception)
358 {
359 return exception instanceof AbortProcessingException;
360 }
361
362 @Override
363 public ExceptionHandler getWrapped()
364 {
365 return _delegate;
366 }
367 }