Plugins event handling through IWithEventHandlers.

keep-around/d31701866686f66088b78de2e29736ae36e55a68
Pingex aka Raphaël 9 years ago
parent 72d4a3b54e
commit 0088bc59c2

@ -1,5 +1,7 @@
package net.pingex.dcf.core;
import net.pingex.dcf.modularity.PluginWrapper;
import net.pingex.dcf.modularity.events.EventManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import sx.blah.discord.api.events.EventSubscriber;
@ -20,6 +22,7 @@ public class CoreEventsHandler
public static void onReady(ReadyEvent event)
{
LOGGER.info("Connection with user #{} ready.", event.getClient().getOurUser().getID());
EventManager.getInstance().updateConnectionHandlers(event.getClient());
}
@EventSubscriber
@ -63,4 +66,50 @@ public class CoreEventsHandler
{
LOGGER.info("Joined guild #{}.", event.getGuild().getID());
}
/**
* Called whenever a new plugin has been preloaded.
* @param plugin Target plugin
*/
public static void pluginPreloaded(PluginWrapper plugin)
{
}
/**
* Called whenever a new plugin has been laoded.
* @param plugin Target plugin
*/
public static void pluginLoaded(PluginWrapper plugin)
{
}
/**
* Called whenever a plugin is running.
* @param plugin Target plugin
*/
public static void pluginRunning(PluginWrapper plugin)
{
EventManager.getInstance().checkAndRegister(plugin); // Hook: event handlers
// TODO: Hook: commands
}
/**
* Called whenever a plugin has stopped.
* @param plugin Target plugin
*/
public static void pluginStopped(PluginWrapper plugin)
{
EventManager.getInstance().unregister(plugin); // Hook: event handlers
}
/**
* Called whenever a plugin has unloaded.
* @param plugin Target plugin
*/
public static void pluginUnloaded(PluginWrapper plugin)
{
}
}

@ -66,7 +66,6 @@ public class GatewayConnectionsManager
IDiscordClient builtConnection = builder.login();
connectionsDatastore.add(builtConnection);
builtConnection.getDispatcher().registerListener(CoreEventsHandler.class); // Register the core event handler independently from the events package
//updateListeners(builtConnection, null); // TODO: EventRegistry
}
catch (DiscordException e)
{
@ -92,7 +91,7 @@ public class GatewayConnectionsManager
* @param target Target conection, must be registered
* @param refListeners Reference listeners list
*/
public void updateListeners(IDiscordClient target, Set<Object> refListeners)
public void updateListeners(IDiscordClient target, Set<Class<?>> refListeners)
{
LOGGER.debug("Updating listeners for target " + target.getOurUser().getID());
@ -124,7 +123,7 @@ public class GatewayConnectionsManager
* Update all connections listeners
* @param refListeners Reference listeners list
*/
public void updateAllListeners(Set<Object> refListeners)
public void updateAllListeners(Set<Class<?>> refListeners)
{
for(IDiscordClient i : connectionsDatastore) updateListeners(i, refListeners);
}

@ -1,6 +1,7 @@
package net.pingex.dcf.modularity;
import net.pingex.dcf.core.Configuration;
import net.pingex.dcf.core.CoreEventsHandler;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -128,9 +129,11 @@ public class PluginLoader
{
try
{
plugins.put(clazz.getAnnotation(Plugin.class).id(), new PluginWrapper(clazz.asSubclass(IPlugin.class), classLoader));
PluginWrapper plugin = new PluginWrapper(clazz.asSubclass(IPlugin.class), classLoader);
plugins.put(clazz.getAnnotation(Plugin.class).id(), plugin);
LOGGER.debug("Plugin {} {} preloaded.", clazz.getAnnotation(Plugin.class).id(), clazz.getAnnotation(Plugin.class).version());
counter++;
CoreEventsHandler.pluginPreloaded(plugin);
}
catch(IllegalAccessException | InstantiationException e)
{
@ -182,6 +185,7 @@ public class PluginLoader
plugin.getInstance().load(Configuration.getStore());
plugin.setState(PluginState.LOADED);
LOGGER.info("Loaded plugin {}.", id);
CoreEventsHandler.pluginLoaded(plugin);
}
catch(Throwable throwable)
{
@ -229,6 +233,7 @@ public class PluginLoader
plugin.getInstance().run();
LOGGER.info("Plugin {} is now running. (last state: {})", id, plugin.getState());
plugin.setState(PluginState.RUNNING);
CoreEventsHandler.pluginRunning(plugin);
}
catch(Throwable throwable)
{
@ -263,6 +268,7 @@ public class PluginLoader
plugin.getInstance().stop();
LOGGER.info("Stopped plugin {}.", id);
plugin.setState(PluginState.STOPPED);
CoreEventsHandler.pluginStopped(plugin);
}
/**
@ -291,6 +297,7 @@ public class PluginLoader
plugin.getInstance().unload();
LOGGER.info("Unloaded plugin {}.", id);
plugin.setState(PluginState.UNLOADED);
CoreEventsHandler.pluginUnloaded(plugin);
}
/**

@ -101,4 +101,10 @@ public class PluginWrapper
{
this.state = state;
}
@Override
public boolean equals(Object obj)
{
return obj instanceof PluginWrapper && id.equals(((PluginWrapper) obj).getId());
}
}

@ -0,0 +1,105 @@
package net.pingex.dcf.modularity.events;
import net.pingex.dcf.core.GatewayConnectionsManager;
import net.pingex.dcf.modularity.PluginWrapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import sx.blah.discord.api.IDiscordClient;
import java.util.HashSet;
import java.util.Set;
/**
* Contains all foreign event handlers for D4J.
*/
public class EventManager
{
/**
* Singleton instance.
*/
private static EventManager ourInstance = new EventManager();
/**
* Logger
*/
private static Logger LOGGER = LogManager.getLogger(EventManager.class);
/**
* Get current instance
* @return The unique instance.
*/
public static EventManager getInstance()
{
return ourInstance;
}
/**
* Contains all plugins which implements IWithEvents
*/
private Set<PluginWrapper> handlers;
/**
* Enforce singleton.
*/
private EventManager()
{
handlers = new HashSet<>();
}
/**
* Check that the plugin has event handlers and register it to active handlers pool.
* @param plugin Target plugin.
*/
public void checkAndRegister(PluginWrapper plugin)
{
LOGGER.trace("Checking {} for event handlers.", plugin.getId());
if(IWithEventHandlers.class.isAssignableFrom(plugin.getPluginClass()))
{
LOGGER.debug("Registering event handlers for plugin {}.", plugin.getId());
handlers.add(plugin);
updateConnectionsHandlers(); // Trigger update
}
else LOGGER.trace("Plugin {} has no event handlers.", plugin.getId());
}
/**
* Unregister plugin from active handlers pool.
* @param plugin Target plugin.
*/
public void unregister(PluginWrapper plugin)
{
if(handlers.contains(plugin))
{
LOGGER.debug("Unregistering event handlers for plugin {}.", plugin.getId());
handlers.remove(plugin);
updateConnectionsHandlers(); // Trigger update
}
}
/**
* Collect all event handlers into a single set
* @return Final set
*/
public Set<Class<?>> collectAllHandlers()
{
Set<Class<?>> toReturn = new HashSet<>();
handlers.forEach(pluginWrapper -> toReturn.addAll(((IWithEventHandlers) pluginWrapper.getInstance()).getEventHandlers()));
return toReturn;
}
/**
* Delegated method
*/
public void updateConnectionsHandlers()
{
GatewayConnectionsManager.getInstance().updateAllListeners(collectAllHandlers());
}
/**
* Delegated method
*/
public void updateConnectionHandlers(IDiscordClient target)
{
GatewayConnectionsManager.getInstance().updateListeners(target, collectAllHandlers());
}
}

@ -0,0 +1,15 @@
package net.pingex.dcf.modularity.events;
import java.util.Set;
/**
* Interface which indicates that the plugin has event handlers.
*/
public interface IWithEventHandlers
{
/**
* Gives all event handlers classes for the plugin.
* @return All events handlers to submit to D4J.
*/
Set<Class<?>> getEventHandlers();
}