diff --git a/src/main/scala/io/izzel/taboolib/TabooLib.java b/src/main/scala/io/izzel/taboolib/TabooLib.java index 49f49b0..002d8db 100644 --- a/src/main/scala/io/izzel/taboolib/TabooLib.java +++ b/src/main/scala/io/izzel/taboolib/TabooLib.java @@ -26,10 +26,10 @@ import java.util.concurrent.Executors; * 注意与 TabooLib4.x 版本的兼容 * 可能存在同时运行的情况 */ -@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/org.slf4j-slf4j-api-1.7.25.jar") -@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/com.zaxxer-HikariCP-3.1.0.jar") -@Dependency(type = Dependency.Type.LIBRARY, maven = "org.scala-lang:scala-library:2.12.8", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/scala-library-2.12.8.jar") -@Dependency(type = Dependency.Type.LIBRARY, maven = "com.google.inject:guice:4.2.2", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/guice-4.2.2.jar") +@Dependency(maven = "org.slf4j:slf4j-api:1.7.25", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/org.slf4j-slf4j-api-1.7.25.jar") +@Dependency(maven = "com.zaxxer:HikariCP:3.1.0", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/com.zaxxer-HikariCP-3.1.0.jar") +@Dependency(maven = "org.scala-lang:scala-library:2.12.8", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/scala-library-2.12.8.jar") +@Dependency(maven = "com.google.inject:guice:4.2.2", url = "https://skymc.oss-cn-shanghai.aliyuncs.com/libs/guice-4.2.2.jar") public class TabooLib { private static TabooLib inst = new TabooLib(); diff --git a/src/main/scala/io/izzel/taboolib/TabooLibLoader.java b/src/main/scala/io/izzel/taboolib/TabooLibLoader.java index 33a2797..8058c8a 100644 --- a/src/main/scala/io/izzel/taboolib/TabooLibLoader.java +++ b/src/main/scala/io/izzel/taboolib/TabooLibLoader.java @@ -29,7 +29,7 @@ public class TabooLibLoader { static void init() { // 加载依赖 - TDependencyInjector.inject("TabooLib", TabooLib.class); + TDependencyInjector.inject(TabooLib.getPlugin(), TabooLib.class); // 插件统计 Metrics metrics = new Metrics(TabooLib.getPlugin()); metrics.addCustomChart(new Metrics.SingleLineChart("plugins_using_taboolib", () -> Math.toIntExact(Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(TabooLibAPI::isDependTabooLib).count()))); diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/Dependency.java b/src/main/scala/io/izzel/taboolib/module/dependency/Dependency.java index 26f459f..1df576c 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/Dependency.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/Dependency.java @@ -7,12 +7,6 @@ import java.lang.annotation.*; @Repeatable(Dependencies.class) public @interface Dependency { - enum Type {PLUGIN, LIBRARY} - - Type type(); - - String plugin() default ""; - String maven() default ""; String mavenRepo() default TDependency.MAVEN_REPO; diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/DependencyAnnotationVisitor.java b/src/main/scala/io/izzel/taboolib/module/dependency/DependencyAnnotationVisitor.java new file mode 100644 index 0000000..2147f00 --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/module/dependency/DependencyAnnotationVisitor.java @@ -0,0 +1,71 @@ +package io.izzel.taboolib.module.dependency; + +import io.izzel.taboolib.TabooLib; +import io.izzel.taboolib.TabooLibAPI; +import io.izzel.taboolib.util.Strings; +import org.bukkit.plugin.Plugin; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Opcodes; + +/** + * @Author 坏黑 + * @Since 2019-07-13 15:25 + */ +public class DependencyAnnotationVisitor extends AnnotationVisitor { + + private Plugin plugin; + private String maven; + private String mavenRepo = TDependency.MAVEN_REPO; + private String url = ""; + + public DependencyAnnotationVisitor(Plugin plugin, AnnotationVisitor annotationVisitor) { + super(Opcodes.ASM5, annotationVisitor); + this.plugin = plugin; + } + + @Override + public void visit(String name, Object value) { + switch (name) { + case "maven": + maven = String.valueOf(value); + break; + case "mavenRepo": + mavenRepo = String.valueOf(value); + break; + case "url": + url = String.valueOf(value); + break; + } + super.visit(name, value); + } + + @Override + public void visitEnum(String name, String descriptor, String value) { + super.visitEnum(name, descriptor, value); + } + + @Override + public AnnotationVisitor visitAnnotation(String name, String descriptor) { + return new DependencyAnnotationVisitor(plugin, super.visitAnnotation(name, descriptor)); + } + + @Override + public AnnotationVisitor visitArray(String name) { + return new DependencyAnnotationVisitor(plugin, super.visitArray(name)); + } + + @Override + public void visitEnd() { + if (maven != null) { + if (TDependency.requestLib(maven, mavenRepo, url)) { + TabooLibAPI.debug(" Loaded " + String.join(":", maven) + " (" + plugin.getName() + ")"); + } else { + TabooLib.getLogger().warn(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("DEPENDENCY-LOAD-FAIL"), plugin.getName(), String.join(":", maven))); + } + maven = null; + mavenRepo = TDependency.MAVEN_REPO; + url = ""; + } + super.visitEnd(); + } +} diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/DependencyClassVisitor.java b/src/main/scala/io/izzel/taboolib/module/dependency/DependencyClassVisitor.java new file mode 100644 index 0000000..b3d4192 --- /dev/null +++ b/src/main/scala/io/izzel/taboolib/module/dependency/DependencyClassVisitor.java @@ -0,0 +1,25 @@ +package io.izzel.taboolib.module.dependency; + +import org.bukkit.plugin.Plugin; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; + +/** + * @Author sky + * @Since 2019-7-13 15:17 + */ +public class DependencyClassVisitor extends ClassVisitor { + + private Plugin plugin; + + public DependencyClassVisitor(Plugin plugin, ClassVisitor classVisitor) { + super(Opcodes.ASM5, classVisitor); + this.plugin = plugin; + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + return new DependencyAnnotationVisitor(plugin, super.visitAnnotation(descriptor, visible)); + } +} diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyInjector.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyInjector.java index f38b6db..54c93b8 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyInjector.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyInjector.java @@ -1,40 +1,31 @@ package io.izzel.taboolib.module.dependency; -import io.izzel.taboolib.TabooLib; -import io.izzel.taboolib.TabooLibAPI; -import io.izzel.taboolib.util.Strings; +import io.izzel.taboolib.util.Files; import org.bukkit.plugin.Plugin; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; /** * @author Izzel_Aliz */ public class TDependencyInjector { - public static Dependency[] getDependencies(Class clazz) { - Dependency[] dependencies = new Dependency[0]; - Dependencies d = clazz.getAnnotation(Dependencies.class); - if (d != null) { - dependencies = d.value(); - } - Dependency d2 = clazz.getAnnotation(Dependency.class); - if (d2 != null) { - dependencies = new Dependency[] {d2}; - } - return dependencies; - } + private static boolean libInjected; public static void inject(Plugin plugin, Class clazz) { - inject(plugin.getName(), clazz); - } - - public static void inject(String name, Class clazz) { - for (Dependency dependency : getDependencies(clazz)) { - if (dependency.type() == Dependency.Type.LIBRARY) { - if (TDependency.requestLib(dependency.maven(), dependency.mavenRepo(), dependency.url())) { - TabooLibAPI.debug(" Loaded " + String.join(":", dependency.maven()) + " (" + name + ")"); - } else { - TabooLib.getLogger().warn(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("DEPENDENCY-LOAD-FAIL"), name, String.join(":", dependency.maven()))); - } + if (!plugin.getName().equals("TabooLib") || !libInjected) { + try { + ClassReader classReader = new ClassReader(Files.getResource(plugin, clazz.getName().replace(".", "/") + ".class")); + ClassWriter classWriter = new ClassWriter(0); + ClassVisitor classVisitor = new DependencyClassVisitor(plugin, classWriter); + classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES); + classWriter.visitEnd(); + classVisitor.visitEnd(); + } catch (Throwable t) { + t.printStackTrace(); + } finally { + libInjected = true; } } } diff --git a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java index 3818b07..0dd9f9f 100644 --- a/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/dependency/TDependencyLoader.java @@ -1,5 +1,6 @@ package io.izzel.taboolib.module.dependency; +import io.izzel.taboolib.common.plugin.InternalPlugin; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; @@ -16,7 +17,7 @@ public class TDependencyLoader { try { Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); method.setAccessible(true); - method.invoke(Bukkit.class.getClassLoader(), url); + method.invoke(plugin instanceof InternalPlugin ? Bukkit.class.getClassLoader() : plugin.getClass().getClassLoader(), url); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } @@ -29,5 +30,4 @@ public class TDependencyLoader { e.printStackTrace(); } } - } diff --git a/src/main/scala/io/izzel/taboolib/module/lite/SimpleClassVisitor.java b/src/main/scala/io/izzel/taboolib/module/lite/SimpleClassVisitor.java index 1cd94fe..af5a310 100644 --- a/src/main/scala/io/izzel/taboolib/module/lite/SimpleClassVisitor.java +++ b/src/main/scala/io/izzel/taboolib/module/lite/SimpleClassVisitor.java @@ -1,9 +1,6 @@ package io.izzel.taboolib.module.lite; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; +import org.objectweb.asm.*; import java.util.stream.IntStream;