001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.autoconfigure.web.servlet.error; 018 019import java.util.ArrayList; 020import java.util.List; 021import java.util.Map; 022 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import org.springframework.boot.web.servlet.error.ErrorAttributes; 027import org.springframework.boot.web.servlet.error.ErrorController; 028import org.springframework.core.annotation.AnnotationAwareOrderComparator; 029import org.springframework.http.HttpStatus; 030import org.springframework.stereotype.Controller; 031import org.springframework.util.Assert; 032import org.springframework.web.context.request.ServletWebRequest; 033import org.springframework.web.context.request.WebRequest; 034import org.springframework.web.servlet.ModelAndView; 035 036/** 037 * Abstract base class for error {@link Controller} implementations. 038 * 039 * @author Dave Syer 040 * @author Phillip Webb 041 * @since 1.3.0 042 * @see ErrorAttributes 043 */ 044public abstract class AbstractErrorController implements ErrorController { 045 046 private final ErrorAttributes errorAttributes; 047 048 private final List<ErrorViewResolver> errorViewResolvers; 049 050 public AbstractErrorController(ErrorAttributes errorAttributes) { 051 this(errorAttributes, null); 052 } 053 054 public AbstractErrorController(ErrorAttributes errorAttributes, 055 List<ErrorViewResolver> errorViewResolvers) { 056 Assert.notNull(errorAttributes, "ErrorAttributes must not be null"); 057 this.errorAttributes = errorAttributes; 058 this.errorViewResolvers = sortErrorViewResolvers(errorViewResolvers); 059 } 060 061 private List<ErrorViewResolver> sortErrorViewResolvers( 062 List<ErrorViewResolver> resolvers) { 063 List<ErrorViewResolver> sorted = new ArrayList<>(); 064 if (resolvers != null) { 065 sorted.addAll(resolvers); 066 AnnotationAwareOrderComparator.sortIfNecessary(sorted); 067 } 068 return sorted; 069 } 070 071 protected Map<String, Object> getErrorAttributes(HttpServletRequest request, 072 boolean includeStackTrace) { 073 WebRequest webRequest = new ServletWebRequest(request); 074 return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace); 075 } 076 077 protected boolean getTraceParameter(HttpServletRequest request) { 078 String parameter = request.getParameter("trace"); 079 if (parameter == null) { 080 return false; 081 } 082 return !"false".equalsIgnoreCase(parameter); 083 } 084 085 protected HttpStatus getStatus(HttpServletRequest request) { 086 Integer statusCode = (Integer) request 087 .getAttribute("javax.servlet.error.status_code"); 088 if (statusCode == null) { 089 return HttpStatus.INTERNAL_SERVER_ERROR; 090 } 091 try { 092 return HttpStatus.valueOf(statusCode); 093 } 094 catch (Exception ex) { 095 return HttpStatus.INTERNAL_SERVER_ERROR; 096 } 097 } 098 099 /** 100 * Resolve any specific error views. By default this method delegates to 101 * {@link ErrorViewResolver ErrorViewResolvers}. 102 * @param request the request 103 * @param response the response 104 * @param status the HTTP status 105 * @param model the suggested model 106 * @return a specific {@link ModelAndView} or {@code null} if the default should be 107 * used 108 * @since 1.4.0 109 */ 110 protected ModelAndView resolveErrorView(HttpServletRequest request, 111 HttpServletResponse response, HttpStatus status, Map<String, Object> model) { 112 for (ErrorViewResolver resolver : this.errorViewResolvers) { 113 ModelAndView modelAndView = resolver.resolveErrorView(request, status, model); 114 if (modelAndView != null) { 115 return modelAndView; 116 } 117 } 118 return null; 119 } 120 121}