mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 15:30:19 +01:00
Allow using PluginLoader classpath API from Bukkit plugins (#10758)
Allows using the PluginLoader API without any of the other changes imposed by switching to a paper-plugin.yml. Used by setting paper-plugin-loader in plugin.yml to the class name of your PluginLoader. Also allows skipping the libraries field by setting paper-skip-libraries to true (by default both libraries and jars provided by the PluginLoader are added to the classpath).
This commit is contained in:
parent
2a90732677
commit
5e7b65a9a9
3 changed files with 233 additions and 8 deletions
|
@ -0,0 +1,91 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||||
|
Date: Tue, 21 May 2024 13:18:00 -0700
|
||||||
|
Subject: [PATCH] Allow Bukkit plugin to use Paper PluginLoader API
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
|
||||||
|
index c0691a849831f99268fdcb7b0f471f80a1a2a70e..8f45caade7357bc55c6a90cfe0c3a2feb2d877ff 100644
|
||||||
|
--- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
|
||||||
|
+++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java
|
||||||
|
@@ -259,6 +259,13 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
|
||||||
|
private Set<PluginAwareness> awareness = ImmutableSet.of();
|
||||||
|
private String apiVersion = null;
|
||||||
|
private List<String> libraries = ImmutableList.of();
|
||||||
|
+ // Paper start - plugin loader api
|
||||||
|
+ private String paperPluginLoader;
|
||||||
|
+ @org.jetbrains.annotations.ApiStatus.Internal @org.jetbrains.annotations.Nullable
|
||||||
|
+ public String getPaperPluginLoader() {
|
||||||
|
+ return this.paperPluginLoader;
|
||||||
|
+ }
|
||||||
|
+ // Paper end - plugin loader api
|
||||||
|
// Paper start - oh my goddddd
|
||||||
|
/**
|
||||||
|
* Don't use this.
|
||||||
|
@@ -1232,6 +1239,23 @@ public final class PluginDescriptionFile implements io.papermc.paper.plugin.conf
|
||||||
|
} else {
|
||||||
|
libraries = ImmutableList.<String>of();
|
||||||
|
}
|
||||||
|
+ // Paper start - plugin loader api
|
||||||
|
+ if (map.containsKey("paper-plugin-loader")) {
|
||||||
|
+ this.paperPluginLoader = map.get("paper-plugin-loader").toString();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ Allow skipping the Bukkit/Spigot 'libraries' list. By default, both the 'libraries'
|
||||||
|
+ list and the 'paper-plugin-loader' will contribute libraries. It may be desired to only
|
||||||
|
+ use one or the other. (i.e. 'libraries' on Spigot and 'paper-plugin-loader' on Paper)
|
||||||
|
+ */
|
||||||
|
+ if (map.containsKey("paper-skip-libraries")) {
|
||||||
|
+ String skip = map.get("paper-skip-libraries").toString();
|
||||||
|
+ if (skip.equalsIgnoreCase("true")) {
|
||||||
|
+ this.libraries = ImmutableList.of();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Paper end - plugin loader api
|
||||||
|
|
||||||
|
try {
|
||||||
|
lazyPermissions = (Map<?, ?>) map.get("permissions");
|
||||||
|
diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||||
|
index 8e1b6be2462aaa692efa1f72986921a6dc357196..c66252802c51174bc26f266cb5cdecdd856ff220 100644
|
||||||
|
--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||||
|
+++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java
|
||||||
|
@@ -84,7 +84,13 @@ public class LibraryLoader
|
||||||
|
@Nullable
|
||||||
|
public ClassLoader createLoader(@NotNull PluginDescriptionFile desc)
|
||||||
|
{
|
||||||
|
- if ( desc.getLibraries().isEmpty() )
|
||||||
|
+ // Paper start - plugin loader api
|
||||||
|
+ return this.createLoader(desc, null);
|
||||||
|
+ }
|
||||||
|
+ @Nullable
|
||||||
|
+ public ClassLoader createLoader(@NotNull PluginDescriptionFile desc, java.util.@Nullable List<java.nio.file.Path> paperLibraryPaths) {
|
||||||
|
+ if ( desc.getLibraries().isEmpty() && paperLibraryPaths == null )
|
||||||
|
+ // Paper end - plugin loader api
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@@ -103,17 +109,20 @@ public class LibraryLoader
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyResult result;
|
||||||
|
- try
|
||||||
|
+ if (!dependencies.isEmpty()) try // Paper - plugin loader api
|
||||||
|
{
|
||||||
|
result = repository.resolveDependencies( session, new DependencyRequest( new CollectRequest( (Dependency) null, dependencies, repositories ), null ) );
|
||||||
|
} catch ( DependencyResolutionException ex )
|
||||||
|
{
|
||||||
|
throw new RuntimeException( "Error resolving libraries", ex );
|
||||||
|
- }
|
||||||
|
+ } else result = null; // Paper - plugin loader api
|
||||||
|
|
||||||
|
List<URL> jarFiles = new ArrayList<>();
|
||||||
|
List<java.nio.file.Path> jarPaths = new ArrayList<>(); // Paper - remap libraries
|
||||||
|
- for ( ArtifactResult artifact : result.getArtifactResults() )
|
||||||
|
+ // Paper start - plugin loader api
|
||||||
|
+ if (paperLibraryPaths != null) jarPaths.addAll(paperLibraryPaths);
|
||||||
|
+ if (result != null) for ( ArtifactResult artifact : result.getArtifactResults() )
|
||||||
|
+ // Paper end - plugin loader api
|
||||||
|
{
|
||||||
|
// Paper start - remap libraries
|
||||||
|
jarPaths.add(artifact.getArtifact().getFile().toPath());
|
|
@ -877,10 +877,10 @@ index 0000000000000000000000000000000000000000..f9a2c55a354c877749db3f92956de802
|
||||||
+}
|
+}
|
||||||
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
|
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..5a00e5c41274ded6b837fb81fa8f54616f2b7bc8
|
index 0000000000000000000000000000000000000000..18401ede9cd1fc7094c6b74859929938e01795ca
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
|
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java
|
||||||
@@ -0,0 +1,205 @@
|
@@ -0,0 +1,209 @@
|
||||||
+package io.papermc.paper.plugin.entrypoint.classloader;
|
+package io.papermc.paper.plugin.entrypoint.classloader;
|
||||||
+
|
+
|
||||||
+import io.papermc.paper.plugin.configuration.PluginMeta;
|
+import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||||
|
@ -936,13 +936,17 @@ index 0000000000000000000000000000000000000000..5a00e5c41274ded6b837fb81fa8f5461
|
||||||
+ this.libraryLoader = libraryLoader;
|
+ this.libraryLoader = libraryLoader;
|
||||||
+
|
+
|
||||||
+ this.logger = logger;
|
+ this.logger = logger;
|
||||||
+ if (this.configuration.hasOpenClassloader()) {
|
+ if (this.configuration().hasOpenClassloader()) {
|
||||||
+ this.group = PaperClassLoaderStorage.instance().registerOpenGroup(this);
|
+ this.group = PaperClassLoaderStorage.instance().registerOpenGroup(this);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ private PaperPluginMeta configuration() {
|
||||||
|
+ return (PaperPluginMeta) this.configuration;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ public void refreshClassloaderDependencyTree(DependencyContext dependencyContext) {
|
+ public void refreshClassloaderDependencyTree(DependencyContext dependencyContext) {
|
||||||
+ if (this.configuration.hasOpenClassloader()) {
|
+ if (this.configuration().hasOpenClassloader()) {
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+ if (this.group != null) {
|
+ if (this.group != null) {
|
||||||
|
@ -1088,13 +1092,13 @@ index 0000000000000000000000000000000000000000..5a00e5c41274ded6b837fb81fa8f5461
|
||||||
+}
|
+}
|
||||||
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java
|
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..a4c18063854e050bd0c54d488ceeda43c768b6df
|
index 0000000000000000000000000000000000000000..967465e542483e93a736129b5f5c6622cefd33fa
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java
|
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java
|
||||||
@@ -0,0 +1,116 @@
|
@@ -0,0 +1,116 @@
|
||||||
+package io.papermc.paper.plugin.entrypoint.classloader;
|
+package io.papermc.paper.plugin.entrypoint.classloader;
|
||||||
+
|
+
|
||||||
+import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta;
|
+import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||||
+import io.papermc.paper.plugin.util.NamespaceChecker;
|
+import io.papermc.paper.plugin.util.NamespaceChecker;
|
||||||
+import org.jetbrains.annotations.ApiStatus;
|
+import org.jetbrains.annotations.ApiStatus;
|
||||||
+
|
+
|
||||||
|
@ -1120,13 +1124,13 @@ index 0000000000000000000000000000000000000000..a4c18063854e050bd0c54d488ceeda43
|
||||||
+ ClassLoader.registerAsParallelCapable();
|
+ ClassLoader.registerAsParallelCapable();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ protected final PaperPluginMeta configuration;
|
+ protected final PluginMeta configuration;
|
||||||
+ protected final Path source;
|
+ protected final Path source;
|
||||||
+ protected final Manifest jarManifest;
|
+ protected final Manifest jarManifest;
|
||||||
+ protected final URL jarUrl;
|
+ protected final URL jarUrl;
|
||||||
+ protected final JarFile jar;
|
+ protected final JarFile jar;
|
||||||
+
|
+
|
||||||
+ public PaperSimplePluginClassLoader(Path source, JarFile file, PaperPluginMeta configuration, ClassLoader parentLoader) throws IOException {
|
+ public PaperSimplePluginClassLoader(Path source, JarFile file, PluginMeta configuration, ClassLoader parentLoader) throws IOException {
|
||||||
+ super(source.getFileName().toString(), new URL[]{source.toUri().toURL()}, parentLoader);
|
+ super(source.getFileName().toString(), new URL[]{source.toUri().toURL()}, parentLoader);
|
||||||
+
|
+
|
||||||
+ this.source = source;
|
+ this.source = source;
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||||
|
Date: Tue, 21 May 2024 13:18:15 -0700
|
||||||
|
Subject: [PATCH] Allow Bukkit plugin to use Paper PluginLoader API
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||||
|
index f9d4b33050a6fe8c2dabe8e5eec075d95dc513e0..dc106685ecb483c33c06e4f83eda27be58251aad 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||||
|
@@ -41,15 +41,7 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaperPluginClassLoader buildClassLoader(Logger logger, Path source, JarFile jarFile, PaperPluginMeta configuration) {
|
||||||
|
- PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
|
||||||
|
- for (ClassPathLibrary library : this.libraries) {
|
||||||
|
- library.register(paperLibraryStore);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- List<Path> paths = paperLibraryStore.getPaths();
|
||||||
|
- if (PluginInitializerManager.instance().pluginRemapper != null) {
|
||||||
|
- paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
|
||||||
|
- }
|
||||||
|
+ List<Path> paths = this.buildLibraryPaths(true);
|
||||||
|
URL[] urls = new URL[paths.size()];
|
||||||
|
for (int i = 0; i < paths.size(); i++) {
|
||||||
|
Path path = paths.get(i);
|
||||||
|
@@ -69,4 +61,17 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public List<Path> buildLibraryPaths(final boolean remap) {
|
||||||
|
+ PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
|
||||||
|
+ for (ClassPathLibrary library : this.libraries) {
|
||||||
|
+ library.register(paperLibraryStore);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ List<Path> paths = paperLibraryStore.getPaths();
|
||||||
|
+ if (remap && PluginInitializerManager.instance().pluginRemapper != null) {
|
||||||
|
+ paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
|
||||||
|
+ }
|
||||||
|
+ return paths;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||||
|
index 75a2b687d58d76b94f8bec111df8613f120ff74b..0fd1040ed376f19c6d5326767baaf3048ce1bfb4 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||||
|
@@ -40,15 +40,17 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
|
||||||
|
private final PluginDescriptionFile description;
|
||||||
|
private final JarFile jarFile;
|
||||||
|
private final Logger logger;
|
||||||
|
+ private final List<Path> paperLibraryPaths;
|
||||||
|
private final ComponentLogger componentLogger;
|
||||||
|
private ProviderStatus status;
|
||||||
|
private DependencyContext dependencyContext;
|
||||||
|
|
||||||
|
- SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description) {
|
||||||
|
+ SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description, List<Path> paperLibraryPaths) {
|
||||||
|
this.path = path;
|
||||||
|
this.jarFile = file;
|
||||||
|
this.description = description;
|
||||||
|
this.logger = PaperPluginLogger.getLogger(description);
|
||||||
|
+ this.paperLibraryPaths = paperLibraryPaths;
|
||||||
|
this.componentLogger = ComponentLogger.logger(this.logger.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -120,7 +122,7 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
|
||||||
|
|
||||||
|
final PluginClassLoader loader;
|
||||||
|
try {
|
||||||
|
- loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.jarFile, this.dependencyContext); // Paper
|
||||||
|
+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description, this.paperLibraryPaths), this.jarFile, this.dependencyContext); // Paper
|
||||||
|
} catch (InvalidPluginException ex) {
|
||||||
|
throw ex;
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||||
|
index fdb52ad85cfaa1d53aadcad72cec3d3c8c12c058..38075b7348ad7ca3cfece2bfae63e0cce827c694 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||||
|
@@ -1,9 +1,18 @@
|
||||||
|
package io.papermc.paper.plugin.provider.type.spigot;
|
||||||
|
|
||||||
|
+import com.destroystokyo.paper.utils.PaperPluginLogger;
|
||||||
|
+import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl;
|
||||||
|
import io.papermc.paper.plugin.entrypoint.classloader.BytecodeModifyingURLClassLoader;
|
||||||
|
+import io.papermc.paper.plugin.entrypoint.classloader.PaperSimplePluginClassLoader;
|
||||||
|
+import io.papermc.paper.plugin.loader.PaperClasspathBuilder;
|
||||||
|
+import io.papermc.paper.plugin.loader.PluginLoader;
|
||||||
|
import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints;
|
||||||
|
import io.papermc.paper.plugin.provider.type.PluginTypeFactory;
|
||||||
|
+import io.papermc.paper.plugin.provider.util.ProviderUtil;
|
||||||
|
import io.papermc.paper.util.MappingEnvironment;
|
||||||
|
+import java.util.List;
|
||||||
|
+import java.util.logging.Logger;
|
||||||
|
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||||
|
import org.bukkit.plugin.InvalidDescriptionException;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
import org.bukkit.plugin.java.LibraryLoader;
|
||||||
|
@@ -36,7 +45,28 @@ class SpigotPluginProviderFactory implements PluginTypeFactory<SpigotPluginProvi
|
||||||
|
throw new InvalidDescriptionException("Restricted name, cannot use 0x20 (space character) in a plugin name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
- return new SpigotPluginProvider(source, file, configuration);
|
||||||
|
+ final List<Path> paperLibraryPaths;
|
||||||
|
+ if (configuration.getPaperPluginLoader() != null) {
|
||||||
|
+ final Logger logger = PaperPluginLogger.getLogger(configuration);
|
||||||
|
+ PaperClasspathBuilder builder = new PaperClasspathBuilder(PluginProviderContextImpl.create(
|
||||||
|
+ configuration, ComponentLogger.logger(logger.getName()), source
|
||||||
|
+ ));
|
||||||
|
+
|
||||||
|
+ try (
|
||||||
|
+ PaperSimplePluginClassLoader simplePluginClassLoader = new PaperSimplePluginClassLoader(source, file, configuration, this.getClass().getClassLoader())
|
||||||
|
+ ) {
|
||||||
|
+ PluginLoader loader = ProviderUtil.loadClass(configuration.getPaperPluginLoader(), PluginLoader.class, simplePluginClassLoader);
|
||||||
|
+ loader.classloader(builder);
|
||||||
|
+ } catch (IOException e) {
|
||||||
|
+ throw new RuntimeException(e);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ paperLibraryPaths = builder.buildLibraryPaths(false);
|
||||||
|
+ } else {
|
||||||
|
+ paperLibraryPaths = null;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return new SpigotPluginProvider(source, file, configuration, paperLibraryPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
Loading…
Reference in a new issue