1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.wrapper;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.lang.reflect.Method;
24 import java.net.Authenticator;
25 import java.net.PasswordAuthentication;
26 import java.net.URI;
27 import java.net.URL;
28 import java.net.URLConnection;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.StandardCopyOption;
33 import java.util.Locale;
34
35 import static org.apache.maven.wrapper.MavenWrapperMain.MVNW_PASSWORD;
36 import static org.apache.maven.wrapper.MavenWrapperMain.MVNW_USERNAME;
37
38
39
40
41 public class DefaultDownloader implements Downloader {
42 private final String applicationName;
43
44 private final String applicationVersion;
45
46 public DefaultDownloader(String applicationName, String applicationVersion) {
47 this.applicationName = applicationName;
48 this.applicationVersion = applicationVersion;
49 configureProxyAuthentication();
50 configureAuthentication();
51 }
52
53 private void configureProxyAuthentication() {
54 if (System.getProperty("http.proxyUser") != null) {
55 Authenticator.setDefault(new SystemPropertiesProxyAuthenticator());
56 }
57 }
58
59 private void configureAuthentication() {
60 if (System.getenv(MVNW_USERNAME) != null
61 && System.getenv(MVNW_PASSWORD) != null
62 && System.getProperty("http.proxyUser") == null) {
63 Authenticator.setDefault(new Authenticator() {
64 @Override
65 protected PasswordAuthentication getPasswordAuthentication() {
66 return new PasswordAuthentication(
67 System.getenv(MVNW_USERNAME),
68 System.getenv(MVNW_PASSWORD).toCharArray());
69 }
70 });
71 }
72 }
73
74 @Override
75 public void download(URI address, Path destination) throws Exception {
76 if (Files.exists(destination)) {
77 return;
78 }
79 Files.createDirectories(destination.getParent());
80
81 if (!"https".equals(address.getScheme())) {
82 Logger.warn("Using an insecure connection to download the Maven distribution."
83 + " Please consider using HTTPS.");
84 }
85 downloadInternal(address, destination);
86 }
87
88 private void downloadInternal(URI address, Path destination) throws IOException {
89 URL url = address.toURL();
90 URLConnection conn = url.openConnection();
91 addBasicAuthentication(address, conn);
92 final String userAgentValue = calculateUserAgent();
93 conn.setRequestProperty("User-Agent", userAgentValue);
94
95 try (InputStream inStream = conn.getInputStream()) {
96 Files.copy(inStream, destination, StandardCopyOption.REPLACE_EXISTING);
97 }
98 }
99
100 private void addBasicAuthentication(URI address, URLConnection connection) {
101 String userInfo = calculateUserInfo(address);
102 if (userInfo == null) {
103 return;
104 }
105 connection.setRequestProperty("Authorization", "Basic " + base64Encode(userInfo));
106 }
107
108
109
110
111
112
113
114
115
116
117
118 private String base64Encode(String userInfo) {
119 ClassLoader loader = getClass().getClassLoader();
120 try {
121 Method getEncoderMethod = loader.loadClass("java.util.Base64").getMethod("getEncoder");
122 Method encodeMethod =
123 loader.loadClass("java.util.Base64$Encoder").getMethod("encodeToString", byte[].class);
124 Object encoder = getEncoderMethod.invoke(null);
125 return (String) encodeMethod.invoke(encoder, new Object[] {userInfo.getBytes(StandardCharsets.UTF_8)});
126 } catch (Exception java7OrEarlier) {
127 try {
128 Method encodeMethod = loader.loadClass("javax.xml.bind.DatatypeConverter")
129 .getMethod("printBase64Binary", byte[].class);
130 return (String) encodeMethod.invoke(null, new Object[] {userInfo.getBytes(StandardCharsets.UTF_8)});
131 } catch (Exception java5OrEarlier) {
132 throw new RuntimeException(
133 "Downloading Maven distributions with HTTP Basic Authentication"
134 + " is not supported on your JVM.",
135 java5OrEarlier);
136 }
137 }
138 }
139
140 private String calculateUserInfo(URI uri) {
141 String username = System.getenv(MVNW_USERNAME);
142 String password = System.getenv(MVNW_PASSWORD);
143 if (username != null && password != null) {
144 return username + ':' + password;
145 }
146 return uri.getUserInfo();
147 }
148
149 private String calculateUserAgent() {
150 String appVersion = applicationVersion;
151
152 String javaVendor = System.getProperty("java.vendor");
153 String javaVersion = System.getProperty("java.version");
154 String javaVendorVersion = System.getProperty("java.vm.version");
155 String osName = System.getProperty("os.name");
156 String osVersion = System.getProperty("os.version");
157 String osArch = System.getProperty("os.arch");
158 return String.format(
159 Locale.ROOT,
160 "%s/%s (%s;%s;%s) (%s;%s;%s)",
161 applicationName,
162 appVersion,
163 osName,
164 osVersion,
165 osArch,
166 javaVendor,
167 javaVersion,
168 javaVendorVersion);
169 }
170
171 private static class SystemPropertiesProxyAuthenticator extends Authenticator {
172 @Override
173 protected PasswordAuthentication getPasswordAuthentication() {
174 return new PasswordAuthentication(
175 System.getProperty("http.proxyUser"),
176 System.getProperty("http.proxyPassword", "").toCharArray());
177 }
178 }
179 }