diff options
Diffstat (limited to 'src/main/java')
4 files changed, 165 insertions, 248 deletions
diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java index d2a59e40..1d79e637 100644 --- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java @@ -773,6 +773,10 @@ public final class PluginDescriptionFile { return name + " v" + version; } + /** + * @deprecated unused + */ + @Deprecated public String getClassLoaderOf() { return classLoaderOf; } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java index 3815da22..bdecbea2 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -13,12 +13,14 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.bukkit.Server; +import org.bukkit.Warning.WarningState; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.generator.ChunkGenerator; +import org.bukkit.plugin.AuthorNagException; import org.bukkit.plugin.PluginBase; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginLoader; @@ -36,7 +38,6 @@ import com.avaje.ebeaninternal.server.ddl.DdlGenerator; */ public abstract class JavaPlugin extends PluginBase { private boolean isEnabled = false; - private boolean initialized = false; private PluginLoader loader = null; private Server server = null; private File file = null; @@ -49,7 +50,37 @@ public abstract class JavaPlugin extends PluginBase { private File configFile = null; private PluginLogger logger = null; - public JavaPlugin() {} + public JavaPlugin() { + final ClassLoader classLoader = this.getClass().getClassLoader(); + if (!(classLoader instanceof PluginClassLoader)) { + throw new IllegalStateException("JavaPlugin requires " + PluginClassLoader.class.getName()); + } + ((PluginClassLoader) classLoader).initialize(this); + } + + /** + * @deprecated This method is intended for unit testing purposes when the + * other {@linkplain #JavaPlugin(JavaPluginLoader, + * PluginDescriptionFile, File, File) constructor} cannot be used. + * <p> + * Its existence may be temporary. + */ + @Deprecated + protected JavaPlugin(final PluginLoader loader, final Server server, final PluginDescriptionFile description, final File dataFolder, final File file) { + final ClassLoader classLoader = this.getClass().getClassLoader(); + if (classLoader instanceof PluginClassLoader) { + throw new IllegalStateException("Cannot use initialization constructor at runtime"); + } + init(loader, server, description, dataFolder, file, classLoader); + } + + protected JavaPlugin(final JavaPluginLoader loader, final PluginDescriptionFile description, final File dataFolder, final File file) { + final ClassLoader classLoader = this.getClass().getClassLoader(); + if (classLoader instanceof PluginClassLoader) { + throw new IllegalStateException("Cannot use initialization constructor at runtime"); + } + init(loader, loader.server, description, dataFolder, file, classLoader); + } /** * Returns the folder that the plugin data's files are located in. The @@ -223,50 +254,46 @@ public abstract class JavaPlugin extends PluginBase { } /** - * Initializes this plugin with the given variables. - * <p> - * This method should never be called manually. - * - * @param loader PluginLoader that is responsible for this plugin - * @param server Server instance that is running this plugin - * @param description PluginDescriptionFile containing metadata on this - * plugin - * @param dataFolder Folder containing the plugin's data - * @param file File containing this plugin - * @param classLoader ClassLoader which holds this plugin + * @deprecated This method is legacy and will be removed - it must be + * replaced by the specially provided constructor(s). */ + @Deprecated protected final void initialize(PluginLoader loader, Server server, PluginDescriptionFile description, File dataFolder, File file, ClassLoader classLoader) { - if (!initialized) { - this.initialized = true; - this.loader = loader; - this.server = server; - this.file = file; - this.description = description; - this.dataFolder = dataFolder; - this.classLoader = classLoader; - this.configFile = new File(dataFolder, "config.yml"); - this.logger = new PluginLogger(this); - - if (description.isDatabaseEnabled()) { - ServerConfig db = new ServerConfig(); - - db.setDefaultServer(false); - db.setRegister(false); - db.setClasses(getDatabaseClasses()); - db.setName(description.getName()); - server.configureDbConfig(db); - - DataSourceConfig ds = db.getDataSourceConfig(); - - ds.setUrl(replaceDatabaseString(ds.getUrl())); - dataFolder.mkdirs(); - - ClassLoader previous = Thread.currentThread().getContextClassLoader(); - - Thread.currentThread().setContextClassLoader(classLoader); - ebean = EbeanServerFactory.create(db); - Thread.currentThread().setContextClassLoader(previous); - } + if (server.getWarningState() == WarningState.OFF) { + return; + } + getLogger().log(Level.WARNING, getClass().getName() + " is already initialized", server.getWarningState() == WarningState.DEFAULT ? null : new AuthorNagException("Explicit initialization")); + } + + final void init(PluginLoader loader, Server server, PluginDescriptionFile description, File dataFolder, File file, ClassLoader classLoader) { + this.loader = loader; + this.server = server; + this.file = file; + this.description = description; + this.dataFolder = dataFolder; + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); + this.logger = new PluginLogger(this); + + if (description.isDatabaseEnabled()) { + ServerConfig db = new ServerConfig(); + + db.setDefaultServer(false); + db.setRegister(false); + db.setClasses(getDatabaseClasses()); + db.setName(description.getName()); + server.configureDbConfig(db); + + DataSourceConfig ds = db.getDataSourceConfig(); + + ds.setUrl(replaceDatabaseString(ds.getUrl())); + dataFolder.mkdirs(); + + ClassLoader previous = Thread.currentThread().getContextClassLoader(); + + Thread.currentThread().setContextClassLoader(classLoader); + ebean = EbeanServerFactory.create(db); + Thread.currentThread().setContextClassLoader(previous); } } @@ -289,9 +316,12 @@ public abstract class JavaPlugin extends PluginBase { * Gets the initialization status of this plugin * * @return true if this plugin is initialized, otherwise false + * @deprecated This method cannot return false, as {@link + * JavaPlugin} is now initialized in the constructor. */ + @Deprecated public final boolean isInitialized() { - return initialized; + return true; } /** diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index ea30d83d..57681dc4 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -4,10 +4,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URL; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -49,44 +47,19 @@ import com.google.common.collect.ImmutableList; /** * Represents a Java plugin loader, allowing plugins in the form of .jar */ -public class JavaPluginLoader implements PluginLoader { +public final class JavaPluginLoader implements PluginLoader { final Server server; - final boolean extended = this.getClass() != JavaPluginLoader.class; - boolean warn; + private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), }; + private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>(); + private 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 + * This class was not meant to be constructed explicitly */ @Deprecated public JavaPluginLoader(Server instance) { Validate.notNull(instance, "Server cannot be null"); 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 { @@ -104,7 +77,7 @@ public class JavaPluginLoader implements PluginLoader { } File dataFolder = new File(file.getParentFile(), description.getName()); - File oldDataFolder = extended ? getDataFolder(file) : getDataFolder0(file); // Don't warn on deprecation, but maintain overridability + File oldDataFolder = getDataFolder(file); // Found old data folder if (dataFolder.equals(oldDataFolder)) { @@ -145,75 +118,31 @@ public class JavaPluginLoader implements PluginLoader { } for (String pluginName : depend) { - if (loaders0 == null) { + if (loaders == null) { throw new UnknownDependencyException(pluginName); } - PluginClassLoader current = loaders0.get(pluginName); + PluginClassLoader current = loaders.get(pluginName); if (current == null) { throw new UnknownDependencyException(pluginName); } } - PluginClassLoader loader = null; - JavaPlugin result = null; - + PluginClassLoader loader; try { - URL[] urls = new URL[1]; - - urls[0] = file.toURI().toURL(); - - if (description.getClassLoaderOf() != null) { - loader = loaders0.get(description.getClassLoaderOf()); - loader.addURL(urls[0]); - } else { - loader = new PluginClassLoader(this, urls, getClass().getClassLoader(), null); - } - - Class<?> jarClass = Class.forName(description.getMain(), true, loader); - Class<? extends JavaPlugin> plugin = jarClass.asSubclass(JavaPlugin.class); - - Constructor<? extends JavaPlugin> constructor = plugin.getConstructor(); - - result = constructor.newInstance(); - - result.initialize(this, server, description, dataFolder, file, loader); - } catch (InvocationTargetException ex) { - throw new InvalidPluginException(ex.getCause()); + loader = new PluginClassLoader(this, getClass().getClassLoader(), description, dataFolder, file); + } catch (InvalidPluginException ex) { + throw ex; } catch (Throwable ex) { throw new InvalidPluginException(ex); } - loaders0.put(description.getName(), loader); + loaders.put(description.getName(), loader); - return result; + return loader.plugin; } - /** - * @deprecated Relic method from PluginLoader that didn't get purged - */ - @Deprecated - 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); - } - - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - 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) { + private File getDataFolder(File file) { File dataFolder = null; String filename = file.getName(); @@ -272,32 +201,20 @@ public class JavaPluginLoader implements PluginLoader { } public Pattern[] getPluginFileFilters() { - return fileFilters0.clone(); - } - - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - public Class<?> getClassByName(final String name) { - if (warn) { - server.getLogger().log(Level.WARNING, "Method \"public Class<?> getClassByName(String)\" is Deprecated, and may be removed in a future version of Bukkit", new AuthorNagException("")); - warn = false; - } - return getClassByName0(name); + return fileFilters.clone(); } - Class<?> getClassByName0(final String name) { - Class<?> cachedClass = classes0.get(name); + Class<?> getClassByName(final String name) { + Class<?> cachedClass = classes.get(name); if (cachedClass != null) { return cachedClass; } else { - for (String current : loaders0.keySet()) { - PluginClassLoader loader = loaders0.get(current); + for (String current : loaders.keySet()) { + PluginClassLoader loader = loaders.get(current); try { - cachedClass = loader.extended ? loader.findClass(name, false) : loader.findClass0(name, false); // Don't warn on deprecation, but maintain overridability + cachedClass = loader.findClass(name, false); } catch (ClassNotFoundException cnfe) {} if (cachedClass != null) { return cachedClass; @@ -307,21 +224,9 @@ public class JavaPluginLoader implements PluginLoader { return null; } - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - public void setClass(final String name, final Class<?> clazz) { - if (warn) { - server.getLogger().log(Level.WARNING, "Method \"public void setClass(String, Class<?>)\" 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); + void setClass(final String name, final Class<?> clazz) { + if (!classes.containsKey(name)) { + classes.put(name, clazz); if (ConfigurationSerializable.class.isAssignableFrom(clazz)) { Class<? extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class); @@ -330,20 +235,8 @@ public class JavaPluginLoader implements PluginLoader { } } - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - public void removeClass(String 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); + private void removeClass(String name) { + Class<?> clazz = classes.remove(name); try { if ((clazz != null) && (ConfigurationSerializable.class.isAssignableFrom(clazz))) { @@ -449,8 +342,8 @@ public class JavaPluginLoader implements PluginLoader { String pluginName = jPlugin.getDescription().getName(); - if (!loaders0.containsKey(pluginName)) { - loaders0.put(pluginName, (PluginClassLoader) jPlugin.getClassLoader()); + if (!loaders.containsKey(pluginName)) { + loaders.put(pluginName, (PluginClassLoader) jPlugin.getClassLoader()); } try { @@ -483,18 +376,14 @@ public class JavaPluginLoader implements PluginLoader { server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); } - loaders0.remove(jPlugin.getDescription().getName()); + loaders.remove(jPlugin.getDescription().getName()); if (cloader instanceof PluginClassLoader) { PluginClassLoader loader = (PluginClassLoader) cloader; - Set<String> names = loader.extended ? loader.getClasses() : loader.getClasses0(); // Don't warn on deprecation, but maintain overridability + Set<String> names = loader.getClasses(); for (String name : names) { - if (extended) { - removeClass(name); - } else { - removeClass0(name); - } + removeClass(name); } } } diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java index 29ec3fc4..c34fb2dc 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -1,71 +1,68 @@ package org.bukkit.plugin.java; +import java.io.File; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.logging.Level; import org.apache.commons.lang.Validate; -import org.bukkit.plugin.AuthorNagException; +import org.bukkit.plugin.InvalidPluginException; +import org.bukkit.plugin.PluginDescriptionFile; /** * A ClassLoader for plugins, to allow shared classes across multiple plugins */ -public class PluginClassLoader extends URLClassLoader { +final class PluginClassLoader extends URLClassLoader { private final JavaPluginLoader loader; 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) { - 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); + private final PluginDescriptionFile description; + private final File dataFolder; + private final File file; + final JavaPlugin plugin; + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + + PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException { + super(new URL[] {file.toURI().toURL()}, parent); Validate.notNull(loader, "Loader cannot be null"); this.loader = loader; - } + this.description = description; + this.dataFolder = dataFolder; + this.file = file; + + try { + Class<?> jarClass; + try { + jarClass = Class.forName(description.getMain(), true, this); + } catch (ClassNotFoundException ex) { + throw new InvalidPluginException("Cannot find main class `" + description.getMain() + "'", ex); + } - @Override - public void addURL(URL url) { // Override for access level! - super.addURL(url); + Class<? extends JavaPlugin> pluginClass; + try { + pluginClass = jarClass.asSubclass(JavaPlugin.class); + } catch (ClassCastException ex) { + throw new InvalidPluginException("main class `" + description.getMain() + "' does not extend JavaPlugin", ex); + } + + plugin = pluginClass.newInstance(); + } catch (IllegalAccessException ex) { + throw new InvalidPluginException("No public constructor", ex); + } catch (InstantiationException ex) { + throw new InvalidPluginException("Abnormal plugin type", ex); + } } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { - return extended ? findClass(name, true) : findClass0(name, true); // Don't warn on deprecation, but maintain overridability + return findClass(name, true); } - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - 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 { + Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException { if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) { throw new ClassNotFoundException(name); } @@ -73,18 +70,14 @@ public class PluginClassLoader extends URLClassLoader { if (result == null) { if (checkGlobal) { - result = loader.extended ? loader.getClassByName(name) : loader.getClassByName0(name); // Don't warn on deprecation, but maintain overridability + result = loader.getClassByName(name); } if (result == null) { result = super.findClass(name); if (result != null) { - if (loader.extended) { // Don't warn on deprecation, but maintain overridability - loader.setClass(name, result); - } else { - loader.setClass0(name, result); - } + loader.setClass(name, result); } } @@ -94,19 +87,20 @@ public class PluginClassLoader extends URLClassLoader { return result; } - /** - * @deprecated Internal method that wasn't intended to be exposed - */ - @Deprecated - 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> getClasses() { + return classes.keySet(); } - Set<String> getClasses0() { - return classes.keySet(); + synchronized void initialize(JavaPlugin javaPlugin) { + Validate.notNull(javaPlugin, "Initializing plugin cannot be null"); + Validate.isTrue(javaPlugin.getClass().getClassLoader() == this, "Cannot initialize plugin outside of this class loader"); + if (this.plugin != null || this.pluginInit != null) { + throw new IllegalArgumentException("Plugin already intialized!", pluginState); + } + + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + + javaPlugin.init(loader, loader.server, description, dataFolder, file, this); } } |