package com.thirdparty.spring.ex;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.util.WebUtils;
public class SimpleMappingExceptionResolver extends AbstractHandlerExceptionResolver {
private Log logger = LogFactory.getLog(SimpleMappingExceptionResolver.class);
public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception";
private Properties exceptionMappings;
private Class<?>[] excludedExceptions;
private String defaultErrorView;
private Integer defaultStatusCode;
private Map<String, Integer> statusCodes = new HashMap();
private String exceptionAttribute = "exception";
public SimpleMappingExceptionResolver() {
}
public void setExceptionMappings(Properties mappings) {
this.exceptionMappings = mappings;
}
public void setExcludedExceptions(Class... excludedExceptions) {
this.excludedExceptions = excludedExceptions;
}
public void setDefaultErrorView(String defaultErrorView) {
this.defaultErrorView = defaultErrorView;
}
public void setStatusCodes(Properties statusCodes) {
Enumeration enumeration = statusCodes.propertyNames();
while (enumeration.hasMoreElements()) {
String viewName = (String) enumeration.nextElement();
Integer statusCode = new Integer(statusCodes.getProperty(viewName));
this.statusCodes.put(viewName, statusCode);
}
}
public void addStatusCode(String viewName, int statusCode) {
this.statusCodes.put(viewName, Integer.valueOf(statusCode));
}
public Map<String, Integer> getStatusCodesAsMap() {
return Collections.unmodifiableMap(this.statusCodes);
}
public void setDefaultStatusCode(int defaultStatusCode) {
this.defaultStatusCode = Integer.valueOf(defaultStatusCode);
}
public void setExceptionAttribute(String exceptionAttribute) {
this.exceptionAttribute = exceptionAttribute;
}
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
String viewName = this.determineViewName(ex, request);
if (viewName != null) {
Integer statusCode = this.determineStatusCode(request, viewName);
if (statusCode != null) {
this.applyStatusCodeIfPossible(request, response, statusCode.intValue());
}
logger.error(ex.getMessage(), ex); // !!! 打印异常栈信息
return this.getModelAndView(viewName, ex, request);
} else {
return null;
}
}
protected String determineViewName(Exception ex, HttpServletRequest request) {
String viewName = null;
if (this.excludedExceptions != null) {
Class[] var4 = this.excludedExceptions;
int var5 = var4.length;
for (int var6 = 0; var6 < var5; ++var6) {
Class excludedEx = var4[var6];
if (excludedEx.equals(ex.getClass())) {
return null;
}
}
}
if (this.exceptionMappings != null) {
viewName = this.findMatchingViewName(this.exceptionMappings, ex);
}
if (viewName == null && this.defaultErrorView != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Resolving to default view \'" + this.defaultErrorView + "\' for exception of type [" + ex.getClass().getName() + "]");
}
viewName = this.defaultErrorView;
}
return viewName;
}
protected String findMatchingViewName(Properties exceptionMappings, Exception ex) {
String viewName = null;
String dominantMapping = null;
int deepest = 2147483647;
Enumeration names = exceptionMappings.propertyNames();
while (true) {
String exceptionMapping;
int depth;
do {
do {
if (!names.hasMoreElements()) {
if (viewName != null && this.logger.isDebugEnabled()) {
this.logger.debug("Resolving to view \'" + viewName + "\' for exception of type [" + ex.getClass().getName() + "], based on exception mapping [" + dominantMapping + "]");
}
return viewName;
}
exceptionMapping = (String) names.nextElement();
depth = this.getDepth(exceptionMapping, ex);
} while (depth < 0);
}
while (depth >= deepest && (depth != deepest || dominantMapping == null || exceptionMapping.length() <= dominantMapping.length()));
deepest = depth;
dominantMapping = exceptionMapping;
viewName = exceptionMappings.getProperty(exceptionMapping);
}
}
protected int getDepth(String exceptionMapping, Exception ex) {
return this.getDepth(exceptionMapping, ex.getClass(), 0);
}
private int getDepth(String exceptionMapping, Class<?> exceptionClass, int depth) {
return exceptionClass.getName().contains(exceptionMapping) ? depth : (exceptionClass == Throwable.class ? -1 : this.getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1));
}
protected Integer determineStatusCode(HttpServletRequest request, String viewName) {
return this.statusCodes.containsKey(viewName) ? (Integer) this.statusCodes.get(viewName) : this.defaultStatusCode;
}
protected void applyStatusCodeIfPossible(HttpServletRequest request, HttpServletResponse response, int statusCode) {
if (!WebUtils.isIncludeRequest(request)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Applying HTTP status code " + statusCode);
}
response.setStatus(statusCode);
request.setAttribute("javax.servlet.error.status_code", Integer.valueOf(statusCode));
}
}
protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request) {
return this.getModelAndView(viewName, ex);
}
protected ModelAndView getModelAndView(String viewName, Exception ex) {
ModelAndView mv = new ModelAndView(viewName);
if (this.exceptionAttribute != null) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Exposing Exception as model attribute \'" + this.exceptionAttribute + "\'");
}
mv.addObject(this.exceptionAttribute, ex);
}
return mv;
}
}