1 | |
package org.apache.maven.wagon.providers.http; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import java.io.FileNotFoundException; |
23 | |
import java.io.IOException; |
24 | |
import java.io.InputStream; |
25 | |
import java.io.OutputStream; |
26 | |
import java.net.Authenticator; |
27 | |
import java.net.HttpURLConnection; |
28 | |
import java.net.MalformedURLException; |
29 | |
import java.net.PasswordAuthentication; |
30 | |
import java.net.URL; |
31 | |
import java.net.URLConnection; |
32 | |
import java.util.Iterator; |
33 | |
import java.util.List; |
34 | |
import java.util.Properties; |
35 | |
import java.util.zip.GZIPInputStream; |
36 | |
|
37 | |
import org.apache.maven.wagon.ConnectionException; |
38 | |
import org.apache.maven.wagon.InputData; |
39 | |
import org.apache.maven.wagon.OutputData; |
40 | |
import org.apache.maven.wagon.ResourceDoesNotExistException; |
41 | |
import org.apache.maven.wagon.StreamWagon; |
42 | |
import org.apache.maven.wagon.TransferFailedException; |
43 | |
import org.apache.maven.wagon.authentication.AuthenticationException; |
44 | |
import org.apache.maven.wagon.authorization.AuthorizationException; |
45 | |
import org.apache.maven.wagon.events.TransferEvent; |
46 | |
import org.apache.maven.wagon.proxy.ProxyInfo; |
47 | |
import org.apache.maven.wagon.resource.Resource; |
48 | |
import org.apache.maven.wagon.shared.http.HtmlFileListParser; |
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | 499 | public class LightweightHttpWagon |
58 | |
extends StreamWagon |
59 | |
{ |
60 | |
private String previousProxyExclusions; |
61 | |
|
62 | |
private String previousHttpProxyHost; |
63 | |
|
64 | |
private String previousHttpProxyPort; |
65 | |
|
66 | |
private HttpURLConnection putConnection; |
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
private boolean useCache; |
74 | |
|
75 | |
|
76 | |
private Properties httpHeaders; |
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
private String buildUrl( String path ) |
85 | |
{ |
86 | 132 | final String repoUrl = getRepository().getUrl(); |
87 | |
|
88 | 132 | path = path.replace( ' ', '+' ); |
89 | |
|
90 | 132 | if ( repoUrl.charAt( repoUrl.length() - 1 ) != '/' ) |
91 | |
{ |
92 | 60 | return repoUrl + '/' + path; |
93 | |
} |
94 | |
|
95 | 72 | return repoUrl + path; |
96 | |
} |
97 | |
|
98 | |
public void fillInputData( InputData inputData ) |
99 | |
throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException |
100 | |
{ |
101 | 50 | Resource resource = inputData.getResource(); |
102 | |
try |
103 | |
{ |
104 | 50 | URL url = new URL( buildUrl( resource.getName() ) ); |
105 | 50 | HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
106 | 50 | urlConnection.setRequestProperty( "Accept-Encoding", "gzip" ); |
107 | 50 | if ( !useCache ) |
108 | |
{ |
109 | 50 | urlConnection.setRequestProperty( "Pragma", "no-cache" ); |
110 | |
} |
111 | |
|
112 | 50 | addHeaders( urlConnection ); |
113 | |
|
114 | |
|
115 | 50 | int responseCode = urlConnection.getResponseCode(); |
116 | 50 | if ( responseCode == HttpURLConnection.HTTP_FORBIDDEN |
117 | |
|| responseCode == HttpURLConnection.HTTP_UNAUTHORIZED ) |
118 | |
{ |
119 | 6 | throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) ); |
120 | |
} |
121 | |
|
122 | 44 | InputStream is = urlConnection.getInputStream(); |
123 | 30 | String contentEncoding = urlConnection.getHeaderField( "Content-Encoding" ); |
124 | 30 | boolean isGZipped = contentEncoding == null ? false : "gzip".equalsIgnoreCase( contentEncoding ); |
125 | 30 | if ( isGZipped ) |
126 | |
{ |
127 | 2 | is = new GZIPInputStream( is ); |
128 | |
} |
129 | 30 | inputData.setInputStream( is ); |
130 | 30 | resource.setLastModified( urlConnection.getLastModified() ); |
131 | 30 | resource.setContentLength( urlConnection.getContentLength() ); |
132 | |
} |
133 | 0 | catch ( MalformedURLException e ) |
134 | |
{ |
135 | 0 | throw new ResourceDoesNotExistException( "Invalid repository URL: " + e.getMessage(), e ); |
136 | |
} |
137 | 12 | catch ( FileNotFoundException e ) |
138 | |
{ |
139 | 12 | throw new ResourceDoesNotExistException( "Unable to locate resource in repository", e ); |
140 | |
} |
141 | 2 | catch ( IOException e ) |
142 | |
{ |
143 | 2 | throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e ); |
144 | 30 | } |
145 | 30 | } |
146 | |
|
147 | |
private void addHeaders( URLConnection urlConnection ) |
148 | |
{ |
149 | 108 | if ( httpHeaders != null ) |
150 | |
{ |
151 | 2 | for ( Iterator i = httpHeaders.keySet().iterator(); i.hasNext(); ) |
152 | |
{ |
153 | 2 | String header = (String) i.next(); |
154 | 2 | urlConnection.setRequestProperty( header, httpHeaders.getProperty( header ) ); |
155 | 2 | } |
156 | |
} |
157 | 108 | } |
158 | |
|
159 | |
public void fillOutputData( OutputData outputData ) |
160 | |
throws TransferFailedException |
161 | |
{ |
162 | 40 | Resource resource = outputData.getResource(); |
163 | |
try |
164 | |
{ |
165 | 40 | URL url = new URL( buildUrl( resource.getName() ) ); |
166 | 40 | putConnection = (HttpURLConnection) url.openConnection(); |
167 | |
|
168 | 40 | addHeaders( putConnection ); |
169 | |
|
170 | 40 | putConnection.setRequestMethod( "PUT" ); |
171 | 40 | putConnection.setDoOutput( true ); |
172 | 40 | outputData.setOutputStream( putConnection.getOutputStream() ); |
173 | |
} |
174 | 0 | catch ( IOException e ) |
175 | |
{ |
176 | 0 | throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e ); |
177 | 40 | } |
178 | 40 | } |
179 | |
|
180 | |
protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output ) |
181 | |
throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException |
182 | |
{ |
183 | |
try |
184 | |
{ |
185 | 40 | int statusCode = putConnection.getResponseCode(); |
186 | |
|
187 | 40 | switch ( statusCode ) |
188 | |
{ |
189 | |
|
190 | |
case HttpURLConnection.HTTP_OK: |
191 | |
case HttpURLConnection.HTTP_CREATED: |
192 | |
case HttpURLConnection.HTTP_ACCEPTED: |
193 | |
case HttpURLConnection.HTTP_NO_CONTENT: |
194 | 30 | break; |
195 | |
|
196 | |
case HttpURLConnection.HTTP_FORBIDDEN: |
197 | 2 | throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) ); |
198 | |
|
199 | |
case HttpURLConnection.HTTP_NOT_FOUND: |
200 | 2 | throw new ResourceDoesNotExistException( "File: " + buildUrl( resource.getName() ) |
201 | |
+ " does not exist" ); |
202 | |
|
203 | |
|
204 | |
default: |
205 | 6 | throw new TransferFailedException( "Failed to transfer file: " + buildUrl( resource.getName() ) |
206 | |
+ ". Return code is: " + statusCode ); |
207 | |
} |
208 | |
} |
209 | 0 | catch ( IOException e ) |
210 | |
{ |
211 | 0 | fireTransferError( resource, e, TransferEvent.REQUEST_PUT ); |
212 | |
|
213 | 0 | throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e ); |
214 | 30 | } |
215 | 30 | } |
216 | |
|
217 | |
protected void openConnectionInternal() |
218 | |
throws ConnectionException, AuthenticationException |
219 | |
{ |
220 | 113 | previousHttpProxyHost = System.getProperty( "http.proxyHost" ); |
221 | 113 | previousHttpProxyPort = System.getProperty( "http.proxyPort" ); |
222 | 113 | previousProxyExclusions = System.getProperty( "http.nonProxyHosts" ); |
223 | |
|
224 | 113 | final ProxyInfo proxyInfo = getProxyInfo( "http", getRepository().getHost() ); |
225 | 113 | if ( proxyInfo != null ) |
226 | |
{ |
227 | 8 | setSystemProperty( "http.proxyHost", proxyInfo.getHost() ); |
228 | 8 | setSystemProperty( "http.proxyPort", String.valueOf( proxyInfo.getPort() ) ); |
229 | 8 | setSystemProperty( "http.nonProxyHosts", proxyInfo.getNonProxyHosts() ); |
230 | |
} |
231 | |
else |
232 | |
{ |
233 | 105 | setSystemProperty( "http.proxyHost", null ); |
234 | 105 | setSystemProperty( "http.proxyPort", null ); |
235 | |
} |
236 | |
|
237 | 113 | final boolean hasProxy = ( proxyInfo != null && proxyInfo.getUserName() != null ); |
238 | 113 | final boolean hasAuthentication = ( authenticationInfo != null && authenticationInfo.getUserName() != null ); |
239 | 113 | if ( hasProxy || hasAuthentication ) |
240 | |
{ |
241 | 14 | Authenticator.setDefault( new Authenticator() |
242 | |
{ |
243 | 14 | protected PasswordAuthentication getPasswordAuthentication() |
244 | |
{ |
245 | |
|
246 | 127 | if ( hasProxy && getRequestingHost().equals( proxyInfo.getHost() ) |
247 | |
&& getRequestingPort() == proxyInfo.getPort() ) |
248 | |
{ |
249 | 1 | String password = ""; |
250 | 1 | if ( proxyInfo.getPassword() != null ) |
251 | |
{ |
252 | 1 | password = proxyInfo.getPassword(); |
253 | |
} |
254 | 1 | return new PasswordAuthentication( proxyInfo.getUserName(), password.toCharArray() ); |
255 | |
} |
256 | |
|
257 | 126 | if ( hasAuthentication ) |
258 | |
{ |
259 | 126 | String password = ""; |
260 | 126 | if ( authenticationInfo.getPassword() != null ) |
261 | |
{ |
262 | 126 | password = authenticationInfo.getPassword(); |
263 | |
} |
264 | 126 | return new PasswordAuthentication( authenticationInfo.getUserName(), password.toCharArray() ); |
265 | |
} |
266 | |
|
267 | 0 | return super.getPasswordAuthentication(); |
268 | |
} |
269 | |
} ); |
270 | |
} |
271 | |
else |
272 | |
{ |
273 | 99 | Authenticator.setDefault( null ); |
274 | |
} |
275 | 113 | } |
276 | |
|
277 | |
public void closeConnection() |
278 | |
throws ConnectionException |
279 | |
{ |
280 | 113 | if ( putConnection != null ) |
281 | |
{ |
282 | 40 | putConnection.disconnect(); |
283 | |
} |
284 | |
|
285 | 113 | setSystemProperty( "http.proxyHost", previousHttpProxyHost ); |
286 | 113 | setSystemProperty( "http.proxyPort", previousHttpProxyPort ); |
287 | 113 | setSystemProperty( "http.nonProxyHosts", previousProxyExclusions ); |
288 | 113 | } |
289 | |
|
290 | |
public List getFileList( String destinationDirectory ) |
291 | |
throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException |
292 | |
{ |
293 | 6 | InputData inputData = new InputData(); |
294 | |
|
295 | 6 | if ( destinationDirectory.length() > 0 && !destinationDirectory.endsWith( "/" ) ) |
296 | |
{ |
297 | 4 | destinationDirectory += "/"; |
298 | |
} |
299 | |
|
300 | 6 | String url = buildUrl( destinationDirectory ); |
301 | |
|
302 | 6 | Resource resource = new Resource( destinationDirectory ); |
303 | |
|
304 | 6 | inputData.setResource( resource ); |
305 | |
|
306 | 6 | fillInputData( inputData ); |
307 | |
|
308 | 4 | InputStream is = inputData.getInputStream(); |
309 | |
|
310 | 4 | if ( is == null ) |
311 | |
{ |
312 | 0 | throw new TransferFailedException( url + " - Could not open input stream for resource: '" + resource |
313 | |
+ "'" ); |
314 | |
} |
315 | |
|
316 | 4 | return HtmlFileListParser.parseFileList( url, is ); |
317 | |
} |
318 | |
|
319 | |
public boolean resourceExists( String resourceName ) |
320 | |
throws TransferFailedException, AuthorizationException |
321 | |
{ |
322 | |
HttpURLConnection headConnection; |
323 | |
|
324 | |
try |
325 | |
{ |
326 | 18 | URL url = new URL( buildUrl( new Resource( resourceName ).getName() ) ); |
327 | 18 | headConnection = (HttpURLConnection) url.openConnection(); |
328 | |
|
329 | 18 | addHeaders( headConnection ); |
330 | |
|
331 | 18 | headConnection.setRequestMethod( "HEAD" ); |
332 | 18 | headConnection.setDoOutput( true ); |
333 | |
|
334 | 18 | int statusCode = headConnection.getResponseCode(); |
335 | |
|
336 | 18 | switch ( statusCode ) |
337 | |
{ |
338 | |
case HttpURLConnection.HTTP_OK: |
339 | 4 | return true; |
340 | |
|
341 | |
case HttpURLConnection.HTTP_FORBIDDEN: |
342 | 2 | throw new AuthorizationException( "Access denied to: " + url ); |
343 | |
|
344 | |
case HttpURLConnection.HTTP_NOT_FOUND: |
345 | 6 | return false; |
346 | |
|
347 | |
case HttpURLConnection.HTTP_UNAUTHORIZED: |
348 | 4 | throw new AuthorizationException( "Access denied to: " + url ); |
349 | |
|
350 | |
default: |
351 | 2 | throw new TransferFailedException( "Failed to look for file: " + buildUrl( resourceName ) |
352 | |
+ ". Return code is: " + statusCode ); |
353 | |
} |
354 | |
} |
355 | 0 | catch ( IOException e ) |
356 | |
{ |
357 | 0 | throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e ); |
358 | |
} |
359 | |
} |
360 | |
|
361 | |
public boolean isUseCache() |
362 | |
{ |
363 | 0 | return useCache; |
364 | |
} |
365 | |
|
366 | |
public void setUseCache( boolean useCache ) |
367 | |
{ |
368 | 0 | this.useCache = useCache; |
369 | 0 | } |
370 | |
|
371 | |
public Properties getHttpHeaders() |
372 | |
{ |
373 | 0 | return httpHeaders; |
374 | |
} |
375 | |
|
376 | |
public void setHttpHeaders( Properties httpHeaders ) |
377 | |
{ |
378 | 2 | this.httpHeaders = httpHeaders; |
379 | 2 | } |
380 | |
|
381 | |
void setSystemProperty( String key, String value ) |
382 | |
{ |
383 | 865 | if ( value != null ) |
384 | |
{ |
385 | 44 | System.setProperty( key, value ); |
386 | |
} |
387 | |
else |
388 | |
{ |
389 | 821 | System.getProperties().remove( key ); |
390 | |
} |
391 | 865 | } |
392 | |
|
393 | |
} |