diff --git a/build.gradle b/build.gradle index 0f4fca2..29acc7b 100644 --- a/build.gradle +++ b/build.gradle @@ -93,6 +93,7 @@ compileCommon 'com.lmax:disruptor:3.2.1' compileCommon 'org.apache.commons:commons-dbcp2:2.1.1' compileCommon 'net.openhft:koloboke-api-jdk8:0.6.8' + compileServer 'jline:jline:2.13', {transitive = false} runtimeCommon 'net.openhft:koloboke-impl-jdk8:0.6.8' runtime 'mysql:mysql-connector-java:5.1.31' diff --git a/src/main/java/cpw/mods/fml/relauncher/ServerLaunchWrapper.java b/src/main/java/cpw/mods/fml/relauncher/ServerLaunchWrapper.java index ef86365..1e335b8 100644 --- a/src/main/java/cpw/mods/fml/relauncher/ServerLaunchWrapper.java +++ b/src/main/java/cpw/mods/fml/relauncher/ServerLaunchWrapper.java @@ -1,5 +1,7 @@ package cpw.mods.fml.relauncher; +import org.ultramine.server.bootstrap.UMBootstrap; + import java.lang.reflect.Method; public class ServerLaunchWrapper { @@ -19,9 +21,7 @@ private void run(String[] args) { - boolean useUMConsole = Boolean.parseBoolean(System.getProperty("org.ultramine.server.umconsole")); - System.out.println((useUMConsole ? "\u00A7e" : "") + "================[ Starting UltraMine server ]================"); - System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"); //always async logging + UMBootstrap.handleFirstLine(args); Class launchwrapper = null; try diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index ece8157..c992463 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -34,7 +34,6 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; import javax.imageio.ImageIO; @@ -85,7 +84,8 @@ import org.ultramine.server.BackupManager; import org.ultramine.server.ConfigurationHandler; import org.ultramine.server.WatchdogThread; -import org.ultramine.server.util.GlobalExecutors; +import org.ultramine.server.bootstrap.UMBootstrap; +import org.ultramine.server.internal.ChatComponentLogMessage; import org.ultramine.server.world.MultiWorld; import net.minecraftforge.common.DimensionManager; @@ -401,7 +401,7 @@ if (normalStarted = startServer()) { FMLCommonHandler.instance().handleServerStarted(); - logger.info((useUMConsole ? "\u00a7e" : "") + "Server loading totally finished"); + logger.info((UMBootstrap.isColoredTerminal() ? "\u00a7e" : "") + "Server loading totally finished"); long i = getSystemTimeMillis(); long l = 0L; this.field_147147_p.func_151315_a(new ChatComponentText(this.motd)); @@ -881,7 +881,7 @@ public void addChatMessage(IChatComponent p_145747_1_) { - logger.info(useUMConsole ? p_145747_1_.getFormattedText() : p_145747_1_.getUnformattedText()); + logger.info(new ChatComponentLogMessage(p_145747_1_)); } public boolean canCommandSenderUseCommand(int p_70003_1_, String p_70003_2_) @@ -1497,7 +1497,6 @@ /* ========================================= ULTRAMINE START ======================================*/ - private static final boolean useUMConsole = Boolean.parseBoolean(System.getProperty("org.ultramine.server.umconsole")); private static final int TPS = 20; private static final int TICK_TIME = 1000000000 / TPS; public double currentTPS = 20; diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java index 780ce26..1bcfb57 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -49,6 +49,8 @@ import org.ultramine.server.PermissionHandler; import org.ultramine.server.UltramineServerConfig; import org.ultramine.server.WorldsConfig.WorldConfig; +import org.ultramine.server.bootstrap.UMBootstrap; +import org.ultramine.server.internal.JLineSupport; import org.ultramine.server.util.BasicTypeParser; import org.ultramine.server.util.GlobalExecutors; @@ -100,7 +102,7 @@ protected boolean startServer() throws IOException { - Thread thread = new Thread("Server console handler") + Thread thread = UMBootstrap.isJLine() ? JLineSupport.setupReadingThread(this) : new Thread("Server console handler") { private static final String __OBFID = "CL_00001786"; public void run() diff --git a/src/main/java/org/ultramine/server/UltraminePlugin.java b/src/main/java/org/ultramine/server/UltraminePlugin.java index b132229..9e2092a 100644 --- a/src/main/java/org/ultramine/server/UltraminePlugin.java +++ b/src/main/java/org/ultramine/server/UltraminePlugin.java @@ -43,8 +43,11 @@ location = (File)data.get("coremodLocation"); isObfEnv = (Boolean)data.get("runtimeDeobfuscationEnabled"); LaunchClassLoader cl = (LaunchClassLoader)this.getClass().getClassLoader(); + cl.addClassLoaderExclusion("org.ultramine.server.bootstrap."); cl.addTransformerExclusion("org.ultramine.server.asm."); + cl.addClassLoaderExclusion("jline."); + cl.addClassLoaderExclusion("org.fusesource.jansi."); cl.addTransformerExclusion("org.yaml.snakeyaml."); cl.addTransformerExclusion("com.lmax.disruptor."); cl.addTransformerExclusion("org.apache.commons.dbcp2."); diff --git a/src/main/java/org/ultramine/server/bootstrap/UMBootstrap.java b/src/main/java/org/ultramine/server/bootstrap/UMBootstrap.java new file mode 100644 index 0000000..93e602d --- /dev/null +++ b/src/main/java/org/ultramine/server/bootstrap/UMBootstrap.java @@ -0,0 +1,132 @@ +package org.ultramine.server.bootstrap; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import jline.console.ConsoleReader; + +import java.io.IOException; + +public class UMBootstrap +{ + private static boolean isJLine; + private static boolean isColoredConsole; + private static boolean isAnsiColors; + private static String charset; + + @SideOnly(Side.SERVER) + private static ConsoleReader reader; + + public static boolean isJLine() + { + return isJLine; + } + + public static boolean isColoredTerminal() + { + return isColoredConsole; + } + + public static boolean isAnsiColors() + { + return isAnsiColors; + } + + public static String getTerminalCharset() + { + return charset; + } + + @SideOnly(Side.SERVER) + public static ConsoleReader getJLineReader() + { + return reader; + } + + @SideOnly(Side.SERVER) + public static void handleFirstLine(String[] args) + { + setSysPropertyIfNotPresent("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"); //always async logging + + setupTerminal(args); + + showGreeting(); + } + + @SideOnly(Side.SERVER) + private static void setupTerminal(String[] args) + { + // -Dorg.ultramine.terminal= + // default - strip all minecraft control codes + // raw - leaves the original minecraft codes with \u00a7 + [0-9k-or] + // ansi - replaces minecraft codes with ANSI control sequences + // jline - same as 'ansi' + JLine ConsoleReader + String terminal = System.getProperty("org.ultramine.terminal", contains(args, "nojline") ? "default" : "jline").toLowerCase(); + isJLine = terminal.equals("jline") && System.console() != null; + if(isJLine) + { + setupJLine(); + } + else + { + setSysPropertyIfNotPresent("log4j.skipJansi", "true"); + isAnsiColors = terminal.equals("ansi"); + isColoredConsole = isAnsiColors || terminal.equals("raw"); + } + charset = System.getProperty("org.ultramine.terminal.charset", charset); + } + + @SideOnly(Side.SERVER) + private static void setupJLine() + { + try + { + reader = new ConsoleReader(System.in, System.out); + reader.setExpandEvents(false); // Avoid parsing exceptions for uncommonly used event designators + isAnsiColors = isColoredConsole = reader.getTerminal().isAnsiSupported(); + charset = reader.getTerminal().getOutputEncoding(); + } + catch (Throwable e) + { + isAnsiColors = isColoredConsole = isJLine = false; + System.err.println("Failed to setup Jline. Add flag '-Dorg.ultramine.terminal=default' to disable"); + e.printStackTrace(); + try + { + // Try again with jline disabled for Windows users without C++ 2008 Redistributable + System.setProperty("jline.terminal", "jline.UnsupportedTerminal"); + System.setProperty("user.language", "en"); + reader = new ConsoleReader(System.in, System.out); + reader.setExpandEvents(false); + } + catch (IOException ignored) {} + } + } + + @SideOnly(Side.SERVER) + private static void showGreeting() + { + String yellow_ansi = "\u001b\u005b\u0030\u003b\u0033\u0033\u003b\u0031\u006d"; + String reset_ansi = "\u001b\u005b\u006d"; + System.out.println( + (isColoredTerminal() ? isAnsiColors() ? yellow_ansi : "\u00A7e" : "") + + "================[ Starting UltraMine server ]================" + + (isAnsiColors() ? reset_ansi : "") + ); + } + + @SideOnly(Side.SERVER) + private static boolean contains(String[] args, String search) + { + for(String arg : args) + if(arg.contains(search)) + return true; + return false; + } + + @SideOnly(Side.SERVER) + private static void setSysPropertyIfNotPresent(String key, String val) + { + if(System.getProperty(key, null) == null) + System.setProperty(key, val); + } +} diff --git a/src/main/java/org/ultramine/server/bootstrap/log4j/UMConsoleLayout.java b/src/main/java/org/ultramine/server/bootstrap/log4j/UMConsoleLayout.java new file mode 100644 index 0000000..3f5f32c --- /dev/null +++ b/src/main/java/org/ultramine/server/bootstrap/log4j/UMConsoleLayout.java @@ -0,0 +1,195 @@ +package org.ultramine.server.bootstrap.log4j; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.helpers.Charsets; +import org.apache.logging.log4j.core.helpers.Constants; +import org.apache.logging.log4j.core.layout.AbstractStringLayout; +import org.fusesource.jansi.Ansi; +import org.ultramine.server.bootstrap.UMBootstrap; +import org.ultramine.server.internal.JLineSupport; + +@Plugin(name = "UMConsoleLayout", category = "Core", elementType = "layout", printObject = false) +public class UMConsoleLayout extends AbstractStringLayout +{ + private static final boolean COLORED = UMBootstrap.isColoredTerminal(); + private static final boolean ANSI = UMBootstrap.isAnsiColors(); + + private static final String[] controlMap = new String[128]; + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + protected UMConsoleLayout(Charset charset) + { + super(charset); + } + + @Override + public String toSerializable(LogEvent event) + { + String msg = event.getMessage().getFormattedMessage(); + StringBuffer trwn = formatThrowable(event.getThrown()); + StringBuilder sb = new StringBuilder(10+1+6+4+1+2 + msg.length() + (trwn == null ? 0 : trwn.length() + 2) + (ANSI ? 100 : 0)); + + sb.append('['); + sb.append(dateFormat.format(event.getMillis())); + sb.append("] "); + + sb.append('['); + Level level = event.getLevel(); + if(COLORED) + { + if(level == Level.WARN) + control(sb, 'e'); + else if(level == Level.ERROR) + control(sb, 'c'); + else if(level == Level.FATAL) + control(sb, '4'); + } + String levelS = event.getLevel().toString(); + int llen = levelS.length(); + if(llen > 4) + levelS = levelS.substring(0, 4); + sb.append(levelS); + if(llen < 4) + sb.append(' '); + if(COLORED && (level == Level.WARN || level == Level.ERROR || level == Level.FATAL)) + control(sb, 'r'); + sb.append("] "); + + if(COLORED) + simplifyControlSequences(sb, msg); + else + stripControlSequences(sb, msg); + + if(trwn != null) + { + sb.append(Constants.LINE_SEP); + sb.append(trwn); + } + + sb.append(Constants.LINE_SEP); + + return sb.toString(); + } + + private static StringBuffer formatThrowable(Throwable t) + { + if(t == null) + return null; + StringWriter w = new StringWriter(4096); + t.printStackTrace(new PrintWriter(w)); + return w.getBuffer(); + } + + private static void control(StringBuilder sb, char code) + { + if(!ANSI) + { + sb.append('\u00a7'); + sb.append(code); + } + else + { + sb.append(controlMap[code]); + } + } + + /** simplifies redundant sequence, for example &4&5&5_&r&6&5_ will be simplified to &5__ */ + private static void simplifyControlSequences(StringBuilder sb, String msg) + { + char prevCode = 'r'; + for(int i = 0, s = msg.length(); i < s; i++) + { + char c = msg.charAt(i); + if(c == '\u00a7') + { + char code = msg.charAt(++i); + if(!isValidCode(code) || i+2 < s && msg.charAt(i+1) == '\u00a7' && isResetCode(msg.charAt(i+2))) + continue; + if(code != prevCode) + control(sb, code); + prevCode = code; + continue; + } + sb.append(c); + } + if(ANSI && prevCode != 'r') + control(sb, 'r'); + } + + private static boolean isValidCode(char code) + { + return code == 'r' || code >= '0' && code <= '9' || code >= 'a' && code <= 'f' || code >= 'k' && code <= 'o'; + } + + private static boolean isResetCode(char code) + { + return !(code >= 'k' && code <= 'o'); + } + + static void stripControlSequences(StringBuilder sb, String msg) + { + for(int i = 0, s = msg.length(); i < s; i++) + { + char c = msg.charAt(i); + if(c == '\u00a7') + { + i++; + continue; + } + sb.append(c); + } + } + + @Override + public Map getContentFormat() + { + return Collections.emptyMap(); + } + + @PluginFactory + public static UMConsoleLayout createLayout(@PluginAttribute("charset") final String charsetName) + { + String overrideCharset = UMBootstrap.getTerminalCharset(); + return new UMConsoleLayout(Charsets.getSupportedCharset(overrideCharset != null && !overrideCharset.isEmpty() ? overrideCharset : charsetName)); + } + + static + { + if(ANSI) + { + controlMap['0'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).boldOff().toString(); + controlMap['1'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).boldOff().toString(); + controlMap['2'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).boldOff().toString(); + controlMap['3'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).boldOff().toString(); + controlMap['4'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).boldOff().toString(); + controlMap['5'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.MAGENTA).boldOff().toString(); + controlMap['6'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).boldOff().toString(); + controlMap['7'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).boldOff().toString(); + controlMap['8'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLACK).bold().toString(); + controlMap['9'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.BLUE).bold().toString(); + controlMap['a'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.GREEN).bold().toString(); + controlMap['b'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.CYAN).bold().toString(); + controlMap['c'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.RED).bold().toString(); + controlMap['d'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.MAGENTA).bold().toString(); + controlMap['e'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.YELLOW).bold().toString(); + controlMap['f'] = Ansi.ansi().a(Ansi.Attribute.RESET).fg(Ansi.Color.WHITE).bold().toString(); + controlMap['k'] = Ansi.ansi().a(Ansi.Attribute.BLINK_SLOW).toString(); + controlMap['l'] = Ansi.ansi().a(Ansi.Attribute.UNDERLINE_DOUBLE).toString(); + controlMap['m'] = Ansi.ansi().a(Ansi.Attribute.STRIKETHROUGH_ON).toString(); + controlMap['n'] = Ansi.ansi().a(Ansi.Attribute.UNDERLINE).toString(); + controlMap['o'] = Ansi.ansi().a(Ansi.Attribute.ITALIC).toString(); + controlMap['r'] = Ansi.ansi().a(Ansi.Attribute.RESET).toString(); + } + } +} diff --git a/src/main/java/org/ultramine/server/bootstrap/log4j/UMStripColorsRewritePolicy.java b/src/main/java/org/ultramine/server/bootstrap/log4j/UMStripColorsRewritePolicy.java new file mode 100644 index 0000000..afb294c --- /dev/null +++ b/src/main/java/org/ultramine/server/bootstrap/log4j/UMStripColorsRewritePolicy.java @@ -0,0 +1,47 @@ +package org.ultramine.server.bootstrap.log4j; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.MessageFormatMessage; +import org.apache.logging.log4j.message.SimpleMessage; +import org.apache.logging.log4j.message.StringFormattedMessage; + +@Plugin(name = "UMStripColorsRewritePolicy", category = "Core", elementType = "rewritePolicy", printObject = false) +public class UMStripColorsRewritePolicy implements RewritePolicy +{ + @Override + public LogEvent rewrite(LogEvent source) + { + Message message = source.getMessage(); + if(message instanceof SimpleMessage || message instanceof MessageFormatMessage || message instanceof StringFormattedMessage) + { + String text = message.getFormattedMessage(); + StringBuilder sb = new StringBuilder(text.length()); + UMConsoleLayout.stripControlSequences(sb, text); + message = new SimpleMessage(sb.toString()); + } + else if(message.getClass().getName().equals("org.ultramine.server.internal.ChatComponentLogMessage")) + { + // All log4j plugins loads by AppClassLoader, ChatComponentLogMessage uses + // minecraft classes and loads by LaunchClassLoader with transform. So + // we should compare class by name and use existing interface methods + message = new SimpleMessage(message.getFormat()); + } + + return new Log4jLogEvent(source.getLoggerName(), source.getMarker(), source.getFQCN(), source.getLevel(), + message, source.getThrown(), source.getContextMap(), source.getContextStack(), source.getThreadName(), + source.getSource(), source.getMillis()); + } + + @PluginFactory + public static UMStripColorsRewritePolicy createPolicy(@PluginConfiguration final Configuration config) + { + return new UMStripColorsRewritePolicy(); + } +} diff --git a/src/main/java/org/ultramine/server/internal/ChatComponentLogMessage.java b/src/main/java/org/ultramine/server/internal/ChatComponentLogMessage.java new file mode 100644 index 0000000..091777d --- /dev/null +++ b/src/main/java/org/ultramine/server/internal/ChatComponentLogMessage.java @@ -0,0 +1,76 @@ +package org.ultramine.server.internal; + +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.IChatComponent; +import org.apache.logging.log4j.message.Message; + +public class ChatComponentLogMessage implements Message +{ + private final IChatComponent comp; + private String formattedMessage; + private String unformattedMessage; + + public ChatComponentLogMessage(IChatComponent comp) + { + this.comp = comp; + } + + @Override + public String getFormattedMessage() + { + if(formattedMessage == null) + formattedMessage = comp.getFormattedText(); + return formattedMessage; + } + + public String getUnformattedMessage() + { + if(unformattedMessage == null) + unformattedMessage = comp.getUnformattedText(); + return unformattedMessage; + } + + /** Used in UMStripColorsRewritePolicy due to classloader issues */ + @Override + public String getFormat() + { + return getUnformattedMessage(); + } + + @Override + public Object[] getParameters() + { + return comp instanceof ChatComponentTranslation ? ((ChatComponentTranslation) comp).getFormatArgs() : null; + } + + @Override + public boolean equals(final Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + final ChatComponentLogMessage that = (ChatComponentLogMessage) o; + + return !(comp != null ? !comp.equals(that.comp) : that.comp != null); + } + + @Override + public int hashCode() + { + return comp.hashCode(); + } + + @Override + public String toString() + { + return "ChatComponentLogMessage[message=" + comp + "]"; + } + + @Override + public Throwable getThrowable() + { + return null; + } +} diff --git a/src/main/java/org/ultramine/server/internal/JLineSupport.java b/src/main/java/org/ultramine/server/internal/JLineSupport.java new file mode 100644 index 0000000..47af593 --- /dev/null +++ b/src/main/java/org/ultramine/server/internal/JLineSupport.java @@ -0,0 +1,71 @@ +package org.ultramine.server.internal; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import jline.console.ConsoleReader; +import jline.console.completer.Completer; +import net.minecraft.command.CommandHandler; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.ultramine.server.bootstrap.UMBootstrap; +import org.ultramine.server.util.GlobalExecutors; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@SideOnly(Side.SERVER) +public class JLineSupport +{ + private static final Logger log = LogManager.getLogger(); + + public static Thread setupReadingThread(final DedicatedServer server) + { + UMBootstrap.getJLineReader().addCompleter(new JLineCompleter()); + return new Thread("Server console handler") + { + public void run() + { + ConsoleReader reader = UMBootstrap.getJLineReader(); + String s4; + + try + { + while (!server.isServerStopped() && server.isServerRunning() && (s4 = reader.readLine()) != null) + { + server.addPendingCommand(s4, server); + } + } + catch (IOException e) + { + log.error("Exception handling console input", e); + } + } + }; + } + + @SideOnly(Side.SERVER) + private static class JLineCompleter implements Completer + { + @Override + public int complete(String buffer, int cursor, List candidates) + { + MinecraftServer server = MinecraftServer.getServer(); + List offers = + GlobalExecutors.nextTick().await(() -> ((CommandHandler) server.getCommandManager()).getRegistry().filterPossibleCommandsNames(server, buffer)); + if(offers.isEmpty()) + return cursor; + + candidates.addAll(offers); + + final int lastSpace = buffer.lastIndexOf(' '); + if(lastSpace == -1) + return cursor - buffer.length(); + else + return cursor - (buffer.length() - lastSpace - 1); + + } + } +} diff --git a/src/main/java/org/ultramine/server/log/UMConsoleLayout.java b/src/main/java/org/ultramine/server/log/UMConsoleLayout.java deleted file mode 100644 index 87e3508..0000000 --- a/src/main/java/org/ultramine/server/log/UMConsoleLayout.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.ultramine.server.log; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Map; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.core.helpers.Charsets; -import org.apache.logging.log4j.core.helpers.Constants; -import org.apache.logging.log4j.core.layout.AbstractStringLayout; - -@Plugin(name = "UMConsoleLayout", category = "Core", elementType = "layout", printObject = false) -public class UMConsoleLayout extends AbstractStringLayout -{ - private static final boolean useUMConsole = Boolean.parseBoolean(System.getProperty("org.ultramine.server.umconsole")); - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); - - protected UMConsoleLayout(Charset charset) - { - super(charset); - } - - @Override - public String toSerializable(LogEvent event) - { - StringBuilder sb = new StringBuilder(); - - sb.append('['); - sb.append(dateFormat.format(event.getMillis())); - sb.append("] "); - - sb.append('['); - Level level = event.getLevel(); - if(useUMConsole) - { - if(level == Level.WARN) - sb.append("\u00A7e"); - else if(level == Level.ERROR) - sb.append("\u00A7c"); - else if(level == Level.FATAL) - sb.append("\u00A74"); - } - String levelS = event.getLevel().toString(); - int llen = levelS.length(); - if(llen > 4) - levelS = levelS.substring(0, 4); - sb.append(levelS); - if(llen < 4) - sb.append(' '); - if(useUMConsole && (level == Level.WARN || level == Level.ERROR || level == Level.FATAL)) - sb.append("\u00A7r"); - sb.append("] "); - - String msg = event.getMessage().getFormattedMessage(); - if(useUMConsole) - { - sb.append(msg); - } - else - { - for(int i = 0, s = msg.length(); i < s; i++) - { - char c = msg.charAt(i); - if(c == '\u00a7') - { - i++; - continue; - } - sb.append(c); - } - } - - Throwable t = event.getThrown(); - if(t != null) - { - StringWriter w = new StringWriter(); - t.printStackTrace(new PrintWriter(w)); - sb.append(Constants.LINE_SEP); - sb.append(w.toString()); - } - - sb.append(Constants.LINE_SEP); - - return sb.toString(); - } - - @Override - public Map getContentFormat() - { - return Collections.emptyMap(); - } - - @PluginFactory - public static UMConsoleLayout createLayout(@PluginAttribute("charset") final String charsetName) - { - return new UMConsoleLayout(Charsets.getSupportedCharset(charsetName)); - } -} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index c91d4ef..ebb2942 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -1,16 +1,19 @@ - + - + - + + + +