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
28 package org.apache.hc.client5.http.impl.io;
29
30 import java.io.IOException;
31 import java.net.Socket;
32 import java.nio.charset.Charset;
33 import java.nio.charset.CharsetDecoder;
34 import java.nio.charset.CharsetEncoder;
35 import java.nio.charset.CodingErrorAction;
36 import java.util.concurrent.atomic.AtomicLong;
37
38 import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
39 import org.apache.hc.core5.annotation.Contract;
40 import org.apache.hc.core5.annotation.ThreadingBehavior;
41 import org.apache.hc.core5.http.ClassicHttpRequest;
42 import org.apache.hc.core5.http.ClassicHttpResponse;
43 import org.apache.hc.core5.http.ContentLengthStrategy;
44 import org.apache.hc.core5.http.config.CharCodingConfig;
45 import org.apache.hc.core5.http.config.Http1Config;
46 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
47 import org.apache.hc.core5.http.impl.io.DefaultHttpRequestWriterFactory;
48 import org.apache.hc.core5.http.impl.io.NoResponseOutOfOrderStrategy;
49 import org.apache.hc.core5.http.io.HttpConnectionFactory;
50 import org.apache.hc.core5.http.io.HttpMessageParserFactory;
51 import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
52 import org.apache.hc.core5.http.io.ResponseOutOfOrderStrategy;
53
54
55
56
57
58 @Contract(threading = ThreadingBehavior.STATELESS)
59 public class ManagedHttpClientConnectionFactory implements HttpConnectionFactory<ManagedHttpClientConnection> {
60
61 private static final AtomicLong COUNTER = new AtomicLong();
62
63
64
65
66 public static final ManagedHttpClientConnectionFactory INSTANCE = new ManagedHttpClientConnectionFactory();
67
68 private final Http1Config h1Config;
69 private final CharCodingConfig charCodingConfig;
70 private final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
71 private final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
72 private final ContentLengthStrategy incomingContentStrategy;
73 private final ContentLengthStrategy outgoingContentStrategy;
74 private final ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
75
76 private ManagedHttpClientConnectionFactory(
77 final Http1Config h1Config,
78 final CharCodingConfig charCodingConfig,
79 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
80 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
81 final ContentLengthStrategy incomingContentStrategy,
82 final ContentLengthStrategy outgoingContentStrategy,
83 final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
84 this.h1Config = h1Config != null ? h1Config : Http1Config.DEFAULT;
85 this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
86 this.requestWriterFactory = requestWriterFactory != null ? requestWriterFactory :
87 new DefaultHttpRequestWriterFactory(this.h1Config);
88 this.responseParserFactory = responseParserFactory != null ? responseParserFactory :
89 new DefaultHttpResponseParserFactory(this.h1Config);
90 this.incomingContentStrategy = incomingContentStrategy != null ? incomingContentStrategy :
91 DefaultContentLengthStrategy.INSTANCE;
92 this.outgoingContentStrategy = outgoingContentStrategy != null ? outgoingContentStrategy :
93 DefaultContentLengthStrategy.INSTANCE;
94 this.responseOutOfOrderStrategy = responseOutOfOrderStrategy != null ? responseOutOfOrderStrategy :
95 NoResponseOutOfOrderStrategy.INSTANCE;
96 }
97
98 public ManagedHttpClientConnectionFactory(
99 final Http1Config h1Config,
100 final CharCodingConfig charCodingConfig,
101 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
102 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory,
103 final ContentLengthStrategy incomingContentStrategy,
104 final ContentLengthStrategy outgoingContentStrategy) {
105 this(
106 h1Config,
107 charCodingConfig,
108 requestWriterFactory,
109 responseParserFactory,
110 incomingContentStrategy,
111 outgoingContentStrategy,
112 null);
113 }
114
115 public ManagedHttpClientConnectionFactory(
116 final Http1Config h1Config,
117 final CharCodingConfig charCodingConfig,
118 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
119 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
120 this(h1Config, charCodingConfig, requestWriterFactory, responseParserFactory, null, null);
121 }
122
123 public ManagedHttpClientConnectionFactory(
124 final Http1Config h1Config,
125 final CharCodingConfig charCodingConfig,
126 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
127 this(h1Config, charCodingConfig, null, responseParserFactory);
128 }
129
130 public ManagedHttpClientConnectionFactory() {
131 this(null, null, null);
132 }
133
134 @Override
135 public ManagedHttpClientConnection createConnection(final Socket socket) throws IOException {
136 CharsetDecoder charDecoder = null;
137 CharsetEncoder charEncoder = null;
138 final Charset charset = this.charCodingConfig.getCharset();
139 final CodingErrorAction malformedInputAction = this.charCodingConfig.getMalformedInputAction() != null ?
140 this.charCodingConfig.getMalformedInputAction() : CodingErrorAction.REPORT;
141 final CodingErrorAction unmappableInputAction = this.charCodingConfig.getUnmappableInputAction() != null ?
142 this.charCodingConfig.getUnmappableInputAction() : CodingErrorAction.REPORT;
143 if (charset != null) {
144 charDecoder = charset.newDecoder();
145 charDecoder.onMalformedInput(malformedInputAction);
146 charDecoder.onUnmappableCharacter(unmappableInputAction);
147 charEncoder = charset.newEncoder();
148 charEncoder.onMalformedInput(malformedInputAction);
149 charEncoder.onUnmappableCharacter(unmappableInputAction);
150 }
151 final String id = "http-outgoing-" + COUNTER.getAndIncrement();
152 final DefaultManagedHttpClientConnection conn = new DefaultManagedHttpClientConnection(
153 id,
154 charDecoder,
155 charEncoder,
156 h1Config,
157 incomingContentStrategy,
158 outgoingContentStrategy,
159 responseOutOfOrderStrategy,
160 requestWriterFactory,
161 responseParserFactory);
162 if (socket != null) {
163 conn.bind(socket);
164 }
165 return conn;
166 }
167
168
169
170
171
172
173 public static Builder builder() {
174 return new Builder();
175 }
176
177
178
179
180
181
182 public static final class Builder {
183
184 private Http1Config http1Config;
185 private CharCodingConfig charCodingConfig;
186 private ContentLengthStrategy incomingContentLengthStrategy;
187 private ContentLengthStrategy outgoingContentLengthStrategy;
188 private ResponseOutOfOrderStrategy responseOutOfOrderStrategy;
189 private HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory;
190 private HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory;
191
192 private Builder() {}
193
194 public Builder http1Config(final Http1Config http1Config) {
195 this.http1Config = http1Config;
196 return this;
197 }
198
199 public Builder charCodingConfig(final CharCodingConfig charCodingConfig) {
200 this.charCodingConfig = charCodingConfig;
201 return this;
202 }
203
204 public Builder incomingContentLengthStrategy(final ContentLengthStrategy incomingContentLengthStrategy) {
205 this.incomingContentLengthStrategy = incomingContentLengthStrategy;
206 return this;
207 }
208
209 public Builder outgoingContentLengthStrategy(final ContentLengthStrategy outgoingContentLengthStrategy) {
210 this.outgoingContentLengthStrategy = outgoingContentLengthStrategy;
211 return this;
212 }
213
214 public Builder responseOutOfOrderStrategy(final ResponseOutOfOrderStrategy responseOutOfOrderStrategy) {
215 this.responseOutOfOrderStrategy = responseOutOfOrderStrategy;
216 return this;
217 }
218
219 public Builder requestWriterFactory(
220 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory) {
221 this.requestWriterFactory = requestWriterFactory;
222 return this;
223 }
224
225 public Builder responseParserFactory(
226 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
227 this.responseParserFactory = responseParserFactory;
228 return this;
229 }
230
231 public ManagedHttpClientConnectionFactory build() {
232 return new ManagedHttpClientConnectionFactory(
233 http1Config,
234 charCodingConfig,
235 requestWriterFactory,
236 responseParserFactory,
237 incomingContentLengthStrategy,
238 outgoingContentLengthStrategy,
239 responseOutOfOrderStrategy);
240 }
241 }
242 }