import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.sql.SQLException;
+
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.InstanceSupport;
+import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.modeler.Registry;
*/
protected static Properties restrictedServlets = null;
+
+ private static Class jspExceptionClazz;
+ static {
+ try {
+ jspExceptionClazz = Class.forName("javax.servlet.jsp.JspException");
+ } catch (ClassNotFoundException e) {
+ // Expected if jsp-api not on classpath, eg when embedding
+ jspExceptionClazz = null;
+ }
+ }
+
+
// ------------------------------------------------------------- Properties
* @param e The servlet exception
*/
public static Throwable getRootCause(ServletException e) {
- Throwable rootCause = e;
- Throwable rootCauseCheck = null;
- // Extra aggressive rootCause finding
- int loops = 0;
- do {
- loops++;
- rootCauseCheck = rootCause.getCause();
- if (rootCauseCheck != null)
- rootCause = rootCauseCheck;
- } while (rootCauseCheck != null && (loops < 20));
- return rootCause;
+ Throwable rootCause = e.getRootCause();
+ return findRootCause(e, rootCause);
}
+ /*
+ * Work through the root causes using specific methods for well known types
+ * and getCause() for the rest. Stop when the next rootCause is null or
+ * an exception is found that has itself as its own rootCause.
+ */
+ private static final Throwable findRootCause(Throwable theException,
+ Throwable theRootCause) {
+
+ Throwable deeperRootCause = null;
+
+ if (theRootCause == null || theRootCause == theException) {
+ return theException;
+ }
+
+ if (theRootCause instanceof ServletException) {
+ deeperRootCause = ((ServletException) theRootCause).getRootCause();
+ } else if (jspExceptionClazz!=null &&
+ jspExceptionClazz.isAssignableFrom(theRootCause.getClass())) {
+ deeperRootCause = (Throwable)IntrospectionUtils.getProperty(
+ theRootCause, "rootCause");
+ } else if (theRootCause instanceof SQLException) {
+ deeperRootCause = ((SQLException) theRootCause).getNextException();
+ }
+ if (deeperRootCause == null) {
+ deeperRootCause = theRootCause.getCause();
+ }
+
+ return findRootCause(theRootCause, deeperRootCause);
+ }
+
+
+
/**
* Refuse to add a child Container, because Wrappers are the lowest level
* of the Container hierarchy.
import java.io.IOException;
import java.io.Writer;
+import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.ServerInfo;
import org.apache.catalina.util.StringManager;
+import org.apache.tomcat.util.IntrospectionUtils;
/**
* <p>Implementation of a Valve that outputs HTML error pages.</p>
StringManager.getManager(Constants.Package);
+ private static Class jspExceptionClazz;
+
+ static {
+ try {
+ jspExceptionClazz = Class.forName("javax.servlet.jsp.JspException");
+ } catch (ClassNotFoundException e) {
+ // Expected if jsp-api not on classpath, eg when embedding
+ jspExceptionClazz = null;
+ }
+ }
+
+
// ------------------------------------------------------------- Properties
sb.append(RequestUtil.filter(stackTrace));
sb.append("</pre></p>");
- int loops = 0;
Throwable rootCause = throwable.getCause();
- while (rootCause != null && (loops < 10)) {
+ Throwable nestedRootCause = null;
+ while (rootCause != null) {
stackTrace = getPartialServletStackTrace(rootCause);
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.rootCause"));
sb.append(RequestUtil.filter(stackTrace));
sb.append("</pre></p>");
// In case root cause is somehow heavily nested
- rootCause = rootCause.getCause();
- loops++;
+ try {
+ if (rootCause instanceof ServletException) {
+ nestedRootCause =
+ ((ServletException) rootCause).getRootCause();
+ } else if (jspExceptionClazz!=null &&
+ jspExceptionClazz.isAssignableFrom(
+ rootCause.getClass())) {
+ nestedRootCause = (Throwable)IntrospectionUtils.
+ getProperty(rootCause, "rootCause");
+ } else if (rootCause instanceof SQLException) {
+ nestedRootCause = ((SQLException) rootCause).
+ getNextException();
+ }
+ if (nestedRootCause == null) {
+ nestedRootCause = rootCause.getCause();
+ }
+
+ if (rootCause == nestedRootCause)
+ rootCause = null;
+ else {
+ rootCause = nestedRootCause;
+ nestedRootCause = null;
+ }
+ } catch (ClassCastException e) {
+ rootCause = null;
+ }
}
-
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.note"));
sb.append("</b> <u>");