mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Revert Spigot PluginClassLoader workaround
This commit is contained in:
parent
9bb1ba12b2
commit
717347273d
@ -31,7 +31,6 @@ import me.lucko.luckperms.api.Contexts;
|
|||||||
import me.lucko.luckperms.api.LuckPermsApi;
|
import me.lucko.luckperms.api.LuckPermsApi;
|
||||||
import me.lucko.luckperms.api.platform.PlatformType;
|
import me.lucko.luckperms.api.platform.PlatformType;
|
||||||
import me.lucko.luckperms.bukkit.calculators.BukkitCalculatorFactory;
|
import me.lucko.luckperms.bukkit.calculators.BukkitCalculatorFactory;
|
||||||
import me.lucko.luckperms.bukkit.classloader.LPClassLoader;
|
|
||||||
import me.lucko.luckperms.bukkit.contexts.BukkitContextManager;
|
import me.lucko.luckperms.bukkit.contexts.BukkitContextManager;
|
||||||
import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
|
import me.lucko.luckperms.bukkit.contexts.WorldCalculator;
|
||||||
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
||||||
@ -96,7 +95,6 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -131,7 +129,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
private DefaultsProvider defaultsProvider;
|
private DefaultsProvider defaultsProvider;
|
||||||
private ChildPermissionProvider childPermissionProvider;
|
private ChildPermissionProvider childPermissionProvider;
|
||||||
private LocaleManager localeManager;
|
private LocaleManager localeManager;
|
||||||
private LPClassLoader lpClassLoader;
|
|
||||||
private DependencyManager dependencyManager;
|
private DependencyManager dependencyManager;
|
||||||
private CachedStateManager cachedStateManager;
|
private CachedStateManager cachedStateManager;
|
||||||
private ContextManager<Player> contextManager;
|
private ContextManager<Player> contextManager;
|
||||||
@ -156,7 +153,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
senderFactory = new BukkitSenderFactory(this);
|
senderFactory = new BukkitSenderFactory(this);
|
||||||
log = new SenderLogger(this, getConsoleSender());
|
log = new SenderLogger(this, getConsoleSender());
|
||||||
|
|
||||||
lpClassLoader = LPClassLoader.obtainFor(this);
|
|
||||||
dependencyManager = new DependencyManager(this);
|
dependencyManager = new DependencyManager(this);
|
||||||
dependencyManager.loadDependencies(Collections.singleton(Dependency.CAFFEINE));
|
dependencyManager.loadDependencies(Collections.singleton(Dependency.CAFFEINE));
|
||||||
}
|
}
|
||||||
@ -393,11 +389,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
|||||||
getLog().info("Goodbye!");
|
getLog().info("Goodbye!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadUrlIntoClasspath(URL url) {
|
|
||||||
lpClassLoader.addURL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tryVaultHook(boolean force) {
|
public void tryVaultHook(boolean force) {
|
||||||
if (vaultHookManager != null) {
|
if (vaultHookManager != null) {
|
||||||
return; // already hooked
|
return; // already hooked
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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.bukkit.classloader;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.common.dependencies.DependencyManager;
|
|
||||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A dummy implementation of {@link LPClassLoader} which just falls back to the
|
|
||||||
* reflection method used by other platforms.
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class FallbackClassLoader implements LPClassLoader {
|
|
||||||
private final LuckPermsPlugin plugin;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addURL(URL url) {
|
|
||||||
DependencyManager.loadUrlIntoClassLoader(url, plugin.getClass().getClassLoader());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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.bukkit.classloader;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.experimental.Delegate;
|
|
||||||
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A fake classloader instance which sits in-front of a PluginClassLoader, and
|
|
||||||
* attempts to load classes from it's own sources before allowing the PCL to load
|
|
||||||
* the class.
|
|
||||||
*
|
|
||||||
* This allows us to inject extra URL sources into the plugin's classloader at
|
|
||||||
* runtime.
|
|
||||||
*/
|
|
||||||
public class InjectedClassLoader extends URLClassLoader implements LPClassLoader {
|
|
||||||
|
|
||||||
public static InjectedClassLoader inject(JavaPlugin plugin) throws Exception {
|
|
||||||
// get the plugin's PluginClassLoader instance
|
|
||||||
ClassLoader classLoader = plugin.getClass().getClassLoader();
|
|
||||||
|
|
||||||
// get a ref to the PCL class
|
|
||||||
Class<?> pclClass = Class.forName("org.bukkit.plugin.java.PluginClassLoader");
|
|
||||||
|
|
||||||
// extract the 'classes' cache map
|
|
||||||
Field classesField = pclClass.getDeclaredField("classes");
|
|
||||||
classesField.setAccessible(true);
|
|
||||||
|
|
||||||
// obtain the classes instance from the classloader
|
|
||||||
//noinspection unchecked
|
|
||||||
Map<String, Class<?>> old = (Map) classesField.get(classLoader);
|
|
||||||
|
|
||||||
// init a new InjectedClassLoader to read from
|
|
||||||
InjectedClassLoader newLoader = new InjectedClassLoader();
|
|
||||||
|
|
||||||
// replace the 'classes' cache map with our own.
|
|
||||||
classesField.set(classLoader, new DelegatingClassMap(newLoader, old));
|
|
||||||
|
|
||||||
return newLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
Method method = ClassLoader.class.getDeclaredMethod("registerAsParallelCapable");
|
|
||||||
if (method != null) {
|
|
||||||
method.setAccessible(true);
|
|
||||||
method.invoke(null);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<String, Class<?>> cache = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private InjectedClassLoader() {
|
|
||||||
super(new URL[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addURL(URL url) {
|
|
||||||
super.addURL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Class<?> lookup(String name) {
|
|
||||||
// try the cache
|
|
||||||
Class<?> clazz = cache.get(name);
|
|
||||||
if (clazz != null) {
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// attempt to load
|
|
||||||
clazz = loadClass(name);
|
|
||||||
|
|
||||||
// if successful, add to the cache file
|
|
||||||
cache.put(name, clazz);
|
|
||||||
return clazz;
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A fake map instance which effectively allows us to override the behaviour
|
|
||||||
* of #findClass in PluginClassLoader.
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
private static final class DelegatingClassMap implements Map<String, Class<?>> {
|
|
||||||
private final InjectedClassLoader loader;
|
|
||||||
|
|
||||||
// delegate all other calls to the original map
|
|
||||||
@Delegate(excludes = Exclude.class)
|
|
||||||
private final Map<String, Class<?>> delegate;
|
|
||||||
|
|
||||||
// override the #get call, so we can attempt to load the class ourselves.
|
|
||||||
@Override
|
|
||||||
public Class<?> get(Object key) {
|
|
||||||
String className = ((String) key);
|
|
||||||
|
|
||||||
Class<?> clazz = loader.lookup(className);
|
|
||||||
if (clazz != null) {
|
|
||||||
return clazz;
|
|
||||||
} else {
|
|
||||||
return delegate.get(className);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface Exclude {
|
|
||||||
Class<?> get(Object key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of LuckPerms, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
|
||||||
* 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.bukkit.classloader;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface over a {@link org.bukkit.plugin.java.JavaPlugin}'s PluginClassLoader.
|
|
||||||
*/
|
|
||||||
public interface LPClassLoader {
|
|
||||||
|
|
||||||
static LPClassLoader obtainFor(LPBukkitPlugin plugin) {
|
|
||||||
try {
|
|
||||||
// try to inject into the classloader
|
|
||||||
return InjectedClassLoader.inject(plugin);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// fallback to a reflection based method
|
|
||||||
return new FallbackClassLoader(plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a URL to the classloader
|
|
||||||
*
|
|
||||||
* @param url the url to add
|
|
||||||
*/
|
|
||||||
void addURL(URL url);
|
|
||||||
|
|
||||||
}
|
|
@ -103,10 +103,14 @@ public class DependencyManager {
|
|||||||
dependencies.add(Dependency.JEDIS);
|
dependencies.add(Dependency.JEDIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't load slf4j or configurate dependencies on sponge, as they're already present
|
// don't load slf4j if it's already present
|
||||||
if (plugin.getServerType() == PlatformType.SPONGE) {
|
if (classExists("org.slf4j.Logger") && classExists("org.slf4j.LoggerFactory")) {
|
||||||
dependencies.remove(Dependency.SLF4J_API);
|
dependencies.remove(Dependency.SLF4J_API);
|
||||||
dependencies.remove(Dependency.SLF4J_SIMPLE);
|
dependencies.remove(Dependency.SLF4J_SIMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't load configurate dependencies on sponge
|
||||||
|
if (plugin.getServerType() == PlatformType.SPONGE) {
|
||||||
dependencies.remove(Dependency.CONFIGURATE_CORE);
|
dependencies.remove(Dependency.CONFIGURATE_CORE);
|
||||||
dependencies.remove(Dependency.CONFIGURATE_GSON);
|
dependencies.remove(Dependency.CONFIGURATE_GSON);
|
||||||
dependencies.remove(Dependency.CONFIGURATE_YAML);
|
dependencies.remove(Dependency.CONFIGURATE_YAML);
|
||||||
@ -184,18 +188,12 @@ public class DependencyManager {
|
|||||||
|
|
||||||
private void loadJar(File file) {
|
private void loadJar(File file) {
|
||||||
// get the classloader to load into
|
// get the classloader to load into
|
||||||
try {
|
ClassLoader classLoader = plugin.getClass().getClassLoader();
|
||||||
plugin.loadUrlIntoClasspath(file.toURI().toURL());
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadUrlIntoClassLoader(URL url, ClassLoader classLoader) {
|
|
||||||
if (classLoader instanceof URLClassLoader) {
|
if (classLoader instanceof URLClassLoader) {
|
||||||
try {
|
try {
|
||||||
ADD_URL_METHOD.invoke(classLoader, url);
|
ADD_URL_METHOD.invoke(classLoader, file.toURI().toURL());
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
|
||||||
throw new RuntimeException("Unable to invoke URLClassLoader#addURL", e);
|
throw new RuntimeException("Unable to invoke URLClassLoader#addURL", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -203,4 +201,13 @@ public class DependencyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean classExists(String className) {
|
||||||
|
try {
|
||||||
|
Class.forName(className);
|
||||||
|
return true;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,6 @@ import me.lucko.luckperms.common.verbose.VerboseHandler;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -155,15 +154,6 @@ public interface LuckPermsPlugin {
|
|||||||
*/
|
*/
|
||||||
DependencyManager getDependencyManager();
|
DependencyManager getDependencyManager();
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a dependency into the plugins classpath
|
|
||||||
*
|
|
||||||
* @param url the url to load
|
|
||||||
*/
|
|
||||||
default void loadUrlIntoClasspath(URL url) {
|
|
||||||
DependencyManager.loadUrlIntoClassLoader(url, getClass().getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the context manager.
|
* Gets the context manager.
|
||||||
* This object handles context accumulation for all players on the platform.
|
* This object handles context accumulation for all players on the platform.
|
||||||
|
Loading…
Reference in New Issue
Block a user