2013-08-27 01:48:04 +00:00
|
|
|
package me.StevenLawson.TotalFreedomMod.HTTPD;
|
|
|
|
|
2013-09-03 19:20:28 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
2013-08-27 01:48:04 +00:00
|
|
|
import java.io.IOException;
|
2013-09-03 14:28:56 +00:00
|
|
|
import java.net.Socket;
|
2013-08-27 01:48:04 +00:00
|
|
|
import java.util.Map;
|
2013-08-27 13:01:12 +00:00
|
|
|
import java.util.concurrent.Callable;
|
|
|
|
import java.util.concurrent.Future;
|
2013-09-03 19:20:28 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2013-08-28 00:20:11 +00:00
|
|
|
import static me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.MIME_PLAINTEXT;
|
2013-09-03 19:20:28 +00:00
|
|
|
import me.StevenLawson.TotalFreedomMod.HTTPD.NanoHTTPD.Response;
|
2013-08-28 00:20:11 +00:00
|
|
|
import me.StevenLawson.TotalFreedomMod.TFM_ConfigEntry;
|
2013-08-27 01:48:04 +00:00
|
|
|
import me.StevenLawson.TotalFreedomMod.TFM_Log;
|
2013-08-27 13:01:12 +00:00
|
|
|
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
|
2013-08-27 01:48:04 +00:00
|
|
|
import org.apache.commons.lang.StringUtils;
|
2013-08-27 13:01:12 +00:00
|
|
|
import org.bukkit.Bukkit;
|
2013-08-27 01:48:04 +00:00
|
|
|
|
|
|
|
public class TFM_HTTPD_Manager
|
|
|
|
{
|
2013-09-03 19:20:28 +00:00
|
|
|
private static final Pattern EXT_REGEX = Pattern.compile("\\.([^\\.\\s]+)$");
|
|
|
|
//
|
2013-08-28 00:20:11 +00:00
|
|
|
public static final int PORT = TFM_ConfigEntry.HTTPD_PORT.getInteger();
|
2013-08-27 01:48:04 +00:00
|
|
|
//
|
|
|
|
private final TFM_HTTPD httpd = new TFM_HTTPD(PORT);
|
|
|
|
|
|
|
|
private TFM_HTTPD_Manager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public void start()
|
|
|
|
{
|
2013-08-28 00:20:11 +00:00
|
|
|
if (!TFM_ConfigEntry.HTTPD_ENABLED.getBoolean())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-27 01:48:04 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
httpd.start();
|
2013-08-27 16:39:28 +00:00
|
|
|
|
|
|
|
if (httpd.isAlive())
|
|
|
|
{
|
|
|
|
TFM_Log.info("TFM HTTPd started. Listening on port: " + httpd.getListeningPort());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TFM_Log.info("Error starting TFM HTTPd.");
|
|
|
|
}
|
2013-08-27 01:48:04 +00:00
|
|
|
}
|
|
|
|
catch (IOException ex)
|
|
|
|
{
|
|
|
|
TFM_Log.severe(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void stop()
|
|
|
|
{
|
2013-08-28 00:20:11 +00:00
|
|
|
if (!TFM_ConfigEntry.HTTPD_ENABLED.getBoolean())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-27 01:48:04 +00:00
|
|
|
httpd.stop();
|
2013-08-27 16:39:28 +00:00
|
|
|
|
|
|
|
TFM_Log.info("TFM HTTPd stopped.");
|
2013-08-27 01:48:04 +00:00
|
|
|
}
|
|
|
|
|
2013-08-28 00:20:11 +00:00
|
|
|
private static enum ModuleType
|
|
|
|
{
|
|
|
|
DUMP(false, "dump"),
|
|
|
|
HELP(true, "help"),
|
|
|
|
LIST(true, "list"),
|
2013-09-03 14:28:56 +00:00
|
|
|
FILE(false, "file"),
|
|
|
|
SCHEMATIC(false, "schematic");
|
2013-08-28 00:20:11 +00:00
|
|
|
private final boolean runOnBukkitThread;
|
|
|
|
private final String name;
|
|
|
|
|
|
|
|
private ModuleType(boolean runOnBukkitThread, String name)
|
|
|
|
{
|
|
|
|
this.runOnBukkitThread = runOnBukkitThread;
|
|
|
|
this.name = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isRunOnBukkitThread()
|
|
|
|
{
|
|
|
|
return runOnBukkitThread;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getName()
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static ModuleType getByName(String needle)
|
|
|
|
{
|
|
|
|
for (ModuleType type : values())
|
|
|
|
{
|
|
|
|
if (type.getName().equalsIgnoreCase(needle))
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FILE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 01:48:04 +00:00
|
|
|
private static class TFM_HTTPD extends NanoHTTPD
|
|
|
|
{
|
|
|
|
public TFM_HTTPD(int port)
|
|
|
|
{
|
|
|
|
super(port);
|
|
|
|
}
|
|
|
|
|
|
|
|
public TFM_HTTPD(String hostname, int port)
|
|
|
|
{
|
|
|
|
super(hostname, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2013-09-03 14:28:56 +00:00
|
|
|
public Response serve(
|
|
|
|
final String uri,
|
|
|
|
final Method method,
|
|
|
|
final Map<String, String> headers,
|
|
|
|
final Map<String, String> params,
|
|
|
|
final Map<String, String> files,
|
|
|
|
final Socket socket)
|
2013-08-27 01:48:04 +00:00
|
|
|
{
|
|
|
|
Response response = null;
|
|
|
|
|
|
|
|
final String[] args = StringUtils.split(uri, "/");
|
2013-08-28 00:20:11 +00:00
|
|
|
final ModuleType moduleType = args.length >= 1 ? ModuleType.getByName(args[0]) : ModuleType.FILE;
|
|
|
|
|
|
|
|
if (moduleType.isRunOnBukkitThread())
|
2013-08-27 01:48:04 +00:00
|
|
|
{
|
2013-08-27 13:01:12 +00:00
|
|
|
Future<Response> responseCall = Bukkit.getScheduler().callSyncMethod(TotalFreedomMod.plugin, new Callable<Response>()
|
2013-08-27 01:48:04 +00:00
|
|
|
{
|
2013-08-27 13:01:12 +00:00
|
|
|
@Override
|
|
|
|
public Response call() throws Exception
|
|
|
|
{
|
2013-08-28 00:20:11 +00:00
|
|
|
switch (moduleType)
|
2013-08-27 13:01:12 +00:00
|
|
|
{
|
2013-08-28 00:20:11 +00:00
|
|
|
case HELP:
|
2013-09-03 14:28:56 +00:00
|
|
|
return new Module_help(uri, method, headers, params, files, socket).getResponse();
|
2013-08-28 00:20:11 +00:00
|
|
|
case LIST:
|
2013-09-03 14:28:56 +00:00
|
|
|
return new Module_list(uri, method, headers, params, files, socket).getResponse();
|
2013-08-28 00:20:11 +00:00
|
|
|
default:
|
|
|
|
return null;
|
2013-08-27 13:01:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
try
|
2013-08-27 01:48:04 +00:00
|
|
|
{
|
2013-08-27 13:01:12 +00:00
|
|
|
response = responseCall.get();
|
2013-08-27 01:48:04 +00:00
|
|
|
}
|
2013-08-27 13:01:12 +00:00
|
|
|
catch (Exception ex)
|
2013-08-27 01:48:04 +00:00
|
|
|
{
|
2013-08-27 13:01:12 +00:00
|
|
|
TFM_Log.severe(ex);
|
2013-08-27 01:48:04 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-28 00:20:11 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (moduleType)
|
|
|
|
{
|
|
|
|
case DUMP:
|
2013-09-03 19:20:28 +00:00
|
|
|
//response = new Module_dump(uri, method, headers, params, files, socket).getResponse();
|
|
|
|
response = new Response(Response.Status.OK, MIME_PLAINTEXT, "The DUMP module is disabled. It is intended for debugging use only.");
|
2013-09-03 14:28:56 +00:00
|
|
|
break;
|
|
|
|
case SCHEMATIC:
|
|
|
|
response = new Module_schematic(uri, method, headers, params, files, socket).getResponse();
|
2013-08-28 00:20:11 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-09-03 14:28:56 +00:00
|
|
|
response = new Module_file(uri, method, headers, params, files, socket).getResponse();
|
2013-08-28 00:20:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 01:48:04 +00:00
|
|
|
if (response == null)
|
|
|
|
{
|
|
|
|
return new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Error 404: Not Found - The requested resource was not found on this server.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-03 19:20:28 +00:00
|
|
|
public static Response serveFileBasic(File file)
|
|
|
|
{
|
|
|
|
Response response = null;
|
|
|
|
|
|
|
|
if (file != null && file.exists())
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
String mimetype = null;
|
|
|
|
|
|
|
|
Matcher matcher = EXT_REGEX.matcher(file.getCanonicalPath());
|
|
|
|
if (matcher.find())
|
|
|
|
{
|
|
|
|
mimetype = Module_file.MIME_TYPES.get(matcher.group(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mimetype == null || mimetype.trim().isEmpty())
|
|
|
|
{
|
|
|
|
mimetype = NanoHTTPD.MIME_DEFAULT_BINARY;
|
|
|
|
}
|
|
|
|
|
|
|
|
response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, mimetype, new FileInputStream(file));
|
|
|
|
response.addHeader("Content-Length", "" + file.length());
|
|
|
|
}
|
|
|
|
catch (IOException ex)
|
|
|
|
{
|
|
|
|
TFM_Log.severe(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
2013-08-27 01:48:04 +00:00
|
|
|
public static TFM_HTTPD_Manager getInstance()
|
|
|
|
{
|
|
|
|
return TFM_HTTPDManagerHolder.INSTANCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class TFM_HTTPDManagerHolder
|
|
|
|
{
|
|
|
|
private static final TFM_HTTPD_Manager INSTANCE = new TFM_HTTPD_Manager();
|
|
|
|
}
|
|
|
|
}
|