Search in sources :

Example 1 with FilterFactory

use of org.spongepowered.common.event.filter.FilterFactory in project SpongeCommon by SpongePowered.

the class SpongeEventManager method registerListener.

private void registerListener(final PluginContainer plugin, final Object listenerObject) {
    Objects.requireNonNull(plugin, "plugin");
    Objects.requireNonNull(listenerObject, "listener");
    if (this.registeredListeners.contains(listenerObject)) {
        SpongeCommon.logger().warn("Plugin {} attempted to register an already registered listener ({})", plugin.metadata().id(), listenerObject.getClass().getName());
        Thread.dumpStack();
        return;
    }
    final List<RegisteredListener<? extends Event>> handlers = new ArrayList<>();
    final Map<ListenerClassVisitor.DiscoveredMethod, String> methodErrors = new HashMap<>();
    final Class<?> handle = listenerObject.getClass();
    final ClassLoader handleLoader = handle.getClassLoader();
    AnnotatedEventListener.Factory handlerFactory = this.classLoaders.get(handleLoader);
    if (handlerFactory == null) {
        final DefineableClassLoader classLoader = new DefineableClassLoader(handleLoader);
        handlerFactory = new ClassEventListenerFactory("org.spongepowered.common.event.listener", new FilterFactory("org.spongepowered.common.event.filters", classLoader), classLoader);
        this.classLoaders.put(handleLoader, handlerFactory);
    }
    try {
        final List<ListenerClassVisitor.DiscoveredMethod> methods = ListenerClassVisitor.getEventListenerMethods(handle);
        for (final ListenerClassVisitor.DiscoveredMethod method : methods) {
            final Listener listener = method.listener();
            @Nullable final String error = SpongeEventManager.getHandlerErrorOrNull(method);
            if (error == null) {
                final Type eventType = method.parameterTypes()[0].genericType();
                final AnnotatedEventListener handler;
                try {
                    handler = handlerFactory.create(listenerObject, method);
                } catch (final Exception e) {
                    SpongeCommon.logger().error("Failed to create handler for {} on {}", method, handle, e);
                    continue;
                }
                handlers.add(SpongeEventManager.createRegistration(plugin, eventType, listener.order(), listener.beforeModifications(), handler));
            } else {
                methodErrors.put(method, error);
            }
        }
    } catch (final IOException ioe) {
        SpongeCommon.logger().warn("Exception trying to register superclass listeners", ioe);
    } catch (final NoSuchMethodException nsme) {
        SpongeCommon.logger().warn("Discovered method listener somehow not found for class " + handle.getName(), nsme);
    } catch (final ClassNotFoundException e) {
        SpongeCommon.logger().warn("Somehow couldn't classload a class while trying to register event listeners for containing class: " + handle.getName(), e);
    }
    // about those.
    for (Class<?> handleParent = handle; handleParent != Object.class; handleParent = handleParent.getSuperclass()) {
        try {
            final List<ListenerClassVisitor.DiscoveredMethod> methods = ListenerClassVisitor.getEventListenerMethods(handleParent);
            for (final ListenerClassVisitor.DiscoveredMethod method : methods) {
                if (!methodErrors.containsKey(method)) {
                    @Nullable final String error = SpongeEventManager.getHandlerErrorOrNull(method);
                    if (error != null) {
                        methodErrors.put(method, error);
                    }
                }
            }
        } catch (final RuntimeException re) {
            // This is the Forge classloader that checks for client sided classes
            if (re.getMessage().startsWith("Attempted to load class")) {
                continue;
            }
            SpongeCommon.logger().warn("Exception trying to register superclass listeners", re);
        } catch (final Exception e) {
            SpongeCommon.logger().warn("Attempted to register listeners but had an exception loading listeners for super classes", e);
        }
    }
    for (final Map.Entry<ListenerClassVisitor.DiscoveredMethod, String> method : methodErrors.entrySet()) {
        SpongeCommon.logger().warn("Invalid listener method {} in {}: {}", method.getKey(), method.getKey().declaringClass().getName(), method.getValue());
    }
    this.registeredListeners.add(listenerObject);
    this.register(handlers);
}
Also used : DefineableClassLoader(org.spongepowered.common.event.gen.DefineableClassLoader) EventListener(org.spongepowered.api.event.EventListener) Listener(org.spongepowered.api.event.Listener) IdentityHashMap(java.util.IdentityHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) FilterFactory(org.spongepowered.common.event.filter.FilterFactory) DefineableClassLoader(org.spongepowered.common.event.gen.DefineableClassLoader) IOException(java.io.IOException) IOException(java.io.IOException) Type(java.lang.reflect.Type) InteractContainerEvent(org.spongepowered.api.event.item.inventory.container.InteractContainerEvent) GenericEvent(org.spongepowered.api.event.GenericEvent) Event(org.spongepowered.api.event.Event) AbstractEvent(org.spongepowered.api.event.impl.AbstractEvent) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Aggregations

IOException (java.io.IOException)1 Type (java.lang.reflect.Type)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Nullable (org.checkerframework.checker.nullness.qual.Nullable)1 Event (org.spongepowered.api.event.Event)1 EventListener (org.spongepowered.api.event.EventListener)1 GenericEvent (org.spongepowered.api.event.GenericEvent)1 Listener (org.spongepowered.api.event.Listener)1 AbstractEvent (org.spongepowered.api.event.impl.AbstractEvent)1 InteractContainerEvent (org.spongepowered.api.event.item.inventory.container.InteractContainerEvent)1 FilterFactory (org.spongepowered.common.event.filter.FilterFactory)1 DefineableClassLoader (org.spongepowered.common.event.gen.DefineableClassLoader)1