package org.jfox.mx.http;
import java.io.IOException;
import java.io.DataOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.net.Socket;
import java.util.Properties;
import java.util.StringTokenizer;
import org.jfox.mx.MxServer;
public class WebServer implements Runnable {
private int port = 8082;
private int backlog = 50;
private ServerSocket ssocket = null;
private final ThreadPool threadPool = new ThreadPool();
private MxServer server = null;
void setMxServer(MxServer server){
this.server = server;
}
public void setPort(int p) {
port = p;
}
public int getPort() {
return port;
}
public String getBindAddress() {
String host = "localhost";
try {
host = InetAddress.getLocalHost().getHostAddress();
}
catch(UnknownHostException e){ }
return host;
}
public int getBacklog() {
return backlog;
}
public void setBacklog(int backlog) {
if( backlog <= 0 )
backlog = 50;
this.backlog = backlog;
}
public void start() throws IOException {
threadPool.enable();
try {
ssocket = new ServerSocket(port, backlog);
Logger.log("started at " + port + " !");
listen();
}
catch (IOException e) {
throw e;
}
}
public void stop() {
try {
ServerSocket srv = ssocket;
ssocket = null;
srv.close();
Logger.log("stopped !");
}
catch (Exception e) {
e.printStackTrace();
}
threadPool.disable();
}
public void run() {
if (ssocket == null)
return;
Socket socket = null;
try {
socket = ssocket.accept();
}
catch(Exception e) {
return;
}
listen();
try {
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
try {
String httpCode = "200 OK";
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Properties queryMap = parseQueryString(getPath(in));
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String className = queryMap.containsKey("action") ? queryMap.getProperty("action") + "Command" : "AgentCommand";
String commClassName = this.getClass().getPackage().getName() + "." + className;
String page = ((Command)loader.loadClass(commClassName).newInstance()).doGet(server, queryMap);
try {
out.writeBytes("HTTP/1.0 "+httpCode+"\r\n");
out.writeBytes("Content-Length: " + page.length() + "\r\n");
out.writeBytes("Content-Type: text/html");
out.writeBytes("\r\n\r\n");
out.write(page.toString().getBytes());
out.flush();
}
catch (IOException ie) {
return;
}
}
catch(Throwable e) {
e.printStackTrace();
try {
out.writeBytes("HTTP/1.0 400 " + e.getMessage() + "\r\n");
out.writeBytes("Content-Type: text/html\r\n\r\n");
out.flush();
}
catch (IOException ex) {
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
try {
socket.close();
}
catch (IOException e) {
}
}
}
private void listen() {
threadPool.run(this);
}
private String getPath(BufferedReader in) throws IOException {
String line = in.readLine();
int start = line.indexOf(' ')+1;
int end = line.indexOf(' ', start+1);
String filePath = line.substring(start+1, end);
return decodeUrl(filePath);
}
private String decodeUrl(String encodeURL) {
int length = encodeURL.length();
char[] charArray = encodeURL.toCharArray();
byte[] byteArray = new byte[length];
int j = 0;
boolean flag = true;
for(int k = 0; k < length; k++) {
char c = charArray[k];
if(c < 0 || c > '\177')
throw new IllegalArgumentException("Not encoded");
byte byte0 = (byte)(0x7f & c);
if(c == '+') {
flag = false;
byte0 = 32;
}
else
if(c == '%' && k + 2 < length) {
flag = false;
byte0 = (byte)(0xff & Integer.parseInt(encodeURL.substring(k + 1, k + 3), 16));
k += 2;
}
byteArray[j++] = byte0;
}
if(flag)
return encodeURL;
try {
return new String(byteArray, 0, j, "ISO-8859-1");
}
catch(UnsupportedEncodingException unsupportedencodingexception) {
return new String(byteArray, 0, j);
}
}
private Properties parseQueryString(String qstring){
Properties prop = new Properties();
if(qstring == null || qstring.trim().length() == 0) return prop;
if(qstring.startsWith("?")) qstring = qstring.substring(1);
StringTokenizer st = new StringTokenizer(qstring,"&");
while(st.hasMoreTokens()){
String nvPair = st.nextToken();
int index = nvPair.indexOf("=");
if(index < 0){ prop.setProperty(nvPair,"");
}
else{
String name = nvPair.substring(0,index);
String value = nvPair.substring(index+1);
prop.setProperty(name,value);
}
}
return prop;
}
public static void main(String[] args) throws Exception {
new WebServer().start();
}
}