TFM-4.3-Reloaded/src/main/java/me/totalfreedom/totalfreedommod/httpd/HTTPDaemon.java
JeromSar e93ac11172 Use custom service abstraction in favour of Aero's AbstractService
Use Aero's YamlConfig in favour of FConfig
Refractoring
Small edits
2016-03-01 17:47:01 +01:00

293 lines
8.5 KiB
Java

package me.totalfreedom.totalfreedommod.httpd;
import me.totalfreedom.totalfreedommod.httpd.module.Module_help;
import me.totalfreedom.totalfreedommod.httpd.module.Module_file;
import me.totalfreedom.totalfreedommod.httpd.module.Module_schematic;
import me.totalfreedom.totalfreedommod.httpd.module.Module_permbans;
import me.totalfreedom.totalfreedommod.httpd.module.Module_players;
import me.totalfreedom.totalfreedommod.httpd.module.Module_logs;
import me.totalfreedom.totalfreedommod.httpd.module.Module_list;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD.HTTPSession;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD.Response;
import me.totalfreedom.totalfreedommod.util.FLog;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bukkit.Bukkit;
public class HTTPDaemon extends FreedomService
{
public static String MIME_DEFAULT_BINARY = "application/octet-stream";
//
private static final Pattern EXT_REGEX = Pattern.compile("\\.([^\\.\\s]+)$");
//
public static final int PORT = ConfigEntry.HTTPD_PORT.getInteger();
//
private static final TFM_HTTPD HTTPD = new TFM_HTTPD(PORT);
public HTTPDaemon(TotalFreedomMod plugin)
{
super(plugin);
}
@Override
public void onStart()
{
if (!ConfigEntry.HTTPD_ENABLED.getBoolean())
{
return;
}
try
{
HTTPD.start();
if (HTTPD.isAlive())
{
FLog.info("TFM HTTPd started. Listening on port: " + HTTPD.getListeningPort());
}
else
{
FLog.info("Error starting TFM HTTPd.");
}
}
catch (IOException ex)
{
FLog.severe(ex);
}
}
@Override
public void onStop()
{
if (!ConfigEntry.HTTPD_ENABLED.getBoolean())
{
return;
}
HTTPD.stop();
FLog.info("TFM HTTPd stopped.");
}
private static enum ModuleType
{
DUMP(new ModuleExecutable(false, "dump")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Response(Response.Status.OK, NanoHTTPD.MIME_PLAINTEXT, "The DUMP module is disabled. It is intended for debugging use only.");
}
}),
HELP(new ModuleExecutable(true, "help")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_help(session).getResponse();
}
}),
LIST(new ModuleExecutable(true, "list")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_list(session).getResponse();
}
}),
FILE(new ModuleExecutable(false, "file")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_file(session).getResponse();
}
}),
SCHEMATIC(new ModuleExecutable(false, "schematic")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_schematic(session).getResponse();
}
}),
PERMBANS(new ModuleExecutable(false, "permbans")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_permbans(session).getResponse();
}
}),
PLAYERS(new ModuleExecutable(true, "players")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_players(session).getResponse();
}
}),
LOGS(new ModuleExecutable(false, "logs")
{
@Override
public Response getResponse(HTTPSession session)
{
return new Module_logs(session).getResponse();
}
});
//
private final ModuleExecutable moduleExecutable;
private ModuleType(ModuleExecutable moduleExecutable)
{
this.moduleExecutable = moduleExecutable;
}
private abstract static class ModuleExecutable
{
private final boolean runOnBukkitThread;
private final String name;
private ModuleExecutable(boolean runOnBukkitThread, String name)
{
this.runOnBukkitThread = runOnBukkitThread;
this.name = name;
}
public Response execute(final HTTPSession session)
{
try
{
if (this.runOnBukkitThread)
{
return Bukkit.getScheduler().callSyncMethod(TotalFreedomMod.plugin, new Callable<Response>()
{
@Override
public Response call() throws Exception
{
return getResponse(session);
}
}).get();
}
else
{
return getResponse(session);
}
}
catch (Exception ex)
{
FLog.severe(ex);
}
return null;
}
public abstract Response getResponse(HTTPSession session);
public String getName()
{
return name;
}
}
public ModuleExecutable getModuleExecutable()
{
return moduleExecutable;
}
private static ModuleType getByName(String needle)
{
for (ModuleType type : values())
{
if (type.getModuleExecutable().getName().equalsIgnoreCase(needle))
{
return type;
}
}
return FILE;
}
}
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
public Response serve(HTTPSession session)
{
Response response;
try
{
final String[] args = StringUtils.split(session.getUri(), "/");
final ModuleType moduleType = args.length >= 1 ? ModuleType.getByName(args[0]) : ModuleType.FILE;
response = moduleType.getModuleExecutable().execute(session);
}
catch (Exception ex)
{
response = new Response(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "Error 500: Internal Server Error\r\n" + ex.getMessage() + "\r\n" + ExceptionUtils.getStackTrace(ex));
}
if (response == null)
{
response = new Response(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "Error 404: Not Found - The requested resource was not found on this server.");
}
return response;
}
}
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 = MIME_DEFAULT_BINARY;
}
response = new Response(Response.Status.OK, mimetype, new FileInputStream(file));
response.addHeader("Content-Length", "" + file.length());
}
catch (IOException ex)
{
FLog.severe(ex);
}
}
return response;
}
}