From 3dc7c479c16fe3a5f6f5c3fd8027378a727a7eb2 Mon Sep 17 00:00:00 2001 From: cremet Date: Mon, 26 Jan 2004 15:38:33 +0000 Subject: - Simple HTTP server adapted from the example i... - Simple HTTP server adapted from the example in the book "Java Network Programming" by Elliotte Rusty Harold to handle servlet invokations. --- sources/scala/tools/scaladoc/HTTPServer.java | 377 +++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100755 sources/scala/tools/scaladoc/HTTPServer.java (limited to 'sources') diff --git a/sources/scala/tools/scaladoc/HTTPServer.java b/sources/scala/tools/scaladoc/HTTPServer.java new file mode 100755 index 0000000000..3cdc8b31ce --- /dev/null +++ b/sources/scala/tools/scaladoc/HTTPServer.java @@ -0,0 +1,377 @@ +package scala.tools.scaladoc; + +import java.net.*; +import java.io.*; +import java.util.*; +import java.util.regex.*; + +/** + * A Java server that can be invoked via HTTP. + */ +public abstract class Servlet { + + /** + * Name of the servlet. + */ + public abstract String name(); + + /** + * Give the servlet a request and a place where to write its + * answer. + */ + public abstract void apply(Map req, Writer out); +} + +/** + * A servlet that echoes the query to its sender. + */ +public class EchoServlet extends Servlet { + + public String name() { + return "echoServlet"; + } + + public void apply(Map req, Writer out) { + printMap(req, out); + } + + /** Print a map. */ + public static void printMap(Map map, Writer out) { + Iterator i = map.keySet().iterator(); + while(i.hasNext()) { + String key = (String) i.next(); + String value = (String) map.get(key); + try { + out.write(key + " -> " + value + "\n"); + } catch(IOException e) {} + } + } +} + +public class HTTPServer extends Thread { + + private File documentRootDirectory; + private String indexFileName = "index.html"; + private ServerSocket server; + private int numThreads = 50; + + private Map/*[String,Servlet]*/ servletNamed; + + public HTTPServer(File documentRootDirectory, + int port, + String indexFileName) throws IOException { + + if (!documentRootDirectory.isDirectory()) { + throw new IOException(documentRootDirectory + + " does not exist as a directory"); + } + this.documentRootDirectory = documentRootDirectory; + this.indexFileName = indexFileName; + this.server = new ServerSocket(port); + } + + public HTTPServer(File documentRootDirectory, int port) + throws IOException { + this(documentRootDirectory, port, "index.html"); + } + + public HTTPServer(File documentRootDirectory) throws IOException { + this(documentRootDirectory, 80, "index.html"); + } + + public HTTPServer(File documentRootDirectory, + int port, + Servlet[] servlets) throws IOException { + this(documentRootDirectory, port, "index.html"); + servletNamed = new HashMap(); + for(int i = 0; i < servlets.length; i++) + servletNamed.put("/" + servlets[i].name(), servlets[i]); + } + + public void run() { + + for (int i = 0; i < numThreads; i++) { + Thread t = new Thread( + new RequestProcessor(documentRootDirectory, + indexFileName, + servletNamed)); + t.start(); + } + System.out.println("Accepting connections on port " + + server.getLocalPort()); + System.out.println("Document Root: " + documentRootDirectory); + while (true) { + try { + Socket request = server.accept(); + RequestProcessor.processRequest(request); + } + catch (IOException e) { + } + } + } + + public static void main(String[] args) { + + // get the Document root + File docroot; + try { + docroot = new File(args[0]); + } + catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Usage: java HTTPServer docroot port indexfile"); + return; + } + + // set the port to listen on + int port; + try { + port = Integer.parseInt(args[1]); + if (port < 0 || port > 65535) port = 80; + } + catch (Exception e) { + port = 80; + } + + try { + Servlet[] servlets = new Servlet[] { new EchoServlet() }; + HTTPServer webserver = new HTTPServer(docroot, port, servlets); + webserver.start(); + } + catch (IOException e) { + System.out.println("Server could not start because of an " + + e.getClass()); + System.out.println(e); + } + } +} + +public class RequestProcessor implements Runnable { + + private static List pool = new LinkedList(); + private File documentRootDirectory; + private String indexFileName = "index.html"; + private Map servletNamed; + + public RequestProcessor(File documentRootDirectory, + String indexFileName, + Map servletNamed) { + + if (documentRootDirectory.isFile()) { + throw new IllegalArgumentException( + "documentRootDirectory must be a directory, not a file"); + } + this.documentRootDirectory = documentRootDirectory; + try { + this.documentRootDirectory + = documentRootDirectory.getCanonicalFile(); + } + catch (IOException e) { + } + if (indexFileName != null) this.indexFileName = indexFileName; + this.servletNamed = servletNamed; + } + + public static void processRequest(Socket request) { + synchronized (pool) { + pool.add(pool.size(), request); + pool.notifyAll(); + } + } + + /** + * Parse a non-null query and put the bindings (key, value) into + * the result map. + */ + public static Map parseQuery(String query) { + Map map = new HashMap(); + String[] bindings = query.split("\\&"); + String regexp = "([^=]*)=([^=]*)"; + Pattern p = Pattern.compile(regexp); + for(int i = 0; i < bindings.length; i++) { + Matcher m = p.matcher(bindings[i]); + if (m.find()) { + String key = URLDecoder.decode(m.group(1)); + String value = URLDecoder.decode(m.group(2)); + map.put(key, value); + } + } + return map; + } + + public static void fileNotFound(String version, Writer out) { + try { + if (version.startsWith("HTTP/")) { // send a MIME header + out.write("HTTP/1.0 404 File Not Found\r\n"); + Date now = new Date(); + out.write("Date: " + now + "\r\n"); + out.write("Server: HTTPServer 1.0\r\n"); + out.write("Content-type: text/html\r\n\r\n"); + } + out.write("\r\n"); + out.write("File Not Found\r\n"); + out.write("\r\n"); + out.write(""); + out.write("

HTTP Error 404: File Not Found

\r\n"); + out.write("\r\n"); + out.flush(); + } + catch(IOException e) { + + } + } + + public void run() { + + // for security checks + String root = documentRootDirectory.getPath(); + + while (true) { + Socket connection; + synchronized (pool) { + while (pool.isEmpty()) { + try { + pool.wait(); + } + catch (InterruptedException e) { + } + } + connection = (Socket) pool.remove(0); + } + + try { + String filename; + String contentType; + OutputStream raw = + new BufferedOutputStream( + connection.getOutputStream()); + Writer out = new OutputStreamWriter(raw); + Reader in = + new InputStreamReader( + new BufferedInputStream(connection.getInputStream()), + "ASCII"); + StringBuffer requestLine = new StringBuffer(); + int c; + while (true) { + c = in.read(); + if (c == '\r' || c == '\n') break; + requestLine.append((char) c); + } + + String get = requestLine.toString(); + + // log the request + System.out.println(get); + + StringTokenizer st = new StringTokenizer(get); + String method = st.nextToken(); + String version = ""; + if (method.equals("GET")) { + filename = st.nextToken(); + + URI uri = new URI(filename); + String resource = uri.getPath(); + Servlet servlet = (Servlet) servletNamed.get(resource); + if (servlet != null) { // servlet invokation + String query = uri.getRawQuery(); + Map map = + (query != null) ? + parseQuery(query) : + new HashMap(); + servlet.apply(map, out); + out.write("\n"); + out.flush(); + } + else { // not a query + if (filename.endsWith("/")) filename += indexFileName; + contentType = guessContentTypeFromName(filename); + if (st.hasMoreTokens()) { + version = st.nextToken(); + } + + File theFile = new File(documentRootDirectory, + filename.substring(1,filename.length())); + if (theFile.canRead() + // Don't let clients outside the document root + && theFile.getCanonicalPath().startsWith(root)) { + DataInputStream fis = + new DataInputStream( + new BufferedInputStream( + new FileInputStream(theFile))); + byte[] theData = new byte[(int) theFile.length()]; + fis.readFully(theData); + fis.close(); + if (version.startsWith("HTTP/")) { // send a MIME header + out.write("HTTP/1.0 200 OK\r\n"); + Date now = new Date(); + out.write("Date: " + now + "\r\n"); + out.write("Server: HTTPServer 1.0\r\n"); + out.write("Content-length: " + theData.length + "\r\n"); + out.write("Content-type: " + contentType + "\r\n\r\n"); + out.flush(); + } // end try + + // send the file; it may be an image or other binary data + // so use the underlying output stream + // instead of the writer + raw.write(theData); + raw.flush(); + } // end if + else { // can't find the file + fileNotFound(version, out); + } + } + } + else { // method does not equal "GET" + if (version.startsWith("HTTP/")) { // send a MIME header + out.write("HTTP/1.0 501 Not Implemented\r\n"); + Date now = new Date(); + out.write("Date: " + now + "\r\n"); + out.write("Server: HTTPServer 1.0\r\n"); + out.write("Content-type: text/html\r\n\r\n"); + } + out.write("\r\n"); + out.write("Not Implemented\r\n"); + out.write("\r\n"); + out.write(""); + out.write("

HTTP Error 501: Not Implemented

\r\n"); + out.write("\r\n"); + out.flush(); + } + } + catch (URISyntaxException e) { + System.out.println("Une exception: " + e); + } + catch (IOException e) { + System.out.println("Une exception: " + e); + } + finally { + try { + connection.close(); + } + catch (IOException e) {} + } + + } // end while + + } // end run + + public static String guessContentTypeFromName(String name) { + if (name.endsWith(".html") || name.endsWith(".htm")) { + return "text/html"; + } + else if (name.endsWith(".txt") || name.endsWith(".java")) { + return "text/plain"; + } + else if (name.endsWith(".gif")) { + return "image/gif"; + } + else if (name.endsWith(".class")) { + return "application/octet-stream"; + } + else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) { + return "image/jpeg"; + } + else return "text/plain"; + } + +} // end RequestProcessor -- cgit v1.2.3