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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.transport.http.apache;
44
45 import static org.eclipse.jgit.util.HttpSupport.METHOD_GET;
46 import static org.eclipse.jgit.util.HttpSupport.METHOD_HEAD;
47 import static org.eclipse.jgit.util.HttpSupport.METHOD_POST;
48 import static org.eclipse.jgit.util.HttpSupport.METHOD_PUT;
49
50 import java.io.IOException;
51 import java.io.InputStream;
52 import java.io.OutputStream;
53 import java.net.InetSocketAddress;
54 import java.net.MalformedURLException;
55 import java.net.ProtocolException;
56 import java.net.Proxy;
57 import java.net.URL;
58 import java.security.KeyManagementException;
59 import java.security.NoSuchAlgorithmException;
60 import java.security.SecureRandom;
61 import java.security.cert.X509Certificate;
62 import java.util.HashMap;
63 import java.util.LinkedList;
64 import java.util.List;
65 import java.util.Map;
66
67 import javax.net.ssl.HostnameVerifier;
68 import javax.net.ssl.KeyManager;
69 import javax.net.ssl.SSLContext;
70 import javax.net.ssl.SSLException;
71 import javax.net.ssl.SSLSession;
72 import javax.net.ssl.SSLSocket;
73 import javax.net.ssl.TrustManager;
74
75 import org.apache.http.Header;
76 import org.apache.http.HeaderElement;
77 import org.apache.http.HttpEntity;
78 import org.apache.http.HttpEntityEnclosingRequest;
79 import org.apache.http.HttpHost;
80 import org.apache.http.HttpResponse;
81 import org.apache.http.client.ClientProtocolException;
82 import org.apache.http.client.HttpClient;
83 import org.apache.http.client.config.RequestConfig;
84 import org.apache.http.client.methods.HttpGet;
85 import org.apache.http.client.methods.HttpHead;
86 import org.apache.http.client.methods.HttpPost;
87 import org.apache.http.client.methods.HttpPut;
88 import org.apache.http.client.methods.HttpUriRequest;
89 import org.apache.http.config.Registry;
90 import org.apache.http.config.RegistryBuilder;
91 import org.apache.http.conn.socket.ConnectionSocketFactory;
92 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
93 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
94 import org.apache.http.conn.ssl.X509HostnameVerifier;
95 import org.apache.http.impl.client.HttpClientBuilder;
96 import org.apache.http.impl.client.HttpClients;
97 import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
98 import org.eclipse.jgit.transport.http.HttpConnection;
99 import org.eclipse.jgit.transport.http.apache.internal.HttpApacheText;
100 import org.eclipse.jgit.util.TemporaryBuffer;
101 import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
102
103
104
105
106
107
108 public class HttpClientConnection implements HttpConnection {
109 HttpClient client;
110
111 URL url;
112
113 HttpUriRequest req;
114
115 HttpResponse resp = null;
116
117 String method = "GET";
118
119 private TemporaryBufferEntity entity;
120
121 private boolean isUsingProxy = false;
122
123 private Proxy proxy;
124
125 private Integer timeout = null;
126
127 private Integer readTimeout;
128
129 private Boolean followRedirects;
130
131 private X509HostnameVerifier hostnameverifier;
132
133 SSLContext ctx;
134
135 private HttpClient getClient() {
136 if (client == null) {
137 HttpClientBuilder clientBuilder = HttpClients.custom();
138 RequestConfig.Builder configBuilder = RequestConfig.custom();
139 if (proxy != null && !Proxy.NO_PROXY.equals(proxy)) {
140 isUsingProxy = true;
141 InetSocketAddress adr = (InetSocketAddress) proxy.address();
142 clientBuilder.setProxy(
143 new HttpHost(adr.getHostName(), adr.getPort()));
144 }
145 if (timeout != null) {
146 configBuilder.setConnectTimeout(timeout.intValue());
147 }
148 if (readTimeout != null) {
149 configBuilder.setSocketTimeout(readTimeout.intValue());
150 }
151 if (followRedirects != null) {
152 configBuilder
153 .setRedirectsEnabled(followRedirects.booleanValue());
154 }
155 if (hostnameverifier != null) {
156 SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
157 getSSLContext(), hostnameverifier);
158 clientBuilder.setSSLSocketFactory(sslConnectionFactory);
159 Registry<ConnectionSocketFactory> registry = RegistryBuilder
160 .<ConnectionSocketFactory> create()
161 .register("https", sslConnectionFactory)
162 .register("http", PlainConnectionSocketFactory.INSTANCE)
163 .build();
164 clientBuilder.setConnectionManager(
165 new BasicHttpClientConnectionManager(registry));
166 }
167 clientBuilder.setDefaultRequestConfig(configBuilder.build());
168 client = clientBuilder.build();
169 }
170
171 return client;
172 }
173
174 private SSLContext getSSLContext() {
175 if (ctx == null) {
176 try {
177 ctx = SSLContext.getInstance("TLS");
178 } catch (NoSuchAlgorithmException e) {
179 throw new IllegalStateException(
180 HttpApacheText.get().unexpectedSSLContextException, e);
181 }
182 }
183 return ctx;
184 }
185
186
187
188
189
190
191 public void setBuffer(TemporaryBuffer buffer) {
192 this.entity = new TemporaryBufferEntity(buffer);
193 }
194
195
196
197
198
199 public HttpClientConnection(String urlStr) throws MalformedURLException {
200 this(urlStr, null);
201 }
202
203
204
205
206
207
208 public HttpClientConnection(String urlStr, Proxy proxy)
209 throws MalformedURLException {
210 this(urlStr, proxy, null);
211 }
212
213
214
215
216
217
218
219 public HttpClientConnection(String urlStr, Proxy proxy, HttpClient cl)
220 throws MalformedURLException {
221 this.client = cl;
222 this.url = new URL(urlStr);
223 this.proxy = proxy;
224 }
225
226 @Override
227 public int getResponseCode() throws IOException {
228 execute();
229 return resp.getStatusLine().getStatusCode();
230 }
231
232 @Override
233 public URL getURL() {
234 return url;
235 }
236
237 @Override
238 public String getResponseMessage() throws IOException {
239 execute();
240 return resp.getStatusLine().getReasonPhrase();
241 }
242
243 private void execute() throws IOException, ClientProtocolException {
244 if (resp != null) {
245 return;
246 }
247
248 if (entity == null) {
249 resp = getClient().execute(req);
250 return;
251 }
252
253 try {
254 if (req instanceof HttpEntityEnclosingRequest) {
255 HttpEntityEnclosingRequest eReq = (HttpEntityEnclosingRequest) req;
256 eReq.setEntity(entity);
257 }
258 resp = getClient().execute(req);
259 } finally {
260 entity.close();
261 entity = null;
262 }
263 }
264
265 @Override
266 public Map<String, List<String>> getHeaderFields() {
267 Map<String, List<String>> ret = new HashMap<>();
268 for (Header hdr : resp.getAllHeaders()) {
269 List<String> list = new LinkedList<>();
270 for (HeaderElement hdrElem : hdr.getElements())
271 list.add(hdrElem.toString());
272 ret.put(hdr.getName(), list);
273 }
274 return ret;
275 }
276
277 @Override
278 public void setRequestProperty(String name, String value) {
279 req.addHeader(name, value);
280 }
281
282 @Override
283 public void setRequestMethod(String method) throws ProtocolException {
284 this.method = method;
285 if (METHOD_GET.equalsIgnoreCase(method)) {
286 req = new HttpGet(url.toString());
287 } else if (METHOD_HEAD.equalsIgnoreCase(method)) {
288 req = new HttpHead(url.toString());
289 } else if (METHOD_PUT.equalsIgnoreCase(method)) {
290 req = new HttpPut(url.toString());
291 } else if (METHOD_POST.equalsIgnoreCase(method)) {
292 req = new HttpPost(url.toString());
293 } else {
294 this.method = null;
295 throw new UnsupportedOperationException();
296 }
297 }
298
299 @Override
300 public void setUseCaches(boolean usecaches) {
301
302 }
303
304 @Override
305 public void setConnectTimeout(int timeout) {
306 this.timeout = Integer.valueOf(timeout);
307 }
308
309 @Override
310 public void setReadTimeout(int readTimeout) {
311 this.readTimeout = Integer.valueOf(readTimeout);
312 }
313
314 @Override
315 public String getContentType() {
316 HttpEntity responseEntity = resp.getEntity();
317 if (responseEntity != null) {
318 Header contentType = responseEntity.getContentType();
319 if (contentType != null)
320 return contentType.getValue();
321 }
322 return null;
323 }
324
325 @Override
326 public InputStream getInputStream() throws IOException {
327 return resp.getEntity().getContent();
328 }
329
330
331 @Override
332 public String getHeaderField(String name) {
333 Header header = resp.getFirstHeader(name);
334 return (header == null) ? null : header.getValue();
335 }
336
337 @Override
338 public int getContentLength() {
339 Header contentLength = resp.getFirstHeader("content-length");
340 if (contentLength == null) {
341 return -1;
342 }
343
344 try {
345 int l = Integer.parseInt(contentLength.getValue());
346 return l < 0 ? -1 : l;
347 } catch (NumberFormatException e) {
348 return -1;
349 }
350 }
351
352 @Override
353 public void setInstanceFollowRedirects(boolean followRedirects) {
354 this.followRedirects = Boolean.valueOf(followRedirects);
355 }
356
357 @Override
358 public void setDoOutput(boolean dooutput) {
359
360 }
361
362 @Override
363 public void setFixedLengthStreamingMode(int contentLength) {
364 if (entity != null)
365 throw new IllegalArgumentException();
366 entity = new TemporaryBufferEntity(new LocalFile(null));
367 entity.setContentLength(contentLength);
368 }
369
370 @Override
371 public OutputStream getOutputStream() throws IOException {
372 if (entity == null)
373 entity = new TemporaryBufferEntity(new LocalFile(null));
374 return entity.getBuffer();
375 }
376
377 @Override
378 public void setChunkedStreamingMode(int chunklen) {
379 if (entity == null)
380 entity = new TemporaryBufferEntity(new LocalFile(null));
381 entity.setChunked(true);
382 }
383
384 @Override
385 public String getRequestMethod() {
386 return method;
387 }
388
389 @Override
390 public boolean usingProxy() {
391 return isUsingProxy;
392 }
393
394 @Override
395 public void connect() throws IOException {
396 execute();
397 }
398
399 @Override
400 public void setHostnameVerifier(final HostnameVerifier hostnameverifier) {
401 this.hostnameverifier = new X509HostnameVerifier() {
402 @Override
403 public boolean verify(String hostname, SSLSession session) {
404 return hostnameverifier.verify(hostname, session);
405 }
406
407 @Override
408 public void verify(String host, String[] cns, String[] subjectAlts)
409 throws SSLException {
410 throw new UnsupportedOperationException();
411 }
412
413 @Override
414 public void verify(String host, X509Certificate cert)
415 throws SSLException {
416 throw new UnsupportedOperationException();
417 }
418
419 @Override
420 public void verify(String host, SSLSocket ssl) throws IOException {
421 hostnameverifier.verify(host, ssl.getSession());
422 }
423 };
424 }
425
426 @Override
427 public void configure(KeyManager[] km, TrustManager[] tm,
428 SecureRandom random) throws KeyManagementException {
429 getSSLContext().init(km, tm, random);
430 }
431 }