List omission issue

Discussion in 'Spigot Plugin Development' started by WAS, May 29, 2017.

  1. WAS

    WAS

    I'm trying to loop through all of bukkits events (which I was told was not possible in a previous thread. :p) but there are a few classes in a the packages which should be omitted. For some reason though, these classes are not being omitted and trying to be loaded as a attribute to build a Listener.

    Code (Text):
    [23:14:12 ERROR]: Error occurred while enabling EventDebugger v0.0.1 (Is it up to date?)
    org.bukkit.plugin.IllegalPluginAccessException: Unable to find handler list for event org.bukkit.event.world.WorldEvent. Static getHandlerList method required!
      at org.bukkit.plugin.SimplePluginManager.getRegistrationClass(SimplePluginManager.java:583) ~[spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.plugin.SimplePluginManager.getRegistrationClass(SimplePluginManager.java:581) ~[spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginManager.java:525) ~[spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at wa.was.eventdebugger.EventDebugger.onEnable(EventDebugger.java:87) ~[?:?]
      at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:264) ~[spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:337) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:402) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.craftbukkit.v1_12_R1.CraftServer.enablePlugin(CraftServer.java:377) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at org.bukkit.craftbukkit.v1_12_R1.CraftServer.enablePlugins(CraftServer.java:327) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at net.minecraft.server.v1_12_R1.MinecraftServer.t(MinecraftServer.java:421) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at net.minecraft.server.v1_12_R1.MinecraftServer.l(MinecraftServer.java:382) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at net.minecraft.server.v1_12_R1.MinecraftServer.a(MinecraftServer.java:337) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at net.minecraft.server.v1_12_R1.DedicatedServer.init(DedicatedServer.java:272) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]
      at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:544) [spigot-1.12-pre5.jar:git-Spigot-ea4525e-ccc420a]p
    See the issue here is "WorldEvent" is part of the blacklist list. It should not be added to the events list, and ultimate registering a listener on Line 87

    Code (Java):
    /*************************
    *
    * Copyright (c) 2017 Jordan Thompson (WASasquatch)
    *
    * Permission is hereby granted, free of charge, to any person obtaining a copy
    * of this software and associated documentation files (the "Software"), to deal
    * in the Software without restriction, including without limitation the rights
    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    * copies of the Software, and to permit persons to whom the Software is
    * furnished to do so, subject to the following conditions:
    *
    * The above copyright notice and this permission notice shall be included in
    * all copies or substantial portions of the Software.
    *
    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    * SOFTWARE.
    *
    *************************/


    public class EventDebugger extends JavaPlugin {

       @SuppressWarnings("rawtypes")
       private Set<Class> events;
       private Set<Listener> enabled;

       @SuppressWarnings({ "unchecked", "rawtypes" })
       @Override
       public void onEnable() {

         createConfig();

         events = new HashSet<Class>();
         enabled = new HashSet<Listener>();
         List<String> blacklist = new ArrayList<String>();

         if (getConfig().getStringList("blacklist-classes").size() > 0)
           blacklist.addAll(getConfig().getStringList("blacklist-classes"));
       
         EventListenerBuilder cb = new EventListenerBuilder(getDataFolder().getAbsolutePath() + File.separator + "cache",
             "../../../spigot-1.12-pre5.jar", "C:\\Program Files\\Java\\jdk1.8.0_131", this);

         Field field = null;
         try {
         
           field = ClassLoader.class.getDeclaredField("classes");
           field.setAccessible(true);
           ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
           List<Class> classes = (List<Class>) field.get(classLoader);
         
           List<Class> classesFinal = new ArrayList<Class>();
           classesFinal.addAll(classes);
         
           for (Class clazz : classesFinal) {
             if (clazz.getName().toString().startsWith("org.bukkit.event.") && !(blacklist.contains(clazz.getSimpleName()))) {
               System.out.println("Class: " + clazz.getSimpleName() + " from " + clazz.getPackage());
               events.add(clazz);
             }
           }
         
         } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
           ex.printStackTrace();
         }

         if (getConfig().getBoolean("enable-safe-mode", false)) {
           for (Class event : events) {
             Listener eventListener = cb.newEventListener(event.getSimpleName());
             if (eventListener != null) {
               getServer().getPluginManager().registerEvents(eventListener, this); // <-- LINE 87
               enabled.add(eventListener);
             }
           }
         } else {
           if (getConfig().getStringList("enabled-events").size() > 0) {
             for (String event : getConfig().getStringList("enabled-events")) {
               boolean validEvent = false;
               for (Class eventClass : events) {
                 if (eventClass.getSimpleName().equals(event)
                     && !(blacklist.contains(eventClass.getSimpleName()))) {
                   validEvent = true;
                   break;
                 }
               }
               if (validEvent) {
                 Listener eventListener = cb.newEventListener(event);
                 getServer().getPluginManager().registerEvents(eventListener, this);
                 enabled.add(eventListener);
               }
             }
           }
         }

       }

       private void createConfig() {
         try {
           if (!getDataFolder().exists()) {
             getDataFolder().mkdirs();
           }
           File file = new File(getDataFolder(), "config.yml");
           if (!file.exists()) {
             getLogger().info("Creating configuration...");
             saveDefaultConfig();
           }
         } catch (Exception e) {
           e.printStackTrace();

         }
       }

    }

    The blacklist comes from the config
    Code (YAML):
    # List enaabled events to monitor manually
    enabled-events
    : []

    # Enable Safe Mode
    # When Safe Mode is enabled, all events will print debug messages.
    enable-safe-mode
    : false

    # Blacklist Classes
    blacklist-classes
    :
     - Cancellable
    - Event
    - EventException
    - EventHandler
    - EventPriority
    - HandlerList
    - Listener
    - Result
    - PlayerEvent
    - BlockEvent
    - WorldEvent
    - EntityEvent
    - HangingEvent
    - InventoryEvent
    - ServerEvent
    - ServiceEvent
    - VehicleEvent
    - WeatherEvent
    - InventoryType
    - PluginEvent
    Note: I tried some lambda to remove the classes in question from the list, but was getting a attribute error on all attempts so I gave up lol

    Sorry if questions getting dumb. Been up for almost two days and just trying to keep occupied with code.
     
    #1 WAS, May 29, 2017
    Last edited: May 29, 2017
  2. One of the edge cases where your code fails: ChunkEvent is not blacklisted, but starts with the package prefix you specified. It's abstract, has no HandlerList, so registering it will attempt to get the handler list for the super type (WorldEvent), which also has no HandlerList, and eventully fail.

    Instead of a config file, just check if there's a HandlerList somewhere down the road (so if not in the current class, in any of it's super classes)
     
  3. WAS

    WAS

    Seems like a lot of random (and fallacy prone) "super" checks to get to a possible "HandlerList". Maybe I don't understand what you mean exactly? Do you have an example? Most classes are in different packages so I'd imagine one being in event and one being in event.player? How do I get the super other than getSuperclass which returns either java.lang.Object or java.lang.Class?

    I also get erros on things like EventPriority which is also in the list. But also must be used, and is the in the class path for the dynamic class builder (also works fine in actaul events).

    It is a different error every server load, some having to do with HandlerList, other having to do with the classes which are not actual implementable Events.

    Also I did initially have the list because I want the the user to be able to have global debug on for all events, while being able to omit events. For example ChunkLoadEvent or ChunkUnloadEvent.
     
    #3 WAS, May 29, 2017
    Last edited: May 29, 2017