/sitebricks/src/main/java/com/google/sitebricks/HiddenMethodFilter.java

http://github.com/dhanji/sitebricks · Java · 96 lines · 58 code · 21 blank · 17 comment · 8 complexity · e7d32580b3b04c5b055df0f84a7ca2ce MD5 · raw file

  1. package com.google.sitebricks;
  2. import com.google.inject.Singleton;
  3. import com.google.sitebricks.rendering.Strings;
  4. import net.jcip.annotations.Immutable;
  5. import javax.servlet.*;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletRequestWrapper;
  8. import java.io.IOException;
  9. import java.util.Locale;
  10. /**
  11. * Enables browsers making a simulated PUT, PATCH and DELETE requests. Currently browsers support making
  12. * GET and POST requests. This {@link javax.servlet.Filter} checks if a hidden field is set and
  13. * renames HTTP method, retrieved via {@link javax.servlet.http.HttpServletRequest#getMethod()} to a method
  14. * set in the hidden field
  15. *
  16. * @author Peter Knego
  17. */
  18. @Immutable
  19. @Singleton
  20. class HiddenMethodFilter implements Filter {
  21. private static final String FILTER_DONE_SUFFIX = "__done";
  22. private static final String HIDDEN_FIELD_NAME = "hiddenFieldName";
  23. /**
  24. * Name of the hidden field. Shared across the entire App. Is guarded by
  25. * init so no danger of visibility issues.
  26. */
  27. static String hiddenFieldName = "__sitebricks__action";
  28. private String filterDoneAttributeName;
  29. public void init(FilterConfig filterConfig) throws ServletException {
  30. String param = filterConfig.getInitParameter(HIDDEN_FIELD_NAME);
  31. if (param != null) {
  32. hiddenFieldName = param;
  33. }
  34. // Request attribute name to signal that filtering was already done in a request
  35. filterDoneAttributeName = hiddenFieldName + FILTER_DONE_SUFFIX;
  36. }
  37. public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
  38. throws IOException, ServletException {
  39. HttpServletRequest httpRequest = (HttpServletRequest) request;
  40. // check if filtering was already done on this request
  41. if (httpRequest.getAttribute(filterDoneAttributeName) != null) {
  42. // Filtering done, forward to another filter in chain
  43. filterChain.doFilter(httpRequest, response);
  44. } else {
  45. httpRequest.setAttribute(filterDoneAttributeName, Boolean.TRUE);
  46. try {
  47. String methodName = httpRequest.getParameter(hiddenFieldName);
  48. if ("POST".equalsIgnoreCase(httpRequest.getMethod()) && !Strings.empty(methodName)) {
  49. String methodNameUppercase = methodName.toUpperCase(Locale.ENGLISH);
  50. HttpServletRequest wrapper = new HttpMethodRequestWrapper(methodNameUppercase, httpRequest);
  51. filterChain.doFilter(wrapper, response);
  52. } else {
  53. // Filtering done, forward to another filter in chain
  54. filterChain.doFilter(httpRequest, response);
  55. }
  56. } finally {
  57. // Remove the filterDone attribute for this request.
  58. request.removeAttribute(filterDoneAttributeName);
  59. }
  60. }
  61. }
  62. public void destroy() {
  63. }
  64. private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
  65. private final String method;
  66. public HttpMethodRequestWrapper(String method, HttpServletRequest request) {
  67. super(request);
  68. this.method = method;
  69. }
  70. @Override
  71. public String getMethod() {
  72. return this.method;
  73. }
  74. }
  75. }