Coverage Report - org.mule.transport.soap.axis.extensions.MuleHttpSender
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleHttpSender
0%
0/342
0%
0/222
0
 
 1  
 /*
 2  
  * $Id: MuleHttpSender.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.transport.soap.axis.extensions;
 12  
 
 13  
 import org.mule.module.cxf.SoapConstants;
 14  
 import org.mule.util.StringUtils;
 15  
 import org.mule.util.SystemUtils;
 16  
 
 17  
 import java.io.BufferedInputStream;
 18  
 import java.io.BufferedOutputStream;
 19  
 import java.io.IOException;
 20  
 import java.io.InputStream;
 21  
 import java.io.OutputStream;
 22  
 import java.net.Socket;
 23  
 import java.net.URL;
 24  
 import java.util.Enumeration;
 25  
 import java.util.Hashtable;
 26  
 import java.util.Iterator;
 27  
 
 28  
 import javax.xml.soap.MimeHeader;
 29  
 import javax.xml.soap.MimeHeaders;
 30  
 import javax.xml.soap.SOAPException;
 31  
 
 32  
 import org.apache.axis.AxisFault;
 33  
 import org.apache.axis.Constants;
 34  
 import org.apache.axis.Message;
 35  
 import org.apache.axis.MessageContext;
 36  
 import org.apache.axis.client.Call;
 37  
 import org.apache.axis.components.logger.LogFactory;
 38  
 import org.apache.axis.components.net.BooleanHolder;
 39  
 import org.apache.axis.components.net.DefaultSocketFactory;
 40  
 import org.apache.axis.components.net.SocketFactory;
 41  
 import org.apache.axis.components.net.SocketFactoryFactory;
 42  
 import org.apache.axis.encoding.Base64;
 43  
 import org.apache.axis.handlers.BasicHandler;
 44  
 import org.apache.axis.soap.SOAP12Constants;
 45  
 import org.apache.axis.soap.SOAPConstants;
 46  
 import org.apache.axis.transport.http.ChunkedInputStream;
 47  
 import org.apache.axis.transport.http.ChunkedOutputStream;
 48  
 import org.apache.axis.transport.http.HTTPConstants;
 49  
 import org.apache.axis.transport.http.HTTPSender;
 50  
 import org.apache.axis.transport.http.SocketHolder;
 51  
 import org.apache.axis.transport.http.SocketInputStream;
 52  
 import org.apache.axis.utils.Messages;
 53  
 import org.apache.axis.utils.TeeOutputStream;
 54  
 import org.apache.commons.io.output.ByteArrayOutputStream;
 55  
 import org.apache.commons.logging.Log;
 56  
 
 57  
 /**
 58  
  * <code>MuleHttpSender</code> is a rewrite of the Axis HttpSender. Unfortunately,
 59  
  * the Axis implementation is not extensible so this class is a copy of it with
 60  
  * modifications. The enhancements made are to allow for asynchronous Http method
 61  
  * calls which Mule initiates when the endpoint is asynchronous.
 62  
  *
 63  
  * @deprecated Use the UniversalSender instead
 64  
  */
 65  
 @Deprecated
 66  0
 public class MuleHttpSender extends BasicHandler
 67  
 {
 68  
     /**
 69  
      * Serial version
 70  
      */
 71  
     private static final long serialVersionUID = -1730816323289419500L;
 72  
 
 73  0
     protected static final Log log = LogFactory.getLog(HTTPSender.class.getName());
 74  
 
 75  0
     private static final String ACCEPT_HEADERS = HTTPConstants.HEADER_ACCEPT
 76  
                                                  // limit to the types that are
 77  
                                                     // meaningful to us.
 78  
                                                  + ": " + HTTPConstants.HEADER_ACCEPT_APPL_SOAP + ", "
 79  
                                                  + HTTPConstants.HEADER_ACCEPT_APPLICATION_DIME + ", "
 80  
                                                  + HTTPConstants.HEADER_ACCEPT_MULTIPART_RELATED + ", "
 81  
                                                  + HTTPConstants.HEADER_ACCEPT_TEXT_ALL + "\r\n"
 82  
                                                  + HTTPConstants.HEADER_USER_AGENT // Tell
 83  
                                                                                     // who
 84  
                                                                                     // we
 85  
                                                                                     // are.
 86  
                                                  + ": " + Messages.getMessage("axisUserAgent") + "\r\n";
 87  
 
 88  
     private static final String CACHE_HEADERS = HTTPConstants.HEADER_CACHE_CONTROL
 89  
                                                 // stop caching proxies from caching
 90  
                                                 // SOAP request.
 91  
                                                 + ": " + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n"
 92  
                                                 + HTTPConstants.HEADER_PRAGMA + ": "
 93  
                                                 + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n";
 94  
 
 95  0
     private static final String CHUNKED_HEADER = HTTPConstants.HEADER_TRANSFER_ENCODING + ": "
 96  
                                                  + HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED + "\r\n";
 97  
 
 98  0
     private static final String HEADER_CONTENT_TYPE_LC = HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase();
 99  
 
 100  0
     private static final String HEADER_LOCATION_LC = HTTPConstants.HEADER_LOCATION.toLowerCase();
 101  
 
 102  0
     private static final String HEADER_CONTENT_LOCATION_LC = HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase();
 103  
 
 104  0
     private static final String HEADER_CONTENT_LENGTH_LC = HTTPConstants.HEADER_CONTENT_LENGTH.toLowerCase();
 105  
 
 106  0
     private static final String HEADER_TRANSFER_ENCODING_LC = HTTPConstants.HEADER_TRANSFER_ENCODING.toLowerCase();
 107  
 
 108  
     /**
 109  
      * the url; used for error reporting
 110  
      */
 111  
     URL targetURL;
 112  
 
 113  
     /**
 114  
      * invoke creates a socket connection, sends the request SOAP message and then
 115  
      * reads the response SOAP message back from the SOAP server
 116  
      * 
 117  
      * @param msgContext the messsage context
 118  
      * @throws AxisFault
 119  
      */
 120  
     public void invoke(MessageContext msgContext) throws AxisFault
 121  
     {
 122  
 
 123  0
         if (log.isDebugEnabled())
 124  
         {
 125  0
             log.debug(Messages.getMessage("enter00", "HTTPSender::invoke"));
 126  
         }
 127  
         try
 128  
         {
 129  0
             Call call = (Call)msgContext.getProperty("call_object");
 130  0
             String transURL = msgContext.getStrProp(MessageContext.TRANS_URL);
 131  0
             String uri = transURL;
 132  0
             if (call != null && call.useSOAPAction())
 133  
             {
 134  0
                 uri = call.getSOAPActionURI();
 135  
             }
 136  0
             msgContext.setProperty(SoapConstants.SOAP_ACTION_PROPERTY_CAPS, uri);
 137  
 
 138  0
             BooleanHolder useFullURL = new BooleanHolder(false);
 139  0
             StringBuffer otherHeaders = new StringBuffer(64);
 140  0
             targetURL = new URL(transURL);
 141  0
             String host = targetURL.getHost();
 142  0
             int port = targetURL.getPort();
 143  
 
 144  0
             SocketHolder socketHolder = new SocketHolder(null);
 145  
 
 146  
             // Send the SOAP request to the server
 147  0
             InputStream inp = writeToSocket(socketHolder, msgContext, targetURL, otherHeaders, host, port,
 148  
                 msgContext.getTimeout(), useFullURL);
 149  
 
 150  0
             if (msgContext.isClient() && call != null)
 151  
             {
 152  0
                 if (Boolean.TRUE.equals(call.getProperty("axis.one.way")))
 153  
                 {
 154  0
                     return;
 155  
                 }
 156  
             }
 157  
 
 158  
             // Read the response back from the server
 159  0
             Hashtable headers = new Hashtable();
 160  0
             inp = readHeadersFromSocket(socketHolder, msgContext, inp, headers);
 161  0
             readFromSocket(socketHolder, msgContext, inp, headers);
 162  
         }
 163  0
         catch (Exception e)
 164  
         {
 165  0
             log.debug(e);
 166  0
             throw AxisFault.makeFault(e);
 167  0
         }
 168  0
         if (log.isDebugEnabled())
 169  
         {
 170  0
             log.debug(Messages.getMessage("exit00", "HTTPDispatchHandler::invoke"));
 171  
         }
 172  0
     }
 173  
 
 174  
     /**
 175  
      * Creates a socket connection to the SOAP server
 176  
      * 
 177  
      * @param protocol "http" for standard, "https" for ssl.
 178  
      * @param host host name
 179  
      * @param port port to connect to
 180  
      * @param otherHeaders buffer for storing additional headers that need to be sent
 181  
      * @param useFullURL flag to indicate if the complete URL has to be sent
 182  
      * @throws java.io.IOException
 183  
      */
 184  
     protected void getSocket(SocketHolder sockHolder,
 185  
                              MessageContext msgContext,
 186  
                              String protocol,
 187  
                              String host,
 188  
                              int port,
 189  
                              int timeout,
 190  
                              StringBuffer otherHeaders,
 191  
                              BooleanHolder useFullURL) throws Exception
 192  
     {
 193  0
         Hashtable options = getOptions();
 194  0
         if (timeout > 0)
 195  
         {
 196  0
             if (options == null)
 197  
             {
 198  0
                 options = new Hashtable();
 199  
             }
 200  0
             options.put(DefaultSocketFactory.CONNECT_TIMEOUT, Integer.toString(timeout));
 201  
         }
 202  0
         SocketFactory factory = SocketFactoryFactory.getFactory(protocol, options);
 203  0
         if (factory == null)
 204  
         {
 205  0
             throw new IOException(Messages.getMessage("noSocketFactory", protocol));
 206  
         }
 207  
         // log.fatal("Axis client: connect on socket: " + host + ":" + port);
 208  0
         Socket sock = null;
 209  
         try
 210  
         {
 211  0
             sock = factory.create(host, port, otherHeaders, useFullURL);
 212  
         }
 213  0
         catch (Exception e)
 214  
         {
 215  0
             Thread.sleep(1000);
 216  
             try
 217  
             {
 218  0
                 sock = factory.create(host, port, otherHeaders, useFullURL);
 219  
             }
 220  0
             catch (Exception e1)
 221  
             {
 222  0
                 log.fatal("Axis client Failed: connect on socket: " + host + ":" + port, e);
 223  0
                 throw e;
 224  0
             }
 225  0
         }
 226  0
         if (timeout > 0)
 227  
         {
 228  0
             sock.setSoTimeout(timeout);
 229  
         }
 230  0
         sockHolder.setSocket(sock);
 231  0
     }
 232  
 
 233  
     /**
 234  
      * Send the soap request message to the server
 235  
      * 
 236  
      * @param msgContext message context
 237  
      * @param tmpURL url to connect to
 238  
      * @param otherHeaders other headers if any
 239  
      * @param host host name
 240  
      * @param port port
 241  
      * @param useFullURL flag to indicate if the whole url needs to be sent
 242  
      * @throws IOException
 243  
      */
 244  
     private InputStream writeToSocket(SocketHolder sockHolder,
 245  
                                       MessageContext msgContext,
 246  
                                       URL tmpURL,
 247  
                                       StringBuffer otherHeaders,
 248  
                                       String host,
 249  
                                       int port,
 250  
                                       int timeout,
 251  
                                       BooleanHolder useFullURL) throws Exception
 252  
     {
 253  
 
 254  0
         String userID = msgContext.getUsername();
 255  0
         String passwd = msgContext.getPassword();
 256  
 
 257  
         // Get SOAPAction, default to ""
 258  0
         String action = msgContext.useSOAPAction() ? msgContext.getSOAPActionURI() : "";
 259  
 
 260  0
         if (action == null)
 261  
         {
 262  0
             action = "";
 263  
         }
 264  
 
 265  
         // if UserID is not part of the context, but is in the URL, use
 266  
         // the one in the URL.
 267  0
         if ((userID == null) && (tmpURL.getUserInfo() != null))
 268  
         {
 269  0
             String info = tmpURL.getUserInfo();
 270  0
             int sep = info.indexOf(':');
 271  
 
 272  0
             if ((sep >= 0) && (sep + 1 < info.length()))
 273  
             {
 274  0
                 userID = info.substring(0, sep);
 275  0
                 passwd = info.substring(sep + 1);
 276  
             }
 277  
             else
 278  
             {
 279  0
                 userID = info;
 280  
             }
 281  
         }
 282  0
         if (userID != null)
 283  
         {
 284  0
             StringBuffer tmpBuf = new StringBuffer(64);
 285  0
             tmpBuf.append(userID).append(":").append((passwd == null) ? "" : passwd);
 286  0
             otherHeaders.append(HTTPConstants.HEADER_AUTHORIZATION).append(": Basic ").append(
 287  
                 Base64.encode(tmpBuf.toString().getBytes())).append("\r\n");
 288  
         }
 289  
 
 290  
         // don't forget the cookies!
 291  
         // mmm... cookies
 292  0
         if (msgContext.getMaintainSession())
 293  
         {
 294  0
             String cookie = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE);
 295  0
             String cookie2 = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE2);
 296  
 
 297  0
             if (cookie != null)
 298  
             {
 299  0
                 otherHeaders.append(HTTPConstants.HEADER_COOKIE).append(": ").append(cookie).append("\r\n");
 300  
             }
 301  0
             if (cookie2 != null)
 302  
             {
 303  0
                 otherHeaders.append(HTTPConstants.HEADER_COOKIE2).append(": ").append(cookie2).append("\r\n");
 304  
             }
 305  
         }
 306  
 
 307  0
         StringBuffer header2 = new StringBuffer(64);
 308  
 
 309  0
         String webMethod = null;
 310  0
         boolean posting = true;
 311  
 
 312  0
         Message reqMessage = msgContext.getRequestMessage();
 313  
 
 314  0
         boolean http10 = true; // True if this is to use HTTP 1.0 / false HTTP
 315  
         // 1.1
 316  0
         boolean httpChunkStream = false; // Use HTTP chunking or not.
 317  0
         boolean httpContinueExpected = false; // Under HTTP 1.1 if false you
 318  
         // *MAY* need to wait for a 100
 319  
         // rc,
 320  
         // if true the server MUST reply with 100 continue.
 321  0
         String httpConnection = null;
 322  
 
 323  0
         String httpver = msgContext.getStrProp(MessageContext.HTTP_TRANSPORT_VERSION);
 324  0
         if (null == httpver)
 325  
         {
 326  0
             httpver = HTTPConstants.HEADER_PROTOCOL_V10;
 327  
         }
 328  0
         httpver = httpver.trim();
 329  0
         if (httpver.equals(HTTPConstants.HEADER_PROTOCOL_V11))
 330  
         {
 331  0
             http10 = false;
 332  
         }
 333  
 
 334  
         // process user defined headers for information.
 335  0
         Hashtable userHeaderTable = (Hashtable)msgContext.getProperty(HTTPConstants.REQUEST_HEADERS);
 336  
 
 337  0
         if (userHeaderTable != null)
 338  
         {
 339  0
             if (null == otherHeaders)
 340  
             {
 341  0
                 otherHeaders = new StringBuffer(1024);
 342  
             }
 343  
 
 344  0
             for (java.util.Iterator e = userHeaderTable.entrySet().iterator(); e.hasNext();)
 345  
             {
 346  
 
 347  0
                 java.util.Map.Entry me = (java.util.Map.Entry)e.next();
 348  0
                 Object keyObj = me.getKey();
 349  0
                 if (null == keyObj)
 350  
                 {
 351  0
                     continue;
 352  
                 }
 353  0
                 String key = keyObj.toString().trim();
 354  
 
 355  0
                 if (key.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING))
 356  
                 {
 357  0
                     if (!http10)
 358  
                     {
 359  0
                         String val = me.getValue().toString();
 360  0
                         if (null != val
 361  
                             && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
 362  
                         {
 363  0
                             httpChunkStream = true;
 364  
                         }
 365  0
                     }
 366  
                 }
 367  0
                 else if (key.equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION))
 368  
                 {
 369  0
                     if (!http10)
 370  
                     {
 371  0
                         String val = me.getValue().toString();
 372  0
                         if (val.trim().equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION_CLOSE))
 373  
                         {
 374  0
                             httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
 375  
                         }
 376  0
                     }
 377  
                     // HTTP 1.0 will always close.
 378  
                     // HTTP 1.1 will use persistent. //no need to specify
 379  
                 }
 380  
                 else
 381  
                 {
 382  0
                     if (!http10 && key.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT))
 383  
                     {
 384  0
                         String val = me.getValue().toString();
 385  0
                         if (null != val
 386  
                             && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_EXPECT_100_Continue))
 387  
                         {
 388  0
                             httpContinueExpected = true;
 389  
                         }
 390  
                     }
 391  
 
 392  0
                     otherHeaders.append(key).append(": ").append(me.getValue()).append("\r\n");
 393  
                 }
 394  0
             }
 395  
         }
 396  
 
 397  0
         if (!http10)
 398  
         {
 399  
             // Force close for now.
 400  
             // TODO HTTP/1.1
 401  0
             httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
 402  
         }
 403  
 
 404  0
         header2.append(" ");
 405  0
         header2.append(http10 ? HTTPConstants.HEADER_PROTOCOL_10 : HTTPConstants.HEADER_PROTOCOL_11).append(
 406  
             "\r\n");
 407  0
         MimeHeaders mimeHeaders = reqMessage.getMimeHeaders();
 408  
 
 409  0
         if (posting)
 410  
         {
 411  
             String contentType;
 412  0
             if (mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE) != null)
 413  
             {
 414  0
                 contentType = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0];
 415  
             }
 416  
             else
 417  
             {
 418  0
                 contentType = reqMessage.getContentType(msgContext.getSOAPConstants());
 419  
             }
 420  0
             header2.append(HTTPConstants.HEADER_CONTENT_TYPE).append(": ").append(contentType).append("\r\n");
 421  
         }
 422  
 
 423  0
         header2.append(ACCEPT_HEADERS).append(HTTPConstants.HEADER_HOST)
 424  
         // used for virtual connections
 425  
             .append(": ")
 426  
             .append(host)
 427  
             .append((port == -1) ? ("") : (":" + port))
 428  
             .append("\r\n")
 429  
             .append(CACHE_HEADERS)
 430  
             .append(HTTPConstants.HEADER_SOAP_ACTION)
 431  
             // The SOAP action.
 432  
             .append(": \"")
 433  
             .append(action)
 434  
             .append("\"\r\n");
 435  
 
 436  0
         if (posting)
 437  
         {
 438  0
             if (!httpChunkStream)
 439  
             {
 440  
                 // Content length MUST be sent on HTTP 1.0 requests.
 441  0
                 header2.append(HTTPConstants.HEADER_CONTENT_LENGTH).append(": ").append(
 442  
                     reqMessage.getContentLength()).append("\r\n");
 443  
             }
 444  
             else
 445  
             {
 446  
                 // Do http chunking.
 447  0
                 header2.append(CHUNKED_HEADER);
 448  
             }
 449  
         }
 450  
 
 451  
         // Transfer MIME headers of SOAPMessage to HTTP headers.
 452  0
         if (mimeHeaders != null)
 453  
         {
 454  0
             for (Iterator i = mimeHeaders.getAllHeaders(); i.hasNext();)
 455  
             {
 456  0
                 MimeHeader mimeHeader = (MimeHeader)i.next();
 457  0
                 String headerName = mimeHeader.getName();
 458  0
                 if (headerName.equals(HTTPConstants.HEADER_CONTENT_TYPE)
 459  
                     || headerName.equals(HTTPConstants.HEADER_SOAP_ACTION))
 460  
                 {
 461  0
                     continue;
 462  
                 }
 463  0
                 header2.append(mimeHeader.getName())
 464  
                     .append(": ")
 465  
                     .append(mimeHeader.getValue())
 466  
                     .append("\r\n");
 467  0
             }
 468  
         }
 469  
 
 470  0
         if (null != httpConnection)
 471  
         {
 472  0
             header2.append(HTTPConstants.HEADER_CONNECTION);
 473  0
             header2.append(": ");
 474  0
             header2.append(httpConnection);
 475  0
             header2.append("\r\n");
 476  
         }
 477  
 
 478  0
         getSocket(sockHolder, msgContext, targetURL.getProtocol(), host, port, timeout, otherHeaders,
 479  
             useFullURL);
 480  
 
 481  0
         if (null != otherHeaders)
 482  
         {
 483  
             // Add other headers to the end.
 484  
             // for pre java1.4 support, we have to turn the string buffer
 485  
             // argument into
 486  
             // a string before appending.
 487  0
             header2.append(otherHeaders.toString());
 488  
         }
 489  
 
 490  0
         header2.append("\r\n"); // The empty line to start the BODY.
 491  
 
 492  0
         StringBuffer header = new StringBuffer(128);
 493  
 
 494  
         // If we're SOAP 1.2, allow the web method to be set from the
 495  
         // MessageContext.
 496  0
         if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS)
 497  
         {
 498  0
             webMethod = msgContext.getStrProp(SOAP12Constants.PROP_WEBMETHOD);
 499  
         }
 500  0
         if (webMethod == null)
 501  
         {
 502  0
             webMethod = HTTPConstants.HEADER_POST;
 503  
         }
 504  
         else
 505  
         {
 506  0
             posting = webMethod.equals(HTTPConstants.HEADER_POST);
 507  
         }
 508  
 
 509  0
         header.append(webMethod).append(" ");
 510  0
         if (useFullURL.value)
 511  
         {
 512  0
             header.append(tmpURL.toExternalForm());
 513  
         }
 514  
         else
 515  
         {
 516  0
             header.append(StringUtils.isEmpty(tmpURL.getFile()) ? "/" : tmpURL.getFile());
 517  
         }
 518  0
         header.append(header2.toString());
 519  
 
 520  0
         OutputStream out = sockHolder.getSocket().getOutputStream();
 521  
 
 522  0
         if (!posting)
 523  
         {
 524  0
             out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
 525  0
             out.flush();
 526  0
             return null;
 527  
         }
 528  
 
 529  0
         InputStream inp = null;
 530  
 
 531  0
         if (httpChunkStream || httpContinueExpected)
 532  
         {
 533  0
             out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
 534  
         }
 535  
 
 536  0
         if (httpContinueExpected)
 537  
         { // We need to get a reply from the server as
 538  
             // to whether
 539  
             // it wants us send anything more.
 540  0
             out.flush();
 541  0
             Hashtable cheaders = new Hashtable();
 542  0
             inp = readHeadersFromSocket(sockHolder, msgContext, null, cheaders);
 543  0
             int returnCode = -1;
 544  0
             Integer Irc = (Integer)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
 545  0
             if (null != Irc)
 546  
             {
 547  0
                 returnCode = Irc.intValue();
 548  
             }
 549  0
             if (100 == returnCode)
 550  
             { // got 100 we may continue.
 551  
                 // Need TODO a little msgContext house keeping....
 552  0
                 msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
 553  0
                 msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
 554  
             }
 555  
             else
 556  
             { // If no 100 Continue then we must not send anything!
 557  0
                 String statusMessage = (String)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
 558  
 
 559  0
                 AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);
 560  
 
 561  0
                 fault.setFaultDetailString(Messages.getMessage("return01", String.valueOf(returnCode), ""));
 562  0
                 throw fault;
 563  
             }
 564  
         }
 565  0
         ByteArrayOutputStream baos = null;
 566  0
         if (log.isDebugEnabled())
 567  
         {
 568  0
             log.debug(Messages.getMessage("xmlSent00"));
 569  0
             log.debug("---------------------------------------------------");
 570  0
             baos = new ByteArrayOutputStream();
 571  
         }
 572  0
         if (httpChunkStream)
 573  
         {
 574  0
             ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(out);
 575  0
             out = new BufferedOutputStream(chunkedOutputStream, Constants.HTTP_TXR_BUFFER_SIZE);
 576  
             try
 577  
             {
 578  0
                 if (baos != null)
 579  
                 {
 580  0
                     out = new TeeOutputStream(out, baos);
 581  
                 }
 582  0
                 reqMessage.writeTo(out);
 583  
             }
 584  0
             catch (SOAPException e)
 585  
             {
 586  0
                 log.error(Messages.getMessage("exception00"), e);
 587  0
             }
 588  0
             out.flush();
 589  0
             chunkedOutputStream.eos();
 590  0
         }
 591  
         else
 592  
         {
 593  0
             out = new BufferedOutputStream(out, Constants.HTTP_TXR_BUFFER_SIZE);
 594  
             try
 595  
             {
 596  0
                 if (!httpContinueExpected)
 597  
                 {
 598  0
                     out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
 599  
                 }
 600  0
                 if (baos != null)
 601  
                 {
 602  0
                     out = new TeeOutputStream(out, baos);
 603  
                 }
 604  0
                 reqMessage.writeTo(out);
 605  
             }
 606  0
             catch (SOAPException e)
 607  
             {
 608  0
                 throw e;
 609  
             }
 610  
             finally
 611  
             {
 612  
                 // Flush ONLY once.
 613  0
                 out.flush();
 614  0
             }
 615  
 
 616  
         }
 617  
 
 618  0
         if (log.isDebugEnabled() && baos != null)
 619  
         {
 620  0
             log.debug(header + new String(baos.toByteArray()));
 621  
         }
 622  
 
 623  0
         return inp;
 624  
     }
 625  
 
 626  
     private InputStream readHeadersFromSocket(SocketHolder sockHolder,
 627  
                                               MessageContext msgContext,
 628  
                                               InputStream inp,
 629  
                                               Hashtable headers) throws IOException
 630  
     {
 631  0
         byte b = 0;
 632  0
         int len = 0;
 633  0
         int colonIndex = -1;
 634  
         String name, value;
 635  0
         int returnCode = 0;
 636  0
         if (null == inp)
 637  
         {
 638  0
             inp = new BufferedInputStream(sockHolder.getSocket().getInputStream());
 639  
         }
 640  
 
 641  0
         if (headers == null)
 642  
         {
 643  0
             headers = new Hashtable();
 644  
         }
 645  
 
 646  
         // Should help performance. Temporary fix only till its all stream
 647  
         // oriented.
 648  
         // Need to add logic for getting the version # and the return code
 649  
         // but that's for tomorrow!
 650  
 
 651  
         /* Logic to read HTTP response headers */
 652  0
         boolean readTooMuch = false;
 653  
 
 654  0
         for (ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);;)
 655  
         {
 656  0
             if (!readTooMuch)
 657  
             {
 658  0
                 b = (byte)inp.read();
 659  
             }
 660  0
             if (b == -1)
 661  
             {
 662  0
                 break;
 663  
             }
 664  0
             readTooMuch = false;
 665  0
             if ((b != '\r') && (b != '\n'))
 666  
             {
 667  0
                 if ((b == ':') && (colonIndex == -1))
 668  
                 {
 669  0
                     colonIndex = len;
 670  
                 }
 671  0
                 len++;
 672  0
                 buf.write(b);
 673  
             }
 674  0
             else if (b == '\r')
 675  
             {
 676  0
                 continue;
 677  
             }
 678  
             else
 679  
             { // b== '\n'
 680  0
                 if (len == 0)
 681  
                 {
 682  0
                     break;
 683  
                 }
 684  0
                 b = (byte)inp.read();
 685  0
                 readTooMuch = true;
 686  
 
 687  
                 // A space or tab at the begining of a line means the header
 688  
                 // continues.
 689  0
                 if ((b == ' ') || (b == '\t'))
 690  
                 {
 691  0
                     continue;
 692  
                 }
 693  0
                 buf.close();
 694  0
                 byte[] hdata = buf.toByteArray();
 695  0
                 buf.reset();
 696  0
                 if (colonIndex != -1)
 697  
                 {
 698  0
                     name = new String(hdata, 0, colonIndex, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
 699  0
                     value = new String(hdata, colonIndex + 1, len - 1 - colonIndex,
 700  
                         HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
 701  0
                     colonIndex = -1;
 702  
                 }
 703  
                 else
 704  
                 {
 705  
 
 706  0
                     name = new String(hdata, 0, len, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
 707  0
                     value = "";
 708  
                 }
 709  0
                 if (log.isDebugEnabled())
 710  
                 {
 711  0
                     log.debug(name + value);
 712  
                 }
 713  0
                 if (msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE) == null)
 714  
                 {
 715  
 
 716  
                     // Reader status code
 717  0
                     int start = name.indexOf(' ') + 1;
 718  0
                     String tmp = name.substring(start).trim();
 719  0
                     int end = tmp.indexOf(' ');
 720  
 
 721  0
                     if (end != -1)
 722  
                     {
 723  0
                         tmp = tmp.substring(0, end);
 724  
                     }
 725  0
                     returnCode = Integer.parseInt(tmp);
 726  0
                     msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, new Integer(returnCode));
 727  0
                     msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE, name.substring(start + end
 728  
                                                                                                 + 1));
 729  0
                 }
 730  
                 else
 731  
                 {
 732  0
                     headers.put(name.toLowerCase(), value);
 733  
                 }
 734  0
                 len = 0;
 735  0
             }
 736  
         }
 737  
 
 738  0
         return inp;
 739  
     }
 740  
 
 741  
     /**
 742  
      * Reads the SOAP response back from the server
 743  
      * 
 744  
      * @param msgContext message context
 745  
      * @throws IOException
 746  
      */
 747  
     private InputStream readFromSocket(SocketHolder socketHolder,
 748  
                                        MessageContext msgContext,
 749  
                                        InputStream inp,
 750  
                                        Hashtable headers) throws IOException
 751  
     {
 752  0
         Message outMsg = null;
 753  
         byte b;
 754  
 
 755  0
         Integer rc = (Integer)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
 756  0
         int returnCode = 0;
 757  0
         if (rc != null)
 758  
         {
 759  0
             returnCode = rc.intValue();
 760  
         }
 761  
         else
 762  
         {
 763  
             // No return code?? Should have one by now.
 764  
         }
 765  
 
 766  
         /* All HTTP headers have been read. */
 767  0
         String contentType = (String)headers.get(HEADER_CONTENT_TYPE_LC);
 768  
 
 769  0
         contentType = (null == contentType) ? null : contentType.trim();
 770  
 
 771  0
         String location = (String)headers.get(HEADER_LOCATION_LC);
 772  
 
 773  0
         location = (null == location) ? null : location.trim();
 774  
 
 775  0
         if ((returnCode > 199) && (returnCode < 300))
 776  
         {
 777  0
             if (returnCode == 202)
 778  
             {
 779  0
                 return inp;
 780  
             }
 781  
             // SOAP return is OK - so fall through
 782  
         }
 783  0
         else if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS)
 784  
         {
 785  
             // For now, if we're SOAP 1.2, fall through, since the range of
 786  
             // valid result codes is much greater
 787  
         }
 788  0
         else if ((contentType != null) && !contentType.startsWith("text/html")
 789  
                  && ((returnCode > 499) && (returnCode < 600)))
 790  
         {
 791  
             // SOAP Fault should be in here - so fall through
 792  
         }
 793  0
         else if ((location != null) && ((returnCode == 302) || (returnCode == 307)))
 794  
         {
 795  
             // Temporary Redirect (HTTP: 302/307)
 796  
             // close old connection
 797  0
             inp.close();
 798  0
             socketHolder.getSocket().close();
 799  
             // remove former result and set new target url
 800  0
             msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
 801  0
             msgContext.setProperty(MessageContext.TRANS_URL, location);
 802  
             // next try
 803  0
             invoke(msgContext);
 804  0
             return inp;
 805  
         }
 806  0
         else if (returnCode == 100)
 807  
         {
 808  0
             msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
 809  0
             msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
 810  0
             readHeadersFromSocket(socketHolder, msgContext, inp, headers);
 811  0
             return readFromSocket(socketHolder, msgContext, inp, headers);
 812  
         }
 813  
         else
 814  
         {
 815  
             // Unknown return code - so wrap up the content into a
 816  
             // SOAP Fault.
 817  0
             ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);
 818  
 
 819  0
             while (-1 != (b = (byte)inp.read()))
 820  
             {
 821  0
                 buf.write(b);
 822  
             }
 823  0
             String statusMessage = msgContext.getStrProp(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
 824  0
             AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);
 825  
 
 826  0
             fault.setFaultDetailString(Messages.getMessage("return01", String.valueOf(returnCode), buf.toString()));
 827  0
             fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE, Integer.toString(returnCode));
 828  0
             throw fault;
 829  
         }
 830  
 
 831  0
         String contentLocation = (String)headers.get(HEADER_CONTENT_LOCATION_LC);
 832  
 
 833  0
         contentLocation = (null == contentLocation) ? null : contentLocation.trim();
 834  
 
 835  0
         String contentLength = (String)headers.get(HEADER_CONTENT_LENGTH_LC);
 836  
 
 837  0
         contentLength = (null == contentLength) ? null : contentLength.trim();
 838  
 
 839  0
         String transferEncoding = (String)headers.get(HEADER_TRANSFER_ENCODING_LC);
 840  
 
 841  0
         if (null != transferEncoding)
 842  
         {
 843  0
             transferEncoding = transferEncoding.trim().toLowerCase();
 844  0
             if (transferEncoding.equals(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
 845  
             {
 846  0
                 inp = new ChunkedInputStream(inp);
 847  
             }
 848  
         }
 849  
 
 850  0
         outMsg = new Message(new SocketInputStream(inp, socketHolder.getSocket()), false, contentType,
 851  
             contentLocation);
 852  
         // Transfer HTTP headers of HTTP message to MIME headers of SOAP message
 853  0
         MimeHeaders mimeHeaders = outMsg.getMimeHeaders();
 854  0
         for (Enumeration e = headers.keys(); e.hasMoreElements();)
 855  
         {
 856  0
             String key = (String)e.nextElement();
 857  0
             mimeHeaders.addHeader(key, ((String)headers.get(key)).trim());
 858  0
         }
 859  0
         outMsg.setMessageType(Message.RESPONSE);
 860  0
         msgContext.setResponseMessage(outMsg);
 861  0
         if (log.isDebugEnabled())
 862  
         {
 863  0
             if (null == contentLength)
 864  
             {
 865  0
                 log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("no00", "Content-Length"));
 866  
             }
 867  0
             log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("xmlRecd00"));
 868  0
             log.debug("-----------------------------------------------");
 869  0
             log.debug(outMsg.getSOAPEnvelope().toString());
 870  
         }
 871  
 
 872  
         // if we are maintaining session state,
 873  
         // handle cookies (if any)
 874  0
         if (msgContext.getMaintainSession())
 875  
         {
 876  0
             handleCookie(HTTPConstants.HEADER_COOKIE, HTTPConstants.HEADER_SET_COOKIE, headers, msgContext);
 877  0
             handleCookie(HTTPConstants.HEADER_COOKIE2, HTTPConstants.HEADER_SET_COOKIE2, headers, msgContext);
 878  
         }
 879  0
         return inp;
 880  
     }
 881  
 
 882  
     /**
 883  
      * little helper function for cookies
 884  
      * 
 885  
      * @param cookieName
 886  
      * @param setCookieName
 887  
      * @param headers
 888  
      * @param msgContext
 889  
      */
 890  
     public void handleCookie(String cookieName,
 891  
                              String setCookieName,
 892  
                              Hashtable headers,
 893  
                              MessageContext msgContext)
 894  
     {
 895  
 
 896  0
         if (headers.containsKey(setCookieName.toLowerCase()))
 897  
         {
 898  0
             String cookie = (String)headers.get(setCookieName.toLowerCase());
 899  0
             cookie = cookie.trim();
 900  
 
 901  
             // chop after first ; a la Apache SOAP (see HTTPUtils.java there)
 902  0
             int index = cookie.indexOf(';');
 903  
 
 904  0
             if (index != -1)
 905  
             {
 906  0
                 cookie = cookie.substring(0, index);
 907  
             }
 908  0
             msgContext.setProperty(cookieName, cookie);
 909  
         }
 910  0
     }
 911  
 }