1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.search.backend.remoterepository.internal;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URI;
24 import java.net.http.HttpClient;
25 import java.net.http.HttpRequest;
26 import java.net.http.HttpResponse;
27 import java.time.Duration;
28 import java.util.AbstractMap;
29 import java.util.Map;
30 import java.util.stream.Collectors;
31
32 import org.apache.maven.search.backend.remoterepository.RemoteRepositorySearchTransport;
33
34 import static java.util.Objects.requireNonNull;
35
36
37
38
39 public class Java11HttpClientRemoteRepositorySearchTransport implements RemoteRepositorySearchTransport {
40 private static class ResponseImpl implements Response {
41
42 private final HttpResponse<?> response;
43
44 private final InputStream inputStream;
45
46 private ResponseImpl(HttpResponse<?> response, InputStream inputStream) {
47 this.response = requireNonNull(response);
48 this.inputStream = inputStream;
49 }
50
51 @Override
52 public int getCode() {
53 return response.statusCode();
54 }
55
56 @Override
57 public Map<String, String> getHeaders() {
58 return response.headers().map().entrySet().stream()
59 .map(e -> new AbstractMap.SimpleEntry<>(
60 e.getKey(), e.getValue().get(0)))
61 .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
62 }
63
64 @Override
65 public InputStream getBody() {
66 return inputStream;
67 }
68
69 @Override
70 public void close() throws IOException {
71 if (inputStream != null) {
72 inputStream.close();
73 }
74 }
75 }
76
77 private final Duration timeout;
78
79 private final HttpClient client;
80
81 public Java11HttpClientRemoteRepositorySearchTransport() {
82 this(Duration.ofSeconds(10L));
83 }
84
85 public Java11HttpClientRemoteRepositorySearchTransport(Duration timeout) {
86 this(
87 timeout,
88 HttpClient.newBuilder()
89 .connectTimeout(timeout)
90 .followRedirects(HttpClient.Redirect.NEVER)
91 .build());
92 }
93
94 public Java11HttpClientRemoteRepositorySearchTransport(Duration timeout, HttpClient client) {
95 this.timeout = requireNonNull(timeout);
96 this.client = requireNonNull(client);
97 }
98
99 @Override
100 public Response get(String serviceUri, Map<String, String> headers) throws IOException {
101 HttpRequest.Builder builder = HttpRequest.newBuilder()
102 .timeout(timeout)
103 .uri(URI.create(serviceUri))
104 .GET();
105 for (Map.Entry<String, String> header : headers.entrySet()) {
106 builder.header(header.getKey(), header.getValue());
107 }
108 HttpRequest request = builder.build();
109 try {
110 HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
111 return new ResponseImpl(response, response.body());
112 } catch (InterruptedException e) {
113 Thread.currentThread().interrupt();
114 throw new IOException(e);
115 }
116 }
117
118 @Override
119 public Response head(String serviceUri, Map<String, String> headers) throws IOException {
120 HttpRequest.Builder builder = HttpRequest.newBuilder()
121 .timeout(timeout)
122 .uri(URI.create(serviceUri))
123 .method("HEAD", HttpRequest.BodyPublishers.noBody());
124 for (Map.Entry<String, String> header : headers.entrySet()) {
125 builder.header(header.getKey(), header.getValue());
126 }
127 HttpRequest request = builder.build();
128 try {
129 HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding());
130 return new ResponseImpl(response, null);
131 } catch (InterruptedException e) {
132 Thread.currentThread().interrupt();
133 throw new IOException(e);
134 }
135 }
136 }