View Javadoc

1   package com.atlassian.johnson.filters;
2   
3   import com.atlassian.johnson.Johnson;
4   import com.atlassian.johnson.JohnsonEventContainer;
5   import com.atlassian.johnson.config.JohnsonConfig;
6   import com.atlassian.johnson.event.Event;
7   import com.atlassian.johnson.event.RequestEventCheck;
8   import com.atlassian.johnson.setup.SetupConfig;
9   import org.apache.commons.lang.StringUtils;
10  
11  import javax.servlet.*;
12  import javax.servlet.http.HttpServletRequest;
13  import javax.servlet.http.HttpServletResponse;
14  import java.io.IOException;
15  import java.util.Collection;
16  
17  /**
18   * Base class for handling error cases where the application is unavailable to handle normal requests.
19   */
20  public abstract class AbstractJohnsonFilter implements Filter
21  {
22      protected static final String TEXT_XML_UTF8_CONTENT_TYPE = "text/xml;charset=utf-8";
23  
24      protected FilterConfig filterConfig;
25      protected JohnsonConfig config;
26  
27      /**
28       * This filter checks to see if there are any application consistency errors before any pages are accessed. If there are errors then a redirect to the errors page is made
29       */
30      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
31      {
32          String alreadyFilteredKey = getClass().getName() + "_already_filtered";
33          if (servletRequest.getAttribute(alreadyFilteredKey) != null)
34          {
35              filterChain.doFilter(servletRequest, servletResponse);
36              return;
37          }
38          else
39          {
40              servletRequest.setAttribute(alreadyFilteredKey, Boolean.TRUE);
41          }
42  
43          HttpServletRequest request = (HttpServletRequest) servletRequest;
44          HttpServletResponse response = (HttpServletResponse) servletResponse;
45  
46          //get the URI of this request
47          String servletPath = getServletPath(request);
48  
49          //Get the container for this context and run all of the configured request event checks
50          JohnsonEventContainer appEventContainer = getContainerAndRunEventChecks(request);
51  
52          SetupConfig setup = config.getSetupConfig();
53  
54          //if there are application consistency events then redirect to the errors page
55          boolean ignoreUri = ignoreURI(servletPath);
56          if (appEventContainer.hasEvents() && !ignoreUri)
57          {
58              handleError(appEventContainer, request, response);
59          }
60          //if application is not setup then send to the Setup Page
61          else if (!ignoreUri && !setup.isSetup() && !setup.isSetupPage(servletPath))
62          {
63              handleNotSetup(request, response);
64          }
65          else
66          {
67              filterChain.doFilter(servletRequest, servletResponse);
68          }
69      }
70  
71      public void destroy()
72      {
73      }
74  
75      public void init(FilterConfig filterConfig)
76      {
77          this.filterConfig = filterConfig;
78  
79          config = Johnson.getConfig();
80      }
81  
82      protected JohnsonEventContainer getContainerAndRunEventChecks(HttpServletRequest req)
83      {
84          //Get the container for this context
85          JohnsonEventContainer appEventContainer = Johnson.getEventContainer(filterConfig.getServletContext());
86          // run all of the configured request event checks
87          for (RequestEventCheck requestEventCheck : config.getRequestEventChecks())
88          {
89              requestEventCheck.check(appEventContainer, req);
90          }
91          return appEventContainer;
92      }
93  
94      /**
95       * Retrieves the current request servlet path. Deals with differences between servlet specs (2.2 vs 2.3+)
96       *
97       * Taken from the Webwork RequestUtils class
98       *
99       * @param request the request
100      * @return the servlet path
101      */
102     protected static String getServletPath(HttpServletRequest request)
103     {
104         String servletPath = request.getServletPath();
105         if (StringUtils.isNotEmpty(servletPath))
106         {
107             return servletPath;
108         }
109 
110         String requestUri = request.getRequestURI();
111         int startIndex = request.getContextPath().equals("") ? 0 : request.getContextPath().length();
112         int endIndex = request.getPathInfo() == null ? requestUri.length() : requestUri.lastIndexOf(request.getPathInfo());
113         if (startIndex > endIndex)
114         {
115             // this should not happen
116             endIndex = startIndex;
117         }
118 
119         return requestUri.substring(startIndex, endIndex);
120     }
121 
122     protected String getStringForEvents(Collection<Event> events)
123     {
124         StringBuilder message = new StringBuilder();
125         for (Event event : events)
126         {
127             if (message.length() > 0)
128             {
129                 message.append("\n");
130             }
131             message.append(event.getDesc());
132         }
133         return message.toString();
134     }
135 
136     /**
137      * Handles the given request for error cases when there is a Johnson {@link com.atlassian.johnson.event.Event} which
138      * stops normal application functioning.
139      * @param appEventContainer the JohnsonEventContainer that contains the events.
140      * @param servletRequest the request being directed to the error.
141      * @param servletResponse the response.
142      * @throws IOException when the error cannot be handled.
143      */
144     protected abstract void handleError(JohnsonEventContainer appEventContainer, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException;
145 
146     /**
147      * Handles the given request for cases when the application is not yet setup which
148      * stops normal application functioning.
149      * @param servletRequest the request being directed to the error.
150      * @param servletResponse the response.
151      * @throws IOException when the error cannot be handled.
152      */
153     protected abstract void handleNotSetup(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException;
154 
155     protected boolean ignoreURI(String uri)
156     {
157         return uri.equalsIgnoreCase(config.getErrorPath()) || config.isIgnoredPath(uri);
158     }
159 }