package am.ik.categolj2.api.error; import am.ik.categolj2.core.logger.LogManager; import am.ik.categolj2.core.web.RemoteAddresses; import am.ik.categolj2.core.web.UserAgents; import org.slf4j.Logger; import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.PessimisticLockingFailureException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.Authentication; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.multipart.MultipartException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import org.terasoluna.gfw.common.exception.BusinessException; import org.terasoluna.gfw.common.exception.ExceptionCodeResolver; import org.terasoluna.gfw.common.exception.ResourceNotFoundException; import org.terasoluna.gfw.common.exception.ResultMessagesNotificationException; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; @ControllerAdvice(basePackages = "am.ik.categolj2.api") public class ApiGlobalExceptionHandler extends ResponseEntityExceptionHandler { private static final Logger logger = LogManager.getLogger(); @Inject ApiErrorCreator apiErrorCreator; @Inject ExceptionCodeResolver exceptionCodeResolver; @Override protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) { final Object apiError; if (body == null) { String errorCode = exceptionCodeResolver.resolveExceptionCode(ex); apiError = apiErrorCreator.createApiError(request, errorCode, ex .getLocalizedMessage()); } else { apiError = body; } return new ResponseEntity<>(apiError, headers, status); } @Override protected ResponseEntity<Object> handleMethodArgumentNotValid( MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { return handleBindingResult(ex, ex.getBindingResult(), headers, status, request); } @Override protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { return handleBindingResult(ex, ex.getBindingResult(), headers, status, request); } private ResponseEntity<Object> handleBindingResult(Exception ex, BindingResult bindingResult, HttpHeaders headers, HttpStatus status, WebRequest request) { String errorCode = exceptionCodeResolver.resolveExceptionCode(ex); ApiError apiError = apiErrorCreator.createBindingResultApiError( request, errorCode, bindingResult, ex.getMessage()); return handleExceptionInternal(ex, apiError, headers, status, request); } @Override protected ResponseEntity<Object> handleHttpMessageNotReadable( HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { if (ex.getCause() instanceof Exception) { return handleExceptionInternal((Exception) ex.getCause(), null, headers, status, request); } else { return handleExceptionInternal(ex, null, headers, status, request); } } @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<Object> handleResourceNotFoundException( ResourceNotFoundException ex, WebRequest request) { return handleResultMessagesNotificationException(ex, null, HttpStatus.NOT_FOUND, request); } @ExceptionHandler(BusinessException.class) public ResponseEntity<Object> handleBusinessException(BusinessException ex, WebRequest request) { return handleResultMessagesNotificationException(ex, null, HttpStatus.CONFLICT, request); } private ResponseEntity<Object> handleResultMessagesNotificationException( ResultMessagesNotificationException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { String errorCode = exceptionCodeResolver.resolveExceptionCode(ex); ApiError apiError = apiErrorCreator.createResultMessagesApiError( request, errorCode, ex.getResultMessages(), ex.getMessage()); return handleExceptionInternal(ex, apiError, headers, status, request); } @ExceptionHandler({OptimisticLockingFailureException.class, PessimisticLockingFailureException.class}) public ResponseEntity<Object> handleLockingFailureException(Exception ex, WebRequest request) { return handleExceptionInternal(ex, null, null, HttpStatus.CONFLICT, request); } @ExceptionHandler(AccessDeniedException.class) public ResponseEntity<Object> handleAccessDeniedException(Exception ex, WebRequest request, HttpServletRequest servletRequest, Authentication authentication) { if (logger.isWarnEnabled()) { logger.warn("Access denied! method={},uri={},query={},principal={},remote={},user-agent={}", servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getQueryString(), authentication == null ? "@@@@" : authentication.getName(), RemoteAddresses.getRemoteAddress(servletRequest), UserAgents.getUserAgent(servletRequest)); } return handleExceptionInternal(ex, null, null, HttpStatus.FORBIDDEN, request); } @ExceptionHandler(MultipartException.class) public ResponseEntity<Object> handleMultipartException(Exception ex, WebRequest request) { return handleExceptionInternal(ex, null, null, HttpStatus.BAD_REQUEST, request); } @ExceptionHandler(Exception.class) public ResponseEntity<Object> handleSystemError(Exception ex, WebRequest request) { return handleExceptionInternal(ex, null, null, HttpStatus.INTERNAL_SERVER_ERROR, request); } }