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