From b2352346338ccaee052d317d73557f1dce10a2c3 Mon Sep 17 00:00:00 2001 From: lucko Date: Thu, 17 Feb 2022 00:22:46 +0000 Subject: [PATCH] Sponge use jar-in-jar loader --- settings.gradle | 5 +- sponge/build.gradle | 4 +- sponge/loader/build.gradle | 32 ++++++++ .../sponge/loader/SpongeLoaderPlugin.java | 75 +++++++++++++++++++ .../resources/META-INF/sponge_plugins.json | 2 +- .../luckperms/sponge/LPSpongeBootstrap.java | 51 ++++++++----- .../sponge/SpongeClassPathAppender.java | 64 ---------------- 7 files changed, 145 insertions(+), 88 deletions(-) create mode 100644 sponge/loader/build.gradle create mode 100644 sponge/loader/src/main/java/me/lucko/luckperms/sponge/loader/SpongeLoaderPlugin.java rename sponge/{ => loader}/src/main/resources/META-INF/sponge_plugins.json (88%) delete mode 100644 sponge/src/main/java/me/lucko/luckperms/sponge/SpongeClassPathAppender.java diff --git a/settings.gradle b/settings.gradle index db3bdea62..17a0c9c99 100644 --- a/settings.gradle +++ b/settings.gradle @@ -23,6 +23,9 @@ include ( 'fabric', 'nukkit', 'nukkit:loader', - 'sponge', 'sponge:sponge-service', 'sponge:sponge-service-api8', + 'sponge', + 'sponge:loader', + 'sponge:sponge-service', + 'sponge:sponge-service-api8', 'velocity' ) diff --git a/sponge/build.gradle b/sponge/build.gradle index 275da4a33..5a26cb16d 100644 --- a/sponge/build.gradle +++ b/sponge/build.gradle @@ -10,6 +10,7 @@ dependencies { implementation project(':common') implementation project(':sponge:sponge-service') implementation project(':sponge:sponge-service-api8') + compileOnly project(':common:loader-utils') compileOnly('org.spongepowered:spongeapi:8.0.0') { exclude(module: 'configurate-core') @@ -26,10 +27,9 @@ processResources { } shadowJar { - archiveFileName = "LuckPerms-Sponge-${project.ext.fullVersion}.jar" + archiveFileName = 'luckperms-sponge.jarinjar' dependencies { - include(dependency('net.luckperms:.*')) include(dependency('me.lucko.luckperms:.*')) } diff --git a/sponge/loader/build.gradle b/sponge/loader/build.gradle new file mode 100644 index 000000000..b7a89d919 --- /dev/null +++ b/sponge/loader/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +repositories { + maven { url 'https://repo.spongepowered.org/repository/maven-public/' } +} + +dependencies { + compileOnly 'org.spongepowered:spongeapi:8.0.0' + + implementation project(':api') + implementation project(':common:loader-utils') +} + +processResources { + filesMatching('META-INF/sponge_plugins.json') { + expand 'pluginVersion': project.ext.fullVersion + } +} + +shadowJar { + archiveFileName = "LuckPerms-Sponge-${project.ext.fullVersion}.jar" + + from { + project(':sponge').tasks.shadowJar.archiveFile + } +} + +artifacts { + archives shadowJar +} \ No newline at end of file diff --git a/sponge/loader/src/main/java/me/lucko/luckperms/sponge/loader/SpongeLoaderPlugin.java b/sponge/loader/src/main/java/me/lucko/luckperms/sponge/loader/SpongeLoaderPlugin.java new file mode 100644 index 000000000..90710d013 --- /dev/null +++ b/sponge/loader/src/main/java/me/lucko/luckperms/sponge/loader/SpongeLoaderPlugin.java @@ -0,0 +1,75 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * 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. + */ + +package me.lucko.luckperms.sponge.loader; + +import com.google.inject.Inject; +import com.google.inject.Injector; + +import me.lucko.luckperms.common.loader.JarInJarClassLoader; +import me.lucko.luckperms.common.loader.LoaderBootstrap; + +import org.spongepowered.api.Server; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.Order; +import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; +import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; +import org.spongepowered.plugin.builtin.jvm.Plugin; + +import java.util.function.Supplier; + +@Plugin("luckperms") +public class SpongeLoaderPlugin implements Supplier { + private static final String JAR_NAME = "luckperms-sponge.jarinjar"; + private static final String BOOTSTRAP_CLASS = "me.lucko.luckperms.sponge.LPSpongeBootstrap"; + + private final LoaderBootstrap plugin; + private final Injector injector; + + @Inject + public SpongeLoaderPlugin(Injector injector) { + this.injector = injector; + + JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME); + this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, Supplier.class, this); + } + + @Override + public Injector get() { + return this.injector; + } + + @Listener(order = Order.FIRST) + public void onEnable(ConstructPluginEvent event) { + this.plugin.onLoad(); + this.plugin.onEnable(); + } + + @Listener + public void onDisable(StoppingEngineEvent event) { + this.plugin.onDisable(); + } + +} diff --git a/sponge/src/main/resources/META-INF/sponge_plugins.json b/sponge/loader/src/main/resources/META-INF/sponge_plugins.json similarity index 88% rename from sponge/src/main/resources/META-INF/sponge_plugins.json rename to sponge/loader/src/main/resources/META-INF/sponge_plugins.json index 324073eb2..50dc3de4d 100644 --- a/sponge/src/main/resources/META-INF/sponge_plugins.json +++ b/sponge/loader/src/main/resources/META-INF/sponge_plugins.json @@ -9,7 +9,7 @@ "id": "luckperms", "name": "LuckPerms", "version": "${pluginVersion}", - "entrypoint": "me.lucko.luckperms.sponge.LPSpongeBootstrap", + "entrypoint": "me.lucko.luckperms.sponge.loader.SpongeLoaderPlugin", "description": "A permissions plugin", "links": { "homepage": "https://luckperms.net" diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java index d74cd065d..3b91e497d 100644 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java +++ b/sponge/src/main/java/me/lucko/luckperms/sponge/LPSpongeBootstrap.java @@ -26,9 +26,13 @@ package me.lucko.luckperms.sponge; import com.google.inject.Inject; +import com.google.inject.Injector; +import me.lucko.luckperms.common.loader.LoaderBootstrap; +import me.lucko.luckperms.common.plugin.bootstrap.BootstrappedWithLoader; import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap; import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender; +import me.lucko.luckperms.common.plugin.classpath.JarInJarClassPathAppender; import me.lucko.luckperms.common.plugin.logging.Log4jPluginLogger; import me.lucko.luckperms.common.plugin.logging.PluginLogger; import me.lucko.luckperms.common.util.MoreFiles; @@ -42,13 +46,8 @@ import org.spongepowered.api.Server; import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.server.ServerPlayer; -import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.Order; -import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; -import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; import org.spongepowered.api.profile.GameProfile; import org.spongepowered.plugin.PluginContainer; -import org.spongepowered.plugin.builtin.jvm.Plugin; import org.spongepowered.plugin.metadata.PluginMetadata; import java.io.IOException; @@ -62,12 +61,13 @@ import java.util.List; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CountDownLatch; +import java.util.function.Supplier; /** * Bootstrap plugin for LuckPerms running on Sponge. */ -@Plugin("luckperms") -public class LPSpongeBootstrap implements LuckPermsBootstrap { +public class LPSpongeBootstrap implements LuckPermsBootstrap, LoaderBootstrap, BootstrappedWithLoader { + private final Object loader; /** * The plugin logger @@ -111,22 +111,31 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap { /** * Injected configuration directory for the plugin */ - private final Path configDirectory; - @Inject - public LPSpongeBootstrap(Logger logger, Game game, PluginContainer pluginContainer, @ConfigDir(sharedRoot = false) Path configDirectory) { - this.logger = new Log4jPluginLogger(logger); - this.game = game; - this.pluginContainer = pluginContainer; - this.configDirectory = configDirectory; + @ConfigDir(sharedRoot = false) + private Path configDirectory; + + public LPSpongeBootstrap(Supplier loader) { + this.loader = loader; + + Injector injector = loader.get(); + this.logger = new Log4jPluginLogger(injector.getInstance(Logger.class)); + this.game = injector.getInstance(Game.class); + this.pluginContainer = injector.getInstance(PluginContainer.class); + injector.injectMembers(this); this.schedulerAdapter = new SpongeSchedulerAdapter(this.game, this.pluginContainer); - this.classPathAppender = new SpongeClassPathAppender(this); + this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader()); this.plugin = new LPSpongePlugin(this); } // provide adapters + @Override + public Object getLoader() { + return this.loader; + } + @Override public PluginLogger getPluginLogger() { return this.logger; @@ -143,15 +152,18 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap { } // lifecycle - @Listener(order = Order.FIRST) - public void onEnable(ConstructPluginEvent event) { - this.startTime = Instant.now(); + + @Override + public void onLoad() { try { this.plugin.load(); } finally { this.loadLatch.countDown(); } + } + public void onEnable() { + this.startTime = Instant.now(); try { this.plugin.enable(); } finally { @@ -159,8 +171,7 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap { } } - @Listener - public void onDisable(StoppingEngineEvent event) { + public void onDisable() { this.plugin.disable(); } diff --git a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeClassPathAppender.java b/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeClassPathAppender.java deleted file mode 100644 index efd521c50..000000000 --- a/sponge/src/main/java/me/lucko/luckperms/sponge/SpongeClassPathAppender.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of LuckPerms, licensed under the MIT License. - * - * Copyright (c) lucko (Luck) - * Copyright (c) contributors - * - * 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. - */ - -package me.lucko.luckperms.sponge; - -import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap; -import me.lucko.luckperms.common.plugin.classpath.ReflectionClassPathAppender; - -import java.lang.reflect.Field; -import java.net.URLClassLoader; - -public class SpongeClassPathAppender extends ReflectionClassPathAppender { - - private static URLClassLoader extractClassLoaderFromBootstrap(LuckPermsBootstrap bootstrap) { - ClassLoader classLoader = bootstrap.getClass().getClassLoader(); - - // try to cast directly to URLClassLoader in case things change in the future - if (classLoader instanceof URLClassLoader) { - return (URLClassLoader) classLoader; - } - - Class classLoaderClass = classLoader.getClass(); - - if (!classLoaderClass.getName().equals("cpw.mods.modlauncher.TransformingClassLoader")) { - throw new IllegalStateException("ClassLoader is not instance of TransformingClassLoader: " + classLoaderClass.getName()); - } - - try { - Field delegatedClassLoaderField = classLoaderClass.getDeclaredField("delegatedClassLoader"); - delegatedClassLoaderField.setAccessible(true); - Object delegatedClassLoader = delegatedClassLoaderField.get(classLoader); - return (URLClassLoader) delegatedClassLoader; - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - public SpongeClassPathAppender(LuckPermsBootstrap bootstrap) throws IllegalStateException { - super(extractClassLoaderFromBootstrap(bootstrap)); - } - -}