working on internal web server for html help

This commit is contained in:
benfry
2008-09-28 22:05:04 +00:00
parent 19e2888de7
commit bf59893c24
2 changed files with 212 additions and 88 deletions
+19
View File
@@ -861,6 +861,25 @@ public class Editor extends JFrame implements RunnerListener {
JMenu menu = new JMenu("Help");
JMenuItem item;
item = new JMenuItem("Web Server Test");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//WebServer ws = new WebServer();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
int port = WebServer.launch("/Users/fry/coconut/processing/build/shared/reference.zip");
Base.openURL("http://127.0.0.1:" + port + "/reference/setup_.html");
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
});
menu.add(item);
/*
item = new JMenuItem("Browser Test");
item.addActionListener(new ActionListener() {
+193 -88
View File
@@ -1,51 +1,34 @@
package processing.app;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.zip.*;
//import javax.swing.SwingUtilities;
/**
* An example of a very simple, multi-threaded HTTP server.
* Implementation notes are in WebServer.html, and also
* as comments in the source code.
* <p>
* Taken from <a href="http://java.sun.com/developer/technicalArticles/Networking/Webserver/">this</a> article on java.sun.com.
*/
class WebServer implements HttpConstants {
/* static class data/methods */
/* print to stdout */
protected static void p(String s) {
System.out.println(s);
}
/* print to the log file */
protected static void log(String s) {
synchronized (log) {
log.println(s);
log.flush();
}
}
static PrintStream log = null;
/* our server's configuration information is stored
* in these properties
*/
protected static Properties props = new Properties();
public class WebServer implements HttpConstants {
/* Where worker threads stand idle */
static Vector threads = new Vector();
/* the web server's virtual root */
static File root;
//static File root;
/* timeout on client connections */
static int timeout = 0;
static int timeout = 10000;
/* max # worker threads */
static int workers = 5;
// static PrintStream log = System.out;
/* load www-server.properties from java.home */
/*
static void loadProps() throws IOException {
File f = new File
(System.getProperty("java.home")+File.separator+
@@ -78,7 +61,7 @@ class WebServer implements HttpConstants {
}
}
/* if no properties were specified, choose defaults */
// if no properties were specified, choose defaults
if (root == null) {
root = new File(System.getProperty("user.dir"));
}
@@ -99,58 +82,109 @@ class WebServer implements HttpConstants {
p("timeout="+timeout);
p("workers="+workers);
}
*/
public static void main(String[] a) throws Exception {
int port = 8080;
if (a.length > 0) {
port = Integer.parseInt(a[0]);
}
loadProps();
printProps();
/* start worker threads */
/* print to stdout */
// protected static void p(String s) {
// System.out.println(s);
// }
/* print to the log file */
protected static void log(String s) {
if (false) {
System.out.println(s);
}
// synchronized (log) {
// log.println(s);
// log.flush();
// }
}
//public static void main(String[] a) throws Exception {
static public int launch(String zipPath) throws IOException {
final ZipFile zip = new ZipFile(zipPath);
final HashMap<String, ZipEntry> entries = new HashMap();
Enumeration en = zip.entries();
while (en.hasMoreElements()) {
ZipEntry entry = (ZipEntry) en.nextElement();
entries.put(entry.getName(), entry);
}
// if (a.length > 0) {
// port = Integer.parseInt(a[0]);
// }
// loadProps();
// printProps();
// start worker threads
for (int i = 0; i < workers; ++i) {
Worker w = new Worker();
(new Thread(w, "worker #"+i)).start();
WebServerWorker w = new WebServerWorker(zip, entries);
Thread t = new Thread(w, "Web Server Worker #" + i);
t.start();
threads.addElement(w);
}
ServerSocket ss = new ServerSocket(port);
while (true) {
final int port = 8080;
Socket s = ss.accept();
Worker w = null;
synchronized (threads) {
if (threads.isEmpty()) {
Worker ws = new Worker();
//SwingUtilities.invokeLater(new Runnable() {
Runnable r = new Runnable() {
public void run() {
try {
ServerSocket ss = new ServerSocket(port);
while (true) {
Socket s = ss.accept();
WebServerWorker w = null;
synchronized (threads) {
if (threads.isEmpty()) {
WebServerWorker ws = new WebServerWorker(zip, entries);
ws.setSocket(s);
(new Thread(ws, "additional worker")).start();
} else {
w = (Worker) threads.elementAt(0);
} else {
w = (WebServerWorker) threads.elementAt(0);
threads.removeElementAt(0);
w.setSocket(s);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
new Thread(r).start();
// });
return port;
}
}
class Worker extends WebServer implements HttpConstants, Runnable {
class WebServerWorker /*extends WebServer*/ implements HttpConstants, Runnable {
ZipFile zip;
HashMap<String, ZipEntry> entries;
final static int BUF_SIZE = 2048;
static final byte[] EOL = {(byte)'\r', (byte)'\n' };
static final byte[] EOL = { (byte)'\r', (byte)'\n' };
/* buffer to use for requests */
byte[] buf;
/* Socket to client we're handling */
private Socket s;
Worker() {
buf = new byte[BUF_SIZE];
s = null;
}
WebServerWorker(ZipFile zip, HashMap entries) {
this.entries = entries;
this.zip = zip;
buf = new byte[BUF_SIZE];
s = null;
}
// Worker() {
// buf = new byte[BUF_SIZE];
// s = null;
// }
//
synchronized void setSocket(Socket s) {
this.s = s;
notify();
@@ -188,40 +222,35 @@ class Worker extends WebServer implements HttpConstants, Runnable {
}
}
void handleClient() throws IOException {
InputStream is = new BufferedInputStream(s.getInputStream());
PrintStream ps = new PrintStream(s.getOutputStream());
/* we will only block in read for this many milliseconds
* before we fail with java.io.InterruptedIOException,
* at which point we will abandon the connection.
*/
// we will only block in read for this many milliseconds
// before we fail with java.io.InterruptedIOException,
// at which point we will abandon the connection.
s.setSoTimeout(WebServer.timeout);
s.setTcpNoDelay(true);
/* zero out the buffer from last time */
// zero out the buffer from last time
for (int i = 0; i < BUF_SIZE; i++) {
buf[i] = 0;
}
try {
/* We only support HTTP GET/HEAD, and don't
* support any fancy HTTP options,
* so we're only interested really in
* the first line.
*/
// We only support HTTP GET/HEAD, and don't support any fancy HTTP
// options, so we're only interested really in the first line.
int nread = 0, r = 0;
outerloop:
while (nread < BUF_SIZE) {
r = is.read(buf, nread, BUF_SIZE - nread);
if (r == -1) {
/* EOF */
return;
return; // EOF
}
int i = nread;
nread += r;
for (; i < nread; i++) {
if (buf[i] == (byte)'\n' || buf[i] == (byte)'\r') {
/* read one line */
break outerloop;
break outerloop; // read one line
}
}
}
@@ -264,8 +293,23 @@ outerloop:
break;
}
}
String fname = (new String(buf, 0, index,
i-index)).replace('/', File.separatorChar);
String fname = new String(buf, index, i-index);
// get the zip entry, remove the front slash
ZipEntry entry = entries.get(fname.substring(1));
//System.out.println(fname + " " + entry);
boolean ok = printHeaders(entry, ps);
if (entry != null) {
InputStream stream = zip.getInputStream(entry);
if (doingGet && ok) {
sendFile(stream, ps);
}
} else {
send404(ps);
}
/*
String fname =
(new String(buf, 0, index, i-index)).replace('/', File.separatorChar);
if (fname.startsWith(File.separator)) {
fname = fname.substring(1);
}
@@ -284,17 +328,68 @@ outerloop:
send404(targ, ps);
}
}
*/
} finally {
s.close();
}
}
boolean printHeaders(ZipEntry targ, PrintStream ps) throws IOException {
boolean ret = false;
int rCode = 0;
if (targ == null) {
rCode = HTTP_NOT_FOUND;
ps.print("HTTP/1.0 " + HTTP_NOT_FOUND + " Not Found");
ps.write(EOL);
ret = false;
} else {
rCode = HTTP_OK;
ps.print("HTTP/1.0 " + HTTP_OK + " OK");
ps.write(EOL);
ret = true;
}
if (targ != null) {
WebServer.log("From " +s.getInetAddress().getHostAddress()+": GET " + targ.getName()+" --> "+rCode);
}
ps.print("Server: Processing Documentation Server");
ps.write(EOL);
ps.print("Date: " + (new Date()));
ps.write(EOL);
if (ret) {
if (!targ.isDirectory()) {
ps.print("Content-length: " + targ.getSize());
ps.write(EOL);
ps.print("Last Modified: " + new Date(targ.getTime()));
ps.write(EOL);
String name = targ.getName();
int ind = name.lastIndexOf('.');
String ct = null;
if (ind > 0) {
ct = (String) map.get(name.substring(ind));
}
if (ct == null) {
//System.err.println("unknown content type " + name.substring(ind));
ct = "application/x-unknown-content-type";
}
ps.print("Content-type: " + ct);
ps.write(EOL);
} else {
ps.print("Content-type: text/html");
ps.write(EOL);
}
}
ps.write(EOL); // adding another newline here [fry]
return ret;
}
boolean printHeaders(File targ, PrintStream ps) throws IOException {
boolean ret = false;
int rCode = 0;
if (!targ.exists()) {
rCode = HTTP_NOT_FOUND;
ps.print("HTTP/1.0 " + HTTP_NOT_FOUND + " not found");
ps.print("HTTP/1.0 " + HTTP_NOT_FOUND + " Not Found");
ps.write(EOL);
ret = false;
} else {
@@ -303,18 +398,16 @@ outerloop:
ps.write(EOL);
ret = true;
}
log("From " +s.getInetAddress().getHostAddress()+": GET " +
targ.getAbsolutePath()+"-->"+rCode);
WebServer.log("From " +s.getInetAddress().getHostAddress()+": GET " + targ.getAbsolutePath()+"-->"+rCode);
ps.print("Server: Simple java");
ps.write(EOL);
ps.print("Date: " + (new Date()));
ps.write(EOL);
if (ret) {
if (!targ.isDirectory()) {
ps.print("Content-length: "+targ.length());
ps.print("Content-length: " + targ.length());
ps.write(EOL);
ps.print("Last Modified: " + (new
Date(targ.lastModified())));
ps.print("Last Modified: " + new Date(targ.lastModified()));
ps.write(EOL);
String name = targ.getName();
int ind = name.lastIndexOf('.');
@@ -335,13 +428,17 @@ outerloop:
return ret;
}
void send404(File targ, PrintStream ps) throws IOException {
void send404(PrintStream ps) throws IOException {
ps.write(EOL);
ps.write(EOL);
ps.print("<html><body><h1>404 Not Found</h1>"+
"The requested resource was not found.</body></html>");
ps.write(EOL);
ps.write(EOL);
ps.println("Not Found\n\n"+
"The requested resource was not found.\n");
}
void sendFile(File targ, PrintStream ps) throws IOException {
InputStream is = null;
ps.write(EOL);
@@ -351,7 +448,11 @@ outerloop:
} else {
is = new FileInputStream(targ.getAbsolutePath());
}
sendFile(is, ps);
}
void sendFile(InputStream is, PrintStream ps) throws IOException {
try {
int n;
while ((n = is.read(buf)) > 0) {
@@ -374,6 +475,7 @@ outerloop:
static void fillMap() {
setSuffix("", "content/unknown");
setSuffix(".uu", "application/octet-stream");
setSuffix(".exe", "application/octet-stream");
setSuffix(".ps", "application/postscript");
@@ -383,19 +485,24 @@ outerloop:
setSuffix(".snd", "audio/basic");
setSuffix(".au", "audio/basic");
setSuffix(".wav", "audio/x-wav");
setSuffix(".gif", "image/gif");
setSuffix(".jpg", "image/jpeg");
setSuffix(".jpeg", "image/jpeg");
setSuffix(".htm", "text/html");
setSuffix(".html", "text/html");
setSuffix(".text", "text/plain");
setSuffix(".css", "text/css");
setSuffix(".java", "text/javascript");
setSuffix(".txt", "text/plain");
setSuffix(".java", "text/plain");
setSuffix(".c", "text/plain");
setSuffix(".cc", "text/plain");
setSuffix(".c++", "text/plain");
setSuffix(".h", "text/plain");
setSuffix(".pl", "text/plain");
setSuffix(".txt", "text/plain");
setSuffix(".java", "text/plain");
}
void listDirectory(File dir, PrintStream ps) throws IOException {
@@ -415,6 +522,7 @@ outerloop:
}
interface HttpConstants {
/** 2XX: generally "OK" */
public static final int HTTP_OK = 200;
@@ -459,6 +567,3 @@ interface HttpConstants {
public static final int HTTP_GATEWAY_TIMEOUT = 504;
public static final int HTTP_VERSION = 505;
}