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