blob: 25eb001d10657db39fd803722919004fb6ba033c [file] [log] [blame]
package com.psibt.framework.net;
import java.net.*;
import java.io.*;
import java.util.*;
import org.apache.log4j.*;
/**
* This class implements a HTTP-server frame. All HTTP-requests are handled by HTTPRequestHandler
* classes which implement the <code>HTTPRequestHandler</code> interface. Every RequestHandler has
* to be registered in the PluggableHTTPServer with the <code>addRequestHandler</code> method.
* A new thread is created for each connection to handle the request. If all reply data are sent
* to the client the connection is closed and the thread ends.
* An example how to use the PluggableHTTPServer class can be found in the <code>main</code> method
* at the end of the source file.
*
* @author <a HREF="mailto:V.Mentzner@psi-bt.de">Volker Mentzner</a>
*/
public class PluggableHTTPServer implements Runnable {
public static final int DEFAULT_PORT = 80;
static Category cat = Category.getInstance("PluggableHTTPServer");
private int port;
private Vector handler;
private ServerSocket server;
/**
* Creates a new server object on the given TCP port.
* If the port is occupied by another process a IOException (java.net.BindException) is thrown.
*
* @param port - TCP port number to listen on for requests
*/
public PluggableHTTPServer(int port) throws IOException {
this.port = port;
this.handler = new Vector();
cat.setPriority(Priority.ERROR);
server = new ServerSocket(this.port);
}
/**
* Creates a new server object on the default TCP port 80
* If the port is occupied by another process a IOException (java.net.BindException) is thrown.
*/
public PluggableHTTPServer() throws IOException {
this(DEFAULT_PORT);
}
/**
* Registers the given HTTPRequestHandler
*
* @param h - the HTTPRequestHandler to register
*/
public void addRequestHandler(HTTPRequestHandler h) {
handler.add(h);
}
/**
* Unregisters the given HTTPRequestHandler
*
* @param h - the HTTPRequestHandler to unregister
*/
public void removeRequestHandler(HTTPRequestHandler h) {
handler.remove(h);
}
/**
* Sends the HTTP message 404 - File Not Found
* see RFC2616 for details
*
* @param out - Out stream for sending data to client browser
*/
public static void replyNotFound(Writer out) {
try {
out.write("HTTP/1.0 404 Not Found\r\n");
out.write("<HTML><HEAD><TITLE>Not Found</TITLE></HEAD>\r\n");
out.write("<BODY><H1>Not Found</H1>\r\n");
out.write("</BODY></HTML>\r\n");
out.flush();
} // end try
catch (IOException e) {
}
}
/**
* Sends the HTTP message 405 - Method Not Allowed
* see RFC2616 for details
*
* @param out - Out stream for sending data to client browser
*/
public static void replyMethodNotAllowed(Writer out) {
try {
out.write("HTTP/1.1 405 Method Not Allowed\r\n");
out.write("Allow: GET, PUT\r\n");
out.write("<HTML><HEAD><TITLE>Method Not Allowed</TITLE></HEAD>\r\n");
out.write("<BODY><H1>Method Not Allowed</H1>\r\n");
out.write("</BODY></HTML>\r\n");
out.flush();
} // end try
catch (IOException e) {
}
}
/**
* Creates the ReplyHTML data for the root page
*
* @param index - index of the RootRequestHandler
*/
public void autoCreateRootPage(int index) {
if (handler.get(index) instanceof RootRequestHandler) {
RootRequestHandler r = (RootRequestHandler)handler.get(index);
String html = "<HTML><HEAD><TITLE>"+r.getTitle()+"</TITLE></HEAD>\r\n";
html = html + "<BODY><H1>"+r.getDescription()+"</H1>\r\n";
for (int i = 0; i < handler.size(); i++) {
html = html + "<a href=\"" + ((HTTPRequestHandler)handler.get(i)).getHandledPath();
html = html + "\">" + ((HTTPRequestHandler)handler.get(i)).getDescription() + "</a><br>";
}
html = html + "</BODY></HTML>\r\n";
r.setReplyHTML(html);
}
}
/**
* Main loop of the PluggableHTTPServer
*/
public void run() {
while (true) {
try {
Socket s = server.accept();
Thread t = new ServerThread(s);
t.start();
}
catch (IOException e) {
}
}
}
/**
* This class handles the incomming connection for one request.
*/
class ServerThread extends Thread {
private Socket connection;
ServerThread(Socket s) {
this.connection = s;
}
/**
* Serves the HTTP request.
*/
public void run() {
try {
Writer out = new BufferedWriter(
new OutputStreamWriter(
connection.getOutputStream(), "ASCII"
)
);
Reader in = new InputStreamReader(
new BufferedInputStream(
connection.getInputStream()
)
);
// read the first line only; that's all we need
StringBuffer req = new StringBuffer(80);
while (true) {
int c = in.read();
if (c == '\r' || c == '\n' || c == -1) break;
req.append((char) c);
}
String get = req.toString();
cat.debug(get);
StringTokenizer st = new StringTokenizer(get);
String method = st.nextToken();
String request = st.nextToken();
String version = st.nextToken();
if (method.equalsIgnoreCase("GET")) {
boolean served = false;
for (int i = 0; i < handler.size(); i++) {
if (handler.get(i) instanceof HTTPRequestHandler) {
if (((HTTPRequestHandler)handler.get(i)).handleRequest(request, out)) {
served = true;
break;
}
}
}
if (!served)
PluggableHTTPServer.replyNotFound(out);
}
else {
PluggableHTTPServer.replyMethodNotAllowed(out);
}
} // end try
catch (IOException e) {
}
finally {
try {
if (connection != null) connection.close();
}
catch (IOException e) {}
}
} // end run
} // end class ServerThread
/**
* Demo how to use the PluggableHTTPServer.
*/
public static void main(String[] args) {
int thePort;
// create some logging stuff
BasicConfigurator.configure();
Category cat1 = Category.getInstance("cat1");
cat1.addAppender(new org.apache.log4j.ConsoleAppender(new PatternLayout("%m%n")));
Category cat2 = Category.getInstance("cat2");
cat2.setPriority(Priority.INFO);
cat2.addAppender(new org.apache.log4j.ConsoleAppender(new PatternLayout("%c - %m%n")));
// set TCP port number
try {
thePort = Integer.parseInt(args[1]);
}
catch (Exception e) {
thePort = PluggableHTTPServer.DEFAULT_PORT;
}
PluggableHTTPServer server = null;
while (server == null) {
try {
server = new PluggableHTTPServer(thePort);
server.addRequestHandler(new RootRequestHandler());
server.addRequestHandler(new Log4jRequestHandler());
server.addRequestHandler(new UserDialogRequestHandler());
server.autoCreateRootPage(0);
Thread t = new Thread(server);
t.start();
} catch (IOException e) {
server = null;
thePort++;
}
}
} // end main
}