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.http.nio.support;
28
29 import java.io.IOException;
30 import java.nio.ByteBuffer;
31 import java.util.List;
32 import java.util.concurrent.atomic.AtomicReference;
33
34 import org.apache.hc.core5.function.Callback;
35 import org.apache.hc.core5.http.EntityDetails;
36 import org.apache.hc.core5.http.Header;
37 import org.apache.hc.core5.http.HeaderElements;
38 import org.apache.hc.core5.http.HttpException;
39 import org.apache.hc.core5.http.HttpHeaders;
40 import org.apache.hc.core5.http.HttpRequest;
41 import org.apache.hc.core5.http.HttpStatus;
42 import org.apache.hc.core5.http.message.BasicHttpResponse;
43 import org.apache.hc.core5.http.nio.AsyncResponseProducer;
44 import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
45 import org.apache.hc.core5.http.nio.CapacityChannel;
46 import org.apache.hc.core5.http.nio.DataStreamChannel;
47 import org.apache.hc.core5.http.nio.ResponseChannel;
48 import org.apache.hc.core5.http.protocol.HttpContext;
49 import org.apache.hc.core5.util.Args;
50
51
52
53
54
55
56
57
58 public class BasicAsyncServerExpectationDecorator implements AsyncServerExchangeHandler {
59
60 private final AsyncServerExchangeHandler handler;
61 private final Callback<Exception> exceptionCallback;
62 private final AtomicReference<AsyncResponseProducer> responseProducerRef;
63
64 public BasicAsyncServerExpectationDecorator(final AsyncServerExchangeHandler handler,
65 final Callback<Exception> exceptionCallback) {
66 this.handler = Args.notNull(handler, "Handler");
67 this.exceptionCallback = exceptionCallback;
68 this.responseProducerRef = new AtomicReference<>();
69 }
70
71 public BasicAsyncServerExpectationDecorator(final AsyncServerExchangeHandler handler) {
72 this(handler, null);
73 }
74
75 protected AsyncResponseProducer verify(
76 final HttpRequest request,
77 final HttpContext context) throws IOException, HttpException {
78 return null;
79 }
80
81 @Override
82 public final void handleRequest(
83 final HttpRequest request,
84 final EntityDetails entityDetails,
85 final ResponseChannel responseChannel,
86 final HttpContext context) throws HttpException, IOException {
87 if (entityDetails != null) {
88 final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
89 if (h != null && HeaderElements.CONTINUE.equalsIgnoreCase(h.getValue())) {
90 final AsyncResponseProducer producer = verify(request, context);
91 if (producer != null) {
92 responseProducerRef.set(producer);
93 producer.sendResponse(responseChannel, context);
94 return;
95 }
96 responseChannel.sendInformation(new BasicHttpResponse(HttpStatus.SC_CONTINUE), context);
97 }
98 }
99 handler.handleRequest(request, entityDetails, responseChannel, context);
100 }
101
102 @Override
103 public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
104 final AsyncResponseProducer responseProducer = responseProducerRef.get();
105 if (responseProducer == null) {
106 handler.updateCapacity(capacityChannel);
107 } else {
108 capacityChannel.update(Integer.MAX_VALUE);
109 }
110 }
111
112 @Override
113 public final void consume(final ByteBuffer src) throws IOException {
114 final AsyncResponseProducer responseProducer = responseProducerRef.get();
115 if (responseProducer == null) {
116 handler.consume(src);
117 }
118 }
119
120 @Override
121 public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
122 final AsyncResponseProducer responseProducer = responseProducerRef.get();
123 if (responseProducer == null) {
124 handler.streamEnd(trailers);
125 }
126 }
127
128 @Override
129 public final int available() {
130 final AsyncResponseProducer responseProducer = responseProducerRef.get();
131 return responseProducer == null ? handler.available() : responseProducer.available();
132 }
133
134 @Override
135 public final void produce(final DataStreamChannel channel) throws IOException {
136 final AsyncResponseProducer responseProducer = responseProducerRef.get();
137 if (responseProducer == null) {
138 handler.produce(channel);
139 } else {
140 responseProducer.produce(channel);
141 }
142 }
143
144 @Override
145 public final void failed(final Exception cause) {
146 if (exceptionCallback != null) {
147 exceptionCallback.execute(cause);
148 }
149 final AsyncResponseProducer dataProducer = responseProducerRef.get();
150 if (dataProducer == null) {
151 handler.failed(cause);
152 } else {
153 dataProducer.failed(cause);
154 }
155 }
156
157 @Override
158 public final void releaseResources() {
159 handler.releaseResources();
160 final AsyncResponseProducer dataProducer = responseProducerRef.getAndSet(null);
161 if (dataProducer != null) {
162 dataProducer.releaseResources();
163 }
164 }
165
166 }