1 16 17 package org.springframework.web.servlet.handler; 18 19 import java.util.Enumeration ; 20 import java.util.Properties ; 21 import java.util.Set ; 22 23 import javax.servlet.http.HttpServletRequest ; 24 import javax.servlet.http.HttpServletResponse ; 25 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 29 import org.springframework.core.Ordered; 30 import org.springframework.web.servlet.HandlerExceptionResolver; 31 import org.springframework.web.servlet.ModelAndView; 32 import org.springframework.web.util.WebUtils; 33 34 47 public class SimpleMappingExceptionResolver implements HandlerExceptionResolver, Ordered { 48 49 52 public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception"; 53 54 55 56 protected final Log logger = LogFactory.getLog(getClass()); 57 58 private int order = Integer.MAX_VALUE; 60 private Set mappedHandlers; 61 62 private Log warnLogger; 63 64 private Properties exceptionMappings; 65 66 private String defaultErrorView; 67 68 private Integer defaultStatusCode; 69 70 private String exceptionAttribute = DEFAULT_EXCEPTION_ATTRIBUTE; 71 72 73 public void setOrder(int order) { 74 this.order = order; 75 } 76 77 public int getOrder() { 78 return this.order; 79 } 80 81 90 public void setMappedHandlers(Set mappedHandlers) { 91 this.mappedHandlers = mappedHandlers; 92 } 93 94 105 public void setWarnLogCategory(String loggerName) { 106 this.warnLogger = LogFactory.getLog(loggerName); 107 } 108 109 127 public void setExceptionMappings(Properties mappings) { 128 this.exceptionMappings = mappings; 129 } 130 131 136 public void setDefaultErrorView(String defaultErrorView) { 137 this.defaultErrorView = defaultErrorView; 138 } 139 140 153 public void setDefaultStatusCode(int defaultStatusCode) { 154 this.defaultStatusCode = new Integer (defaultStatusCode); 155 } 156 157 164 public void setExceptionAttribute(String exceptionAttribute) { 165 this.exceptionAttribute = exceptionAttribute; 166 } 167 168 169 public ModelAndView resolveException( 170 HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 171 172 if (this.mappedHandlers != null && !this.mappedHandlers.contains(handler)) { 174 return null; 175 } 176 177 if (logger.isDebugEnabled()) { 179 logger.debug("Resolving exception from handler [" + handler + "]: " + ex); 180 } 181 logException(ex, request); 182 183 String viewName = determineViewName(ex, request); 185 if (viewName != null) { 186 Integer statusCode = determineStatusCode(request, viewName); 189 if (statusCode != null) { 190 applyStatusCodeIfPossible(request, response, statusCode.intValue()); 191 } 192 return getModelAndView(viewName, ex, request); 193 } 194 else { 195 return null; 196 } 197 } 198 199 200 211 protected void logException(Exception ex, HttpServletRequest request) { 212 if (this.warnLogger != null && this.warnLogger.isWarnEnabled()) { 213 this.warnLogger.warn(buildLogMessage(ex, request), ex); 214 } 215 } 216 217 224 protected String buildLogMessage(Exception ex, HttpServletRequest request) { 225 return "Handler execution resulted in exception"; 226 } 227 228 229 237 protected String determineViewName(Exception ex, HttpServletRequest request) { 238 String viewName = null; 239 if (this.exceptionMappings != null) { 241 viewName = findMatchingViewName(this.exceptionMappings, ex); 242 } 243 if (viewName == null && this.defaultErrorView != null) { 245 if (logger.isDebugEnabled()) { 246 logger.debug("Resolving to default view '" + this.defaultErrorView + 247 "' for exception of type [" + ex.getClass().getName() + "]"); 248 } 249 viewName = this.defaultErrorView; 250 } 251 return viewName; 252 } 253 254 261 protected String findMatchingViewName(Properties exceptionMappings, Exception ex) { 262 String viewName = null; 263 String dominantMapping = null; 264 int deepest = Integer.MAX_VALUE; 265 for (Enumeration names = exceptionMappings.propertyNames(); names.hasMoreElements();) { 266 String exceptionMapping = (String ) names.nextElement(); 267 int depth = getDepth(exceptionMapping, ex); 268 if (depth >= 0 && depth < deepest) { 269 deepest = depth; 270 dominantMapping = exceptionMapping; 271 viewName = exceptionMappings.getProperty(exceptionMapping); 272 } 273 } 274 if (viewName != null && logger.isDebugEnabled()) { 275 logger.debug("Resolving to view '" + viewName + "' for exception of type [" + ex.getClass().getName() + 276 "], based on exception mapping [" + dominantMapping + "]"); 277 } 278 return viewName; 279 } 280 281 288 protected int getDepth(String exceptionMapping, Exception ex) { 289 return getDepth(exceptionMapping, ex.getClass(), 0); 290 } 291 292 private int getDepth(String exceptionMapping, Class exceptionClass, int depth) { 293 if (exceptionClass.getName().indexOf(exceptionMapping) != -1) { 294 return depth; 296 } 297 if (exceptionClass.equals(Throwable .class)) { 299 return -1; 300 } 301 return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1); 302 } 303 304 305 318 protected Integer determineStatusCode(HttpServletRequest request, String viewName) { 319 return this.defaultStatusCode; 320 } 321 322 332 protected void applyStatusCodeIfPossible(HttpServletRequest request, HttpServletResponse response, int statusCode) { 333 if (!WebUtils.isIncludeRequest(request)) { 334 if (logger.isDebugEnabled()) { 335 logger.debug("Applying HTTP status code " + statusCode); 336 } 337 response.setStatus(statusCode); 338 } 339 } 340 341 349 protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request) { 350 return getModelAndView(viewName, ex); 351 } 352 353 362 protected ModelAndView getModelAndView(String viewName, Exception ex) { 363 ModelAndView mv = new ModelAndView(viewName); 364 if (this.exceptionAttribute != null) { 365 if (logger.isDebugEnabled()) { 366 logger.debug("Exposing Exception as model attribute '" + this.exceptionAttribute + "'"); 367 } 368 mv.addObject(this.exceptionAttribute, ex); 369 } 370 return mv; 371 } 372 373 } 374 | Popular Tags |