package org.codehaus.xfire.transport.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.XFireException;
import org.codehaus.xfire.exchange.InMessage;
import org.codehaus.xfire.exchange.OutMessage;
import org.codehaus.xfire.fault.XFireFault;
import org.codehaus.xfire.util.STAXUtils;

/**
 * Sends a http message via commons http client.
 * 
 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
 * @since Oct 26, 2004
 */
public class CommonsHttpMessageSender extends AbstractMessageSender
{
    private PostMethod postMethod;

    private HttpClient client;

    private static final Log log = LogFactory.getLog(CommonsHttpMessageSender.class);
    
    public CommonsHttpMessageSender(OutMessage message, MessageContext context)
    {
        super(message, context);
    }
    
    public void open()
        throws IOException, XFireFault
    {
        client = new HttpClient();

        client.getParams().setParameter("http.useragent", " Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; " +
                "XFire Client +http://xfire.codehaus.org)");
        client.getParams().setBooleanParameter("http.protocol.expect-continue", false);
        client.getParams().setVersion(HttpVersion.HTTP_1_1);

        postMethod = new PostMethod(getUri());
        postMethod.setRequestHeader("Content-Type", "text/xml; charset="+getEncoding());

        if (getSoapAction() != null)
        {
            postMethod.setRequestHeader("SOAPAction", getQuotedSoapAction());
        }
    }

    public void send()
        throws HttpException, IOException
    {
        RequestEntity requestEntity;
        
        /**
         * Lots of HTTP servers don't handle chunking correctly, so its turned off by default.
         */
        boolean chunkingOn = Boolean.valueOf((String) getMessageContext()
                .getProperty(HttpTransport.CHUNKING_ENABLED)).booleanValue();
        if (!chunkingOn)
        {
            requestEntity = getByteArrayRequestEntity();
        }
        else
        {
            requestEntity = new OutMessageRequestEntity(getMessage(), getMessageContext());
        }
        
        getMethod().setRequestEntity(requestEntity);
        
        client.executeMethod(postMethod);
    }

    private RequestEntity getByteArrayRequestEntity()
        throws IOException
    {
        OutMessage message = getMessage();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(bos, message.getEncoding());
        try
        {
            message.getSerializer().writeMessage(message, writer, getMessageContext());
            writer.close();
            bos.close();
            
            return new ByteArrayRequestEntity(bos.toByteArray());
        }
        catch (XFireFault e)
        {
            log.error("Couldn't send message.", e);
            throw new IOException(e.getMessage());
        }
        catch (XMLStreamException e)
        {
            log.error("Couldn't send message.", e);
            throw new IOException(e.getMessage());
        }
    }

    public InMessage getInMessage()
        throws IOException
    {
        InputStream in = postMethod.getResponseBodyAsStream();
        return new InMessage(STAXUtils.createXMLStreamReader(in, getEncoding()), getUri());
    }

    public PostMethod getMethod()
    {
        return this.postMethod;
    }

    public void close()
        throws XFireException
    {
        if (postMethod != null)
            postMethod.releaseConnection();
    }
}

@@ -41,189 +41,8 @@
 p;%0A%0A
-import java.io.ByteArrayOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.InputStream;%0A%0Aimport javax.xml.stream.XMLStreamException;%0Aimport javax.xml.stream.XMLStreamWriter;%0A%0A
 impo
@@ -86,16 +86,16 @@
 Client;%0A
+
 import o
@@ -184,24 +184,72 @@
 ttpVersion;%0A
+import org.apache.commons.httpclient.HttpState;%0A
 import org.a
@@ -771,16 +771,196 @@
 Utils;%0A%0A
+import javax.xml.stream.XMLStreamException;%0Aimport javax.xml.stream.XMLStreamWriter;%0Aimport java.io.ByteArrayOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.InputStream;%0A%0A
 /**%0A * S
@@ -1174,16 +1174,85 @@
 ender%0A%7B%0A
+    private static final ThreadLocal httpState = new ThreadLocal();%0A%0A
     priv
@@ -2956,16 +2956,22 @@
 eMethod(
+null, 
 postMeth
@@ -2972,17 +2972,275 @@
 stMethod
-)
+, getHttpState() );%0A    %7D%0A%0A    private HttpState getHttpState()%0A    %7B%0A        HttpState state = (HttpState)httpState.get();%0A%0A        if( null == state ) %7B%0A            state = new HttpState();%0A            httpState.set( state );%0A        %7D%0A%0A        return state
 ;%0A    %7D%0A
@@ -3692,28 +3692,16 @@
 lose();%0A
-            
 %0A       

store cookies on a per-thread basis