BSkyBlock/src/main/java/us/tastybento/bskyblock/api/addons/AddonClassLoader.java

139 lines
4.8 KiB
Java

package us.tastybento.bskyblock.api.addons;
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 org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.util.permissions.DefaultPermissions;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.addons.AddonDescription.AddonDescriptionBuilder;
import us.tastybento.bskyblock.api.addons.exception.InvalidAddonFormatException;
import us.tastybento.bskyblock.api.addons.exception.InvalidAddonInheritException;
import us.tastybento.bskyblock.managers.AddonsManager;
/**
* Loads addons and sets up permissions
* @author Tastybento, ComminQ
*/
public class AddonClassLoader extends URLClassLoader {
private final Map<String, Class<?>> classes = new HashMap<>();
private Addon addon;
private AddonsManager loader;
public AddonClassLoader(AddonsManager addonsManager, YamlConfiguration data, File path, ClassLoader parent)
throws InvalidAddonInheritException,
MalformedURLException,
InvalidAddonFormatException,
InvalidDescriptionException,
InstantiationException,
IllegalAccessException {
super(new URL[]{path.toURI().toURL()}, parent);
loader = addonsManager;
Class<?> javaClass;
try {
String mainClass = data.getString("main");
javaClass = Class.forName(mainClass, true, this);
if(mainClass.contains("us.tastybento")){
throw new InvalidAddonFormatException("Packages declaration cannot start with 'us.tastybento'");
}
} catch (ClassNotFoundException e) {
BSkyBlock.getInstance().logError("Could not load '" + path.getName() + "' in folder '" + path.getParent() + "' - invalid addon.yml");
throw new InvalidDescriptionException("Invalid addon.yml");
}
Class<? extends Addon> addonClass;
try{
addonClass = javaClass.asSubclass(Addon.class);
} catch(ClassCastException e){
throw new InvalidAddonInheritException("Main class doesn't not extends super class 'Addon'");
}
addon = addonClass.newInstance();
addon.setDescription(asDescription(data));
// Set permissions
if (data.isConfigurationSection("permissions")) {
ConfigurationSection perms = data.getConfigurationSection("permissions");
perms.getKeys(true).forEach(perm -> {
if (perms.contains(perm + ".default") && perms.contains(perm + ".description")) {
registerPermission(perms, perm);
}
});
}
}
private void registerPermission(ConfigurationSection perms, String perm) {
PermissionDefault pd = PermissionDefault.getByName(perms.getString(perm + ".default"));
if (pd == null) {
Bukkit.getLogger().severe("Permission default is invalid : " + perms.getName());
return;
}
String desc = perms.getString(perm + ".description");
DefaultPermissions.registerPermission(perm, desc, pd);
}
private AddonDescription asDescription(YamlConfiguration data){
return new AddonDescriptionBuilder(data.getString("name"))
.withVersion(data.getString("version"))
.withAuthor(data.getString("authors")).build();
}
/* (non-Javadoc)
* @see java.net.URLClassLoader#findClass(java.lang.String)
*/
@Override
protected Class<?> findClass(String name) {
return findClass(name, true);
}
/**
* This is a custom findClass that enables classes in other addons to be found
* @param name - class name
* @param checkGlobal - check globally or not when searching
* @return Class - class if found
*/
public Class<?> findClass(String name, boolean checkGlobal) {
if (name.startsWith("us.tastybento.")) {
return null;
}
Class<?> result = classes.get(name);
if (result == null) {
if (checkGlobal) {
result = loader.getClassByName(name);
}
if (result == null) {
try {
result = super.findClass(name);
} catch (ClassNotFoundException e) {
return null;
}
if (result != null) {
loader.setClass(name, result);
}
classes.put(name, result);
}
}
return result;
}
/**
* @return the addon
*/
public Addon getAddon() {
return addon;
}
}