package org.mom4j.xcp.impl;
import java.net.Socket;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.mom4j.xcp.XcpConfig;
import org.mom4j.xcp.XcpServerFactory;
import org.mom4j.xcp.util.BlockingQueue;
import org.mom4j.xcp.util.HttpHeaders;
import org.mom4j.xcp.util.LimitedReader;
public class XcpWorker extends Thread {
/** logger */
private static Log log = LogFactory.getLog(XcpWorker.class);
public static final String WORKER = "XcpWorker#";
public static final String POST = "POST";
public static final String XCP = "/XCP";
public static final String CL = "Content-length";
private BlockingQueue requestQueue;
private List responseQueue;
private XcpConfig config;
private XMLReader parser;
XcpWorker(BlockingQueue q, int n, XcpConfig cfg, ThreadGroup tg) {
super(tg, WORKER + n);
this.requestQueue = q;
this.responseQueue = new LinkedList();
this.config = cfg;
this.parser = null;
this.setDaemon(true);
}
public void run() {
Socket s = null;
try {
SAXParserFactory f = SAXParserFactory.newInstance();
this.parser = f.newSAXParser().getXMLReader();
} catch(Exception ex) {
log.error("failed creating SAX parser", ex);
return;
}
while(true) {
s = (Socket)this.requestQueue.next();
try {
this.work(s);
} catch(IOException ioex) {
log.error("failed processing request", ioex);
log.error("skipping reqest");
} finally {
try { s.close(); } catch(Exception ex) {}
}
}
}
private void work(Socket s)
throws IOException
{
InputStream in = null;
OutputStream out = null;
try {
in = s.getInputStream();
int len = this.getContentLength(in);
XcpServerImpl xcpServer =
(XcpServerImpl)XcpServerFactory.getByPort(s.getLocalPort());
LimitedReader r = new LimitedReader(in, len, true);
xcpServer.receiveData(r, this.responseQueue, this.parser);
out = s.getOutputStream();
this.respond(out);
} catch(Exception ex) {
log.error("error reading request", ex);
try {
if(out == null)
out = s.getOutputStream();
this.writeErrMsg(out, ex.getMessage());
} catch(Exception exx) {
log.error("", exx);
}
} finally {
this.responseQueue.clear();
try { in.close(); } catch(Exception ex) {}
try { out.flush(); } catch(Exception ex) {}
try { out.close(); } catch(Exception ex) {}
}
}
private int getContentLength(InputStream in)
throws IOException
{
HttpHeaders headers = new HttpHeaders(in);
if(!headers.getCommand().equals(POST)) {
throw new IOException("Expected " + POST + "-Command");
}
if(!headers.getUri().equals(XCP)) {
throw new IOException("Expected uri " + XCP);
}
int length = 0;
String s = headers.getHeader(CL);
try {
length = Integer.parseInt(s);
} catch(Exception ex) {
throw new IOException("Failed reading content-length: '" + s + "'");
}
return length;
}
private void respond(OutputStream out)
throws IOException
{
PrintStream ps = null;
try {
ps = new PrintStream(out);
println(ps, "HTTP/1.0 200 OK");
println(ps, "Content-Type: text/html");
println(ps, "MIME-Version: 1.0");
println(ps, "Connection: close");
ps.println();
print(ps, "<?xml version=\"1.0\" ?>");
ps.flush();
if(this.responseQueue.size() < 1) {
print(ps, "<" + XcpDocumentHandler.PROTOCOL + ">");
print(ps, "OK");
print(ps, "</" + XcpDocumentHandler.PROTOCOL + ">");
} else {
Iterator it = this.responseQueue.iterator();
while(it.hasNext()) {
ByteArrayOutputStream b = (ByteArrayOutputStream)it.next();
b.writeTo(out);
}
}
} finally {
try { ps.close(); } catch(Exception ex) {}
}
}
private void writeErrMsg(OutputStream out, String msg) {
PrintStream ps = null;
try {
ps = new PrintStream(out);
// ps.println("HTTP/1.0 500 INTERNAL SERVER ERROR");
ps.println("HTTP/1.0 200 OK");
ps.println("Content-Type: text/plain");
ps.println("MIME-Version: 1.0");
ps.println("Connection: close");
ps.println();
ps.print("<?xml version=\"1.0\" ?>");
// ps.print("<" + XcpDocumentHandler.PROTOCOL + ">");
ps.print("<error>");
if(msg != null) {
ps.print(msg);
}
ps.print("</error>");
// ps.print("</" + XcpDocumentHandler.PROTOCOL + ">");
} finally {
try { ps.flush(); } catch(Exception ex) {}
try { ps.close(); } catch(Exception ex) {}
}
}
private void println(PrintStream ps, String str) {
if (log.isDebugEnabled()) log.debug(str);
ps.println(str);
}
private void print(PrintStream ps, String str) {
if (log.isDebugEnabled()) log.debug(str);
ps.print(str);
}
}