1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.testing.nio;
28
29 import java.io.IOException;
30 import java.nio.ByteBuffer;
31 import java.util.List;
32
33 import org.apache.hc.core5.http.EntityDetails;
34 import org.apache.hc.core5.http.Header;
35 import org.apache.hc.core5.http.HttpException;
36 import org.apache.hc.core5.http.HttpRequest;
37 import org.apache.hc.core5.http.HttpResponse;
38 import org.apache.hc.core5.http.HttpStatus;
39 import org.apache.hc.core5.http.message.BasicHttpResponse;
40 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
41 import org.apache.hc.core5.http.nio.CapacityChannel;
42 import org.apache.hc.core5.http.nio.DataStreamChannel;
43 import org.apache.hc.core5.http.nio.ResponseChannel;
44 import org.apache.hc.core5.http.protocol.HttpContext;
45
46 public class EchoHandler implements AsyncServerExchangeHandler {
47
48 private volatile ByteBuffer buffer;
49 private volatile CapacityChannel inputCapacityChannel;
50 private volatile DataStreamChannel outputDataChannel;
51 private volatile boolean endStream;
52
53 public EchoHandler(final int bufferSize) {
54 this.buffer = ByteBuffer.allocate(bufferSize);
55 }
56
57 private void ensureCapacity(final int chunk) {
58 if (buffer.remaining() < chunk) {
59 final ByteBuffer oldBuffer = buffer;
60 oldBuffer.flip();
61 buffer = ByteBuffer.allocate(oldBuffer.remaining() + (chunk > 2048 ? chunk : 2048));
62 buffer.put(oldBuffer);
63 }
64 }
65
66 @Override
67 public void handleRequest(
68 final HttpRequest request,
69 final EntityDetails entityDetails,
70 final ResponseChannel responseChannel,
71 final HttpContext context) throws HttpException, IOException {
72 final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK);
73 responseChannel.sendResponse(response, entityDetails, context);
74 }
75
76 @Override
77 public void consume(final ByteBuffer src) throws IOException {
78 if (buffer.position() == 0) {
79 if (outputDataChannel != null) {
80 outputDataChannel.write(src);
81 }
82 }
83 if (src.hasRemaining()) {
84 ensureCapacity(src.remaining());
85 buffer.put(src);
86 if (outputDataChannel != null) {
87 outputDataChannel.requestOutput();
88 }
89 }
90 }
91
92 @Override
93 public void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
94 if (buffer.hasRemaining()) {
95 capacityChannel.update(buffer.remaining());
96 inputCapacityChannel = null;
97 } else {
98 inputCapacityChannel = capacityChannel;
99 }
100 }
101
102 @Override
103 public void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
104 endStream = true;
105 if (buffer.position() == 0) {
106 if (outputDataChannel != null) {
107 outputDataChannel.endStream();
108 }
109 } else {
110 if (outputDataChannel != null) {
111 outputDataChannel.requestOutput();
112 }
113 }
114 }
115
116 @Override
117 public int available() {
118 return buffer.position();
119 }
120
121 @Override
122 public void produce(final DataStreamChannel channel) throws IOException {
123 outputDataChannel = channel;
124 buffer.flip();
125 if (buffer.hasRemaining()) {
126 channel.write(buffer);
127 }
128 buffer.compact();
129 if (buffer.position() == 0 && endStream) {
130 channel.endStream();
131 }
132 final CapacityChannel capacityChannel = inputCapacityChannel;
133 if (capacityChannel != null && buffer.hasRemaining()) {
134 capacityChannel.update(buffer.remaining());
135 }
136 }
137
138 @Override
139 public void failed(final Exception cause) {
140 }
141
142 @Override
143 public void releaseResources() {
144 }
145
146 }