cn.nukkit.plugin.JavaPluginLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of powernukkit Show documentation
Show all versions of powernukkit Show documentation
A Minecraft Bedrock Edition server software implementation made in Java from scratch which supports all new features.
package cn.nukkit.plugin;
import cn.nukkit.Server;
import cn.nukkit.api.PowerNukkitDifference;
import cn.nukkit.event.plugin.PluginDisableEvent;
import cn.nukkit.event.plugin.PluginEnableEvent;
import cn.nukkit.utils.PluginException;
import cn.nukkit.utils.Utils;
import lombok.extern.log4j.Log4j2;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
/**
* @author Nukkit Team.
*/
@Log4j2
public class JavaPluginLoader implements PluginLoader {
private final Server server;
private final Map classes = new HashMap<>();
private final Map classLoaders = new HashMap<>();
public JavaPluginLoader(Server server) {
this.server = server;
}
@Override
public Plugin loadPlugin(File file) throws Exception {
PluginDescription description = this.getPluginDescription(file);
if (description != null) {
log.info(this.server.getLanguage().translateString("nukkit.plugin.load", description.getFullName()));
File dataFolder = new File(file.getParentFile(), description.getName());
if (dataFolder.exists() && !dataFolder.isDirectory()) {
throw new IllegalStateException("Projected dataFolder '" + dataFolder.toString() + "' for " + description.getName() + " exists and is not a directory");
}
String className = description.getMain();
PluginClassLoader classLoader = new PluginClassLoader(this, this.getClass().getClassLoader(), file);
this.classLoaders.put(description.getName(), classLoader);
PluginBase plugin;
try {
Class javaClass = classLoader.loadClass(className);
if (!PluginBase.class.isAssignableFrom(javaClass)) {
throw new PluginException("Main class `" + description.getMain() + "' does not extend PluginBase");
}
try {
Class pluginClass = (Class) javaClass.asSubclass(PluginBase.class);
plugin = pluginClass.newInstance();
this.initPlugin(plugin, description, dataFolder, file);
return plugin;
} catch (ClassCastException e) {
throw new PluginException("Error whilst initializing main class `" + description.getMain() + "'", e);
} catch (InstantiationException | IllegalAccessException e) {
log.error("An exception happened while initializing the plgin {}, {}, {}, {}", file, className, description.getName(), description.getVersion(), e);
}
} catch (ClassNotFoundException e) {
throw new PluginException("Couldn't load plugin " + description.getName() + ": main class not found");
}
}
return null;
}
@Override
public Plugin loadPlugin(String filename) throws Exception {
return this.loadPlugin(new File(filename));
}
@Override
public PluginDescription getPluginDescription(File file) {
try (JarFile jar = new JarFile(file)) {
JarEntry entry = jar.getJarEntry("nukkit.yml");
if (entry == null) {
entry = jar.getJarEntry("plugin.yml");
if (entry == null) {
return null;
}
}
try (InputStream stream = jar.getInputStream(entry)) {
return new PluginDescription(Utils.readFile(stream));
}
} catch (IOException e) {
return null;
}
}
@Override
public PluginDescription getPluginDescription(String filename) {
return this.getPluginDescription(new File(filename));
}
@Override
public Pattern[] getPluginFilters() {
return new Pattern[]{Pattern.compile("^.+\\.jar$")};
}
private void initPlugin(PluginBase plugin, PluginDescription description, File dataFolder, File file) {
plugin.init(this, this.server, description, dataFolder, file);
plugin.onLoad();
}
@Override
public void enablePlugin(Plugin plugin) {
if (plugin instanceof PluginBase && !plugin.isEnabled()) {
log.info(this.server.getLanguage().translateString("nukkit.plugin.enable", plugin.getDescription().getFullName()));
((PluginBase) plugin).setEnabled(true);
this.server.getPluginManager().callEvent(new PluginEnableEvent(plugin));
}
}
@PowerNukkitDifference(info = "Made impossible to disable special the PowerNukkitPlugin", since = "1.3.0.0-PN")
@Override
public void disablePlugin(Plugin plugin) {
if (plugin instanceof PluginBase && plugin.isEnabled()) {
if (plugin == PowerNukkitPlugin.getInstance()) {
throw new UnsupportedOperationException("The PowerNukkitPlugin cannot be disabled");
}
log.info(this.server.getLanguage().translateString("nukkit.plugin.disable", plugin.getDescription().getFullName()));
this.server.getServiceManager().cancel(plugin);
this.server.getPluginManager().callEvent(new PluginDisableEvent(plugin));
((PluginBase) plugin).setEnabled(false);
}
}
Class> getClassByName(final String name) {
Class> cachedClass = classes.get(name);
if (cachedClass != null) {
return cachedClass;
} else {
for (PluginClassLoader loader : this.classLoaders.values()) {
try {
cachedClass = loader.findClass(name, false);
} catch (ClassNotFoundException e) {
//ignore
}
if (cachedClass != null) {
return cachedClass;
}
}
}
return null;
}
void setClass(final String name, final Class> clazz) {
if (!classes.containsKey(name)) {
classes.put(name, clazz);
}
}
private void removeClass(String name) {
Class> clazz = classes.remove(name);
}
}