View Javadoc
1   package com.atlassian.plugin.servlet.filter;
2   
3   import com.atlassian.plugin.servlet.ServletModuleManager;
4   import com.atlassian.plugin.servlet.util.ServletContextServletModuleManagerAccessor;
5   import org.slf4j.Logger;
6   import org.slf4j.LoggerFactory;
7   
8   import javax.servlet.Filter;
9   import javax.servlet.FilterChain;
10  import javax.servlet.FilterConfig;
11  import javax.servlet.ServletException;
12  import javax.servlet.ServletRequest;
13  import javax.servlet.ServletResponse;
14  import javax.servlet.http.HttpServletRequest;
15  import javax.servlet.http.HttpServletResponse;
16  import java.io.IOException;
17  
18  /**
19   * Applications need to create a concrete subclass of this for use in their filter stack. This filters responsiblity
20   * is to retrieve the filters to be applied to the request from the {@link ServletModuleManager} and build a
21   * {@link FilterChain} from them. Once all the filters in the chain have been applied to the request, this filter
22   * returns control to the main chain.
23   * <p>
24   * There is one init parameters that must be configured for this filter, the "location" parameter. It can be one of
25   * "top", "middle" or "bottom". A filter with a "top" location must appear before the filter with a "middle" location
26   * which must appear before a filter with a "bottom" location. Where any other application filters lie in the filter
27   * stack is completely up to the application.
28   *
29   * @since 2.1.0
30   */
31  public class ServletFilterModuleContainerFilter implements Filter {
32      private static final Logger log = LoggerFactory.getLogger(ServletFilterModuleContainerFilter.class);
33  
34      private FilterConfig filterConfig;
35      private FilterLocation location;
36  
37      public void init(FilterConfig filterConfig) throws ServletException {
38          this.filterConfig = filterConfig;
39          location = FilterLocation.parse(filterConfig.getInitParameter("location"));
40      }
41  
42      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
43          doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
44      }
45  
46      void doFilter(HttpServletRequest request, HttpServletResponse response, final FilterChain chain) throws IOException, ServletException {
47          if (getServletModuleManager() == null) {
48              log.info("Could not get ServletModuleManager. Skipping filter plugins.");
49              chain.doFilter(request, response);
50              return;
51          }
52  
53          final Iterable<Filter> filters = getServletModuleManager().getFilters(location, getUri(request), filterConfig, request.getDispatcherType());
54          FilterChain pluginFilterChain = new IteratingFilterChain(filters.iterator(), chain);
55          pluginFilterChain.doFilter(request, response);
56      }
57  
58      public void destroy() {
59      }
60  
61      /**
62       * Retrieve the DefaultServletModuleManager from your container framework. Uses the {@link com.atlassian.plugin.servlet.util.ServletContextServletModuleManagerAccessor}
63       * by default.
64       */
65      protected ServletModuleManager getServletModuleManager() {
66          return ServletContextServletModuleManagerAccessor.getServletModuleManager(filterConfig.getServletContext());
67      }
68  
69      protected final FilterConfig getFilterConfig() {
70          return filterConfig;
71      }
72  
73      protected final FilterLocation getFilterLocation() {
74          return location;
75      }
76  
77      /**
78       * Gets the uri from the request. Copied from Struts 2.1.0.
79       *
80       * @param request The request
81       * @return The uri
82       */
83      private static String getUri(HttpServletRequest request) {
84          // handle http dispatcher includes.
85          String uri = (String) request
86                  .getAttribute("javax.servlet.include.servlet_path");
87          if (uri != null) {
88              return uri;
89          }
90  
91          uri = getServletPath(request);
92          if (uri != null && !"".equals(uri)) {
93              return uri;
94          }
95  
96          uri = request.getRequestURI();
97          return uri.substring(request.getContextPath().length());
98      }
99  
100     /**
101      * Retrieves the current request servlet path.
102      * Deals with differences between servlet specs (2.2 vs 2.3+).
103      * Copied from Struts 2.1.0.
104      *
105      * @param request the request
106      * @return the servlet path
107      */
108     private static String getServletPath(HttpServletRequest request) {
109         String servletPath = request.getServletPath();
110 
111         String requestUri = request.getRequestURI();
112         // Detecting other characters that the servlet container cut off (like anything after ';')
113         if (requestUri != null && servletPath != null && !requestUri.endsWith(servletPath)) {
114             int pos = requestUri.indexOf(servletPath);
115             if (pos > -1) {
116                 servletPath = requestUri.substring(requestUri.indexOf(servletPath));
117             }
118         }
119 
120         if (null != servletPath && !"".equals(servletPath)) {
121             return servletPath;
122         }
123 
124         int startIndex = request.getContextPath().equals("") ? 0 : request.getContextPath().length();
125         int endIndex = request.getPathInfo() == null ? requestUri.length() : requestUri.lastIndexOf(request.getPathInfo());
126 
127         if (startIndex > endIndex) { // this should not happen
128             endIndex = startIndex;
129         }
130 
131         return requestUri.substring(startIndex, endIndex);
132     }
133 }