//Oppgavetekst: Lag en webserver med foelgende funksjoner:
// * Server filer
// * List opp mapper og filer i en mappe - saakalt directory index
// * Sender en 404-side naar noen spoer om en fil som ikke finnes
// * Kjoer Python-scripts, filer som ender i .py, og send resultatet til nettlesere
import java.util.Scanner;
import java.util.HashMap;
import java.io.*;
import java.nio.file.Paths;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
class Templates {
public static String sysInfo =
"
"+
""+
"Web Server running on "+
System.getProperty("os.name")+" "+
System.getProperty("os.version")+" "+
System.getProperty("os.arch")+
"
";
public static String err404 =
""+
""+
""+
"Error 404"+
""+
""+
"404 Not Found
"+
"The file {{$1}} was not found.
"+
sysInfo+
""+
"";
public static String index =
""+
""+
""+
"Index"+
""+
""+
""+
sysInfo+
""+
"";
public static String indexEntry =
""+
"{{$1}}"+
"";
//Convenience function; many templates have only one argument,
//pointless to have to build up a String[] just for that
public static String templatify(String str, String arg) {
String[] args = {arg};
return templatify(str, args);
}
//Build a template, replacing things within {{ and }} with
//the arguments provided
public static String templatify(String str, String[] args) {
for (int i = 0; i < args.length; ++i) {
str = str.replace("{{$"+(i+1)+"}}", args[i]);
}
return str;
}
}
class RequestHandler implements HttpHandler {
private File root;
@Override public void handle(HttpExchange t) throws IOException {
OutputStream out = t.getResponseBody();
String url = t.getRequestURI().toString().split("\\?")[0];
int lmul = 1;
//HEAD requests want to only receive headers, but that's
//somewhat hard to implement with this structure.
//We'll just kill the connection if that happens.
if (t.getRequestMethod().equalsIgnoreCase("HEAD")) {
out.close();
return;
}
File f = new File(root, url);
if (!f.exists()) {
send404(f, url, out, t);
} else if (f.isDirectory())
sendIndex(f, url, out, t);
else {
if (url.endsWith(".py"))
sendPython(f, url, out, t);
else
sendFile(f, url, out, t);
}
out.close();
}
RequestHandler(File r) {
root = r;
}
//404 when a file which doesn't exist is requested
private static void send404(File f, String url, OutputStream out, HttpExchange t) throws IOException {
byte[] res = Templates.templatify(Templates.err404, url).getBytes();
t.sendResponseHeaders(404, res.length);
out.write(res);
}
//Directory index when a directory is requested
private static void sendIndex(File dir, String url, OutputStream out, HttpExchange t) throws IOException {
File[] files = dir.listFiles();
String entries = "";
//Loop through files in the requested directory,
//building up the list of entries
for (int i = 0; i < files.length; ++i) {
File f = files[i];
String name = f.toPath().getFileName().toString();
if (f.isDirectory())
name += "/";
entries += Templates.templatify(Templates.indexEntry, name);
}
//Combine the entries with the rest of the index' HTML,
//and send to the client
byte[] res = Templates.templatify(Templates.index, entries).getBytes();
t.sendResponseHeaders(200, res.length);
out.write(res);
}
//Send file when a file is requested
private static void sendFile(File f, String url, OutputStream out, HttpExchange t) throws IOException {
Scanner s = new Scanner(f);
t.sendResponseHeaders(200, f.length());
while (s.hasNextLine()) {
out.write((s.nextLine()+"\n").getBytes());
}
}
//Execute python script and send the output to the browser
private static void sendPython(File f, String url, OutputStream out, HttpExchange t) throws IOException {
String[] command = {"python", f.toPath().toString()};
Process proc = Runtime.getRuntime().exec(command);
BufferedReader stdin = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String res = "";
String s = null;
//Print the output from the python script
while ((s = stdin.readLine()) != null) {
res += s+"\n";
}
//Print the errors from the python script
while ((s = stderr.readLine()) != null) {
res += s+"\n";
}
t.getResponseHeaders().add("Content-Type", "text/plain");
t.sendResponseHeaders(200, res.length());
out.write(res.getBytes());
}
}
class MinOppgave4 {
private static HttpServer server;
private static File root = new File("www");
private static int port = 8000;
//Simple command line interface
public static String onCommand(String str) {
String[] tokens = str.split("\\s+");
switch (tokens[0]) {
case "help":
return
"help: Display this help text\n"+
"stop: Stop the web server";
case "stop":
System.exit(0);
return "";
default:
return
"Unknown command: "+tokens[0]+"\n"+
"Type 'help' for help.";
}
}
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
//Create an HTTP server
server = HttpServer.create(new InetSocketAddress(port), 0);
//Add request handler
server.createContext("/", new RequestHandler(root));
//Start the server
server.start();
System.out.println("Server started. Visit http://localhost:"+port+" in a web browser.");
System.out.println("Try modifying the contents of the directory "+root.toPath().getFileName()+".");
//Simple command line interface
System.out.print("> ");
while (s.hasNextLine()) {
System.out.println(onCommand(s.nextLine()));
System.out.print("> ");
}
}
}