Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of method discovery in AnnotatedEventManager #2454

2 changes: 1 addition & 1 deletion src/main/java/net/dv8tion/jda/api/JDABuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,7 @@ public JDA build()
if (audioSendFactory != null)
jda.setAudioSendFactory(audioSendFactory);

listeners.forEach(jda::addEventListener);
jda.addEventListener(listeners.toArray());
jda.setStatus(JDA.Status.INITIALIZED); //This is already set by JDA internally, but this is to make sure the listeners catch it.

// Set the presence information before connecting to have the correct information ready when sending IDENTIFY
Expand Down
53 changes: 28 additions & 25 deletions src/main/java/net/dv8tion/jda/api/hooks/AnnotatedEventManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ public class AnnotatedEventManager implements IEventManager
@Override
public void register(@Nonnull Object listener)
{
if (listener.getClass().isArray())
throw new IllegalArgumentException("Tried to register an array (" + listener.getClass().getCanonicalName() + ") as an annotated event listener." +
"You might want to cast the array into Object[]");
freya022 marked this conversation as resolved.
Show resolved Hide resolved

if (listeners.add(listener))
{
updateMethods();
registerListenerMethods(listener);
}
}

Expand Down Expand Up @@ -114,32 +118,31 @@ private void updateMethods()
methods.clear();
for (Object listener : listeners)
{
boolean isClass = listener instanceof Class;
Class<?> c = isClass ? (Class) listener : listener.getClass();
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods)
{
if (!m.isAnnotationPresent(SubscribeEvent.class) || (isClass && !Modifier.isStatic(m.getModifiers())))
{
continue;
}
Class<?>[] pType = m.getParameterTypes();
if (pType.length == 1 && GenericEvent.class.isAssignableFrom(pType[0]))
{
Class<?> eventClass = pType[0];
if (!methods.containsKey(eventClass))
{
methods.put(eventClass, new ConcurrentHashMap<>());
}
registerListenerMethods(listener);
}
}

if (!methods.get(eventClass).containsKey(listener))
{
methods.get(eventClass).put(listener, new CopyOnWriteArrayList<>());
}
private void registerListenerMethods(Object listener)
{
boolean isClass = listener instanceof Class;
Class<?> c = isClass ? (Class<?>) listener : listener.getClass();
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods)
{
if (!m.isAnnotationPresent(SubscribeEvent.class))
continue;
//Skip member methods if listener is a Class
if (isClass && !Modifier.isStatic(m.getModifiers()))
continue;

methods.get(eventClass).get(listener).add(m);
}
}
final Class<?>[] parameterTypes = m.getParameterTypes();
if (parameterTypes.length != 1 || !GenericEvent.class.isAssignableFrom(parameterTypes[0]))
throw new IllegalArgumentException("Method '" + m + "' must have at most 1 parameter, which implements GenericEvent");
freya022 marked this conversation as resolved.
Show resolved Hide resolved

Class<?> eventClass = parameterTypes[0];
methods.computeIfAbsent(eventClass, k -> new ConcurrentHashMap<>())
.computeIfAbsent(listener, k -> new CopyOnWriteArrayList<>())
.add(m);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ protected JDAImpl buildInstance(final int shardId)
if (this.sessionConfig.getAudioSendFactory() != null)
jda.setAudioSendFactory(this.sessionConfig.getAudioSendFactory());

this.eventConfig.getListeners().forEach(jda::addEventListener);
jda.addEventListener(this.eventConfig.getListeners().toArray());
this.eventConfig.getListenerProviders().forEach(provider -> jda.addEventListener(provider.apply(shardId)));

// Set the presence information before connecting to have the correct information ready when sending IDENTIFY
Expand Down