package org.jboss.axis.transport.http;
import org.jboss.axis.AxisFault;
import org.jboss.axis.Message;
import org.jboss.axis.MessageContext;
import org.jboss.axis.MessagePart;
import org.jboss.axis.components.net.BooleanHolder;
import org.jboss.axis.components.net.SocketFactory;
import org.jboss.axis.components.net.SocketFactoryFactory;
import org.jboss.axis.encoding.Base64;
import org.jboss.axis.handlers.BasicHandler;
import org.jboss.axis.soap.SOAP12Constants;
import org.jboss.axis.soap.SOAPConstants;
import org.jboss.axis.utils.Messages;
import org.jboss.logging.Logger;
import javax.xml.soap.SOAPException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.util.Hashtable;
public class HTTPSender extends BasicHandler
{
private static Logger log = Logger.getLogger(HTTPSender.class.getName());
public void invoke(MessageContext msgContext) throws AxisFault
{
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage("enter00", "HTTPSender::invoke"));
}
try
{
BooleanHolder useFullURL = new BooleanHolder(false);
StringBuffer otherHeaders = new StringBuffer();
URL targetURL = new URL(msgContext.getStrProp(MessageContext.TRANS_URL));
String host = targetURL.getHost();
int port = targetURL.getPort();
Socket sock = null;
log.debug("TargetURL: " + targetURL);
sock = getSocket(targetURL.getProtocol(), host, port, otherHeaders, useFullURL);
if (msgContext.getTimeout() != 0)
{
sock.setSoTimeout(msgContext.getTimeout());
}
InputStream inp = writeToSocket(sock, msgContext, targetURL, otherHeaders, host, port, useFullURL);
Hashtable headers = new Hashtable();
inp = readHeadersFromSocket(sock, msgContext, inp, headers);
readFromSocket(sock, msgContext, inp, headers);
}
catch (Exception e)
{
log.debug(e.getMessage(), e);
throw AxisFault.makeFault(e);
}
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage("exit00",
"HTTPDispatchHandler::invoke"));
}
}
private Socket getSocket(String protocol,
String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL)
throws Exception
{
SocketFactory factory = SocketFactoryFactory.getFactory(protocol, getOptions());
return factory.create(host, port, otherHeaders, useFullURL);
}
private InputStream writeToSocket(Socket sock, MessageContext msgContext, URL tmpURL,
StringBuffer otherHeaders, String host, int port,
BooleanHolder useFullURL)
throws IOException
{
String userID = null;
String passwd = null;
userID = msgContext.getUsername();
passwd = msgContext.getPassword();
String action = msgContext.useSOAPAction()
? msgContext.getSOAPActionURI()
: "";
if (action == null)
{
action = "";
}
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();
tmpBuf.append(userID).append(":").append((passwd == null)
? ""
: passwd);
otherHeaders.append(HTTPConstants.HEADER_AUTHORIZATION)
.append(": Basic ")
.append(Base64.encode(tmpBuf.toString().getBytes()))
.append("\r\n");
}
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 header = new StringBuffer();
String webMethod = null;
boolean posting = true;
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((((tmpURL.getFile() == null)
|| tmpURL.getFile().equals(""))
? "/"
: tmpURL.getFile()));
}
Message requestMsg = msgContext.getRequestMessage();
boolean http10 = true; boolean httpChunkStream = false; boolean httpContinueExpected = false; 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;
}
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_HOST))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_CONTENT_TYPE))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_SOAP_ACTION))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_CONTENT_LENGTH))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_COOKIE))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_COOKIE2))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_AUTHORIZATION))
{
}
else if (key.equalsIgnoreCase(HTTPConstants.HEADER_PROXY_AUTHORIZATION))
{
}
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;
}
}
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)
httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
header.append(" ");
header.append(http10 ? HTTPConstants.HEADER_PROTOCOL_10 :
HTTPConstants.HEADER_PROTOCOL_11)
.append("\r\n");
if (posting)
{
header.append(HTTPConstants.HEADER_CONTENT_TYPE)
.append(": ")
.append(requestMsg.getContentType(msgContext.getSOAPConstants()))
.append("\r\n");
}
header.append(HTTPConstants.HEADER_ACCEPT) .append(": ")
.append(HTTPConstants.HEADER_ACCEPT_APPL_SOAP)
.append(", ")
.append(HTTPConstants.HEADER_ACCEPT_APPLICATION_DIME)
.append(", ")
.append(HTTPConstants.HEADER_ACCEPT_MULTIPART_RELATED)
.append(", ")
.append(HTTPConstants.HEADER_ACCEPT_TEXT_ALL)
.append("\r\n")
.append(HTTPConstants.HEADER_USER_AGENT) .append(": ")
.append(Messages.getMessage("axisUserAgent"))
.append("\r\n")
.append(HTTPConstants.HEADER_HOST) .append(": ")
.append(host)
.append((port == -1) ? ("") : (":" + port))
.append("\r\n")
.append(HTTPConstants.HEADER_CACHE_CONTROL) .append(": ")
.append(HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE)
.append("\r\n")
.append(HTTPConstants.HEADER_PRAGMA)
.append(": ")
.append(HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE)
.append("\r\n")
.append(HTTPConstants.HEADER_SOAP_ACTION) .append(": \"")
.append(action)
.append("\"\r\n");
if (posting)
{
if (!httpChunkStream)
{
header.append(HTTPConstants.HEADER_CONTENT_LENGTH)
.append(": ")
.append(requestMsg.getContentLength())
.append("\r\n");
}
else
{
header.append(HTTPConstants.HEADER_TRANSFER_ENCODING)
.append(": ")
.append(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED)
.append("\r\n");
}
}
if (null != httpConnection)
{
header.append(HTTPConstants.HEADER_CONNECTION);
header.append(": ");
header.append(httpConnection);
header.append("\r\n");
}
if (null != otherHeaders)
{
header.append(otherHeaders.toString());
}
header.append("\r\n");
OutputStream out = sock.getOutputStream();
if (!posting)
{
out.write(header.toString()
.getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
out.flush();
return null;
}
InputStream inp = null;
if (httpChunkStream)
{
out.write(header.toString()
.getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
}
if (httpContinueExpected)
{
out.flush();
Hashtable cheaders = new Hashtable();
inp = readHeadersFromSocket(sock, 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)
{
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
}
else
{
String statusMessage = (String)
msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);
fault.setFaultDetailString(Messages.getMessage("return01",
"" + returnCode, ""));
throw fault;
}
}
try
{
if (httpChunkStream == false)
{
out = new BufferedOutputStream(out, 8 * 1024);
out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
requestMsg.writeTo(out);
out.flush();
}
else
{
ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(out);
out = new BufferedOutputStream(chunkedOutputStream, 8 * 1024);
requestMsg.writeTo(out);
out.flush();
chunkedOutputStream.eos();
}
}
catch (SOAPException e)
{
log.debug("Cannot serialize request message", e);
}
if (log.isDebugEnabled())
{
log.debug("XML request sent");
log.debug("----------------------------------------------");
MessagePart msgPart = (MessagePart)requestMsg.getSOAPPart();
String xmlMessage = msgPart.getAsString();
log.debug("----------------------------------------------");
log.debug(xmlMessage);
log.debug("----------------------------------------------");
}
return inp;
}
private InputStream readHeadersFromSocket(Socket sock, MessageContext msgContext, InputStream inp, Hashtable headers)
throws IOException
{
byte b = 0;
int len = 0;
int colonIndex = -1;
String name, value;
int returnCode = 0;
if (null == inp) inp = new BufferedInputStream(sock.getInputStream());
if (headers == null)
headers = new Hashtable();
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
{ if (len == 0)
{
break;
}
b = (byte)inp.read();
readTooMuch = true;
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)
{
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;
}
private void readFromSocket(Socket sock,
MessageContext msgContext,
InputStream inp,
Hashtable headers)
throws IOException
{
Message responseMsg = null;
byte b;
Integer rc = (Integer)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
int returnCode = 0;
if (rc != null)
{
returnCode = rc.intValue();
}
else
{
}
String contentType =
(String)headers
.get(HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase());
contentType = (null == contentType)
? null
: contentType.trim();
if ((returnCode > 199) && (returnCode < 300))
{
}
else if (msgContext.getSOAPConstants() ==
SOAPConstants.SOAP12_CONSTANTS)
{
}
else if ((contentType != null) && !contentType.startsWith("text/html")
&& ((returnCode > 499) && (returnCode < 600)))
{
}
else
{
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",
"" + returnCode, buf.toString()));
throw fault;
}
String contentLocation =
(String)headers
.get(HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase());
contentLocation = (null == contentLocation)
? null
: contentLocation.trim();
String contentLength =
(String)headers
.get(HTTPConstants.HEADER_CONTENT_LENGTH.toLowerCase());
contentLength = (null == contentLength)
? null
: contentLength.trim();
String transferEncoding =
(String)headers
.get(HTTPConstants.HEADER_TRANSFER_ENCODING.toLowerCase());
if (null != transferEncoding
&& transferEncoding.trim()
.equals(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
{
inp = new ChunkedInputStream(inp);
}
InputStream inputStream = new SocketInputStream(inp, sock);
responseMsg = new Message(inputStream, false, contentType, contentLocation);
responseMsg.setMessageType(Message.RESPONSE);
msgContext.setResponseMessage(responseMsg);
if (msgContext.getMaintainSession())
{
handleCookie(HTTPConstants.HEADER_COOKIE,
HTTPConstants.HEADER_SET_COOKIE, headers, msgContext);
handleCookie(HTTPConstants.HEADER_COOKIE2,
HTTPConstants.HEADER_SET_COOKIE2, headers, msgContext);
}
if (log.isDebugEnabled())
{
log.debug("XML response received");
log.debug("----------------------------------------------");
MessagePart msgPart = (MessagePart)responseMsg.getSOAPPart();
String xmlMessage = new String(msgPart.getAsBytes());
log.debug("----------------------------------------------");
log.debug(xmlMessage);
log.debug("----------------------------------------------");
}
}
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();
int index = cookie.indexOf(';');
if (index != -1)
{
cookie = cookie.substring(0, index);
}
msgContext.setProperty(cookieName, cookie);
}
}
}