| 1 6 package fr.jayasoft.ivy.url; 7 8 import java.io.File ; 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.net.URL ; 12 import java.net.UnknownHostException ; 13 import java.text.ParseException ; 14 import java.text.SimpleDateFormat ; 15 import java.util.ArrayList ; 16 import java.util.List ; 17 import java.util.Locale ; 18 19 import org.apache.commons.httpclient.Header; 20 import org.apache.commons.httpclient.HttpClient; 21 import org.apache.commons.httpclient.HttpException; 22 import org.apache.commons.httpclient.HttpMethodBase; 23 import org.apache.commons.httpclient.HttpStatus; 24 import org.apache.commons.httpclient.UsernamePasswordCredentials; 25 import org.apache.commons.httpclient.auth.AuthPolicy; 26 import org.apache.commons.httpclient.methods.GetMethod; 27 import org.apache.commons.httpclient.methods.HeadMethod; 28 29 import fr.jayasoft.ivy.util.CopyProgressListener; 30 import fr.jayasoft.ivy.util.Credentials; 31 import fr.jayasoft.ivy.util.FileUtil; 32 import fr.jayasoft.ivy.util.Message; 33 34 38 public class HttpClientHandler extends AbstractURLHandler { 39 private static final SimpleDateFormat LAST_MODIFIED_FORMAT = new SimpleDateFormat ("EEE, d MMM yyyy HH:mm:ss z", Locale.US); 40 41 private int _proxyPort; 43 44 private String _proxyRealm = null; 45 private String _proxyHost = null; 46 private String _proxyUserName = null; 47 private String _proxyPasswd = null; 48 49 private HttpClientHelper _httpClientHelper; 50 51 public HttpClientHandler() { 52 configureProxy(); 53 } 54 55 private void configureProxy() { 56 _proxyRealm = null; 57 _proxyHost = System.getProperty("http.proxyHost"); 59 if(useProxy()) { 61 _proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); 62 _proxyUserName = System.getProperty("http.proxyUser"); 63 _proxyPasswd = System.getProperty("http.proxyPassword"); 64 Message.verbose("proxy configured: host="+_proxyHost+" port="+_proxyPort+" user="+_proxyUserName); 67 } else { 68 Message.verbose("no proxy configured"); 69 } 70 } 71 72 73 74 public InputStream openStream(URL url) throws IOException { 75 GetMethod get = doGet(url); 76 return new GETInputStream(get); 77 } 78 79 public void download(URL src, File dest, CopyProgressListener l) throws IOException { 80 GetMethod get = doGet(src); 81 FileUtil.copy(get.getResponseBodyAsStream(), dest, l); 82 get.releaseConnection(); 83 } 84 85 public URLInfo getURLInfo(URL url) { 86 return getURLInfo(url, 0); 87 } 88 89 public URLInfo getURLInfo(URL url, int timeout) { 90 HeadMethod head = null; 91 try { 92 head = doHead(url, timeout); 93 int status = head.getStatusCode(); 94 head.releaseConnection(); 95 if (status == HttpStatus.SC_OK) { 96 return new URLInfo(true, getResponseContentLength(head), getLastModified(head)); 97 } 98 if (status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { 99 Message.error("Your proxy requires authentication."); 100 }else if (String.valueOf(status).startsWith("4")) { 101 Message.verbose("CLIENT ERROR: "+head.getStatusText()+" url="+url); 102 }else if (String.valueOf(status).startsWith("5")) { 103 Message.warn("SERVER ERROR: "+head.getStatusText()+" url="+url); 104 } 105 Message.debug("HTTP response status: "+status +"="+head.getStatusText()+" url="+url); 106 } catch (HttpException e) { 107 Message.error("HttpClientHandler: "+e.getMessage()+":" + e.getReasonCode()+"="+e.getReason()+" url="+url); 108 } catch (UnknownHostException e) { 109 Message.warn("Host " + e.getMessage() +" not found. url="+url); 110 Message.info("You probably access the destination server through a proxy server that is not well configured."); 111 }catch (IOException e) { 112 Message.error("HttpClientHandler: "+e.getMessage()+" url="+url); 113 } finally{ 114 if(head != null) { 115 head.releaseConnection(); 116 } 117 } 118 return UNAVAILABLE; 119 } 120 121 private long getLastModified(HeadMethod head) { 122 Header header = head.getResponseHeader("last-modified"); 123 if (header != null) { 124 String lastModified = header.getValue(); 125 try { 126 return LAST_MODIFIED_FORMAT.parse(lastModified).getTime(); 127 } catch (ParseException e) { 128 } 129 return System.currentTimeMillis(); 130 } else { 131 return System.currentTimeMillis(); 132 } 133 } 134 135 private long getResponseContentLength(HeadMethod head) { 136 return getHttpClientHelper().getResponseContentLength(head); 137 } 138 139 private HttpClientHelper getHttpClientHelper() { 140 if (_httpClientHelper == null) { 141 try { 143 HttpMethodBase.class.getMethod("getResponseContentLength", new Class [0]); 144 _httpClientHelper = new HttpClientHelper3x(); 145 Message.verbose("using commons httpclient 3.x helper"); 146 } catch (SecurityException e) { 147 Message.verbose("unable to get access to getResponseContentLength of commons-httpclient HeadMethod. Please use commons-httpclient 3.0 or use ivy with sufficient security permissions."); 148 Message.verbose("exception: "+e.getMessage()); 149 _httpClientHelper = new HttpClientHelper2x(); 150 Message.verbose("using commons httpclient 2.x helper"); 151 } catch (NoSuchMethodException e) { 152 _httpClientHelper = new HttpClientHelper2x(); 153 Message.verbose("using commons httpclient 2.x helper"); 154 } 155 } 156 return _httpClientHelper; 157 } 158 159 public int getHttpClientMajorVersion() { 160 HttpClientHelper helper = getHttpClientHelper(); 161 return helper.getHttpClientMajorVersion(); 162 } 163 164 private GetMethod doGet(URL url) throws IOException , HttpException { 165 HttpClient client = getClient(url); 166 167 GetMethod get = new GetMethod(url.toExternalForm()); 168 get.setDoAuthentication(useAuthentication(url) || useProxyAuthentication()); 169 client.executeMethod(get); 170 return get; 171 } 172 173 private HeadMethod doHead(URL url, int timeout) throws IOException , HttpException { 174 HttpClient client = getClient(url); 175 client.setTimeout(timeout); 176 177 HeadMethod head = new HeadMethod(url.toExternalForm()); 178 head.setDoAuthentication(useAuthentication(url) || useProxyAuthentication()); 179 client.executeMethod(head); 180 return head; 181 } 182 183 private HttpClient getClient(URL url) { 184 HttpClient client = new HttpClient(); 185 186 List authPrefs = new ArrayList (2); 187 authPrefs.add(AuthPolicy.DIGEST); 188 authPrefs.add(AuthPolicy.BASIC); 189 client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs); 191 192 if (useProxy()) { 193 client.getHostConfiguration().setProxy(_proxyHost, _proxyPort); 194 if (useProxyAuthentication()) { 195 client.getState().setProxyCredentials(_proxyRealm, _proxyHost, 196 new UsernamePasswordCredentials(_proxyUserName, _proxyPasswd)); 197 } 198 } 199 Credentials c = getCredentials(url); 200 if (c != null) { 201 Message.debug("found credentials for "+url+": "+c); 202 client.getState().setCredentials( 203 c.getRealm(), 204 c.getHost(), 205 new UsernamePasswordCredentials(c.getUserName(), c.getPasswd()) 206 ); 207 } 208 return client; 209 } 210 211 private boolean useProxy() { 212 return _proxyHost != null && _proxyHost.trim().length() > 0; 213 } 214 private boolean useAuthentication(URL url) { 215 return getCredentials(url) != null; 216 } 217 218 private Credentials getCredentials(URL url) { 219 return CredentialsStore.INSTANCE.getCredentials(null, url.getHost()); 220 } 221 222 private boolean useProxyAuthentication() { 223 return (_proxyUserName != null && _proxyUserName.trim().length() > 0); 224 } 225 226 private static final class GETInputStream extends InputStream { 227 private InputStream _is; 228 private GetMethod _get; 229 230 private GETInputStream(GetMethod get) throws IOException { 231 _get = get; 232 _is = get.getResponseBodyAsStream(); 233 } 234 235 public int available() throws IOException { 236 return _is.available(); 237 } 238 239 public void close() throws IOException { 240 _is.close(); 241 _get.releaseConnection(); 242 } 243 244 public boolean equals(Object obj) { 245 return _is.equals(obj); 246 } 247 248 public int hashCode() { 249 return _is.hashCode(); 250 } 251 252 public void mark(int readlimit) { 253 _is.mark(readlimit); 254 } 255 256 public boolean markSupported() { 257 return _is.markSupported(); 258 } 259 260 public int read() throws IOException { 261 return _is.read(); 262 } 263 264 public int read(byte[] b, int off, int len) throws IOException { 265 return _is.read(b, off, len); 266 } 267 268 public int read(byte[] b) throws IOException { 269 return _is.read(b); 270 } 271 272 public void reset() throws IOException { 273 _is.reset(); 274 } 275 276 public long skip(long n) throws IOException { 277 return _is.skip(n); 278 } 279 280 public String toString() { 281 return _is.toString(); 282 } 283 } 284 private static final class HttpClientHelper3x implements HttpClientHelper { 285 private HttpClientHelper3x() { 286 } 287 288 public long getResponseContentLength(HeadMethod head) { 289 return head.getResponseContentLength(); 290 } 291 292 295 public int getHttpClientMajorVersion() { 296 return 3; 297 } 298 } 299 private static final class HttpClientHelper2x implements HttpClientHelper { 300 private HttpClientHelper2x() { 301 } 302 303 public long getResponseContentLength(HeadMethod head) { 304 Header header = head.getResponseHeader("Content-Length"); 305 if (header != null) { 306 try { 307 return Integer.parseInt(header.getValue()); 308 } catch (NumberFormatException e) { 309 Message.verbose("Invalid content-length value: " + e.getMessage()); 310 } 311 } 312 return 0; 313 } 314 315 318 public int getHttpClientMajorVersion() { 319 return 2; 320 } 321 } 322 public interface HttpClientHelper { 323 long getResponseContentLength(HeadMethod head); 324 int getHttpClientMajorVersion(); 325 } 326 } 327 | Popular Tags |