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.BufferedOutputStream;
26 import java.io.File;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.lang.reflect.Method;
32 import java.net.Authenticator;
33 import java.net.PasswordAuthentication;
34 import java.net.URI;
35 import java.net.URL;
36 import java.net.URLConnection;
37
38
39
40
41 public class DefaultDownloader
42 implements Downloader
43 {
44 private static final int PROGRESS_CHUNK = 500000;
45
46 private static final int BUFFER_SIZE = 10000;
47
48 private final String applicationName;
49
50 private final String applicationVersion;
51
52 public DefaultDownloader( String applicationName, String applicationVersion )
53 {
54 this.applicationName = applicationName;
55 this.applicationVersion = applicationVersion;
56 configureProxyAuthentication();
57 configureAuthentication();
58 }
59
60 private void configureProxyAuthentication()
61 {
62 if ( System.getProperty( "http.proxyUser" ) != null )
63 {
64 Authenticator.setDefault( new SystemPropertiesProxyAuthenticator() );
65 }
66 }
67
68 private void configureAuthentication()
69 {
70 if ( System.getenv( MVNW_USERNAME ) != null && System.getenv( MVNW_PASSWORD ) != null
71 && System.getProperty( "http.proxyUser" ) == null )
72 {
73 Authenticator.setDefault( new Authenticator()
74 {
75 protected PasswordAuthentication getPasswordAuthentication()
76 {
77 return new PasswordAuthentication( System.getenv( MVNW_USERNAME ),
78 System.getenv( MVNW_PASSWORD ).toCharArray() );
79 }
80 } );
81 }
82 }
83
84 public void download( URI address, File destination )
85 throws Exception
86 {
87 if ( destination.exists() )
88 {
89 return;
90 }
91 destination.getParentFile().mkdirs();
92
93 downloadInternal( address, destination );
94 }
95
96 private void downloadInternal( URI address, File destination )
97 throws Exception
98 {
99 URL url = address.toURL();
100 URLConnection conn = url.openConnection();
101 addBasicAuthentication( address, conn );
102 final String userAgentValue = calculateUserAgent();
103 conn.setRequestProperty( "User-Agent", userAgentValue );
104
105 try ( OutputStream out = new BufferedOutputStream( new FileOutputStream( destination ) );
106 InputStream in = conn.getInputStream() )
107 {
108 byte[] buffer = new byte[BUFFER_SIZE];
109 int numRead;
110 long progressCounter = 0;
111 while ( ( numRead = in.read( buffer ) ) != -1 )
112 {
113 progressCounter += numRead;
114 if ( progressCounter / PROGRESS_CHUNK > 0 )
115 {
116 Logger.info( "." );
117 progressCounter = progressCounter - PROGRESS_CHUNK;
118 }
119 out.write( buffer, 0, numRead );
120 }
121 }
122
123 Logger.info( "" );
124 }
125
126 private void addBasicAuthentication( URI address, URLConnection connection )
127 throws IOException
128 {
129 String userInfo = calculateUserInfo( address );
130 if ( userInfo == null )
131 {
132 return;
133 }
134 if ( !"https".equals( address.getScheme() ) )
135 {
136 Logger.warn( "WARNING Using HTTP Basic Authentication over an insecure connection"
137 + " to download the Maven distribution. Please consider using HTTPS." );
138 }
139 connection.setRequestProperty( "Authorization", "Basic " + base64Encode( userInfo ) );
140 }
141
142
143
144
145
146
147
148
149
150
151
152 private String base64Encode( String userInfo )
153 {
154 ClassLoader loader = getClass().getClassLoader();
155 try
156 {
157 Method getEncoderMethod = loader.loadClass( "java.util.Base64" ).getMethod( "getEncoder" );
158 Method encodeMethod =
159 loader.loadClass( "java.util.Base64$Encoder" ).getMethod( "encodeToString", byte[].class );
160 Object encoder = getEncoderMethod.invoke( null );
161 return (String) encodeMethod.invoke( encoder, new Object[] { userInfo.getBytes( "UTF-8" ) } );
162 }
163 catch ( Exception java7OrEarlier )
164 {
165 try
166 {
167 Method encodeMethod =
168 loader.loadClass( "javax.xml.bind.DatatypeConverter" ).getMethod( "printBase64Binary",
169 byte[].class );
170 return (String) encodeMethod.invoke( null, new Object[] { userInfo.getBytes( "UTF-8" ) } );
171 }
172 catch ( Exception java5OrEarlier )
173 {
174 throw new RuntimeException( "Downloading Maven distributions with HTTP Basic Authentication"
175 + " is not supported on your JVM.", java5OrEarlier );
176 }
177 }
178 }
179
180 private String calculateUserInfo( URI uri )
181 {
182 String username = System.getenv( MVNW_USERNAME );
183 String password = System.getenv( MVNW_PASSWORD );
184 if ( username != null && password != null )
185 {
186 return username + ':' + password;
187 }
188 return uri.getUserInfo();
189 }
190
191 private String calculateUserAgent()
192 {
193 String appVersion = applicationVersion;
194
195 String javaVendor = System.getProperty( "java.vendor" );
196 String javaVersion = System.getProperty( "java.version" );
197 String javaVendorVersion = System.getProperty( "java.vm.version" );
198 String osName = System.getProperty( "os.name" );
199 String osVersion = System.getProperty( "os.version" );
200 String osArch = System.getProperty( "os.arch" );
201 return String.format( "%s/%s (%s;%s;%s) (%s;%s;%s)", applicationName, appVersion, osName, osVersion, osArch,
202 javaVendor, javaVersion, javaVendorVersion );
203 }
204
205 private static class SystemPropertiesProxyAuthenticator
206 extends Authenticator
207 {
208 @Override
209 protected PasswordAuthentication getPasswordAuthentication()
210 {
211 return new PasswordAuthentication( System.getProperty( "http.proxyUser" ),
212 System.getProperty( "http.proxyPassword", "" ).toCharArray() );
213 }
214 }
215 }