org.mule.transport.soap.axis.extensions.MuleHttpSender.java Source code

Java tutorial

Introduction

Here is the source code for org.mule.transport.soap.axis.extensions.MuleHttpSender.java

Source

/*
 * $Id$
 * --------------------------------------------------------------------------------------
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */

package org.mule.transport.soap.axis.extensions;

import org.mule.module.cxf.SoapConstants;
import org.mule.util.StringUtils;
import org.mule.util.SystemUtils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPException;

import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.client.Call;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.components.net.BooleanHolder;
import org.apache.axis.components.net.DefaultSocketFactory;
import org.apache.axis.components.net.SocketFactory;
import org.apache.axis.components.net.SocketFactoryFactory;
import org.apache.axis.encoding.Base64;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.soap.SOAP12Constants;
import org.apache.axis.soap.SOAPConstants;
import org.apache.axis.transport.http.ChunkedInputStream;
import org.apache.axis.transport.http.ChunkedOutputStream;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.transport.http.HTTPSender;
import org.apache.axis.transport.http.SocketHolder;
import org.apache.axis.transport.http.SocketInputStream;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.TeeOutputStream;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.logging.Log;

/**
 * <code>MuleHttpSender</code> is a rewrite of the Axis HttpSender. Unfortunately,
 * the Axis implementation is not extensible so this class is a copy of it with
 * modifications. The enhancements made are to allow for asynchronous Http method
 * calls which Mule initiates when the endpoint is asynchronous.
 *
 * @deprecated Use the UniversalSender instead
 */
@Deprecated
public class MuleHttpSender extends BasicHandler {
    /**
     * Serial version
     */
    private static final long serialVersionUID = -1730816323289419500L;

    protected static final Log log = LogFactory.getLog(HTTPSender.class.getName());

    private static final String ACCEPT_HEADERS = HTTPConstants.HEADER_ACCEPT
            // limit to the types that are
            // meaningful to us.
            + ": " + HTTPConstants.HEADER_ACCEPT_APPL_SOAP + ", " + HTTPConstants.HEADER_ACCEPT_APPLICATION_DIME
            + ", " + HTTPConstants.HEADER_ACCEPT_MULTIPART_RELATED + ", " + HTTPConstants.HEADER_ACCEPT_TEXT_ALL
            + "\r\n" + HTTPConstants.HEADER_USER_AGENT // Tell
                                                                                                                                                                                                                                                                 // who
                                                                                                                                                                                                                                                                 // we
                                                                                                                                                                                                                                                                 // are.
            + ": " + Messages.getMessage("axisUserAgent") + "\r\n";

    private static final String CACHE_HEADERS = HTTPConstants.HEADER_CACHE_CONTROL
            // stop caching proxies from caching
            // SOAP request.
            + ": " + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n" + HTTPConstants.HEADER_PRAGMA + ": "
            + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n";

    private static final String CHUNKED_HEADER = HTTPConstants.HEADER_TRANSFER_ENCODING + ": "
            + HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED + "\r\n";

    private static final String HEADER_CONTENT_TYPE_LC = HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase();

    private static final String HEADER_LOCATION_LC = HTTPConstants.HEADER_LOCATION.toLowerCase();

    private static final String HEADER_CONTENT_LOCATION_LC = HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase();

    private static final String HEADER_CONTENT_LENGTH_LC = HTTPConstants.HEADER_CONTENT_LENGTH.toLowerCase();

    private static final String HEADER_TRANSFER_ENCODING_LC = HTTPConstants.HEADER_TRANSFER_ENCODING.toLowerCase();

    /**
     * the url; used for error reporting
     */
    URL targetURL;

    /**
     * invoke creates a socket connection, sends the request SOAP message and then
     * reads the response SOAP message back from the SOAP server
     *
     * @param msgContext the messsage context
     * @throws AxisFault
     */
    @Override
    public void invoke(MessageContext msgContext) throws AxisFault {

        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("enter00", "HTTPSender::invoke"));
        }
        try {
            Call call = (Call) msgContext.getProperty("call_object");
            String transURL = msgContext.getStrProp(MessageContext.TRANS_URL);
            String uri = transURL;
            if (call != null && call.useSOAPAction()) {
                uri = call.getSOAPActionURI();
            }
            msgContext.setProperty(SoapConstants.SOAP_ACTION_PROPERTY_CAPS, uri);

            BooleanHolder useFullURL = new BooleanHolder(false);
            StringBuffer otherHeaders = new StringBuffer(64);
            targetURL = new URL(transURL);
            String host = targetURL.getHost();
            int port = targetURL.getPort();

            SocketHolder socketHolder = new SocketHolder(null);

            // Send the SOAP request to the server
            InputStream inp = writeToSocket(socketHolder, msgContext, targetURL, otherHeaders, host, port,
                    msgContext.getTimeout(), useFullURL);

            if (msgContext.isClient() && call != null) {
                if (Boolean.TRUE.equals(call.getProperty("axis.one.way"))) {
                    return;
                }
            }

            // Read the response back from the server
            Hashtable<String, String> headers = new Hashtable<String, String>();
            inp = readHeadersFromSocket(socketHolder, msgContext, inp, headers);
            readFromSocket(socketHolder, msgContext, inp, headers);
        } catch (Exception e) {
            log.debug(e);
            throw AxisFault.makeFault(e);
        }
        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("exit00", "HTTPDispatchHandler::invoke"));
        }
    }

    /**
     * Creates a socket connection to the SOAP server
     *
     * @param protocol "http" for standard, "https" for ssl.
     * @param host host name
     * @param port port to connect to
     * @param otherHeaders buffer for storing additional headers that need to be sent
     * @param useFullURL flag to indicate if the complete URL has to be sent
     * @throws java.io.IOException
     */
    protected void getSocket(SocketHolder sockHolder, MessageContext msgContext, String protocol, String host,
            int port, int timeout, StringBuffer otherHeaders, BooleanHolder useFullURL) throws Exception {
        @SuppressWarnings("unchecked")
        Hashtable<Object, Object> socketFactoryOptions = getOptions();
        if (timeout > 0) {
            if (socketFactoryOptions == null) {
                socketFactoryOptions = new Hashtable<Object, Object>();
            }
            socketFactoryOptions.put(DefaultSocketFactory.CONNECT_TIMEOUT, Integer.toString(timeout));
        }
        SocketFactory factory = SocketFactoryFactory.getFactory(protocol, socketFactoryOptions);
        if (factory == null) {
            throw new IOException(Messages.getMessage("noSocketFactory", protocol));
        }
        // log.fatal("Axis client: connect on socket: " + host + ":" + port);
        Socket sock = null;
        try {
            sock = factory.create(host, port, otherHeaders, useFullURL);
        } catch (Exception e) {
            Thread.sleep(1000);
            try {
                sock = factory.create(host, port, otherHeaders, useFullURL);
            } catch (Exception e1) {
                log.fatal("Axis client Failed: connect on socket: " + host + ":" + port, e);
                throw e;
            }
        }
        if (timeout > 0) {
            sock.setSoTimeout(timeout);
        }
        sockHolder.setSocket(sock);
    }

    /**
     * Send the soap request message to the server
     *
     * @param msgContext message context
     * @param tmpURL url to connect to
     * @param otherHeaders other headers if any
     * @param host host name
     * @param port port
     * @param useFullURL flag to indicate if the whole url needs to be sent
     * @throws IOException
     */
    private InputStream writeToSocket(SocketHolder sockHolder, MessageContext msgContext, URL tmpURL,
            StringBuffer otherHeaders, String host, int port, int timeout, BooleanHolder useFullURL)
            throws Exception {

        String userID = msgContext.getUsername();
        String passwd = msgContext.getPassword();

        // Get SOAPAction, default to ""
        String action = msgContext.useSOAPAction() ? msgContext.getSOAPActionURI() : "";

        if (action == null) {
            action = "";
        }

        // if UserID is not part of the context, but is in the URL, use
        // the one in the URL.
        if ((userID == null) && (tmpURL.getUserInfo() != null)) {
            String info = tmpURL.getUserInfo();
            int sep = info.indexOf(':');

            if ((sep >= 0) && (sep + 1 < info.length())) {
                userID = info.substring(0, sep);
                passwd = info.substring(sep + 1);
            } else {
                userID = info;
            }
        }
        if (userID != null) {
            StringBuffer tmpBuf = new StringBuffer(64);
            tmpBuf.append(userID).append(":").append((passwd == null) ? "" : passwd);
            otherHeaders.append(HTTPConstants.HEADER_AUTHORIZATION).append(": Basic ")
                    .append(Base64.encode(tmpBuf.toString().getBytes())).append("\r\n");
        }

        // don't forget the cookies!
        // mmm... cookies
        if (msgContext.getMaintainSession()) {
            String cookie = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE);
            String cookie2 = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE2);

            if (cookie != null) {
                otherHeaders.append(HTTPConstants.HEADER_COOKIE).append(": ").append(cookie).append("\r\n");
            }
            if (cookie2 != null) {
                otherHeaders.append(HTTPConstants.HEADER_COOKIE2).append(": ").append(cookie2).append("\r\n");
            }
        }

        StringBuffer header2 = new StringBuffer(64);

        String webMethod = null;
        boolean posting = true;

        Message reqMessage = msgContext.getRequestMessage();

        boolean http10 = true; // True if this is to use HTTP 1.0 / false HTTP
        // 1.1
        boolean httpChunkStream = false; // Use HTTP chunking or not.
        boolean httpContinueExpected = false; // Under HTTP 1.1 if false you
        // *MAY* need to wait for a 100
        // rc,
        // if true the server MUST reply with 100 continue.
        String httpConnection = null;

        String httpver = msgContext.getStrProp(MessageContext.HTTP_TRANSPORT_VERSION);
        if (null == httpver) {
            httpver = HTTPConstants.HEADER_PROTOCOL_V10;
        }
        httpver = httpver.trim();
        if (httpver.equals(HTTPConstants.HEADER_PROTOCOL_V11)) {
            http10 = false;
        }

        // process user defined headers for information.
        Hashtable userHeaderTable = (Hashtable) msgContext.getProperty(HTTPConstants.REQUEST_HEADERS);

        if (userHeaderTable != null) {
            if (null == otherHeaders) {
                otherHeaders = new StringBuffer(1024);
            }

            for (java.util.Iterator e = userHeaderTable.entrySet().iterator(); e.hasNext();) {

                java.util.Map.Entry me = (java.util.Map.Entry) e.next();
                Object keyObj = me.getKey();
                if (null == keyObj) {
                    continue;
                }
                String key = keyObj.toString().trim();

                if (key.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING)) {
                    if (!http10) {
                        String val = me.getValue().toString();
                        if (null != val
                                && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED)) {
                            httpChunkStream = true;
                        }
                    }
                } else if (key.equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION)) {
                    if (!http10) {
                        String val = me.getValue().toString();
                        if (val.trim().equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION_CLOSE)) {
                            httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
                        }
                    }
                    // HTTP 1.0 will always close.
                    // HTTP 1.1 will use persistent. //no need to specify
                } else {
                    if (!http10 && key.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT)) {
                        String val = me.getValue().toString();
                        if (null != val && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_EXPECT_100_Continue)) {
                            httpContinueExpected = true;
                        }
                    }

                    otherHeaders.append(key).append(": ").append(me.getValue()).append("\r\n");
                }
            }
        }

        if (!http10) {
            // Force close for now.
            // TODO HTTP/1.1
            httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
        }

        header2.append(" ");
        header2.append(http10 ? HTTPConstants.HEADER_PROTOCOL_10 : HTTPConstants.HEADER_PROTOCOL_11).append("\r\n");
        MimeHeaders mimeHeaders = reqMessage.getMimeHeaders();

        if (posting) {
            String contentType;
            if (mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE) != null) {
                contentType = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0];
            } else {
                contentType = reqMessage.getContentType(msgContext.getSOAPConstants());
            }
            header2.append(HTTPConstants.HEADER_CONTENT_TYPE).append(": ").append(contentType).append("\r\n");
        }

        header2.append(ACCEPT_HEADERS).append(HTTPConstants.HEADER_HOST)
                // used for virtual connections
                .append(": ").append(host).append((port == -1) ? ("") : (":" + port)).append("\r\n")
                .append(CACHE_HEADERS).append(HTTPConstants.HEADER_SOAP_ACTION)
                // The SOAP action.
                .append(": \"").append(action).append("\"\r\n");

        if (posting) {
            if (!httpChunkStream) {
                // Content length MUST be sent on HTTP 1.0 requests.
                header2.append(HTTPConstants.HEADER_CONTENT_LENGTH).append(": ")
                        .append(reqMessage.getContentLength()).append("\r\n");
            } else {
                // Do http chunking.
                header2.append(CHUNKED_HEADER);
            }
        }

        // Transfer MIME headers of SOAPMessage to HTTP headers.
        if (mimeHeaders != null) {
            for (Iterator i = mimeHeaders.getAllHeaders(); i.hasNext();) {
                MimeHeader mimeHeader = (MimeHeader) i.next();
                String headerName = mimeHeader.getName();
                if (headerName.equals(HTTPConstants.HEADER_CONTENT_TYPE)
                        || headerName.equals(HTTPConstants.HEADER_SOAP_ACTION)) {
                    continue;
                }
                header2.append(mimeHeader.getName()).append(": ").append(mimeHeader.getValue()).append("\r\n");
            }
        }

        if (null != httpConnection) {
            header2.append(HTTPConstants.HEADER_CONNECTION);
            header2.append(": ");
            header2.append(httpConnection);
            header2.append("\r\n");
        }

        getSocket(sockHolder, msgContext, targetURL.getProtocol(), host, port, timeout, otherHeaders, useFullURL);

        if (null != otherHeaders) {
            // Add other headers to the end.
            // for pre java1.4 support, we have to turn the string buffer
            // argument into
            // a string before appending.
            header2.append(otherHeaders.toString());
        }

        header2.append("\r\n"); // The empty line to start the BODY.

        StringBuffer header = new StringBuffer(128);

        // If we're SOAP 1.2, allow the web method to be set from the
        // MessageContext.
        if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) {
            webMethod = msgContext.getStrProp(SOAP12Constants.PROP_WEBMETHOD);
        }
        if (webMethod == null) {
            webMethod = HTTPConstants.HEADER_POST;
        } else {
            posting = webMethod.equals(HTTPConstants.HEADER_POST);
        }

        header.append(webMethod).append(" ");
        if (useFullURL.value) {
            header.append(tmpURL.toExternalForm());
        } else {
            header.append(StringUtils.isEmpty(tmpURL.getFile()) ? "/" : tmpURL.getFile());
        }
        header.append(header2.toString());

        OutputStream out = sockHolder.getSocket().getOutputStream();

        if (!posting) {
            out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
            out.flush();
            return null;
        }

        InputStream inp = null;

        if (httpChunkStream || httpContinueExpected) {
            out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
        }

        if (httpContinueExpected) { // We need to get a reply from the server as
                                    // to whether
                                    // it wants us send anything more.
            out.flush();
            Hashtable cheaders = new Hashtable();
            inp = readHeadersFromSocket(sockHolder, msgContext, null, cheaders);
            int returnCode = -1;
            Integer Irc = (Integer) msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
            if (null != Irc) {
                returnCode = Irc.intValue();
            }
            if (100 == returnCode) { // got 100 we may continue.
                                     // Need TODO a little msgContext house keeping....
                msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
                msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
            } else { // If no 100 Continue then we must not send anything!
                String statusMessage = (String) msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);

                AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);

                fault.setFaultDetailString(Messages.getMessage("return01", String.valueOf(returnCode), ""));
                throw fault;
            }
        }
        ByteArrayOutputStream baos = null;
        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("xmlSent00"));
            log.debug("---------------------------------------------------");
            baos = new ByteArrayOutputStream();
        }
        if (httpChunkStream) {
            ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(out);
            out = new BufferedOutputStream(chunkedOutputStream, Constants.HTTP_TXR_BUFFER_SIZE);
            try {
                if (baos != null) {
                    out = new TeeOutputStream(out, baos);
                }
                reqMessage.writeTo(out);
            } catch (SOAPException e) {
                log.error(Messages.getMessage("exception00"), e);
            }
            out.flush();
            chunkedOutputStream.eos();
        } else {
            out = new BufferedOutputStream(out, Constants.HTTP_TXR_BUFFER_SIZE);
            try {
                if (!httpContinueExpected) {
                    out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
                }
                if (baos != null) {
                    out = new TeeOutputStream(out, baos);
                }
                reqMessage.writeTo(out);
            } catch (SOAPException e) {
                throw e;
            } finally {
                // Flush ONLY once.
                out.flush();
            }

        }

        if (log.isDebugEnabled() && baos != null) {
            log.debug(header + new String(baos.toByteArray()));
        }

        return inp;
    }

    private InputStream readHeadersFromSocket(SocketHolder sockHolder, MessageContext msgContext, InputStream inp,
            Hashtable<String, String> headers) throws IOException {
        byte b = 0;
        int len = 0;
        int colonIndex = -1;
        String name, value;
        int returnCode = 0;
        if (null == inp) {
            inp = new BufferedInputStream(sockHolder.getSocket().getInputStream());
        }

        if (headers == null) {
            headers = new Hashtable<String, String>();
        }

        // Should help performance. Temporary fix only till its all stream
        // oriented.
        // Need to add logic for getting the version # and the return code
        // but that's for tomorrow!

        /* Logic to read HTTP response headers */
        boolean readTooMuch = false;

        for (ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);;) {
            if (!readTooMuch) {
                b = (byte) inp.read();
            }
            if (b == -1) {
                break;
            }
            readTooMuch = false;
            if ((b != '\r') && (b != '\n')) {
                if ((b == ':') && (colonIndex == -1)) {
                    colonIndex = len;
                }
                len++;
                buf.write(b);
            } else if (b == '\r') {
                continue;
            } else { // b== '\n'
                if (len == 0) {
                    break;
                }
                b = (byte) inp.read();
                readTooMuch = true;

                // A space or tab at the begining of a line means the header
                // continues.
                if ((b == ' ') || (b == '\t')) {
                    continue;
                }
                buf.close();
                byte[] hdata = buf.toByteArray();
                buf.reset();
                if (colonIndex != -1) {
                    name = new String(hdata, 0, colonIndex, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
                    value = new String(hdata, colonIndex + 1, len - 1 - colonIndex,
                            HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
                    colonIndex = -1;
                } else {

                    name = new String(hdata, 0, len, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
                    value = "";
                }
                if (log.isDebugEnabled()) {
                    log.debug(name + value);
                }
                if (msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE) == null) {

                    // Reader status code
                    int start = name.indexOf(' ') + 1;
                    String tmp = name.substring(start).trim();
                    int end = tmp.indexOf(' ');

                    if (end != -1) {
                        tmp = tmp.substring(0, end);
                    }
                    returnCode = Integer.parseInt(tmp);
                    msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, new Integer(returnCode));
                    msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE, name.substring(start + end + 1));
                } else {
                    headers.put(name.toLowerCase(), value);
                }
                len = 0;
            }
        }

        return inp;
    }

    /**
     * Reads the SOAP response back from the server
     *
     * @param msgContext message context
     * @throws IOException
     */
    private InputStream readFromSocket(SocketHolder socketHolder, MessageContext msgContext, InputStream inp,
            Hashtable headers) throws IOException {
        Message outMsg = null;
        byte b;

        Integer rc = (Integer) msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
        int returnCode = 0;
        if (rc != null) {
            returnCode = rc.intValue();
        } else {
            // No return code?? Should have one by now.
        }

        /* All HTTP headers have been read. */
        String contentType = (String) headers.get(HEADER_CONTENT_TYPE_LC);

        contentType = (null == contentType) ? null : contentType.trim();

        String location = (String) headers.get(HEADER_LOCATION_LC);

        location = (null == location) ? null : location.trim();

        if ((returnCode > 199) && (returnCode < 300)) {
            if (returnCode == 202) {
                return inp;
            }
            // SOAP return is OK - so fall through
        } else if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS) {
            // For now, if we're SOAP 1.2, fall through, since the range of
            // valid result codes is much greater
        } else if ((contentType != null) && !contentType.startsWith("text/html")
                && ((returnCode > 499) && (returnCode < 600))) {
            // SOAP Fault should be in here - so fall through
        } else if ((location != null) && ((returnCode == 302) || (returnCode == 307))) {
            // Temporary Redirect (HTTP: 302/307)
            // close old connection
            inp.close();
            socketHolder.getSocket().close();
            // remove former result and set new target url
            msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
            msgContext.setProperty(MessageContext.TRANS_URL, location);
            // next try
            invoke(msgContext);
            return inp;
        } else if (returnCode == 100) {
            msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
            msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
            readHeadersFromSocket(socketHolder, msgContext, inp, headers);
            return readFromSocket(socketHolder, msgContext, inp, headers);
        } else {
            // Unknown return code - so wrap up the content into a
            // SOAP Fault.
            ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);

            while (-1 != (b = (byte) inp.read())) {
                buf.write(b);
            }
            String statusMessage = msgContext.getStrProp(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
            AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);

            fault.setFaultDetailString(Messages.getMessage("return01", String.valueOf(returnCode), buf.toString()));
            fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE, Integer.toString(returnCode));
            throw fault;
        }

        String contentLocation = (String) headers.get(HEADER_CONTENT_LOCATION_LC);

        contentLocation = (null == contentLocation) ? null : contentLocation.trim();

        String contentLength = (String) headers.get(HEADER_CONTENT_LENGTH_LC);

        contentLength = (null == contentLength) ? null : contentLength.trim();

        String transferEncoding = (String) headers.get(HEADER_TRANSFER_ENCODING_LC);

        if (null != transferEncoding) {
            transferEncoding = transferEncoding.trim().toLowerCase();
            if (transferEncoding.equals(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED)) {
                inp = new ChunkedInputStream(inp);
            }
        }

        outMsg = new Message(new SocketInputStream(inp, socketHolder.getSocket()), false, contentType,
                contentLocation);
        // Transfer HTTP headers of HTTP message to MIME headers of SOAP message
        MimeHeaders mimeHeaders = outMsg.getMimeHeaders();
        for (Enumeration e = headers.keys(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            mimeHeaders.addHeader(key, ((String) headers.get(key)).trim());
        }
        outMsg.setMessageType(Message.RESPONSE);
        msgContext.setResponseMessage(outMsg);
        if (log.isDebugEnabled()) {
            if (null == contentLength) {
                log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("no00", "Content-Length"));
            }
            log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("xmlRecd00"));
            log.debug("-----------------------------------------------");
            log.debug(outMsg.getSOAPEnvelope().toString());
        }

        // if we are maintaining session state,
        // handle cookies (if any)
        if (msgContext.getMaintainSession()) {
            handleCookie(HTTPConstants.HEADER_COOKIE, HTTPConstants.HEADER_SET_COOKIE, headers, msgContext);
            handleCookie(HTTPConstants.HEADER_COOKIE2, HTTPConstants.HEADER_SET_COOKIE2, headers, msgContext);
        }
        return inp;
    }

    /**
     * little helper function for cookies
     *
     * @param cookieName
     * @param setCookieName
     * @param headers
     * @param msgContext
     */
    public void handleCookie(String cookieName, String setCookieName, Hashtable headers,
            MessageContext msgContext) {

        if (headers.containsKey(setCookieName.toLowerCase())) {
            String cookie = (String) headers.get(setCookieName.toLowerCase());
            cookie = cookie.trim();

            // chop after first ; a la Apache SOAP (see HTTPUtils.java there)
            int index = cookie.indexOf(';');

            if (index != -1) {
                cookie = cookie.substring(0, index);
            }
            msgContext.setProperty(cookieName, cookie);
        }
    }
}