HTTP Server Framework Updates

thobaben_serialize
Harald Wolff 2014-08-24 13:07:11 +02:00
parent a623c22f2e
commit 0fa6e912da
11 changed files with 588 additions and 56 deletions

View File

@ -2,6 +2,7 @@ package org.hwo.net;
import java.io.IOException;
import org.hwo.net.http.HttpException;
import org.hwo.net.serverobjects.ServerObjectRequest;
public interface ServerObject {
@ -13,7 +14,7 @@ public interface ServerObject {
public void addNamedChild(String childName,ServerObject serverObject);
public void climb(ServerObjectRequest request) throws IOException;
public void request(ServerObjectRequest request) throws IOException;
public void climb(ServerObjectRequest request) throws IOException, HttpException;
public void request(ServerObjectRequest request) throws IOException, HttpException;
}

View File

@ -0,0 +1,116 @@
package org.hwo.net.http;
import java.io.IOException;
import java.util.LinkedList;
import org.hwo.ByteArrayHexlifier;
public class HttpCookie {
private String name;
private String content;
private String path;
private Integer maxAge;
static public HttpCookie[] readCookies(HttpServerRequest request)
{
LinkedList<HttpCookie> cookies = new LinkedList<HttpCookie>();
String cookiesource = request.getRequestHeader("Cookie");
System.err.println("Cookie: "+cookiesource);
if (cookiesource == null)
return new HttpCookie[0];
for (String cookieav: cookiesource.split(";"))
{
int p = cookieav.indexOf('=');
if (p > 0)
{
String cn,cv;
cn = cookieav.substring(0,p);
cv = cookieav.substring(p+1);
HttpCookie hc = new HttpCookie();
hc.setName(cn);
hc.setContent(new String(ByteArrayHexlifier.stringToByteArray(cv)));
cookies.add(hc);
}
}
return cookies.toArray(new HttpCookie[0]);
}
public HttpCookie()
{
}
public void sendCookie(HttpServerRequest request)
{
String hexname,hexcontent;
StringBuilder cookievalue;
hexname = name; // ByteArrayHexlifier.byteArrayToString(name.getBytes());
hexcontent = ByteArrayHexlifier.byteArrayToString(getContent().getBytes());
cookievalue = new StringBuilder();
cookievalue.append(String.format("%s=%s;",hexname,hexcontent));
if (path != null)
{
cookievalue.append(String.format(" Path=\"%s\";",this.path));
}
if (maxAge != null)
{
cookievalue.append(String.format(" Max-Age=\"%d\";",this.maxAge));
}
try
{
request.connection.getBufferedWriter().write(String.format("Set-Cookie: %s", cookievalue.toString()));
request.connection.getBufferedWriter().newLine();
System.err.println(String.format("Set-Cookie: %s", cookievalue.toString()));
} catch (IOException io)
{
System.err.println("HttpCookie.sendCookie(): " + io.toString());
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getMaxAge() {
return maxAge;
}
public void setMaxAge(Integer maxAge) {
this.maxAge = maxAge;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}

View File

@ -0,0 +1,18 @@
package org.hwo.net.http;
public class HttpException extends Exception {
private int code;
public HttpException(int code)
{
this.code = code;
}
public Integer getCode()
{
return this.code;
}
}

View File

@ -6,7 +6,9 @@ import java.net.ServerSocket;
import java.net.Socket;
import org.hwo.net.requesthandler.ServerObjectHandler;
import org.hwo.net.serverobjects.DAVCollectionSO;
import org.hwo.net.serverobjects.VirtualRootObject;
import org.hwo.sessions.SessionManager;
public class HttpServer extends Thread {
@ -16,21 +18,25 @@ public class HttpServer extends Thread {
private HttpServerConnectionFactory connectionFactory;
private HttpServerRequestFactory requestFactory;
private HttpServerRequestHandler requestHandler;
private SessionManager sessionManager;
private SessionTracker sessionTracker;
public HttpServer(int port)
{
this.port = port;
this.connectionFactory = new HttpServerConnection.Factory();
this.requestFactory = new HttpServerRequest.Factory();
this.requestHandler = new HttpServerRequestHandler() {
@Override
public void doRequest(HttpServerRequest httpRequest) throws IOException{
httpRequest.setResponseHeader("Content-Type", "text/plain");
httpRequest.getResponseWriter().write("This Page has no other content than this text.");
}
};
this.sessionManager = new SessionManager();
this.sessionTracker = new SessionTracker();
}
public HttpServerConnectionFactory getConnectionFactory()
@ -83,8 +89,26 @@ public class HttpServer extends Thread {
HttpServer httpServer = new HttpServer(8080);
ServerObjectHandler soh = new ServerObjectHandler();
httpServer.setRequestHandler(soh);
DAVCollectionSO dav = new DAVCollectionSO();
soh.getRootObject().addNamedChild("dav", dav);
httpServer.setRequestHandler(soh);
httpServer.start();
}
public SessionManager getSessionManager() {
return sessionManager;
}
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
public SessionTracker getSessionTracker() {
return sessionTracker;
}
public void setSessionTracker(SessionTracker sessionTracker) {
this.sessionTracker = sessionTracker;
}
}

View File

@ -8,6 +8,8 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import org.hwo.io.StreamReader;
public class HttpServerConnection extends Thread {
public static class Factory implements HttpServerConnectionFactory
@ -22,14 +24,14 @@ public class HttpServerConnection extends Thread {
private HttpServer httpServer;
private Socket clientSocket;
private BufferedReader bufferedReader;
private StreamReader streamReader;
private BufferedWriter bufferedWriter;
public HttpServerConnection(HttpServer httpServer,Socket clientSocket) throws IOException
{
this.httpServer = httpServer;
this.clientSocket = clientSocket;
this.bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
this.streamReader = new StreamReader(clientSocket.getInputStream());
this.bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
}
@ -43,9 +45,9 @@ public class HttpServerConnection extends Thread {
return clientSocket;
}
public BufferedReader getBufferedReader()
public StreamReader getStreamReader()
{
return bufferedReader;
return streamReader;
}
public BufferedWriter getBufferedWriter()

View File

@ -1,14 +1,26 @@
package org.hwo.net.http;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.hwo.sessions.Session;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class HttpServerRequest {
public static class Factory implements HttpServerRequestFactory
@ -26,11 +38,18 @@ public class HttpServerRequest {
String requestProtocol;
HttpRequestURI
requestURI;
MessageHeaders
requestHeaders;
Hashtable<String,HttpCookie>
requestCookies;
Properties header;
byte[] requestContent;
Document
xmlRequest;
Integer resultCode;
Properties responseHeader;
private Integer resultCode;
MessageHeaders
responseHeaders;
byte[] responseBody;
ByteArrayOutputStream
@ -40,11 +59,18 @@ public class HttpServerRequest {
boolean responseSent;
Session session;
List<HttpCookie> responseCookies;
public HttpServerRequest(HttpServerConnection httpServerConnection) throws IOException
{
this.connection = httpServerConnection;
this.header = new Properties();
this.requestHeaders = new MessageHeaders();
this.requestCookies = new Hashtable<String, HttpCookie>();
this.responseCookies = new ArrayList<HttpCookie>();
readRequest();
readHeader();
@ -52,10 +78,81 @@ public class HttpServerRequest {
requestURI.decode();
resultCode = 400;
responseHeader = new Properties();
responseHeaders = new MessageHeaders();
responseOutputStream = new ByteArrayOutputStream();
responseBufferedWriter = new BufferedWriter(new OutputStreamWriter(responseOutputStream));
readCookies();
attachSession();
readContent();
if ((getRequestHeader("Content-Type") != null) && getRequestHeader("Content-Type").equals("text/xml"))
readXML();
}
private void readCookies()
{
HttpCookie[] cookies = HttpCookie.readCookies(this);
for (HttpCookie c:cookies)
requestCookies.put(c.getName(), c);
}
private void attachSession()
{
SessionTracker tracker = connection.getHttpServer().getSessionTracker();
if (tracker != null)
{
String sid = tracker.retrieveSessionID(this);
if (sid != null)
session = connection.getHttpServer().getSessionManager().getSession(sid);
if (session == null)
{
session = connection.getHttpServer().getSessionManager().createSession();
connection.getHttpServer().getSessionTracker().implantSession(this,session);
}
}
}
private void readContent() throws IOException
{
String cl = getRequestHeader("Content-Length");
if (cl != null)
{
int len = Integer.decode(cl);
requestContent = new byte[ len ];
connection.getStreamReader().read(requestContent, 0, len);
}
}
private void readXML()
{
DocumentBuilder builder;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
builder = dbf.newDocumentBuilder();
this.xmlRequest = builder.parse(new ByteArrayInputStream(requestContent));
this.xmlRequest.normalize();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException ex)
{
ex.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Session getSession()
{
return session;
}
public boolean isResponseSent()
@ -65,7 +162,13 @@ public class HttpServerRequest {
private void readRequest() throws IOException
{
this.requestLine = connection.getBufferedReader().readLine();
do
{
this.requestLine = connection.getStreamReader().readLine();
if (this.requestLine == null)
throw new IOException("0byte read()");
} while (this.requestLine.length() == 0);
String[] tokens = this.requestLine.split(" ",3);
requestMethod = tokens[0];
if (tokens.length > 1)
@ -77,34 +180,7 @@ public class HttpServerRequest {
private void readHeader() throws IOException
{
String line;
String headerName = null;
StringBuilder headerValue = new StringBuilder();
while (true)
{
line = connection.getBufferedReader().readLine();
if ((line.length() == 0) || (line.charAt(0) > 32))
{
if (headerName != null)
{
header.setProperty(headerName, headerValue.toString());
}
if (line.length() > 0)
{
headerName = line.substring(0,line.indexOf(':'));
headerValue = new StringBuilder();
headerValue.append(line.substring(line.indexOf(':')+1).trim());
} else
return;
} else
{
if (headerName != null)
headerValue.append(line.trim());
}
}
requestHeaders.read(connection.getStreamReader());
}
public HttpRequestURI getRequestURI()
@ -114,9 +190,38 @@ public class HttpServerRequest {
public String getRequestHeader(String headerName)
{
return header.getProperty(headerName);
return requestHeaders.getHeaderValue(headerName);
}
public String getRequestMethod()
{
return requestMethod;
}
public byte[] getRequestContent()
{
return requestContent;
}
public Document getXMLRequest()
{
return this.xmlRequest;
}
public HttpCookie[] getRequestCookies()
{
return this.requestCookies.keySet().toArray(new HttpCookie[0]);
}
public HttpCookie getRequestCookie(String cookieName)
{
return requestCookies.get(cookieName);
}
public void addCookie(HttpCookie cookie)
{
responseCookies.add(cookie);
}
public OutputStream getResponseOutputStream()
{
@ -127,11 +232,20 @@ public class HttpServerRequest {
return responseBufferedWriter;
}
public void setResponseHeader(String headerName,String headerValue)
public MessageHeaders getRepsonseHeaders()
{
responseHeader.setProperty(headerName, headerValue);
return responseHeaders;
}
public void setResponseHeader(String headerName,String headerValue)
{
responseHeaders.setHeaderValue(headerName, headerValue);
}
public void addResponseHeader(String headerName,String headerValue)
{
responseHeaders.addHeaderValue(headerName, headerValue);
}
public void sendResponse(int code,byte[] responseBody) throws IOException
{
@ -151,9 +265,9 @@ public class HttpServerRequest {
{
if (responseSent)
throw new IOException("The Response has already been sent.");
responseSent = true;
if (responseBody == null)
{
responseBufferedWriter.flush();
@ -164,25 +278,34 @@ public class HttpServerRequest {
responseBody = new byte[0];
}
responseHeader.setProperty("Content-Length", String.format("%d", responseBody.length));
setResponseHeader("Content-Length", String.format("%d", responseBody.length));
String protocol = "HTTP/1.0";
if (requestProtocol != null)
protocol = requestProtocol;
connection.getBufferedWriter().write(String.format("%s %d\r\n", protocol, resultCode));
Enumeration<?> headerEnum = responseHeader.keys();
while (headerEnum.hasMoreElements())
for (String headerName: responseHeaders.getHeaderNames())
{
String headerName = (String)headerEnum.nextElement();
connection.getBufferedWriter().write(String.format("%s: %s\r\n", headerName, responseHeader.getProperty(headerName)));
String headerValue = responseHeaders.getHeaderValue(headerName);
connection.getBufferedWriter().write(String.format("%s: %s\r\n", headerName, headerValue));
}
for (HttpCookie cookie: responseCookies)
cookie.sendCookie(this);
connection.getBufferedWriter().write("\r\n");
connection.getBufferedWriter().flush();
connection.getClientSocket().getOutputStream().write(responseBody);
}
public Integer getResultCode() {
return resultCode;
}
public void setResultCode(Integer resultCode) {
this.resultCode = resultCode;
}
}

View File

@ -0,0 +1,107 @@
package org.hwo.net.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.hwo.StringHelper;
import org.hwo.io.StreamReader;
public class MessageHeaders {
private Hashtable<String, List<String>> headers;
public MessageHeaders()
{
headers = new Hashtable<String, List<String>>();
}
public void read(StreamReader reader) throws IOException
{
String line;
String headerName = null;
List<String> values = new ArrayList<String>();
while (true)
{
line = reader.readLine();
if ((line == null) || (line.length() == 0))
{
break;
} else if (line.charAt(0) <= 32)
{
String stripped = line.trim();
if (stripped.length() > 0)
{
values.add(stripped);
}
} else
{
int p = line.indexOf(':');
headerName = line.substring(0,p);
values = getHeaderValueList(headerName);
values.add(line.substring(p+1).trim());
}
}
}
private List<String> getHeaderValueList(String headerName)
{
List<String> values;
if (!headers.containsKey(headerName))
{
values = new ArrayList<String>();
headers.put(headerName, values);
System.err.println("New Header: " + headerName);
} else
{
values = headers.get(headerName);
System.err.println("Appending Header: " + headerName);
}
return values;
}
public void addHeader(String headerName,String headerValue)
{
}
public String getHeaderValue(String headerName)
{
String[] values = getHeaderValues(headerName);
if (values.length > 0)
return StringHelper.join(values, " ");
return null;
}
public String[] getHeaderValues(String headerName)
{
if (headers.containsKey(headerName))
{
return headers.get(headerName).toArray(new String[0]);
}
return new String[0];
}
public String[] getHeaderNames()
{
return headers.keySet().toArray(new String[0]);
}
public void setHeaderValue(String headerName,String headerValue)
{
List<String> values = new ArrayList<String>();
values.add(headerValue);
headers.put(headerName, values);
}
public void addHeaderValue(String headerName,String headerValue)
{
getHeaderValueList(headerName).add(headerValue);
}
}

View File

@ -0,0 +1,37 @@
package org.hwo.net.http;
import org.hwo.sessions.Session;
public class SessionTracker {
public SessionTracker()
{
}
public String retrieveSessionID(HttpServerRequest request)
{
HttpCookie sidcookie = request.getRequestCookie("hwo.sid");
if (sidcookie != null)
{
System.err.println("Session found: " + sidcookie.getContent());
return sidcookie.getContent();
}
return null;
}
public void implantSession(HttpServerRequest request,Session session)
{
HttpCookie cookie = new HttpCookie();
cookie.setName("hwo.sid");
cookie.setContent(session.getSessionID());
request.addCookie(cookie);
System.err.println("Session Implant: " + session.getSessionID());
}
}

View File

@ -3,9 +3,13 @@ package org.hwo.net.requesthandler;
import java.io.IOException;
import java.util.HashMap;
import javax.xml.ws.http.HTTPException;
import org.hwo.net.ServerObject;
import org.hwo.net.http.HttpException;
import org.hwo.net.http.HttpServerRequest;
import org.hwo.net.http.HttpServerRequestHandler;
import org.hwo.net.serverobjects.ServerObjectNotFoundException;
import org.hwo.net.serverobjects.ServerObjectRequest;
import org.hwo.net.serverobjects.VirtualRootObject;
@ -38,7 +42,19 @@ public class ServerObjectHandler implements HttpServerRequestHandler{
public void doRequest(HttpServerRequest httpRequest) throws IOException {
ServerObjectRequest sor = new ServerObjectRequest(httpRequest);
rootObject.climb(sor);
try
{
rootObject.climb(sor);
} catch (HttpException httpex)
{
try
{
getErrorObject(httpex.getCode()).request(sor);
} catch (Exception ex)
{
}
}
}

View File

@ -0,0 +1,36 @@
package org.hwo.sessions;
import java.util.Hashtable;
public class Session {
private String sessionID;
private Hashtable<String, Object> sessionVars;
public Session()
{
this.sessionID = null;
this.sessionVars = new Hashtable<String, Object>();
}
public Session(String sid)
{
this.sessionID = sid;
this.sessionVars = new Hashtable<String, Object>();
}
public String getSessionID()
{
return this.sessionID;
}
public Object getObject(String name)
{
return this.sessionVars.get(name);
}
public void setObject(String name,Object o)
{
this.sessionVars.put(name, o);
}
}

View File

@ -0,0 +1,52 @@
package org.hwo.sessions;
import java.util.Hashtable;
import java.util.UUID;
public class SessionManager {
private Hashtable<String, Session> loadedSessions;
private ThreadLocal<Session> threadSession;
public SessionManager()
{
loadedSessions = new Hashtable<String, Session>();
threadSession = new ThreadLocal<Session>();
}
synchronized private String createUniqueSessionID()
{
String sid;
do
{
UUID uuid = UUID.randomUUID();
sid = String.format("%s%s", Long.toHexString(uuid.getLeastSignificantBits()),Long.toHexString(uuid.getMostSignificantBits()));
} while (loadedSessions.containsKey(sid));
return sid;
}
synchronized public Session createSession()
{
Session s = new Session(createUniqueSessionID());
this.loadedSessions.put(s.getSessionID(), s);
return s;
}
public Session getDefaultSession()
{
return threadSession.get();
}
public Session getSession(String sid)
{
return this.loadedSessions.get(sid);
}
public void associateDefaultSession(Session s)
{
this.threadSession.set(s);
}
}