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