1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.embedded;
20
21 import java.io.IOException;
22 import java.util.concurrent.atomic.AtomicBoolean;
23
24 import javax.servlet.AsyncContext;
25 import javax.servlet.ReadListener;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletInputStream;
28 import javax.servlet.ServletOutputStream;
29 import javax.servlet.WriteListener;
30 import javax.servlet.http.HttpServlet;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34
35 public class AsyncEchoServlet extends HttpServlet
36 {
37 private static final long serialVersionUID = 1L;
38
39 @Override
40 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
41 {
42 AsyncContext asyncContext = request.startAsync(request, response);
43 asyncContext.setTimeout(0);
44 Echoer echoer = new Echoer(asyncContext);
45 request.getInputStream().setReadListener(echoer);
46 response.getOutputStream().setWriteListener(echoer);
47 }
48
49 private class Echoer implements ReadListener, WriteListener
50 {
51 private final byte[] buffer = new byte[4096];
52 private final AsyncContext asyncContext;
53 private final ServletInputStream input;
54 private final ServletOutputStream output;
55 private final AtomicBoolean complete = new AtomicBoolean(false);
56
57 private Echoer(AsyncContext asyncContext) throws IOException
58 {
59 this.asyncContext = asyncContext;
60 this.input = asyncContext.getRequest().getInputStream();
61 this.output = asyncContext.getResponse().getOutputStream();
62 }
63
64 @Override
65 public void onDataAvailable() throws IOException
66 {
67 handleAsyncIO();
68 }
69
70 @Override
71 public void onAllDataRead() throws IOException
72 {
73 handleAsyncIO();
74 }
75
76 @Override
77 public void onWritePossible() throws IOException
78 {
79 handleAsyncIO();
80 }
81
82 private void handleAsyncIO() throws IOException
83 {
84
85
86
87
88
89
90
91 while (true)
92 {
93 if (!output.isReady())
94
95
96 break;
97
98 if (!input.isReady())
99
100 break;
101
102 int read = input.read(buffer);
103 if (read<0)
104 {
105 if (complete.compareAndSet(false,true))
106 asyncContext.complete();
107 break;
108 }
109 else if (read>0)
110 {
111 output.write(buffer, 0, read);
112 }
113 }
114 }
115
116 @Override
117 public void onError(Throwable failure)
118 {
119 new Throwable("onError",failure).printStackTrace();
120 asyncContext.complete();
121 }
122 }
123 }