Warn if exceptions are caused by broken plugins

This commit is contained in:
Dan Mulloy 2015-02-14 21:57:45 -05:00
parent a3784b3cf1
commit 66be4900a3
3 changed files with 54 additions and 7 deletions

View File

@ -34,6 +34,7 @@ public final class PluginContext {
return caller; return caller;
} }
} }
return null; return null;
} }
@ -41,25 +42,25 @@ public final class PluginContext {
* Lookup the plugin that this method invocation belongs to, and return its file name. * Lookup the plugin that this method invocation belongs to, and return its file name.
* @param element - the method invocation. * @param element - the method invocation.
* @return Plugin name, or NULL if not found. * @return Plugin name, or NULL if not found.
*
*/ */
public static String getPluginName(StackTraceElement element) { public static String getPluginName(StackTraceElement element) {
try { try {
if (Bukkit.getServer() == null) if (Bukkit.getServer() == null) {
return null; return null;
CodeSource codeSource = Class.forName(element.getClassName()).getProtectionDomain().getCodeSource(); }
CodeSource codeSource = Class.forName(element.getClassName()).getProtectionDomain().getCodeSource();
if (codeSource != null) { if (codeSource != null) {
String encoding = codeSource.getLocation().getPath(); String encoding = codeSource.getLocation().getPath();
File path = new File(URLDecoder.decode(encoding, "UTF-8")); File path = new File(URLDecoder.decode(encoding, "UTF-8"));
File plugins = getPluginFolder(); File plugins = getPluginFolder();
if (plugins != null && folderContains(plugins, path)) { if (plugins != null && folderContains(plugins, path)) {
return path.getName(); return path.getName().replaceAll(".jar", "");
} }
} }
return null; // Cannot find it
return null; // Cannot find it
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new RuntimeException("Cannot lookup plugin name.", e); throw new RuntimeException("Cannot lookup plugin name.", e);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
@ -86,6 +87,7 @@ public final class PluginContext {
return true; return true;
file = file.getParentFile(); file = file.getParentFile();
} }
return false; return false;
} }
@ -104,6 +106,7 @@ public final class PluginContext {
pluginFolder = folder; pluginFolder = folder;
} }
} }
return folder; return folder;
} }
} }

View File

@ -24,12 +24,16 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; 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.compiler.BackgroundCompiler;
import com.comphenix.protocol.reflect.instances.BannedGenerator; import com.comphenix.protocol.reflect.instances.BannedGenerator;
import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.reflect.instances.InstanceProvider; import com.comphenix.protocol.reflect.instances.InstanceProvider;
import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.Util;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -179,14 +183,30 @@ public class StructureModifier<TField> {
this.useStructureCompiler = useStructureCompiler; this.useStructureCompiler = useStructureCompiler;
} }
private static final List<String> BROKEN_PLUGINS = Util.asList("TagAPI");
/** /**
* Reads the value of a field given its index. * Reads the value of a field given its index.
* @param fieldIndex - index of the field. * @param fieldIndex - index of the field.
* @return Value of the field. * @return Value of the field.
* @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints. * @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 { 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) if (target == null)
throw new IllegalStateException("Cannot read from a null target!"); throw new IllegalStateException("Cannot read from a null target!");
@ -288,6 +308,20 @@ public class StructureModifier<TField> {
* @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints. * @throws FieldAccessException The field doesn't exist, or it cannot be accessed under the current security contraints.
*/ */
public StructureModifier<TField> write(int fieldIndex, TField value) throws FieldAccessException { public StructureModifier<TField> 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<TField> writeInternal(int fieldIndex, TField value) throws FieldAccessException {
if (target == null) if (target == null)
throw new IllegalStateException("Cannot read from a null target!"); throw new IllegalStateException("Cannot read from a null target!");

View File

@ -1,6 +1,7 @@
package com.comphenix.protocol.utility; package com.comphenix.protocol.utility;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -45,4 +46,13 @@ public class Util {
return (List<Player>) Bukkit.getOnlinePlayers(); return (List<Player>) Bukkit.getOnlinePlayers();
} }
public static <E> List<E> asList(E... elements) {
List<E> list = new ArrayList<E>();
for (E element : elements) {
list.add(element);
}
return list;
}
} }