View Javadoc

1   package org.eclipse.jetty.continuation;
2   
3   import java.io.IOException;
4   
5   import javax.servlet.AsyncContext;
6   import javax.servlet.AsyncEvent;
7   import javax.servlet.AsyncListener;
8   import javax.servlet.DispatcherType;
9   import javax.servlet.ServletRequest;
10  import javax.servlet.ServletResponse;
11  import javax.servlet.ServletResponseWrapper;
12  
13  
14  
15  /* ------------------------------------------------------------ */
16  /**
17   * This implementation of Continuation is used by {@link ContinuationSupport}
18   * when it detects that the application has been deployed in a non-jetty Servlet 3 
19   * server.
20   */
21  public class Servlet3Continuation implements Continuation
22  {
23      // Exception reused for all continuations
24      // Turn on debug in ContinuationFilter to see real stack trace.
25      private final static ContinuationThrowable __exception = new ContinuationThrowable();
26      
27      private final ServletRequest _request;
28      private ServletResponse _response;
29      private AsyncContext _context;
30      private final AsyncListener _listener = new AsyncListener()
31      {
32          public void onComplete(AsyncEvent event) throws IOException
33          {
34          }
35  
36          public void onTimeout(AsyncEvent event) throws IOException
37          {
38              _initial=false;
39          }
40      };
41  
42      private volatile boolean _initial=true;
43      private volatile boolean _resumed=false;
44      private volatile boolean _expired=false;
45      private volatile boolean _responseWrapped=false;
46      
47      public Servlet3Continuation(ServletRequest request)
48      {
49          _request=request;
50      }
51      
52  
53      public void addContinuationListener(final ContinuationListener listener)
54      {
55          _request.addAsyncListener(new AsyncListener()
56          {
57              public void onComplete(final AsyncEvent event) throws IOException
58              {
59                  listener.onComplete(Servlet3Continuation.this);
60              }
61  
62              public void onTimeout(AsyncEvent event) throws IOException
63              {
64                  _expired=true;
65                  listener.onTimeout(Servlet3Continuation.this);
66              }
67          });
68      }
69  
70      public void complete()
71      {
72          AsyncContext context=_context;
73          if (context==null)
74              throw new IllegalStateException();
75          _context.complete();
76      }
77  
78      public ServletResponse getServletResponse()
79      {
80          return _response;
81      }
82  
83      public boolean isExpired()
84      {
85          return _expired;
86      }
87  
88      public boolean isInitial()
89      {
90          // TODO - this is not perfect if non continuation API is used directly
91          return _initial&&_request.getDispatcherType()!=DispatcherType.ASYNC;
92      }
93  
94      public boolean isResumed()
95      {
96          return _resumed;
97      }
98  
99      public boolean isSuspended()
100     {
101         return _request.isAsyncStarted();
102     }
103 
104     public void keepWrappers()
105     {
106         _responseWrapped=true;
107     }
108 
109     public void resume()
110     {
111         AsyncContext context=_context;
112         if (context==null)
113             throw new IllegalStateException();
114         _resumed=true;
115         _context.dispatch();
116     }
117 
118     public void setTimeout(long timeoutMs)
119     {
120         _request.setAsyncTimeout(timeoutMs);
121     }
122 
123     public void suspend(ServletResponse response)
124     {
125         _response=response;
126         _responseWrapped=response instanceof ServletResponseWrapper;
127         _request.addAsyncListener(_listener);
128         _resumed=false;
129         _expired=false;
130         _context=_request.startAsync();
131     }
132 
133     public void suspend()
134     {
135         _request.addAsyncListener(_listener);
136         _resumed=false;
137         _expired=false;
138         _context=_request.startAsync();
139     }
140 
141     public boolean isResponseWrapped()
142     {
143         return _responseWrapped;
144     }
145 
146 
147     /* ------------------------------------------------------------ */
148     /**
149      * @see org.eclipse.jetty.continuation.Continuation#getAttribute(java.lang.String)
150      */
151     public Object getAttribute(String name)
152     {
153         return _request.getAttribute(name);
154     }
155 
156 
157     /* ------------------------------------------------------------ */
158     /**
159      * @see org.eclipse.jetty.continuation.Continuation#removeAttribute(java.lang.String)
160      */
161     public void removeAttribute(String name)
162     {
163         _request.removeAttribute(name);
164     }
165 
166     /* ------------------------------------------------------------ */
167     /**
168      * @see org.eclipse.jetty.continuation.Continuation#setAttribute(java.lang.String, java.lang.Object)
169      */
170     public void setAttribute(String name, Object attribute)
171     {
172         _request.setAttribute(name,attribute);
173     }
174 
175 
176     /* ------------------------------------------------------------ */
177     /**
178      * @see org.eclipse.jetty.continuation.Continuation#undispatch()
179      */
180     public void undispatch()
181     {
182         if (isSuspended())
183         {
184             if (ContinuationFilter.__debug)
185                 throw new ContinuationThrowable();
186             throw __exception;
187         }
188         throw new IllegalStateException("!suspended");
189     }
190 }