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