1 31 32 package org.apache.commons.httpclient; 33 34 import java.io.ByteArrayInputStream ; 35 import java.io.ByteArrayOutputStream ; 36 import java.io.IOException ; 37 import java.io.InputStream ; 38 import java.io.InterruptedIOException ; 39 import java.util.HashSet ; 40 import java.util.Set ; 41 42 import org.apache.commons.httpclient.auth.AuthScheme; 43 import org.apache.commons.httpclient.auth.AuthenticationException; 44 import org.apache.commons.httpclient.auth.HttpAuthenticator; 45 import org.apache.commons.httpclient.auth.MalformedChallengeException; 46 import org.apache.commons.httpclient.auth.NTLMScheme; 47 import org.apache.commons.httpclient.cookie.CookiePolicy; 48 import org.apache.commons.httpclient.cookie.CookieSpec; 49 import org.apache.commons.httpclient.cookie.MalformedCookieException; 50 import org.apache.commons.httpclient.protocol.Protocol; 51 import org.apache.commons.httpclient.util.EncodingUtil; 52 import org.apache.commons.logging.Log; 53 import org.apache.commons.logging.LogFactory; 54 55 111 public abstract class HttpMethodBase implements HttpMethod { 112 113 114 private static final int MAX_FORWARDS = 100; 115 116 118 119 private static final Log LOG = LogFactory.getLog(HttpMethodBase.class); 120 121 122 protected static final Header USER_AGENT; 123 124 static { 125 String agent = null; 126 try { 127 agent = System.getProperty("httpclient.useragent"); 128 } catch (SecurityException ignore) { 129 } 130 if (agent == null) { 131 agent = "Jakarta Commons-HttpClient/2.0.1"; 132 } 133 USER_AGENT = new Header("User-Agent", agent); 134 } 135 136 138 139 private HeaderGroup requestHeaders = new HeaderGroup(); 140 141 142 private StatusLine statusLine = null; 143 144 145 private HeaderGroup responseHeaders = new HeaderGroup(); 146 147 148 private HeaderGroup responseTrailerHeaders = new HeaderGroup(); 149 150 151 private AuthScheme authScheme = null; 152 153 154 private Set realms = null; 155 156 157 private String realm = null; 158 159 160 private AuthScheme proxyAuthScheme = null; 161 162 163 private Set proxyRealms = null; 164 165 166 private String proxyRealm = null; 167 168 169 private String path = null; 170 171 172 private String queryString = null; 173 174 176 private InputStream responseStream = null; 177 178 179 private HttpConnection responseConnection = null; 180 181 182 private byte[] responseBody = null; 183 184 186 private boolean followRedirects = false; 187 188 190 private boolean doAuthentication = true; 191 192 193 private boolean http11 = true; 194 195 197 private boolean strictMode = false; 198 199 200 private boolean used = false; 201 202 204 private int recoverableExceptionCount = 0; 205 206 207 private HostConfiguration hostConfiguration; 208 209 212 private MethodRetryHandler methodRetryHandler; 213 214 215 private boolean inExecute = false; 216 217 218 private boolean doneWithConnection = false; 219 220 221 private boolean connectionCloseForced = false; 222 223 224 private static final int RESPONSE_WAIT_TIME_MS = 3000; 225 226 228 231 public HttpMethodBase() { 232 } 233 234 245 public HttpMethodBase(String uri) 246 throws IllegalArgumentException , IllegalStateException { 247 248 try { 249 250 if (uri == null || uri.equals("")) { 252 uri = "/"; 253 } 254 URI parsedURI = new URI(uri.toCharArray()); 255 256 if (parsedURI.isAbsoluteURI()) { 258 hostConfiguration = new HostConfiguration(); 259 hostConfiguration.setHost( 260 parsedURI.getHost(), 261 parsedURI.getPort(), 262 parsedURI.getScheme() 263 ); 264 } 265 266 setPath( 268 parsedURI.getPath() == null 269 ? "/" 270 : parsedURI.getEscapedPath() 271 ); 272 setQueryString(parsedURI.getEscapedQuery()); 273 274 } catch (URIException e) { 275 throw new IllegalArgumentException ("Invalid uri '" 276 + uri + "': " + e.getMessage() 277 ); 278 } 279 } 280 281 283 289 public abstract String getName(); 290 291 300 public URI getURI() throws URIException { 301 302 if (hostConfiguration == null) { 303 URI tmpUri = new URI(null, null, path, null, null); 305 tmpUri.setEscapedQuery(queryString); 306 return tmpUri; 307 } else { 308 309 int port = hostConfiguration.getPort(); 311 if (port == hostConfiguration.getProtocol().getDefaultPort()) { 312 port = -1; 313 } 314 315 URI tmpUri = new URI( 316 hostConfiguration.getProtocol().getScheme(), 317 null, 318 hostConfiguration.getHost(), 319 port, 320 path, 321 null ); 323 tmpUri.setEscapedQuery(queryString); 324 return tmpUri; 325 326 } 327 328 } 329 330 337 public void setFollowRedirects(boolean followRedirects) { 338 this.followRedirects = followRedirects; 339 } 340 341 348 public boolean getFollowRedirects() { 349 return this.followRedirects; 350 } 351 352 357 public void setHttp11(boolean http11) { 358 this.http11 = http11; 359 } 360 361 370 public boolean getDoAuthentication() { 371 return doAuthentication; 372 } 373 374 383 public void setDoAuthentication(boolean doAuthentication) { 384 this.doAuthentication = doAuthentication; 385 } 386 387 389 395 public boolean isHttp11() { 396 return http11; 397 } 398 399 407 public void setPath(String path) { 408 this.path = path; 409 } 410 411 417 public void addRequestHeader(Header header) { 418 LOG.trace("HttpMethodBase.addRequestHeader(Header)"); 419 420 if (header == null) { 421 LOG.debug("null header value ignored"); 422 } else { 423 getRequestHeaderGroup().addHeader(header); 424 } 425 } 426 427 432 public void addResponseFooter(Header footer) { 433 getResponseTrailerHeaderGroup().addHeader(footer); 434 } 435 436 444 public String getPath() { 445 return (path == null || path.equals("")) ? "/" : path; 446 } 447 448 457 public void setQueryString(String queryString) { 458 this.queryString = queryString; 459 } 460 461 473 public void setQueryString(NameValuePair[] params) { 474 LOG.trace("enter HttpMethodBase.setQueryString(NameValuePair[])"); 475 queryString = EncodingUtil.formUrlEncode(params, "UTF-8"); 476 } 477 478 483 public String getQueryString() { 484 return queryString; 485 } 486 487 494 public void setRequestHeader(String headerName, String headerValue) { 495 Header header = new Header(headerName, headerValue); 496 setRequestHeader(header); 497 } 498 499 505 public void setRequestHeader(Header header) { 506 507 Header[] headers = getRequestHeaderGroup().getHeaders(header.getName()); 508 509 for (int i = 0; i < headers.length; i++) { 510 getRequestHeaderGroup().removeHeader(headers[i]); 511 } 512 513 getRequestHeaderGroup().addHeader(header); 514 515 } 516 517 527 public Header getRequestHeader(String headerName) { 528 if (headerName == null) { 529 return null; 530 } else { 531 return getRequestHeaderGroup().getCondensedHeader(headerName); 532 } 533 } 534 535 540 public Header[] getRequestHeaders() { 541 return getRequestHeaderGroup().getAllHeaders(); 542 } 543 544 551 protected HeaderGroup getRequestHeaderGroup() { 552 return requestHeaders; 553 } 554 555 563 protected HeaderGroup getResponseTrailerHeaderGroup() { 564 return responseTrailerHeaders; 565 } 566 567 574 protected HeaderGroup getResponseHeaderGroup() { 575 return responseHeaders; 576 } 577 578 583 public int getStatusCode() { 584 return statusLine.getStatusCode(); 585 } 586 587 593 public StatusLine getStatusLine() { 594 return statusLine; 595 } 596 597 601 private boolean responseAvailable() { 602 return (responseBody != null) || (responseStream != null); 603 } 604 605 611 public Header[] getResponseHeaders() { 612 return getResponseHeaderGroup().getAllHeaders(); 613 } 614 615 625 public Header getResponseHeader(String headerName) { 626 if (headerName == null) { 627 return null; 628 } else { 629 return getResponseHeaderGroup().getCondensedHeader(headerName); 630 } 631 } 632 633 634 647 protected int getResponseContentLength() { 648 Header[] headers = getResponseHeaderGroup().getHeaders("Content-Length"); 649 if (headers.length == 0) { 650 return -1; 651 } 652 if (headers.length > 1) { 653 LOG.warn("Multiple content-length headers detected"); 654 } 655 for (int i = headers.length - 1; i >= 0; i--) { 656 Header header = headers[i]; 657 try { 658 return Integer.parseInt(header.getValue()); 659 } catch (NumberFormatException e) { 660 if (LOG.isWarnEnabled()) { 661 LOG.warn("Invalid content-length value: " + e.getMessage()); 662 } 663 } 664 } 666 return -1; 667 } 668 669 670 676 public byte[] getResponseBody() { 677 if (this.responseBody == null) { 678 try { 679 InputStream instream = getResponseBodyAsStream(); 680 if (instream != null) { 681 LOG.debug("Buffering response body"); 682 ByteArrayOutputStream outstream = new ByteArrayOutputStream (); 683 byte[] buffer = new byte[4096]; 684 int len; 685 while ((len = instream.read(buffer)) > 0) { 686 outstream.write(buffer, 0, len); 687 } 688 outstream.close(); 689 setResponseStream(null); 690 this.responseBody = outstream.toByteArray(); 691 } 692 } catch (IOException e) { 693 LOG.error("I/O failure reading response body", e); 694 this.responseBody = null; 695 } 696 } 697 return this.responseBody; 698 } 699 700 709 public InputStream getResponseBodyAsStream() throws IOException { 710 if (responseStream != null) { 711 return responseStream; 712 } 713 if (responseBody != null) { 714 InputStream byteResponseStream = new ByteArrayInputStream (responseBody); 715 LOG.debug("re-creating response stream from byte array"); 716 return byteResponseStream; 717 } 718 return null; 719 } 720 721 729 public String getResponseBodyAsString() { 730 byte[] rawdata = null; 731 if (responseAvailable()) { 732 rawdata = getResponseBody(); 733 } 734 if (rawdata != null) { 735 return HttpConstants.getContentString(rawdata, getResponseCharSet()); 736 } else { 737 return null; 738 } 739 } 740 741 747 public Header[] getResponseFooters() { 748 return getResponseTrailerHeaderGroup().getAllHeaders(); 749 } 750 751 763 public Header getResponseFooter(String footerName) { 764 if (footerName == null) { 765 return null; 766 } else { 767 return getResponseTrailerHeaderGroup().getCondensedHeader(footerName); 768 } 769 } 770 771 775 protected void setResponseStream(InputStream responseStream) { 776 this.responseStream = responseStream; 777 } 778 779 787 protected InputStream getResponseStream() { 788 return responseStream; 789 } 790 791 797 public String getStatusText() { 798 return statusLine.getReasonPhrase(); 799 } 800 801 810 public void setStrictMode(boolean strictMode) { 811 this.strictMode = strictMode; 812 } 813 814 819 public boolean isStrictMode() { 820 return strictMode; 821 } 822 823 830 public void addRequestHeader(String headerName, String headerValue) { 831 addRequestHeader(new Header(headerName, headerValue)); 832 } 833 834 839 protected boolean isConnectionCloseForced() { 840 return this.connectionCloseForced; 841 } 842 843 851 protected void setConnectionCloseForced(boolean b) { 852 if (LOG.isDebugEnabled()) { 853 LOG.debug("Force-close connection: " + b); 854 } 855 this.connectionCloseForced = b; 856 } 857 858 867 protected boolean shouldCloseConnection(HttpConnection conn) { 868 869 if (isConnectionCloseForced()) { 871 LOG.debug("Should force-close connection."); 872 return true; 873 } 874 875 Header connectionHeader = null; 876 if (!conn.isTransparent()) { 878 connectionHeader = responseHeaders.getFirstHeader("proxy-connection"); 880 } 881 if (connectionHeader == null) { 885 connectionHeader = responseHeaders.getFirstHeader("connection"); 886 } 887 if (connectionHeader != null) { 888 if (connectionHeader.getValue().equalsIgnoreCase("close")) { 889 if (LOG.isDebugEnabled()) { 890 LOG.debug("Should close connection in response to " 891 + connectionHeader.toExternalForm()); 892 } 893 return true; 894 } else if (connectionHeader.getValue().equalsIgnoreCase("keep-alive")) { 895 if (LOG.isDebugEnabled()) { 896 LOG.debug("Should NOT close connection in response to " 897 + connectionHeader.toExternalForm()); 898 } 899 return false; 900 } else { 901 if (LOG.isDebugEnabled()) { 902 LOG.debug("Unknown directive: " + connectionHeader.toExternalForm()); 903 } 904 } 905 } 906 LOG.debug("Resorting to protocol version default close connection policy"); 907 if (http11) { 909 LOG.debug("Should NOT close connection, using HTTP/1.1."); 910 } else { 911 LOG.debug("Should close connection, using HTTP/1.0."); 912 } 913 return !http11; 914 } 915 916 923 private boolean isRetryNeeded(int statusCode, HttpState state, HttpConnection conn) { 924 switch (statusCode) { 925 case HttpStatus.SC_UNAUTHORIZED: 926 case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: 927 LOG.debug("Authorization required"); 928 if (doAuthentication) { if (processAuthenticationResponse(state, conn)) { 932 return false; 933 } 934 } else { return false; 936 } 937 break; 938 939 case HttpStatus.SC_MOVED_TEMPORARILY: 940 case HttpStatus.SC_MOVED_PERMANENTLY: 941 case HttpStatus.SC_SEE_OTHER: 942 case HttpStatus.SC_TEMPORARY_REDIRECT: 943 LOG.debug("Redirect required"); 944 945 if (!processRedirectResponse(conn)) { 946 return false; 947 } 948 break; 949 950 default: 951 return false; 953 } 955 return true; 956 } 957 958 965 private void checkExecuteConditions(HttpState state, HttpConnection conn) 966 throws HttpException { 967 968 if (state == null) { 969 throw new IllegalArgumentException ("HttpState parameter may not be null"); 970 } 971 if (conn == null) { 972 throw new IllegalArgumentException ("HttpConnection parameter may not be null"); 973 } 974 if (hasBeenUsed()) { 975 throw new HttpException("Already used, but not recycled."); 976 } 977 if (!validate()) { 978 throw new HttpException("Not valid"); 979 } 980 if (inExecute) { 981 throw new IllegalStateException ("Execute invoked recursively, or exited abnormally."); 982 } 983 } 984 985 1010 public int execute(HttpState state, HttpConnection conn) 1011 throws HttpException, HttpRecoverableException, 1012 IOException { 1013 1014 LOG.trace("enter HttpMethodBase.execute(HttpState, HttpConnection)"); 1015 1016 this.responseConnection = conn; 1019 1020 checkExecuteConditions(state, conn); 1021 inExecute = true; 1022 1023 try { 1024 if (state.isAuthenticationPreemptive()) { 1026 1027 LOG.debug("Preemptively sending default basic credentials"); 1028 1029 try { 1030 if (HttpAuthenticator.authenticateDefault(this, conn, state)) { 1031 LOG.debug("Default basic credentials applied"); 1032 } else { 1033 LOG.warn("Preemptive authentication failed"); 1034 } 1035 if (conn.isProxied()) { 1036 if (HttpAuthenticator.authenticateProxyDefault(this, conn, state)) { 1037 LOG.debug("Default basic proxy credentials applied"); 1038 } else { 1039 LOG.warn("Preemptive proxy authentication failed"); 1040 } 1041 } 1042 } catch (AuthenticationException e) { 1043 LOG.error(e.getMessage(), e); 1045 } 1046 } 1047 1048 realms = new HashSet (); 1049 proxyRealms = new HashSet (); 1050 int forwardCount = 0; 1052 while (forwardCount++ < MAX_FORWARDS) { 1053 conn.setLastResponseInputStream(null); 1055 1056 if (LOG.isDebugEnabled()) { 1057 LOG.debug("Execute loop try " + forwardCount); 1058 } 1059 1060 this.statusLine = null; 1062 this.connectionCloseForced = false; 1063 1064 processRequest(state, conn); 1066 1067 if (!isRetryNeeded(statusLine.getStatusCode(), state, conn)) { 1068 break; 1070 } 1071 1072 if (responseStream != null) { 1076 responseStream.close(); 1077 } 1078 1079 } 1081 if (forwardCount >= MAX_FORWARDS) { 1082 LOG.error("Narrowly avoided an infinite loop in execute"); 1083 throw new HttpRecoverableException("Maximum redirects (" 1084 + MAX_FORWARDS + ") exceeded"); 1085 } 1086 1087 } finally { 1088 inExecute = false; 1089 if (doneWithConnection) { 1095 ensureConnectionRelease(); 1096 } 1097 } 1098 1099 return statusLine.getStatusCode(); 1100 } 1101 1102 1109 private boolean processRedirectResponse(HttpConnection conn) { 1110 1111 if (!getFollowRedirects()) { 1112 LOG.info("Redirect requested but followRedirects is " 1113 + "disabled"); 1114 return false; 1115 } 1116 1117 Header locationHeader = getResponseHeader("location"); 1119 if (locationHeader == null) { 1120 LOG.error("Received redirect response " + getStatusCode() 1122 + " but no location header"); 1123 return false; 1124 } 1125 String location = locationHeader.getValue(); 1126 if (LOG.isDebugEnabled()) { 1127 LOG.debug("Redirect requested to location '" + location 1128 + "'"); 1129 } 1130 1131 URI redirectUri = null; 1134 URI currentUri = null; 1135 1136 try { 1137 currentUri = new URI( 1138 conn.getProtocol().getScheme(), 1139 null, 1140 conn.getHost(), 1141 conn.getPort(), 1142 this.getPath() 1143 ); 1144 redirectUri = new URI(location.toCharArray()); 1145 if (redirectUri.isRelativeURI()) { 1146 if (isStrictMode()) { 1147 LOG.warn("Redirected location '" + location 1148 + "' is not acceptable in strict mode"); 1149 return false; 1150 } else { 1151 LOG.debug("Redirect URI is not absolute - parsing as relative"); 1153 redirectUri = new URI(currentUri, redirectUri); 1154 } 1155 } 1156 } catch (URIException e) { 1157 LOG.warn("Redirected location '" + location + "' is malformed"); 1158 return false; 1159 } 1160 1161 try { 1163 checkValidRedirect(currentUri, redirectUri); 1164 } catch (HttpException ex) { 1165 LOG.warn(ex.getMessage()); 1167 return false; 1168 } 1169 1170 this.realms.clear(); 1172 if (this.proxyAuthScheme instanceof NTLMScheme) { 1174 removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); 1175 } 1176 removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); 1177 setPath(redirectUri.getEscapedPath()); 1181 setQueryString(redirectUri.getEscapedQuery()); 1182 1183 if (LOG.isDebugEnabled()) { 1184 LOG.debug("Redirecting from '" + currentUri.getEscapedURI() 1185 + "' to '" + redirectUri.getEscapedURI()); 1186 } 1187 1188 return true; 1189 } 1190 1191 1200 private static void checkValidRedirect(URI currentUri, URI redirectUri) 1201 throws HttpException { 1202 LOG.trace("enter HttpMethodBase.checkValidRedirect(HttpConnection, URL)"); 1203 1204 String oldProtocol = currentUri.getScheme(); 1205 String newProtocol = redirectUri.getScheme(); 1206 if (!oldProtocol.equals(newProtocol)) { 1207 throw new HttpException("Redirect from protocol " + oldProtocol 1208 + " to " + newProtocol + " is not supported"); 1209 } 1210 1211 try { 1212 String oldHost = currentUri.getHost(); 1213 String newHost = redirectUri.getHost(); 1214 if (!oldHost.equalsIgnoreCase(newHost)) { 1215 throw new HttpException("Redirect from host " + oldHost 1216 + " to " + newHost + " is not supported"); 1217 } 1218 } catch (URIException e) { 1219 LOG.warn("Error getting URI host", e); 1220 throw new HttpException("Invalid Redirect URI from: " 1221 + currentUri.getEscapedURI() + " to: " + redirectUri.getEscapedURI() 1222 ); 1223 } 1224 1225 int oldPort = currentUri.getPort(); 1226 if (oldPort < 0) { 1227 oldPort = getDefaultPort(oldProtocol); 1228 } 1229 int newPort = redirectUri.getPort(); 1230 if (newPort < 0) { 1231 newPort = getDefaultPort(newProtocol); 1232 } 1233 if (oldPort != newPort) { 1234 throw new HttpException("Redirect from port " + oldPort 1235 + " to " + newPort + " is not supported"); 1236 } 1237 } 1238 1239 1249 private static int getDefaultPort(String protocol) { 1250 String proto = protocol.toLowerCase().trim(); 1251 if (proto.equals("http")) { 1252 return 80; 1253 } else if (proto.equals("https")) { 1254 return 443; 1255 } 1256 return -1; 1257 } 1258 1259 1265 public boolean hasBeenUsed() { 1266 return used; 1267 } 1268 1269 1280 public void recycle() { 1281 LOG.trace("enter HttpMethodBase.recycle()"); 1282 1283 releaseConnection(); 1284 1285 path = null; 1286 followRedirects = false; 1287 doAuthentication = true; 1288 authScheme = null; 1289 realm = null; 1290 proxyAuthScheme = null; 1291 proxyRealm = null; 1292 queryString = null; 1293 getRequestHeaderGroup().clear(); 1294 getResponseHeaderGroup().clear(); 1295 getResponseTrailerHeaderGroup().clear(); 1296 statusLine = null; 1297 used = false; 1298 http11 = true; 1299 responseBody = null; 1300 recoverableExceptionCount = 0; 1301 inExecute = false; 1302 doneWithConnection = false; 1303 connectionCloseForced = false; 1304 } 1305 1306 1314 public void releaseConnection() { 1315 1316 if (responseStream != null) { 1317 try { 1318 responseStream.close(); 1320 } catch (IOException e) { 1321 ensureConnectionRelease(); 1323 } 1324 } else { 1325 ensureConnectionRelease(); 1329 } 1330 } 1331 1332 1338 public void removeRequestHeader(String headerName) { 1339 1340 Header[] headers = getRequestHeaderGroup().getHeaders(headerName); 1341 for (int i = 0; i < headers.length; i++) { 1342 getRequestHeaderGroup().removeHeader(headers[i]); 1343 } 1344 1345 } 1346 1347 1349 1354 public boolean validate() { 1355 return true; 1356 } 1357 1358 1373 protected int getRequestContentLength() { 1374 return 0; 1375 } 1376 1377 1391 protected void addAuthorizationRequestHeader(HttpState state, 1392 HttpConnection conn) 1393 throws IOException , HttpException { 1394 LOG.trace("enter HttpMethodBase.addAuthorizationRequestHeader(" 1395 + "HttpState, HttpConnection)"); 1396 1397 if (getRequestHeader(HttpAuthenticator.WWW_AUTH_RESP) == null) { 1399 Header[] challenges = getResponseHeaderGroup().getHeaders( 1400 HttpAuthenticator.WWW_AUTH); 1401 if (challenges.length > 0) { 1402 try { 1403 this.authScheme = HttpAuthenticator.selectAuthScheme(challenges); 1404 HttpAuthenticator.authenticate(this.authScheme, this, conn, state); 1405 } catch (HttpException e) { 1406 if (LOG.isErrorEnabled()) { 1408 LOG.error(e.getMessage(), e); 1409 } 1410 } 1411 } 1412 } 1413 } 1414 1415 1430 protected void addContentLengthRequestHeader(HttpState state, 1431 HttpConnection conn) 1432 throws IOException , HttpException { 1433 LOG.trace("enter HttpMethodBase.addContentLengthRequestHeader(" 1434 + "HttpState, HttpConnection)"); 1435 1436 int len = getRequestContentLength(); 1438 if (getRequestHeader("content-length") == null) { 1439 if (0 < len) { 1440 setRequestHeader("Content-Length", String.valueOf(len)); 1441 } else if (http11 && (len < 0)) { 1442 setRequestHeader("Transfer-Encoding", "chunked"); 1443 } 1444 } 1445 } 1446 1447 1461 protected void addCookieRequestHeader(HttpState state, HttpConnection conn) 1462 throws IOException , HttpException { 1463 1464 LOG.trace("enter HttpMethodBase.addCookieRequestHeader(HttpState, " 1465 + "HttpConnection)"); 1466 1467 removeRequestHeader("cookie"); 1469 1470 CookieSpec matcher = CookiePolicy.getSpecByPolicy(state.getCookiePolicy()); 1471 Cookie[] cookies = matcher.match(conn.getHost(), conn.getPort(), 1472 getPath(), conn.isSecure(), state.getCookies()); 1473 if ((cookies != null) && (cookies.length > 0)) { 1474 if (this.isStrictMode()) { 1475 getRequestHeaderGroup().addHeader( 1477 matcher.formatCookieHeader(cookies)); 1478 } else { 1479 for (int i = 0; i < cookies.length; i++) { 1481 getRequestHeaderGroup().addHeader( 1482 matcher.formatCookieHeader(cookies[i])); 1483 } 1484 } 1485 } 1486 } 1487 1488 1502 protected void addHostRequestHeader(HttpState state, HttpConnection conn) 1503 throws IOException , HttpException { 1504 LOG.trace("enter HttpMethodBase.addHostRequestHeader(HttpState, " 1505 + "HttpConnection)"); 1506 1507 String host = conn.getVirtualHost(); 1512 if (host != null) { 1513 LOG.debug("Using virtual host name: " + host); 1514 } else { 1515 host = conn.getHost(); 1516 } 1517 int port = conn.getPort(); 1518 1519 if (getRequestHeader("host") != null) { 1520 LOG.debug( 1521 "Request to add Host header ignored: header already added"); 1522 return; 1523 } 1524 1525 if (LOG.isDebugEnabled()) { 1534 LOG.debug("Adding Host request header"); 1535 } 1536 1537 if (conn.getProtocol().getDefaultPort() != port) { 1539 host += (":" + port); 1540 } 1541 1542 setRequestHeader("Host", host); 1543 } 1544 1545 1559 protected void addProxyAuthorizationRequestHeader(HttpState state, 1560 HttpConnection conn) 1561 throws IOException , HttpException { 1562 LOG.trace("enter HttpMethodBase.addProxyAuthorizationRequestHeader(" 1563 + "HttpState, HttpConnection)"); 1564 1565 if (getRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP) == null) { 1567 Header[] challenges = getResponseHeaderGroup().getHeaders( 1568 HttpAuthenticator.PROXY_AUTH); 1569 if (challenges.length > 0) { 1570 try { 1571 this.proxyAuthScheme = HttpAuthenticator.selectAuthScheme(challenges); 1572 HttpAuthenticator.authenticateProxy(this.proxyAuthScheme, this, conn, state); 1573 } catch (HttpException e) { 1574 if (LOG.isErrorEnabled()) { 1576 LOG.error(e.getMessage(), e); 1577 } 1578 } 1579 } 1580 } 1581 } 1582 1583 1597 protected void addProxyConnectionHeader(HttpState state, 1598 HttpConnection conn) 1599 throws IOException , HttpException { 1600 LOG.trace("enter HttpMethodBase.addProxyConnectionHeader(" 1601 + "HttpState, HttpConnection)"); 1602 if (!conn.isTransparent()) { 1603 setRequestHeader("Proxy-Connection", "Keep-Alive"); 1604 } 1605 } 1606 1607 1635 protected void addRequestHeaders(HttpState state, HttpConnection conn) 1636 throws IOException , HttpException { 1637 LOG.trace("enter HttpMethodBase.addRequestHeaders(HttpState, " 1638 + "HttpConnection)"); 1639 1640 addUserAgentRequestHeader(state, conn); 1641 addHostRequestHeader(state, conn); 1642 addCookieRequestHeader(state, conn); 1643 addAuthorizationRequestHeader(state, conn); 1644 addProxyAuthorizationRequestHeader(state, conn); 1645 addProxyConnectionHeader(state, conn); 1646 addContentLengthRequestHeader(state, conn); 1647 } 1648 1649 1663 protected void addUserAgentRequestHeader(HttpState state, 1664 HttpConnection conn) 1665 throws IOException , HttpException { 1666 LOG.trace("enter HttpMethodBase.addUserAgentRequestHeaders(HttpState, " 1667 + "HttpConnection)"); 1668 1669 if (getRequestHeader("user-agent") == null) { 1670 setRequestHeader(HttpMethodBase.USER_AGENT); 1671 } 1672 } 1673 1674 1681 protected void checkNotUsed() throws IllegalStateException { 1682 if (used) { 1683 throw new IllegalStateException ("Already used."); 1684 } 1685 } 1686 1687 1694 protected void checkUsed() throws IllegalStateException { 1695 if (!used) { 1696 throw new IllegalStateException ("Not Used."); 1697 } 1698 } 1699 1700 1702 1714 protected static String generateRequestLine(HttpConnection connection, 1715 String name, String requestPath, String query, String version) { 1716 LOG.trace("enter HttpMethodBase.generateRequestLine(HttpConnection, " 1717 + "String, String, String, String)"); 1718 1719 StringBuffer buf = new StringBuffer (); 1720 buf.append(name); 1722 buf.append(" "); 1723 if (!connection.isTransparent()) { 1725 Protocol protocol = connection.getProtocol(); 1726 buf.append(protocol.getScheme().toLowerCase()); 1727 buf.append("://"); 1728 buf.append(connection.getHost()); 1729 if ((connection.getPort() != -1) 1730 && (connection.getPort() != protocol.getDefaultPort()) 1731 ) { 1732 buf.append(":"); 1733 buf.append(connection.getPort()); 1734 } 1735 } 1736 if (requestPath == null) { 1738 buf.append("/"); 1739 } else { 1740 if (!connection.isTransparent() && !requestPath.startsWith("/")) { 1741 buf.append("/"); 1742 } 1743 buf.append(requestPath); 1744 } 1745 if (query != null) { 1747 if (query.indexOf("?") != 0) { 1748 buf.append("?"); 1749 } 1750 buf.append(query); 1751 } 1752 buf.append(" "); 1754 buf.append(version); 1755 buf.append("\r\n"); 1756 1757 return buf.toString(); 1758 } 1759 1760 1776 protected void processResponseBody(HttpState state, HttpConnection conn) { 1777 } 1778 1779 1797 protected void processResponseHeaders(HttpState state, 1798 HttpConnection conn) { 1799 LOG.trace("enter HttpMethodBase.processResponseHeaders(HttpState, " 1800 + "HttpConnection)"); 1801 1802 Header[] headers = getResponseHeaderGroup().getHeaders("set-cookie2"); 1803 if (headers.length == 0) { 1806 headers = getResponseHeaderGroup().getHeaders("set-cookie"); 1807 } 1808 1809 CookieSpec parser = CookiePolicy.getSpecByPolicy(state.getCookiePolicy()); 1810 for (int i = 0; i < headers.length; i++) { 1811 Header header = headers[i]; 1812 Cookie[] cookies = null; 1813 try { 1814 cookies = parser.parse( 1815 conn.getHost(), 1816 conn.getPort(), 1817 getPath(), 1818 conn.isSecure(), 1819 header); 1820 } catch (MalformedCookieException e) { 1821 if (LOG.isWarnEnabled()) { 1822 LOG.warn("Invalid cookie header: \"" 1823 + header.getValue() 1824 + "\". " + e.getMessage()); 1825 } 1826 } 1827 if (cookies != null) { 1828 for (int j = 0; j < cookies.length; j++) { 1829 Cookie cookie = cookies[j]; 1830 try { 1831 parser.validate( 1832 conn.getHost(), 1833 conn.getPort(), 1834 getPath(), 1835 conn.isSecure(), 1836 cookie); 1837 state.addCookie(cookie); 1838 if (LOG.isDebugEnabled()) { 1839 LOG.debug("Cookie accepted: \"" 1840 + parser.formatCookie(cookie) + "\""); 1841 } 1842 } catch (MalformedCookieException e) { 1843 if (LOG.isWarnEnabled()) { 1844 LOG.warn("Cookie rejected: \"" + parser.formatCookie(cookie) 1845 + "\". " + e.getMessage()); 1846 } 1847 } 1848 } 1849 } 1850 } 1851 } 1852 1853 1865 protected void processStatusLine(HttpState state, HttpConnection conn) { 1866 } 1867 1868 1916 protected void readResponse(HttpState state, HttpConnection conn) 1917 throws HttpException { 1918 LOG.trace( 1919 "enter HttpMethodBase.readResponse(HttpState, HttpConnection)"); 1920 try { 1921 while (this.statusLine == null) { 1924 readStatusLine(state, conn); 1925 processStatusLine(state, conn); 1926 readResponseHeaders(state, conn); 1927 processResponseHeaders(state, conn); 1928 1929 int status = this.statusLine.getStatusCode(); 1930 if ((status >= 100) && (status < 200)) { 1931 if (LOG.isInfoEnabled()) { 1932 LOG.info("Discarding unexpected response: " + this.statusLine.toString()); 1933 } 1934 this.statusLine = null; 1935 } 1936 } 1937 readResponseBody(state, conn); 1938 processResponseBody(state, conn); 1939 } catch (IOException e) { 1940 throw new HttpRecoverableException(e.toString()); 1941 } 1942 } 1943 1944 1972 protected void readResponseBody(HttpState state, HttpConnection conn) 1973 throws IOException , HttpException { 1974 LOG.trace( 1975 "enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)"); 1976 1977 doneWithConnection = false; 1979 InputStream stream = readResponseBody(conn); 1980 if (stream == null) { 1981 responseBodyConsumed(); 1983 } else { 1984 conn.setLastResponseInputStream(stream); 1985 setResponseStream(stream); 1986 } 1987 } 1988 1989 2008 private InputStream readResponseBody(HttpConnection conn) 2009 throws IOException { 2010 2011 LOG.trace("enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)"); 2012 2013 responseBody = null; InputStream is = conn.getResponseInputStream(); 2015 if (Wire.CONTENT_WIRE.enabled()) { 2016 is = new WireLogInputStream(is, Wire.CONTENT_WIRE); 2017 } 2018 InputStream result = null; 2019 Header transferEncodingHeader = responseHeaders.getFirstHeader("Transfer-Encoding"); 2020 if (transferEncodingHeader != null) { 2023 2024 String transferEncoding = transferEncodingHeader.getValue(); 2025 if (!"chunked".equalsIgnoreCase(transferEncoding) 2026 && !"identity".equalsIgnoreCase(transferEncoding)) { 2027 if (LOG.isWarnEnabled()) { 2028 LOG.warn("Unsupported transfer encoding: " + transferEncoding); 2029 } 2030 } 2031 HeaderElement[] encodings = transferEncodingHeader.getValues(); 2032 int len = encodings.length; 2035 if ((len > 0) && ("chunked".equalsIgnoreCase(encodings[len - 1].getName()))) { 2036 if (conn.isResponseAvailable(conn.getSoTimeout())) { 2038 result = new ChunkedInputStream(is, this); 2039 } else { 2040 if (isStrictMode()) { 2041 throw new HttpException("Chunk-encoded body declared but not sent"); 2042 } else { 2043 LOG.warn("Chunk-encoded body missing"); 2044 } 2045 } 2046 } else { 2047 if (LOG.isWarnEnabled()) { 2048 LOG.warn("Transfer-Encoding is set but does not contain \"chunked\": " 2049 + transferEncoding); 2050 } 2051 setConnectionCloseForced(true); 2054 result = is; 2055 } 2056 } else { 2057 int expectedLength = getResponseContentLength(); 2058 if (expectedLength == -1) { 2059 if (canResponseHaveBody(statusLine.getStatusCode())) { 2060 Header connectionHeader = responseHeaders.getFirstHeader("Connection"); 2061 String connectionDirective = null; 2062 if (connectionHeader != null) { 2063 connectionDirective = connectionHeader.getValue(); 2064 } 2065 if (!"close".equalsIgnoreCase(connectionDirective)) { 2066 LOG.warn("Response content length is not known"); 2067 setConnectionCloseForced(true); 2068 } 2069 result = is; 2070 } 2071 } else { 2072 result = new ContentLengthInputStream(is, expectedLength); 2073 } 2074 } 2075 if (result != null) { 2079 2080 result = new AutoCloseInputStream( 2081 result, 2082 new ResponseConsumedWatcher() { 2083 public void responseConsumed() { 2084 responseBodyConsumed(); 2085 } 2086 } 2087 ); 2088 } 2089 2090 return result; 2091 } 2092 2093 2121 protected void readResponseHeaders(HttpState state, HttpConnection conn) 2122 throws IOException , HttpException { 2123 LOG.trace("enter HttpMethodBase.readResponseHeaders(HttpState," 2124 + "HttpConnection)"); 2125 2126 getResponseHeaderGroup().clear(); 2127 Header[] headers = HttpParser.parseHeaders(conn.getResponseInputStream()); 2128 if (Wire.HEADER_WIRE.enabled()) { 2129 for (int i = 0; i < headers.length; i++) { 2130 Wire.HEADER_WIRE.input(headers[i].toExternalForm()); 2131 } 2132 } 2133 getResponseHeaderGroup().setHeaders(headers); 2134 } 2135 2136 2158 protected void readStatusLine(HttpState state, HttpConnection conn) 2159 throws IOException , HttpRecoverableException, HttpException { 2160 LOG.trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)"); 2161 2162 String s = conn.readLine(); 2164 while ((s != null) && !StatusLine.startsWithHTTP(s)) { 2165 if (Wire.HEADER_WIRE.enabled()) { 2166 Wire.HEADER_WIRE.input(s + "\r\n"); 2167 } 2168 s = conn.readLine(); 2169 } 2170 if (s == null) { 2171 throw new HttpRecoverableException("Error in parsing the status " 2174 + " line from the response: unable to find line starting with" 2175 + " \"HTTP\""); 2176 } 2177 if (Wire.HEADER_WIRE.enabled()) { 2178 Wire.HEADER_WIRE.input(s + "\r\n"); 2179 } 2180 statusLine = new StatusLine(s); 2182 2183 String httpVersion = statusLine.getHttpVersion(); 2185 if (httpVersion.equals("HTTP/1.0")) { 2186 http11 = false; 2187 } else if (httpVersion.equals("HTTP/1.1")) { 2188 http11 = true; 2189 } else if (httpVersion.equals("HTTP")) { 2190 http11 = false; 2192 } else { 2193 throw new HttpException("Unrecognized server protocol: '" 2194 + httpVersion + "'"); 2195 } 2196 2197 } 2198 2199 2201 2244 protected void writeRequest(HttpState state, HttpConnection conn) 2245 throws IOException , HttpException { 2246 LOG.trace( 2247 "enter HttpMethodBase.writeRequest(HttpState, HttpConnection)"); 2248 writeRequestLine(state, conn); 2249 writeRequestHeaders(state, conn); 2250 conn.writeLine(); conn.flushRequestOutputStream(); 2253 if (Wire.HEADER_WIRE.enabled()) { 2254 Wire.HEADER_WIRE.output("\r\n"); 2255 } 2256 2257 Header expectheader = getRequestHeader("Expect"); 2258 String expectvalue = null; 2259 if (expectheader != null) { 2260 expectvalue = expectheader.getValue(); 2261 } 2262 if ((expectvalue != null) 2263 && (expectvalue.compareToIgnoreCase("100-continue") == 0)) { 2264 if (this.isHttp11()) { 2265 int readTimeout = conn.getSoTimeout(); 2266 try { 2267 conn.setSoTimeout(RESPONSE_WAIT_TIME_MS); 2268 readStatusLine(state, conn); 2269 processStatusLine(state, conn); 2270 readResponseHeaders(state, conn); 2271 processResponseHeaders(state, conn); 2272 2273 if (this.statusLine.getStatusCode() == HttpStatus.SC_CONTINUE) { 2274 this.statusLine = null; 2276 LOG.debug("OK to continue received"); 2277 } else { 2278 return; 2279 } 2280 } catch (InterruptedIOException e) { 2281 removeRequestHeader("Expect"); 2285 LOG.info("100 (continue) read timeout. Resume sending the request"); 2286 } finally { 2287 conn.setSoTimeout(readTimeout); 2288 } 2289 2290 } else { 2291 removeRequestHeader("Expect"); 2292 LOG.info("'Expect: 100-continue' handshake is only supported by " 2293 + "HTTP/1.1 or higher"); 2294 } 2295 } 2296 2297 writeRequestBody(state, conn); 2298 conn.flushRequestOutputStream(); 2300 } 2301 2302 2327 protected boolean writeRequestBody(HttpState state, HttpConnection conn) 2328 throws IOException , HttpException { 2329 return true; 2330 } 2331 2332 2358 protected void writeRequestHeaders(HttpState state, HttpConnection conn) 2359 throws IOException , HttpException { 2360 LOG.trace("enter HttpMethodBase.writeRequestHeaders(HttpState," 2361 + "HttpConnection)"); 2362 addRequestHeaders(state, conn); 2363 2364 Header[] headers = getRequestHeaders(); 2365 for (int i = 0; i < headers.length; i++) { 2366 String s = headers[i].toExternalForm(); 2367 if (Wire.HEADER_WIRE.enabled()) { 2368 Wire.HEADER_WIRE.output(s); 2369 } 2370 conn.print(s); 2371 } 2372 } 2373 2374 2394 protected void writeRequestLine(HttpState state, HttpConnection conn) 2395 throws IOException , HttpException { 2396 LOG.trace( 2397 "enter HttpMethodBase.writeRequestLine(HttpState, HttpConnection)"); 2398 String requestLine = getRequestLine(conn); 2399 if (Wire.HEADER_WIRE.enabled()) { 2400 Wire.HEADER_WIRE.output(requestLine); 2401 } 2402 conn.print(requestLine); 2403 } 2404 2405 2413 private String getRequestLine(HttpConnection conn) { 2414 return HttpMethodBase.generateRequestLine(conn, getName(), 2415 getPath(), getQueryString(), getHttpVersion()); 2416 } 2417 2418 2425 private String getHttpVersion() { 2426 return (http11 ? "HTTP/1.1" : "HTTP/1.0"); 2427 } 2428 2429 2438 private static boolean canResponseHaveBody(int status) { 2439 LOG.trace("enter HttpMethodBase.canResponseHaveBody(int)"); 2440 2441 boolean result = true; 2442 2443 if ((status >= 100 && status <= 199) || (status == 204) 2444 || (status == 304)) { result = false; 2446 } 2447 2448 return result; 2449 } 2450 2451 2461 private boolean processAuthenticationResponse(HttpState state, HttpConnection conn) { 2462 LOG.trace("enter HttpMethodBase.processAuthenticationResponse(" 2463 + "HttpState, HttpConnection)"); 2464 2465 if (this.proxyAuthScheme instanceof NTLMScheme) { 2466 removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); 2467 } 2468 if (this.authScheme instanceof NTLMScheme) { 2469 removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); 2470 } 2471 int statusCode = statusLine.getStatusCode(); 2472 Header[] challenges = null; 2474 Set realmsUsed = null; 2475 String host = null; 2476 switch (statusCode) { 2477 case HttpStatus.SC_UNAUTHORIZED: 2478 challenges = getResponseHeaderGroup().getHeaders(HttpAuthenticator.WWW_AUTH); 2479 realmsUsed = realms; 2480 host = conn.getVirtualHost(); 2481 if (host == null) { 2482 host = conn.getHost(); 2483 } 2484 break; 2485 case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: 2486 challenges = getResponseHeaderGroup().getHeaders(HttpAuthenticator.PROXY_AUTH); 2487 realmsUsed = proxyRealms; 2488 host = conn.getProxyHost(); 2489 break; 2490 } 2491 boolean authenticated = false; 2492 if (challenges.length > 0) { 2494 AuthScheme authscheme = null; 2495 try { 2496 authscheme = HttpAuthenticator.selectAuthScheme(challenges); 2497 } catch (MalformedChallengeException e) { 2498 if (LOG.isErrorEnabled()) { 2499 LOG.error(e.getMessage(), e); 2500 } 2501 return true; 2502 } catch (UnsupportedOperationException e) { 2503 if (LOG.isErrorEnabled()) { 2504 LOG.error(e.getMessage(), e); 2505 } 2506 return true; 2507 } 2508 2509 StringBuffer buffer = new StringBuffer (); 2510 buffer.append(host); 2511 buffer.append('#'); 2512 buffer.append(authscheme.getID()); 2513 String realm = buffer.toString(); 2514 2515 if (realmsUsed.contains(realm)) { 2516 if (LOG.isInfoEnabled()) { 2517 buffer = new StringBuffer (); 2518 buffer.append("Already tried to authenticate with '"); 2519 buffer.append(authscheme.getRealm()); 2520 buffer.append("' authentication realm at "); 2521 buffer.append(host); 2522 buffer.append(", but still receiving: "); 2523 buffer.append(statusLine.toString()); 2524 LOG.info(buffer.toString()); 2525 } 2526 return true; 2527 } else { 2528 realmsUsed.add(realm); 2529 } 2530 2531 try { 2532 switch (statusCode) { 2534 case HttpStatus.SC_UNAUTHORIZED: 2535 removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); 2536 authenticated = HttpAuthenticator.authenticate( 2537 authscheme, this, conn, state); 2538 this.realm = authscheme.getRealm(); 2539 this.authScheme = authscheme; 2540 break; 2541 case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: 2542 removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); 2543 authenticated = HttpAuthenticator.authenticateProxy( 2544 authscheme, this, conn, state); 2545 this.proxyRealm = authscheme.getRealm(); 2546 this.proxyAuthScheme = authscheme; 2547 break; 2548 } 2549 } catch (AuthenticationException e) { 2550 LOG.warn(e.getMessage()); 2551 return true; } 2553 if (!authenticated) { 2554 LOG.debug("HttpMethodBase.execute(): Server demands " 2557 + "authentication credentials, but none are " 2558 + "available, so aborting."); 2559 } else { 2560 LOG.debug("HttpMethodBase.execute(): Server demanded " 2561 + "authentication credentials, will try again."); 2562 } 2564 } 2565 2566 return !authenticated; } 2568 2569 2575 public String getProxyAuthenticationRealm() { 2576 return this.proxyRealm; 2577 } 2578 2579 2585 public String getAuthenticationRealm() { 2586 return this.realm; 2587 } 2588 2589 2611 private void processRequest(HttpState state, HttpConnection connection) 2612 throws HttpException, IOException { 2613 LOG.trace("enter HttpMethodBase.processRequest(HttpState, HttpConnection)"); 2614 2615 int execCount = 0; 2616 boolean requestSent = false; 2617 2618 while (true) { 2621 execCount++; 2622 requestSent = false; 2623 2624 if (LOG.isTraceEnabled()) { 2625 LOG.trace("Attempt number " + execCount + " to process request"); 2626 } 2627 try { 2628 if (!connection.isOpen()) { 2629 LOG.debug("Opening the connection."); 2630 connection.open(); 2631 } 2632 writeRequest(state, connection); 2633 requestSent = true; 2634 readResponse(state, connection); 2635 used = true; 2637 break; 2638 } catch (HttpRecoverableException httpre) { 2639 if (LOG.isDebugEnabled()) { 2640 LOG.debug("Closing the connection."); 2641 } 2642 connection.close(); 2643 LOG.info("Recoverable exception caught when processing request"); 2644 recoverableExceptionCount++; 2646 2647 if (!getMethodRetryHandler().retryMethod( 2649 this, 2650 connection, 2651 httpre, 2652 execCount, 2653 requestSent) 2654 ) { 2655 LOG.warn( 2656 "Recoverable exception caught but MethodRetryHandler.retryMethod() " 2657 + "returned false, rethrowing exception" 2658 ); 2659 doneWithConnection = true; 2661 throw httpre; 2662 } 2663 } catch (IOException e) { 2664 connection.close(); 2665 doneWithConnection = true; 2666 throw e; 2667 } catch (RuntimeException e) { 2668 connection.close(); 2669 doneWithConnection = true; 2670 throw e; 2671 } 2672 } 2673 } 2674 2675 2680 protected static String getContentCharSet(Header contentheader) { 2681 LOG.trace("enter getContentCharSet( Header contentheader )"); 2682 String charset = null; 2683 if (contentheader != null) { 2684 try { 2685 HeaderElement values[] = contentheader.getValues(); 2686 if (values.length == 1) { 2689 NameValuePair param = values[0].getParameterByName("charset"); 2690 if (param != null) { 2691 charset = param.getValue(); 2694 } 2695 } 2696 } catch (HttpException e) { 2697 LOG.error(e); 2698 } 2699 } 2700 if (charset == null) { 2701 if (LOG.isDebugEnabled()) { 2702 LOG.debug("Default charset used: " + HttpConstants.DEFAULT_CONTENT_CHARSET); 2703 } 2704 charset = HttpConstants.DEFAULT_CONTENT_CHARSET; 2705 } 2706 return charset; 2707 } 2708 2709 2710 2715 public String getRequestCharSet() { 2716 return getContentCharSet(getRequestHeader("Content-Type")); 2717 } 2718 2719 2720 2725 public String getResponseCharSet() { 2726 return getContentCharSet(getResponseHeader("Content-Type")); 2727 } 2728 2729 2735 public int getRecoverableExceptionCount() { 2736 return recoverableExceptionCount; 2737 } 2738 2739 2748 protected void responseBodyConsumed() { 2749 2750 responseStream = null; 2753 if (responseConnection != null) { 2754 responseConnection.setLastResponseInputStream(null); 2755 2756 if (shouldCloseConnection(responseConnection)) { 2757 responseConnection.close(); 2758 } 2759 } 2760 this.connectionCloseForced = false; 2761 doneWithConnection = true; 2762 if (!inExecute) { 2763 ensureConnectionRelease(); 2764 } 2765 } 2766 2767 2770 private void ensureConnectionRelease() { 2771 if (responseConnection != null) { 2772 responseConnection.releaseConnection(); 2773 responseConnection = null; 2774 } 2775 } 2776 2777 2782 public HostConfiguration getHostConfiguration() { 2783 return hostConfiguration; 2784 } 2785 2786 2791 public void setHostConfiguration(HostConfiguration hostConfiguration) { 2792 this.hostConfiguration = hostConfiguration; 2793 } 2794 2795 2800 public MethodRetryHandler getMethodRetryHandler() { 2801 2802 if (methodRetryHandler == null) { 2803 methodRetryHandler = new DefaultMethodRetryHandler(); 2804 } 2805 2806 return methodRetryHandler; 2807 } 2808 2809 2814 public void setMethodRetryHandler(MethodRetryHandler handler) { 2815 methodRetryHandler = handler; 2816 } 2817 2818 2826 protected void fakeResponse( 2827 StatusLine statusline, 2828 HeaderGroup responseheaders, 2829 InputStream responseStream 2830 ) { 2831 this.used = true; 2833 this.statusLine = statusline; 2834 this.responseHeaders = responseheaders; 2835 this.responseBody = null; 2836 this.responseStream = responseStream; 2837 } 2838} 2839 | Popular Tags |