1 16 package org.apache.axis.transport.http; 17 18 import org.apache.axis.AxisFault; 19 import org.apache.axis.Constants; 20 import org.apache.axis.Message; 21 import org.apache.axis.MessageContext; 22 import org.apache.axis.components.logger.LogFactory; 23 import org.apache.axis.components.net.CommonsHTTPClientProperties; 24 import org.apache.axis.components.net.CommonsHTTPClientPropertiesFactory; 25 import org.apache.axis.components.net.TransportClientProperties; 26 import org.apache.axis.components.net.TransportClientPropertiesFactory; 27 import org.apache.axis.handlers.BasicHandler; 28 import org.apache.axis.soap.SOAP12Constants; 29 import org.apache.axis.soap.SOAPConstants; 30 import org.apache.axis.utils.Messages; 31 import org.apache.axis.utils.NetworkUtils; 32 import org.apache.axis.utils.JavaUtils; 33 import org.apache.commons.httpclient.Cookie; 34 import org.apache.commons.httpclient.Credentials; 35 import org.apache.commons.httpclient.Header; 36 import org.apache.commons.httpclient.HostConfiguration; 37 import org.apache.commons.httpclient.HttpClient; 38 import org.apache.commons.httpclient.HttpConnectionManager; 39 import org.apache.commons.httpclient.HttpMethodBase; 40 import org.apache.commons.httpclient.HttpState; 41 import org.apache.commons.httpclient.HttpVersion; 42 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; 43 import org.apache.commons.httpclient.NTCredentials; 44 import org.apache.commons.httpclient.UsernamePasswordCredentials; 45 import org.apache.commons.httpclient.auth.AuthScope; 46 import org.apache.commons.httpclient.cookie.CookiePolicy; 47 import org.apache.commons.httpclient.methods.GetMethod; 48 import org.apache.commons.httpclient.methods.PostMethod; 49 import org.apache.commons.httpclient.methods.RequestEntity; 50 import org.apache.commons.httpclient.params.HttpMethodParams; 51 import org.apache.commons.logging.Log; 52 53 import javax.xml.soap.MimeHeader ; 54 import javax.xml.soap.MimeHeaders ; 55 import javax.xml.soap.SOAPException ; 56 import java.io.FilterInputStream ; 57 import java.io.IOException ; 58 import java.io.InputStream ; 59 import java.io.OutputStream ; 60 import java.net.URL ; 61 import java.util.Hashtable ; 62 import java.util.Iterator ; 63 import java.util.Map ; 64 import java.util.StringTokenizer ; 65 import java.util.ArrayList ; 66 67 78 public class CommonsHTTPSender extends BasicHandler { 79 80 81 protected static Log log = 82 LogFactory.getLog(CommonsHTTPSender.class.getName()); 83 84 protected HttpConnectionManager connectionManager; 85 protected CommonsHTTPClientProperties clientProperties; 86 boolean httpChunkStream = true; 88 public CommonsHTTPSender() { 89 initialize(); 90 } 91 92 protected void initialize() { 93 MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager(); 94 this.clientProperties = CommonsHTTPClientPropertiesFactory.create(); 95 cm.getParams().setDefaultMaxConnectionsPerHost(clientProperties.getMaximumConnectionsPerHost()); 96 cm.getParams().setMaxTotalConnections(clientProperties.getMaximumTotalConnections()); 97 if(this.clientProperties.getDefaultConnectionTimeout()>0) { 100 cm.getParams().setConnectionTimeout(this.clientProperties.getDefaultConnectionTimeout()); 101 } 102 if(this.clientProperties.getDefaultSoTimeout()>0) { 103 cm.getParams().setSoTimeout(this.clientProperties.getDefaultSoTimeout()); 104 } 105 this.connectionManager = cm; 106 } 107 108 116 public void invoke(MessageContext msgContext) throws AxisFault { 117 HttpMethodBase method = null; 118 if (log.isDebugEnabled()) { 119 log.debug(Messages.getMessage("enter00", 120 "CommonsHTTPSender::invoke")); 121 } 122 try { 123 URL targetURL = 124 new URL (msgContext.getStrProp(MessageContext.TRANS_URL)); 125 126 HttpClient httpClient = new HttpClient(this.connectionManager); 131 httpClient.getParams().setConnectionManagerTimeout(this.clientProperties.getConnectionPoolTimeout()); 133 134 HostConfiguration hostConfiguration = 135 getHostConfiguration(httpClient, msgContext, targetURL); 136 137 boolean posting = true; 138 139 if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) { 142 String webMethod = msgContext.getStrProp(SOAP12Constants.PROP_WEBMETHOD); 143 if (webMethod != null) { 144 posting = webMethod.equals(HTTPConstants.HEADER_POST); 145 } 146 } 147 148 if (posting) { 149 Message reqMessage = msgContext.getRequestMessage(); 150 method = new PostMethod(targetURL.toString()); 151 152 method.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, 154 false); 155 156 addContextInfo(method, httpClient, msgContext, targetURL); 157 158 ((PostMethod)method).setRequestEntity( 159 new MessageRequestEntity(method, reqMessage, httpChunkStream)); 160 } else { 161 method = new GetMethod(targetURL.toString()); 162 addContextInfo(method, httpClient, msgContext, targetURL); 163 } 164 165 String httpVersion = 166 msgContext.getStrProp(MessageContext.HTTP_TRANSPORT_VERSION); 167 if (httpVersion != null) { 168 if (httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_V10)) { 169 method.getParams().setVersion(HttpVersion.HTTP_1_0); 170 } 171 } 173 174 if (msgContext.getMaintainSession()) { 178 HttpState state = httpClient.getState(); 179 method.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); 180 String host = hostConfiguration.getHost(); 181 String path = targetURL.getPath(); 182 boolean secure = hostConfiguration.getProtocol().isSecure(); 183 fillHeaders(msgContext, state, HTTPConstants.HEADER_COOKIE, host, path, secure); 184 fillHeaders(msgContext, state, HTTPConstants.HEADER_COOKIE2, host, path, secure); 185 httpClient.setState(state); 186 } 187 188 int returnCode = httpClient.executeMethod(hostConfiguration, method, null); 189 190 String contentType = 191 getHeader(method, HTTPConstants.HEADER_CONTENT_TYPE); 192 String contentLocation = 193 getHeader(method, HTTPConstants.HEADER_CONTENT_LOCATION); 194 String contentLength = 195 getHeader(method, HTTPConstants.HEADER_CONTENT_LENGTH); 196 197 if ((returnCode > 199) && (returnCode < 300)) { 198 199 } else if (msgContext.getSOAPConstants() == 201 SOAPConstants.SOAP12_CONSTANTS) { 202 } else if ((contentType != null) && !contentType.equals("text/html") 205 && ((returnCode > 499) && (returnCode < 600))) { 206 207 } else { 209 String statusMessage = method.getStatusText(); 210 AxisFault fault = new AxisFault("HTTP", 211 "(" + returnCode + ")" 212 + statusMessage, null, 213 null); 214 215 try { 216 fault.setFaultDetailString( 217 Messages.getMessage("return01", 218 "" + returnCode, 219 method.getResponseBodyAsString())); 220 fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE, 221 Integer.toString(returnCode)); 222 throw fault; 223 } finally { 224 method.releaseConnection(); } 226 } 227 228 InputStream releaseConnectionOnCloseStream = 231 createConnectionReleasingInputStream(method); 232 233 Message outMsg = new Message(releaseConnectionOnCloseStream, 234 false, contentType, contentLocation); 235 Header[] responseHeaders = method.getResponseHeaders(); 237 MimeHeaders responseMimeHeaders = outMsg.getMimeHeaders(); 238 for (int i = 0; i < responseHeaders.length; i++) { 239 Header responseHeader = responseHeaders[i]; 240 responseMimeHeaders.addHeader(responseHeader.getName(), 241 responseHeader.getValue()); 242 } 243 outMsg.setMessageType(Message.RESPONSE); 244 msgContext.setResponseMessage(outMsg); 245 if (log.isDebugEnabled()) { 246 if (null == contentLength) { 247 log.debug("\n" 248 + Messages.getMessage("no00", "Content-Length")); 249 } 250 log.debug("\n" + Messages.getMessage("xmlRecd00")); 251 log.debug("-----------------------------------------------"); 252 log.debug(outMsg.getSOAPPartAsString()); 253 } 254 255 if (msgContext.getMaintainSession()) { 258 Header[] headers = method.getResponseHeaders(); 259 260 for (int i = 0; i < headers.length; i++) { 261 if (headers[i].getName().equalsIgnoreCase(HTTPConstants.HEADER_SET_COOKIE)) { 262 handleCookie(HTTPConstants.HEADER_COOKIE, headers[i].getValue(), msgContext); 263 } else if (headers[i].getName().equalsIgnoreCase(HTTPConstants.HEADER_SET_COOKIE2)) { 264 handleCookie(HTTPConstants.HEADER_COOKIE2, headers[i].getValue(), msgContext); 265 } 266 } 267 } 268 269 if (msgContext.isPropertyTrue("axis.one.way")) { 272 method.releaseConnection(); 273 } 274 275 } catch (Exception e) { 276 log.debug(e); 277 throw AxisFault.makeFault(e); 278 } 279 280 if (log.isDebugEnabled()) { 281 log.debug(Messages.getMessage("exit00", 282 "CommonsHTTPSender::invoke")); 283 } 284 } 285 286 295 public void handleCookie(String cookieName, String cookie, 296 MessageContext msgContext) { 297 298 cookie = cleanupCookie(cookie); 299 int keyIndex = cookie.indexOf("="); 300 String key = (keyIndex != -1) ? cookie.substring(0, keyIndex) : cookie; 301 302 ArrayList cookies = new ArrayList (); 303 Object oldCookies = msgContext.getProperty(cookieName); 304 boolean alreadyExist = false; 305 if(oldCookies != null) { 306 if(oldCookies instanceof String []) { 307 String [] oldCookiesArray = (String [])oldCookies; 308 for(int i = 0; i < oldCookiesArray.length; i++) { 309 String anOldCookie = oldCookiesArray[i]; 310 if (key != null && anOldCookie.indexOf(key) == 0) { anOldCookie = cookie; alreadyExist = true; 313 } 314 cookies.add(anOldCookie); 315 } 316 } else { 317 String oldCookie = (String )oldCookies; 318 if (key != null && oldCookie.indexOf(key) == 0) { oldCookie = cookie; alreadyExist = true; 321 } 322 cookies.add(oldCookie); 323 } 324 } 325 326 if (!alreadyExist) { 327 cookies.add(cookie); 328 } 329 330 if(cookies.size()==1) { 331 msgContext.setProperty(cookieName, cookies.get(0)); 332 } else if (cookies.size() > 1) { 333 msgContext.setProperty(cookieName, cookies.toArray(new String [cookies.size()])); 334 } 335 } 336 337 347 private void fillHeaders(MessageContext msgContext, HttpState state, String header, String host, String path, boolean secure) { 348 Object ck1 = msgContext.getProperty(header); 349 if (ck1 != null) { 350 if (ck1 instanceof String []) { 351 String [] cookies = (String []) ck1; 352 for (int i = 0; i < cookies.length; i++) { 353 addCookie(state, cookies[i], host, path, secure); 354 } 355 } else { 356 addCookie(state, (String ) ck1, host, path, secure); 357 } 358 } 359 } 360 361 366 private void addCookie(HttpState state, String cookie,String host, String path, boolean secure) { 367 int index = cookie.indexOf('='); 368 state.addCookie(new Cookie(host, cookie.substring(0, index), 369 cookie.substring(index + 1), path, 370 null, secure)); 371 } 372 373 380 private String cleanupCookie(String cookie) { 381 cookie = cookie.trim(); 382 int index = cookie.indexOf(';'); 384 if (index != -1) { 385 cookie = cookie.substring(0, index); 386 } 387 return cookie; 388 } 389 390 protected HostConfiguration getHostConfiguration(HttpClient client, 391 MessageContext context, 392 URL targetURL) { 393 TransportClientProperties tcp = 394 TransportClientPropertiesFactory.create(targetURL.getProtocol()); int port = targetURL.getPort(); 396 boolean hostInNonProxyList = 397 isHostInNonProxyList(targetURL.getHost(), tcp.getNonProxyHosts()); 398 399 HostConfiguration config = new HostConfiguration(); 400 401 if (port == -1) { 402 port = 80; } 404 405 if(hostInNonProxyList){ 406 config.setHost(targetURL.getHost(), port, targetURL.getProtocol()); 407 } else { 408 if (tcp.getProxyHost().length() == 0 || 409 tcp.getProxyPort().length() == 0) { 410 config.setHost(targetURL.getHost(), port, targetURL.getProtocol()); 411 } else { 412 if (tcp.getProxyUser().length() != 0) { 413 Credentials proxyCred = 414 new UsernamePasswordCredentials(tcp.getProxyUser(), 415 tcp.getProxyPassword()); 416 int domainIndex = tcp.getProxyUser().indexOf("\\"); 419 if (domainIndex > 0) { 420 String domain = tcp.getProxyUser().substring(0, domainIndex); 421 if (tcp.getProxyUser().length() > domainIndex + 1) { 422 String user = tcp.getProxyUser().substring(domainIndex + 1); 423 proxyCred = new NTCredentials(user, 424 tcp.getProxyPassword(), 425 tcp.getProxyHost(), domain); 426 } 427 } 428 client.getState().setProxyCredentials(AuthScope.ANY, proxyCred); 429 } 430 int proxyPort = new Integer (tcp.getProxyPort()).intValue(); 431 config.setProxy(tcp.getProxyHost(), proxyPort); 432 } 433 } 434 return config; 435 } 436 437 447 private void addContextInfo(HttpMethodBase method, 448 HttpClient httpClient, 449 MessageContext msgContext, 450 URL tmpURL) 451 throws Exception { 452 453 if (msgContext.getTimeout() != 0) { 455 457 httpClient.getHttpConnectionManager().getParams().setSoTimeout(msgContext.getTimeout()); 459 httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(msgContext.getTimeout()); 461 } 462 463 String action = msgContext.useSOAPAction() 465 ? msgContext.getSOAPActionURI() 466 : ""; 467 468 if (action == null) { 469 action = ""; 470 } 471 472 Message msg = msgContext.getRequestMessage(); 473 if (msg != null){ 474 method.setRequestHeader(new Header(HTTPConstants.HEADER_CONTENT_TYPE, 475 msg.getContentType(msgContext.getSOAPConstants()))); 476 } 477 method.setRequestHeader(new Header(HTTPConstants.HEADER_SOAP_ACTION, 478 "\"" + action + "\"")); 479 480 String userID = msgContext.getUsername(); 481 String passwd = msgContext.getPassword(); 482 483 if ((userID == null) && (tmpURL.getUserInfo() != null)) { 486 String info = tmpURL.getUserInfo(); 487 int sep = info.indexOf(':'); 488 489 if ((sep >= 0) && (sep + 1 < info.length())) { 490 userID = info.substring(0, sep); 491 passwd = info.substring(sep + 1); 492 } else { 493 userID = info; 494 } 495 } 496 if (userID != null) { 497 Credentials proxyCred = 498 new UsernamePasswordCredentials(userID, 499 passwd); 500 int domainIndex = userID.indexOf("\\"); 503 if (domainIndex > 0) { 504 String domain = userID.substring(0, domainIndex); 505 if (userID.length() > domainIndex + 1) { 506 String user = userID.substring(domainIndex + 1); 507 proxyCred = new NTCredentials(user, 508 passwd, 509 NetworkUtils.getLocalHostname(), domain); 510 } 511 } 512 httpClient.getState().setCredentials(AuthScope.ANY, proxyCred); 513 } 514 515 MimeHeaders mimeHeaders = msg.getMimeHeaders(); 517 if (mimeHeaders != null) { 518 for (Iterator i = mimeHeaders.getAllHeaders(); i.hasNext(); ) { 519 MimeHeader mimeHeader = (MimeHeader ) i.next(); 520 String headerName = mimeHeader.getName(); 523 if (headerName.equals(HTTPConstants.HEADER_CONTENT_TYPE) 524 || headerName.equals(HTTPConstants.HEADER_SOAP_ACTION)) { 525 continue; 526 } 527 method.addRequestHeader(mimeHeader.getName(), 528 mimeHeader.getValue()); 529 } 530 } 531 532 Hashtable userHeaderTable = 534 (Hashtable ) msgContext.getProperty(HTTPConstants.REQUEST_HEADERS); 535 536 if (userHeaderTable != null) { 537 for (Iterator e = userHeaderTable.entrySet().iterator(); 538 e.hasNext();) { 539 Map.Entry me = (Map.Entry ) e.next(); 540 Object keyObj = me.getKey(); 541 542 if (null == keyObj) { 543 continue; 544 } 545 String key = keyObj.toString().trim(); 546 String value = me.getValue().toString().trim(); 547 548 if (key.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT) && 549 value.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT_100_Continue)) { 550 method.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, 551 true); 552 } else if (key.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED)) { 553 String val = me.getValue().toString(); 554 if (null != val) { 555 httpChunkStream = JavaUtils.isTrue(val); 556 } 557 } else { 558 method.addRequestHeader(key, value); 559 } 560 } 561 } 562 } 563 564 572 protected boolean isHostInNonProxyList(String host, String nonProxyHosts) { 573 574 if ((nonProxyHosts == null) || (host == null)) { 575 return false; 576 } 577 578 582 StringTokenizer tokenizer = new StringTokenizer (nonProxyHosts, "|\""); 583 584 while (tokenizer.hasMoreTokens()) { 585 String pattern = tokenizer.nextToken(); 586 587 if (log.isDebugEnabled()) { 588 log.debug(Messages.getMessage("match00", 589 new String []{"HTTPSender", 590 host, 591 pattern})); 592 } 593 if (match(pattern, host, false)) { 594 return true; 595 } 596 } 597 return false; 598 } 599 600 613 protected static boolean match(String pattern, String str, 614 boolean isCaseSensitive) { 615 616 char[] patArr = pattern.toCharArray(); 617 char[] strArr = str.toCharArray(); 618 int patIdxStart = 0; 619 int patIdxEnd = patArr.length - 1; 620 int strIdxStart = 0; 621 int strIdxEnd = strArr.length - 1; 622 char ch; 623 boolean containsStar = false; 624 625 for (int i = 0; i < patArr.length; i++) { 626 if (patArr[i] == '*') { 627 containsStar = true; 628 break; 629 } 630 } 631 if (!containsStar) { 632 633 if (patIdxEnd != strIdxEnd) { 635 return false; } 637 for (int i = 0; i <= patIdxEnd; i++) { 638 ch = patArr[i]; 639 if (isCaseSensitive && (ch != strArr[i])) { 640 return false; } 642 if (!isCaseSensitive 643 && (Character.toUpperCase(ch) 644 != Character.toUpperCase(strArr[i]))) { 645 return false; } 647 } 648 return true; } 650 if (patIdxEnd == 0) { 651 return true; } 653 654 while ((ch = patArr[patIdxStart]) != '*' 656 && (strIdxStart <= strIdxEnd)) { 657 if (isCaseSensitive && (ch != strArr[strIdxStart])) { 658 return false; } 660 if (!isCaseSensitive 661 && (Character.toUpperCase(ch) 662 != Character.toUpperCase(strArr[strIdxStart]))) { 663 return false; } 665 patIdxStart++; 666 strIdxStart++; 667 } 668 if (strIdxStart > strIdxEnd) { 669 670 for (int i = patIdxStart; i <= patIdxEnd; i++) { 673 if (patArr[i] != '*') { 674 return false; 675 } 676 } 677 return true; 678 } 679 680 while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) { 682 if (isCaseSensitive && (ch != strArr[strIdxEnd])) { 683 return false; } 685 if (!isCaseSensitive 686 && (Character.toUpperCase(ch) 687 != Character.toUpperCase(strArr[strIdxEnd]))) { 688 return false; } 690 patIdxEnd--; 691 strIdxEnd--; 692 } 693 if (strIdxStart > strIdxEnd) { 694 695 for (int i = patIdxStart; i <= patIdxEnd; i++) { 698 if (patArr[i] != '*') { 699 return false; 700 } 701 } 702 return true; 703 } 704 705 while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) { 708 int patIdxTmp = -1; 709 710 for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { 711 if (patArr[i] == '*') { 712 patIdxTmp = i; 713 break; 714 } 715 } 716 if (patIdxTmp == patIdxStart + 1) { 717 718 patIdxStart++; 720 continue; 721 } 722 723 int patLength = (patIdxTmp - patIdxStart - 1); 726 int strLength = (strIdxEnd - strIdxStart + 1); 727 int foundIdx = -1; 728 729 strLoop: 730 for (int i = 0; i <= strLength - patLength; i++) { 731 for (int j = 0; j < patLength; j++) { 732 ch = patArr[patIdxStart + j + 1]; 733 if (isCaseSensitive 734 && (ch != strArr[strIdxStart + i + j])) { 735 continue strLoop; 736 } 737 if (!isCaseSensitive && (Character 738 .toUpperCase(ch) != Character 739 .toUpperCase(strArr[strIdxStart + i + j]))) { 740 continue strLoop; 741 } 742 } 743 foundIdx = strIdxStart + i; 744 break; 745 } 746 if (foundIdx == -1) { 747 return false; 748 } 749 patIdxStart = patIdxTmp; 750 strIdxStart = foundIdx + patLength; 751 } 752 753 for (int i = patIdxStart; i <= patIdxEnd; i++) { 756 if (patArr[i] != '*') { 757 return false; 758 } 759 } 760 return true; 761 } 762 763 private static String getHeader(HttpMethodBase method, String headerName) { 764 Header header = method.getResponseHeader(headerName); 765 return (header == null) ? null : header.getValue().trim(); 766 } 767 768 private InputStream createConnectionReleasingInputStream(final HttpMethodBase method) throws IOException { 769 return new FilterInputStream (method.getResponseBodyAsStream()) { 770 public void close() throws IOException { 771 try { 772 super.close(); 773 } finally { 774 method.releaseConnection(); 775 } 776 } 777 }; 778 } 779 780 private static class MessageRequestEntity implements RequestEntity { 781 782 private HttpMethodBase method; 783 private Message message; 784 boolean httpChunkStream = true; 786 public MessageRequestEntity(HttpMethodBase method, Message message) { 787 this.message = message; 788 this.method = method; 789 } 790 791 public MessageRequestEntity(HttpMethodBase method, Message message, boolean httpChunkStream) { 792 this.message = message; 793 this.method = method; 794 this.httpChunkStream = httpChunkStream; 795 } 796 797 public boolean isRepeatable() { 798 return true; 799 } 800 801 public void writeRequest(OutputStream out) throws IOException { 802 try { 803 this.message.writeTo(out); 804 } catch (SOAPException e) { 805 throw new IOException (e.getMessage()); 806 } 807 } 808 809 public long getContentLength() { 810 if (this.method.getParams().getVersion() == HttpVersion.HTTP_1_0 || !httpChunkStream) { 811 try { 812 return message.getContentLength(); 813 } catch (Exception e) { 814 return -1; 815 } 816 } else { 817 return -1; 818 } 819 } 820 821 public String getContentType() { 822 return null; } 824 825 } 826 } 827 828 | Popular Tags |