1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.context;
21
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import javax.faces.FacesException;
26 import javax.faces.application.FacesMessage;
27 import javax.faces.application.NavigationHandler;
28 import javax.faces.application.ViewExpiredException;
29 import javax.faces.application.ViewHandler;
30 import javax.faces.component.UIViewRoot;
31 import javax.faces.context.ExceptionHandler;
32 import javax.faces.context.ExceptionHandlerWrapper;
33 import javax.faces.context.FacesContext;
34 import javax.faces.event.ExceptionQueuedEvent;
35 import javax.faces.event.ExceptionQueuedEventContext;
36 import javax.faces.event.PhaseId;
37 import javax.faces.event.PreRenderViewEvent;
38 import javax.faces.view.ViewDeclarationLanguage;
39 import javax.servlet.http.HttpServletResponse;
40 import java.io.FileNotFoundException;
41 import java.lang.invoke.MethodHandles;
42 import java.util.Iterator;
43
44 public class TobagoExceptionHandler extends ExceptionHandlerWrapper {
45
46 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
47
48 private ExceptionHandler wrapped;
49
50 public TobagoExceptionHandler(final ExceptionHandler wrapped) {
51 this.wrapped = wrapped;
52 }
53
54 @Override
55 public ExceptionHandler getWrapped() {
56 return wrapped;
57 }
58
59 @Override
60 public void handle() throws FacesException {
61
62 final Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
63 while (iterator.hasNext()) {
64 final ExceptionQueuedEvent event = iterator.next();
65 final ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
66 final Throwable cause = this.getWrapped().getRootCause(context.getException());
67 final FacesContext facesContext = FacesContext.getCurrentInstance();
68 final NavigationHandler nav = facesContext.getApplication().getNavigationHandler();
69
70 if (cause instanceof ViewExpiredException
71 || cause != null && cause.getCause() instanceof ViewExpiredException) {
72 final ViewExpiredException viewExpiredException = (ViewExpiredException)
73 (cause instanceof ViewExpiredException ? cause : cause.getCause());
74 try {
75 facesContext.addMessage(null,
76 new FacesMessage(FacesMessage.SEVERITY_WARN,
77 "The view has been expired!",
78 "Please check the given data or try to start from the beginning."));
79 nav.handleNavigation(facesContext, null, viewExpiredException.getViewId());
80 facesContext.renderResponse();
81 LOG.debug("Handling ViewExpiredException on viewId: {}", viewExpiredException.getViewId());
82 } finally {
83 iterator.remove();
84 }
85 } else {
86 try {
87 final boolean error404 = cause instanceof FileNotFoundException
88 || cause != null && cause.getCause() instanceof FileNotFoundException;
89 final FacesMessage message;
90 if (error404) {
91 message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
92 "The page was not found!",
93 "The requested page was not found!");
94 facesContext.getExternalContext().setResponseStatus(HttpServletResponse.SC_NOT_FOUND);
95 LOG.warn("Handling 404 exception.");
96 } else {
97 message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
98 "An unknown error has occurred!",
99 "An unknown error has occurred!");
100 facesContext.getExternalContext().setResponseStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
101 LOG.warn("Handling 500 exception.", cause);
102 }
103 facesContext.addMessage(null, message);
104 final String viewId = "/tobago/error.xhtml";
105
106
107 if (event.getContext().getPhaseId().getOrdinal() < PhaseId.RENDER_RESPONSE.getOrdinal()) {
108 nav.handleNavigation(facesContext, null, viewId);
109 facesContext.renderResponse();
110 } else {
111 final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
112 response.resetBuffer();
113 final ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
114 final ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(facesContext, viewId);
115 final UIViewRoot viewRoot = viewHandler.createView(facesContext, viewId);
116 vdl.buildView(facesContext, viewRoot);
117 facesContext.getApplication().publishEvent(facesContext, PreRenderViewEvent.class, viewRoot);
118 vdl.renderView(facesContext, viewRoot);
119 facesContext.responseComplete();
120 }
121 } catch (Exception e) {
122 LOG.error("Exception while exception handling!", e);
123 } finally {
124 iterator.remove();
125 }
126 }
127 }
128 getWrapped().handle();
129 }
130 }