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 }
169
170 @Override
171 public void close(final CloseMode closeMode) {
172 if (this.closed.compareAndSet(false, true)) {
173 if (LOG.isDebugEnabled()) {
174 LOG.debug("{} close connection {}", this.id, closeMode);
175 }
176 super.close(closeMode);
177 }
178 }
179
180 @Override
181 public void bind(final Socket socket) throws IOException {
182 super.bind(WIRE_LOG.isDebugEnabled() ? new LoggingSocketHolder(socket, this.id, WIRE_LOG) : new SocketHolder(socket));
183 socketTimeout = Timeout.ofMilliseconds(socket.getSoTimeout());
184 }
185
186 @Override
187 protected void onResponseReceived(final ClassicHttpResponse response) {
188 if (response != null && HEADER_LOG.isDebugEnabled()) {
189 HEADER_LOG.debug("{} << {}", this.id, new StatusLine(response));
190 final Header[] headers = response.getHeaders();
191 for (final Header header : headers) {
192 HEADER_LOG.debug("{} << {}", this.id, header);
193 }
194 }
195 }
196
197 @Override
198 protected void onRequestSubmitted(final ClassicHttpRequest request) {
199 if (request != null && HEADER_LOG.isDebugEnabled()) {
200 HEADER_LOG.debug("{} >> {}", this.id, new RequestLine(request));
201 final Header[] headers = request.getHeaders();
202 for (final Header header : headers) {
203 HEADER_LOG.debug("{} >> {}", this.id, header);
204 }
205 }
206 }
207
208 @Override
209 public void passivate() {
210 super.setSocketTimeout(Timeout.ZERO_MILLISECONDS);
211 }
212
213 @Override
214 public void activate() {
215 super.setSocketTimeout(socketTimeout);
216 }
217
218 }