diff --git a/src/main/java/com/ilummc/tlib/TLib.java b/src/main/java/com/ilummc/tlib/TLib.java index 0273481..62261f6 100644 --- a/src/main/java/com/ilummc/tlib/TLib.java +++ b/src/main/java/com/ilummc/tlib/TLib.java @@ -14,7 +14,8 @@ import java.io.File; import java.lang.reflect.Field; @Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1") -@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.0.0") +@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0") +@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25") public class TLib { private static TLib tLib; diff --git a/src/main/java/com/ilummc/tlib/annotations/Config.java b/src/main/java/com/ilummc/tlib/annotations/Config.java index 03b792a..b4ebd42 100644 --- a/src/main/java/com/ilummc/tlib/annotations/Config.java +++ b/src/main/java/com/ilummc/tlib/annotations/Config.java @@ -1,5 +1,7 @@ package com.ilummc.tlib.annotations; +import com.ilummc.tlib.util.Ref; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -20,6 +22,6 @@ public @interface Config { boolean listenChanges() default false; - int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT; + int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT | Ref.ACC_SYNTHETIC | Ref.ACC_BRIDGE; } diff --git a/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java b/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java index 8c32a5d..04b4030 100644 --- a/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java +++ b/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java @@ -3,6 +3,7 @@ package com.ilummc.tlib.inject; import com.ilummc.tlib.TLib; import com.ilummc.tlib.annotations.*; import com.ilummc.tlib.dependency.TDependency; +import com.ilummc.tlib.util.Ref; import com.ilummc.tlib.util.TLogger; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; @@ -14,22 +15,10 @@ import java.lang.reflect.Field; public class DependencyInjector { public static void inject(Plugin plugin, Object o) { - try { - injectLogger(plugin, o); - } catch (NoClassDefFoundError ignored) { - } - try { - injectConfig(plugin, o); - } catch (NoClassDefFoundError ignored) { - } - try { - injectPluginInstance(plugin, o); - } catch (NoClassDefFoundError ignored) { - } - try { - injectDependencies(plugin, o); - } catch (NoClassDefFoundError ignored) { - } + injectLogger(plugin, o); + injectConfig(plugin, o); + injectPluginInstance(plugin, o); + injectDependencies(plugin, o); } static void injectOnEnable(Plugin plugin) { @@ -48,7 +37,7 @@ public class DependencyInjector { } private static void ejectConfig(Plugin plugin, Object o) { - for (Field field : o.getClass().getDeclaredFields()) { + for (Field field : Ref.getDeclaredFields(o.getClass())) { Config config; if ((config = field.getType().getAnnotation(Config.class)) != null) { try { @@ -64,7 +53,7 @@ public class DependencyInjector { } private static void injectConfig(Plugin plugin, Object o) { - for (Field field : o.getClass().getDeclaredFields()) { + for (Field field : Ref.getDeclaredFields(o.getClass())) { try { Config config; if ((config = field.getType().getAnnotation(Config.class)) != null) { @@ -100,7 +89,7 @@ public class DependencyInjector { } private static void injectLogger(Plugin plugin, Object o) { - for (Field field : o.getClass().getDeclaredFields()) { + for (Field field : Ref.getDeclaredFields(o.getClass())) { try { Logger logger; if ((logger = field.getAnnotation(Logger.class)) != null) { @@ -116,7 +105,7 @@ public class DependencyInjector { } private static void injectPluginInstance(Plugin plugin, Object o) { - for (Field field : o.getClass().getDeclaredFields()) { + for (Field field : Ref.getDeclaredFields(o.getClass())) { try { PluginInstance instance; if ((instance = field.getAnnotation(PluginInstance.class)) != null) { diff --git a/src/main/java/com/ilummc/tlib/inject/TLibPluginManager.java b/src/main/java/com/ilummc/tlib/inject/TLibPluginManager.java index 3d92b66..42f640d 100644 --- a/src/main/java/com/ilummc/tlib/inject/TLibPluginManager.java +++ b/src/main/java/com/ilummc/tlib/inject/TLibPluginManager.java @@ -49,9 +49,7 @@ public class TLibPluginManager implements PluginManager { @Override public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { - Plugin plugin = instance.loadPlugin(file); - DependencyInjector.injectOnEnable(plugin); - return plugin; + return instance.loadPlugin(file); } @Override @@ -94,6 +92,7 @@ public class TLibPluginManager implements PluginManager { @Override public void enablePlugin(Plugin plugin) { + DependencyInjector.injectOnEnable(plugin); instance.enablePlugin(plugin); } diff --git a/src/main/java/com/ilummc/tlib/util/IO.java b/src/main/java/com/ilummc/tlib/util/IO.java new file mode 100644 index 0000000..92d4d16 --- /dev/null +++ b/src/main/java/com/ilummc/tlib/util/IO.java @@ -0,0 +1,18 @@ +package com.ilummc.tlib.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class IO { + + public static byte[] readFully(InputStream inputStream) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int len = 0; + while ((len = inputStream.read(buf)) > 0) { + stream.write(buf, 0, len); + } + return stream.toByteArray(); + } +} diff --git a/src/main/java/com/ilummc/tlib/util/Ref.java b/src/main/java/com/ilummc/tlib/util/Ref.java new file mode 100644 index 0000000..218fa55 --- /dev/null +++ b/src/main/java/com/ilummc/tlib/util/Ref.java @@ -0,0 +1,59 @@ +package com.ilummc.tlib.util; + +import com.ilummc.tlib.util.asm.AsmAnalyser; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import javax.annotation.concurrent.ThreadSafe; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +@ThreadSafe +public class Ref { + + private static final Map> cachedFields = new ConcurrentHashMap<>(); + + public static final int ACC_BRIDGE = 0x0040; + public static final int ACC_SYNTHETIC = 0x1000; + + public static List getDeclaredFields(Class clazz) { + return getDeclaredFields(clazz, 0, false); + } + + public static List getDeclaredFields(String clazz, int excludeModifiers, boolean cache) { + try { + return getDeclaredFields(Class.forName(clazz), excludeModifiers, cache); + } catch (ClassNotFoundException e) { + return Collections.emptyList(); + } + } + + public static List getDeclaredFields(Class clazz, int excludeModifiers, boolean cache) { + try { + Class.forName("org.objectweb.asm.ClassVisitor"); + List fields; + if ((fields = cachedFields.get(clazz.getName())) != null) return fields; + ClassReader classReader = new ClassReader(clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class")); + AsmAnalyser analyser = new AsmAnalyser(new ClassWriter(ClassWriter.COMPUTE_MAXS), excludeModifiers); + classReader.accept(analyser, ClassReader.SKIP_DEBUG); + fields = analyser.getFields().stream().map(name -> { + try { + return clazz.getDeclaredField(name); + } catch (Throwable ignored) { + } + return null; + }).filter(Objects::nonNull).collect(Collectors.toList()); + if (cache) cachedFields.putIfAbsent(clazz.getName(), fields); + return fields; + } catch (Exception e) { + return Collections.emptyList(); + } + } + +} diff --git a/src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java b/src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java new file mode 100644 index 0000000..70d6937 --- /dev/null +++ b/src/main/java/com/ilummc/tlib/util/asm/AsmAnalyser.java @@ -0,0 +1,31 @@ +package com.ilummc.tlib.util.asm; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; + +import java.util.ArrayList; +import java.util.List; + +public class AsmAnalyser extends ClassVisitor implements Opcodes { + + private final List fields = new ArrayList<>(); + + private final int excludeModifier; + + public AsmAnalyser(ClassVisitor classVisitor, int excludeModifiers) { + super(Opcodes.ASM6, classVisitor); + this.excludeModifier = excludeModifiers; + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + if ((access & excludeModifier) == 0) + fields.add(name); + return super.visitField(access, name, descriptor, signature, value); + } + + public List getFields() { + return fields; + } +} diff --git a/src/main/java/me/skymc/taboolib/Main.java b/src/main/java/me/skymc/taboolib/Main.java index 7c5d3f7..cd6b530 100644 --- a/src/main/java/me/skymc/taboolib/Main.java +++ b/src/main/java/me/skymc/taboolib/Main.java @@ -51,21 +51,6 @@ import java.util.Random; @SuppressWarnings("deprecation") public class Main extends JavaPlugin implements Listener { - public Main() { - super(); - - inst = this; - disable = false; - - TLib.injectPluginManager(); - - // 载入配置 - saveDefaultConfig(); - - // 加载依赖 - TLib.init(); - } - @Getter private static Plugin inst; @Getter @@ -116,6 +101,17 @@ public class Main extends JavaPlugin implements Listener { @Override public void onLoad() { + inst = this; + disable = false; + + TLib.injectPluginManager(); + + // 载入配置 + saveDefaultConfig(); + + // 加载依赖 + TLib.init(); + // 载入目录 setupDataFolder(); // 注册配置