View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.continuation.test;
15  
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.net.Socket;
19  import java.util.Timer;
20  import java.util.TimerTask;
21  
22  import javax.servlet.ServletException;
23  import javax.servlet.http.HttpServlet;
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  
27  import junit.framework.TestCase;
28  
29  import org.eclipse.jetty.continuation.Continuation;
30  import org.eclipse.jetty.continuation.ContinuationListener;
31  import org.eclipse.jetty.continuation.ContinuationSupport;
32  
33  
34  
35  public abstract class ContinuationBase extends TestCase
36  {
37      protected SuspendServlet _servlet=new SuspendServlet();
38      protected int _port;
39      
40      protected void doNormal(String type) throws Exception
41      {
42          String response=process(null,null);
43          assertContains(type,response);
44          assertContains("NORMAL",response);
45          assertNotContains("history: onTimeout",response);
46          assertNotContains("history: onComplete",response);
47      }
48  
49      protected void doSleep() throws Exception
50      {
51          String response=process("sleep=200",null);
52          assertContains("SLEPT",response);
53          assertNotContains("history: onTimeout",response);
54          assertNotContains("history: onComplete",response);
55      }
56  
57      protected void doSuspend() throws Exception
58      {
59          String response=process("suspend=200",null);
60          assertContains("TIMEOUT",response);
61          assertContains("history: onTimeout",response);
62          assertContains("history: onComplete",response);
63      }
64  
65      protected void doSuspendWaitResume() throws Exception
66      {
67          String response=process("suspend=200&resume=10",null);
68          assertContains("RESUMED",response);
69          assertNotContains("history: onTimeout",response);
70          assertContains("history: onComplete",response);
71      }
72  
73      protected void doSuspendResume() throws Exception
74      {
75          String response=process("suspend=200&resume=0",null);
76          assertContains("RESUMED",response);
77          assertNotContains("history: onTimeout",response);
78          assertContains("history: onComplete",response);
79      }
80  
81      protected void doSuspendWaitComplete() throws Exception
82      {
83          String response=process("suspend=200&complete=50",null);
84          assertContains("COMPLETED",response);
85          assertContains("history: initial",response);
86          assertNotContains("history: onTimeout",response);
87          assertContains("history: onComplete",response);
88          assertNotContains("history: !initial",response);
89      }
90  
91      protected void doSuspendComplete() throws Exception
92      {
93          String response=process("suspend=200&complete=0",null);
94          assertContains("COMPLETED",response);
95          assertContains("history: initial",response);
96          assertNotContains("history: onTimeout",response);
97          assertContains("history: onComplete",response);
98          assertNotContains("history: !initial",response);
99      }
100 
101     protected void doSuspendWaitResumeSuspendWaitResume() throws Exception
102     {
103         String response=process("suspend=1000&resume=10&suspend2=1000&resume2=10",null);
104         assertEquals(2,count(response,"history: suspend"));
105         assertEquals(2,count(response,"history: resume"));
106         assertEquals(0,count(response,"history: onTimeout"));
107         assertEquals(1,count(response,"history: onComplete"));
108         assertContains("RESUMED",response);
109     }
110     
111     protected void doSuspendWaitResumeSuspendComplete() throws Exception
112     {
113         String response=process("suspend=1000&resume=10&suspend2=1000&complete2=10",null);
114         assertEquals(2,count(response,"history: suspend"));
115         assertEquals(1,count(response,"history: resume"));
116         assertEquals(0,count(response,"history: onTimeout"));
117         assertEquals(1,count(response,"history: onComplete"));
118         assertContains("COMPLETED",response);
119     }
120 
121     protected void doSuspendWaitResumeSuspend() throws Exception
122     {
123         String response=process("suspend=1000&resume=10&suspend2=10",null);
124         assertEquals(2,count(response,"history: suspend"));
125         assertEquals(1,count(response,"history: resume"));
126         assertEquals(1,count(response,"history: onTimeout"));
127         assertEquals(1,count(response,"history: onComplete"));
128         assertContains("TIMEOUT",response);
129     }
130 
131     protected void doSuspendTimeoutSuspendResume() throws Exception
132     {
133         String response=process("suspend=10&suspend2=1000&resume2=10",null);
134         assertEquals(2,count(response,"history: suspend"));
135         assertEquals(1,count(response,"history: resume"));
136         assertEquals(1,count(response,"history: onTimeout"));
137         assertEquals(1,count(response,"history: onComplete"));
138         assertContains("RESUMED",response);
139     }
140 
141     protected void doSuspendTimeoutSuspendComplete() throws Exception
142     {
143         String response=process("suspend=10&suspend2=1000&complete2=10",null);
144         assertEquals(2,count(response,"history: suspend"));
145         assertEquals(0,count(response,"history: resume"));
146         assertEquals(1,count(response,"history: onTimeout"));
147         assertEquals(1,count(response,"history: onComplete"));
148         assertContains("COMPLETED",response);
149     }
150 
151     protected void doSuspendTimeoutSuspend() throws Exception
152     {
153         String response=process("suspend=10&suspend2=10",null);
154         assertEquals(2,count(response,"history: suspend"));
155         assertEquals(0,count(response,"history: resume"));
156         assertEquals(2,count(response,"history: onTimeout"));
157         assertEquals(1,count(response,"history: onComplete"));
158         assertContains("TIMEOUT",response);
159     }
160 
161     protected void doSuspendThrowResume() throws Exception
162     {
163         String response=process("suspend=200&resume=10&undispatch=true",null);
164         assertContains("RESUMED",response);
165         assertNotContains("history: onTimeout",response);
166         assertContains("history: onComplete",response);
167     }
168 
169     protected void doSuspendResumeThrow() throws Exception
170     {
171         String response=process("suspend=200&resume=0&undispatch=true",null);
172         assertContains("RESUMED",response);
173         assertNotContains("history: onTimeout",response);
174         assertContains("history: onComplete",response);
175     }
176 
177     protected void doSuspendThrowComplete() throws Exception
178     {
179         String response=process("suspend=200&complete=10&undispatch=true",null);
180         assertContains("COMPLETED",response);
181         assertNotContains("history: onTimeout",response);
182         assertContains("history: onComplete",response);
183     }
184 
185     protected void doSuspendCompleteThrow() throws Exception
186     {
187         String response=process("suspend=200&complete=0&undispatch=true",null);
188         assertContains("COMPLETED",response);
189         assertNotContains("history: onTimeout",response);
190         assertContains("history: onComplete",response);
191     }
192 
193     
194     private int count(String responses,String substring)
195     {
196         int count=0;
197         int i=responses.indexOf(substring);
198         while (i>=0)
199         {
200             count++;
201             i=responses.indexOf(substring,i+substring.length());
202         }
203         
204         return count;
205     }
206     
207     protected void assertContains(String content,String response)
208     {
209         assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
210         if (response.indexOf(content,15)<0)
211         {
212             System.err.println("'"+content+"' NOT IN:\n"+response+"\n--");
213             assertTrue(false);
214         }
215     }
216     
217     protected void assertNotContains(String content,String response)
218     {
219         assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
220         if (response.indexOf(content,15)>=0)
221         {
222             System.err.println("'"+content+"' IS IN:\n"+response+"'\n--");
223             assertTrue(false);
224         }
225     }
226     
227     public synchronized String process(String query,String content) throws Exception
228     {
229         String request = "GET /";
230         
231         if (query!=null)
232             request+="?"+query;
233         request+=" HTTP/1.1\r\n"+
234         "Host: localhost\r\n"+
235         "Connection: close\r\n";
236         if (content!=null)
237             request+="Content-Length: "+content.length()+"\r\n";
238         request+="\r\n" + content;
239         
240         int port=_port;
241         String response=null;
242         try
243         {
244             Socket socket = new Socket("localhost",port);
245             socket.getOutputStream().write(request.getBytes("UTF-8"));
246 
247             response = toString(socket.getInputStream());
248         }
249         catch(Exception e)
250         {
251             System.err.println("failed on port "+port);
252             e.printStackTrace();
253             throw e;
254         }
255         return response;
256     }
257     
258     
259     protected abstract String toString(InputStream in) throws IOException;
260     
261     
262     private static class SuspendServlet extends HttpServlet
263     {
264         private Timer _timer=new Timer();
265         
266         public SuspendServlet()
267         {}
268         
269         /* ------------------------------------------------------------ */
270         protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
271         {
272             final Continuation continuation = ContinuationSupport.getContinuation(request);
273 
274             response.addHeader("history",continuation.getClass().toString());
275             
276             int read_before=0;
277             long sleep_for=-1;
278             long suspend_for=-1;
279             long suspend2_for=-1;
280             long resume_after=-1;
281             long resume2_after=-1;
282             long complete_after=-1;
283             long complete2_after=-1;
284             boolean undispatch=false;
285             
286             if (request.getParameter("read")!=null)
287                 read_before=Integer.parseInt(request.getParameter("read"));
288             if (request.getParameter("sleep")!=null)
289                 sleep_for=Integer.parseInt(request.getParameter("sleep"));
290             if (request.getParameter("suspend")!=null)
291                 suspend_for=Integer.parseInt(request.getParameter("suspend"));
292             if (request.getParameter("suspend2")!=null)
293                 suspend2_for=Integer.parseInt(request.getParameter("suspend2"));
294             if (request.getParameter("resume")!=null)
295                 resume_after=Integer.parseInt(request.getParameter("resume"));
296             if (request.getParameter("resume2")!=null)
297                 resume2_after=Integer.parseInt(request.getParameter("resume2"));
298             if (request.getParameter("complete")!=null)
299                 complete_after=Integer.parseInt(request.getParameter("complete"));
300             if (request.getParameter("complete2")!=null)
301                 complete2_after=Integer.parseInt(request.getParameter("complete2"));
302             if (request.getParameter("undispatch")!=null)
303                 undispatch=Boolean.parseBoolean(request.getParameter("undispatch"));
304             
305             if (continuation.isInitial())
306             {
307                 ((HttpServletResponse)response).addHeader("history","initial");
308                 if (read_before>0)
309                 {
310                     byte[] buf=new byte[read_before];
311                     request.getInputStream().read(buf);
312                 }
313                 else if (read_before<0)
314                 {
315                     InputStream in = request.getInputStream();
316                     int b=in.read();
317                     while(b!=-1)
318                         b=in.read();
319                 }
320 
321                 if (suspend_for>=0)
322                 {
323                     if (suspend_for>0)
324                         continuation.setTimeout(suspend_for);
325                     continuation.addContinuationListener(__listener);
326                     ((HttpServletResponse)response).addHeader("history","suspend");
327                     continuation.suspend(response);
328                     
329                     if (complete_after>0)
330                     {
331                         TimerTask complete = new TimerTask()
332                         {
333                             @Override
334                             public void run()
335                             {
336                                 try
337                                 {
338                                     response.setStatus(200);
339                                     response.getOutputStream().println("COMPLETED\n");
340                                     continuation.complete();
341                                 }
342                                 catch(Exception e)
343                                 {
344                                     e.printStackTrace();
345                                 }
346                             }
347                         };
348                         synchronized (_timer)
349                         {
350                             _timer.schedule(complete,complete_after);
351                         }
352                     }
353                     else if (complete_after==0)
354                     {
355                         response.setStatus(200);
356                         response.getOutputStream().println("COMPLETED\n");
357                         continuation.complete();
358                     }
359                     else if (resume_after>0)
360                     {
361                         TimerTask resume = new TimerTask()
362                         {
363                             @Override
364                             public void run()
365                             {
366                                 ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
367                                 continuation.resume();
368                             }
369                         };
370                         synchronized (_timer)
371                         {
372                             _timer.schedule(resume,resume_after);
373                         }
374                     }
375                     else if (resume_after==0)
376                     {
377                         ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
378                         continuation.resume();
379                     }
380                     
381                     if (undispatch)
382                         continuation.undispatch();
383                 }
384                 else if (sleep_for>=0)
385                 {
386                     try
387                     {
388                         Thread.sleep(sleep_for);
389                     }
390                     catch (InterruptedException e)
391                     {
392                         e.printStackTrace();
393                     }
394                     response.setStatus(200);
395                     response.getOutputStream().println("SLEPT\n");
396                 }
397                 else
398                 {
399                     response.setStatus(200);
400                     response.getOutputStream().println("NORMAL\n");
401                 }
402             }
403             else    
404             {
405                 ((HttpServletResponse)response).addHeader("history","!initial");
406                 if (suspend2_for>=0 && request.getAttribute("2nd")==null)
407                 {
408                     request.setAttribute("2nd","cycle");
409 
410                     if (suspend2_for>0)
411                         continuation.setTimeout(suspend2_for);
412                     // continuation.addContinuationListener(__listener);
413                     ((HttpServletResponse)response).addHeader("history","suspend");
414                     continuation.suspend(response);
415 
416                     if (complete2_after>0)
417                     {
418                         TimerTask complete = new TimerTask()
419                         {
420                             @Override
421                             public void run()
422                             {
423                                 try
424                                 {
425                                     response.setStatus(200);
426                                     response.getOutputStream().println("COMPLETED\n");
427                                     continuation.complete();
428                                 }
429                                 catch(Exception e)
430                                 {
431                                     e.printStackTrace();
432                                 }
433                             }
434                         };
435                         synchronized (_timer)
436                         {
437                             _timer.schedule(complete,complete2_after);
438                         }
439                     }
440                     else if (complete2_after==0)
441                     {
442                         response.setStatus(200);
443                         response.getOutputStream().println("COMPLETED\n");
444                         continuation.complete();
445                     }
446                     else if (resume2_after>0)
447                     {
448                         TimerTask resume = new TimerTask()
449                         {
450                             @Override
451                             public void run()
452                             {
453                                 ((HttpServletResponse)response).addHeader("history","resume");
454                                 continuation.resume();
455                             }
456                         };
457                         synchronized (_timer)
458                         {
459                             _timer.schedule(resume,resume2_after);
460                         }
461                     }
462                     else if (resume2_after==0)
463                     {
464                         ((HttpServletResponse)response).addHeader("history","resume");
465                         continuation.resume();
466                     }
467                     if (undispatch)
468                         continuation.undispatch();
469                     return;
470                 }
471                 else if (continuation.isExpired())
472                 {
473                     response.setStatus(200);
474                     response.getOutputStream().println("TIMEOUT\n");
475                 }
476                 else if (continuation.isResumed())
477                 {
478                     response.setStatus(200);
479                     response.getOutputStream().println("RESUMED\n");
480                 }
481                 else 
482                 {
483                     response.setStatus(200);
484                     response.getOutputStream().println("unknown???\n");
485                 }
486             }
487         }
488     }
489     
490     
491     private static ContinuationListener __listener = new ContinuationListener()
492     {
493         public void onComplete(Continuation continuation)
494         {
495             ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onComplete");
496         }
497 
498         public void onTimeout(Continuation continuation)
499         {
500             ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onTimeout");
501             continuation.resume();
502         }
503         
504     };
505 }