diff --git a/src/main/java/net/minestom/server/extensions/DiscoveredExtension.java b/src/main/java/net/minestom/server/extensions/DiscoveredExtension.java index cffe445ba..1239990db 100644 --- a/src/main/java/net/minestom/server/extensions/DiscoveredExtension.java +++ b/src/main/java/net/minestom/server/extensions/DiscoveredExtension.java @@ -116,7 +116,7 @@ public final class DiscoveredExtension { void createClassLoader() { Check.stateCondition(classLoader != null, "Extension classloader has already been created"); final URL[] urls = this.files.toArray(new URL[0]); - classLoader = new ExtensionClassLoader(this.getName(), urls); + classLoader = new ExtensionClassLoader(this.getName(), urls, this); } @NotNull diff --git a/src/main/java/net/minestom/server/extensions/Extension.java b/src/main/java/net/minestom/server/extensions/Extension.java index 1130e83ec..2ecc9e8fc 100644 --- a/src/main/java/net/minestom/server/extensions/Extension.java +++ b/src/main/java/net/minestom/server/extensions/Extension.java @@ -17,16 +17,6 @@ import java.util.HashSet; import java.util.Set; public abstract class Extension { - // Set by reflection - @SuppressWarnings("unused") - private DiscoveredExtension origin; - // Set by reflection - @SuppressWarnings("unused") - private Logger logger; - // Set by reflection - @SuppressWarnings("unused") - private EventNode eventNode; - /** * List of extensions that depend on this extension. */ @@ -56,9 +46,16 @@ public abstract class Extension { } + ExtensionClassLoader getExtensionClassLoader() { + if (getClass().getClassLoader() instanceof ExtensionClassLoader extensionClassLoader) { + return extensionClassLoader; + } + throw new IllegalStateException("Extension class loader is not an ExtensionClassLoader"); + } + @NotNull public DiscoveredExtension getOrigin() { - return origin; + return getExtensionClassLoader().getDiscoveredExtension(); } /** @@ -68,11 +65,11 @@ public abstract class Extension { */ @NotNull public Logger getLogger() { - return logger; + return getExtensionClassLoader().getLogger(); } public @NotNull EventNode getEventNode() { - return eventNode; + return getExtensionClassLoader().getEventNode(); } public @NotNull Path getDataDirectory() { diff --git a/src/main/java/net/minestom/server/extensions/ExtensionClassLoader.java b/src/main/java/net/minestom/server/extensions/ExtensionClassLoader.java index e59bd1b85..1c212bd9a 100644 --- a/src/main/java/net/minestom/server/extensions/ExtensionClassLoader.java +++ b/src/main/java/net/minestom/server/extensions/ExtensionClassLoader.java @@ -1,7 +1,11 @@ package net.minestom.server.extensions; import net.minestom.server.MinecraftServer; +import net.minestom.server.event.Event; +import net.minestom.server.event.EventNode; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.InputStream; import java.net.URL; @@ -11,13 +15,18 @@ import java.util.List; public final class ExtensionClassLoader extends URLClassLoader { private final List children = new ArrayList<>(); + private final DiscoveredExtension discoveredExtension; + private EventNode eventNode; + private Logger logger; - public ExtensionClassLoader(String name, URL[] urls) { + public ExtensionClassLoader(String name, URL[] urls, DiscoveredExtension discoveredExtension) { super("Ext_" + name, urls, MinecraftServer.class.getClassLoader()); + this.discoveredExtension = discoveredExtension; } - public ExtensionClassLoader(String name, URL[] urls, ClassLoader parent) { + public ExtensionClassLoader(String name, URL[] urls, ClassLoader parent, DiscoveredExtension discoveredExtension) { super("Ext_" + name, urls, parent); + this.discoveredExtension = discoveredExtension; } @Override @@ -55,4 +64,29 @@ public final class ExtensionClassLoader extends URLClassLoader { return null; } + + public DiscoveredExtension getDiscoveredExtension() { + return discoveredExtension; + } + + public EventNode getEventNode() { + if (eventNode == null) { + eventNode = EventNode.all(discoveredExtension.getName()); + MinecraftServer.getGlobalEventHandler().addChild(eventNode); + } + return eventNode; + } + + public Logger getLogger() { + if (logger == null) { + logger = LoggerFactory.getLogger(discoveredExtension.getName()); + } + return logger; + } + + void terminate() { + if (eventNode != null) { + MinecraftServer.getGlobalEventHandler().removeChild(eventNode); + } + } } diff --git a/src/main/java/net/minestom/server/extensions/ExtensionManager.java b/src/main/java/net/minestom/server/extensions/ExtensionManager.java index 7c92fd60a..dfb9be46b 100644 --- a/src/main/java/net/minestom/server/extensions/ExtensionManager.java +++ b/src/main/java/net/minestom/server/extensions/ExtensionManager.java @@ -5,8 +5,6 @@ import net.minestom.dependencies.DependencyGetter; import net.minestom.dependencies.ResolvedDependency; import net.minestom.dependencies.maven.MavenRepository; import net.minestom.server.ServerProcess; -import net.minestom.server.event.Event; -import net.minestom.server.event.EventNode; import net.minestom.server.utils.PropertyUtils; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.ApiStatus; @@ -17,7 +15,6 @@ import org.slf4j.LoggerFactory; import java.io.*; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.nio.file.Path; @@ -322,47 +319,6 @@ public class ExtensionManager { return null; } - // Set extension origin to its DiscoveredExtension - try { - Field originField = Extension.class.getDeclaredField("origin"); - originField.setAccessible(true); - originField.set(extension, discoveredExtension); - } catch (IllegalAccessException e) { - // We made it accessible, should not occur - } catch (NoSuchFieldException e) { - LOGGER.error("Main class '{}' in '{}' has no description field.", mainClass, extensionName, e); - return null; - } - - // Set logger - try { - Field loggerField = Extension.class.getDeclaredField("logger"); - loggerField.setAccessible(true); - loggerField.set(extension, LoggerFactory.getLogger(extensionClass)); - } catch (IllegalAccessException e) { - // We made it accessible, should not occur - serverProcess.exception().handleException(e); - } catch (NoSuchFieldException e) { - // This should also not occur (unless someone changed the logger in Extension superclass). - LOGGER.error("Main class '{}' in '{}' has no logger field.", mainClass, extensionName, e); - } - - // Set event node - try { - EventNode eventNode = EventNode.all(extensionName); // Use the extension name - Field loggerField = Extension.class.getDeclaredField("eventNode"); - loggerField.setAccessible(true); - loggerField.set(extension, eventNode); - - serverProcess.eventHandler().addChild(eventNode); - } catch (IllegalAccessException e) { - // We made it accessible, should not occur - serverProcess.exception().handleException(e); - } catch (NoSuchFieldException e) { - // This should also not occur - LOGGER.error("Main class '{}' in '{}' has no event node field.", mainClass, extensionName, e); - } - // add dependents to pre-existing extensions, so that they can easily be found during reloading for (String dependencyName : discoveredExtension.getDependencies()) { Extension dependency = extensions.get(dependencyName.toLowerCase()); @@ -716,7 +672,7 @@ public class ExtensionManager { for (String dependentID : dependents) { Extension dependentExt = extensions.get(dependentID.toLowerCase()); - if ( dependentExt != null ) { // check if extension isn't already unloaded. + if (dependentExt != null) { // check if extension isn't already unloaded. LOGGER.info("Unloading dependent extension {} (because it depends on {})", dependentID, extensionName); unload(dependentExt); } @@ -730,9 +686,7 @@ public class ExtensionManager { ext.preTerminate(); ext.terminate(); - // Remove event node - EventNode eventNode = ext.getEventNode(); - serverProcess.eventHandler().removeChild(eventNode); + ext.getExtensionClassLoader().terminate(); ext.postTerminate();