All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cattleframework.webmvc.exception.ExceptionHandlerUtils Maven / Gradle / Ivy

There is a newer version: 1.0.1-M3
Show newest version
/*
 * Copyright (C) 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cattleframework.webmvc.exception;

import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.cattleframework.aop.context.SpringContext;
import org.cattleframework.aop.resource.Resource;
import org.cattleframework.exception.CommonException;
import org.cattleframework.exception.CommonResponseRuntimeException;
import org.cattleframework.exception.CommonRuntimeException;
import org.cattleframework.exception.ExceptionConstants;
import org.cattleframework.exception.web.ExceptionProcessCustomizer;
import org.cattleframework.exception.web.ExceptionProcessResponse;
import org.cattleframework.web.WebProperties;
import org.cattleframework.web.WebProperties.ErrorPage;
import org.cattleframework.web.WebProperties.StaticResource;
import org.cattleframework.webmvc.matcher.AntPathRequestMatcher;
import org.cattleframework.webmvc.view.HtmlPageView;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.error.ErrorAttributeOptions.Include;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

class ExceptionHandlerUtils {

    private static final String SEPARATE = "/";

    private static final String PATH = "path";

    private static final String MESSAGE = "message";

    private static final String STATUS = "status";

    private static final String ERROR = "error";

    private static final String EXCEPTION_CODE = "error-code";

    private static final String EXCEPTION_RESPONSE = "response";

    private static final String MESSAGE_STATUS = "success";

    private static final String MESSAGE_SOURCE = "source";

    private static final String SOURCE_OWNER = "cattle";

    public static ModelAndView getExceptionModelAndView(HttpServletRequest request, HttpServletResponse response,
	    ErrorAttributes errorAttributes, WebProperties webProperties, boolean isHtml, boolean pageUseTemplate,
	    ExceptionProcessCustomizer[] exceptionProcessCustomizers) {
	Integer httpStatusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
	Throwable exception = errorAttributes.getError(new ServletWebRequest(request));
	String path = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
	Map exceptionResponseMap = new HashMap(3);
	if (StringUtils.isNotBlank(path)) {
	    exceptionResponseMap.put(PATH, path);
	}
	if (exception != null) {
	    if (exception instanceof UndeclaredThrowableException) {
		exception = exception.getCause();
	    }
	    String message = exception.getMessage();
	    ExceptionProcessCustomizer exceptionProcessCustomizer = null;
	    if (ArrayUtils.isNotEmpty(exceptionProcessCustomizers)) {
		for (ExceptionProcessCustomizer customizer : exceptionProcessCustomizers) {
		    if (classEquals(customizer.getType(), exception)) {
			exceptionProcessCustomizer = customizer;
			break;
		    }
		}
	    }
	    if (exceptionProcessCustomizer != null) {
		Throwable excep = getException(exceptionProcessCustomizer.getType(), exception);
		ExceptionProcessResponse exceptionProcessResponse = exceptionProcessCustomizer.customize(excep);
		Integer tHttpStatusCode = exceptionProcessResponse.getHttpStatusCode();
		String tMessage = exceptionProcessResponse.getMessage();
		if (tHttpStatusCode != null && tHttpStatusCode.intValue() != -1 && tHttpStatusCode.intValue() != 0) {
		    httpStatusCode = tHttpStatusCode;
		}
		if (StringUtils.isNotBlank(tMessage)) {
		    message = tMessage;
		}
	    } else {
		Map cattleExceptionInfo = getCattleExceptionInfo(exception);
		if (MapUtils.isNotEmpty(cattleExceptionInfo)) {
		    if (cattleExceptionInfo.containsKey(EXCEPTION_CODE)) {
			exceptionResponseMap.put(EXCEPTION_CODE, cattleExceptionInfo.get(EXCEPTION_CODE));
		    }
		    if (cattleExceptionInfo.containsKey(MESSAGE)) {
			message = (String) cattleExceptionInfo.get(MESSAGE);
		    }
		    if (cattleExceptionInfo.containsKey(EXCEPTION_RESPONSE)) {
			exceptionResponseMap.put(EXCEPTION_RESPONSE, cattleExceptionInfo.get(EXCEPTION_RESPONSE));
		    }
		}
	    }
	    exceptionResponseMap.put(MESSAGE, message);
	} else {
	    Map errorAttr = errorAttributes.getErrorAttributes(new ServletWebRequest(request),
		    ErrorAttributeOptions.of(Include.MESSAGE));
	    String message = (String) errorAttr.get(MESSAGE);
	    if (StringUtils.isBlank(message)) {
		message = (String) errorAttr.get(ERROR);
	    }
	    if (httpStatusCode == null) {
		httpStatusCode = (Integer) errorAttr.get(STATUS);
	    }
	    exceptionResponseMap.put(MESSAGE, message);
	}
	if (httpStatusCode == null) {
	    httpStatusCode = Integer.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value());
	}
	exceptionResponseMap.put(MESSAGE_STATUS, false);
	response.addHeader(MESSAGE_SOURCE, SOURCE_OWNER);
	ModelAndView modelAndView = null;
	if (isHtml) {
	    modelAndView = processExceptionHtmlView(httpStatusCode, webProperties, pageUseTemplate);
	}
	if (modelAndView == null) {
	    modelAndView = new ModelAndView(new MappingJackson2JsonView());
	}
	modelAndView.addAllObjects(exceptionResponseMap);
	modelAndView.setStatus(HttpStatusCode.valueOf(httpStatusCode));
	return modelAndView;
    }

    private static Throwable getException(Class type, Throwable exception) {
	Class exceptionClass = exception.getClass();
	if (type == exceptionClass || type.isAssignableFrom(exceptionClass)) {
	    return exception;
	} else {
	    Throwable causeException = exception.getCause();
	    if (causeException != null) {
		return getException(type, causeException);
	    }
	}
	return null;
    }

    private static boolean classEquals(Class type, Throwable exception) {
	if (type == null || exception == null) {
	    return false;
	}
	Class exceptionClass = exception.getClass();
	if (type == exceptionClass || type.isAssignableFrom(exceptionClass)) {
	    return true;
	} else {
	    Throwable causeException = exception.getCause();
	    return classEquals(type, causeException);
	}
    }

    private static ModelAndView processExceptionHtmlView(int httpStatusCode, WebProperties webProperties,
	    boolean pageUseTemplate) {
	String page = null;
	ErrorPage errorPage = webProperties.getErrorPage();
	if (MapUtils.isNotEmpty(errorPage.getStatusCodePages())) {
	    page = errorPage.getStatusCodePages().get(Integer.valueOf(httpStatusCode));
	}
	if (StringUtils.isBlank(page)) {
	    page = errorPage.getDefaultPage();
	}
	if (StringUtils.isNotBlank(page) && page.startsWith(SEPARATE)) {
	    page = page.substring(1);
	}
	ModelAndView modelAndView = null;
	if (StringUtils.isNotBlank(page)) {
	    if (CollectionUtils.isNotEmpty(webProperties.getStaticResources())) {
		final String pageLocation = page;
		if (pageUseTemplate) {
		    if (webProperties.getStaticResources().stream()
			    .anyMatch(staticResource -> (pageUseTemplate
				    && ArrayUtils.isNotEmpty(staticResource.getDirectoryLocations())
				    && AntPathRequestMatcher.antMatcher(staticResource.getStaticPathPattern())
					    .matches(pageLocation)
				    && SpringContext.get().getClassResourceLoader().getResource(
					    staticResource.getDirectoryLocations(),
					    pageLocation + webProperties.getTemplateResource().getSuffix()) != null))) {
			modelAndView = new ModelAndView(page);
		    }
		} else {
		    Resource resource = null;
		    for (StaticResource staticResource : webProperties.getStaticResources()) {
			if (ArrayUtils.isNotEmpty(staticResource.getDirectoryLocations()) && AntPathRequestMatcher
				.antMatcher(staticResource.getStaticPathPattern()).matches(pageLocation)) {
			    resource = SpringContext.get().getClassResourceLoader()
				    .getResource(staticResource.getDirectoryLocations(), pageLocation, true);
			    if (resource != null) {
				break;
			    }
			}
		    }
		    if (resource != null) {
			modelAndView = new ModelAndView(new HtmlPageView(resource));
		    }
		}
	    }
	}
	return modelAndView;
    }

    private static Map getCattleExceptionInfo(Throwable e) {
	if (e instanceof CommonResponseRuntimeException) {
	    CommonResponseRuntimeException exception = (CommonResponseRuntimeException) e;
	    Map exceptionInfo = new HashMap(0);
	    if (exception.getCode() != ExceptionConstants.GENERAL) {
		exceptionInfo.put(EXCEPTION_CODE, exception.getCode());
	    }
	    if (StringUtils.isNotBlank(exception.getMessage())) {
		exceptionInfo.put(MESSAGE, exception.getMessage());
	    }
	    if (StringUtils.isNotBlank(exception.getResponse())) {
		exceptionInfo.put(EXCEPTION_RESPONSE, exception.getResponse());
	    }
	    return exceptionInfo;
	} else if (e instanceof CommonRuntimeException) {
	    CommonRuntimeException exception = (CommonRuntimeException) e;
	    Map exceptionInfo = new HashMap(0);
	    if (exception.getCode() != ExceptionConstants.GENERAL) {
		exceptionInfo.put(EXCEPTION_CODE, exception.getCode());
	    }
	    if (StringUtils.isNotBlank(exception.getMessage())) {
		exceptionInfo.put(MESSAGE, exception.getMessage());
	    }
	    return exceptionInfo;
	} else if (e instanceof CommonException) {
	    CommonException exception = (CommonException) e;
	    Map exceptionInfo = new HashMap(0);
	    if (exception.getCode() != ExceptionConstants.GENERAL) {
		exceptionInfo.put(EXCEPTION_CODE, exception.getCode());
	    }
	    if (StringUtils.isNotBlank(exception.getMessage())) {
		exceptionInfo.put(MESSAGE, exception.getMessage());
	    }
	    return exceptionInfo;
	} else {
	    if (e.getCause() != null) {
		return getCattleExceptionInfo(e.getCause());
	    }
	}
	return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy