mirror of
https://github.com/Xiao-MoMi/Custom-Nameplates.git
synced 2025-12-19 15:09:23 +00:00
remap libs
This commit is contained in:
@@ -7,7 +7,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
|
||||
version = "2.3.2.2"
|
||||
version = "2.3.3.0"
|
||||
|
||||
apply<JavaPlugin>()
|
||||
apply(plugin = "java")
|
||||
|
||||
@@ -12,7 +12,10 @@ dependencies {
|
||||
compileOnly("me.clip:placeholderapi:2.11.5")
|
||||
|
||||
// config
|
||||
compileOnly("dev.dejvokep:boosted-yaml:1.3.1")
|
||||
compileOnly("dev.dejvokep:boosted-yaml:1.3.2")
|
||||
|
||||
// bStats
|
||||
compileOnly("org.bstats:bstats-bukkit:3.0.2")
|
||||
|
||||
// team
|
||||
compileOnly("me.neznamy:tab-api:4.0.2")
|
||||
@@ -48,11 +51,6 @@ dependencies {
|
||||
// adventure
|
||||
implementation("net.kyori:adventure-api:4.15.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.3.2")
|
||||
implementation("net.kyori:adventure-text-minimessage:4.15.0")
|
||||
implementation("net.kyori:adventure-text-serializer-legacy:4.15.0")
|
||||
|
||||
// bStats
|
||||
implementation("org.bstats:bstats-bukkit:3.0.2")
|
||||
|
||||
// local lib
|
||||
implementation(files("libs/BiomeAPI.jar"))
|
||||
@@ -63,5 +61,14 @@ tasks {
|
||||
relocate ("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
relocate ("org.bstats", "net.momirealms.customnameplates.libraries.bstats")
|
||||
relocate ("net.momirealms.biomeapi", "net.momirealms.customnameplates.libraries.biomeapi")
|
||||
relocate ("org.apache.commons.pool2", "net.momirealms.customnameplates.libraries.commonspool2")
|
||||
relocate ("com.mysql", "net.momirealms.customnameplates.libraries.mysql")
|
||||
relocate ("org.mariadb", "net.momirealms.customnameplates.libraries.mariadb")
|
||||
relocate ("com.zaxxer.hikari", "net.momirealms.customnameplates.libraries.hikari")
|
||||
relocate ("redis.clients.jedis", "net.momirealms.customnameplates.libraries.jedis")
|
||||
relocate ("com.mongodb", "net.momirealms.customnameplates.libraries.mongodb")
|
||||
relocate ("org.bson", "net.momirealms.customnameplates.libraries.bson")
|
||||
relocate ("dev.jorel.commandapi", "net.momirealms.customnameplates.libraries.commandapi")
|
||||
relocate ("dev.dejvokep.boostedyaml", "net.momirealms.customnameplates.libraries.boostedyaml")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,10 @@ import net.momirealms.customnameplates.api.event.CustomNameplatesReloadEvent;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.adventure.AdventureManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.command.CommandManager;
|
||||
import net.momirealms.customnameplates.paper.helper.LibraryLoader;
|
||||
import net.momirealms.customnameplates.paper.libraries.classpath.ReflectionClassPathAppender;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.Dependency;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManager;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.actionbar.ActionBarManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.background.BackGroundManagerImpl;
|
||||
import net.momirealms.customnameplates.paper.mechanic.bossbar.BossBarManagerImpl;
|
||||
@@ -50,16 +53,41 @@ import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.TimeZone;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implements Listener {
|
||||
|
||||
private CoolDownManager coolDownManager;
|
||||
private PacketManager packetManager;
|
||||
private DependencyManager dependencyManager;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.loadLibraries();
|
||||
this.dependencyManager = new DependencyManagerImpl(this, new ReflectionClassPathAppender(this.getClassLoader()));
|
||||
this.dependencyManager.loadDependencies(new ArrayList<>(
|
||||
List.of(
|
||||
Dependency.GSON,
|
||||
Dependency.SLF4J_API,
|
||||
Dependency.SLF4J_SIMPLE,
|
||||
Dependency.COMMAND_API,
|
||||
Dependency.BOOSTED_YAML,
|
||||
Dependency.ADVENTURE_TEXT_MINIMESSAGE,
|
||||
Dependency.ADVENTURE_LEGACY_SERIALIZER,
|
||||
Dependency.MYSQL_DRIVER,
|
||||
Dependency.MARIADB_DRIVER,
|
||||
Dependency.MONGODB_DRIVER_SYNC,
|
||||
Dependency.MONGODB_DRIVER_CORE,
|
||||
Dependency.MONGODB_DRIVER_BSON,
|
||||
Dependency.JEDIS,
|
||||
Dependency.COMMONS_POOL_2,
|
||||
Dependency.H2_DRIVER,
|
||||
Dependency.SQLITE_DRIVER,
|
||||
Dependency.BSTATS_BASE,
|
||||
Dependency.HIKARI,
|
||||
Dependency.BSTATS_BUKKIT
|
||||
)
|
||||
));
|
||||
ReflectionUtils.load();
|
||||
}
|
||||
|
||||
@@ -155,27 +183,6 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLibraries() {
|
||||
String mavenRepo = TimeZone.getDefault().getID().startsWith("Asia") ?
|
||||
"https://maven.aliyun.com/repository/public/" : "https://repo.maven.apache.org/maven2/";
|
||||
LibraryLoader.loadDependencies(
|
||||
"org.apache.commons:commons-pool2:2.12.0", mavenRepo,
|
||||
"redis.clients:jedis:5.1.0", mavenRepo,
|
||||
"dev.dejvokep:boosted-yaml:1.3.1", mavenRepo,
|
||||
"com.zaxxer:HikariCP:5.0.1", mavenRepo,
|
||||
"org.mariadb.jdbc:mariadb-java-client:3.3.0", mavenRepo,
|
||||
"com.mysql:mysql-connector-j:8.2.0", mavenRepo,
|
||||
"commons-io:commons-io:2.15.1", mavenRepo,
|
||||
"com.google.code.gson:gson:2.10.1", mavenRepo,
|
||||
"com.h2database:h2:2.2.224", mavenRepo,
|
||||
"org.mongodb:mongodb-driver-sync:4.11.1", mavenRepo,
|
||||
"org.mongodb:mongodb-driver-core:4.11.1", mavenRepo,
|
||||
"org.mongodb:bson:4.11.1", mavenRepo,
|
||||
"org.xerial:sqlite-jdbc:3.43.2.2", mavenRepo,
|
||||
"dev.jorel:commandapi-bukkit-shade:9.3.0", mavenRepo
|
||||
);
|
||||
}
|
||||
|
||||
public CoolDownManager getCoolDownManager() {
|
||||
return coolDownManager;
|
||||
}
|
||||
@@ -183,4 +190,8 @@ public class CustomNameplatesPluginImpl extends CustomNameplatesPlugin implement
|
||||
public PacketManager getPacketManager() {
|
||||
return packetManager;
|
||||
}
|
||||
|
||||
public DependencyManager getDependencyManager() {
|
||||
return dependencyManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* This file is part of helper, 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 net.momirealms.customnameplates.paper.helper;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.util.LogUtils;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
|
||||
* into the classloader.
|
||||
*/
|
||||
public final class LibraryLoader {
|
||||
|
||||
@SuppressWarnings("Guava")
|
||||
private static final Supplier<URLClassLoaderAccess> URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomNameplatesPluginImpl.getInstance().getClass().getClassLoader()));
|
||||
|
||||
/**
|
||||
* Resolves all {@link MavenLibrary} annotations on the given object.
|
||||
*
|
||||
* @param object the object to load libraries for.
|
||||
*/
|
||||
public static void loadAll(Object object) {
|
||||
loadAll(object.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves all {@link MavenLibrary} annotations on the given class.
|
||||
*
|
||||
* @param clazz the class to load libraries for.
|
||||
*/
|
||||
public static void loadAll(Class<?> clazz) {
|
||||
MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
|
||||
for (MavenLibrary lib : libs) {
|
||||
load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(String groupId, String artifactId, String version, String repoUrl) {
|
||||
load(new Dependency(groupId, artifactId, version, repoUrl));
|
||||
}
|
||||
|
||||
public static void loadDependencies(String... libs) {
|
||||
if (libs == null || libs.length % 2 != 0)
|
||||
return;
|
||||
for (int i = 0; i < libs.length; i+=2) {
|
||||
String[] split = libs[i].split(":");
|
||||
load(new Dependency(
|
||||
split[0],
|
||||
split[1],
|
||||
split[2],
|
||||
libs[i+1]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(Dependency d) {
|
||||
// LogUtils.info(String.format("Loading dependency %s:%s:%s", d.groupId, d.artifactId, d.version));
|
||||
String name = d.artifactId() + "-" + d.version();
|
||||
File saveLocation = new File(getLibFolder(d), name + ".jar");
|
||||
if (!saveLocation.exists()) {
|
||||
try {
|
||||
LogUtils.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
|
||||
URL url = d.getUrl();
|
||||
try (InputStream is = url.openStream()) {
|
||||
Files.copy(is, saveLocation.toPath());
|
||||
LogUtils.info("Dependency '" + name + "' successfully downloaded.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!saveLocation.exists())
|
||||
throw new RuntimeException("Unable to download dependency: " + d);
|
||||
try {
|
||||
URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to load dependency: " + saveLocation, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static File getLibFolder(Dependency dependency) {
|
||||
File pluginDataFolder = CustomNameplatesPlugin.getInstance().getDataFolder();
|
||||
File serverDir = pluginDataFolder.getParentFile().getParentFile();
|
||||
|
||||
File helperDir = new File(serverDir, "libraries");
|
||||
String[] split = dependency.groupId().split("\\.");
|
||||
File jarDir;
|
||||
StringJoiner stringJoiner = new StringJoiner(File.separator);
|
||||
for (String str : split) {
|
||||
stringJoiner.add(str);
|
||||
}
|
||||
jarDir = new File(helperDir, stringJoiner + File.separator + dependency.artifactId + File.separator + dependency.version);
|
||||
jarDir.mkdirs();
|
||||
return jarDir;
|
||||
}
|
||||
|
||||
public record Dependency(String groupId, String artifactId, String version, String repoUrl) {
|
||||
public Dependency(String groupId, String artifactId, String version, String repoUrl) {
|
||||
this.groupId = Objects.requireNonNull(groupId, "groupId");
|
||||
this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
|
||||
this.version = Objects.requireNonNull(version, "version");
|
||||
this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
|
||||
}
|
||||
|
||||
public URL getUrl() throws MalformedURLException {
|
||||
String repo = this.repoUrl;
|
||||
if (!repo.endsWith("/")) {
|
||||
repo += "/";
|
||||
}
|
||||
repo += "%s/%s/%s/%s-%s.jar";
|
||||
|
||||
String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
|
||||
return new URL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Dependency other)) return false;
|
||||
return this.groupId().equals(other.groupId()) &&
|
||||
this.artifactId().equals(other.artifactId()) &&
|
||||
this.version().equals(other.version()) &&
|
||||
this.repoUrl().equals(other.repoUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = result * PRIME + this.groupId().hashCode();
|
||||
result = result * PRIME + this.artifactId().hashCode();
|
||||
result = result * PRIME + this.version().hashCode();
|
||||
result = result * PRIME + this.repoUrl().hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LibraryLoader.Dependency(" +
|
||||
"groupId=" + this.groupId() + ", " +
|
||||
"artifactId=" + this.artifactId() + ", " +
|
||||
"version=" + this.version() + ", " +
|
||||
"repoUrl=" + this.repoUrl() + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,21 +23,19 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Annotation to indicate the required libraries for a class.
|
||||
* Interface which allows access to add URLs to the plugin classpath at runtime.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MavenLibraries {
|
||||
public interface ClassPathAppender extends AutoCloseable {
|
||||
|
||||
@NotNull
|
||||
MavenLibrary[] value() default {};
|
||||
void addJarToClasspath(Path file);
|
||||
|
||||
@Override
|
||||
default void close() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import net.momirealms.customnameplates.paper.libraries.loader.JarInJarClassLoader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class JarInJarClassPathAppender implements ClassPathAppender {
|
||||
private final JarInJarClassLoader classLoader;
|
||||
|
||||
public JarInJarClassPathAppender(ClassLoader classLoader) {
|
||||
if (!(classLoader instanceof JarInJarClassLoader)) {
|
||||
throw new IllegalArgumentException("Loader is not a JarInJarClassLoader: " + classLoader.getClass().getName());
|
||||
}
|
||||
this.classLoader = (JarInJarClassLoader) classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
try {
|
||||
this.classLoader.addJarToClasspath(file.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.classLoader.deleteJarResource();
|
||||
try {
|
||||
this.classLoader.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class ReflectionClassPathAppender implements ClassPathAppender {
|
||||
private final URLClassLoaderAccess classLoaderAccess;
|
||||
|
||||
public ReflectionClassPathAppender(ClassLoader classLoader) throws IllegalStateException {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader);
|
||||
} else {
|
||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJarToClasspath(Path file) {
|
||||
try {
|
||||
this.classLoaderAccess.addURL(file.toUri().toURL());
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,11 +23,12 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.classpath;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Collection;
|
||||
@@ -43,8 +44,10 @@ public abstract class URLClassLoaderAccess {
|
||||
* @param classLoader the class loader
|
||||
* @return the access object
|
||||
*/
|
||||
static URLClassLoaderAccess create(URLClassLoader classLoader) {
|
||||
if (Unsafe.isSupported()) {
|
||||
public static URLClassLoaderAccess create(URLClassLoader classLoader) {
|
||||
if (Reflection.isSupported()) {
|
||||
return new Reflection(classLoader);
|
||||
} else if (Unsafe.isSupported()) {
|
||||
return new Unsafe(classLoader);
|
||||
} else {
|
||||
return Noop.INSTANCE;
|
||||
@@ -63,7 +66,48 @@ public abstract class URLClassLoaderAccess {
|
||||
*
|
||||
* @param url the URL to add
|
||||
*/
|
||||
public abstract void addURL(@NotNull URL url);
|
||||
public abstract void addURL(@NonNull URL url);
|
||||
|
||||
private static void throwError(Throwable cause) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("LuckPerms is unable to inject into the plugin URLClassLoader.\n" +
|
||||
"You may be able to fix this problem by adding the following command-line argument " +
|
||||
"directly after the 'java' command in your start script: \n'--add-opens java.base/java.lang=ALL-UNNAMED'", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses using reflection, not supported on Java 9+.
|
||||
*/
|
||||
private static class Reflection extends URLClassLoaderAccess {
|
||||
private static final Method ADD_URL_METHOD;
|
||||
|
||||
static {
|
||||
Method addUrlMethod;
|
||||
try {
|
||||
addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||
addUrlMethod.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
addUrlMethod = null;
|
||||
}
|
||||
ADD_URL_METHOD = addUrlMethod;
|
||||
}
|
||||
|
||||
private static boolean isSupported() {
|
||||
return ADD_URL_METHOD != null;
|
||||
}
|
||||
|
||||
Reflection(URLClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NonNull URL url) {
|
||||
try {
|
||||
ADD_URL_METHOD.invoke(super.classLoader, url);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
URLClassLoaderAccess.throwError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses using sun.misc.Unsafe, supported on Java 9+.
|
||||
@@ -106,6 +150,7 @@ public abstract class URLClassLoaderAccess {
|
||||
unopenedURLs = null;
|
||||
pathURLs = null;
|
||||
}
|
||||
|
||||
this.unopenedURLs = unopenedURLs;
|
||||
this.pathURLs = pathURLs;
|
||||
}
|
||||
@@ -117,11 +162,17 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NotNull URL url) {
|
||||
public void addURL(@NonNull URL url) {
|
||||
if (this.unopenedURLs == null || this.pathURLs == null) {
|
||||
URLClassLoaderAccess.throwError(new NullPointerException("unopenedURLs or pathURLs"));
|
||||
}
|
||||
|
||||
synchronized (this.unopenedURLs) {
|
||||
this.unopenedURLs.add(url);
|
||||
this.pathURLs.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Noop extends URLClassLoaderAccess {
|
||||
private static final Noop INSTANCE = new Noop();
|
||||
@@ -131,8 +182,8 @@ public abstract class URLClassLoaderAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addURL(@NotNull URL url) {
|
||||
throw new UnsupportedOperationException();
|
||||
public void addURL(@NonNull URL url) {
|
||||
URLClassLoaderAccess.throwError(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.Relocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* The dependencies used by LuckPerms.
|
||||
*/
|
||||
public enum Dependency {
|
||||
|
||||
ASM(
|
||||
"org.ow2.asm",
|
||||
"asm",
|
||||
"9.1",
|
||||
null,
|
||||
"asm"
|
||||
),
|
||||
ASM_COMMONS(
|
||||
"org.ow2.asm",
|
||||
"asm-commons",
|
||||
"9.1",
|
||||
null,
|
||||
"asm-commons"
|
||||
),
|
||||
JAR_RELOCATOR(
|
||||
"me.lucko",
|
||||
"jar-relocator",
|
||||
"1.7",
|
||||
null,
|
||||
"jar-relocator"
|
||||
),
|
||||
KYORI_OPTION(
|
||||
"net{}kyori",
|
||||
"option",
|
||||
"1.0.0",
|
||||
null,
|
||||
"kyori-option",
|
||||
Relocation.of("option", "net{}kyori{}option")
|
||||
),
|
||||
ADVENTURE_API(
|
||||
"net{}kyori",
|
||||
"adventure-api",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-api",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_KEY(
|
||||
"net{}kyori",
|
||||
"adventure-key",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-key",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_NBT(
|
||||
"net{}kyori",
|
||||
"adventure-nbt",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-nbt",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_LEGACY_SERIALIZER(
|
||||
"net{}kyori",
|
||||
"adventure-text-serializer-legacy",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-text-serializer-legacy",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_TEXT_LOGGER(
|
||||
"net{}kyori",
|
||||
"adventure-text-logger-slf4j",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-text-logger-slf4j",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_GSON(
|
||||
"net{}kyori",
|
||||
"adventure-text-serializer-gson",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-text-serializer-gson",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_GSON_LEGACY(
|
||||
"net{}kyori",
|
||||
"adventure-text-serializer-gson-legacy-impl",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-text-serializer-gson-legacy-impl",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_PLATFORM(
|
||||
"net{}kyori",
|
||||
"adventure-platform-api",
|
||||
"4.3.2",
|
||||
null,
|
||||
"adventure-platform-api",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_PLATFORM_BUKKIT(
|
||||
"net{}kyori",
|
||||
"adventure-platform-bukkit",
|
||||
"4.3.2",
|
||||
null,
|
||||
"adventure-platform-bukkit",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_PLATFORM_FACET(
|
||||
"net{}kyori",
|
||||
"adventure-platform-facet",
|
||||
"4.3.2",
|
||||
null,
|
||||
"adventure-platform-facet",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
ADVENTURE_TEXT_MINIMESSAGE(
|
||||
"net{}kyori",
|
||||
"adventure-text-minimessage",
|
||||
"4.15.0",
|
||||
null,
|
||||
"adventure-text-minimessage",
|
||||
Relocation.of("adventure", "net{}kyori{}adventure")
|
||||
),
|
||||
COMMAND_API(
|
||||
"dev{}jorel",
|
||||
"commandapi-bukkit-shade",
|
||||
"9.3.0",
|
||||
null,
|
||||
"commandapi-bukkit",
|
||||
Relocation.of("commandapi", "dev{}jorel{}commandapi")
|
||||
),
|
||||
MARIADB_DRIVER(
|
||||
"org{}mariadb{}jdbc",
|
||||
"mariadb-java-client",
|
||||
"3.3.2",
|
||||
null,
|
||||
"mariadb-java-client",
|
||||
Relocation.of("mariadb", "org{}mariadb")
|
||||
),
|
||||
BOOSTED_YAML(
|
||||
"dev{}dejvokep",
|
||||
"boosted-yaml",
|
||||
"1.3.2",
|
||||
null,
|
||||
"boosted-yaml",
|
||||
Relocation.of("boostedyaml", "dev{}dejvokep{}boostedyaml")
|
||||
),
|
||||
MYSQL_DRIVER(
|
||||
"com{}mysql",
|
||||
"mysql-connector-j",
|
||||
"8.3.0",
|
||||
null,
|
||||
"mysql-connector-j",
|
||||
Relocation.of("mysql", "com{}mysql")
|
||||
),
|
||||
H2_DRIVER(
|
||||
"com.h2database",
|
||||
"h2",
|
||||
"2.2.224",
|
||||
null,
|
||||
"h2database"
|
||||
),
|
||||
SQLITE_DRIVER(
|
||||
"org.xerial",
|
||||
"sqlite-jdbc",
|
||||
"3.45.1.0",
|
||||
null,
|
||||
"sqlite-jdbc"
|
||||
),
|
||||
HIKARI(
|
||||
"com{}zaxxer",
|
||||
"HikariCP",
|
||||
"5.0.1",
|
||||
null,
|
||||
"HikariCP",
|
||||
Relocation.of("hikari", "com{}zaxxer{}hikari")
|
||||
),
|
||||
SLF4J_SIMPLE(
|
||||
"org.slf4j",
|
||||
"slf4j-simple",
|
||||
"2.0.12",
|
||||
null,
|
||||
"slf4j-simple"
|
||||
),
|
||||
SLF4J_API(
|
||||
"org.slf4j",
|
||||
"slf4j-api",
|
||||
"2.0.12",
|
||||
null,
|
||||
"slf4j-api"
|
||||
),
|
||||
MONGODB_DRIVER_CORE(
|
||||
"org{}mongodb",
|
||||
"mongodb-driver-core",
|
||||
"4.11.1",
|
||||
null,
|
||||
"mongodb-driver-core",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
MONGODB_DRIVER_SYNC(
|
||||
"org{}mongodb",
|
||||
"mongodb-driver-sync",
|
||||
"4.11.1",
|
||||
null,
|
||||
"mongodb-driver-sync",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
MONGODB_DRIVER_BSON(
|
||||
"org{}mongodb",
|
||||
"bson",
|
||||
"4.11.1",
|
||||
null,
|
||||
"mongodb-bson",
|
||||
Relocation.of("mongodb", "com{}mongodb"),
|
||||
Relocation.of("bson", "org{}bson")
|
||||
),
|
||||
JEDIS(
|
||||
"redis{}clients",
|
||||
"jedis",
|
||||
"5.1.0",
|
||||
null,
|
||||
"jedis",
|
||||
Relocation.of("jedis", "redis{}clients{}jedis"),
|
||||
Relocation.of("commonspool2", "org{}apache{}commons{}pool2")
|
||||
),
|
||||
BSTATS_BASE(
|
||||
"org{}bstats",
|
||||
"bstats-base",
|
||||
"3.0.2",
|
||||
null,
|
||||
"bstats-base",
|
||||
Relocation.of("bstats", "org{}bstats")
|
||||
),
|
||||
BSTATS_BUKKIT(
|
||||
"org{}bstats",
|
||||
"bstats-bukkit",
|
||||
"3.0.2",
|
||||
null,
|
||||
"bstats-bukkit",
|
||||
Relocation.of("bstats", "org{}bstats")
|
||||
),
|
||||
COMMONS_POOL_2(
|
||||
"org{}apache{}commons",
|
||||
"commons-pool2",
|
||||
"2.11.0",
|
||||
null,
|
||||
"commons-pool2",
|
||||
Relocation.of("commonspool2", "org{}apache{}commons{}pool2")
|
||||
),
|
||||
GSON(
|
||||
"com.google.code.gson",
|
||||
"gson",
|
||||
"2.10.1",
|
||||
null,
|
||||
"gson"
|
||||
),;
|
||||
|
||||
private final String mavenRepoPath;
|
||||
private final String version;
|
||||
private final List<Relocation> relocations;
|
||||
private final String repo;
|
||||
private final String artifact;
|
||||
|
||||
private static final String MAVEN_FORMAT = "%s/%s/%s/%s-%s.jar";
|
||||
|
||||
Dependency(String groupId, String artifactId, String version, String repo, String artifact) {
|
||||
this(groupId, artifactId, version, repo, artifact, new Relocation[0]);
|
||||
}
|
||||
|
||||
Dependency(String groupId, String artifactId, String version, String repo, String artifact, Relocation... relocations) {
|
||||
this.mavenRepoPath = String.format(MAVEN_FORMAT,
|
||||
rewriteEscaping(groupId).replace(".", "/"),
|
||||
rewriteEscaping(artifactId),
|
||||
version,
|
||||
rewriteEscaping(artifactId),
|
||||
version
|
||||
);
|
||||
this.version = version;
|
||||
this.relocations = ImmutableList.copyOf(relocations);
|
||||
this.repo = repo;
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
private static String rewriteEscaping(String s) {
|
||||
return s.replace("{}", ".");
|
||||
}
|
||||
|
||||
public String getFileName(String classifier) {
|
||||
String name = artifact.toLowerCase(Locale.ROOT).replace('_', '-');
|
||||
String extra = classifier == null || classifier.isEmpty()
|
||||
? ""
|
||||
: "-" + classifier;
|
||||
|
||||
return name + "-" + this.version + extra + ".jar";
|
||||
}
|
||||
|
||||
String getMavenRepoPath() {
|
||||
return this.mavenRepoPath;
|
||||
}
|
||||
|
||||
public List<Relocation> getRelocations() {
|
||||
return this.relocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MessageDigest} suitable for computing the checksums
|
||||
* of dependencies.
|
||||
*
|
||||
* @return the digest
|
||||
*/
|
||||
public static MessageDigest createDigest() {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getRepo() {
|
||||
return repo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
/**
|
||||
* Exception thrown if a dependency cannot be downloaded.
|
||||
*/
|
||||
public class DependencyDownloadException extends Exception {
|
||||
|
||||
public DependencyDownloadException() {
|
||||
|
||||
}
|
||||
|
||||
public DependencyDownloadException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public DependencyDownloadException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DependencyDownloadException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,51 +23,31 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
package net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a required library for a class.
|
||||
* Loads and manages runtime dependencies for the plugin.
|
||||
*/
|
||||
@Documented
|
||||
@Repeatable(MavenLibraries.class)
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MavenLibrary {
|
||||
public interface DependencyManager extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* The group id of the library
|
||||
* Loads dependencies.
|
||||
*
|
||||
* @return the group id of the library
|
||||
* @param dependencies the dependencies to load
|
||||
*/
|
||||
@NotNull
|
||||
String groupId();
|
||||
void loadDependencies(Collection<Dependency> dependencies);
|
||||
|
||||
/**
|
||||
* The artifact id of the library
|
||||
* Obtains an isolated classloader containing the given dependencies.
|
||||
*
|
||||
* @return the artifact id of the library
|
||||
* @param dependencies the dependencies
|
||||
* @return the classloader
|
||||
*/
|
||||
@NotNull
|
||||
String artifactId();
|
||||
|
||||
/**
|
||||
* The version of the library
|
||||
*
|
||||
* @return the version of the library
|
||||
*/
|
||||
@NotNull
|
||||
String version();
|
||||
|
||||
/**
|
||||
* The repo where the library can be obtained from
|
||||
*
|
||||
* @return the repo where the library can be obtained from
|
||||
*/
|
||||
@NotNull
|
||||
Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
|
||||
ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies);
|
||||
|
||||
@Override
|
||||
void close();
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
import net.momirealms.customnameplates.paper.libraries.classpath.ClassPathAppender;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.classloader.IsolatedClassLoader;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.Relocation;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.relocation.RelocationHandler;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* Loads and manages runtime dependencies for the plugin.
|
||||
*/
|
||||
public class DependencyManagerImpl implements DependencyManager {
|
||||
|
||||
/** A registry containing plugin specific behaviour for dependencies. */
|
||||
private final DependencyRegistry registry;
|
||||
/** The path where library jars are cached. */
|
||||
private final Path cacheDirectory;
|
||||
/** The classpath appender to preload dependencies into */
|
||||
private final ClassPathAppender classPathAppender;
|
||||
/** A map of dependencies which have already been loaded. */
|
||||
private final EnumMap<Dependency, Path> loaded = new EnumMap<>(Dependency.class);
|
||||
/** A map of isolated classloaders which have been created. */
|
||||
private final Map<ImmutableSet<Dependency>, IsolatedClassLoader> loaders = new HashMap<>();
|
||||
/** Cached relocation handler instance. */
|
||||
private @MonotonicNonNull RelocationHandler relocationHandler = null;
|
||||
|
||||
public DependencyManagerImpl(CustomNameplatesPluginImpl plugin, ClassPathAppender classPathAppender) {
|
||||
this.registry = new DependencyRegistry();
|
||||
this.cacheDirectory = setupCacheDirectory(plugin);
|
||||
this.classPathAppender = classPathAppender;
|
||||
}
|
||||
|
||||
private synchronized RelocationHandler getRelocationHandler() {
|
||||
if (this.relocationHandler == null) {
|
||||
this.relocationHandler = new RelocationHandler(this);
|
||||
}
|
||||
return this.relocationHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader obtainClassLoaderWith(Set<Dependency> dependencies) {
|
||||
ImmutableSet<Dependency> set = ImmutableSet.copyOf(dependencies);
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
if (!this.loaded.containsKey(dependency)) {
|
||||
throw new IllegalStateException("Dependency " + dependency + " is not loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (this.loaders) {
|
||||
IsolatedClassLoader classLoader = this.loaders.get(set);
|
||||
if (classLoader != null) {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
URL[] urls = set.stream()
|
||||
.map(this.loaded::get)
|
||||
.map(file -> {
|
||||
try {
|
||||
return file.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.toArray(URL[]::new);
|
||||
|
||||
classLoader = new IsolatedClassLoader(urls);
|
||||
this.loaders.put(set, classLoader);
|
||||
return classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDependencies(Collection<Dependency> dependencies) {
|
||||
CountDownLatch latch = new CountDownLatch(dependencies.size());
|
||||
|
||||
for (Dependency dependency : dependencies) {
|
||||
if (this.loaded.containsKey(dependency)) {
|
||||
latch.countDown();
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
loadDependency(dependency);
|
||||
} catch (Throwable e) {
|
||||
new RuntimeException("Unable to load dependency " + dependency.name(), e).printStackTrace();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDependency(Dependency dependency) throws Exception {
|
||||
if (this.loaded.containsKey(dependency)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path file = remapDependency(dependency, downloadDependency(dependency));
|
||||
|
||||
this.loaded.put(dependency, file);
|
||||
|
||||
if (this.classPathAppender != null && this.registry.shouldAutoLoad(dependency)) {
|
||||
this.classPathAppender.addJarToClasspath(file);
|
||||
}
|
||||
}
|
||||
|
||||
private Path downloadDependency(Dependency dependency) throws DependencyDownloadException {
|
||||
Path file = this.cacheDirectory.resolve(dependency.getFileName(null));
|
||||
|
||||
// if the file already exists, don't attempt to re-download it.
|
||||
if (Files.exists(file)) {
|
||||
return file;
|
||||
}
|
||||
|
||||
DependencyDownloadException lastError = null;
|
||||
|
||||
String forceRepo = dependency.getRepo();
|
||||
if (forceRepo == null) {
|
||||
// attempt to download the dependency from each repo in order.
|
||||
for (DependencyRepository repo : DependencyRepository.values()) {
|
||||
if (repo.getId().equals("maven") && TimeZone.getDefault().getID().startsWith("Asia")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
repo.download(dependency, file);
|
||||
return file;
|
||||
} catch (DependencyDownloadException e) {
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DependencyRepository repository = DependencyRepository.getByID(forceRepo);
|
||||
if (repository != null) {
|
||||
try {
|
||||
repository.download(dependency, file);
|
||||
return file;
|
||||
} catch (DependencyDownloadException e) {
|
||||
lastError = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Objects.requireNonNull(lastError);
|
||||
}
|
||||
|
||||
private Path remapDependency(Dependency dependency, Path normalFile) throws Exception {
|
||||
List<Relocation> rules = new ArrayList<>(dependency.getRelocations());
|
||||
if (rules.isEmpty()) {
|
||||
return normalFile;
|
||||
}
|
||||
|
||||
Path remappedFile = this.cacheDirectory.resolve(dependency.getFileName(DependencyRegistry.isGsonRelocated() ? "remapped-legacy" : "remapped"));
|
||||
|
||||
// if the remapped source exists already, just use that.
|
||||
if (Files.exists(remappedFile)) {
|
||||
return remappedFile;
|
||||
}
|
||||
|
||||
getRelocationHandler().remap(normalFile, remappedFile, rules);
|
||||
return remappedFile;
|
||||
}
|
||||
|
||||
private static Path setupCacheDirectory(CustomNameplatesPluginImpl plugin) {
|
||||
File folder = new File(plugin.getDataFolder(), "libs");
|
||||
folder.mkdirs();
|
||||
return folder.toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IOException firstEx = null;
|
||||
|
||||
for (IsolatedClassLoader loader : this.loaders.values()) {
|
||||
try {
|
||||
loader.close();
|
||||
} catch (IOException ex) {
|
||||
if (firstEx == null) {
|
||||
firstEx = ex;
|
||||
} else {
|
||||
firstEx.addSuppressed(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firstEx != null) {
|
||||
firstEx.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* Applies LuckPerms specific behaviour for {@link Dependency}s.
|
||||
*/
|
||||
public class DependencyRegistry {
|
||||
|
||||
public boolean shouldAutoLoad(Dependency dependency) {
|
||||
return switch (dependency) {
|
||||
// all used within 'isolated' classloaders, and are therefore not
|
||||
// relocated.
|
||||
case ASM, ASM_COMMONS, JAR_RELOCATOR, H2_DRIVER, SQLITE_DRIVER -> false;
|
||||
default -> true;
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static boolean isGsonRelocated() {
|
||||
return JsonElement.class.getName().startsWith("net.momirealms");
|
||||
}
|
||||
|
||||
private static boolean classExists(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean slf4jPresent() {
|
||||
return classExists("org.slf4j.Logger") && classExists("org.slf4j.LoggerFactory");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Represents a repository which contains {@link Dependency}s.
|
||||
*/
|
||||
public enum DependencyRepository {
|
||||
|
||||
MAVEN_CENTRAL("maven", "https://repo1.maven.org/maven2/") {
|
||||
@Override
|
||||
protected URLConnection openConnection(Dependency dependency) throws IOException {
|
||||
URLConnection connection = super.openConnection(dependency);
|
||||
connection.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(5));
|
||||
connection.setReadTimeout((int) TimeUnit.SECONDS.toMillis(5));
|
||||
return connection;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Maven Central
|
||||
*/
|
||||
MAVEN_CENTRAL_MIRROR("aliyun", "https://maven.aliyun.com/repository/public/"),
|
||||
/**
|
||||
* Code MC
|
||||
*/
|
||||
CODE_MC("codemc", "https://repo.codemc.io/repository/maven-public/");
|
||||
|
||||
private final String url;
|
||||
private final String id;
|
||||
|
||||
DependencyRepository(String id, String url) {
|
||||
this.url = url;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static DependencyRepository getByID(String id) {
|
||||
for (DependencyRepository repository : values()) {
|
||||
if (id.equals(repository.id)) {
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a connection to the given {@code dependency}.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @return the connection
|
||||
* @throws IOException if unable to open a connection
|
||||
*/
|
||||
protected URLConnection openConnection(Dependency dependency) throws IOException {
|
||||
URL dependencyUrl = new URL(this.url + dependency.getMavenRepoPath());
|
||||
return dependencyUrl.openConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the raw bytes of the {@code dependency}.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @return the downloaded bytes
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public byte[] downloadRaw(Dependency dependency) throws DependencyDownloadException {
|
||||
try {
|
||||
URLConnection connection = openConnection(dependency);
|
||||
try (InputStream in = connection.getInputStream()) {
|
||||
byte[] bytes = ByteStreams.toByteArray(in);
|
||||
if (bytes.length == 0) {
|
||||
throw new DependencyDownloadException("Empty stream");
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new DependencyDownloadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dependency the dependency to download
|
||||
* @return the downloaded bytes
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public byte[] download(Dependency dependency) throws DependencyDownloadException {
|
||||
return downloadRaw(dependency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the the {@code dependency} to the {@code file}, ensuring the
|
||||
* downloaded bytes match the checksum.
|
||||
*
|
||||
* @param dependency the dependency to download
|
||||
* @param file the file to write to
|
||||
* @throws DependencyDownloadException if unable to download
|
||||
*/
|
||||
public void download(Dependency dependency, Path file) throws DependencyDownloadException {
|
||||
try {
|
||||
Files.write(file, download(dependency));
|
||||
} catch (IOException e) {
|
||||
throw new DependencyDownloadException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies.classloader;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* A classloader "isolated" from the rest of the Minecraft server.
|
||||
*
|
||||
* <p>Used to load specific LuckPerms dependencies without causing conflicts
|
||||
* with other plugins, or libraries provided by the server implementation.</p>
|
||||
*/
|
||||
public class IsolatedClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
public IsolatedClassLoader(URL[] urls) {
|
||||
/*
|
||||
* ClassLoader#getSystemClassLoader returns the AppClassLoader
|
||||
*
|
||||
* Calling #getParent on this returns the ExtClassLoader (Java 8) or
|
||||
* the PlatformClassLoader (Java 9). Since we want this classloader to
|
||||
* be isolated from the Minecraft server (the app), we set the parent
|
||||
* to be the platform class loader.
|
||||
*/
|
||||
super(urls, ClassLoader.getSystemClassLoader().getParent());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Relocation {
|
||||
private static final String RELOCATION_PREFIX = "net.momirealms.customnameplates.libraries.";
|
||||
|
||||
public static Relocation of(String id, String pattern) {
|
||||
return new Relocation(pattern.replace("{}", "."), RELOCATION_PREFIX + id);
|
||||
}
|
||||
|
||||
private final String pattern;
|
||||
private final String relocatedPattern;
|
||||
|
||||
private Relocation(String pattern, String relocatedPattern) {
|
||||
this.pattern = pattern;
|
||||
this.relocatedPattern = relocatedPattern;
|
||||
}
|
||||
|
||||
public String getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
public String getRelocatedPattern() {
|
||||
return this.relocatedPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Relocation that = (Relocation) o;
|
||||
return Objects.equals(this.pattern, that.pattern) &&
|
||||
Objects.equals(this.relocatedPattern, that.relocatedPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.pattern, this.relocatedPattern);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.Dependency;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.DependencyManager;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.classloader.IsolatedClassLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Handles class runtime relocation of packages in downloaded dependencies
|
||||
*/
|
||||
public class RelocationHandler {
|
||||
public static final Set<Dependency> DEPENDENCIES = EnumSet.of(Dependency.ASM, Dependency.ASM_COMMONS, Dependency.JAR_RELOCATOR);
|
||||
private static final String JAR_RELOCATOR_CLASS = "me.lucko.jarrelocator.JarRelocator";
|
||||
private static final String JAR_RELOCATOR_RUN_METHOD = "run";
|
||||
|
||||
private final Constructor<?> jarRelocatorConstructor;
|
||||
private final Method jarRelocatorRunMethod;
|
||||
|
||||
public RelocationHandler(DependencyManager dependencyManager) {
|
||||
ClassLoader classLoader = null;
|
||||
try {
|
||||
// download the required dependencies for remapping
|
||||
dependencyManager.loadDependencies(DEPENDENCIES);
|
||||
// get a classloader containing the required dependencies as sources
|
||||
classLoader = dependencyManager.obtainClassLoaderWith(DEPENDENCIES);
|
||||
|
||||
// load the relocator class
|
||||
Class<?> jarRelocatorClass = classLoader.loadClass(JAR_RELOCATOR_CLASS);
|
||||
|
||||
// prepare the the reflected constructor & method instances
|
||||
this.jarRelocatorConstructor = jarRelocatorClass.getDeclaredConstructor(File.class, File.class, Map.class);
|
||||
this.jarRelocatorConstructor.setAccessible(true);
|
||||
|
||||
this.jarRelocatorRunMethod = jarRelocatorClass.getDeclaredMethod(JAR_RELOCATOR_RUN_METHOD);
|
||||
this.jarRelocatorRunMethod.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
if (classLoader instanceof IsolatedClassLoader) {
|
||||
((IsolatedClassLoader) classLoader).close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void remap(Path input, Path output, List<Relocation> relocations) throws Exception {
|
||||
Map<String, String> mappings = new HashMap<>();
|
||||
for (Relocation relocation : relocations) {
|
||||
mappings.put(relocation.getPattern(), relocation.getRelocatedPattern());
|
||||
}
|
||||
|
||||
// create and invoke a new relocator
|
||||
Object relocator = this.jarRelocatorConstructor.newInstance(input.toFile(), output.toFile(), mappings);
|
||||
this.jarRelocatorRunMethod.invoke(relocator);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.dependencies.relocation;
|
||||
|
||||
public final class RelocationHelper {
|
||||
|
||||
// screw maven shade
|
||||
public static final String OKIO_STRING = String.valueOf(new char[]{'o', 'k', 'i', 'o'});
|
||||
public static final String OKHTTP3_STRING = String.valueOf(new char[]{'o', 'k', 'h', 't', 't', 'p', '3'});
|
||||
|
||||
private RelocationHelper() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
/**
|
||||
* Classloader that can load a jar from within another jar file.
|
||||
*
|
||||
* <p>The "loader" jar contains the loading code & public API classes,
|
||||
* and is class-loaded by the platform.</p>
|
||||
*
|
||||
* <p>The inner "plugin" jar contains the plugin itself, and is class-loaded
|
||||
* by the loading code & this classloader.</p>
|
||||
*/
|
||||
public class JarInJarClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new jar-in-jar class loader.
|
||||
*
|
||||
* @param loaderClassLoader the loader plugin's classloader (setup and created by the platform)
|
||||
* @param jarResourcePath the path to the jar-in-jar resource within the loader jar
|
||||
* @throws LoadingException if something unexpectedly bad happens
|
||||
*/
|
||||
public JarInJarClassLoader(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
|
||||
super(new URL[]{extractJar(loaderClassLoader, jarResourcePath)}, loaderClassLoader);
|
||||
}
|
||||
|
||||
public void addJarToClasspath(URL url) {
|
||||
addURL(url);
|
||||
}
|
||||
|
||||
public void deleteJarResource() {
|
||||
URL[] urls = getURLs();
|
||||
if (urls.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Path path = Paths.get(urls[0].toURI());
|
||||
Files.deleteIfExists(path);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new plugin instance.
|
||||
*
|
||||
* @param bootstrapClass the name of the bootstrap plugin class
|
||||
* @param loaderPluginType the type of the loader plugin, the only parameter of the bootstrap
|
||||
* plugin constructor
|
||||
* @param loaderPlugin the loader plugin instance
|
||||
* @param <T> the type of the loader plugin
|
||||
* @return the instantiated bootstrap plugin
|
||||
*/
|
||||
public <T> LoaderBootstrap instantiatePlugin(String bootstrapClass, Class<T> loaderPluginType, T loaderPlugin) throws LoadingException {
|
||||
Class<? extends LoaderBootstrap> plugin;
|
||||
try {
|
||||
plugin = loadClass(bootstrapClass).asSubclass(LoaderBootstrap.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to load bootstrap class", e);
|
||||
}
|
||||
|
||||
Constructor<? extends LoaderBootstrap> constructor;
|
||||
try {
|
||||
constructor = plugin.getConstructor(loaderPluginType);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to get bootstrap constructor", e);
|
||||
}
|
||||
|
||||
try {
|
||||
return constructor.newInstance(loaderPlugin);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new LoadingException("Unable to create bootstrap plugin instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the "jar-in-jar" from the loader plugin into a temporary file,
|
||||
* then returns a URL that can be used by the {@link JarInJarClassLoader}.
|
||||
*
|
||||
* @param loaderClassLoader the classloader for the "host" loader plugin
|
||||
* @param jarResourcePath the inner jar resource path
|
||||
* @return a URL to the extracted file
|
||||
*/
|
||||
private static URL extractJar(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
|
||||
// get the jar-in-jar resource
|
||||
URL jarInJar = loaderClassLoader.getResource(jarResourcePath);
|
||||
if (jarInJar == null) {
|
||||
throw new LoadingException("Could not locate jar-in-jar");
|
||||
}
|
||||
|
||||
// create a temporary file
|
||||
// on posix systems by default this is only read/writable by the process owner
|
||||
Path path;
|
||||
try {
|
||||
path = Files.createTempFile("luckperms-jarinjar", ".jar.tmp");
|
||||
} catch (IOException e) {
|
||||
throw new LoadingException("Unable to create a temporary file", e);
|
||||
}
|
||||
|
||||
// mark that the file should be deleted on exit
|
||||
path.toFile().deleteOnExit();
|
||||
|
||||
// copy the jar-in-jar to the temporary file path
|
||||
try (InputStream in = jarInJar.openStream()) {
|
||||
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new LoadingException("Unable to copy jar-in-jar to temporary path", e);
|
||||
}
|
||||
|
||||
try {
|
||||
return path.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new LoadingException("Unable to get URL from path", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is part of helper, licensed under the MIT License.
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
@@ -23,23 +23,17 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.momirealms.customnameplates.paper.helper;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
package net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
/**
|
||||
* Represents a maven repository.
|
||||
* Minimal bootstrap plugin, called by the loader plugin.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.LOCAL_VARIABLE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Repository {
|
||||
public interface LoaderBootstrap {
|
||||
|
||||
/**
|
||||
* Gets the base url of the repository.
|
||||
*
|
||||
* @return the base url of the repository
|
||||
*/
|
||||
String url();
|
||||
void onLoad();
|
||||
|
||||
default void onEnable() {}
|
||||
|
||||
default void onDisable() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 net.momirealms.customnameplates.paper.libraries.loader;
|
||||
|
||||
/**
|
||||
* Runtime exception used if there is a problem during loading
|
||||
*/
|
||||
public class LoadingException extends RuntimeException {
|
||||
|
||||
public LoadingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public LoadingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -238,7 +238,7 @@ public class VersionManagerImpl implements VersionManager, Listener {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.isOp()) {
|
||||
if (!PlaceholderAPI.isRegistered("player")) {
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "You haven't installed Player Expansion yet. Click <b><gold><click:run_command:/papi ecloud download Player>HERE</click></gold><b> to download.");
|
||||
AdventureManagerImpl.getInstance().sendMessageWithPrefix(player, "You haven't installed Player Expansion yet. Click <b><gold><u><click:run_command:/papi ecloud download Player>HERE</click></u></gold></b> to download. Otherwise you might encounter console spam on first installation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public class MagicCosmeticsListener implements Listener {
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,6 +60,7 @@ public class MagicCosmeticsListener implements Listener {
|
||||
final Cosmetic cosmetic = playerData.getHat();
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +74,7 @@ public class MagicCosmeticsListener implements Listener {
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +85,7 @@ public class MagicCosmeticsListener implements Listener {
|
||||
if (event.getCosmeticType() == CosmeticType.HAT) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(player.getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(0);
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,6 +96,7 @@ public class MagicCosmeticsListener implements Listener {
|
||||
if (cosmetic instanceof Hat hat) {
|
||||
if (unlimitedTagManager.getUnlimitedObject(event.getPlayerData().getUniqueId()) instanceof UnlimitedPlayer unlimitedPlayer) {
|
||||
unlimitedPlayer.setHatOffset(hat.isHideCosmetic() ? 0 : hat.getOffSetY());
|
||||
unlimitedPlayer.teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class SchedulerImpl implements Scheduler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the scheduler configuration based on CustomFishingPlugin settings.
|
||||
* Reloads the scheduler configuration based on settings.
|
||||
*/
|
||||
public void reload() {
|
||||
try {
|
||||
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractHikariDatabase extends AbstractSQLDatabase impleme
|
||||
return;
|
||||
}
|
||||
|
||||
super.tablePrefix = section.getString("table-prefix", "customfishing");
|
||||
super.tablePrefix = section.getString("table-prefix", "nameplates");
|
||||
HikariConfig hikariConfig = new HikariConfig();
|
||||
hikariConfig.setUsername(section.getString("user", "root"));
|
||||
hikariConfig.setPassword(section.getString("password", "pa55w0rd"));
|
||||
|
||||
@@ -19,19 +19,23 @@ package net.momirealms.customnameplates.paper.storage.method.database.sql;
|
||||
|
||||
import net.momirealms.customnameplates.api.CustomNameplatesPlugin;
|
||||
import net.momirealms.customnameplates.api.data.StorageType;
|
||||
import net.momirealms.customnameplates.paper.CustomNameplatesPluginImpl;
|
||||
import net.momirealms.customnameplates.paper.libraries.dependencies.Dependency;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.h2.jdbcx.JdbcConnectionPool;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* An implementation of AbstractSQLDatabase that uses the H2 embedded database for player data storage.
|
||||
*/
|
||||
public class H2Impl extends AbstractSQLDatabase {
|
||||
|
||||
private JdbcConnectionPool connectionPool;
|
||||
private Object connectionPool;
|
||||
private Method disposeMethod;
|
||||
private Method getConnectionMethod;
|
||||
|
||||
public H2Impl(CustomNameplatesPlugin plugin) {
|
||||
super(plugin);
|
||||
@@ -44,10 +48,20 @@ public class H2Impl extends AbstractSQLDatabase {
|
||||
public void initialize() {
|
||||
YamlConfiguration config = plugin.getConfig("database.yml");
|
||||
File databaseFile = new File(plugin.getDataFolder(), config.getString("H2.file", "data.db"));
|
||||
super.tablePrefix = config.getString("H2.table-prefix", "customnameplates");
|
||||
super.tablePrefix = config.getString("H2.table-prefix", "nameplates");
|
||||
|
||||
final String url = String.format("jdbc:h2:%s", databaseFile.getAbsolutePath());
|
||||
this.connectionPool = JdbcConnectionPool.create(url, "sa", "");
|
||||
ClassLoader classLoader = ((CustomNameplatesPluginImpl) plugin).getDependencyManager().obtainClassLoaderWith(EnumSet.of(Dependency.H2_DRIVER));
|
||||
try {
|
||||
Class<?> connectionClass = classLoader.loadClass("org.h2.jdbcx.JdbcConnectionPool");
|
||||
Method createPoolMethod = connectionClass.getMethod("create", String.class, String.class, String.class);
|
||||
this.connectionPool = createPoolMethod.invoke(null, url, "sa", "");
|
||||
this.disposeMethod = connectionClass.getMethod("dispose");
|
||||
this.getConnectionMethod = connectionClass.getMethod("getConnection");
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
super.createTableIfNotExist();
|
||||
}
|
||||
|
||||
@@ -57,7 +71,11 @@ public class H2Impl extends AbstractSQLDatabase {
|
||||
@Override
|
||||
public void disable() {
|
||||
if (connectionPool != null) {
|
||||
connectionPool.dispose();
|
||||
try {
|
||||
disposeMethod.invoke(connectionPool);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +85,11 @@ public class H2Impl extends AbstractSQLDatabase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return connectionPool.getConnection();
|
||||
public Connection getConnection() {
|
||||
try {
|
||||
return (Connection) getConnectionMethod.invoke(connectionPool);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class SQLiteImpl extends AbstractSQLDatabase {
|
||||
public void initialize() {
|
||||
YamlConfiguration config = plugin.getConfig("database.yml");
|
||||
this.databaseFile = new File(plugin.getDataFolder(), config.getString("SQLite.file", "data") + ".db");
|
||||
super.tablePrefix = config.getString("SQLite.table-prefix", "customfishing");
|
||||
super.tablePrefix = config.getString("SQLite.table-prefix", "nameplates");
|
||||
super.createTableIfNotExist();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,5 +11,14 @@ tasks {
|
||||
relocate ("net.kyori", "net.momirealms.customnameplates.libraries")
|
||||
relocate ("org.bstats", "net.momirealms.customnameplates.libraries.bstats")
|
||||
relocate ("net.momirealms.biomeapi", "net.momirealms.customnameplates.libraries.biomeapi")
|
||||
relocate ("org.apache.commons.pool2", "net.momirealms.customnameplates.libraries.commonspool2")
|
||||
relocate ("com.mysql", "net.momirealms.customnameplates.libraries.mysql")
|
||||
relocate ("org.mariadb", "net.momirealms.customnameplates.libraries.mariadb")
|
||||
relocate ("com.zaxxer.hikari", "net.momirealms.customnameplates.libraries.hikari")
|
||||
relocate ("redis.clients.jedis", "net.momirealms.customnameplates.libraries.jedis")
|
||||
relocate ("com.mongodb", "net.momirealms.customnameplates.libraries.mongodb")
|
||||
relocate ("org.bson", "net.momirealms.customnameplates.libraries.bson")
|
||||
relocate ("dev.jorel.commandapi", "net.momirealms.customnameplates.libraries.commandapi")
|
||||
relocate ("dev.dejvokep.boostedyaml", "net.momirealms.customnameplates.libraries.boostedyaml")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user