Resolving HTTP-status-codes explicitly to specialized error-pages
[maven-thymeleaf-skin] / src / main / java / de / juplo / thymeproxy / ExceptionResolverErrorController.java
index 6315100..7339ddf 100644 (file)
@@ -4,6 +4,7 @@ package de.juplo.thymeproxy;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -23,6 +24,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.core.annotation.AnnotationAwareOrderComparator;
 import org.springframework.core.io.ClassPathResource;
 import org.springframework.core.io.support.PropertiesLoaderUtils;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.util.ClassUtils;
 import org.springframework.util.StringUtils;
@@ -52,8 +54,8 @@ public class ExceptionResolverErrorController extends BasicErrorController
    */
   private static final String DEFAULT_STRATEGIES_PATH =
       "DispatcherServlet.properties";
-  private static final Properties DEFAULT_STRATEGIES;
 
+  private static final Properties DEFAULT_STRATEGIES;
   static
   {
     // Load default strategy implementations from properties file.
@@ -78,6 +80,12 @@ public class ExceptionResolverErrorController extends BasicErrorController
   }
 
 
+  /** Name of the default-error-view */
+  private String defaultErrorView = "error";
+
+  /** Mapping from HTTP-status-codes to specialized error-pages */
+  private Map<HttpStatus, String> errorMappings = new HashMap<>();
+
   /** List of HandlerExceptionResolvers used by this servlet */
   private List<HandlerExceptionResolver> handlerExceptionResolvers;
 
@@ -135,7 +143,20 @@ public class ExceptionResolverErrorController extends BasicErrorController
       }
     }
 
-    return new ModelAndView("error", model);
+    String viewName = null;
+    Integer code = (Integer)model.get("status");
+    try
+    {
+      HttpStatus status = HttpStatus.valueOf(code);
+      viewName = errorMappings.get(status);
+    }
+    catch(Throwable t)
+    {
+      LOG.warn("cannot map status-code {}: {}", code, t.getMessage());
+    }
+    if (viewName == null)
+      viewName = defaultErrorView;
+    return new ModelAndView(viewName, model);
   }
 
 
@@ -280,6 +301,52 @@ public class ExceptionResolverErrorController extends BasicErrorController
   }
 
 
+  /**
+   * @
+   * @see #addErrorMapping(HttpStatus, String)
+   */
+  public String addErrorMapping(Integer status, String viewName)
+  {
+    if (status == null)
+      throw new IllegalArgumentException("The status must not be null");
+    return addErrorMapping(HttpStatus.valueOf(status), viewName);
+  }
+
+  /**
+   * Adds a mapping from a {@link HttpStatus} to a view.
+   * 
+   * @param status The {@link HttpStatus}, that should be mapped.
+   * @param viewName The name of the view, the status should be mapped to. 
+   * @return The name of the view, the status was previously mapped to, or
+   * <code>null</code>, if the status was not mapped before.
+   */
+  public String addErrorMapping(HttpStatus status, String viewName)
+  {
+    if (!StringUtils.hasText(viewName))
+      throw new IllegalArgumentException("The view-name must not be empty!");
+    if (status == null)
+      throw new IllegalArgumentException("The status must not be null!");
+    return errorMappings.put(status, viewName);
+  }
+
+  /**
+   * Sets mappings from {@link HttpStatus} to specialized error-views.
+   * @param mappings The mappings to set.
+   */
+  public void setErrorMappings(Map<HttpStatus, String> mappings)
+  {
+    errorMappings = mappings;
+  }
+
+  /**
+   * Sets the default error-view for not-mapped status-codes.
+   * @param view The default error-view to set.
+   */
+  public void setDefaultErrorView(String view)
+  {
+    defaultErrorView = view;
+  }
+
   /**
    * Set whether to detect all HandlerExceptionResolver beans in this servlet's
    * context. Otherwise,