Death to ACFLog (#42)

This commit is contained in:
kashike
2017-06-06 16:03:01 -07:00
committed by Daniel Ennis
parent cd892fccd4
commit 96a3a3c57d
14 changed files with 107 additions and 124 deletions
@@ -24,8 +24,6 @@
package co.aikar.commands;
import com.google.common.collect.Iterables;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@@ -64,14 +62,8 @@ public class ACFBukkitUtil {
public static void sendMsg(CommandSender player, String message) {
message = color(message);
if (player == null) {
for (String msg : ACFPatterns.NEWLINE.split(message)) {
ACFLog.info(msg);
}
} else {
for (String msg : ACFPatterns.NEWLINE.split(message)) {
player.sendMessage(msg);
}
for (String msg : ACFPatterns.NEWLINE.split(message)) {
player.sendMessage(msg);
}
}
@@ -110,7 +110,7 @@ public class BukkitCommandContexts extends CommandContexts<BukkitCommandExecutio
if (matcher.find()) {
int mcMajorVersion = ACFUtil.parseInt(matcher.toMatchResult().group(1), 0);
int mcMinorVersion = ACFUtil.parseInt(matcher.toMatchResult().group(2), 0);
ACFLog.info("Minecraft Version: " + mcMajorVersion + "." + mcMinorVersion);
manager.log(LogLevel.INFO, "Minecraft Version: " + mcMajorVersion + "." + mcMinorVersion);
if (mcMajorVersion >= 1 && mcMinorVersion >= 12) {
BukkitCommandContexts_1_12.register(this);
}
@@ -23,6 +23,7 @@
package co.aikar.commands;
import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
import co.aikar.timings.lib.TimingManager;
import org.bukkit.Bukkit;
import org.bukkit.Server;
@@ -43,6 +44,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
@SuppressWarnings("WeakerAccess")
public class BukkitCommandManager extends CommandManager {
@@ -66,19 +68,19 @@ public class BukkitCommandManager extends CommandManager {
getCommandMap.setAccessible(true);
commandMap = (CommandMap) getCommandMap.invoke(server);
if (!SimpleCommandMap.class.isAssignableFrom(commandMap.getClass())) {
ACFLog.severe("ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName());
ACFLog.severe("We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
ACFLog.severe("We can not guarantee things are going to work.");
this.log(LogLevel.ERROR, "ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName());
this.log(LogLevel.ERROR, "We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
this.log(LogLevel.ERROR, "We can not guarantee things are going to work.");
Field cmField = server.getClass().getDeclaredField("commandMap");
cmField.set(server, commandMap = new ProxyCommandMap(commandMap));
ACFLog.info("Injected Proxy Command Map... good luck...");
this.log(LogLevel.INFO, "Injected Proxy Command Map... good luck...");
}
Field knownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
knownCommands.setAccessible(true);
//noinspection unchecked
this.knownCommands = (Map<String, Command>) knownCommands.get(commandMap);
} catch (Exception e) {
ACFLog.severe("Failed to get Command Map. ACF will not function.");
this.log(LogLevel.ERROR, "Failed to get Command Map. ACF will not function.");
ACFUtil.sneaky(e);
}
this.commandMap = commandMap;
@@ -195,6 +197,31 @@ public class BukkitCommandManager extends CommandManager {
return new RegisteredCommand(command, cmdName, method, prefSubCommand);
}
@Override
public void log(LogLevel level, String message) {
switch(level) {
case INFO:
this.plugin.getLogger().info(LogLevel.LOG_PREFIX + message);
return;
case ERROR:
this.plugin.getLogger().severe(LogLevel.LOG_PREFIX + message);
}
}
@Override
public void log(LogLevel level, String message, Throwable throwable) {
switch(level) {
case INFO:
this.plugin.getLogger().log(Level.INFO, LogLevel.LOG_PREFIX + message, throwable);
return;
case ERROR:
this.plugin.getLogger().log(Level.SEVERE, LogLevel.LOG_PREFIX + message);
for(String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
this.plugin.getLogger().severe(LogLevel.LOG_PREFIX + line);
}
}
}
class ProxyCommandMap extends SimpleCommandMap {
CommandMap proxied;
@@ -98,8 +98,8 @@ public class BukkitRootCommand extends Command implements RootCommand {
}
BaseCommand regged = this.subCommands.get(key);
if (regged != null) {
ACFLog.severe("ACF Error: " + command.getName() + " registered subcommand " + key + " for root command " + getName() + " - but it is already defined in " + regged.getName());
ACFLog.severe("2 subcommands of the same prefix may not be spread over 2 different classes. Ignoring this.");
this.manager.log(LogLevel.ERROR, "ACF Error: " + command.getName() + " registered subcommand " + key + " for root command " + getName() + " - but it is already defined in " + regged.getName());
this.manager.log(LogLevel.ERROR, "2 subcommands of the same prefix may not be spread over 2 different classes. Ignoring this.");
return;
}
this.subCommands.put(key, command);
@@ -1,96 +0,0 @@
/*
* Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package co.aikar.commands;
import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
import java.util.logging.Logger;
@SuppressWarnings("WeakerAccess")
final class ACFLog {
private static final Logger LOGGER = Logger.getLogger("ACF");
public static final String PREFIX = "[ACF] ";
private ACFLog() {}
public static void log(String message) {
info(message);
}
public static void info(String message) {
for (String s : ACFPatterns.NEWLINE.split(message)) {
LOGGER.info(PREFIX + s);
}
}
public static void warn(String message) {
for (String s : ACFPatterns.NEWLINE.split(message)) {
LOGGER.warning(PREFIX + s);
}
}
public static void severe(String message) {
for (String s : ACFPatterns.NEWLINE.split(message)) {
LOGGER.severe(PREFIX + s);
}
}
public static void error(String message) {
severe(message);
}
public static void exception(String msg) {
exception(new Throwable(msg));
}
public static void exception(Throwable e) {
exception(e.getMessage(), e);
}
public static void exception(String msg, Throwable e) {
if (msg != null) {
severe(msg);
}
severe(ApacheCommonsExceptionUtil.getFullStackTrace(e));
}
public static void exception(Throwable dbg, int lines) {
if (dbg == null) {
return;
}
severe(dbg.getMessage());
final StackTraceElement current = new Throwable().getStackTrace()[1];
severe("c: "+ current.getClassName()+":" + current.getLineNumber());
final StackTraceElement[] stack = dbg.getStackTrace();
for (int i = 0; i < lines && i < stack.length; i++) {
final StackTraceElement cur = stack[i];
severe(" " + cur);
}
}
}
@@ -194,7 +194,7 @@ public abstract class BaseCommand {
if (parameters.length == 1) {
subCommand = (BaseSubCommand) declaredConstructor.newInstance(this);
} else {
ACFLog.info("Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining(", ")) + ")");
manager.log(LogLevel.INFO, "Found unusable constructor: " + declaredConstructor.getName() + "(" + Stream.of(parameters).map(p -> p.getType().getSimpleName() + " " + p.getName()).collect(Collectors.joining(", ")) + ")");
}
}
if (subCommand != null) {
@@ -203,7 +203,7 @@ public abstract class BaseCommand {
this.subCommands.putAll(subCommand.subCommands);
this.registeredCommands.putAll(subCommand.registeredCommands);
} else {
ACFLog.severe("Could not find a subcommand ctor for " + clazz.getName());
this.manager.log(LogLevel.ERROR, "Could not find a subcommand ctor for " + clazz.getName());
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
@@ -465,7 +465,7 @@ public abstract class BaseCommand {
return (boolean) preCommandHandler.invoke(this, sender.getIssuer(), args);
}
} catch (IllegalAccessException | InvocationTargetException e) {
ACFLog.exception(e);
this.manager.log(LogLevel.ERROR, "Exception encountered while command pre-processing", e);
}
}
return false;
@@ -105,7 +105,7 @@ public class CommandCompletionContext {
//noinspection unchecked
Map<String, Object> resolved = command.resolveContexts(issuer, args, args.size());
if (resolved == null || paramIdx > resolved.size()) {
ACFLog.error("resolved: " + resolved + " paramIdx: " + paramIdx + " - size: " + (resolved != null ? resolved.size() : null ));
this.command.scope.manager.log(LogLevel.ERROR, "resolved: " + resolved + " paramIdx: " + paramIdx + " - size: " + (resolved != null ? resolved.size() : null ));
ACFUtil.sneaky(new CommandCompletionTextLookupException());
}
@@ -160,7 +160,7 @@ public class CommandContexts <R extends CommandExecutionContext<?>> {
}
} while ((type = type.getSuperclass()) != null);
ACFLog.exception(new IllegalStateException("No context resolver defined for " + rootType.getName()));
this.manager.log(LogLevel.ERROR, "Could not find context resolver", new IllegalStateException("No context resolver defined for " + rootType.getName()));
return null;
}
}
@@ -84,4 +84,7 @@ abstract class CommandManager {
public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
return new RegisteredCommand(command, cmdName, method, prefSubCommand);
}
public abstract void log(final LogLevel level, final String message);
public abstract void log(final LogLevel level, final String message, final Throwable throwable);
}
@@ -51,8 +51,8 @@ public class CommandReplacements {
public String addReplacement(String key, String val) {
if (this.manager.hasRegisteredCommands()) {
ACFLog.severe("You are registering replacements after you have registered your commands!");
ACFLog.severe("This is not allowed, and this replacement (" + key + ") will not work for any previously registered command.");
this.manager.log(LogLevel.ERROR, "You are registering replacements after you have registered your commands!");
this.manager.log(LogLevel.ERROR, "This is not allowed, and this replacement (" + key + ") will not work for any previously registered command.");
}
key = ACFPatterns.PERCENTAGE.matcher(key.toLowerCase()).replaceAll("");
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package co.aikar.commands;
enum LogLevel {
INFO,
ERROR;
static final String LOG_PREFIX = "[ACF] ";
}
@@ -154,7 +154,7 @@ public class RegisteredCommand <R extends CommandExecutionContext<? extends Comm
}
} else {
sender.sendMessage("&cI'm sorry, but there was an error performing this command.");
ACFLog.exception("Exception in command: " + command + " " + ACFUtil.join(args), e);
this.scope.manager.log(LogLevel.ERROR, "Exception in command: " + command + " " + ACFUtil.join(args), e);
}
}
@@ -23,6 +23,7 @@
package co.aikar.commands;
import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil;
import co.aikar.timings.Timing;
import co.aikar.timings.Timings;
import org.spongepowered.api.Sponge;
@@ -119,4 +120,29 @@ public class SpongeCommandManager extends CommandManager {
public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) {
return new RegisteredCommand(command, cmdName, method, prefSubCommand);
}
@Override
public void log(final LogLevel level, final String message) {
switch(level) {
case INFO:
this.plugin.getLogger().info(LogLevel.LOG_PREFIX + message);
return;
case ERROR:
this.plugin.getLogger().error(LogLevel.LOG_PREFIX + message);
}
}
@Override
public void log(final LogLevel level, final String message, final Throwable throwable) {
switch(level) {
case INFO:
this.plugin.getLogger().info(LogLevel.LOG_PREFIX + message, throwable);
return;
case ERROR:
this.plugin.getLogger().error(LogLevel.LOG_PREFIX + message, throwable);
for(String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) {
this.plugin.getLogger().error(LogLevel.LOG_PREFIX + line);
}
}
}
}
@@ -129,8 +129,8 @@ public class SpongeRootCommand implements CommandCallable, RootCommand {
}
BaseCommand regged = this.subCommands.get(key);
if (regged != null) {
ACFLog.severe("ACF Error: " + command.getName() + " registered subcommand " + key + " for root command " + this.name + " - but it is already defined in " + regged.getName());
ACFLog.severe("2 subcommands of the same prefix may not be spread over 2 different classes. Ignoring this.");
this.manager.log(LogLevel.ERROR, "ACF Error: " + command.getName() + " registered subcommand " + key + " for root command " + this.name + " - but it is already defined in " + regged.getName());
this.manager.log(LogLevel.ERROR, "2 subcommands of the same prefix may not be spread over 2 different classes. Ignoring this.");
return;
}
this.subCommands.put(key, command);