diff --git a/src/main/java/org/sculk/plugin/Plugin.java b/src/main/java/org/sculk/plugin/Plugin.java index 782cef6..f006162 100644 --- a/src/main/java/org/sculk/plugin/Plugin.java +++ b/src/main/java/org/sculk/plugin/Plugin.java @@ -1,6 +1,7 @@ package org.sculk.plugin; import com.google.common.base.Preconditions; +import lombok.Getter; import org.apache.logging.log4j.Logger; import org.sculk.Server; @@ -10,6 +11,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; +@Getter public abstract class Plugin { protected boolean enabled = false; private PluginData description; @@ -19,9 +21,6 @@ public abstract class Plugin { private File dataFolder; private boolean initialized = false; - public Plugin() { - } - protected final void init(PluginData description, Server server, File pluginFile) { Preconditions.checkArgument(!this.initialized, "Plugin has been already initialized!"); this.initialized = true; @@ -31,8 +30,10 @@ protected final void init(PluginData description, Server server, File pluginFile this.pluginFile = pluginFile; this.dataFolder = new File(Server.getInstance().getDataPath() + "/plugins/" + description.getName().toLowerCase() + "/"); - if (!this.dataFolder.exists()) { - this.dataFolder.mkdirs(); + + if (this.dataFolder.mkdirs()) { + this.logger.info("Created plugin data folder"); + } } @@ -45,52 +46,31 @@ public void onDisable() { } public InputStream getResourceFile(String filename) { - try { - JarFile pluginJar = new JarFile(this.pluginFile); - JarEntry entry = pluginJar.getJarEntry(filename); - return pluginJar.getInputStream(entry); + try(JarFile jar = new JarFile(this.pluginFile)) { + JarEntry entry = jar.getJarEntry(filename); + return jar.getInputStream(entry); } catch (IOException e) { + return null; } - return null; - } - - public boolean isEnabled() { - return this.enabled; } public void setEnabled(boolean enabled) { - if (this.enabled == enabled) { - return; - } - this.enabled = enabled; - try { - if (enabled) { - this.onEnable(); - } else { - this.onDisable(); + if (this.enabled != enabled) { + this.enabled = enabled; + + try { + if (enabled) { + this.onEnable(); + } else { + this.onDisable(); + } + } catch (Exception e) { + this.logger.error("Error while enabling/disabling plugin " + this.getName() + ": " + e); } - } catch (Exception e) { - this.logger.error("Error while enabling/disabling plugin " + this.getName() + ": " + e); } } - public PluginData getDescription() { - return this.description; - } - public String getName() { return this.description.getName(); } - - public Server getServer() { - return this.server; - } - - public Logger getLogger() { - return this.logger; - } - - public File getDataFolder() { - return this.dataFolder; - } } \ No newline at end of file diff --git a/src/main/java/org/sculk/plugin/PluginClassLoader.java b/src/main/java/org/sculk/plugin/PluginClassLoader.java index 73a2479..8eeb5fe 100644 --- a/src/main/java/org/sculk/plugin/PluginClassLoader.java +++ b/src/main/java/org/sculk/plugin/PluginClassLoader.java @@ -35,6 +35,7 @@ protected Class findClass(String name, boolean checkGlobal) throws ClassNotFo if (result == null && (result = super.findClass(name)) != null) { this.pluginManager.cacheClass(name, result); } + this.classes.put(name, result); return result; } diff --git a/src/main/java/org/sculk/plugin/PluginData.java b/src/main/java/org/sculk/plugin/PluginData.java index 8b29f1a..f52e331 100644 --- a/src/main/java/org/sculk/plugin/PluginData.java +++ b/src/main/java/org/sculk/plugin/PluginData.java @@ -1,35 +1,27 @@ package org.sculk.plugin; +import lombok.Getter; import lombok.ToString; +import java.util.ArrayList; +import java.util.ArrayList; import java.util.List; +@Getter @ToString -public class PluginData{ - +public class PluginData { public String name; public String version; public String author; public String main; + public String api; + public List apis; public List depends; - public String getAuthor() { - return this.author; - } - - public String getMain() { - return this.main; - } - - public String getName() { - return this.name; - } - - public String getVersion() { - return this.version; - } + public List getApi() { + if(apis == null) apis = new ArrayList<>(); + if(api != null && !apis.contains(api)) apis.add(api); - public List getDepends() { - return this.depends; + return apis; } } \ No newline at end of file diff --git a/src/main/java/org/sculk/plugin/PluginLoader.java b/src/main/java/org/sculk/plugin/PluginLoader.java index 19452a0..db3e768 100644 --- a/src/main/java/org/sculk/plugin/PluginLoader.java +++ b/src/main/java/org/sculk/plugin/PluginLoader.java @@ -1,7 +1,7 @@ package org.sculk.plugin; import lombok.extern.log4j.Log4j2; -import org.yaml.snakeyaml.Yaml; +import org.sculk.Sculk; import java.io.File; import java.io.InputStream; @@ -49,9 +49,10 @@ protected Plugin loadPluginJAR(PluginData pluginConfig, File pluginJar, PluginCl return null; } - protected PluginData loadPluginData(File file, Yaml yaml) { + protected PluginData loadPluginData(File file) { try (JarFile pluginJar = new JarFile(file)) { - JarEntry configEntry = pluginJar.getJarEntry("plugin.yml"); + JarEntry configEntry = pluginJar.getJarEntry("sculk.yml"); + if (configEntry == null) { configEntry = pluginJar.getJarEntry("plugin.yml"); } @@ -62,13 +63,15 @@ protected PluginData loadPluginData(File file, Yaml yaml) { } try (InputStream fileStream = pluginJar.getInputStream(configEntry)) { - PluginData pluginConfig = yaml.loadAs(fileStream, PluginData.class); - if (pluginConfig.getMain() != null && pluginConfig.getName() != null) { + PluginData pluginConfig = PluginManager.yamlLoader.loadAs(fileStream, PluginData.class); + if (pluginConfig.getMain() != null && pluginConfig.getName() != null && pluginConfig.getApi().contains(Sculk.CODE_VERSION.replace("v", ""))) { // Valid plugin.yml, main and name set return pluginConfig; } } - log.warn("Invalid plugin.yml for " + file.getName() + ": main and/or name property missing"); + + log.warn("Invalid plugin.yml for " + file.getName() + ": main and/or name property missing, incompactible api version"); + } catch (Exception e) { log.error("Can not load plugin files in " + file.getPath(), e); } diff --git a/src/main/java/org/sculk/plugin/PluginManager.java b/src/main/java/org/sculk/plugin/PluginManager.java index e84fcf9..12c97d1 100644 --- a/src/main/java/org/sculk/plugin/PluginManager.java +++ b/src/main/java/org/sculk/plugin/PluginManager.java @@ -5,6 +5,8 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair; +import lombok.Getter; + import org.sculk.Server; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.LoaderOptions; @@ -22,12 +24,14 @@ public class PluginManager { public static final Yaml yamlLoader; + static { Representer representer = new Representer(new DumperOptions()); representer.getPropertyUtils().setSkipMissingProperties(true); yamlLoader = new Yaml(new CustomClassLoaderConstructor(PluginManager.class.getClassLoader(), new LoaderOptions()), representer); } + @Getter private final Server server; private final PluginLoader pluginLoader; @@ -59,7 +63,7 @@ private void loadPluginsInside(Path folderPath) throws IOException { }; Map plugins = new TreeMap<>(comparator); - try (Stream stream = Files.walk(folderPath)){ + try (Stream stream = Files.walk(folderPath)) { stream.filter(Files::isRegularFile).filter(PluginLoader::isJarFile).forEach(jarPath -> { PluginData config = this.loadPluginConfig(jarPath); if (config != null) { @@ -80,7 +84,8 @@ private PluginData loadPluginConfig(Path path) { if (!pluginFile.exists()) { return null; } - return this.pluginLoader.loadPluginData(pluginFile, yamlLoader); + + return this.pluginLoader.loadPluginData(pluginFile); } private PluginClassLoader registerClassLoader(PluginData config, Path path) { @@ -151,31 +156,42 @@ public void enableAllPlugins() { return; } - StringBuilder builder = new StringBuilder("§cFailed to load plugins: §e"); - while (failed.peek() != null) { - Plugin plugin = failed.poll(); - builder.append(plugin.getName()); - if (failed.peek() != null) { - builder.append(", "); - } - } - server.getLogger().warn(builder.toString()); + server.getLogger().warn("§cFailed to load plugins: §e" + String.join(", ", failed.stream() + .map(Plugin::getName) + .toList())); } public boolean enablePlugin(Plugin plugin, String parent) { - if (plugin.isEnabled()) return true; - String pluginName = plugin.getName(); + if (plugin.isEnabled()) { + return true; + } + + if (plugin.getDescription().getDepends() != null && !this.checkDependencies(plugin, parent)) { + return false; + } + + try { + plugin.setEnabled(true); + } catch (Exception e) { + server.getLogger().error(e.getMessage()); + return false; + } + return true; + } + private boolean checkDependencies(Plugin plugin, String parent) { + String pluginName = plugin.getName(); if (plugin.getDescription().getDepends() != null) { for (String depend : plugin.getDescription().getDepends()) { if (depend.equals(parent)) { - server.getLogger().warn("§cCan not enable plugin " + pluginName + " circular dependency " + parent + "!"); + server.getLogger().warn("§cCannot enable plugin " + pluginName + ", circular dependency " + parent + "!"); return false; } Plugin dependPlugin = this.getPluginByName(depend); if (dependPlugin == null) { - server.getLogger().warn("§cCan not enable plugin " + pluginName + " missing dependency " + depend + "!"); + server.getLogger().warn("§cCannot enable plugin " + pluginName + ", missing dependency " + depend + "!"); + return false; } @@ -184,13 +200,7 @@ public boolean enablePlugin(Plugin plugin, String parent) { } } } - - try { - plugin.setEnabled(true); - } catch (Exception e) { - server.getLogger().error(e.getMessage()); - return false; - } + return true; } @@ -213,11 +223,14 @@ public Class getClassFromCache(String className) { for (PluginClassLoader loader : this.pluginClassLoaders.values()) { try { - if ((clazz = loader.findClass(className, false)) != null) { + + clazz = loader.findClass(className, false); + if (clazz != null) { + this.cachedClasses.put(className, clazz); // Cache the found class return clazz; } } catch (ClassNotFoundException e) { - //ignore + // Ignore } } return null; @@ -242,8 +255,4 @@ public Collection getPluginClassLoaders() { public Plugin getPluginByName(String pluginName) { return this.pluginMap.getOrDefault(pluginName, null); } - - public Server getServer() { - return this.server; - } } \ No newline at end of file