mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-22 08:11:59 +01:00
Deprecate methods in JavaPluginLoader and PluginClassLoader
These methods are unnecessarily exposed. They are specific to a type of implementation for the class loaders, and should have no external use. Because these methods are exposed, it limits the versatility to change how the internal class loading system works, including an inherent class loader leak for some situations. They are now replaced with internal, package-private methods. The public facing methods will print a stack trace the first time one is activated. Extending the classes also produces a stack trace, to indicate that extension is not actively supported. By: Wesley Wolfe <weswolf@aol.com>
This commit is contained in:
parent
982f31e75c
commit
fb2cf30fbe
@ -50,13 +50,43 @@ import com.google.common.collect.ImmutableList;
|
|||||||
* Represents a Java plugin loader, allowing plugins in the form of .jar
|
* Represents a Java plugin loader, allowing plugins in the form of .jar
|
||||||
*/
|
*/
|
||||||
public class JavaPluginLoader implements PluginLoader {
|
public class JavaPluginLoader implements PluginLoader {
|
||||||
private final Server server;
|
final Server server;
|
||||||
protected final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), };
|
final boolean extended = this.getClass() != JavaPluginLoader.class;
|
||||||
protected final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
|
boolean warn;
|
||||||
protected final Map<String, PluginClassLoader> loaders = new LinkedHashMap<String, PluginClassLoader>();
|
|
||||||
|
|
||||||
|
private final Pattern[] fileFilters0 = new Pattern[] { Pattern.compile("\\.jar$"), };
|
||||||
|
/**
|
||||||
|
* @deprecated Internal field that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected final Pattern[] fileFilters = fileFilters0;
|
||||||
|
|
||||||
|
private final Map<String, Class<?>> classes0 = new HashMap<String, Class<?>>();
|
||||||
|
/**
|
||||||
|
* @deprecated Internal field that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected final Map<String, Class<?>> classes = classes0;
|
||||||
|
|
||||||
|
private final Map<String, PluginClassLoader> loaders0 = new LinkedHashMap<String, PluginClassLoader>();
|
||||||
|
/**
|
||||||
|
* @deprecated Internal field that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected final Map<String, PluginClassLoader> loaders = loaders0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class was not meant to be extended
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public JavaPluginLoader(Server instance) {
|
public JavaPluginLoader(Server instance) {
|
||||||
|
Validate.notNull(instance, "Server cannot be null");
|
||||||
server = instance;
|
server = instance;
|
||||||
|
warn = instance.getWarningState() != WarningState.OFF;
|
||||||
|
if (extended && warn) {
|
||||||
|
warn = false;
|
||||||
|
instance.getLogger().log(Level.WARNING, "JavaPluginLoader not intended to be extended by " + getClass() + ", and may be final in a future version of Bukkit");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Plugin loadPlugin(File file) throws InvalidPluginException {
|
public Plugin loadPlugin(File file) throws InvalidPluginException {
|
||||||
@ -74,7 +104,7 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File dataFolder = new File(file.getParentFile(), description.getName());
|
File dataFolder = new File(file.getParentFile(), description.getName());
|
||||||
File oldDataFolder = getDataFolder(file);
|
File oldDataFolder = extended ? getDataFolder(file) : getDataFolder0(file); // Don't warn on deprecation, but maintain overridability
|
||||||
|
|
||||||
// Found old data folder
|
// Found old data folder
|
||||||
if (dataFolder.equals(oldDataFolder)) {
|
if (dataFolder.equals(oldDataFolder)) {
|
||||||
@ -115,10 +145,10 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (String pluginName : depend) {
|
for (String pluginName : depend) {
|
||||||
if (loaders == null) {
|
if (loaders0 == null) {
|
||||||
throw new UnknownDependencyException(pluginName);
|
throw new UnknownDependencyException(pluginName);
|
||||||
}
|
}
|
||||||
PluginClassLoader current = loaders.get(pluginName);
|
PluginClassLoader current = loaders0.get(pluginName);
|
||||||
|
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
throw new UnknownDependencyException(pluginName);
|
throw new UnknownDependencyException(pluginName);
|
||||||
@ -134,10 +164,10 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
urls[0] = file.toURI().toURL();
|
urls[0] = file.toURI().toURL();
|
||||||
|
|
||||||
if (description.getClassLoaderOf() != null) {
|
if (description.getClassLoaderOf() != null) {
|
||||||
loader = loaders.get(description.getClassLoaderOf());
|
loader = loaders0.get(description.getClassLoaderOf());
|
||||||
loader.addURL(urls[0]);
|
loader.addURL(urls[0]);
|
||||||
} else {
|
} else {
|
||||||
loader = new PluginClassLoader(this, urls, getClass().getClassLoader());
|
loader = new PluginClassLoader(this, urls, getClass().getClassLoader(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> jarClass = Class.forName(description.getMain(), true, loader);
|
Class<?> jarClass = Class.forName(description.getMain(), true, loader);
|
||||||
@ -154,16 +184,36 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
throw new InvalidPluginException(ex);
|
throw new InvalidPluginException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
loaders.put(description.getName(), loader);
|
loaders0.put(description.getName(), loader);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Relic method from PluginLoader that didn't get purged
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Plugin loadPlugin(File file, boolean ignoreSoftDependencies) throws InvalidPluginException {
|
public Plugin loadPlugin(File file, boolean ignoreSoftDependencies) throws InvalidPluginException {
|
||||||
|
if (warn) {
|
||||||
|
server.getLogger().log(Level.WARNING, "Method \"public Plugin loadPlugin(File, boolean)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
warn = false;
|
||||||
|
}
|
||||||
return loadPlugin(file);
|
return loadPlugin(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected File getDataFolder(File file) {
|
protected File getDataFolder(File file) {
|
||||||
|
if (warn) {
|
||||||
|
server.getLogger().log(Level.WARNING, "Method \"protected File getDataFolder(File)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
warn = false;
|
||||||
|
}
|
||||||
|
return getDataFolder0(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getDataFolder0(File file) {
|
||||||
File dataFolder = null;
|
File dataFolder = null;
|
||||||
|
|
||||||
String filename = file.getName();
|
String filename = file.getName();
|
||||||
@ -222,20 +272,32 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Pattern[] getPluginFileFilters() {
|
public Pattern[] getPluginFileFilters() {
|
||||||
return fileFilters;
|
return fileFilters0.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Class<?> getClassByName(final String name) {
|
public Class<?> getClassByName(final String name) {
|
||||||
Class<?> cachedClass = classes.get(name);
|
if (warn) {
|
||||||
|
server.getLogger().log(Level.WARNING, "Method \"public Plugin loadPlugin(File, boolean)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
warn = false;
|
||||||
|
}
|
||||||
|
return getClassByName0(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> getClassByName0(final String name) {
|
||||||
|
Class<?> cachedClass = classes0.get(name);
|
||||||
|
|
||||||
if (cachedClass != null) {
|
if (cachedClass != null) {
|
||||||
return cachedClass;
|
return cachedClass;
|
||||||
} else {
|
} else {
|
||||||
for (String current : loaders.keySet()) {
|
for (String current : loaders0.keySet()) {
|
||||||
PluginClassLoader loader = loaders.get(current);
|
PluginClassLoader loader = loaders0.get(current);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cachedClass = loader.findClass(name, false);
|
cachedClass = loader.extended ? loader.findClass(name, false) : loader.findClass0(name, false); // Don't warn on deprecation, but maintain overridability
|
||||||
} catch (ClassNotFoundException cnfe) {}
|
} catch (ClassNotFoundException cnfe) {}
|
||||||
if (cachedClass != null) {
|
if (cachedClass != null) {
|
||||||
return cachedClass;
|
return cachedClass;
|
||||||
@ -245,9 +307,21 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setClass(final String name, final Class<?> clazz) {
|
public void setClass(final String name, final Class<?> clazz) {
|
||||||
if (!classes.containsKey(name)) {
|
if (warn) {
|
||||||
classes.put(name, clazz);
|
server.getLogger().log(Level.WARNING, "Method \"public Plugin loadPlugin(File, boolean)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
warn = false;
|
||||||
|
}
|
||||||
|
setClass0(name, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setClass0(final String name, final Class<?> clazz) {
|
||||||
|
if (!classes0.containsKey(name)) {
|
||||||
|
classes0.put(name, clazz);
|
||||||
|
|
||||||
if (ConfigurationSerializable.class.isAssignableFrom(clazz)) {
|
if (ConfigurationSerializable.class.isAssignableFrom(clazz)) {
|
||||||
Class<? extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class);
|
Class<? extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class);
|
||||||
@ -256,8 +330,20 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void removeClass(String name) {
|
public void removeClass(String name) {
|
||||||
Class<?> clazz = classes.remove(name);
|
if (warn) {
|
||||||
|
server.getLogger().log(Level.WARNING, "Method \"public void removeClass(String)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
warn = false;
|
||||||
|
}
|
||||||
|
removeClass0(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeClass0(String name) {
|
||||||
|
Class<?> clazz = classes0.remove(name);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((clazz != null) && (ConfigurationSerializable.class.isAssignableFrom(clazz))) {
|
if ((clazz != null) && (ConfigurationSerializable.class.isAssignableFrom(clazz))) {
|
||||||
@ -354,20 +440,17 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void enablePlugin(final Plugin plugin) {
|
public void enablePlugin(final Plugin plugin) {
|
||||||
if (!(plugin instanceof JavaPlugin)) {
|
Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader");
|
||||||
throw new IllegalArgumentException("Plugin is not associated with this PluginLoader");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!plugin.isEnabled()) {
|
if (!plugin.isEnabled()) {
|
||||||
String message = String.format("Enabling %s", plugin.getDescription().getFullName());
|
plugin.getLogger().info("Enabling " + plugin.getDescription().getFullName());
|
||||||
plugin.getLogger().info(message);
|
|
||||||
|
|
||||||
JavaPlugin jPlugin = (JavaPlugin) plugin;
|
JavaPlugin jPlugin = (JavaPlugin) plugin;
|
||||||
|
|
||||||
String pluginName = jPlugin.getDescription().getName();
|
String pluginName = jPlugin.getDescription().getName();
|
||||||
|
|
||||||
if (!loaders.containsKey(pluginName)) {
|
if (!loaders0.containsKey(pluginName)) {
|
||||||
loaders.put(pluginName, (PluginClassLoader) jPlugin.getClassLoader());
|
loaders0.put(pluginName, (PluginClassLoader) jPlugin.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -383,9 +466,7 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void disablePlugin(Plugin plugin) {
|
public void disablePlugin(Plugin plugin) {
|
||||||
if (!(plugin instanceof JavaPlugin)) {
|
Validate.isTrue(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader");
|
||||||
throw new IllegalArgumentException("Plugin is not associated with this PluginLoader");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (plugin.isEnabled()) {
|
if (plugin.isEnabled()) {
|
||||||
String message = String.format("Disabling %s", plugin.getDescription().getFullName());
|
String message = String.format("Disabling %s", plugin.getDescription().getFullName());
|
||||||
@ -402,14 +483,18 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
loaders.remove(jPlugin.getDescription().getName());
|
loaders0.remove(jPlugin.getDescription().getName());
|
||||||
|
|
||||||
if (cloader instanceof PluginClassLoader) {
|
if (cloader instanceof PluginClassLoader) {
|
||||||
PluginClassLoader loader = (PluginClassLoader) cloader;
|
PluginClassLoader loader = (PluginClassLoader) cloader;
|
||||||
Set<String> names = loader.getClasses();
|
Set<String> names = loader.extended ? loader.getClasses() : loader.getClasses0(); // Don't warn on deprecation, but maintain overridability
|
||||||
|
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
removeClass(name);
|
if (extended) {
|
||||||
|
removeClass(name);
|
||||||
|
} else {
|
||||||
|
removeClass0(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ import java.net.URLClassLoader;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.plugin.AuthorNagException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ClassLoader for plugins, to allow shared classes across multiple plugins
|
* A ClassLoader for plugins, to allow shared classes across multiple plugins
|
||||||
@ -12,9 +16,29 @@ import java.util.Set;
|
|||||||
public class PluginClassLoader extends URLClassLoader {
|
public class PluginClassLoader extends URLClassLoader {
|
||||||
private final JavaPluginLoader loader;
|
private final JavaPluginLoader loader;
|
||||||
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
|
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
|
||||||
|
final boolean extended = this.getClass() != PluginClassLoader.class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal class not intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public PluginClassLoader(final JavaPluginLoader loader, final URL[] urls, final ClassLoader parent) {
|
public PluginClassLoader(final JavaPluginLoader loader, final URL[] urls, final ClassLoader parent) {
|
||||||
|
this(loader, urls, parent, null);
|
||||||
|
|
||||||
|
if (loader.warn) {
|
||||||
|
if (extended) {
|
||||||
|
loader.server.getLogger().log(Level.WARNING, "PluginClassLoader not intended to be extended by " + getClass() + ", and may be final in a future version of Bukkit");
|
||||||
|
} else {
|
||||||
|
loader.server.getLogger().log(Level.WARNING, "Constructor \"public PluginClassLoader(JavaPluginLoader, URL[], ClassLoader)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
}
|
||||||
|
loader.warn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PluginClassLoader(final JavaPluginLoader loader, final URL[] urls, final ClassLoader parent, final Object methodSignature) {
|
||||||
super(urls, parent);
|
super(urls, parent);
|
||||||
|
Validate.notNull(loader, "Loader cannot be null");
|
||||||
|
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
}
|
}
|
||||||
@ -26,10 +50,22 @@ public class PluginClassLoader extends URLClassLoader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||||
return findClass(name, true);
|
return extended ? findClass(name, true) : findClass0(name, true); // Don't warn on deprecation, but maintain overridability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException {
|
protected Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException {
|
||||||
|
if (loader.warn) {
|
||||||
|
loader.server.getLogger().log(Level.WARNING, "Method \"protected Class<?> findClass(String, boolean)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
loader.warn = false;
|
||||||
|
}
|
||||||
|
return findClass0(name, checkGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> findClass0(String name, boolean checkGlobal) throws ClassNotFoundException {
|
||||||
if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
|
if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
|
||||||
throw new ClassNotFoundException(name);
|
throw new ClassNotFoundException(name);
|
||||||
}
|
}
|
||||||
@ -37,14 +73,18 @@ public class PluginClassLoader extends URLClassLoader {
|
|||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
if (checkGlobal) {
|
if (checkGlobal) {
|
||||||
result = loader.getClassByName(name);
|
result = loader.extended ? loader.getClassByName(name) : loader.getClassByName0(name); // Don't warn on deprecation, but maintain overridability
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = super.findClass(name);
|
result = super.findClass(name);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
loader.setClass(name, result);
|
if (loader.extended) { // Don't warn on deprecation, but maintain overridability
|
||||||
|
loader.setClass(name, result);
|
||||||
|
} else {
|
||||||
|
loader.setClass0(name, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +94,19 @@ public class PluginClassLoader extends URLClassLoader {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Internal method that wasn't intended to be exposed
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Set<String> getClasses() {
|
public Set<String> getClasses() {
|
||||||
|
if (loader.warn) {
|
||||||
|
loader.server.getLogger().log(Level.WARNING, "Method \"public Set<String> getClasses()\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException(""));
|
||||||
|
loader.warn = false;
|
||||||
|
}
|
||||||
|
return getClasses0();
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> getClasses0() {
|
||||||
return classes.keySet();
|
return classes.keySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user