PageRenderTime 21ms CodeModel.GetById 10ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

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