diff --git a/src/org/hwo/io/StreamReader.java b/src/org/hwo/io/StreamReader.java new file mode 100644 index 0000000..e0f3395 --- /dev/null +++ b/src/org/hwo/io/StreamReader.java @@ -0,0 +1,41 @@ +package org.hwo.io; + +import java.io.IOException; +import java.io.InputStream; + +public class StreamReader { + + private InputStream stream; + + public StreamReader(InputStream stream) + { + this.stream = stream; + } + + public int read(byte[] buffer,int offset,int len) throws IOException + { + return this.stream.read(buffer, offset, len); + } + + public String readLine() throws IOException + { + StringBuilder builder = new StringBuilder(); + while (true) + { + int ch = this.stream.read(); + + if ((ch == -1)||(ch == '\n')) + return builder.toString(); + + if (ch >= 32) + { + builder.append((char)ch); + } + } + } + + + + + +} diff --git a/src/org/hwo/net/ServerObject.java b/src/org/hwo/net/ServerObject.java index ea42708..ab8b1f1 100644 --- a/src/org/hwo/net/ServerObject.java +++ b/src/org/hwo/net/ServerObject.java @@ -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; } diff --git a/src/org/hwo/net/http/HttpCookie.java b/src/org/hwo/net/http/HttpCookie.java new file mode 100644 index 0000000..1aabc2d --- /dev/null +++ b/src/org/hwo/net/http/HttpCookie.java @@ -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 cookies = new LinkedList(); + + 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; + } + + +} diff --git a/src/org/hwo/net/http/HttpException.java b/src/org/hwo/net/http/HttpException.java new file mode 100644 index 0000000..07a465d --- /dev/null +++ b/src/org/hwo/net/http/HttpException.java @@ -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; + } + + +} diff --git a/src/org/hwo/net/http/HttpServer.java b/src/org/hwo/net/http/HttpServer.java index 729be88..8ceaff4 100644 --- a/src/org/hwo/net/http/HttpServer.java +++ b/src/org/hwo/net/http/HttpServer.java @@ -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; + } } diff --git a/src/org/hwo/net/http/HttpServerConnection.java b/src/org/hwo/net/http/HttpServerConnection.java index 386cb6b..2cf73dc 100644 --- a/src/org/hwo/net/http/HttpServerConnection.java +++ b/src/org/hwo/net/http/HttpServerConnection.java @@ -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() diff --git a/src/org/hwo/net/http/HttpServerRequest.java b/src/org/hwo/net/http/HttpServerRequest.java index 771eed5..2acf147 100644 --- a/src/org/hwo/net/http/HttpServerRequest.java +++ b/src/org/hwo/net/http/HttpServerRequest.java @@ -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 + 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 responseCookies; + + public HttpServerRequest(HttpServerConnection httpServerConnection) throws IOException { this.connection = httpServerConnection; - this.header = new Properties(); + this.requestHeaders = new MessageHeaders(); + this.requestCookies = new Hashtable(); + this.responseCookies = new ArrayList(); 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; + } } diff --git a/src/org/hwo/net/http/MessageHeaders.java b/src/org/hwo/net/http/MessageHeaders.java new file mode 100644 index 0000000..7ce05ef --- /dev/null +++ b/src/org/hwo/net/http/MessageHeaders.java @@ -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> headers; + + public MessageHeaders() + { + headers = new Hashtable>(); + } + + public void read(StreamReader reader) throws IOException + { + String line; + String headerName = null; + List values = new ArrayList(); + + 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 getHeaderValueList(String headerName) + { + List values; + + if (!headers.containsKey(headerName)) + { + values = new ArrayList(); + 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 values = new ArrayList(); + values.add(headerValue); + headers.put(headerName, values); + } + + public void addHeaderValue(String headerName,String headerValue) + { + getHeaderValueList(headerName).add(headerValue); + } + + +} diff --git a/src/org/hwo/net/http/SessionTracker.java b/src/org/hwo/net/http/SessionTracker.java new file mode 100644 index 0000000..50e25c4 --- /dev/null +++ b/src/org/hwo/net/http/SessionTracker.java @@ -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()); + } + + + + +} diff --git a/src/org/hwo/net/requesthandler/ServerObjectHandler.java b/src/org/hwo/net/requesthandler/ServerObjectHandler.java index 820e7fc..8109b7c 100644 --- a/src/org/hwo/net/requesthandler/ServerObjectHandler.java +++ b/src/org/hwo/net/requesthandler/ServerObjectHandler.java @@ -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) + { + + } + } } diff --git a/src/org/hwo/net/serverobjects/AbstractServerObject.java b/src/org/hwo/net/serverobjects/AbstractServerObject.java index 1359ef9..d3e2be7 100644 --- a/src/org/hwo/net/serverobjects/AbstractServerObject.java +++ b/src/org/hwo/net/serverobjects/AbstractServerObject.java @@ -4,7 +4,10 @@ import java.io.IOException; import java.util.ArrayList; 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; public abstract class AbstractServerObject implements ServerObject { @@ -49,7 +52,7 @@ public abstract class AbstractServerObject implements ServerObject { } @Override - public void climb(ServerObjectRequest request) throws IOException { + public void climb(ServerObjectRequest request) throws IOException, HttpException { String nextChildName = request.popNextElement(); if (nextChildName == null) diff --git a/src/org/hwo/net/serverobjects/DAVCollectionSO.java b/src/org/hwo/net/serverobjects/DAVCollectionSO.java new file mode 100644 index 0000000..a0f20cd --- /dev/null +++ b/src/org/hwo/net/serverobjects/DAVCollectionSO.java @@ -0,0 +1,116 @@ +package org.hwo.net.serverobjects; + +import java.io.IOException; + +import javax.xml.ws.http.HTTPException; + +import org.hwo.net.http.HttpException; +import org.hwo.net.serverobjects.dav.DAVCollection; +import org.hwo.net.serverobjects.dav.DAVPropertyName; +import org.hwo.net.serverobjects.dav.DAVPropertyNameList; +import org.hwo.net.serverobjects.dav.DAVResource; +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class DAVCollectionSO extends AbstractServerObject{ + + class RootCollection extends DAVCollection + { + + public RootCollection(String name) { + super(name); + } + + @Override + protected String constructURI() { + return ""; + } + @Override + public DAVResource getParent() { + return null; + } + + } + + + private DAVCollection rootCollection; + + public DAVCollectionSO() + { + rootCollection = new RootCollection(""); + } + + @Override + public void request(ServerObjectRequest request) throws IOException, HttpException + { + request.getHttpRequest().addResponseHeader("DAV", "1"); + + String method = request.getHttpRequest().getRequestMethod(); + + System.err.println("DAV Request: " + method); + + if (method.equals("GET")) + { + request.getHttpRequest().setResponseHeader("Content-Type", "text/plain"); + request.getHttpRequest().getResponseWriter().write("This is a DAV Container."); + } else if (method.equals("PROPFIND")) + { + doPROPFIND(request); + } else if (method.equals("PROPPATCH")) + { + doPROPPATCH(request); + } else if (method.equals("MKCOL")) + { + doMKCOL(request); + } else if (method.equals("DELETE")) + { + doDELETE(request); + } else if (method.equals("OPTIONS")) + { + doOPTIONS(request); + } + } + + protected void doPROPFIND(ServerObjectRequest request) throws HttpException + { + System.err.println("PROPFIND:"); + System.err.println(new String(request.getHttpRequest().getRequestContent())); + + Document d = request.getHttpRequest().getXMLRequest(); + if (d == null) + throw new HttpException(403); + + Element propfind = d.getDocumentElement(); + + if (propfind.getLocalName().equals("propfind") && propfind.getNamespaceURI().equals("DAV:")) + { + for (Element child:NodeListIterator.create(propfind.getChildNodes())) + { + if (child.getLocalName().equals("prop")) + { + DAVPropertyNameList names = DAVPropertyNameList.fromXML(child); + for (DAVPropertyName name:names) + { + System.err.println("DAVProp: " + name.getNamespaceURI() + " : " + name.getPropertyName()); + } + } + } + } + + } + protected void doPROPPATCH(ServerObjectRequest request) throws HttpException + { + } + protected void doMKCOL(ServerObjectRequest request) throws HttpException + { + } + protected void doDELETE(ServerObjectRequest request) throws HttpException + { + } + protected void doOPTIONS(ServerObjectRequest request) throws HttpException + { + request.getHttpRequest().setResultCode(200); + } + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVCollection.java b/src/org/hwo/net/serverobjects/dav/DAVCollection.java new file mode 100644 index 0000000..2263f8e --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVCollection.java @@ -0,0 +1,53 @@ +package org.hwo.net.serverobjects.dav; + +import java.util.LinkedList; +import java.util.List; + +public class DAVCollection extends DAVResource{ + + List children; + + public DAVCollection(String name) { + super(name); + children = new LinkedList(); + } + + @Override + public boolean isCollection() { + return true; + } + + @Override + public DAVResource[] getChildren() { + return children.toArray(new DAVResource[0]); + } + + public void appendResource(DAVResource child) + { + DAVResource resource = getChildByName(child.getName()); + if (resource != null) + { + removeChild(resource); + } + children.add(child); + child.setParent(this); + } + + public DAVResource getChildByName(String name) + { + for (DAVResource resource: children) + { + if (resource.getName().equals(name)) + return resource; + } + return null; + } + + public void removeChild(DAVResource child) + { + children.remove(child); + child.setParent(null); + } + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVDeadPropertyNS.java b/src/org/hwo/net/serverobjects/dav/DAVDeadPropertyNS.java new file mode 100644 index 0000000..f710f63 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVDeadPropertyNS.java @@ -0,0 +1,46 @@ +package org.hwo.net.serverobjects.dav; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class DAVDeadPropertyNS extends DAVPropertyNamespace { + + DocumentBuilder builder; + + public DAVDeadPropertyNS(String namespaceURI) + { + super(namespaceURI); + + try { + DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setNamespaceAware(true); + builder = f.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } + } + + @Override + public Element getPropertyValue(DAVResource resource, DAVProperty property) { + return resource.getProperty(property.getNamespace().getNamespaceURI(), property.getPropertyName()); + } + + @Override + public void setPropertyValue(DAVResource resource, DAVProperty property,Element value) { + if (property.isValue(value)) + { + Document d = builder.newDocument(); + Node n = d.importNode(value, true); + d.appendChild(n); + System.err.println("setPropertyValue: " + d.toString()); + } + } + + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVProperty.java b/src/org/hwo/net/serverobjects/dav/DAVProperty.java new file mode 100644 index 0000000..72bf622 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVProperty.java @@ -0,0 +1,43 @@ +package org.hwo.net.serverobjects.dav; + +import org.w3c.dom.Element; + +public abstract class DAVProperty { + + private DAVPropertyNamespace namespace; + private String propertyName; + + public DAVProperty(DAVPropertyNamespace namespace,String propertyName) + { + this.namespace = namespace; + this.propertyName = propertyName; + + } + + public DAVPropertyNamespace getNamespace() { + return namespace; + } + + public String getPropertyName() { + return propertyName; + } + + public Element getValue(DAVResource resource) + { + return namespace.getPropertyValue(resource, this); + } + public void setValue(DAVResource resource,Element value) + { + this.namespace.setPropertyValue(resource, this, value); + } + + + public boolean isValue(Element value) + { + if (value.getNamespaceURI().equals(namespace.getNamespaceURI()) && value.getLocalName().equals(propertyName)) + return true; + return false; + } + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVPropertyDAVNS.java b/src/org/hwo/net/serverobjects/dav/DAVPropertyDAVNS.java new file mode 100644 index 0000000..9fd86f7 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVPropertyDAVNS.java @@ -0,0 +1,29 @@ +package org.hwo.net.serverobjects.dav; + +import org.w3c.dom.Element; + +public class DAVPropertyDAVNS extends DAVPropertyNamespace { + + public DAVPropertyDAVNS(String namespaceURI) { + super(namespaceURI); + } + + @Override + public Element getPropertyValue(DAVResource resource, DAVProperty property) { + + if (property.getPropertyName().equals("")) + { + + } + return null; + } + + @Override + public void setPropertyValue(DAVResource resource, DAVProperty property, + Element value) { + } + + + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVPropertyName.java b/src/org/hwo/net/serverobjects/dav/DAVPropertyName.java new file mode 100644 index 0000000..2abbdb2 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVPropertyName.java @@ -0,0 +1,52 @@ +package org.hwo.net.serverobjects.dav; + +import org.w3c.dom.Element; + +public class DAVPropertyName { + + private String namespaceURI; + private String propertyName; + + public static DAVPropertyName fromXML(Element property) + { + DAVPropertyName dpn = new DAVPropertyName(); + dpn.setNamespaceURI(property.getNamespaceURI()); + dpn.setPropertyName(property.getLocalName()); + return dpn; + } + + public DAVPropertyName() + { + setNamespaceURI(null); + setPropertyName(null); + } + public DAVPropertyName(String propertyName) + { + setNamespaceURI(propertyName); + setPropertyName(null); + } + public DAVPropertyName(String propertyName,String namespaceURI) + { + setNamespaceURI(propertyName); + setPropertyName(namespaceURI); + } + + public String getNamespaceURI() { + return namespaceURI; + } + + public void setNamespaceURI(String namespaceURI) { + this.namespaceURI = namespaceURI; + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVPropertyNameList.java b/src/org/hwo/net/serverobjects/dav/DAVPropertyNameList.java new file mode 100644 index 0000000..c23e355 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVPropertyNameList.java @@ -0,0 +1,23 @@ +package org.hwo.net.serverobjects.dav; + +import java.util.LinkedList; + +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class DAVPropertyNameList extends LinkedList{ + + public static DAVPropertyNameList fromXML(Element prop) + { + DAVPropertyNameList l = new DAVPropertyNameList(); + + NodeList props = prop.getChildNodes(); + for (Element p:new NodeListIterator(props)) + l.add(DAVPropertyName.fromXML(p)); + + return l; + } + + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVPropertyNamespace.java b/src/org/hwo/net/serverobjects/dav/DAVPropertyNamespace.java new file mode 100644 index 0000000..0091dda --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVPropertyNamespace.java @@ -0,0 +1,40 @@ +package org.hwo.net.serverobjects.dav; + +import java.util.Hashtable; + +import org.w3c.dom.Element; + +public abstract class DAVPropertyNamespace { + + private static Hashtable + namespaces; + + public static DAVPropertyNamespace getNameSpace(String namespaceURI) + { + if (!namespaces.containsKey(namespaceURI)) + namespaces.put(namespaceURI, new DAVDeadPropertyNS(namespaceURI)); + + return namespaces.get(namespaceURI); + } + + private String namespaceURI; + + public DAVPropertyNamespace(String namespaceURI) + { + this.namespaceURI = namespaceURI; + } + + + public String getNamespaceURI() { + return namespaceURI; + } + + abstract public Element getPropertyValue(DAVResource resource,DAVProperty property); + abstract public void setPropertyValue(DAVResource resource,DAVProperty property,Element value); + + + static { + namespaces = new Hashtable(); + } + +} diff --git a/src/org/hwo/net/serverobjects/dav/DAVResource.java b/src/org/hwo/net/serverobjects/dav/DAVResource.java new file mode 100644 index 0000000..22bbfb6 --- /dev/null +++ b/src/org/hwo/net/serverobjects/dav/DAVResource.java @@ -0,0 +1,153 @@ +package org.hwo.net.serverobjects.dav; + +import java.util.Hashtable; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.w3c.dom.traversal.NodeIterator; + +public class DAVResource { + + private byte[] content; + private String name; + private String mimetype; + + private DAVResource + parent; + + private String uri; + + private Hashtable + properties; + + private DocumentBuilder + builder; + + public DAVResource(String name) + { + this.setContent(new byte[0]); + this.setName(name); + this.setMimetype("application/octet-stream"); + + DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setNamespaceAware(true); + try { + builder = f.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } + } + + protected void setParent(DAVResource resource) + { + this.parent = resource; + this.setURI(constructURI()); + } + + public DAVResource getParent() + { + return this.parent; + } + + protected String constructURI() + { + if (parent != null) + return String.format("%s/%s",parent.constructURI(),name); + return String.format("/%s", name); + } + + + public boolean isCollection() + { + return false; + } + + public DAVResource[] getChildren() + { + return new DAVResource[0]; + } + + public int getContentLength() + { + return content.length; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public byte[] getContent() { + return content; + } + public void setContent(byte[] content) { + this.content = content; + } + + public String getURI() + { + return this.uri; + } + private void setURI(String uri) + { + this.uri = uri; + } + + + public String getMimetype() { + return mimetype; + } + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + public Document getPropertyDocument(String namespaceURI) + { + if (!properties.containsKey(namespaceURI)) + { + Document d = builder.newDocument(); + d.appendChild(d.createElementNS(namespaceURI, "properties")); + properties.put(namespaceURI, d); + } + return properties.get(namespaceURI); + } + + public Element getProperty(String namespaceURI,String propertyName) + { + Document pdoc = getPropertyDocument(namespaceURI); + + NodeList nl = pdoc.getElementsByTagNameNS(namespaceURI, propertyName); + if (nl.getLength()>0) + return (Element)nl.item(0); + return null; + } + + public void setProperty(String namespaceURI,String propertyName,Element value) + { + Document pdoc = getPropertyDocument(namespaceURI); + + Element propertyElement = getProperty(namespaceURI, propertyName); + if (propertyElement == null) + { + propertyElement = pdoc.createElementNS(namespaceURI, propertyName); + pdoc.getDocumentElement().appendChild( propertyElement ); + } + while (propertyElement.hasChildNodes()) + propertyElement.removeChild(propertyElement.getFirstChild()); + + Element imp = (Element)pdoc.importNode(propertyElement, true); + for (Element c: NodeListIterator.create(imp.getChildNodes())) + propertyElement.appendChild( c ); + } + + + +} diff --git a/src/org/hwo/security/User.java b/src/org/hwo/security/User.java new file mode 100644 index 0000000..45be7ec --- /dev/null +++ b/src/org/hwo/security/User.java @@ -0,0 +1,40 @@ +package org.hwo.security; + +import java.util.ArrayList; +import java.util.List; + +public class User { + + private String username; + private List associatedRights; + + public User() + { + username = null; + associatedRights = new ArrayList(); + } + + public String[] getAssociatedRights() + { + return associatedRights.toArray(new String[0]); + } + + public String getUserName() + { + return this.username; + } + + public void deauthenticate() + { + this.username = null; + this.associatedRights.clear(); + } + + public boolean authenticate(String username,String password) + { + this.username = username; + this.associatedRights.add("sys.default.user.implementation"); + return true; + } + +} diff --git a/src/org/hwo/sessions/Session.java b/src/org/hwo/sessions/Session.java new file mode 100644 index 0000000..ce314d5 --- /dev/null +++ b/src/org/hwo/sessions/Session.java @@ -0,0 +1,36 @@ +package org.hwo.sessions; + +import java.util.Hashtable; + +public class Session { + + private String sessionID; + private Hashtable sessionVars; + + public Session() + { + this.sessionID = null; + this.sessionVars = new Hashtable(); + } + public Session(String sid) + { + this.sessionID = sid; + this.sessionVars = new Hashtable(); + } + + 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); + } + + +} diff --git a/src/org/hwo/sessions/SessionManager.java b/src/org/hwo/sessions/SessionManager.java new file mode 100644 index 0000000..2a52a6e --- /dev/null +++ b/src/org/hwo/sessions/SessionManager.java @@ -0,0 +1,52 @@ +package org.hwo.sessions; + +import java.util.Hashtable; +import java.util.UUID; + +public class SessionManager { + + private Hashtable loadedSessions; + + private ThreadLocal threadSession; + + public SessionManager() + { + loadedSessions = new Hashtable(); + threadSession = new ThreadLocal(); + } + + 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); + } + + +} diff --git a/src/org/hwo/xml/NodeListIterator.java b/src/org/hwo/xml/NodeListIterator.java new file mode 100644 index 0000000..c194986 --- /dev/null +++ b/src/org/hwo/xml/NodeListIterator.java @@ -0,0 +1,38 @@ +package org.hwo.xml; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class NodeListIterator implements Iterable{ + + + private List elements; + + public static NodeListIterator create(NodeList nodes) + { + return new NodeListIterator(nodes); + } + + public NodeListIterator(NodeList nodes) + { + this.elements = new ArrayList(); + for (int i=0;i iterator() { + return this.elements.iterator(); + } + + +}