Update to using a newer method.
This commit is contained in:
parent
fc125dfd32
commit
ee629e2bc8
10 changed files with 277 additions and 9 deletions
|
@ -1,14 +1,22 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
|
||||
import dev.zontreck.eventsbus.annotations.Priority;
|
||||
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
|
||||
import dev.zontreck.eventsbus.annotations.Subscribe;
|
||||
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
|
||||
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* To be removed
|
||||
* <br/>
|
||||
* Use {} instead
|
||||
*/
|
||||
@Deprecated()
|
||||
public class Bus {
|
||||
/**
|
||||
* The main event bus!
|
||||
|
|
93
src/main/java/dev/zontreck/eventsbus/ClassScanner.java
Normal file
93
src/main/java/dev/zontreck/eventsbus/ClassScanner.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* Used internally. Do not directly invoke
|
||||
* <br/>
|
||||
* Accessor is set Protected intentionally!!!!!!!!!
|
||||
*/
|
||||
class ClassScanner {
|
||||
/**
|
||||
* Start the process of scanning the classes and forcing them to load in
|
||||
* <br/>
|
||||
* This is used by the event dispatcher
|
||||
*/
|
||||
protected static void DoScan() {
|
||||
// Scan all classes in the classpath
|
||||
Set<Class<?>> scannedClasses = scanClasses();
|
||||
|
||||
// Force loading of all scanned classes
|
||||
for (Class<?> clazz : scannedClasses) {
|
||||
try {
|
||||
// Load the class
|
||||
Class.forName(clazz.getName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Class<?>> scanClasses() {
|
||||
String classpath = System.getProperty("java.class.path");
|
||||
String[] classpathEntries = classpath.split(File.pathSeparator);
|
||||
|
||||
Set<Class<?>> scannedClasses = new HashSet<>();
|
||||
for (String classpathEntry : classpathEntries) {
|
||||
File file = new File(classpathEntry);
|
||||
if (file.isDirectory()) {
|
||||
scanClassesInDirectory(file, "", scannedClasses);
|
||||
} else if (file.isFile() && classpathEntry.endsWith(".jar")) {
|
||||
scanClassesInJar(file, scannedClasses);
|
||||
}
|
||||
}
|
||||
|
||||
return scannedClasses;
|
||||
}
|
||||
|
||||
private static void scanClassesInDirectory(File directory, String packageName, Set<Class<?>> scannedClasses) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
scanClassesInDirectory(file, packageName + "." + file.getName(), scannedClasses);
|
||||
} else if (file.getName().endsWith(".class")) {
|
||||
String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
scannedClasses.add(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void scanClassesInJar(File jarFile, Set<Class<?>> scannedClasses) {
|
||||
try (JarFile jf = new JarFile(jarFile)) {
|
||||
for (JarEntry entry : Collections.list(jf.entries())) {
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
String className = entry.getName().replace("/", ".").substring(0, entry.getName().length() - 6);
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
scannedClasses.add(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
|
||||
|
||||
import dev.zontreck.eventsbus.annotations.Cancellable;
|
||||
import dev.zontreck.eventsbus.annotations.Priority;
|
||||
|
||||
public class Event {
|
||||
private boolean cancelled = false;
|
||||
|
||||
|
|
145
src/main/java/dev/zontreck/eventsbus/EventDispatcher.java
Normal file
145
src/main/java/dev/zontreck/eventsbus/EventDispatcher.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
|
||||
import dev.zontreck.eventsbus.annotations.EventSubscriber;
|
||||
import dev.zontreck.eventsbus.annotations.Priority;
|
||||
import dev.zontreck.eventsbus.annotations.SingleshotEvent;
|
||||
import dev.zontreck.eventsbus.annotations.Subscribe;
|
||||
import dev.zontreck.eventsbus.events.EventBusReadyEvent;
|
||||
import dev.zontreck.eventsbus.events.ResetEventBusEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EventDispatcher
|
||||
{
|
||||
private static List<Method> singleshot = new ArrayList<>();
|
||||
private static List<Class<?>> subscribers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Scans every Java class that is currently loaded. It then checks for Subscribe, and a proper parameter before posting the Event.
|
||||
* The Event will only be posted if not cancelled using {@link Event#setCancelled(boolean)} and that {@link Subscribe#allowCancelled()} allows.
|
||||
* @param event The event to post
|
||||
* @return True if cancelled.
|
||||
*/
|
||||
|
||||
public static boolean Post(Event event)
|
||||
{
|
||||
for(PriorityLevel level : PriorityLevel.values())
|
||||
{
|
||||
|
||||
for(Class<?> clazz : subscribers)
|
||||
{
|
||||
for(Method M :clazz.getMethods())
|
||||
{
|
||||
if(!M.isAnnotationPresent(Subscribe.class)) continue;
|
||||
|
||||
Subscribe subscriber = M.getAnnotation(Subscribe.class);
|
||||
|
||||
|
||||
boolean canPost=true;
|
||||
Class<?> param = M.getParameterTypes()[0];
|
||||
if(param == event.getClass())
|
||||
{
|
||||
if(M.isAnnotationPresent(SingleshotEvent.class))
|
||||
{
|
||||
if(singleshot.contains(M))
|
||||
{
|
||||
canPost=false;
|
||||
}
|
||||
}
|
||||
} else canPost=false;
|
||||
|
||||
PriorityLevel eventPriotityLevel= PriorityLevel.HIGH; // Default
|
||||
|
||||
if(M.isAnnotationPresent(Priority.class))
|
||||
{
|
||||
Priority prio = M.getAnnotation(Priority.class);
|
||||
eventPriotityLevel=prio.Level();
|
||||
}
|
||||
|
||||
if(level != eventPriotityLevel)
|
||||
{
|
||||
canPost=false;
|
||||
}
|
||||
|
||||
|
||||
// Dispatch the event now
|
||||
|
||||
try {
|
||||
if(event.isCancelled() && !subscriber.allowCancelled())
|
||||
continue;
|
||||
else
|
||||
M.invoke(null, event);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return event.isCancelled();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scan all event subscribers
|
||||
*/
|
||||
public static void Scan()
|
||||
{
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
Package[] packages = Package.getPackages();
|
||||
|
||||
List<Class<?>> loaded = new ArrayList<>();
|
||||
|
||||
for(Package pkg : packages)
|
||||
{
|
||||
try{
|
||||
String packageName = pkg.getName();
|
||||
Field classesField = ClassLoader.class.getDeclaredField("classes");
|
||||
classesField.setAccessible(true);
|
||||
|
||||
List<Class<?>> classes = (List<Class<?>>) classesField.get(classLoader);
|
||||
|
||||
for(Class<?> clazz : classes)
|
||||
{
|
||||
if(clazz.getPackage().getName().equalsIgnoreCase(packageName))
|
||||
{
|
||||
|
||||
if(clazz.isAnnotationPresent(EventSubscriber.class))
|
||||
loaded.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
subscribers = loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the events system.
|
||||
* <br/>
|
||||
* This action clears the Singleshot list for the events that should only be invoked once. And rescans all classes incase new classes were dynamically loaded.
|
||||
*/
|
||||
public static void Reset()
|
||||
{
|
||||
Post(new ResetEventBusEvent());
|
||||
|
||||
singleshot.clear();
|
||||
Scan();
|
||||
ClassScanner.DoScan();
|
||||
|
||||
Post(new EventBusReadyEvent());
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
package dev.zontreck.eventsbus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -1,4 +1,4 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
package dev.zontreck.eventsbus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
|
@ -6,7 +6,6 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = ElementType.METHOD)
|
||||
|
||||
public @interface Subscribe {
|
||||
@Target(value = ElementType.TYPE)
|
||||
public @interface EventSubscriber {
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
package dev.zontreck.eventsbus.annotations;
|
||||
|
||||
import dev.zontreck.eventsbus.PriorityLevel;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -1,4 +1,4 @@
|
|||
package dev.zontreck.eventsbus;
|
||||
package dev.zontreck.eventsbus.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
|
@ -0,0 +1,18 @@
|
|||
package dev.zontreck.eventsbus.annotations;
|
||||
|
||||
import dev.zontreck.eventsbus.Event;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
@Target(value = ElementType.METHOD)
|
||||
|
||||
public @interface Subscribe {
|
||||
/**
|
||||
* Marks that the subscribed method will not receive the signal if the event was cancelled with {@link Event#setCancelled(boolean)}
|
||||
*/
|
||||
boolean allowCancelled();
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package dev.zontreck.eventsbus.events;
|
||||
|
||||
import dev.zontreck.eventsbus.Cancellable;
|
||||
import dev.zontreck.eventsbus.annotations.Cancellable;
|
||||
import dev.zontreck.eventsbus.Event;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue