diff --git a/bFundamentals/pom.xml b/bFundamentals/pom.xml
index 6a2eedf..6256a98 100644
--- a/bFundamentals/pom.xml
+++ b/bFundamentals/pom.xml
@@ -32,6 +32,11 @@
jNBT
1.1
+
+ org.reflections
+ reflections
+ 0.9.9-RC1
+
@@ -50,7 +55,9 @@
commons-*:*
- org.jnbt:jNBT
+ org.jnbt:jNBT
+ org.javassist:javassist
+ org.reflections:reflections
org.apache.httpcomponents:*
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/BukkitConfigurationManager.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/BukkitConfigurationManager.java
index f4bd670..8570b89 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/BukkitConfigurationManager.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/BukkitConfigurationManager.java
@@ -40,6 +40,7 @@ public class BukkitConfigurationManager implements ConfigManager {
protected String m_logPrefix = null;
protected DatabaseSettings m_databaseSettings = null;
protected String m_crashPass;
+ protected File m_moduleDir;
/* (non-Javadoc)
* @see uk.codingbadgers.bFundamentals.ConfigManager#loadConfiguration(java.io.File)
@@ -48,10 +49,14 @@ public class BukkitConfigurationManager implements ConfigManager {
public void loadConfiguration(File configFile) throws IOException {
FileConfiguration config = YamlConfiguration.loadConfiguration(configFile);
+ config.options().header("bFundamentals configuration");
+
config.addDefault("general.language", "UK");
config.addDefault("general.debug", false);
config.addDefault("general.crash.password", "Password");
+ config.addDefault("module.loading.dir", "${plugindir}/modules");
+
config.addDefault("module.update.enabled", false);
config.addDefault("module.update.download", false);
config.addDefault("module.update.apply", false);
@@ -66,7 +71,8 @@ public void loadConfiguration(File configFile) throws IOException {
config.addDefault("database.password", "");
config.addDefault("database.port", 3306);
config.addDefault("database.updateRate", 5);
-
+
+ config.options().copyHeader(true);
config.options().copyDefaults(true);
config.save(configFile);
@@ -74,6 +80,8 @@ public void loadConfiguration(File configFile) throws IOException {
m_debug = config.getBoolean("general.debug");
m_crashPass = config.getString("general.crash.password", "Password");
+ m_moduleDir = parseDirectory(config.getString("module.loading.dir"));
+
m_autoUpdate = config.getBoolean("module.update.enabled");
m_autoDownload = config.getBoolean("module.update.download");
m_autoApply = config.getBoolean("module.update.apply");
@@ -92,68 +100,55 @@ public void loadConfiguration(File configFile) throws IOException {
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#getDatabaseSettings()
- */
+ private File parseDirectory(String string) {
+ string = string.replace("${plugindir}", bFundamentals.getInstance().getDataFolder().getAbsolutePath());
+ string = string.replace("${basedir}", new File(".").getAbsolutePath());
+ return new File(string);
+ }
+
@Override
public DatabaseSettings getDatabaseSettings() {
return m_databaseSettings;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#getLanguage()
- */
@Override
public String getLanguage() {
return m_language;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#isDebugEnabled()
- */
@Override
public boolean isDebugEnabled() {
return m_debug;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#isAutoUpdateEnabled()
- */
@Override
public boolean isAutoUpdateEnabled() {
return m_autoUpdate;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#isAutoDownloadEnabled()
- */
@Override
public boolean isAutoDownloadEnabled() {
return m_autoDownload;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#isAutoInstallEnabled()
- */
@Override
public boolean isAutoInstallEnabled() {
return m_autoApply;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#getLogPrefix()
- */
@Override
public String getLogPrefix() {
return m_logPrefix;
}
- /* (non-Javadoc)
- * @see uk.codingbadgers.bFundamentals.ConfigManager#getCrashPassword()
- */
@Override
public String getCrashPassword() {
return m_crashPass;
}
+ @Override
+ public File getModuleDirectory() {
+ return m_moduleDir;
+ }
+
}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/ConfigManager.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/ConfigManager.java
index 8aab7af..ff3a110 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/ConfigManager.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/ConfigManager.java
@@ -86,4 +86,11 @@ public interface ConfigManager {
*/
public abstract String getCrashPassword();
+ /**
+ * Gets the current module directory.
+ *
+ * @return the module directory
+ */
+ public abstract File getModuleDirectory();
+
}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/bFundamentals.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/bFundamentals.java
index 6910c8b..d579721 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/bFundamentals.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/bFundamentals.java
@@ -48,7 +48,7 @@
import ru.tehkode.permissions.bukkit.PermissionsEx;
import uk.codingbadgers.bFundamentals.module.Module;
-import uk.codingbadgers.bFundamentals.module.ModuleLoader;
+import uk.codingbadgers.bFundamentals.module.loader.ModuleLoader;
import uk.codingbadgers.bFundamentals.player.FundamentalPlayer;
import uk.codingbadgers.bFundamentals.player.FundamentalPlayerArray;
import uk.thecodingbadgers.bDatabaseManager.bDatabaseManager;
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/commands/ModuleCommand.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/commands/ModuleCommand.java
index e4ec623..c5bc2d1 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/commands/ModuleCommand.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/commands/ModuleCommand.java
@@ -23,6 +23,7 @@
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
+import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandException;
import org.bukkit.command.CommandSender;
@@ -32,6 +33,7 @@
import com.google.common.collect.ImmutableList.Builder;
import uk.codingbadgers.bFundamentals.bFundamentals;
+import uk.codingbadgers.bFundamentals.error.ExceptionHandler;
import uk.codingbadgers.bFundamentals.module.Module;
/**
@@ -225,30 +227,36 @@ public void addChildCommand(ModuleChildCommand command) {
*/
@Override
public final boolean execute(CommandSender sender, String label, String[] args) {
- if (args.length >= 1) {
- for (ModuleChildCommand child : m_children) {
- if (child.getLabel().equalsIgnoreCase(args[0])) {
- m_module.log(Level.INFO, child.getLabel());
- // cut first argument (sub command) out of command then handle as child command
- args = Arrays.copyOfRange(args, 1, args.length);
- return child.execute(sender, label, args);
+ try {
+ if (args.length >= 1) {
+ for (ModuleChildCommand child : m_children) {
+ if (child.getLabel().equalsIgnoreCase(args[0])) {
+ m_module.log(Level.INFO, child.getLabel());
+ // cut first argument (sub command) out of command then handle as child command
+ args = Arrays.copyOfRange(args, 1, args.length);
+ return child.execute(sender, label, args);
+ }
}
}
+
+ // for backwards compatibility call old method first, will pass to new if left as default
+ if (onCommand(sender, label, args)) {
+ return true;
+ }
+
+ // call command method in module if still not handled
+ if (m_module.onCommand(sender, label, args)) {
+ return true;
+ }
+
+ // if not handled for any reason, send usage
+ Module.sendMessage(m_module.getName(), sender, getUsage());
+ return false;
+ } catch (Exception ex) {
+ ExceptionHandler.handleException(ex);
+ sender.sendMessage(ChatColor.RED + "Sorry there was a error executing your command.");
+ return false;
}
-
- // for backwards compatibility call old method first, will pass to new if left as default
- if (onCommand(sender, label, args)) {
- return true;
- }
-
- // call command method in module if still not handled
- if (m_module.onCommand(sender, label, args)) {
- return true;
- }
-
- // if not handled for any reason, send usage
- Module.sendMessage(m_module.getName(), sender, getUsage());
- return false;
}
/**
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/error/ExceptionHandler.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/error/ExceptionHandler.java
index 554d337..2b8b342 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/error/ExceptionHandler.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/error/ExceptionHandler.java
@@ -18,7 +18,14 @@
package uk.codingbadgers.bFundamentals.error;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.logging.Level;
+import uk.codingbadgers.bFundamentals.bFundamentals;
+
+/**
+ * The Class ExceptionHandler, handles exceptions generated by bFundamentals
+ * and any sub modules.
+ */
public class ExceptionHandler implements UncaughtExceptionHandler {
private static final ExceptionHandler instance;
@@ -28,12 +35,21 @@ public class ExceptionHandler implements UncaughtExceptionHandler {
Thread.setDefaultUncaughtExceptionHandler(instance);
}
+ /**
+ * Handle an exception.
+ *
+ * @param e the exception caught
+ * @return true, if successful
+ */
public static boolean handleException(Throwable e) {
- e.printStackTrace();
+ bFundamentals.getInstance().getLogger().log(Level.WARNING, null, e);
ReportExceptionRunnable run = new ReportExceptionRunnable(e);
return run.run();
}
+ /* (non-Javadoc)
+ * @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
+ */
@Override
public void uncaughtException(Thread t, Throwable e) {
handleException(e);
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/Module.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/Module.java
index d3b293b..5ff0b0f 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/Module.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/Module.java
@@ -26,21 +26,30 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.io.FileInputStream;
import java.io.InputStreamReader;
+import java.net.URL;
import java.util.HashMap;
+import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.zip.ZipEntry;
+import net.milkbowl.vault.chat.Chat;
+import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.Validate;
+import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import uk.codingbadgers.bFundamentals.bFundamentals;
@@ -48,52 +57,65 @@
import uk.codingbadgers.bFundamentals.commands.ModuleCommandHandler;
import uk.codingbadgers.bFundamentals.config.ConfigFactory;
import uk.codingbadgers.bFundamentals.config.ConfigFile;
-import uk.codingbadgers.bFundamentals.module.loader.Loadable;
+import uk.codingbadgers.bFundamentals.module.events.ModuleDisableEvent;
+import uk.codingbadgers.bFundamentals.module.events.ModuleEnableEvent;
+import uk.codingbadgers.bFundamentals.module.loader.ClassFinder;
+import uk.codingbadgers.bFundamentals.module.loader.ModuleClassLoader;
import uk.codingbadgers.bFundamentals.update.UpdateThread;
import uk.codingbadgers.bFundamentals.update.Updater;
import uk.thecodingbadgers.bDatabaseManager.Database.BukkitDatabase;
/**
* The base Module class any module should extend this, it also provides helper
- * methods for the module.
+ * methods for the module, modules should be annotated with {@link ModuleInfo}
+ * to save the information of the module.
*/
-public abstract class Module extends Loadable implements Listener {
+public abstract class Module implements Listener {
- protected static BukkitDatabase m_database = null;
+ protected final BukkitDatabase m_database;
protected final bFundamentals m_plugin;
- protected File m_configFile = null;
+ protected File m_configFile;
protected FileConfiguration m_config;
- private static Permission m_permissions = null;
+
private boolean m_debug = false;
private boolean loadedLanguageFile;
private boolean m_enabled;
+ private File m_file;
+ private JarFile m_jar;
+ private File m_dataFolder;
+ private ModuleLogger m_log;
+ private UpdateThread m_updater;
+ private ModuleDescription m_description;
private List> m_configFiles;
private List m_listeners = new ArrayList();
- private ModuleLogger m_log;
private Map m_languageMap = new HashMap();
- private UpdateThread m_updater;
+ private ModuleClassLoader m_loader;
/**
* Instantiates a new module with default settings.
*/
public Module() {
- super();
m_plugin = bFundamentals.getInstance();
m_database = bFundamentals.getBukkitDatabase();
m_debug = bFundamentals.getConfigurationManager().isDebugEnabled();
- m_permissions = bFundamentals.getPermissions();
}
- public void init() {
+ /**
+ * Initialise this module
+ */
+ public final void init() {
m_log = new ModuleLogger(this);
}
- protected void setUpdater(Updater updater) {
+ protected final void setUpdater(Updater updater) {
m_updater = new UpdateThread(updater);
log(Level.INFO, "Set new updater to " + m_updater.getUpdater().getUpdater());
}
- public void update() {
+ /**
+ * If enabled, check if this module needs a update
+ */
+ public final void update() {
if (m_updater == null) {
log(Level.INFO, "Updater is null, cannot check for updates");
return;
@@ -202,6 +224,31 @@ protected void loadLanguageFile() {
}
+ /**
+ * Gets the language value for the current loaded language, case
+ * insensitive, all keys are forced to be in lower case.
+ *
+ * @param key
+ * the language key
+ * @return the language value, if available, the key with hyphens removed
+ * and in lower case otherwise
+ */
+ public String getLanguageValue(String key) {
+ Validate.notNull(key, "Language key cannot be null");
+
+ if (!loadedLanguageFile) {
+ log(Level.SEVERE, "Cannot get language value before loading language file");
+ }
+
+ String value = m_languageMap.get(key.toLowerCase());
+
+ if (value == null) {
+ value = key.toLowerCase().replace("-", " ");
+ }
+
+ return value;
+ }
+
/**
* Log a message console via this modules logger.
*
@@ -230,6 +277,10 @@ public Logger getLogger() {
* the bukkit event listener
*/
public final void register(Listener listener) {
+ if (m_listeners.contains(listener)) {
+ return;
+ }
+
m_plugin.getServer().getPluginManager().registerEvents(listener, m_plugin);
m_listeners.add(listener);
}
@@ -239,23 +290,41 @@ public final void register(Listener listener) {
*
* @return the vault permissions instance
*/
- public Permission getPermissions() {
- return m_permissions;
+ public final Permission getPermissions() {
+ return bFundamentals.getPermissions();
+ }
+
+ /**
+ * Gets the vault chat instance.
+ *
+ * @return the vault chat instance
+ */
+ public final Chat getChat() {
+ return bFundamentals.getChat();
}
+ /**
+ * Gets the vault economy instance.
+ *
+ * @return the vault economy instance
+ */
+ public final Economy getEconomy() {
+ return bFundamentals.getEconomy();
+ }
+
/**
* The enable method for this module, called on enabling the module via
* {@link #setEnabled(boolean)} this is used to register commands, events
* and any other things that should be registered on enabling the module.
*/
- public abstract void onEnable();
+ public void onEnable() {}
/**
* The disable method for this module, called on disabling the module via
* {@link #setEnabled(boolean)} this is used to clean up after the module when
* it is disabled.
*/
- public abstract void onDisable();
+ public void onDisable() {}
/**
* The load method for this module, called on loading the module via the
@@ -272,21 +341,46 @@ public void onLoad() {}
*
* @param enabled if you want to enable or disable the module
*/
- public void setEnabled(boolean enabled) {
+ public final void setEnabled(boolean enabled) {
if (enabled) {
if (m_enabled) {
return;
}
-
+
+ ModuleEnableEvent event = new ModuleEnableEvent(bFundamentals.getInstance(), this);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
onEnable();
m_enabled = true;
+
+ try {
+ Set> listeners = ClassFinder.findListeners(m_loader, new URL[] {m_file.toURI().toURL()});
+ debugConsole("Loading " + listeners.size() + " listeners");
+
+ for (Class extends Listener> clazz : listeners) {
+ try {
+ debugConsole("Loading Listener (" + clazz.getName() + ")");
+ register(clazz.newInstance());
+ } catch (Exception ex) {
+ log(Level.WARNING, clazz.getName() + " does not have atleast one public no argument constructor.");
+ }
+ }
+ } catch (Exception ex) {
+ }
+
} else {
if (!m_enabled) {
return;
}
-
+
+ ModuleDisableEvent event = new ModuleDisableEvent(bFundamentals.getInstance(), this);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
onDisable();
ModuleCommandHandler.deregisterCommand(this);
+ for (Listener listener : getListeners()) {
+ HandlerList.unregisterAll(listener);
+ }
m_enabled = false;
}
}
@@ -296,7 +390,7 @@ public void setEnabled(boolean enabled) {
*
* @return if the module is enabled
*/
- public boolean isEnabled() {
+ public final boolean isEnabled() {
return m_enabled;
}
@@ -318,45 +412,6 @@ public boolean onCommand(CommandSender sender, String label, String[] args) {
return false;
}
- /**
- * Gets the version of this module loaded from the path.yml file.
- *
- * @return the module version
- */
- public String getVersion() {
- return getDesciption().getVersion();
- }
-
- /**
- * Checks if a player has a specific permission.
- *
- * @param player
- * the player to check
- * @param node
- * the permission node
- * @return true, if the player has the permission
- */
- public static boolean hasPermission(final Player player, final String node) {
- if (m_permissions.has(player, node)) {
- return true;
- }
- return false;
- }
-
- /**
- * Send message to a player formated in the default style.
- *
- * @param name
- * the name of the module
- * @param player
- * the player to send to
- * @param message
- * the message
- */
- public static void sendMessage(String name, CommandSender player, String message) {
- player.sendMessage(ChatColor.DARK_PURPLE + "[" + name + "] " + ChatColor.RESET + message);
- }
-
/**
* Register a command to this module.
*
@@ -377,38 +432,13 @@ public List getCommands() {
return ModuleCommandHandler.getCommands(this);
}
- /**
- * Gets the language value for the current loaded language, case
- * insensitive, all keys are forced to be in lower case.
- *
- * @param key
- * the language key
- * @return the language value, if available, the key with hyphens removed
- * and in lower case otherwise
- */
- public String getLanguageValue(String key) {
- Validate.notNull(key, "Language key cannot be null");
-
- if (!loadedLanguageFile) {
- log(Level.SEVERE, "Cannot get language value before loading language file");
- }
-
- String value = m_languageMap.get(key.toLowerCase());
-
- if (value == null) {
- value = key.toLowerCase().replace("-", " ");
- }
-
- return value;
- }
-
/**
* Get all the listeners registered to this module, for cleaning up on
* disable
*
* @return a list of all listeners
*/
- public List getListeners() {
+ public final List getListeners() {
return m_listeners;
}
@@ -417,7 +447,7 @@ public List getListeners() {
*
* @return if debug is enabled
*/
- public boolean isDebug() {
+ public final boolean isDebug() {
return m_debug;
}
@@ -427,7 +457,7 @@ public boolean isDebug() {
* @param debug
* whether debug is on or not
*/
- public void setDebug(boolean debug) {
+ public final void setDebug(boolean debug) {
m_debug = debug;
}
@@ -437,7 +467,7 @@ public void setDebug(boolean debug) {
* @param message
* the message to output
*/
- public void debugConsole(String message) {
+ public final void debugConsole(String message) {
if (!m_debug)
return;
@@ -450,10 +480,9 @@ public void debugConsole(String message) {
* file should be {@code static} and have a {@link Element}
* annotation associated with it.
*
- * @param clazz
- * the config class
+ * @param clazz the config class
*/
- public void registerConfig(Class extends ConfigFile> clazz) {
+ public final void registerConfig(Class extends ConfigFile> clazz) {
if (m_configFiles == null) {
m_configFiles = new ArrayList>();
}
@@ -467,4 +496,238 @@ public void registerConfig(Class extends ConfigFile> clazz) {
}
m_configFiles.add(clazz);
}
+
+ /* Start Loading specific methods */
+
+ /**
+ * Set the datafolder.
+ *
+ * @param dataFolder the data folder
+ */
+ public final void setDatafolder(File dataFolder) {
+ if (m_dataFolder != null) {
+ throw new IllegalStateException("Data folder already set");
+ }
+ dataFolder.mkdirs();
+ this.m_dataFolder = dataFolder;
+ }
+
+ /**
+ * Set the file for this loadable.
+ *
+ * @param file the file
+ */
+ public final void setFile(File file) {
+ if (m_file != null) {
+ throw new IllegalStateException("File already set");
+ }
+ this.m_file = file;
+ }
+
+ /**
+ * Set the jar file.
+ *
+ * @param jar the jar
+ */
+ public final void setJarFile(JarFile jar) {
+ if (m_jar != null) {
+ throw new IllegalStateException("Jar file already set");
+ }
+ this.m_jar = jar;
+ }
+
+ /**
+ * Set the {@link ModuleDescription} for this module.
+ *
+ * @param ldf the loadable description file
+ */
+ public final void setDesciption(ModuleDescription ldf) {
+ if (m_description != null) {
+ throw new IllegalStateException("Description already set");
+ }
+ this.m_description = ldf;
+ }
+
+ /**
+ * Sets the {@link ModuleClassLoader} for this module
+ *
+ * @param loader the current class loader for this module
+ */
+ public final void setClassLoader(ModuleClassLoader loader) {
+ if (m_loader != null) {
+ throw new IllegalStateException("Class loader already set");
+ }
+ this.m_loader = loader;
+ }
+
+ /* End Loading specific methods */
+
+ /**
+ * Gets the config.
+ *
+ * @return The config
+ */
+ public final FileConfiguration getConfig() {
+ if (m_config == null) {
+ reloadConfig();
+ }
+
+ return m_config;
+ }
+
+ /**
+ * Gets the data folder of this.
+ *
+ * @return The directory of this
+ */
+ public final File getDataFolder() {
+ return m_dataFolder;
+ }
+
+ /**
+ * Gets the file of the loadable.
+ *
+ * @return the jar file as a {@link File}
+ */
+ public final File getFile() {
+ return m_file;
+ }
+
+ /**
+ * Gets the name of the Loadable.
+ *
+ * @return The name
+ */
+ public final ModuleClassLoader getClassLoader() {
+ return m_loader;
+ }
+
+ /**
+ * Gets the name of the Loadable.
+ *
+ * @return The name
+ */
+ public final String getName() {
+ return getDescription().getName();
+ }
+
+ /**
+ * Gets the version of this module loaded from the path.yml file.
+ *
+ * @return the module version
+ */
+ public final String getVersion() {
+ return getDescription().getVersion();
+ }
+
+ /**
+ * Gets an embedded resource in this plugin.
+ *
+ * @param name File name of the resource
+ * @return InputStream of the file if found, otherwise null
+ */
+ public final InputStream getResource(String name) {
+ ZipEntry entry = m_jar.getEntry(name);
+
+ if (entry == null)
+ return null;
+
+ try {
+ return m_jar.getInputStream(entry);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Reloads the config.
+ */
+ public final void reloadConfig() {
+ if (m_configFile == null) {
+ m_configFile = new File(getDataFolder(), "config.yml");
+ }
+
+ m_config = YamlConfiguration.loadConfiguration(m_configFile);
+
+ InputStream defConfigStream = getResource("config.yml");
+
+ if (defConfigStream != null) {
+ YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
+ m_config.setDefaults(defConfig);
+ }
+ }
+
+ /**
+ * Saves the config.
+ *
+ * @return if the config was saved successfully
+ */
+ public final boolean saveConfig() {
+ if (m_config == null || m_configFile == null) {
+ return false;
+ }
+
+ try {
+ m_config.save(m_configFile);
+ } catch (IOException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gets the description.
+ *
+ * @return the description
+ */
+ public final ModuleDescription getDescription() {
+ return this.m_description;
+ }
+
+ /**
+ * Checks if a player has a specific permission.
+ *
+ * @param player
+ * the player to check
+ * @param node
+ * the permission node
+ * @return true, if the player has the permission
+ */
+ public static boolean hasPermission(final Player player, final String node) {
+ if (bFundamentals.getPermissions().has(player, node)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if a player has a specific permission.
+ *
+ * @param player
+ * the player to check
+ * @param node
+ * the permission node
+ * @return true, if the player has the permission
+ */
+ public static boolean hasPermission(final CommandSender player, final String node) {
+ if (bFundamentals.getPermissions().has(player, node)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Send message to a player formated in the default style.
+ *
+ * @param name
+ * the name of the module
+ * @param player
+ * the player to send to
+ * @param message
+ * the message
+ */
+ public static void sendMessage(String name, CommandSender player, String message) {
+ player.sendMessage(ChatColor.DARK_PURPLE + "[" + name + "] " + ChatColor.RESET + message);
+ }
+
}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleDescription.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleDescription.java
new file mode 100644
index 0000000..5ba1022
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleDescription.java
@@ -0,0 +1,138 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.bukkit.configuration.file.YamlConfiguration;
+
+import uk.codingbadgers.bFundamentals.module.annotation.ModuleInfo;
+import uk.codingbadgers.bFundamentals.utils.CollectionUtils;
+
+/**
+ * The Class LoadableDescriptionFile, represents the data stored in the about a
+ * module, either by a path.yml file of a {@link Module} or a {@link ModuleInfo}
+ * annotation.
+ *
+ * @author James Fitzpatrick
+ */
+public class ModuleDescription {
+
+ private final String name;
+ private final String version;
+ private final String description;
+ private final String mainClass;
+ private final List authors;
+ private final Collection dependencies;
+
+ /**
+ * Instantiates a new module description from the data in a path.yml file.
+ *
+ * @param istream
+ * the input stream that this file is loaded from
+ */
+ public ModuleDescription(InputStream istream) {
+ YamlConfiguration ldf = YamlConfiguration.loadConfiguration(istream);
+
+ name = ldf.getString("name", "Unknown Module");
+ version = ldf.getString("version", "0.0");
+ description = ldf.getString("description", "");
+ mainClass = ldf.getString("main-class");
+ authors = CollectionUtils.toImmutableList(ldf.getStringList("authors"));
+ dependencies = Collections.unmodifiableCollection(ldf.getStringList("dependencies"));
+ }
+
+ /**
+ * Instantiates a new module description from the data in a
+ * {@link ModuleInfo} annotation.
+ *
+ * @param info
+ * the {@link ModuleInfo} annotation
+ * @param mainclass
+ * the mainclass loaded
+ */
+ public ModuleDescription(ModuleInfo info, String mainclass) {
+ this.name = info.value();
+ this.version = info.version();
+ this.mainClass = mainclass;
+ this.description = info.description();
+ this.authors = CollectionUtils.toImmutableList(Arrays.asList(info.authors()));
+ this.dependencies = Collections.unmodifiableCollection(new ArrayList());
+ }
+
+ /**
+ * Gets the name of this module.
+ *
+ * @return the name of this module
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the version of this module.
+ *
+ * @return the version of this module
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Gets the description for this module.
+ *
+ * @return the description of this module
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Gets the main class of this module.
+ *
+ * @return the fully qualified name of the main class of this module
+ * @deprecated Main classes should not have to be defined anymore
+ */
+ public String getMainClass() {
+ return mainClass;
+ }
+
+ /**
+ * Gets the authors of this module.
+ *
+ * @return a immutable list of the authors of this module
+ */
+ public List getAuthors() {
+ return authors;
+ }
+
+ /**
+ * Gets the module dependencies of this loadable, this module will load
+ * after all of the dependencies have module.
+ *
+ * @return a unmodifiable collection of the dependencies
+ */
+ public Collection getDependencies() {
+ return dependencies;
+ }
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoader.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoader.java
deleted file mode 100644
index 58f2526..0000000
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoader.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.logging.Level;
-
-import org.bukkit.Bukkit;
-import org.bukkit.event.HandlerList;
-import org.bukkit.event.Listener;
-
-import uk.codingbadgers.bFundamentals.bFundamentals;
-import uk.codingbadgers.bFundamentals.error.ExceptionHandler;
-import uk.codingbadgers.bFundamentals.module.loader.Loader;
-
-/**
- * The ModuleLoader.
- */
-public class ModuleLoader {
-
- /** The List of modules. */
- private final List m_modules;
- private Loader m_loader;
-
- /**
- * Instantiates a new module loader.
- */
- public ModuleLoader() {
- m_modules = new LinkedList();
- if (getModuleDir().mkdir())
- bFundamentals.log(Level.INFO, "Creating Module Directory...");
- }
-
- /**
- * Gets the directory of the modules.
- *
- * @return the module dir
- */
- public File getModuleDir() {
- return new File(bFundamentals.getInstance().getDataFolder(), "modules");
- }
-
- /**
- * Loads all the modules in the base modules directory.
- */
- public void load() {
- m_loader = new Loader(bFundamentals.getInstance(), getModuleDir());
- m_modules.addAll(m_loader.sort(m_loader.load()));
-
- for (Module module : m_modules) {
- try {
- module.onLoad();
- Bukkit.getHelpMap().addTopic(new ModuleHelpTopic(module));
- module.log(Level.INFO, module.getName() + " v:" + module.getVersion() + " has been loaded successfuly");
- } catch (Throwable ex) {
- ExceptionHandler.handleException(ex);
- }
- }
-
- bFundamentals.log(Level.INFO, "Loaded " + m_modules.size() + " modules.");
- }
-
- /**
- * Loads a module with a given name
- *
- * @param fileName the files name
- */
- public void load(String fileName) {
- File module = new File(getModuleDir() + File.separator + fileName + ".jar");
- load(module);
- }
-
- /**
- * Loads a module with a jar file
- *
- * @param file the jar file for this module
- */
- public void load(File file) {
- if (m_loader == null)
- m_loader = new Loader(bFundamentals.getInstance(), getModuleDir());
-
- if (getModule(file) != null)
- throw new IllegalArgumentException("Module " + file.getName() + " is already loaded");
-
- m_modules.clear();
- m_modules.addAll(m_loader.sort(m_loader.load(file)));
-
- Module module = getModule(file);
- module.onLoad();
- module.log(Level.INFO, module.getName() + " v:" + module.getVersion() + " has been loaded successfuly");
- }
-
- /**
- * Unloads the modules.
- */
- public void unload() {
- disable();
- m_modules.clear();
- }
-
- /**
- * Unload a specific module.
- *
- * @param module the module
- */
- public void unload(Module module) {
- try {
- module.setEnabled(false);
- for (Listener listener : module.getListeners()) {
- HandlerList.unregisterAll(listener);
- }
- m_modules.remove(module);
- } catch (Throwable ex) {
- ExceptionHandler.handleException(ex);
- }
- }
-
- /**
- * Run on enable in all modules.
- */
- public void enable() {
- for (Module module : m_modules) {
- try {
- module.setEnabled(true);
- } catch (Throwable ex) {
- ExceptionHandler.handleException(ex);
- }
- }
- }
-
- /**
- * run on disable in all modules.
- */
- public void disable() {
- List modules = new ArrayList(m_modules);
- for (Module module : modules) {
- try {
- unload(module);
- } catch (Throwable ex) {
- ExceptionHandler.handleException(ex);
- }
- }
- }
-
- /**
- * Gets the modules.
- *
- * @return the modules
- */
- public List getModules() {
- return m_modules;
- }
-
-
- /**
- * Update all the loaded modules if an updater is set
- */
- public void update() {
- for (Module module : m_modules) {
- module.update();
- }
- }
-
- /**
- * Gets the module from its name.
- *
- * @param string the string
- * @return the module
- */
- public Module getModule(String string) {
- Iterator itr = m_modules.iterator();
- while(itr.hasNext()) {
- Module module = itr.next();
- if (module.getName().equalsIgnoreCase(string)) {
- return module;
- }
- }
- return null;
- }
-
- /**
- * Gets the module from its file.
- *
- * @param file the file
- * @return the module
- */
- public Module getModule(File file) {
- Iterator itr = m_modules.iterator();
- while(itr.hasNext()) {
- Module module = itr.next();
- if (module.getFile().getPath().equalsIgnoreCase(file.getPath())) {
- return module;
- }
- }
- return null;
- }
-
-}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/annotation/ModuleInfo.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/annotation/ModuleInfo.java
new file mode 100644
index 0000000..a971033
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/annotation/ModuleInfo.java
@@ -0,0 +1,62 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Annotation ModuleInfo, defines the module information for a class.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ModuleInfo {
+
+ /**
+ * The module's name.
+ *
+ * @return the module's name
+ */
+ String value();
+
+ /**
+ * The module's version.
+ *
+ * @return the module's version
+ */
+ String version() default "1.0";
+
+ /**
+ * The module's authors.
+ *
+ * @return the module's authors
+ */
+ String[] authors() default {"Unkown"};
+
+ /**
+ * The module's description.
+ *
+ * @return the module's description
+ */
+ String description() default "";
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleDisableEvent.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleDisableEvent.java
new file mode 100644
index 0000000..c3dc664
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleDisableEvent.java
@@ -0,0 +1,40 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.events;
+
+import org.bukkit.plugin.Plugin;
+
+import uk.codingbadgers.bFundamentals.module.Module;
+
+/**
+ * The ModuleDisableEvent, called when a module is disabled via
+ * {@link Module#setEnabled(boolean)}.
+ */
+public class ModuleDisableEvent extends ModuleEvent {
+
+ /**
+ * Instantiates a new module disable event.
+ *
+ * @param plugin the plugin
+ * @param loadable the loadable
+ */
+ public ModuleDisableEvent(Plugin plugin, Module loadable) {
+ super(plugin, loadable);
+ }
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoadEvent.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEnableEvent.java
similarity index 62%
rename from bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoadEvent.java
rename to bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEnableEvent.java
index 3241072..0d95f63 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/ModuleLoadEvent.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEnableEvent.java
@@ -1,32 +1,40 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module;
-
-import java.util.jar.JarFile;
-
-import org.bukkit.plugin.Plugin;
-
-import uk.codingbadgers.bFundamentals.module.loader.LoadEvent;
-
-public class ModuleLoadEvent extends LoadEvent {
-
- public ModuleLoadEvent(Plugin plugin, Module loadable, JarFile jarFile) {
- super(plugin, loadable, jarFile);
- }
-
-}
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.events;
+
+import org.bukkit.plugin.Plugin;
+
+import uk.codingbadgers.bFundamentals.module.Module;
+
+/**
+ * The ModuleEnableEvent, called when a module is enabled via
+ * {@link Module#setEnabled(boolean)}.
+ */
+public class ModuleEnableEvent extends ModuleEvent {
+
+ /**
+ * Instantiates a new module enable event.
+ *
+ * @param plugin the plugin
+ * @param loadable the loadable
+ */
+ public ModuleEnableEvent(Plugin plugin, Module loadable) {
+ super(plugin, loadable);
+ }
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEvent.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEvent.java
new file mode 100644
index 0000000..ded11e7
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleEvent.java
@@ -0,0 +1,82 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.events;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.plugin.Plugin;
+
+import uk.codingbadgers.bFundamentals.module.Module;
+
+/**
+ * A module event, represents an event that .
+ */
+public abstract class ModuleEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ /* (non-Javadoc)
+ * @see org.bukkit.event.Event#getHandlers()
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ /**
+ * Gets the handler list.
+ *
+ * @return the handler list
+ */
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ private final Plugin plugin;
+ private final Module loadable;
+
+ /**
+ * Instantiates a new module event.
+ *
+ * @param plugin the plugin
+ * @param loadable the module involved in the event
+ */
+ public ModuleEvent(Plugin plugin, Module loadable) {
+ this.plugin = plugin;
+ this.loadable = loadable;
+ }
+
+ /**
+ * Gets the module involved in the event.
+ *
+ * @return the module
+ */
+ public Module getModule() {
+ return loadable;
+ }
+
+ /**
+ * Gets the plugin.
+ *
+ * @return the plugin
+ */
+ public Plugin getPlugin() {
+ return plugin;
+ }
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleLoadEvent.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleLoadEvent.java
new file mode 100644
index 0000000..ead4cde
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/events/ModuleLoadEvent.java
@@ -0,0 +1,75 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.events;
+
+import java.util.jar.JarFile;
+
+import org.bukkit.event.HandlerList;
+import org.bukkit.plugin.Plugin;
+
+import uk.codingbadgers.bFundamentals.module.Module;
+
+/**
+ * The ModuleLoadEvent, called when a module is loaded via
+ * {@link ModuleLoader#loadModule(java.io.File)}.
+ */
+public class ModuleLoadEvent extends ModuleEvent {
+
+ private static final HandlerList handlers = new HandlerList();
+
+
+ /* (non-Javadoc)
+ * @see uk.codingbadgers.bFundamentals.module.events.ModuleEvent#getHandlers()
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ /**
+ * Gets the handler list.
+ *
+ * @return the handler list
+ */
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ private final JarFile jarFile;
+
+ /**
+ * Instantiates a new module load event.
+ *
+ * @param plugin the plugin
+ * @param loadable the loadable
+ * @param jarFile the jar file
+ */
+ public ModuleLoadEvent(Plugin plugin, Module loadable, JarFile jarFile) {
+ super(plugin, loadable);
+ this.jarFile = jarFile;
+ }
+
+ /**
+ * Gets the jar file.
+ *
+ * @return the jar file
+ */
+ public JarFile getJarFile() {
+ return jarFile;
+ }
+}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ClassFinder.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ClassFinder.java
new file mode 100644
index 0000000..1f12b2a
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ClassFinder.java
@@ -0,0 +1,60 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.loader;
+
+import java.net.URL;
+import java.util.Set;
+
+import org.bukkit.event.Listener;
+import org.reflections.Reflections;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+
+import uk.codingbadgers.bFundamentals.module.Module;
+
+/**
+ * The Class ClassFinder, used to find specific types of classes quickly for
+ * module auto loading and registration.
+ */
+public class ClassFinder {
+
+ /**
+ * Find all the module classes in a class loader.
+ *
+ * @param loader the loader
+ * @param url the urls to check
+ * @return all classes that extend {@link Module} in that loader
+ */
+ public static Set> findModules(ModuleClassLoader loader, URL[] url) {
+ Reflections reflect = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(loader)).addClassLoader(loader));
+ return reflect.getSubTypesOf(Module.class);
+ }
+
+ /**
+ * Find all the listener classes in a class loader.
+ *
+ * @param loader the loader
+ * @param url the urls to check
+ * @return all classes that implement {@link Listener} in that loader
+ */
+ public static Set> findListeners(ModuleClassLoader loader, URL[] url) {
+ Reflections reflect = new Reflections(new ConfigurationBuilder().addUrls(url).addClassLoader(loader).addClassLoader(ClassFinder.class.getClassLoader()));
+ return reflect.getSubTypesOf(Listener.class);
+ }
+
+}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/FileExtensionFilter.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/FileExtensionFilter.java
index 28e577e..e3368bd 100644
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/FileExtensionFilter.java
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/FileExtensionFilter.java
@@ -1,34 +1,45 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module.loader;
-
-import java.io.File;
-import java.io.FileFilter;
-
-public final class FileExtensionFilter implements FileFilter {
-
- private final String extension;
-
- public FileExtensionFilter(String extension) {
- this.extension = extension;
- }
-
- public boolean accept(File file) {
- return file.getName().endsWith(extension);
- }
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.loader;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * The Class FileExtensionFilter.
+ */
+public final class FileExtensionFilter implements FileFilter {
+
+ private final String extension;
+
+ /**
+ * Instantiates a new file extension filter.
+ *
+ * @param extension the extension to test for
+ */
+ public FileExtensionFilter(String extension) {
+ this.extension = extension;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FileFilter#accept(java.io.File)
+ */
+ public boolean accept(File file) {
+ return file.getName().endsWith(extension);
+ }
}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadEvent.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadEvent.java
deleted file mode 100644
index d5bd35a..0000000
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadEvent.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module.loader;
-
-import java.util.jar.JarFile;
-import org.bukkit.event.Event;
-import org.bukkit.event.HandlerList;
-import org.bukkit.plugin.Plugin;
-
-/* Copyright (C) 2012 Nodin Chan
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/**
- * LoadEvent - Called when a Loadable has been loaded
- *
- * @author NodinChan
- * @param the loadable type
- */
-public class LoadEvent extends Event {
-
- private static final HandlerList handlers = new HandlerList();
-
- private final Plugin plugin;
-
- private final T loadable;
-
- private final JarFile jarFile;
-
- public LoadEvent(Plugin plugin, T loadable, JarFile jarFile) {
- this.plugin = plugin;
- this.loadable = loadable;
- this.jarFile = jarFile;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
-
- public static HandlerList getHandlerList() {
- return handlers;
- }
-
- /**
- * Gets the JAR file of the loaded loadable
- *
- * @return The JAR file
- */
- public JarFile getJarFile() {
- return jarFile;
- }
-
- /**
- * Gets the loaded Loadable
- *
- * @return The Loadable
- */
- public T getLoadable() {
- return loadable;
- }
-
- /**
- * Gets the plugin calling this event
- *
- * @return The plugin calling the event
- */
- public Plugin getPlugin() {
- return plugin;
- }
-}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loadable.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loadable.java
deleted file mode 100644
index b4b60d1..0000000
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loadable.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module.loader;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-/* Copyright (C) 2012 Nodin Chan
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/**
- * Loadable - Base for loadable classes.
- *
- * @author NodinChan
- */
-public class Loadable implements Cloneable {
-
- private String name;
- private File configFile;
- private FileConfiguration config;
- private LoadableDescriptionFile description;
- private JarFile jar;
- private File dataFolder;
- private File file;
-
- /**
- * Instantiates a new loadable.
- *
- * @param name the name
- * @deprecated use a {@link LoadableDescriptionFile} instead
- */
- public Loadable(String name) {
- this.name = name;
- }
-
- /**
- * Instantiates a new loadable.
- */
- public Loadable() {
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#clone()
- */
- @Override
- public Loadable clone() {
- Loadable loadable = new Loadable(name);
- loadable.config = YamlConfiguration.loadConfiguration(configFile);
- loadable.configFile = configFile;
- loadable.dataFolder = dataFolder;
- loadable.file = file;
- loadable.jar = jar;
- loadable.description = description;
- return loadable;
- }
-
- /**
- * Set the datafolder.
- *
- * @param dataFolder the data folder
- * @return the file
- */
- public File setDatafolder(File dataFolder) {
- dataFolder.mkdirs();
- return this.dataFolder = dataFolder;
- }
-
- /**
- * Set the file for this loadable.
- *
- * @param file the file
- * @return the file
- */
- public File setFile(File file) {
- return this.file = file;
- }
-
- /**
- * Set the jar file.
- *
- * @param jar the jar
- * @return the jar file
- */
- public JarFile setJarFile(JarFile jar) {
- return this.jar = jar;
- }
-
- /**
- * Set the {@link LoadableDescriptionFile} for this module.
- *
- * @param ldf the loadable description file
- * @return the loadable description file
- */
- public LoadableDescriptionFile setDesciption(LoadableDescriptionFile ldf) {
- this.description = ldf;
- this.name = description.getName();
- return description;
- }
-
- /**
- * Initialises the loadable, called on loading the module.
- */
- public void init() {}
-
- /**
- * Gets the config.
- *
- * @return The config
- */
- public FileConfiguration getConfig() {
- if (config == null)
- reloadConfig();
-
- return config;
- }
-
- /**
- * Gets the data folder of this.
- *
- * @return The directory of this
- */
- public File getDataFolder() {
- return dataFolder;
- }
-
- /**
- * Gets the file of the loadable.
- *
- * @return the jar file as a {@link File}
- */
- public File getFile() {
- return file;
- }
-
- /**
- * Gets the name of the Loadable.
- *
- * @return The name
- */
- public final String getName() {
- return getDesciption().getName();
- }
-
- /**
- * Gets an embedded resource in this plugin.
- *
- * @param name File name of the resource
- * @return InputStream of the file if found, otherwise null
- */
- public InputStream getResource(String name) {
- ZipEntry entry = jar.getEntry(name);
-
- if (entry == null)
- return null;
-
- try {
- return jar.getInputStream(entry);
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * Reloads the config.
- */
- public void reloadConfig() {
- if (configFile == null)
- configFile = new File(getDataFolder(), "config.yml");
-
- config = YamlConfiguration.loadConfiguration(configFile);
-
- InputStream defConfigStream = getResource("config.yml");
-
- if (defConfigStream != null) {
- YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
- config.setDefaults(defConfig);
- }
- }
-
- /**
- * Saves the config.
- */
- public void saveConfig() {
- if (config == null || configFile == null)
- return;
-
- try {
- config.save(configFile);
- } catch (IOException e) {
- }
- }
-
- /**
- * Called when the Loadable is unloaded.
- */
- public void unload() {
- }
-
- /**
- * Gets the desciption.
- *
- * @return the desciption
- */
- public LoadableDescriptionFile getDesciption() {
- return this.description;
- }
-
- /**
- * The Class LoadResult.
- */
- public static final class LoadResult {
-
- /** The result. */
- private final Result result;
-
- /** The reason. */
- private final String reason;
-
- /**
- * Instantiates a new load result.
- */
- public LoadResult() {
- this(Result.SUCCESS, "");
- }
-
- /**
- * Instantiates a new load result.
- *
- * @param failReason the fail reason
- */
- public LoadResult(String failReason) {
- this(Result.FAILURE, failReason);
- }
-
- /**
- * Instantiates a new load result.
- *
- * @param result the result
- * @param reason the reason
- */
- public LoadResult(Result result, String reason) {
- this.result = result;
- this.reason = reason;
- }
-
- /**
- * Gets the reason.
- *
- * @return the reason
- */
- public String getReason() {
- return reason;
- }
-
- /**
- * Gets the result.
- *
- * @return the result
- */
- public Result getResult() {
- return result;
- }
-
- /**
- * The Result for loading.
- */
- public enum Result {
-
- /** If the loadable didn't load successfully. */
- FAILURE,
- /** If the loadable loaded successfully. */
- SUCCESS
- }
- }
-}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadableDescriptionFile.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadableDescriptionFile.java
deleted file mode 100644
index debfb46..0000000
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/LoadableDescriptionFile.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module.loader;
-
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import com.google.common.collect.ImmutableList;
-
-/**
- * The Class LoadableDescriptionFile, represents the data stored in the
- * path.yml file of a {@link Loadable}.
- *
- * @author James Fitzpatrick
- */
-public class LoadableDescriptionFile {
-
- private final String name;
- private final String version;
- private final String description;
- private final String mainClass;
- private final List authors;
- private final Collection dependencies;
-
- /**
- * Instantiates a new loadable description file.
- *
- * @param istream the input stream that this file is loaded from
- */
- @SuppressWarnings("deprecation")
- public LoadableDescriptionFile(InputStream istream) {
- YamlConfiguration ldf = YamlConfiguration.loadConfiguration(istream);
-
- name = ldf.getString("name", "Unknown Module");
- version = ldf.getString("version", "0.0");
- description = ldf.getString("description", "");
- mainClass = ldf.getString("main-class");
- authors = ImmutableList.of(ldf.getStringList("authors").toArray(new String[0]));
- dependencies = Collections.unmodifiableCollection(ldf.getStringList("dependencies"));
- }
-
- /**
- * Gets the name of this loadable.
- *
- * @return the name of this loadable
- */
- public String getName() {
- return name;
- }
-
- /**
- * Gets the version of this loadable.
- *
- * @return the version of this loadable
- */
- public String getVersion() {
- return version;
- }
-
- /**
- * Gets the description for this loadable.
- *
- * @return the description of this loadable
- */
- public String getDescription() {
- return description;
- }
-
- /**
- * Gets the main class of this loadable.
- *
- * @return the fully qualified name of the main class of this loadable
- */
- public String getMainClass() {
- return mainClass;
- }
-
- /**
- * Gets the authors of this loadable.
- *
- * @return a immutable list of the authors of this loadable
- */
- public List getAuthors() {
- return authors;
- }
-
- /**
- * Gets the module dependencies of this loadable, this module will load after
- * all of the dependencies have loaded.
- *
- * @return a unmodifiable collection of the dependencies
- */
- public Collection getDependencies() {
- return dependencies;
- }
-}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loader.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loader.java
deleted file mode 100644
index d5d2652..0000000
--- a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/Loader.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/**
- * bFundamentals 1.2-SNAPSHOT
- * Copyright (C) 2013 CodingBadgers
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package uk.codingbadgers.bFundamentals.module.loader;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.bukkit.plugin.Plugin;
-import org.bukkit.plugin.java.PluginClassLoader;
-
-import uk.codingbadgers.bFundamentals.error.ExceptionHandler;
-import uk.codingbadgers.bFundamentals.module.Module;
-import uk.codingbadgers.bFundamentals.module.ModuleLoadEvent;
-
-/* Copyright (C) 2012 Nodin Chan
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-/**
- * Loader - Loader base for loading Loadables.
- *
- * @author NodinChan
- */
-public class Loader {
-
- private final Plugin plugin;
- private final List files;
- private final List loadables;
- private ClassLoader loader;
-
- /**
- * Instantiates a new loader.
- *
- * @param plugin
- * the plugin
- * @param dir
- * the directory to load modules from
- */
- public Loader(Plugin plugin, File dir) {
- this.plugin = plugin;
- this.files = Arrays.asList(dir.listFiles(new FileExtensionFilter(".jar")));
- this.loadables = new ArrayList();
-
- generateClassLoader();
- }
-
- private void generateClassLoader() {
- this.loadables.clear();
-
- List urls = new ArrayList();
-
- for (File file : files) {
- try {
- urls.add(file.toURI().toURL());
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- }
-
- this.loader = PluginClassLoader.newInstance(urls.toArray(new URL[0]), plugin.getClass().getClassLoader());
- }
-
- /**
- * Gets the Logger.
- *
- * @return The Logger
- */
- public Logger getLogger() {
- return plugin.getLogger();
- }
-
- /**
- * Loads the all loadables in the directory specified.
- *
- * @return List of loaded loadables
- */
- public final List load() {
- for (File file : files) {
- load(file);
- }
- return loadables;
- }
-
- /**
- * Load file into the loader.
- *
- * @param file
- * the file
- * @return the list
- * @TODO support module dependencies
- */
- public List load(File file) {
- try {
- JarFile jarFile = new JarFile(file);
- String mainClass = null;
- LoadableDescriptionFile ldf = null;
-
- if (jarFile.getEntry("path.yml") != null) {
- JarEntry element = jarFile.getJarEntry("path.yml");
- ldf = new LoadableDescriptionFile(jarFile.getInputStream(element));
- mainClass = ldf.getMainClass();
- }
-
- if (mainClass != null) {
- Class> clazz = Class.forName(mainClass, true, loader);
-
- if (clazz != null) {
- Class extends Module> loadableClass = clazz.asSubclass(Module.class);
- Constructor extends Module> constructor = loadableClass.getConstructor();
- Module loadable = constructor.newInstance();
-
- if (loadables.contains(loadable)) {
- getLogger().log(Level.WARNING, "The loadable " + file.getName() + " is already loaded, make sure to disable the module first");
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load");
- jarFile.close();
- return loadables;
- }
-
- loadable.setFile(file);
- loadable.setDesciption(ldf);
- loadable.setJarFile(jarFile);
- loadable.setDatafolder(new File(file.getParentFile(), loadable.getName()));
- loadable.init();
-
- loadables.add(loadable);
-
- ModuleLoadEvent event = new ModuleLoadEvent(plugin, loadable, jarFile);
- plugin.getServer().getPluginManager().callEvent(event);
-
- } else {
- jarFile.close();
- throw new ClassNotFoundException("Class " + mainClass + " could not be found.");
- }
-
- } else {
- jarFile.close();
- throw new ClassNotFoundException("Could not find main class in the path.yml.");
- }
-
- } catch (ClassCastException e) {
- e.printStackTrace();
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " is in the wrong directory.");
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load.");
- } catch (ClassNotFoundException e) {
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load.");
- getLogger().log(Level.WARNING, "Invalid path.yml.");
- getLogger().log(Level.WARNING, e.getMessage());
- } catch (NoClassDefFoundError e) {
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load.");
- getLogger().log(Level.WARNING, "The class " + e.getMessage() + " cannot be found.");
- getLogger().log(Level.WARNING, "Is this module missing a required dependency?");
- } catch (Throwable e) {
- ExceptionHandler.handleException(e);
- getLogger().log(Level.WARNING, "Unknown cause.");
- getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load.");
- }
- return loadables;
- }
-
- /**
- * Reloads the Loader.
- *
- * @return the list of modules loaded
- */
- public List reload() {
- unload();
- generateClassLoader();
- return load();
- }
-
- /**
- * Sorts a list of Loadables by name in alphabetical order.
- *
- * @param loadables
- * The list of Loadables to sort
- * @return The sorted list of Loadables
- */
- public List sort(List loadables) {
- List sortedLoadables = new ArrayList();
- List names = new ArrayList();
-
- for (Loadable t : loadables) {
- names.add(t.getName());
- }
-
- Collections.sort(names);
-
- for (String name : names) {
- for (Module t : loadables) {
- if (t.getName().equals(name)) {
- sortedLoadables.add(t);
- }
- }
- }
-
- return sortedLoadables;
- }
-
- /**
- * Sorts a map of Loadables by name in alphabetical order.
- *
- * @param loadables
- * The map of Loadables to sort
- * @return The sorted map of Loadables
- */
- public Map sort(Map loadables) {
- Map sortedLoadables = new HashMap();
- List names = new ArrayList(loadables.keySet());
-
- Collections.sort(names);
-
- for (String name : names) {
- sortedLoadables.put(name, loadables.get(name));
- }
-
- return sortedLoadables;
- }
-
- /**
- * Unloads the Loader.
- */
- public void unload() {
- loadables.clear();
- }
-}
\ No newline at end of file
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleClassLoader.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleClassLoader.java
new file mode 100644
index 0000000..4261c65
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleClassLoader.java
@@ -0,0 +1,108 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.loader;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.Validate;
+
+
+/**
+ * The ModuleClassLoader, used to load classes for modules.
+ */
+public class ModuleClassLoader extends URLClassLoader {
+ private final ModuleLoader loader;
+ private final Map> classes = new HashMap>();
+
+ /**
+ * Instantiates a new module class loader.
+ *
+ * @param moduleLoader the module loader
+ * @param urls the urls of the module
+ * @param parent the parent
+ */
+ public ModuleClassLoader(final ModuleLoader moduleLoader, final URL[] urls, final ClassLoader parent) {
+ super(urls, parent);
+ Validate.notNull(moduleLoader, "Loader cannot be null");
+ this.loader = moduleLoader;
+ }
+
+ @Override
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+
+ @Override
+ protected Class> findClass(String name) throws ClassNotFoundException {
+ return findClass(name, true);
+ }
+
+ /**
+ * Find a class.
+ *
+ * @param name the name of the class in the format for {@link Class#forName(String)}
+ * @param checkGlobal whether or not to check the global cache
+ * @return the class loaded
+ * @throws ClassNotFoundException the class not found exception
+ */
+ public Class> findClass(String name, boolean checkGlobal) throws ClassNotFoundException {
+ if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
+ throw new ClassNotFoundException(name);
+ }
+
+ System.out.println("Finding class " + name);
+
+ Class> result = classes.get(name);
+
+ if (result == null) {
+ if (checkGlobal) {
+ result = loader.getClassByName(name);
+ }
+
+ if (result == null) {
+ result = super.findClass(name);
+
+ if (result != null) {
+ loader.setClass(name, result);
+ }
+ }
+
+ classes.put(name, result);
+ }
+
+ if (result == null) {
+ throw new ClassNotFoundException(name);
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets the cache of all the classes loaded by this loader.
+ *
+ * @return the cache
+ */
+ public Set getClasses() {
+ return classes.keySet();
+ }
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleLoader.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleLoader.java
new file mode 100644
index 0000000..d5fecec
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/module/loader/ModuleLoader.java
@@ -0,0 +1,419 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.module.loader;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.bukkit.Bukkit;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.configuration.serialization.ConfigurationSerialization;
+
+import uk.codingbadgers.bFundamentals.bFundamentals;
+import uk.codingbadgers.bFundamentals.error.ExceptionHandler;
+import uk.codingbadgers.bFundamentals.module.Module;
+import uk.codingbadgers.bFundamentals.module.ModuleDescription;
+import uk.codingbadgers.bFundamentals.module.ModuleHelpTopic;
+import uk.codingbadgers.bFundamentals.module.annotation.ModuleInfo;
+import uk.codingbadgers.bFundamentals.module.events.ModuleLoadEvent;
+
+/**
+ * The ModuleLoader, used to load bFundamentals {@link Module}'s at runtime,
+ * it will automatically find any classes that extend {@link Module} in jars
+ * in the module directory and load them in.
+ */
+public class ModuleLoader {
+
+ private Map loaders = new HashMap();
+ private Map> classes = new HashMap>();
+ private List m_modules;
+
+ /**
+ * Instantiates a new module loader.
+ */
+ public ModuleLoader() {
+ m_modules = new LinkedList();
+ if (bFundamentals.getConfigurationManager().getModuleDirectory().mkdir()) {
+ bFundamentals.log(Level.INFO, "Creating Module Directory...");
+ }
+ }
+
+ /**
+ * Gets the directory of the modules.
+ *
+ * @return the module dir
+ * @deprecated {@link uk.codingbadgers.bFundamentals.ConfigManager#getModuleDirectory()}
+ */
+ public File getModuleDir() {
+ return bFundamentals.getConfigurationManager().getModuleDirectory();
+ }
+
+ /**
+ * Loads all the modules in the base modules directory.
+ */
+ public void load() {
+
+ List files = Arrays.asList(bFundamentals.getConfigurationManager().getModuleDirectory().listFiles(new FileExtensionFilter(".jar")));
+ for (File file : files) {
+ loadModule(file);
+ }
+
+ sort();
+
+ for (Module module : m_modules) {
+ try {
+ module.onLoad();
+ module.log(Level.INFO, module.getName() + " v:" + module.getVersion() + " has been loaded successfuly");
+ } catch (Exception ex) {
+ ExceptionHandler.handleException(ex);
+ }
+ }
+
+ bFundamentals.log(Level.INFO, "Loaded " + m_modules.size() + " modules.");
+ }
+
+ /**
+ * Load a module into the server.
+ *
+ * @param file the module's jar file
+ * @return the module instance
+ */
+ public Module loadModule(File file) {
+ Module result = null;
+
+ try {
+ URL[] urls = new URL[] { file.toURI().toURL() };
+
+ ModuleClassLoader loader = new ModuleClassLoader(this, urls, getClass().getClassLoader());
+
+ JarFile jarFile = new JarFile(file);
+ ModuleDescription moduledescription = null;
+ Set> modules = new HashSet>();
+
+ modules.addAll(ClassFinder.findModules(loader, urls));
+
+ // Old system descriptive system, left for backwards compatibility
+ if (jarFile.getEntry("path.yml") != null) {
+ JarEntry element = jarFile.getJarEntry("path.yml");
+ moduledescription = new ModuleDescription(jarFile.getInputStream(element));
+ }
+
+ if (modules.size() == 0) {
+ jarFile.close();
+ throw new ClassNotFoundException("Could not find a main class in jar " + file.getName() + ".");
+ }
+
+ if (bFundamentals.getConfigurationManager().isDebugEnabled()) {
+ getLogger().log(Level.INFO, "Loading " + modules.size() + " modules for jar " + file.getName());
+ }
+
+ for (Class extends Module> clazz : modules) {
+
+ if (bFundamentals.getConfigurationManager().isDebugEnabled()) {
+ getLogger().log(Level.INFO, "Loading clazz " + clazz.getName());
+ }
+
+ ModuleDescription description = moduledescription;
+
+ if (clazz.isAnnotationPresent(ModuleInfo.class)) {
+ ModuleInfo info = clazz.getAnnotation(ModuleInfo.class);
+ description = new ModuleDescription(info, clazz.getName());
+ }
+
+ if (description == null) {
+ throw new IOException("Description not found for module " + file.getName() + ".");
+ }
+
+ result = clazz.newInstance();
+
+ if (m_modules.contains(result)) {
+ getLogger().log(Level.WARNING, "The loadable " + file.getName() + " is already loaded, make sure to disable the module first");
+ getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load");
+ jarFile.close();
+ return null;
+ }
+
+ result.setFile(file);
+ result.setDesciption(description);
+ result.setJarFile(jarFile);
+ result.setDatafolder(new File(bFundamentals.getConfigurationManager().getModuleDirectory(), result.getName()));
+ result.setClassLoader(loader);
+ result.init();
+
+ ModuleLoadEvent event = new ModuleLoadEvent(bFundamentals.getInstance(), result, jarFile);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+
+ m_modules.add(result);
+ loaders.put(result.getName(), loader);
+ }
+
+ } catch (Throwable e) {
+ if (e instanceof Error && !(e instanceof NoClassDefFoundError)) {
+ getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load because of a serious error");
+ getLogger().log(Level.WARNING, e.getClass().getName());
+ } else {
+ getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " failed to load.");
+ }
+
+ if (e instanceof ClassCastException) {
+ getLogger().log(Level.WARNING, "The JAR file " + file.getName() + " is in the wrong directory.");
+ } else if (e instanceof ClassNotFoundException || e instanceof NoClassDefFoundError) {
+ getLogger().log(Level.WARNING, "Could not find class " + e.getMessage());
+ getLogger().log(Level.WARNING, "Are you missing a required dependecy?");
+ } else if (e instanceof RuntimeException) {
+ getLogger().log(Level.WARNING, "Unknown cause", e);
+ } else {
+ getLogger().log(Level.WARNING, "Unknown cause.");
+ getLogger().log(Level.WARNING, e.getMessage());
+ ExceptionHandler.handleException(e);
+ }
+ }
+
+ return result;
+ }
+
+ private Logger getLogger() {
+ return bFundamentals.getInstance().getLogger();
+ }
+
+ /**
+ * Loads a module with a given name.
+ *
+ * @param fileName the files name
+ */
+ public void load(String fileName) {
+ File module = new File(bFundamentals.getConfigurationManager().getModuleDirectory() + File.separator + fileName + ".jar");
+ load(module);
+ }
+
+ /**
+ * Loads a module with a jar file.
+ *
+ * @param file the jar file for this module
+ */
+ public void load(File file) {
+ if (getModule(file) != null) {
+ throw new IllegalArgumentException("Module " + file.getName() + " is already loaded");
+ }
+
+ Module result = loadModule(file);
+
+ if (result == null) {
+ return;
+ }
+
+ m_modules.add(result);
+
+ result.onLoad();
+ result.log(Level.INFO, result.getName() + " v:" + result.getVersion() + " has been loaded successfuly");
+ }
+
+ /**
+ * Unloads the modules.
+ */
+ public void unload() {
+ disable();
+ m_modules.clear();
+ }
+
+ /**
+ * Unload a specific module.
+ *
+ * @param module
+ * the module
+ */
+ public void unload(Module module) {
+ try {
+ module.setEnabled(false);
+ m_modules.remove(module);
+ } catch (Exception ex) {
+ ExceptionHandler.handleException(ex);
+ }
+ }
+
+ /**
+ * Run on enable in all modules.
+ */
+ public void enable() {
+ for (Module module : m_modules) {
+ try {
+ module.setEnabled(true);
+ Bukkit.getHelpMap().addTopic(new ModuleHelpTopic(module));
+ } catch (Exception ex) {
+ ExceptionHandler.handleException(ex);
+ }
+ }
+ }
+
+ /**
+ * run on disable in all modules.
+ */
+ public void disable() {
+ List modules = new ArrayList(m_modules);
+ for (Module module : modules) {
+ try {
+ unload(module);
+ } catch (Exception ex) {
+ ExceptionHandler.handleException(ex);
+ }
+ }
+ }
+
+ /**
+ * Gets the modules.
+ *
+ * @return the modules
+ */
+ public List getModules() {
+ return m_modules;
+ }
+
+ /**
+ * Update all the loaded modules if an updater is set.
+ */
+ public void update() {
+ if (!bFundamentals.getConfigurationManager().isAutoUpdateEnabled()) {
+ return;
+ }
+
+ for (Module module : m_modules) {
+ module.update();
+ }
+ }
+
+ /**
+ * Gets the module from its name.
+ *
+ * @param string
+ * the string
+ * @return the module
+ */
+ public Module getModule(String string) {
+ Iterator itr = m_modules.iterator();
+ while (itr.hasNext()) {
+ Module module = itr.next();
+ if (module.getName().equalsIgnoreCase(string)) {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the module from its file.
+ *
+ * @param file
+ * the file
+ * @return the module
+ */
+ public Module getModule(File file) {
+ Iterator itr = m_modules.iterator();
+ while (itr.hasNext()) {
+ Module module = itr.next();
+ if (module.getFile().getPath().equalsIgnoreCase(file.getPath())) {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets a class by its name from any of the module class loads.
+ *
+ * @param name the full class name, in the format for {@link Class#forName(String)}
+ * @return the class specified by its name
+ * @throws ClassNotFoundException if the specific class cannot be found
+ */
+ Class> getClassByName(String name) throws ClassNotFoundException {
+ Class> cachedClass = classes.get(name);
+
+ if (cachedClass != null) {
+ return cachedClass;
+ } else {
+ for (String current : loaders.keySet()) {
+ ModuleClassLoader loader = loaders.get(current);
+ try {
+ cachedClass = loader.findClass(name, false);
+ } catch (ClassNotFoundException cnfe) {
+ }
+
+ if (cachedClass != null) {
+ return cachedClass;
+ }
+ }
+ }
+ throw new ClassNotFoundException(name);
+ }
+
+ /**
+ * Sets a class for a specific name in the internal cache.
+ *
+ * @param name the name
+ * @param clazz the class
+ */
+ void setClass(String name, Class> clazz) {
+ if (!classes.containsKey(name)) {
+ classes.put(name, clazz);
+
+ if (ConfigurationSerializable.class.isAssignableFrom(clazz)) {
+ Class extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class);
+ ConfigurationSerialization.registerClass(serializable);
+ }
+ }
+ }
+
+ /**
+ * Sort the modules by name in the module list.
+ */
+ void sort() {
+ List sortedLoadables = new ArrayList();
+ List names = new ArrayList();
+
+ for (Module t : m_modules) {
+ names.add(t.getName());
+ }
+
+ Collections.sort(names);
+
+ for (String name : names) {
+ for (Module t : m_modules) {
+ if (t.getName().equals(name)) {
+ sortedLoadables.add(t);
+ }
+ }
+ }
+
+ m_modules = sortedLoadables;
+ }
+
+}
diff --git a/bFundamentals/src/uk/codingbadgers/bFundamentals/utils/CollectionUtils.java b/bFundamentals/src/uk/codingbadgers/bFundamentals/utils/CollectionUtils.java
new file mode 100644
index 0000000..507dba3
--- /dev/null
+++ b/bFundamentals/src/uk/codingbadgers/bFundamentals/utils/CollectionUtils.java
@@ -0,0 +1,41 @@
+/**
+ * bFundamentals 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package uk.codingbadgers.bFundamentals.utils;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList.Builder;
+
+/**
+ * The Utility class for using google collections.
+ */
+public class CollectionUtils {
+
+ /**
+ * Create a immutable copy of a list.
+ *
+ * @param the generic type of the list
+ * @param list the list to create a copy of
+ * @return a immutable copy of the list
+ */
+ public static List toImmutableList(List list) {
+ Builder builder = new Builder();
+ builder.addAll(list);
+ return builder.build();
+ }
+}
diff --git a/bFundamentals/test/uk/thecodingbadgers/bFundamentals/TestConfigManager.java b/bFundamentals/test/uk/thecodingbadgers/bFundamentals/TestConfigManager.java
index e6f87cb..903d1ec 100644
--- a/bFundamentals/test/uk/thecodingbadgers/bFundamentals/TestConfigManager.java
+++ b/bFundamentals/test/uk/thecodingbadgers/bFundamentals/TestConfigManager.java
@@ -65,6 +65,11 @@ public String getLogPrefix() {
throw new UnsupportedOperationException();
}
+ @Override
+ public File getModuleDirectory() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String getCrashPassword() {
return "PASSWORD";
diff --git a/bGui/src/uk/codingbadgers/bgui/click/ServerHandler.java b/bGui/src/uk/codingbadgers/bgui/click/ServerHandler.java
index e963c85..67330b2 100644
--- a/bGui/src/uk/codingbadgers/bgui/click/ServerHandler.java
+++ b/bGui/src/uk/codingbadgers/bgui/click/ServerHandler.java
@@ -1,3 +1,20 @@
+/**
+ * bGui 1.2-SNAPSHOT
+ * Copyright (C) 2013 CodingBadgers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
package uk.codingbadgers.bgui.click;
import java.io.ByteArrayOutputStream;