package org.fenixedu.bennu.core.servlet; import java.io.IOException; import java.util.Objects; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Filter that catches any exception thrown by the application, allowing a configured handler to deal with it. * * @author João Carvalho (joao.pedro.carvalho@tecnico.ulisboa.pt) * */ public class ExceptionHandlerFilter implements Filter { /** * An {@link ExceptionHandler} is invoked whenever an uncaught exception is thrown by the application, giving it an * opportunity to recover gracefully. */ public static interface ExceptionHandler { /** * Attempts to handle the exception thrown by the application. * * @param request * The request that caused the exception * @param response * The response object * @param throwable * The exception that was thrown by the application * @return * Whether the handler was able to handle the exception. If not, the exception is re-thrown, leaving its handling * to the container. * @throws ServletException * If an exception occurs while handling the original exception * @throws IOException * If an exception occurs while handling the original exception */ public boolean handle(ServletRequest request, ServletResponse response, Throwable throwable) throws ServletException, IOException; } /** * Registers the given {@link ExceptionHandler} as this application's exception handler * * @param handler the {@link ExceptionHandler} instance to register * @throws NullPointerException if the provided handler is null */ public static void setExceptionHandler(ExceptionHandler handler) { exceptionHandler = Objects.requireNonNull(handler); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); } catch (Throwable throwable) { if (!exceptionHandler.handle(request, response, throwable)) { // Re-throw the exception to the container if the handler cannot handle it throw throwable; } } } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } private static ExceptionHandler exceptionHandler = (req, resp, t) -> false; }