diff --git a/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java index 6619236600..8682f341b4 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -1,6 +1,10 @@ package org.bukkit.plugin; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; +import com.google.common.graph.GraphBuilder; +import com.google.common.graph.Graphs; +import com.google.common.graph.MutableGraph; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -44,6 +48,7 @@ public final class SimplePluginManager implements PluginManager { private final Map fileAssociations = new HashMap(); private final List plugins = new ArrayList(); private final Map lookupNames = new HashMap(); + private MutableGraph dependencyGraph = GraphBuilder.directed().build(); private File updateDirectory; private final SimpleCommandMap commandMap; private final Map permissions = new HashMap(); @@ -168,11 +173,19 @@ public final class SimplePluginManager implements PluginManager { } else { softDependencies.put(description.getName(), new LinkedList(softDependencySet)); } + + for (String depend : softDependencySet) { + dependencyGraph.putEdge(description.getName(), depend); + } } Collection dependencySet = description.getDepend(); if (dependencySet != null && !dependencySet.isEmpty()) { dependencies.put(description.getName(), new LinkedList(dependencySet)); + + for (String depend : dependencySet) { + dependencyGraph.putEdge(description.getName(), depend); + } } Collection loadBeforeSet = description.getLoadBefore(); @@ -186,6 +199,8 @@ public final class SimplePluginManager implements PluginManager { shortSoftDependency.add(description.getName()); softDependencies.put(loadBeforeTarget, shortSoftDependency); } + + dependencyGraph.putEdge(loadBeforeTarget, description.getName()); } } } @@ -480,6 +495,7 @@ public final class SimplePluginManager implements PluginManager { disablePlugins(); plugins.clear(); lookupNames.clear(); + dependencyGraph = GraphBuilder.directed().build(); HandlerList.unregisterAll(); fileAssociations.clear(); permissions.clear(); @@ -780,6 +796,13 @@ public final class SimplePluginManager implements PluginManager { return new HashSet(permissions.values()); } + public boolean isTransitiveDepend(@NotNull PluginDescriptionFile plugin, @NotNull Plugin depend) { + Preconditions.checkArgument(plugin != null, "plugin"); + Preconditions.checkArgument(depend != null, "depend"); + + return Graphs.reachableNodes(dependencyGraph, plugin.getName()).contains(depend.getName()); + } + @Override public boolean useTimings() { return useTimings; diff --git a/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java index c6633ee7d9..bd10ca723f 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -22,6 +22,7 @@ import java.util.logging.Level; import org.apache.commons.lang.Validate; import org.bukkit.plugin.InvalidPluginException; import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.SimplePluginManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -113,12 +114,15 @@ final class PluginClassLoader extends URLClassLoader { if (provider != plugin && !seenIllegalAccess.contains(providerName) - && !description.getDepend().contains(providerName) - && !description.getSoftDepend().contains(providerName) - && !provider.getDescription().getLoadBefore().contains(description.getName())) { + && !((SimplePluginManager) loader.server.getPluginManager()).isTransitiveDepend(description, provider)) { seenIllegalAccess.add(providerName); - plugin.getLogger().log(Level.WARNING, "Loaded class {0} from {1} which is not a depend, softdepend or loadbefore of this plugin.", new Object[]{name, provider.getDescription().getFullName()}); + if (plugin != null) { + plugin.getLogger().log(Level.WARNING, "Loaded class {0} from {1} which is not a depend, softdepend or loadbefore of this plugin.", new Object[]{name, provider.getDescription().getFullName()}); + } else { + // In case the bad access occurs on construction + loader.server.getLogger().log(Level.WARNING, "[{0}] Loaded class {1} from {2} which is not a depend, softdepend or loadbefore of this plugin.", new Object[]{description.getName(), name, provider.getDescription().getFullName()}); + } } } }