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