blob: 0629aebc05f7a677c683f03d4b1a1245319328e6 [file] [log] [blame] [raw]
package net.glowstone;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.logging.Formatter;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import jline.ArgumentCompletor;
import jline.Completor;
import jline.ConsoleReader;
import jline.NullCompletor;
import jline.SimpleCompletor;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandException;
import org.bukkit.command.ConsoleCommandSender;
/**
* A meta-class to handle all logging and input-related console improvements.
* Portions are heavily based on CraftBukkit.
*/
public class ConsoleManager {
private GlowServer server;
private ConsoleReader reader;
private ConsoleCommandSender sender;
private ConsoleCommandThread thread;
private LoggingConsoleHandler handler;
private boolean running = true;
private boolean fancy = true;
public ConsoleManager(GlowServer server, boolean fancy) {
this.server = server;
this.fancy = fancy;
sender = new ColoredCommandSender();
thread = new ConsoleCommandThread();
handler = new LoggingConsoleHandler();
handler.setFormatter(new DateOutputFormatter(new SimpleDateFormat()));
Logger logger = server.getLogger();
logger.setUseParentHandlers(false);
logger.addHandler(handler);
Logger global = Logger.getLogger("");
for (Handler handler: global.getHandlers()) {
global.removeHandler(handler);
}
global.addHandler(handler);
try {
reader = new ConsoleReader();
} catch (IOException ex) {
server.getLogger().log(Level.SEVERE, "Exception inintializing console reader: {0}", ex.getMessage());
ex.printStackTrace();
}
Runtime.getRuntime().addShutdownHook(new ServerShutdownThread());
thread.setDaemon(true);
thread.start();
System.setOut(new PrintStream(new LoggerOutputStream(Level.INFO), true));
System.setErr(new PrintStream(new LoggerOutputStream(Level.SEVERE), true));
}
public void stop() {
running = false;
}
public void refreshCommands() {
for (Object c : new ArrayList(reader.getCompletors())) {
reader.removeCompletor((Completor) c);
}
Completor[] list = new Completor[] { new SimpleCompletor(server.getAllCommands()), new NullCompletor() };
reader.addCompletor(new ArgumentCompletor(list));
}
public String colorize(String string) {
if (!string.contains("\u00A7")) {
return string;
} else if (!fancy || !reader.getTerminal().isANSISupported()) {
return ChatColor.stripColor(string);
} else {
return string.replace(ChatColor.RED.toString(), "\033[1;31m")
.replace(ChatColor.YELLOW.toString(), "\033[1;33m")
.replace(ChatColor.GREEN.toString(), "\033[1;32m")
.replace(ChatColor.AQUA.toString(), "\033[1;36m")
.replace(ChatColor.BLUE.toString(), "\033[1;34m")
.replace(ChatColor.LIGHT_PURPLE.toString(), "\033[1;35m")
.replace(ChatColor.BLACK.toString(), "\033[0;0m")
.replace(ChatColor.DARK_GRAY.toString(), "\033[1;30m")
.replace(ChatColor.DARK_RED.toString(), "\033[0;31m")
.replace(ChatColor.GOLD.toString(), "\033[0;33m")
.replace(ChatColor.DARK_GREEN.toString(), "\033[0;32m")
.replace(ChatColor.DARK_AQUA.toString(), "\033[0;36m")
.replace(ChatColor.DARK_BLUE.toString(), "\033[0;34m")
.replace(ChatColor.DARK_PURPLE.toString(), "\033[0;35m")
.replace(ChatColor.GRAY.toString(), "\033[0;37m")
.replace(ChatColor.WHITE.toString(), "\033[1;37m") +
"\033[0m";
}
}
private class ConsoleCommandThread extends Thread {
@Override
public void run() {
String command;
while (running) {
try {
if (fancy) {
command = reader.readLine(">", null);
} else {
command = reader.readLine();
}
if (command == null || command.trim().length() == 0)
continue;
server.getScheduler().scheduleSyncDelayedTask(null, new CommandTask(command.trim()));
}
catch (CommandException ex) {
System.out.println("Exception while executing command: " + ex.getMessage());
ex.printStackTrace();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
private class ServerShutdownThread extends Thread {
@Override
public void run() {
server.stop();
}
}
private class CommandTask implements Runnable {
private String command;
public CommandTask(String command) {
this.command = command;
}
public void run() {
if (!server.dispatchCommand(sender, command)) {
String firstword = command;
if (command.indexOf(' ') >= 0) {
firstword = command.substring(0, command.indexOf(' '));
}
System.out.println("Command not found: " + firstword);
}
}
}
private class ColoredCommandSender extends ConsoleCommandSender {
public ColoredCommandSender() {
super(server);
}
@Override
public void sendMessage(String text) {
server.getLogger().info(text);
}
}
private class LoggerOutputStream extends ByteArrayOutputStream {
private final String separator = System.getProperty("line.separator");
private final Level level;
public LoggerOutputStream(Level level) {
super();
this.level = level;
}
@Override
public synchronized void flush() throws IOException {
super.flush();
String record = this.toString();
super.reset();
if (record.length() > 0 && !record.equals(separator)) {
server.getLogger().logp(level, "LoggerOutputStream", "log" + level, record);
}
}
}
private class LoggingConsoleHandler extends ConsoleHandler {
public LoggingConsoleHandler() {
//setOutputStream(System.out);
}
@Override
public synchronized void flush() {
try {
if (fancy) {
reader.printString(ConsoleReader.RESET_LINE + "");
reader.flushConsole();
super.flush();
try {
reader.drawLine();
} catch (Throwable ex) {
reader.getCursorBuffer().clearBuffer();
}
reader.flushConsole();
} else {
super.flush();
}
} catch (IOException ex) {
server.getLogger().severe("I/O exception flushing console output");
ex.printStackTrace();
}
}
}
private class DateOutputFormatter extends Formatter {
private SimpleDateFormat date;
public DateOutputFormatter(SimpleDateFormat date) {
this.date = date;
}
@Override
public String format(LogRecord record) {
StringBuilder builder = new StringBuilder();
builder.append(date.format(record.getMillis()));
builder.append(" [");
builder.append(record.getLevel().getLocalizedName().toUpperCase());
builder.append("] ");
builder.append(colorize(formatMessage(record)));
builder.append('\n');
if (record.getThrown() != null) {
StringWriter writer = new StringWriter();
record.getThrown().printStackTrace(new PrintWriter(writer));
builder.append(writer.toString());
}
return builder.toString();
}
}
}