Adds basic plugin dependencies, courtesy of Raphfrk

By: Dinnerbone <dinnerbone@dinnerbone.com>
This commit is contained in:
Bukkit/Spigot 2011-03-07 13:56:34 +00:00
parent f370268047
commit 6dc6946312
9 changed files with 183 additions and 24 deletions

View File

@ -8,6 +8,7 @@ import org.bukkit.*;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.UnknownDependencyException;
public class Getter {
private Server server;
@ -40,6 +41,8 @@ public class Getter {
File plugin = new File(DIRECTORY, name + ".jar");
try {
server.getPluginManager().loadPlugin(plugin);
} catch (UnknownDependencyException ex) {
server.getLogger().log(Level.SEVERE, null, ex);
} catch (InvalidPluginException ex) {
server.getLogger().log(Level.SEVERE, null, ex);
} catch (InvalidDescriptionException ex) {

View File

@ -98,6 +98,8 @@ public class Updater {
File plugin = new File(DIRECTORY, name + ".jar");
try {
server.getPluginManager().loadPlugin(plugin);
} catch (UnknownDependencyException ex) {
server.getLogger().log(Level.SEVERE, null, ex);
} catch (InvalidPluginException ex) {
server.getLogger().log(Level.SEVERE, null, ex);
} catch (InvalidDescriptionException ex) {

View File

@ -7,6 +7,7 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
@ -18,6 +19,7 @@ public final class PluginDescriptionFile {
private static final Yaml yaml = new Yaml(new SafeConstructor());
private String name = null;
private String main = null;
private ArrayList<String> depend = null;
private String version = null;
private Object commands = null;
private String description = null;
@ -99,6 +101,10 @@ public final class PluginDescriptionFile {
return commands;
}
public Object getDepend() {
return depend;
}
/**
* Gets the description of this plugin
*
@ -149,6 +155,14 @@ public final class PluginDescriptionFile {
}
}
if (map.containsKey("depend")) {
try {
depend = (ArrayList<String>)map.get("depend");
} catch (ClassCastException ex) {
throw new InvalidDescriptionException(ex, "depend is of wrong type");
}
}
if (map.containsKey("website")) {
try {
website = (String)map.get("website");
@ -191,6 +205,7 @@ public final class PluginDescriptionFile {
map.put("version", version);
if (commands != null) map.put("command", commands);
if (depend != null) map.put("depend", depend);
if (website != null) map.put("website", website);
if (description != null) map.put("description", description);

View File

@ -20,7 +20,7 @@ public interface PluginLoader {
* unsuccessful
* @throws InvalidPluginException Thrown when the specified file is not a plugin
*/
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException;
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException;
/**
* Returns a list of all filename filters expected by this PluginLoader

View File

@ -65,7 +65,7 @@ public interface PluginManager {
* @throws InvalidPluginException Thrown when the specified file is not a valid plugin
* @throws InvalidDescriptionException Thrown when the specified file contains an invalid description
*/
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException;
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException;
/**
* Loads the plugins contained within the specified directory

View File

@ -12,6 +12,9 @@ import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@ -88,19 +91,45 @@ public final class SimplePluginManager implements PluginManager {
List<Plugin> result = new ArrayList<Plugin>();
File[] files = directory.listFiles();
for (File file : files) {
Plugin plugin = null;
boolean allFailed = false;
boolean finalPass = false;
try {
plugin = loadPlugin(file);
} catch (InvalidPluginException ex) {
server.getLogger().log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath() + ": " + ex.getMessage(), ex);
} catch (InvalidDescriptionException ex) {
server.getLogger().log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath() + ": " + ex.getMessage(), ex);
LinkedList<File> filesList = new LinkedList(Arrays.asList(files));
while(!allFailed || finalPass) {
allFailed = true;
Iterator<File> itr = filesList.iterator();
while(itr.hasNext()) {
File file = itr.next();
Plugin plugin = null;
try {
plugin = loadPlugin(file);
itr.remove();
} catch (UnknownDependencyException ex) {
if(finalPass) {
server.getLogger().log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath() + ": " + ex.getMessage(), ex);
itr.remove();
} else {
plugin = null;
}
} catch (InvalidPluginException ex) {
server.getLogger().log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath() + ": " + ex.getMessage(), ex);
itr.remove();
} catch (InvalidDescriptionException ex) {
server.getLogger().log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath() + ": " + ex.getMessage(), ex);
itr.remove();
}
if (plugin != null) {
result.add(plugin);
allFailed = false;
}
}
if (plugin != null) {
result.add(plugin);
if(finalPass) {
break;
} else if(allFailed) {
finalPass = true;
}
}
@ -117,7 +146,7 @@ public final class SimplePluginManager implements PluginManager {
* @throws InvalidPluginException Thrown when the specified file is not a valid plugin
* @throws InvalidDescriptionException Thrown when the specified file contains an invalid description
*/
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException {
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
Set<Pattern> filters = fileAssociations.keySet();
Plugin result = null;

View File

@ -0,0 +1,63 @@
package org.bukkit.plugin;
/**
* Thrown when attempting to load an invalid Plugin file
*/
public class UnknownDependencyException extends Exception {
private static final long serialVersionUID = 5721389371901775894L;
private final Throwable cause;
private final String message;
/**
* Constructs a new UnknownDependencyException based on the given Exception
*
* @param throwable Exception that triggered this Exception
*/
public UnknownDependencyException(Throwable throwable) {
this(throwable, "Unknown dependency");
}
/**
* Constructs a new UnknownDependencyException with the given message
*
* @param message Brief message explaining the cause of the exception
*/
public UnknownDependencyException(final String message) {
this(null, message);
}
/**
* Constructs a new UnknownDependencyException based on the given Exception
*
* @param message Brief message explaining the cause of the exception
* @param throwable Exception that triggered this Exception
*/
public UnknownDependencyException(final Throwable throwable, final String message) {
this.cause = null;
this.message = message;
}
/**
* Constructs a new UnknownDependencyException
*/
public UnknownDependencyException() {
this(null, "Unknown dependency");
}
/**
* If applicable, returns the Exception that triggered this Exception
*
* @return Inner exception, or null if one does not exist
*/
@Override
public Throwable getCause() {
return cause;
}
@Override
public String getMessage() {
return message;
}
}

View File

@ -9,6 +9,9 @@ import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.util.Map;
import java.util.ArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
@ -36,12 +39,13 @@ public final class JavaPluginLoader implements PluginLoader {
Pattern.compile("\\.jar$"),
};
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
private final Map<String, File> files = new HashMap<String, File>();
public JavaPluginLoader(Server instance) {
server = instance;
}
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException {
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
JavaPlugin result = null;
PluginDescriptionFile description = null;
@ -67,8 +71,37 @@ public final class JavaPluginLoader implements PluginLoader {
File dataFolder = getDataFolder(file);
ArrayList<String> depend;
try {
ClassLoader loader = new PluginClassLoader(this, new URL[]{file.toURI().toURL()}, getClass().getClassLoader());
depend = (ArrayList)description.getDepend();
if(depend == null) {
depend = new ArrayList<String>();
}
} catch (ClassCastException ex) {
throw new InvalidPluginException(ex);
}
ArrayList<File> dependFiles = new ArrayList<File>();
for(String pluginName : depend) {
if(files == null) {
throw new UnknownDependencyException(pluginName);
}
File current = files.get(pluginName);
if(current == null) {
throw new UnknownDependencyException(pluginName);
}
dependFiles.add(current);
}
try {
URL[] urls = new URL[dependFiles.size() + 1];
urls[0] = file.toURI().toURL();
int cnt = 1;
for(File f : dependFiles) {
urls[cnt++] = f.toURI().toURL();
}
ClassLoader loader = new PluginClassLoader(this, urls, getClass().getClassLoader());
Class<?> jarClass = Class.forName(description.getMain(), true, loader);
Class<? extends JavaPlugin> plugin = jarClass.asSubclass(JavaPlugin.class);
@ -80,6 +113,8 @@ public final class JavaPluginLoader implements PluginLoader {
throw new InvalidPluginException(ex);
}
files.put(description.getName(), file);
return (Plugin)result;
}
@ -112,7 +147,9 @@ public final class JavaPluginLoader implements PluginLoader {
}
public void setClass(final String name, final Class<?> clazz) {
classes.put(name, clazz);
if(!classes.containsKey(name)) {
classes.put(name, clazz);
}
}
public EventExecutor createExecutor( Event.Type type, Listener listener ) {
@ -429,6 +466,8 @@ public final class JavaPluginLoader implements PluginLoader {
server.getPluginManager().callEvent(new PluginEvent(Event.Type.PLUGIN_DISABLE, plugin));
files.remove(jPlugin.getDescription().getName());
if (cloader instanceof PluginClassLoader) {
PluginClassLoader loader = (PluginClassLoader)cloader;
Set<String> names = loader.getClasses();

View File

@ -24,17 +24,25 @@ public class PluginClassLoader extends URLClassLoader {
Class<?> result = classes.get(name);
if (result == null) {
result = loader.getClassByName(name);
ClassNotFoundException ex = null;
if (result == null) {
try {
result = super.findClass(name);
if (result != null) {
loader.setClass(name, result);
}
} catch (ClassNotFoundException e) {
ex = e;
}
classes.put(name, result);
if (result != null) {
loader.setClass(name, result);
} else {
result = loader.getClassByName(name);
}
if (result != null ) {
classes.put(name, result);
} else {
throw ex;
}
}
return result;