View Javadoc

1   package org.eclipse.jetty.continuation;
2   
3   import java.io.IOException;
4   import javax.servlet.Filter;
5   import javax.servlet.FilterChain;
6   import javax.servlet.FilterConfig;
7   import javax.servlet.ServletContext;
8   import javax.servlet.ServletException;
9   import javax.servlet.ServletRequest;
10  import javax.servlet.ServletResponse;
11  
12  
13  
14  /* ------------------------------------------------------------ */
15  /**
16   * <p>ContinuationFilter must be applied to servlet paths that make use of
17   * the asynchronous features provided by {@link Continuation} APIs, but that
18   * are deployed in servlet containers that are neither Jetty (>= 7) nor a
19   * compliant Servlet 3.0 container.</p>
20   * <p>The following init parameters may be used to configure the filter (these are mostly for testing):</p>
21   * <dl>
22   * <dt>debug</dt><dd>Boolean controlling debug output</dd>
23   * <dt>jetty6</dt><dd>Boolean to force use of Jetty 6 continuations</dd>
24   * <dt>faux</dt><dd>Boolean to force use of faux continuations</dd>
25   * </dl>
26   * <p>If the servlet container is not Jetty (either 6 or 7) nor a Servlet 3
27   * container, then "faux" continuations will be used.</p>
28   * <p>Faux continuations will just put the thread that called {@link Continuation#suspend()}
29   * in wait, and will notify that thread when {@link Continuation#resume()} or
30   * {@link Continuation#complete()} is called.</p>
31   * <p>Faux continuations are not threadless continuations (they are "faux" - fake - for this reason)
32   * and as such they will scale less than proper continuations.</p>
33   */
34  public class ContinuationFilter implements Filter
35  {
36      static boolean _initialized;
37      static boolean __debug; // shared debug status
38      private boolean _faux;
39      private boolean _jetty6;
40      private boolean _filtered;
41      ServletContext _context;
42      private boolean _debug;
43  
44      public void init(FilterConfig filterConfig) throws ServletException
45      {
46          boolean jetty_7_or_greater="org.eclipse.jetty.servlet".equals(filterConfig.getClass().getPackage().getName());
47          _context = filterConfig.getServletContext();
48  
49          String param=filterConfig.getInitParameter("debug");
50          _debug=param!=null&&Boolean.parseBoolean(param);
51          if (_debug)
52              __debug=true;
53  
54          param=filterConfig.getInitParameter("jetty6");
55          if (param==null)
56              param=filterConfig.getInitParameter("partial");
57          if (param!=null)
58              _jetty6=Boolean.parseBoolean(param);
59          else
60              _jetty6=ContinuationSupport.__jetty6 && !jetty_7_or_greater;
61  
62          param=filterConfig.getInitParameter("faux");
63          if (param!=null)
64              _faux=Boolean.parseBoolean(param);
65          else
66              _faux=!(jetty_7_or_greater || _jetty6 || _context.getMajorVersion()>=3);
67  
68          _filtered=_faux||_jetty6;
69          if (_debug)
70              _context.log("ContinuationFilter "+
71                      " jetty="+jetty_7_or_greater+
72                      " jetty6="+_jetty6+
73                      " faux="+_faux+
74                      " filtered="+_filtered+
75                      " servlet3="+ContinuationSupport.__servlet3);
76          _initialized=true;
77      }
78  
79      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
80      {
81          if (_filtered)
82          {
83              Continuation c = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
84              FilteredContinuation fc;
85              if (_faux && (c==null || !(c instanceof FauxContinuation)))
86              {
87                  fc = new FauxContinuation(request);
88                  request.setAttribute(Continuation.ATTRIBUTE,fc);
89              }
90              else
91                  fc=(FilteredContinuation)c;
92  
93              boolean complete=false;
94              while (!complete)
95              {
96                  try
97                  {
98                      if (fc==null || (fc).enter(response))
99                          chain.doFilter(request,response);
100                 }
101                 catch (ContinuationThrowable e)
102                 {
103                     debug("faux",e);
104                 }
105                 finally
106                 {
107                     if (fc==null)
108                         fc = (FilteredContinuation) request.getAttribute(Continuation.ATTRIBUTE);
109 
110                     complete=fc==null || (fc).exit();
111                 }
112             }
113         }
114         else
115         {
116             try
117             {
118                 chain.doFilter(request,response);
119             }
120             catch (ContinuationThrowable e)
121             {
122                 debug("caught",e);
123             }
124         }
125     }
126 
127     private void debug(String string)
128     {
129         if (_debug)
130         {
131             _context.log(string);
132         }
133     }
134 
135     private void debug(String string, Throwable th)
136     {
137         if (_debug)
138         {
139             if (th instanceof ContinuationThrowable)
140                 _context.log(string+":"+th);
141             else
142                 _context.log(string,th);
143         }
144     }
145 
146     public void destroy()
147     {
148     }
149 
150     public interface FilteredContinuation extends Continuation
151     {
152         boolean enter(ServletResponse response);
153         boolean exit();
154     }
155 }