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 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 final String repoUrl = getRepository().getUrl();
87
88 path = path.replace( ' ', '+' );
89
90 if ( repoUrl.charAt( repoUrl.length() - 1 ) != '/' )
91 {
92 return repoUrl + '/' + path;
93 }
94
95 return repoUrl + path;
96 }
97
98 public void fillInputData( InputData inputData )
99 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
100 {
101 Resource resource = inputData.getResource();
102 try
103 {
104 URL url = new URL( buildUrl( resource.getName() ) );
105 HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
106 urlConnection.setRequestProperty( "Accept-Encoding", "gzip" );
107 if ( !useCache )
108 {
109 urlConnection.setRequestProperty( "Pragma", "no-cache" );
110 }
111
112 addHeaders( urlConnection );
113
114
115 int responseCode = urlConnection.getResponseCode();
116 if ( responseCode == HttpURLConnection.HTTP_FORBIDDEN
117 || responseCode == HttpURLConnection.HTTP_UNAUTHORIZED )
118 {
119 throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) );
120 }
121
122 InputStream is = urlConnection.getInputStream();
123 String contentEncoding = urlConnection.getHeaderField( "Content-Encoding" );
124 boolean isGZipped = contentEncoding == null ? false : "gzip".equalsIgnoreCase( contentEncoding );
125 if ( isGZipped )
126 {
127 is = new GZIPInputStream( is );
128 }
129 inputData.setInputStream( is );
130 resource.setLastModified( urlConnection.getLastModified() );
131 resource.setContentLength( urlConnection.getContentLength() );
132 }
133 catch ( MalformedURLException e )
134 {
135 throw new ResourceDoesNotExistException( "Invalid repository URL: " + e.getMessage(), e );
136 }
137 catch ( FileNotFoundException e )
138 {
139 throw new ResourceDoesNotExistException( "Unable to locate resource in repository", e );
140 }
141 catch ( IOException e )
142 {
143 throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
144 }
145 }
146
147 private void addHeaders( URLConnection urlConnection )
148 {
149 if ( httpHeaders != null )
150 {
151 for ( Iterator i = httpHeaders.keySet().iterator(); i.hasNext(); )
152 {
153 String header = (String) i.next();
154 urlConnection.setRequestProperty( header, httpHeaders.getProperty( header ) );
155 }
156 }
157 }
158
159 public void fillOutputData( OutputData outputData )
160 throws TransferFailedException
161 {
162 Resource resource = outputData.getResource();
163 try
164 {
165 URL url = new URL( buildUrl( resource.getName() ) );
166 putConnection = (HttpURLConnection) url.openConnection();
167
168 addHeaders( putConnection );
169
170 putConnection.setRequestMethod( "PUT" );
171 putConnection.setDoOutput( true );
172 outputData.setOutputStream( putConnection.getOutputStream() );
173 }
174 catch ( IOException e )
175 {
176 throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
177 }
178 }
179
180 protected void finishPutTransfer( Resource resource, InputStream input, OutputStream output )
181 throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
182 {
183 try
184 {
185 int statusCode = putConnection.getResponseCode();
186
187 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 break;
195
196 case HttpURLConnection.HTTP_FORBIDDEN:
197 throw new AuthorizationException( "Access denied to: " + buildUrl( resource.getName() ) );
198
199 case HttpURLConnection.HTTP_NOT_FOUND:
200 throw new ResourceDoesNotExistException( "File: " + buildUrl( resource.getName() )
201 + " does not exist" );
202
203
204 default:
205 throw new TransferFailedException( "Failed to transfer file: " + buildUrl( resource.getName() )
206 + ". Return code is: " + statusCode );
207 }
208 }
209 catch ( IOException e )
210 {
211 fireTransferError( resource, e, TransferEvent.REQUEST_PUT );
212
213 throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
214 }
215 }
216
217 protected void openConnectionInternal()
218 throws ConnectionException, AuthenticationException
219 {
220 previousHttpProxyHost = System.getProperty( "http.proxyHost" );
221 previousHttpProxyPort = System.getProperty( "http.proxyPort" );
222 previousProxyExclusions = System.getProperty( "http.nonProxyHosts" );
223
224 final ProxyInfo proxyInfo = getProxyInfo( "http", getRepository().getHost() );
225 if ( proxyInfo != null )
226 {
227 setSystemProperty( "http.proxyHost", proxyInfo.getHost() );
228 setSystemProperty( "http.proxyPort", String.valueOf( proxyInfo.getPort() ) );
229 setSystemProperty( "http.nonProxyHosts", proxyInfo.getNonProxyHosts() );
230 }
231 else
232 {
233 setSystemProperty( "http.proxyHost", null );
234 setSystemProperty( "http.proxyPort", null );
235 }
236
237 final boolean hasProxy = ( proxyInfo != null && proxyInfo.getUserName() != null );
238 final boolean hasAuthentication = ( authenticationInfo != null && authenticationInfo.getUserName() != null );
239 if ( hasProxy || hasAuthentication )
240 {
241 Authenticator.setDefault( new Authenticator()
242 {
243 protected PasswordAuthentication getPasswordAuthentication()
244 {
245
246 if ( hasProxy && getRequestingHost().equals( proxyInfo.getHost() )
247 && getRequestingPort() == proxyInfo.getPort() )
248 {
249 String password = "";
250 if ( proxyInfo.getPassword() != null )
251 {
252 password = proxyInfo.getPassword();
253 }
254 return new PasswordAuthentication( proxyInfo.getUserName(), password.toCharArray() );
255 }
256
257 if ( hasAuthentication )
258 {
259 String password = "";
260 if ( authenticationInfo.getPassword() != null )
261 {
262 password = authenticationInfo.getPassword();
263 }
264 return new PasswordAuthentication( authenticationInfo.getUserName(), password.toCharArray() );
265 }
266
267 return super.getPasswordAuthentication();
268 }
269 } );
270 }
271 else
272 {
273 Authenticator.setDefault( null );
274 }
275 }
276
277 public void closeConnection()
278 throws ConnectionException
279 {
280 if ( putConnection != null )
281 {
282 putConnection.disconnect();
283 }
284
285 setSystemProperty( "http.proxyHost", previousHttpProxyHost );
286 setSystemProperty( "http.proxyPort", previousHttpProxyPort );
287 setSystemProperty( "http.nonProxyHosts", previousProxyExclusions );
288 }
289
290 public List getFileList( String destinationDirectory )
291 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
292 {
293 InputData inputData = new InputData();
294
295 if ( destinationDirectory.length() > 0 && !destinationDirectory.endsWith( "/" ) )
296 {
297 destinationDirectory += "/";
298 }
299
300 String url = buildUrl( destinationDirectory );
301
302 Resource resource = new Resource( destinationDirectory );
303
304 inputData.setResource( resource );
305
306 fillInputData( inputData );
307
308 InputStream is = inputData.getInputStream();
309
310 if ( is == null )
311 {
312 throw new TransferFailedException( url + " - Could not open input stream for resource: '" + resource
313 + "'" );
314 }
315
316 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 URL url = new URL( buildUrl( new Resource( resourceName ).getName() ) );
327 headConnection = (HttpURLConnection) url.openConnection();
328
329 addHeaders( headConnection );
330
331 headConnection.setRequestMethod( "HEAD" );
332 headConnection.setDoOutput( true );
333
334 int statusCode = headConnection.getResponseCode();
335
336 switch ( statusCode )
337 {
338 case HttpURLConnection.HTTP_OK:
339 return true;
340
341 case HttpURLConnection.HTTP_FORBIDDEN:
342 throw new AuthorizationException( "Access denied to: " + url );
343
344 case HttpURLConnection.HTTP_NOT_FOUND:
345 return false;
346
347 case HttpURLConnection.HTTP_UNAUTHORIZED:
348 throw new AuthorizationException( "Access denied to: " + url );
349
350 default:
351 throw new TransferFailedException( "Failed to look for file: " + buildUrl( resourceName )
352 + ". Return code is: " + statusCode );
353 }
354 }
355 catch ( IOException e )
356 {
357 throw new TransferFailedException( "Error transferring file: " + e.getMessage(), e );
358 }
359 }
360
361 public boolean isUseCache()
362 {
363 return useCache;
364 }
365
366 public void setUseCache( boolean useCache )
367 {
368 this.useCache = useCache;
369 }
370
371 public Properties getHttpHeaders()
372 {
373 return httpHeaders;
374 }
375
376 public void setHttpHeaders( Properties httpHeaders )
377 {
378 this.httpHeaders = httpHeaders;
379 }
380
381 void setSystemProperty( String key, String value )
382 {
383 if ( value != null )
384 {
385 System.setProperty( key, value );
386 }
387 else
388 {
389 System.getProperties().remove( key );
390 }
391 }
392
393 }