From 66be4900a3768154c606aff8a651deebe00d28ee Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Sat, 14 Feb 2015 21:57:45 -0500 Subject: [PATCH] Warn if exceptions are caused by broken plugins --- .../protocol/error/PluginContext.java | 15 ++++---- .../protocol/reflect/StructureModifier.java | 36 ++++++++++++++++++- .../com/comphenix/protocol/utility/Util.java | 10 ++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/error/PluginContext.java b/ProtocolLib/src/main/java/com/comphenix/protocol/error/PluginContext.java index 2727c75b..f0371a63 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/error/PluginContext.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/error/PluginContext.java @@ -34,6 +34,7 @@ public final class PluginContext { return caller; } } + return null; } @@ -41,25 +42,25 @@ public final class PluginContext { * Lookup the plugin that this method invocation belongs to, and return its file name. * @param element - the method invocation. * @return Plugin name, or NULL if not found. - * */ public static String getPluginName(StackTraceElement element) { try { - if (Bukkit.getServer() == null) + if (Bukkit.getServer() == null) { return null; + } + CodeSource codeSource = Class.forName(element.getClassName()).getProtectionDomain().getCodeSource(); - if (codeSource != null) { String encoding = codeSource.getLocation().getPath(); File path = new File(URLDecoder.decode(encoding, "UTF-8")); File plugins = getPluginFolder(); if (plugins != null && folderContains(plugins, path)) { - return path.getName(); + return path.getName().replaceAll(".jar", ""); } } + return null; // Cannot find it - } catch (UnsupportedEncodingException e) { throw new RuntimeException("Cannot lookup plugin name.", e); } catch (ClassNotFoundException e) { @@ -86,6 +87,7 @@ public final class PluginContext { return true; file = file.getParentFile(); } + return false; } @@ -96,7 +98,7 @@ public final class PluginContext { private static File getPluginFolder() { File folder = pluginFolder; - if (folder == null && Bukkit.getServer() != null) { + if (folder == null && Bukkit.getServer() != null) { Plugin[] plugins = Bukkit.getPluginManager().getPlugins(); if (plugins.length > 0) { @@ -104,6 +106,7 @@ public final class PluginContext { pluginFolder = folder; } } + return folder; } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java index 92111264..15025e19 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java @@ -24,12 +24,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.error.PluginContext; import com.comphenix.protocol.reflect.compiler.BackgroundCompiler; import com.comphenix.protocol.reflect.instances.BannedGenerator; import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.reflect.instances.InstanceProvider; import com.comphenix.protocol.utility.MinecraftReflection; +import com.comphenix.protocol.utility.Util; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; @@ -178,6 +182,8 @@ public class StructureModifier { this.subtypeCache = subTypeCache; this.useStructureCompiler = useStructureCompiler; } + + private static final List BROKEN_PLUGINS = Util.asList("TagAPI"); /** * Reads the value of a field given its index. @@ -185,8 +191,22 @@ public class StructureModifier { * @return Value of the field. * @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints. */ - @SuppressWarnings("unchecked") public TField read(int fieldIndex) throws FieldAccessException { + try { + return readInternal(fieldIndex); + } catch (FieldAccessException ex) { + String plugin = PluginContext.getPluginCaller(ex); + if (BROKEN_PLUGINS.contains(plugin)) { + ProtocolLibrary.log(Level.WARNING, "Encountered an exception caused by broken plugin {0}.", plugin); + ProtocolLibrary.log(Level.WARNING, "It is advised that you remove it."); + } + + throw ex; + } + } + + @SuppressWarnings("unchecked") + private TField readInternal(int fieldIndex) throws FieldAccessException { if (target == null) throw new IllegalStateException("Cannot read from a null target!"); @@ -288,6 +308,20 @@ public class StructureModifier { * @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints. */ public StructureModifier write(int fieldIndex, TField value) throws FieldAccessException { + try { + return writeInternal(fieldIndex, value); + } catch (FieldAccessException ex) { + String plugin = PluginContext.getPluginCaller(ex); + if (BROKEN_PLUGINS.contains(plugin)) { + ProtocolLibrary.log(Level.WARNING, "Encountered an exception caused by broken plugin {0}.", plugin); + ProtocolLibrary.log(Level.WARNING, "It is advised that you remove it."); + } + + throw ex; + } + } + + private StructureModifier writeInternal(int fieldIndex, TField value) throws FieldAccessException { if (target == null) throw new IllegalStateException("Cannot read from a null target!"); diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/Util.java b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/Util.java index 36087375..b7a4494a 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/utility/Util.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/utility/Util.java @@ -1,6 +1,7 @@ package com.comphenix.protocol.utility; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -45,4 +46,13 @@ public class Util { return (List) Bukkit.getOnlinePlayers(); } + + public static List asList(E... elements) { + List list = new ArrayList(); + for (E element : elements) { + list.add(element); + } + + return list; + } } \ No newline at end of file