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.io.InterruptedIOException;
32 import java.net.Socket;
33 import java.nio.charset.CharsetDecoder;
34 import java.nio.charset.CharsetEncoder;
35 import java.util.concurrent.atomic.AtomicBoolean;
36
37 import javax.net.ssl.SSLSession;
38 import javax.net.ssl.SSLSocket;
39
40 import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
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.Header;
45 import org.apache.hc.core5.http.config.Http1Config;
46 import org.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection;
47 import org.apache.hc.core5.http.impl.io.SocketHolder;
48 import org.apache.hc.core5.http.io.HttpMessageParserFactory;
49 import org.apache.hc.core5.http.io.HttpMessageWriterFactory;
50 import org.apache.hc.core5.http.io.ResponseOutOfOrderStrategy;
51 import org.apache.hc.core5.http.message.RequestLine;
52 import org.apache.hc.core5.http.message.StatusLine;
53 import org.apache.hc.core5.io.CloseMode;
54 import org.apache.hc.core5.util.Identifiable;
55 import org.apache.hc.core5.util.Timeout;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 final class DefaultManagedHttpClientConnection
60 extends DefaultBHttpClientConnection implements ManagedHttpClientConnection, Identifiable {
61
62 private static final Logger LOG = LoggerFactory.getLogger(DefaultManagedHttpClientConnection.class);
63 private static final Logger HEADER_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http.headers");
64 private static final Logger WIRE_LOG = LoggerFactory.getLogger("org.apache.hc.client5.http.wire");
65
66 private final String id;
67 private final AtomicBoolean closed;
68
69 private Timeout socketTimeout;
70
71 public DefaultManagedHttpClientConnection(
72 final String id,
73 final CharsetDecoder charDecoder,
74 final CharsetEncoder charEncoder,
75 final Http1Config h1Config,
76 final ContentLengthStrategy incomingContentStrategy,
77 final ContentLengthStrategy outgoingContentStrategy,
78 final ResponseOutOfOrderStrategy responseOutOfOrderStrategy,
79 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
80 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
81 super(
82 h1Config,
83 charDecoder,
84 charEncoder,
85 incomingContentStrategy,
86 outgoingContentStrategy,
87 responseOutOfOrderStrategy,
88 requestWriterFactory,
89 responseParserFactory);
90 this.id = id;
91 this.closed = new AtomicBoolean();
92 }
93
94 public DefaultManagedHttpClientConnection(
95 final String id,
96 final CharsetDecoder charDecoder,
97 final CharsetEncoder charEncoder,
98 final Http1Config h1Config,
99 final ContentLengthStrategy incomingContentStrategy,
100 final ContentLengthStrategy outgoingContentStrategy,
101 final HttpMessageWriterFactory<ClassicHttpRequest> requestWriterFactory,
102 final HttpMessageParserFactory<ClassicHttpResponse> responseParserFactory) {
103 this(
104 id,
105 charDecoder,
106 charEncoder,
107 h1Config,
108 incomingContentStrategy,
109 outgoingContentStrategy,
110 null,
111 requestWriterFactory,
112 responseParserFactory);
113 }
114
115 public DefaultManagedHttpClientConnection(final String id) {
116 this(id, null, null, null, null, null, null, null);
117 }
118
119 @Override
120 public String getId() {
121 return this.id;
122 }
123
124 @Override
125 public void bind(final SocketHolder socketHolder) throws IOException {
126 if (this.closed.get()) {
127 final Socket socket = socketHolder.getSocket();
128 socket.close();
129
130 throw new InterruptedIOException("Connection already shutdown");
131 }
132 super.bind(socketHolder);
133 socketTimeout = Timeout.ofMilliseconds(socketHolder.getSocket().getSoTimeout());
134 }
135
136 @Override
137 public Socket getSocket() {
138 final SocketHolder socketHolder = getSocketHolder();
139 return socketHolder != null ? socketHolder.getSocket() : null;
140 }
141
142 @Override
143 public SSLSession getSSLSession() {
144 final Socket socket = getSocket();
145 if (socket instanceof SSLSocket) {
146 return ((SSLSocket) socket).getSession();
147 } else {
148 return null;
149 }
150 }
151
152 @Override
153 public void close() throws IOException {
154 if (this.closed.compareAndSet(false, true)) {
155 if (LOG.isDebugEnabled()) {
156 LOG.debug("{} Close connection", this.id);
157 }
158 super.close();
159 }
160 }
161
162 @Override
163 public void setSocketTimeout(final Timeout timeout) {
164 if (LOG.isDebugEnabled()) {
165 LOG.debug("{} set socket timeout to {}", this.id, timeout);
166 }
167 super.setSocketTimeout(timeout);
168 socketTimeout = timeout;
169 }
170
171 @Override
172 public void close(final CloseMode closeMode) {
173 if (this.closed.compareAndSet(false, true)) {
174 if (LOG.isDebugEnabled()) {
175 LOG.debug("{} close connection {}", this.id, closeMode);
176 }
177 super.close(closeMode);
178 }
179 }
180
181 @Override
182 public void bind(final Socket socket) throws IOException {
183 super.bind(WIRE_LOG.isDebugEnabled() ? new LoggingSocketHolder(socket, this.id, WIRE_LOG) : new SocketHolder(socket));
184 socketTimeout = Timeout.ofMilliseconds(socket.getSoTimeout());
185 }
186
187 @Override
188 protected void onResponseReceived(final ClassicHttpResponse response) {
189 if (response != null && HEADER_LOG.isDebugEnabled()) {
190 HEADER_LOG.debug("{} << {}", this.id, new StatusLine(response));
191 final Header[] headers = response.getHeaders();
192 for (final Header header : headers) {
193 HEADER_LOG.debug("{} << {}", this.id, header);
194 }
195 }
196 }
197
198 @Override
199 protected void onRequestSubmitted(final ClassicHttpRequest request) {
200 if (request != null && HEADER_LOG.isDebugEnabled()) {
201 HEADER_LOG.debug("{} >> {}", this.id, new RequestLine(request));
202 final Header[] headers = request.getHeaders();
203 for (final Header header : headers) {
204 HEADER_LOG.debug("{} >> {}", this.id, header);
205 }
206 }
207 }
208
209 @Override
210 public void passivate() {
211 super.setSocketTimeout(Timeout.ZERO_MILLISECONDS);
212 }
213
214 @Override
215 public void activate() {
216 super.setSocketTimeout(socketTimeout);
217 }
218
219 }