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 }
148 return null;
149 }
150
151 @Override
152 public void close() throws IOException {
153 if (this.closed.compareAndSet(false, true)) {
154 if (LOG.isDebugEnabled()) {
155 LOG.debug("{} Close connection", this.id);
156 }
157 super.close();
158 }
159 }
160
161 @Override
162 public void setSocketTimeout(final Timeout timeout) {
163 if (LOG.isDebugEnabled()) {
164 LOG.debug("{} set socket timeout to {}", this.id, timeout);
165 }
166 super.setSocketTimeout(timeout);
167 socketTimeout = 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 public void bind(final SSLSocket sslSocket, final Socket socket) throws IOException {
188 super.bind(WIRE_LOG.isDebugEnabled() ?
189 new LoggingSocketHolder(sslSocket, socket, this.id, WIRE_LOG) :
190 new SocketHolder(sslSocket, socket));
191 socketTimeout = Timeout.ofMilliseconds(sslSocket.getSoTimeout());
192 }
193
194 @Override
195 protected void onResponseReceived(final ClassicHttpResponse response) {
196 if (response != null && HEADER_LOG.isDebugEnabled()) {
197 HEADER_LOG.debug("{} << {}", this.id, new StatusLine(response));
198 final Header[] headers = response.getHeaders();
199 for (final Header header : headers) {
200 HEADER_LOG.debug("{} << {}", this.id, header);
201 }
202 }
203 }
204
205 @Override
206 protected void onRequestSubmitted(final ClassicHttpRequest request) {
207 if (request != null && HEADER_LOG.isDebugEnabled()) {
208 HEADER_LOG.debug("{} >> {}", this.id, new RequestLine(request));
209 final Header[] headers = request.getHeaders();
210 for (final Header header : headers) {
211 HEADER_LOG.debug("{} >> {}", this.id, header);
212 }
213 }
214 }
215
216 @Override
217 public void passivate() {
218 super.setSocketTimeout(Timeout.ZERO_MILLISECONDS);
219 }
220
221 @Override
222 public void activate() {
223 super.setSocketTimeout(socketTimeout);
224 }
225
226 }