package hudson.init.impl;
import hudson.init.Initializer;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.WebApp;
import org.kohsuke.stapler.compression.CompressionFilter;
import org.kohsuke.stapler.compression.UncaughtExceptionHandler;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.kohsuke.stapler.Stapler;
/**
* @author Kohsuke Kawaguchi
*/
public class InstallUncaughtExceptionHandler {
@Initializer
public static void init(final Jenkins j) throws IOException {
CompressionFilter.setUncaughtExceptionHandler(j.servletContext, new UncaughtExceptionHandler() {
@Override
public void reportException(Throwable e, ServletContext context, HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException {
req.setAttribute("javax.servlet.error.exception",e);
try {
WebApp.get(j.servletContext).getSomeStapler()
.invoke(req,rsp, Jenkins.getInstance(), "/oops");
} catch (ServletException | IOException x) {
if (!Stapler.isSocketException(x)) {
throw x;
}
}
}
});
try {
Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler());
DefaultUncaughtExceptionHandler.LOGGER.log(Level.FINE, "Successfully installed a global UncaughtExceptionHandler.");
}
catch (SecurityException ex) {
DefaultUncaughtExceptionHandler.LOGGER.log(Level.SEVERE,
"Failed to set the default UncaughtExceptionHandler. " +
"If any threads die due to unhandled coding errors then there will be no logging of this information. " +
"The lack of this diagnostic information will make it harder to track down issues which will reduce the supportability of Jenkins. " +
"It is highly recomended that you consult the documentation that comes with you servlet container on how to allow the " +
"`setDefaultUncaughtExceptionHandler` permission and enable it.", ex);
}
}
/** An UncaughtExceptionHandler that just logs the exception */
private static class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private static final Logger LOGGER = Logger.getLogger(InstallUncaughtExceptionHandler.class.getName());
@Override
public void uncaughtException(Thread t, Throwable ex) {
// if this was an OutOfMemoryError then all bets about logging are off - but in the absence of anything else...
LOGGER.log(Level.SEVERE,
"A thread (" + t.getName() + '/' + t.getId()
+ ") died unexpectedly due to an uncaught exception, this may leave your Jenkins in a bad way and is usually indicative of a bug in the code.",
ex);
}
}
}