1 19 20 package com.maverick.http; 21 22 import java.io.EOFException ; 23 import java.io.IOException ; 24 import java.net.UnknownHostException ; 25 import java.text.MessageFormat ; 26 import java.util.Date ; 27 import java.util.Enumeration ; 28 import java.util.StringTokenizer ; 29 import java.util.Vector ; 30 31 35 public class HttpClient { 36 37 static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; 38 static final String AUTHORIZATION = "Authorization"; 39 static final String WWW_AUTHENTICATE = "WWW-Authenticate"; 40 static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; 41 42 public static final int PROXY_NONE = 0; 43 public static final int PROXY_HTTP = 1; 44 public static final int PROXY_HTTPS = 2; 45 46 public static String USER_AGENT = "Maverick-HttpClient/1.0"; 48 51 String hostname; 52 int port; 53 boolean isSecure; 54 PasswordCredentials credentials; 55 AuthenticationPrompt prompt; 56 String preferedAuthentication = HttpAuthenticatorFactory.BASIC; 57 boolean preemptiveAuthentication = false; 58 HttpConnectionManager connections = new HttpConnectionManager(this); 59 boolean includeCookies = true; 60 Vector cookies = new Vector (); 61 int maxAuthenticationAttempts = 5; 62 int proxyMaxAuthenticationAttempts = 5; 63 boolean proxyPreemptiveAuthentication = false; 64 HttpClient proxyClient; 65 boolean credentialsFailed = false; 66 67 70 String proxyHost; 71 int proxyPort = -1; 72 int proxyType = PROXY_NONE; 73 74 PasswordCredentials proxyCredentials; 75 AuthenticationPrompt proxyAuthenticationPrompt; 76 String proxyPreferedAuthentication = HttpAuthenticatorFactory.BASIC; 77 boolean isProxyClient = false; 78 79 static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(HttpClient.class); 81 82 84 public HttpClient(String hostname, int port, boolean isSecure) { 85 this.hostname = hostname; 86 this.port = port; 87 this.isSecure = isSecure; 88 89 } 90 91 96 public static void setUserAgent(String userAgent) { 97 USER_AGENT = userAgent; 98 } 99 100 HttpClient(HttpClient client) { 101 this(client.proxyHost, client.proxyPort, client.proxyType == HttpClient.PROXY_HTTPS); 102 setAuthenticationPrompt(client.proxyAuthenticationPrompt); 103 setCredentials(client.proxyCredentials); 104 setMaxAuthenticationAttempts(client.proxyMaxAuthenticationAttempts); 105 setPreemtiveAuthentication(client.proxyPreemptiveAuthentication); 106 setPreferredAuthentication(client.proxyPreferedAuthentication); 107 this.isProxyClient = true; 108 } 109 110 boolean configureProxy() { 111 115 if (!isProxyClient && !isNonProxiedHost(hostname)) { 116 if (System.getProperty("com.maverick.ssl.https.HTTPProxyHostname") != null) { setProxyHost(System.getProperty("com.maverick.ssl.https.HTTPProxyHostname")); log.debug(MessageFormat.format(Messages.getString("HttpClient.setClientProxyHost"), new Object [] { proxyHost })); 122 if (System.getProperty("com.maverick.ssl.https.HTTPProxyPort") != null) { setProxyPort(Integer.parseInt(System.getProperty("com.maverick.ssl.https.HTTPProxyPort"))); log.debug(MessageFormat.format(Messages.getString("HttpClient.setClientProxyPort"), new Object [] { new Integer (proxyPort) })); } else 128 setProxyPort(80); 129 130 if (System.getProperty("com.maverick.ssl.https.HTTPProxySecure") != null) { setProxyType(System.getProperty("com.maverick.ssl.https.HTTPProxySecure").equalsIgnoreCase("true") ? PROXY_HTTPS : PROXY_HTTP); 133 } else 134 setProxyType(PROXY_HTTP); 135 136 if (System.getProperty("com.maverick.ssl.https.HTTPProxyUsername") != null) { setProxyCredentials(new PasswordCredentials(System.getProperty("com.maverick.ssl.https.HTTPProxyUsername"), 138 System.getProperty("com.maverick.ssl.https.HTTPProxyPassword")==null ? "" : System.getProperty("com.maverick.ssl.https.HTTPProxyPassword"))); 139 } 140 141 return true; 142 } 143 } 144 145 return false; 146 } 147 148 public boolean isProxyConfigured() { 149 if (proxyType == PROXY_NONE) 150 return configureProxy(); 151 else 152 return true; 153 } 154 155 public static boolean isNonProxiedHost(String host) { 156 String nonProxiedHosts = System.getProperty("com.maverick.ssl.https.HTTPProxyNonProxyHosts"); if (nonProxiedHosts == null || nonProxiedHosts.equals("")) { return false; 159 } 160 StringTokenizer t = new StringTokenizer (nonProxiedHosts, "|"); while (t.hasMoreTokens()) { 162 String token = t.nextToken(); 163 int idx = token.indexOf('*'); 164 if (idx != -1) { 165 if (token.length() == 1) { 166 return true; 167 } 168 String before = token.substring(0, idx); 169 String after = token.substring(idx + 1); 170 if (((before.length() == 0) || host.startsWith(before)) && ((after.length() == 0) || host.endsWith(after))) { 171 return true; 172 } 173 } else { 174 if (host.equalsIgnoreCase(token)) { 175 return true; 176 } 177 } 178 } 179 return false; 180 } 181 182 public HttpConnectionManager getConnectionManager() { 183 return connections; 184 } 185 186 public String getHost() { 187 return hostname; 188 } 189 190 public int getPort() { 191 return port; 192 } 193 194 public boolean isSecure() { 195 return isSecure; 196 } 197 198 public void setMaxAuthenticationAttempts(int maxAuthenticationAttempts) { 199 this.maxAuthenticationAttempts = maxAuthenticationAttempts; 200 } 201 202 public void setProxyHost(String proxyHost) { 203 this.proxyHost = proxyHost; 204 } 205 206 public void setProxyPort(int proxyPort) { 207 this.proxyPort = proxyPort; 208 } 209 210 public void setProxyMaxAuthenticationAttempts(int proxyMaxAuthenticationAttempts) { 211 this.proxyMaxAuthenticationAttempts = proxyMaxAuthenticationAttempts; 212 } 213 214 public void setProxyType(int proxyType) { 215 if (proxyType > PROXY_HTTPS || proxyType < PROXY_NONE) { 216 throw new IllegalArgumentException (MessageFormat.format(Messages.getString("HttpClient.notValidProxyType"), new Object [] { new Integer (proxyType) })); } 218 this.proxyType = proxyType; 219 } 220 221 public void setProxyCredentials(PasswordCredentials proxyCredentials) { 222 this.proxyCredentials = proxyCredentials; 223 } 224 225 public void setProxyPreemptiveAuthentication(boolean proxyPreemptiveAuthentication) { 226 this.proxyPreemptiveAuthentication = proxyPreemptiveAuthentication; 227 } 228 229 public void setProxyAuthenticationPrompt(AuthenticationPrompt proxyAuthenticationPrompt) { 230 this.proxyAuthenticationPrompt = proxyAuthenticationPrompt; 231 } 232 233 public void setProxyPreferedAuthentication(String scheme) { 234 this.proxyPreferedAuthentication = scheme; 235 } 236 237 public void setAuthenticationPrompt(AuthenticationPrompt prompt) { 238 this.prompt = prompt; 239 } 240 241 public void setPreferredAuthentication(String scheme) { 242 this.preferedAuthentication = scheme; 243 } 244 245 public void setCredentials(PasswordCredentials credentials) { 246 this.credentials = credentials; 247 credentialsFailed = false; 248 } 249 250 public void close() { 251 connections.closeConnections(); 252 } 253 254 synchronized void prepareRequest(HttpRequest request, HttpMethod method, HttpConnection con) throws IOException , HttpException, 255 UnsupportedAuthenticationException, AuthenticationCancelledException { 256 257 if (con.isMonitoring()) { 258 con.monitor(method.getURI()); 259 } 260 261 request.reset(); 262 263 if (preemptiveAuthentication && credentials != null) { 264 BasicAuthentication authenticator = new BasicAuthentication(method.getURI(), con.getHost(), con.getPort(), con.isSecure()); 266 authenticator.setCredentials(credentials); 267 authenticator.setConnection(con); 268 authenticator.setChallenge("Basic"); authenticator.setAuthenicationHeader(method.getName().equals("CONNECT") ? PROXY_AUTHENTICATE : WWW_AUTHENTICATE); authenticator.setAuthorizationHeader(method.getName().equals("CONNECT") ? PROXY_AUTHORIZATION : AUTHORIZATION); con.setAuthenticator(authenticator); 272 } 273 274 connections.checkConnection(con); 275 276 if (includeCookies) { 277 String cookiesHeader = ""; for (Enumeration e = cookies.elements(); e.hasMoreElements();) { 279 Cookie cookie = (Cookie) e.nextElement(); 280 281 Date now = new Date (); 283 if (cookie.getExpires() == null || cookie.expires.after(now)) { 284 if (method.getURI().startsWith(cookie.getPath()) && getHost().endsWith(cookie.getDomain()) 285 && (cookie.isSecure() == isSecure || !cookie.isSecure())) { 286 cookiesHeader += cookie + "; "; } 288 } 289 } 290 291 if (!cookiesHeader.equals("")) { request.setHeaderField("Cookie", cookiesHeader); } 294 } 295 296 if (con.isKeepAlive()) 297 request.setHeaderField("Connection", "Keep-Alive"); 299 if (con.getAuthenticator() != null && con.getAuthenticator().canAuthenticate()) { 300 log.debug(MessageFormat.format(Messages.getString("HttpClient.settingAuthCredentials"), new Object [] { con.getAuthenticator().getScheme() })); try { 304 request.removeFields(con.getAuthenticator().getAuthorizationHeader()); 305 con.getAuthenticator().authenticate(request, method); 306 } catch (Exception ex) { 307 log.info(Messages.getString("HttpClient.authenticatorException"), ex); con.setAuthenticator(null); 311 } 312 } 313 314 } 315 316 HttpResponse execute(HttpRequest request, HttpMethod method, HttpConnection con) throws IOException , HttpException, 317 UnsupportedAuthenticationException, AuthenticationCancelledException { 318 319 prepareRequest(request, method, con); 320 321 log.info(MessageFormat.format(Messages.getString("HttpClient.executingMethod"), new Object [] { method.getName(), con.getHost() })); 325 return processResponse(request, method, con, method.execute(request, con)); 326 } 327 328 HttpConnection executeAsync(HttpRequest request, AsyncHttpMethod method, HttpConnection con) throws IOException , HttpException, 329 UnsupportedAuthenticationException, AuthenticationCancelledException { 330 331 prepareRequest(request, method, con); 332 333 log.info(MessageFormat.format(Messages.getString("HttpClient.executingMethod"), new Object [] { method.getName(), con.getHost() })); 337 method.executeAsync(request, con); 338 339 return con; 340 } 341 342 synchronized HttpResponse processResponse(HttpRequest request, HttpMethod method, HttpConnection con, HttpResponse response) 343 throws IOException , HttpException, UnsupportedAuthenticationException, AuthenticationCancelledException { 344 345 346 if (includeCookies) { 348 String [] cookies = response.getHeaderFields("Set-Cookie"); if (cookies != null) { 350 for (int i = 0; i < cookies.length; i++) { 351 this.cookies.addElement(new Cookie(cookies[i])); 352 } 353 } 354 } 355 356 try { 357 361 switch (response.getStatus()) { 362 case 401: 363 case 407: 364 if (con.getAuthenticator() != null) { 365 int success = con.getAuthenticator().processResponse(response); 366 367 switch (success) { 368 case HttpAuthenticator.AUTHENTICATION_COMPLETED: 369 return response; 371 case HttpAuthenticator.AUTHENTICATION_FAILED: 372 request.cycles++; 374 credentialsFailed = true; 375 break; 376 case HttpAuthenticator.AUTHENTICATION_IN_PROGRESS: 377 default: 378 } 380 381 } else if (credentials == null && prompt == null) { 382 return response; 383 } 384 385 if (con.getAuthenticator() == null || request.cycles < maxAuthenticationAttempts) 386 return doAuthentication(response.getStatus() == 401 ? WWW_AUTHENTICATE : PROXY_AUTHENTICATE, response .getStatus() == 401 ? AUTHORIZATION : PROXY_AUTHORIZATION, request, method, response, con); 389 else 390 return response; 391 default: 392 if (con.getAuthenticator() != null) { 394 credentials = con.getAuthenticator().credentials; 395 con.getAuthenticator().complete(); 396 } 397 return response; 398 399 } 400 } catch (UnsupportedAuthenticationException ex) { 401 405 return response; 406 } 407 } 408 409 private HttpResponse doAuthentication(String authenticateHeader, String authorizationHeader, HttpRequest request, 410 HttpMethod method, HttpResponse response, HttpConnection con) throws IOException , 411 HttpException, UnsupportedAuthenticationException, AuthenticationCancelledException { 412 413 if (credentialsFailed) { 415 con.setAuthenticator(null); 416 return response; 417 } 418 response.close(false); 420 421 String [] challenges = response.getHeaderFields(authenticateHeader); 423 424 if (challenges == null) 425 return response; 426 427 for (int i = 0; i < challenges.length; i++) { 429 log.info(MessageFormat.format(Messages.getString("HttpClient.requiresAuthType"), new Object [] { con.getHost(), HttpAuthenticatorFactory.getAuthenticationMethod(challenges[i]) })); } 431 433 436 if (credentials == null && prompt == null && con.getAuthenticator() == null) { 437 return response; 440 } 441 442 446 if (con.getAuthenticator() == null || !con.getAuthenticator().getURI().startsWith(method.getURI())) { 447 con.setAuthenticator(HttpAuthenticatorFactory.createAuthenticator(con, 448 challenges, 449 authenticateHeader, 450 authorizationHeader, 451 preferedAuthentication, 452 method.getURI())); 453 } 454 455 if (credentials != null) { 456 log.info(Messages.getString("HttpClient.settingUserCreds")); con.getAuthenticator().setCredentials(credentials); 460 } else if (prompt != null && con.getAuthenticator().wantsPrompt()) { 461 log.info(Messages.getString("HttpClient.promptingForCreds")); if (!prompt.promptForCredentials(authenticateHeader.equals(PROXY_AUTHENTICATE), con.getAuthenticator())) { 465 throw new AuthenticationCancelledException(); 466 } 467 } 468 469 if (!con.canReuse()) 470 con.reconnect(); 471 472 try { 473 return execute(request, method, con); 474 } catch (EOFException ex) { 475 con.reconnect(); 478 return execute(request, method, con); 479 } 480 } 481 482 public HttpResponse execute(HttpMethod method) throws UnknownHostException , IOException , HttpException, 483 UnsupportedAuthenticationException, AuthenticationCancelledException { 484 log.debug(MessageFormat.format(Messages.getString("HttpClient.executing"), new Object [] { method.getName() })); for (int i = 0; i < 2; i++) { 488 try { 489 return execute(method, connections.getConnection()); 490 } catch (EOFException eof) { 491 if (i != 1) { 493 log.warn(MessageFormat.format(Messages.getString("HttpClient.eof.attemptingAgain"), new Object [] { new Integer (i) })); } else { 495 log.warn(MessageFormat.format(Messages.getString("HttpClient.eof.givingUp"), new Object [] { new Integer (i) })); } 497 } 499 } 500 throw new EOFException (Messages.getString("HttpClient.couldNotConnect")); } 502 503 public HttpResponse execute(HttpMethod method, HttpConnection con) throws UnknownHostException , IOException , HttpException, 504 UnsupportedAuthenticationException, AuthenticationCancelledException { 505 return execute(new HttpRequest(), method, con); 506 } 507 508 public HttpConnection executeAsync(AsyncHttpMethod method) throws UnknownHostException , IOException , HttpException, 509 UnsupportedAuthenticationException, AuthenticationCancelledException { 510 return executeAsync(method, connections.getConnection()); 511 } 512 513 public HttpConnection executeAsync(AsyncHttpMethod method, HttpConnection con) throws UnknownHostException , IOException , HttpException, 514 UnsupportedAuthenticationException, AuthenticationCancelledException { 515 log.debug(MessageFormat.format(Messages.getString("HttpClient.executing"), new Object [] { method.getName() })); return executeAsync(new HttpRequest(), method, connections.getConnection()); 519 } 520 521 522 public void setIncludeCookies(boolean includeCookies) { 523 this.includeCookies = includeCookies; 524 } 525 526 public void setPreemtiveAuthentication(boolean preemptiveAuthentication) { 527 this.preemptiveAuthentication = preemptiveAuthentication; 528 } 529 530 public void removeAllCookies() { 531 cookies.removeAllElements(); 532 } 533 } 534 | Popular Tags |