package org.royaldev.royalbot.plugins; import org.royaldev.royalbot.RoyalBot; import org.royaldev.royalbot.plugins.exceptions.InvalidPluginException; import org.royaldev.royalbot.plugins.exceptions.PluginException; import org.royaldev.royalbot.plugins.exceptions.PluginLoadException; import java.io.File; import java.lang.reflect.Constructor; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Class that loads plugins into the bot. */ public class PluginLoader { private final RoyalBot rb; public PluginLoader(RoyalBot instance) { rb = instance; } /** * Loads a plugin and registers it in the PluginHandler. The file given must be from within the official plugins * folder or an Exception will be thrown. * * @param file File representing plugin JAR * @return Loaded plugin * @throws org.royaldev.royalbot.plugins.exceptions.PluginLoadException If there is an issue that prevents the * loading of the plugin * @throws org.royaldev.royalbot.plugins.exceptions.InvalidPluginException If there is an issue with the plugin * and its structure or setup */ public Plugin loadPlugin(File file) throws PluginLoadException, InvalidPluginException { final PluginClassLoader pcl; try { pcl = new PluginClassLoader(new URL[]{new File(rb.getPath(), "plugins").toURI().toURL()}); } catch (MalformedURLException ex) { throw new PluginLoadException(ex); } final PluginDescription pd; try { pd = pcl.loadAndScanJar(file); } catch (Exception ex) { throw new PluginLoadException("Could not load plugin! (" + file.getName() + ")", ex); } rb.getLogger().info("Loading plugin " + pd.getName()); final Class<?> c; try { c = Class.forName(pd.getMain(), true, pcl); } catch (ClassNotFoundException ex) { throw new InvalidPluginException("Couldn't load plugin " + pd.getName() + ": No main class " + pd.getMain(), ex); } if (!Plugin.class.isAssignableFrom(c)) throw new InvalidPluginException("Couldn't load plugin " + pd.getName() + ": Doesn't implement Plugin interface"); final Class<? extends IRCPlugin> pluginClass = c.asSubclass(IRCPlugin.class); final IRCPlugin plugin; try { final Constructor constructor = pluginClass.getDeclaredConstructor(); plugin = (IRCPlugin) constructor.newInstance(); } catch (Exception ex) { throw new PluginLoadException("Could not load plugin " + pd.getName() + ": Couldn't construct plugin", ex); } plugin.init(rb, pd, pcl, new File(rb.getPath(), "plugins" + File.separator + pd.getName())); rb.getLogger().info("Loaded " + pd.getName()); rb.getPluginHandler().register(plugin); return plugin; } /** * Loads all plugins in the default plugins directory. * * @return Array of loaded plugins */ public Plugin[] loadPlugins() { final File f = new File(rb.getPath(), "plugins"); if (!f.exists() || !f.isDirectory()) return new Plugin[0]; // no plugins to be loaded, obviously List<Plugin> plugins = new ArrayList<>(); for (String name : f.list()) { if (!name.endsWith(".jar")) continue; Plugin plugin; try { plugin = loadPlugin(new File(f, name)); } catch (PluginException ex) { rb.getLogger().severe("Exception while loading plugin: " + ex.getMessage()); ex.printStackTrace(); continue; } plugins.add(plugin); } return plugins.toArray(new Plugin[plugins.size()]); } public void enablePlugins() { for (Plugin plugin : rb.getPluginHandler().getAll()) { rb.getLogger().info("Enabling " + plugin.getPluginDescription().getName()); try { plugin.onEnable(); } catch (Throwable t) { rb.getLogger().severe("Exception while enabling plugin " + plugin.getPluginDescription().getName()); t.printStackTrace(); } } } public void disablePlugins() { for (Plugin plugin : rb.getPluginHandler().getAll()) { rb.getLogger().info("Disabling " + plugin.getPluginDescription().getName()); try { plugin.onDisable(); } catch (Throwable t) { rb.getLogger().severe("Exception while disabling plugin " + plugin.getPluginDescription().getName()); t.printStackTrace(); } } } }