package org.jboss.axis.transport.http;
import org.jboss.axis.AxisFault;
import org.jboss.axis.Constants;
import org.jboss.axis.Message;
import org.jboss.axis.MessageContext;
import org.jboss.axis.description.OperationDesc;
import org.jboss.axis.description.ServiceDesc;
import org.jboss.axis.encoding.Base64;
import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
import org.jboss.axis.message.SOAPFaultImpl;
import org.jboss.axis.server.AxisServer;
import org.jboss.axis.utils.Messages;
import org.jboss.axis.utils.XMLUtils;
import org.jboss.logging.Logger;
import org.w3c.dom.Document;
import javax.xml.namespace.QName;
import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
public class SimpleAxisWorker implements Runnable
{
private static Logger log = Logger.getLogger(SimpleAxisWorker.class.getName());
private SimpleAxisServer server;
private Socket socket;
private static String transportName = "SimpleHTTP";
private static byte OK[] = ("200 " + Messages.getMessage("ok00")).getBytes();
private static byte UNAUTH[] = ("401 " + Messages.getMessage("unauth00")).getBytes();
private static byte SENDER[] = "400".getBytes();
private static byte ISE[] = ("500 " + Messages.getMessage("internalError01")).getBytes();
private static byte HTTP[] = "HTTP/1.0 ".getBytes();
private static byte XML_MIME_STUFF[] =
("\r\nContent-Type: text/xml; charset=utf-8\r\n" +
"Content-Length: ").getBytes();
private static byte HTML_MIME_STUFF[] =
("\r\nContent-Type: text/html; charset=utf-8\r\n" +
"Content-Length: ").getBytes();
private static byte SEPARATOR[] = "\r\n\r\n".getBytes();
private static final byte[] toLower = new byte[256];
static
{
for (int i = 0; i < 256; i++)
{
toLower[i] = (byte)i;
}
for (int lc = 'a'; lc <= 'z'; lc++)
{
toLower[lc + 'A' - 'a'] = (byte)lc;
}
}
private static final int BUFSIZ = 4096;
private static final byte lenHeader[] = "content-length: ".getBytes();
private static final int lenLen = lenHeader.length;
private static final byte typeHeader[] = (HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase() + ": ").getBytes();
private static final int typeLen = typeHeader.length;
private static final byte locationHeader[] = (HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase() + ": ").getBytes();
private static final int locationLen = locationHeader.length;
private static final byte actionHeader[] = "soapaction: ".getBytes();
private static final int actionLen = actionHeader.length;
private static final byte cookieHeader[] = "cookie: ".getBytes();
private static final int cookieLen = cookieHeader.length;
private static final byte cookie2Header[] = "cookie2: ".getBytes();
private static final int cookie2Len = cookie2Header.length;
private static final byte authHeader[] = "authorization: ".getBytes();
private static final int authLen = authHeader.length;
private static final byte getHeader[] = "GET".getBytes();
private static final byte postHeader[] = "POST".getBytes();
private static final byte headerEnder[] = ": ".getBytes();
private static final byte basicAuth[] = "basic ".getBytes();
public SimpleAxisWorker(SimpleAxisServer server, Socket socket)
{
this.server = server;
this.socket = socket;
}
public void run()
{
byte buf[] = new byte[BUFSIZ];
AxisServer engine = server.getAxisServer();
MessageContext msgContext = new MessageContext(engine);
Message requestMsg = null;
NonBlockingBufferedInputStream is =
new NonBlockingBufferedInputStream();
StringBuffer soapAction = new StringBuffer();
StringBuffer httpRequest = new StringBuffer();
StringBuffer fileName = new StringBuffer();
StringBuffer cookie = new StringBuffer();
StringBuffer cookie2 = new StringBuffer();
StringBuffer authInfo = new StringBuffer();
StringBuffer contentType = new StringBuffer();
StringBuffer contentLocation = new StringBuffer();
Message responseMsg = null;
msgContext.setTransportName(transportName);
responseMsg = null;
try
{
byte[] status = OK;
boolean doWsdl = false;
String cooky = null;
String methodName = null;
try
{
if (server.isSessionUsed())
{
cookie.delete(0, cookie.length());
cookie2.delete(0, cookie2.length());
}
authInfo.delete(0, authInfo.length());
is.setInputStream(socket.getInputStream());
int contentLength = parseHeaders(is, buf, contentType,
contentLocation, soapAction,
httpRequest, fileName,
cookie, cookie2, authInfo);
is.setContentLength(contentLength);
int paramIdx = fileName.toString().indexOf('?');
if (paramIdx != -1)
{
String params = fileName.substring(paramIdx + 1);
fileName.setLength(paramIdx);
log.debug(Messages.getMessage("filename00",
fileName.toString()));
log.debug(Messages.getMessage("params00",
params));
if ("wsdl".equalsIgnoreCase(params))
doWsdl = true;
if (params.startsWith("method="))
{
methodName = params.substring(7);
}
}
msgContext.setProperty(Constants.MC_REALPATH,
fileName.toString());
msgContext.setProperty(Constants.MC_RELATIVE_PATH,
fileName.toString());
msgContext.setProperty(Constants.MC_JWS_CLASSDIR,
"jwsClasses");
String url = "http://" + getLocalHost() + ":" +
server.getServerSocket().getLocalPort() + "/" +
fileName.toString();
msgContext.setProperty(MessageContext.TRANS_URL, url);
String filePart = fileName.toString();
if (filePart.startsWith("axis/services/"))
{
msgContext.setTargetService(filePart.substring(14));
}
if (authInfo.length() > 0)
{
byte[] decoded = Base64.decode(authInfo.toString());
StringBuffer userBuf = new StringBuffer();
StringBuffer pwBuf = new StringBuffer();
StringBuffer authBuf = userBuf;
for (int i = 0; i < decoded.length; i++)
{
if ((char)(decoded[i] & 0x7f) == ':')
{
authBuf = pwBuf;
continue;
}
authBuf.append((char)(decoded[i] & 0x7f));
}
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage("user00",
userBuf.toString()));
}
msgContext.setUsername(userBuf.toString());
msgContext.setPassword(pwBuf.toString());
}
if (httpRequest.toString().equals("GET"))
{
OutputStream out = socket.getOutputStream();
out.write(HTTP);
out.write(status);
if (methodName != null)
{
String body =
"<" + methodName + ">" +
"</" + methodName + ">";
String msgtxt =
"<SOAP-ENV:Envelope" +
" xmlns:SOAP-ENV=\"" + Constants.URI_SOAP12_ENV + "\">" +
"<SOAP-ENV:Body>" + body + "</SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
ByteArrayInputStream istream =
new ByteArrayInputStream(msgtxt.getBytes());
requestMsg = new Message(istream);
}
else if (doWsdl)
{
engine.generateWSDL(msgContext);
Document doc = (Document)msgContext.getProperty("WSDL");
if (doc != null)
{
String response = XMLUtils.DocumentToString(doc);
byte[] respBytes = response.getBytes();
out.write(XML_MIME_STUFF);
putInt(buf, out, respBytes.length);
out.write(SEPARATOR);
out.write(respBytes);
out.flush();
return;
}
}
else
{
StringBuffer sb = new StringBuffer();
sb.append("<h2>And now... Some Services</h2>\n");
Iterator i = engine.getConfig().getDeployedServices();
out.write("<ul>\n".getBytes());
while (i.hasNext())
{
ServiceDesc sd = (ServiceDesc)i.next();
sb.append("<li>\n");
sb.append(sd.getName());
sb.append(" <a href=\"../services/");
sb.append(sd.getName());
sb.append("?wsdl\"><i>(wsdl)</i></a></li>\n");
ArrayList operations = sd.getOperations();
if (!operations.isEmpty())
{
sb.append("<ul>\n");
for (Iterator it = operations.iterator(); it.hasNext();)
{
OperationDesc desc = (OperationDesc)it.next();
sb.append("<li>" + desc.getName());
}
sb.append("</ul>\n");
}
}
sb.append("</ul>\n");
byte[] bytes = sb.toString().getBytes();
out.write(HTML_MIME_STUFF);
putInt(buf, out, bytes.length);
out.write(SEPARATOR);
out.write(bytes);
out.flush();
return;
}
}
else
{
String soapActionString = soapAction.toString();
if (soapActionString != null)
{
msgContext.setUseSOAPAction(true);
msgContext.setSOAPActionURI(soapActionString);
}
requestMsg = new Message(is,
false,
contentType.toString(),
contentLocation.toString());
}
msgContext.setRequestMessage(requestMsg);
if (server.isSessionUsed())
{
if (cookie.length() > 0)
{
cooky = cookie.toString().trim();
}
else if (cookie2.length() > 0)
{
cooky = cookie2.toString().trim();
}
if (cooky == null)
{
int i = server.sessionIndex++;
cooky = "" + i;
}
msgContext.setSession(server.createSession(cooky));
}
engine.invoke(msgContext);
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null)
{
throw new AxisFault(Messages.getMessage("nullResponse00"));
}
}
catch (Exception e)
{
AxisFault af;
if (e instanceof AxisFault)
{
af = (AxisFault)e;
log.debug(Messages.getMessage("serverFault00"), af);
QName faultCode = af.getFaultCode();
if (Constants.FAULT_SOAP12_SENDER.equals(faultCode))
{
status = SENDER;
}
else if ("Server.Unauthorized".equals(af.getFaultCode().getLocalPart()))
{
status = UNAUTH; }
else
{
status = ISE; }
}
else
{
status = ISE; af = AxisFault.makeFault(e);
}
responseMsg = msgContext.getResponseMessage();
if (responseMsg == null)
{
responseMsg = new Message(af);
responseMsg.setMessageContext(msgContext);
}
else
{
try
{
SOAPEnvelopeAxisImpl env = responseMsg.getSOAPEnvelope();
env.clearBody();
env.addBodyElement(new SOAPFaultImpl((AxisFault)e));
}
catch (AxisFault fault)
{
}
}
}
OutputStream out = socket.getOutputStream();
out.write(HTTP);
out.write(status);
out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_TYPE + ": " + responseMsg.getContentType(msgContext.getSOAPConstants())).getBytes());
if (server.isSessionUsed() && null != cooky && 0 != cooky.trim().length())
{
StringBuffer cookieOut = new StringBuffer();
cookieOut.append("\r\nSet-Cookie: ")
.append(cooky)
.append("\r\nSet-Cookie2: ")
.append(cooky);
out.write(cookieOut.toString().getBytes());
}
out.write(SEPARATOR);
responseMsg.writeTo(out);
out.flush();
}
catch (Exception e)
{
log.debug(Messages.getMessage("exception00"), e);
}
finally
{
try
{
if (socket != null) socket.close();
}
catch (Exception e)
{
}
}
if (msgContext.getProperty(msgContext.QUIT_REQUESTED) != null)
{
try
{
server.stop();
}
catch (Exception e)
{
}
}
}
protected void invokeMethodFromGet(String methodName, String args) throws Exception
{
}
private int parseHeaders(NonBlockingBufferedInputStream is,
byte buf[],
StringBuffer contentType,
StringBuffer contentLocation,
StringBuffer soapAction,
StringBuffer httpRequest,
StringBuffer fileName,
StringBuffer cookie,
StringBuffer cookie2,
StringBuffer authInfo)
throws java.io.IOException
{
int n;
int len = 0;
n = this.readLine(is, buf, 0, buf.length);
if (n < 0)
{
throw new java.io.IOException(Messages.getMessage("unexpectedEOS00"));
}
httpRequest.delete(0, httpRequest.length());
fileName.delete(0, fileName.length());
contentType.delete(0, contentType.length());
contentLocation.delete(0, contentLocation.length());
if (buf[0] == getHeader[0])
{
httpRequest.append("GET");
for (int i = 0; i < n - 5; i++)
{
char c = (char)(buf[i + 5] & 0x7f);
if (c == ' ')
break;
fileName.append(c);
}
log.debug(Messages.getMessage("filename01", "SimpleAxisServer", fileName.toString()));
return 0;
}
else if (buf[0] == postHeader[0])
{
httpRequest.append("POST");
for (int i = 0; i < n - 6; i++)
{
char c = (char)(buf[i + 6] & 0x7f);
if (c == ' ')
break;
fileName.append(c);
}
log.debug(Messages.getMessage("filename01", "SimpleAxisServer", fileName.toString()));
}
else
{
throw new java.io.IOException(Messages.getMessage("badRequest00"));
}
while ((n = readLine(is, buf, 0, buf.length)) > 0)
{
if ((n <= 2) && (buf[0] == '\n' || buf[0] == '\r') && (len > 0)) break;
int endHeaderIndex = 0;
while (endHeaderIndex < n && toLower[buf[endHeaderIndex]] != headerEnder[0])
{
endHeaderIndex++;
}
endHeaderIndex += 2;
int i = endHeaderIndex - 1;
if (endHeaderIndex == lenLen && matches(buf, lenHeader))
{
while ((++i < n) && (buf[i] >= '0') && (buf[i] <= '9'))
{
len = (len * 10) + (buf[i] - '0');
}
}
else if (endHeaderIndex == actionLen
&& matches(buf, actionHeader))
{
soapAction.delete(0, soapAction.length());
i++;
while ((++i < n) && (buf[i] != '"'))
{
soapAction.append((char)(buf[i] & 0x7f));
}
}
else if (server.isSessionUsed() && endHeaderIndex == cookieLen
&& matches(buf, cookieHeader))
{
while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] != '\n'))
{
cookie.append((char)(buf[i] & 0x7f));
}
}
else if (server.isSessionUsed() && endHeaderIndex == cookie2Len
&& matches(buf, cookie2Header))
{
while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] != '\n'))
{
cookie2.append((char)(buf[i] & 0x7f));
}
}
else if (endHeaderIndex == authLen && matches(buf, authHeader))
{
if (matches(buf, endHeaderIndex, basicAuth))
{
i += basicAuth.length;
while (++i < n && (buf[i] != '\r') && (buf[i] != '\n'))
{
if (buf[i] == ' ') continue;
authInfo.append((char)(buf[i] & 0x7f));
}
}
else
{
throw new java.io.IOException(Messages.getMessage("badAuth00"));
}
}
else if (endHeaderIndex == locationLen && matches(buf, locationHeader))
{
while (++i < n && (buf[i] != '\r') && (buf[i] != '\n'))
{
if (buf[i] == ' ') continue;
contentLocation.append((char)(buf[i] & 0x7f));
}
}
else if (endHeaderIndex == typeLen && matches(buf, typeHeader))
{
while (++i < n && (buf[i] != '\r') && (buf[i] != '\n'))
{
if (buf[i] == ' ') continue;
contentType.append((char)(buf[i] & 0x7f));
}
}
}
return len;
}
public boolean matches(byte[] buf, byte[] target)
{
for (int i = 0; i < target.length; i++)
{
if (toLower[buf[i]] != target[i])
{
return false;
}
}
return true;
}
public boolean matches(byte[] buf, int bufIdx, byte[] target)
{
for (int i = 0; i < target.length; i++)
{
if (toLower[buf[bufIdx + i]] != target[i])
{
return false;
}
}
return true;
}
private void putInt(byte buf[], OutputStream out, int value)
throws java.io.IOException
{
int len = 0;
int offset = buf.length;
if (value < 0)
{
buf[--offset] = (byte)'-';
value = -value;
len++;
}
if (value == 0)
{
buf[--offset] = (byte)'0';
len++;
}
while (value > 0)
{
buf[--offset] = (byte)(value % 10 + '0');
value = value / 10;
len++;
}
out.write(buf, offset, len);
}
private int readLine(NonBlockingBufferedInputStream is, byte[] b, int off, int len)
throws java.io.IOException
{
int count = 0, c;
while ((c = is.read()) != -1)
{
if (c != '\n' && c != '\r')
{
b[off++] = (byte)c;
count++;
}
if (count == len) break;
if ('\n' == c)
{
int peek = is.peek(); if (peek != ' ' && peek != '\t') break;
}
}
return count > 0 ? count : -1;
}
public static String getLocalHost()
{
try
{
return InetAddress.getLocalHost().getHostAddress();
}
catch (UnknownHostException uhe)
{
return "localhost";
}
}
}