View Javadoc
1   /*
2    * Copyright 2018-2022 Medical Information Systems Research Group (https://medical.zcu.cz),
3    * Department of Computer Science and Engineering, University of West Bohemia.
4    * Address: Univerzitni 8, 306 14 Plzen, Czech Republic.
5    *
6    * Author Petr Vcelak (vcelak@kiv.zcu.cz).
7    *
8    * This file is part of MRECore project.
9    *
10   * MRECore is free software: you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation, either version 3 of the License.
13   *
14   * MRECore is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with MRECore. If not, see <http://www.gnu.org/licenses/>.
21   */
22  package cz.zcu.mre.controller;
23  
24  import java.text.MessageFormat;
25  import jakarta.servlet.http.HttpServletRequest;
26  import jakarta.servlet.http.HttpServletResponse;
27  import org.springframework.http.HttpStatus;
28  import org.springframework.stereotype.Controller;
29  import org.springframework.ui.Model;
30  import org.springframework.web.bind.annotation.RequestMapping;
31  import java.security.Principal;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  import org.springframework.security.access.AccessDeniedException;
35  import org.springframework.web.bind.annotation.ControllerAdvice;
36  import org.springframework.web.bind.annotation.ExceptionHandler;
37  import org.springframework.web.bind.annotation.ResponseStatus;
38  
39  /**
40   * 
41   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
42   */
43  @Controller
44  @ControllerAdvice
45  public class ErrorController {
46  
47      private static final Logger LOG = LoggerFactory.getLogger(ErrorController.class);
48  
49      public static final String ERROR_ACCESS_DENIED = "/error/accessDenied";
50      public static final String ERROR_GENERAL = "error/general";
51  
52      @ExceptionHandler(value = AccessDeniedException.class)
53      @RequestMapping(value = "/securityAccessDenied")
54      @ResponseStatus(HttpStatus.FORBIDDEN)
55      public String errorAccessDeniedException(HttpServletRequest request) {
56  
57          LOG.info("Handling AccessDeniedException for user {} and request {}", request.getRemoteUser(), request.getRequestURL());
58  
59          return ERROR_ACCESS_DENIED;
60      }
61  
62      /**
63       * Display an error page, as defined in web.xml <code>custom-error</code>
64       * element.
65       *
66       * @param principal The principal.
67       * @param request The request.
68       * @param response The response.
69       * @param throwable Throwable.
70       * @param exception Exception.
71       * @param model The model.
72       * @return String name of the view.
73       */
74      @RequestMapping("generalError")
75      @ExceptionHandler(Throwable.class)
76      @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
77      public String generalError(Principal principal, HttpServletRequest request, HttpServletResponse response,
78              final Throwable throwable, final Exception exception, Model model) {
79  
80          // servlet name
81          String servletName = (String) request.getAttribute("jakarta.servlet.error.servlet_name");
82          if (servletName == null) {
83              servletName = "Unknown";
84          }
85  
86          // get status code
87          Integer statusCode = (Integer) request.getAttribute("jakarta.servlet.error.status_code");
88  
89          // check reqeust uri
90          String requestUri = (String) request.getAttribute("jakarta.servlet.error.request_uri");
91          if (requestUri == null) {
92              requestUri = "Unknown";
93          }
94  
95          // check throwable argument
96          String exceptionMessage = null;
97          if (throwable != null) {
98              exceptionMessage = throwable.getMessage();
99          }
100 
101         // check throwable from the request
102         Throwable throwableByRequest = (Throwable) request.getAttribute("jakarta.servlet.error.exception");
103         if (throwableByRequest != null && exceptionMessage == null) {
104             exceptionMessage = throwableByRequest.getMessage();
105         }
106 
107         // check exception from the argument
108         if (exception != null && exceptionMessage == null) {
109             exceptionMessage = exception.getMessage();
110         }
111 
112         // use HTTP Status reason if exceptionMessage is still null
113         if (exceptionMessage == null) {
114             HttpStatus httpStatus = HttpStatus.valueOf(statusCode);
115             exceptionMessage = httpStatus.getReasonPhrase();
116         }
117 
118         String errorMessage = MessageFormat.format("Status {0} returned for {1} with message {2}", statusCode, requestUri, exceptionMessage);
119         LOG.error("Exception: {}", errorMessage, exception);
120         model.addAttribute("servletName", servletName);
121         model.addAttribute("httpStatus", HttpStatus.valueOf(statusCode));
122         model.addAttribute("statusCode", statusCode);
123         model.addAttribute("requestUri", requestUri);
124         model.addAttribute("exceptionMessage", exceptionMessage);
125         model.addAttribute("errorMessage", errorMessage);
126 
127         return ERROR_GENERAL;
128     }
129 
130 }