Moved handlers to their own (independent) classes.
This commit is contained in:
parent
79552bf040
commit
6cd10e21bc
7 changed files with 274 additions and 244 deletions
|
|
@ -1,18 +1,26 @@
|
||||||
package org.dynmap;
|
package org.dynmap;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import org.bukkit.*;
|
import java.io.IOException;
|
||||||
import org.bukkit.event.*;
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.Event.Priority;
|
import org.bukkit.event.Event.Priority;
|
||||||
import org.bukkit.event.block.BlockListener;
|
import org.bukkit.event.block.BlockListener;
|
||||||
import org.bukkit.plugin.*;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.java.*;
|
import org.bukkit.plugin.PluginLoader;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.util.config.Configuration;
|
import org.bukkit.util.config.Configuration;
|
||||||
import org.dynmap.debug.BukkitPlayerDebugger;
|
import org.dynmap.debug.BukkitPlayerDebugger;
|
||||||
import org.dynmap.web.WebServer;
|
import org.dynmap.web.WebServer;
|
||||||
|
import org.dynmap.web.handlers.ClientConfigurationHandler;
|
||||||
|
import org.dynmap.web.handlers.ClientUpdateHandler;
|
||||||
|
import org.dynmap.web.handlers.FilesystemHandler;
|
||||||
|
|
||||||
public class DynmapPlugin extends JavaPlugin {
|
public class DynmapPlugin extends JavaPlugin {
|
||||||
|
|
||||||
|
|
@ -54,10 +62,29 @@ public class DynmapPlugin extends JavaPlugin {
|
||||||
mapManager = new MapManager(getWorld(), debugger, configuration);
|
mapManager = new MapManager(getWorld(), debugger, configuration);
|
||||||
mapManager.startManager();
|
mapManager.startManager();
|
||||||
|
|
||||||
|
InetAddress bindAddress;
|
||||||
|
{
|
||||||
|
String address = configuration.getString("webserver-bindaddress", "0.0.0.0");
|
||||||
|
try {
|
||||||
|
bindAddress = address.equals("0.0.0.0")
|
||||||
|
? null
|
||||||
|
: InetAddress.getByName(address);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
bindAddress = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int port = configuration.getInt("webserver-port", 8123);
|
||||||
|
|
||||||
|
webServer = new WebServer(bindAddress, port);
|
||||||
|
webServer.handlers.put("/", new FilesystemHandler(mapManager.webDirectory));
|
||||||
|
webServer.handlers.put("/tiles/", new FilesystemHandler(mapManager.tileDirectory));
|
||||||
|
webServer.handlers.put("/up/", new ClientUpdateHandler(mapManager, playerList, getWorld()));
|
||||||
|
webServer.handlers.put("/up/configuration", new ClientConfigurationHandler((Map<?, ?>) configuration.getProperty("web")));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webServer = new WebServer(mapManager, getWorld(), playerList, debugger, configuration);
|
webServer.startServer();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.info("position failed to start WebServer (IOException)");
|
log.severe("Failed to start WebServer on " + bindAddress + ":" + port + "!");
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEvents();
|
registerEvents();
|
||||||
|
|
|
||||||
|
|
@ -4,42 +4,30 @@ import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.util.config.ConfigurationNode;
|
|
||||||
import org.dynmap.MapManager;
|
|
||||||
import org.dynmap.PlayerList;
|
|
||||||
import org.dynmap.debug.Debugger;
|
|
||||||
|
|
||||||
public class WebServer extends Thread {
|
public class WebServer extends Thread {
|
||||||
|
|
||||||
public static final String VERSION = "Huncraft";
|
|
||||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||||
|
|
||||||
private Debugger debugger;
|
|
||||||
|
|
||||||
private ServerSocket sock = null;
|
private ServerSocket sock = null;
|
||||||
private boolean running = false;
|
private boolean running = false;
|
||||||
|
|
||||||
private MapManager mgr;
|
private InetAddress bindAddress;
|
||||||
private World world;
|
private int port;
|
||||||
private PlayerList playerList;
|
|
||||||
private ConfigurationNode configuration;
|
|
||||||
|
|
||||||
public WebServer(MapManager mgr, World world, PlayerList playerList, Debugger debugger, ConfigurationNode configuration) throws IOException {
|
public SortedMap<String, HttpHandler> handlers = new TreeMap<String, HttpHandler>(Collections.reverseOrder());
|
||||||
this.mgr = mgr;
|
|
||||||
this.world = world;
|
|
||||||
this.playerList = playerList;
|
|
||||||
this.configuration = configuration;
|
|
||||||
this.debugger = debugger;
|
|
||||||
|
|
||||||
String bindAddress = configuration.getString("webserver-bindaddress", "0.0.0.0");
|
public WebServer(InetAddress bindAddress, int port) {
|
||||||
int port = configuration.getInt("webserver-port", 8123);
|
this.bindAddress = bindAddress;
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
sock = new ServerSocket(port, 5, bindAddress.equals("0.0.0.0")
|
public void startServer() throws IOException {
|
||||||
? null
|
sock = new ServerSocket(port, 5, bindAddress);
|
||||||
: InetAddress.getByName(bindAddress));
|
|
||||||
running = true;
|
running = true;
|
||||||
start();
|
start();
|
||||||
log.info("Dynmap WebServer started on " + bindAddress + ":" + port);
|
log.info("Dynmap WebServer started on " + bindAddress + ":" + port);
|
||||||
|
|
@ -50,7 +38,7 @@ public class WebServer extends Thread {
|
||||||
while (running) {
|
while (running) {
|
||||||
try {
|
try {
|
||||||
Socket socket = sock.accept();
|
Socket socket = sock.accept();
|
||||||
WebServerRequest requestThread = new WebServerRequest(socket, mgr, world, playerList, configuration, debugger);
|
WebServerRequest requestThread = new WebServerRequest(socket, this);
|
||||||
requestThread.start();
|
requestThread.start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.info("map WebServer.run() stops with IOException");
|
log.info("map WebServer.run() stops with IOException");
|
||||||
|
|
@ -59,7 +47,7 @@ public class WebServer extends Thread {
|
||||||
}
|
}
|
||||||
log.info("map WebServer run() exiting");
|
log.info("map WebServer run() exiting");
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
debugger.error("Exception on WebServer-thread: " + ex.toString());
|
log.log(Level.SEVERE, "Exception on WebServer-thread", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,78 +1,32 @@
|
||||||
package org.dynmap.web;
|
package org.dynmap.web;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.Reader;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.SortedMap;
|
import java.util.logging.Level;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.util.config.ConfigurationNode;
|
|
||||||
import org.dynmap.ChatQueue;
|
|
||||||
import org.dynmap.MapManager;
|
|
||||||
import org.dynmap.PlayerList;
|
|
||||||
import org.dynmap.TileUpdate;
|
|
||||||
import org.dynmap.debug.Debugger;
|
|
||||||
|
|
||||||
public class WebServerRequest extends Thread {
|
public class WebServerRequest extends Thread {
|
||||||
protected static final Logger log = Logger.getLogger("Minecraft");
|
protected static final Logger log = Logger.getLogger("Minecraft");
|
||||||
|
|
||||||
private Debugger debugger;
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private MapManager mgr;
|
private WebServer server;
|
||||||
private World world;
|
|
||||||
private PlayerList playerList;
|
|
||||||
private ConfigurationNode configuration;
|
|
||||||
|
|
||||||
public SortedMap<String, HttpHandler> handlers = new TreeMap<String, HttpHandler>(Collections.reverseOrder());
|
public WebServerRequest(Socket socket, WebServer server) {
|
||||||
|
|
||||||
public WebServerRequest(Socket socket, MapManager mgr, World world, PlayerList playerList, ConfigurationNode configuration, Debugger debugger) {
|
|
||||||
this.debugger = debugger;
|
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.mgr = mgr;
|
this.server = server;
|
||||||
this.world = world;
|
|
||||||
this.playerList = playerList;
|
|
||||||
this.configuration = configuration;
|
|
||||||
|
|
||||||
handlers.put("/", new FilesystemHandler(mgr.webDirectory));
|
|
||||||
handlers.put("/tiles/", new FilesystemHandler(mgr.tileDirectory));
|
|
||||||
handlers.put("/up/", new ClientUpdateHandler());
|
|
||||||
handlers.put("/up/configuration", new ClientConfigurationHandler());
|
|
||||||
handlers.put("/test/", new HttpHandler() {
|
|
||||||
@Override
|
|
||||||
public void handle(String path, HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
response.fields.put("Content-Type", "text/plain");
|
|
||||||
BufferedOutputStream s = new BufferedOutputStream(response.getBody());
|
|
||||||
s.write("test".getBytes());
|
|
||||||
s.flush();
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Pattern requestHeaderLine = Pattern.compile("^(\\S+)\\s+(\\S+)\\s+HTTP/(.+)$");
|
private static Pattern requestHeaderLine = Pattern.compile("^(\\S+)\\s+(\\S+)\\s+HTTP/(.+)$");
|
||||||
private static Pattern requestHeaderField = Pattern.compile("^([^:]+):\\s*(.+)$");
|
private static Pattern requestHeaderField = Pattern.compile("^([^:]+):\\s*(.+)$");
|
||||||
|
|
||||||
private static boolean readRequestHeader(InputStream in, HttpRequest request) throws IOException {
|
private static boolean readRequestHeader(InputStream in, HttpRequest request) throws IOException {
|
||||||
BufferedReader r = new BufferedReader(new InputStreamReader(in));
|
BufferedReader r = new BufferedReader(new InputStreamReader(in));
|
||||||
Matcher m = requestHeaderLine.matcher(r.readLine());
|
Matcher m = requestHeaderLine.matcher(r.readLine());
|
||||||
|
|
@ -83,7 +37,7 @@ public class WebServerRequest extends Thread {
|
||||||
request.version = m.group(3);
|
request.version = m.group(3);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
while((line = r.readLine()) != null) {
|
while ((line = r.readLine()) != null) {
|
||||||
if (line.equals(""))
|
if (line.equals(""))
|
||||||
break;
|
break;
|
||||||
m = requestHeaderField.matcher(line);
|
m = requestHeaderField.matcher(line);
|
||||||
|
|
@ -108,7 +62,7 @@ public class WebServerRequest extends Thread {
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
sb.append(response.statusMessage);
|
sb.append(response.statusMessage);
|
||||||
sb.append("\n");
|
sb.append("\n");
|
||||||
for(Entry<String,String> field : response.fields.entrySet()) {
|
for (Entry<String, String> field : response.fields.entrySet()) {
|
||||||
sb.append(field.getKey());
|
sb.append(field.getKey());
|
||||||
sb.append(": ");
|
sb.append(": ");
|
||||||
sb.append(field.getValue());
|
sb.append(field.getValue());
|
||||||
|
|
@ -128,13 +82,13 @@ public class WebServerRequest extends Thread {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize HttpHandler-finding by using a real path-aware tree.
|
// TODO: Optimize HttpHandler-finding by using a real path-aware
|
||||||
|
// tree.
|
||||||
HttpResponse response = null;
|
HttpResponse response = null;
|
||||||
for(Entry<String, HttpHandler> entry : handlers.entrySet()) {
|
for (Entry<String, HttpHandler> entry : server.handlers.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
boolean directoryHandler = key.endsWith("/");
|
boolean directoryHandler = key.endsWith("/");
|
||||||
if (directoryHandler && request.path.startsWith(entry.getKey()) ||
|
if (directoryHandler && request.path.startsWith(entry.getKey()) || !directoryHandler && request.path.equals(entry.getKey())) {
|
||||||
!directoryHandler && request.path.equals(entry.getKey())) {
|
|
||||||
String path = request.path.substring(entry.getKey().length());
|
String path = request.path.substring(entry.getKey().length());
|
||||||
|
|
||||||
response = new HttpResponse(socket.getOutputStream());
|
response = new HttpResponse(socket.getOutputStream());
|
||||||
|
|
@ -162,153 +116,21 @@ public class WebServerRequest extends Thread {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
try { socket.close(); } catch(IOException ex) { }
|
if (socket != null) {
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
try { socket.close(); } catch(IOException ex) { }
|
if (socket != null) {
|
||||||
debugger.error("Exception on WebRequest-thread: " + e.toString());
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.log(Level.SEVERE, "Exception while handling request: ", e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String stringifyJson(Object o) {
|
|
||||||
if (o == null) {
|
|
||||||
return "null";
|
|
||||||
} else if (o instanceof Boolean) {
|
|
||||||
return ((Boolean) o) ? "true" : "false";
|
|
||||||
} else if (o instanceof String) {
|
|
||||||
return "\"" + o + "\"";
|
|
||||||
} else if (o instanceof Integer || o instanceof Long || o instanceof Float || o instanceof Double) {
|
|
||||||
return o.toString();
|
|
||||||
} else if (o instanceof LinkedHashMap<?, ?>) {
|
|
||||||
LinkedHashMap<?, ?> m = (LinkedHashMap<?, ?>) o;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("{");
|
|
||||||
boolean first = true;
|
|
||||||
for (Object key : m.keySet()) {
|
|
||||||
if (first)
|
|
||||||
first = false;
|
|
||||||
else
|
|
||||||
sb.append(",");
|
|
||||||
|
|
||||||
sb.append(stringifyJson(key));
|
|
||||||
sb.append(": ");
|
|
||||||
sb.append(stringifyJson(m.get(key)));
|
|
||||||
}
|
|
||||||
sb.append("}");
|
|
||||||
return sb.toString();
|
|
||||||
} else if (o instanceof ArrayList<?>) {
|
|
||||||
ArrayList<?> l = (ArrayList<?>) o;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < l.size(); i++) {
|
|
||||||
sb.append(count++ == 0 ? "[" : ",");
|
|
||||||
sb.append(stringifyJson(l.get(i)));
|
|
||||||
}
|
|
||||||
sb.append("]");
|
|
||||||
return sb.toString();
|
|
||||||
} else {
|
|
||||||
return "undefined";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ClientConfigurationHandler implements HttpHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(String path, HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
String s = stringifyJson(configuration.getProperty("web"));
|
|
||||||
|
|
||||||
byte[] bytes = s.getBytes();
|
|
||||||
String dateStr = new Date().toString();
|
|
||||||
|
|
||||||
response.fields.put("Date", dateStr);
|
|
||||||
response.fields.put("Content-Type", "text/plain");
|
|
||||||
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
|
|
||||||
response.fields.put("Last-modified", dateStr);
|
|
||||||
response.fields.put("Content-Length", Integer.toString(bytes.length));
|
|
||||||
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
|
|
||||||
out.write(s.getBytes());
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ClientUpdateHandler implements HttpHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(String path, HttpRequest request, HttpResponse response) throws IOException {
|
|
||||||
int current = (int) (System.currentTimeMillis() / 1000);
|
|
||||||
long cutoff = 0;
|
|
||||||
|
|
||||||
if (path.length() > 0) {
|
|
||||||
try {
|
|
||||||
cutoff = ((long) Integer.parseInt(path)) * 1000;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
long relativeTime = world.getTime() % 24000;
|
|
||||||
sb.append(current + " " + relativeTime + "\n");
|
|
||||||
|
|
||||||
Player[] players = playerList.getVisiblePlayers();
|
|
||||||
for (Player player : players) {
|
|
||||||
sb.append("player " + player.getName() + " " + player.getLocation().getX() + " " + player.getLocation().getY() + " " + player.getLocation().getZ() + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
TileUpdate[] tileUpdates = mgr.staleQueue.getTileUpdates(cutoff);
|
|
||||||
for (TileUpdate tu : tileUpdates) {
|
|
||||||
sb.append("tile " + tu.tile.getName() + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatQueue.ChatMessage[] messages = mgr.chatQueue.getChatMessages(cutoff);
|
|
||||||
for (ChatQueue.ChatMessage cu : messages) {
|
|
||||||
sb.append("chat " + cu.playerName + " " + cu.message + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
debugger.debug("Sending " + players.length + " players, " + tileUpdates.length + " tile-updates, and " + messages.length + " chats. " + path + ";" + cutoff);
|
|
||||||
|
|
||||||
byte[] bytes = sb.toString().getBytes();
|
|
||||||
|
|
||||||
String dateStr = new Date().toString();
|
|
||||||
response.fields.put("Date", dateStr);
|
|
||||||
response.fields.put("Content-Type", "text/plain");
|
|
||||||
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
|
|
||||||
response.fields.put("Last-modified", dateStr);
|
|
||||||
response.fields.put("Content-Length", Integer.toString(bytes.length));
|
|
||||||
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
|
|
||||||
out.write(bytes);
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class JarFileHandler extends FileHandler {
|
|
||||||
private String root;
|
|
||||||
public JarFileHandler(String root) {
|
|
||||||
if (root.endsWith("/")) root = root.substring(0, root.length()-1);
|
|
||||||
this.root = root;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected InputStream getFileInput(String path) {
|
|
||||||
return this.getClass().getResourceAsStream(root + "/" + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FilesystemHandler extends FileHandler {
|
|
||||||
private File root;
|
|
||||||
public FilesystemHandler(File root) {
|
|
||||||
if (!root.isDirectory())
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
this.root = root;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected InputStream getFileInput(String path) {
|
|
||||||
File file = new File(root, path);
|
|
||||||
if (file.getAbsolutePath().startsWith(root.getAbsolutePath()) && file.isFile()) {
|
|
||||||
try {
|
|
||||||
return new FileInputStream(file);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.dynmap.web.handlers;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.dynmap.web.HttpHandler;
|
||||||
|
import org.dynmap.web.HttpRequest;
|
||||||
|
import org.dynmap.web.HttpResponse;
|
||||||
|
|
||||||
|
public class ClientConfigurationHandler implements HttpHandler {
|
||||||
|
private Map<?, ?> configuration;
|
||||||
|
public ClientConfigurationHandler(Map<?, ?> configuration) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void handle(String path, HttpRequest request, HttpResponse response) throws IOException {
|
||||||
|
String s = stringifyJson(configuration);
|
||||||
|
|
||||||
|
byte[] bytes = s.getBytes();
|
||||||
|
String dateStr = new Date().toString();
|
||||||
|
|
||||||
|
response.fields.put("Date", dateStr);
|
||||||
|
response.fields.put("Content-Type", "text/plain");
|
||||||
|
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
|
||||||
|
response.fields.put("Last-modified", dateStr);
|
||||||
|
response.fields.put("Content-Length", Integer.toString(bytes.length));
|
||||||
|
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
|
||||||
|
out.write(s.getBytes());
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String stringifyJson(Object o) {
|
||||||
|
if (o == null) {
|
||||||
|
return "null";
|
||||||
|
} else if (o instanceof Boolean) {
|
||||||
|
return ((Boolean) o) ? "true" : "false";
|
||||||
|
} else if (o instanceof String) {
|
||||||
|
return "\"" + o + "\"";
|
||||||
|
} else if (o instanceof Integer || o instanceof Long || o instanceof Float || o instanceof Double) {
|
||||||
|
return o.toString();
|
||||||
|
} else if (o instanceof LinkedHashMap<?, ?>) {
|
||||||
|
LinkedHashMap<?, ?> m = (LinkedHashMap<?, ?>) o;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("{");
|
||||||
|
boolean first = true;
|
||||||
|
for (Object key : m.keySet()) {
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
sb.append(",");
|
||||||
|
|
||||||
|
sb.append(stringifyJson(key));
|
||||||
|
sb.append(": ");
|
||||||
|
sb.append(stringifyJson(m.get(key)));
|
||||||
|
}
|
||||||
|
sb.append("}");
|
||||||
|
return sb.toString();
|
||||||
|
} else if (o instanceof ArrayList<?>) {
|
||||||
|
ArrayList<?> l = (ArrayList<?>) o;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < l.size(); i++) {
|
||||||
|
sb.append(count++ == 0 ? "[" : ",");
|
||||||
|
sb.append(stringifyJson(l.get(i)));
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
} else {
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package org.dynmap.web.handlers;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.dynmap.ChatQueue;
|
||||||
|
import org.dynmap.MapManager;
|
||||||
|
import org.dynmap.PlayerList;
|
||||||
|
import org.dynmap.TileUpdate;
|
||||||
|
import org.dynmap.web.HttpHandler;
|
||||||
|
import org.dynmap.web.HttpRequest;
|
||||||
|
import org.dynmap.web.HttpResponse;
|
||||||
|
|
||||||
|
public class ClientUpdateHandler implements HttpHandler {
|
||||||
|
private MapManager mapManager;
|
||||||
|
private PlayerList playerList;
|
||||||
|
private World world;
|
||||||
|
public ClientUpdateHandler(MapManager mapManager, PlayerList playerList, World world) {
|
||||||
|
this.mapManager = mapManager;
|
||||||
|
this.playerList = playerList;
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void handle(String path, HttpRequest request, HttpResponse response) throws IOException {
|
||||||
|
int current = (int) (System.currentTimeMillis() / 1000);
|
||||||
|
long cutoff = 0;
|
||||||
|
|
||||||
|
if (path.length() > 0) {
|
||||||
|
try {
|
||||||
|
cutoff = ((long) Integer.parseInt(path)) * 1000;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
long relativeTime = world.getTime() % 24000;
|
||||||
|
sb.append(current + " " + relativeTime + "\n");
|
||||||
|
|
||||||
|
Player[] players = playerList.getVisiblePlayers();
|
||||||
|
for (Player player : players) {
|
||||||
|
sb.append("player " + player.getName() + " " + player.getLocation().getX() + " " + player.getLocation().getY() + " " + player.getLocation().getZ() + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TileUpdate[] tileUpdates = mapManager.staleQueue.getTileUpdates(cutoff);
|
||||||
|
for (TileUpdate tu : tileUpdates) {
|
||||||
|
sb.append("tile " + tu.tile.getName() + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatQueue.ChatMessage[] messages = mapManager.chatQueue.getChatMessages(cutoff);
|
||||||
|
for (ChatQueue.ChatMessage cu : messages) {
|
||||||
|
sb.append("chat " + cu.playerName + " " + cu.message + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//debugger.debug("Sending " + players.length + " players, " + tileUpdates.length + " tile-updates, and " + messages.length + " chats. " + path + ";" + cutoff);
|
||||||
|
|
||||||
|
byte[] bytes = sb.toString().getBytes();
|
||||||
|
|
||||||
|
String dateStr = new Date().toString();
|
||||||
|
response.fields.put("Date", dateStr);
|
||||||
|
response.fields.put("Content-Type", "text/plain");
|
||||||
|
response.fields.put("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
|
||||||
|
response.fields.put("Last-modified", dateStr);
|
||||||
|
response.fields.put("Content-Length", Integer.toString(bytes.length));
|
||||||
|
BufferedOutputStream out = new BufferedOutputStream(response.getBody());
|
||||||
|
out.write(bytes);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/org/dynmap/web/handlers/FilesystemHandler.java
Normal file
29
src/main/java/org/dynmap/web/handlers/FilesystemHandler.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.dynmap.web.handlers;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.dynmap.web.FileHandler;
|
||||||
|
|
||||||
|
public class FilesystemHandler extends FileHandler {
|
||||||
|
private File root;
|
||||||
|
public FilesystemHandler(File root) {
|
||||||
|
if (!root.isDirectory())
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected InputStream getFileInput(String path) {
|
||||||
|
File file = new File(root, path);
|
||||||
|
if (file.getAbsolutePath().startsWith(root.getAbsolutePath()) && file.isFile()) {
|
||||||
|
try {
|
||||||
|
return new FileInputStream(file);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/java/org/dynmap/web/handlers/JarFileHandler.java
Normal file
17
src/main/java/org/dynmap/web/handlers/JarFileHandler.java
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.dynmap.web.handlers;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.dynmap.web.FileHandler;
|
||||||
|
|
||||||
|
public class JarFileHandler extends FileHandler {
|
||||||
|
private String root;
|
||||||
|
public JarFileHandler(String root) {
|
||||||
|
if (root.endsWith("/")) root = root.substring(0, root.length()-1);
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected InputStream getFileInput(String path) {
|
||||||
|
return this.getClass().getResourceAsStream(root + "/" + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue