diff --git a/build.gradle b/build.gradle index 99838c6..44553d4 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'me.skymc' -version = '5.1' +version = '5.11' sourceCompatibility = 1.8 targetCompatibility = 1.8 diff --git a/src/main/resources/__resources__/lang/zh_CN.yml b/src/main/resources/__resources__/lang/zh_CN.yml index 4ecf5ae..1f4de7e 100644 --- a/src/main/resources/__resources__/lang/zh_CN.yml +++ b/src/main/resources/__resources__/lang/zh_CN.yml @@ -12,13 +12,6 @@ MISC: FIELD-COPY-FAILED: '拷贝 {0} 对象失败' FIELD-COPY-ERROR: '拷贝 {0} 对象出错:{1}' -ITEM-UTILS: - FAIL-LOAD-ATTRIBUTE: '&c{0} &4不是一个有效的属性名称, 输入 &c/tlib attributes&4 查看所有属性' - FAIL-LOAD-ENCHANT: '&c{0} &4不是一个有效的附魔名称, 输入 &c/tlib enchants&4 查看所有附魔' - FAIL-LOAD-POTION: '&c{0} &4不是一个有效的药水名称, 输入 &c/tlib potions&4 查看所有药水' - FAIL-LOAD-FLAG: '&c{0} &4不是一个有效的标签名称, 输入 &c/tlib flags&4 查看所有标签' - FAIL-SAVE-EXISTS: '无法载入载入物品 &4{0}&c, 因为它已经存在了' - MYSQL-HIKARI: CREATE-SUCCESS: '&7插件 &f{0} &7注册新的连接池: &f{1}' CREATE-EXISTS: '&7插件 &f{0} &7引用插件 &f{1} &7注册的连接池.' diff --git a/src/main/scala/io/izzel/taboolib/TabooLib.java b/src/main/scala/io/izzel/taboolib/TabooLib.java index 9361651..5742a5a 100644 --- a/src/main/scala/io/izzel/taboolib/TabooLib.java +++ b/src/main/scala/io/izzel/taboolib/TabooLib.java @@ -5,7 +5,6 @@ import io.izzel.taboolib.module.config.TConfig; import io.izzel.taboolib.module.config.TConfigWatcher; import io.izzel.taboolib.module.db.local.Local; import io.izzel.taboolib.module.db.local.LocalPlayer; -import io.izzel.taboolib.module.db.source.DBSource; import io.izzel.taboolib.module.dependency.Dependency; import io.izzel.taboolib.module.locale.TLocaleLoader; import io.izzel.taboolib.module.locale.logger.TLogger; @@ -82,8 +81,6 @@ public class TabooLib { LocalPlayer.saveFiles(); // 关闭文件监听 TConfigWatcher.getInst().unregisterAll(); - // 关闭连接池 - DBSource.closeDataSourceForce(); // 关闭插件 PluginLoader.stop(getPlugin()); }); diff --git a/src/main/scala/io/izzel/taboolib/compat/kotlin/CompatKotlin.java b/src/main/scala/io/izzel/taboolib/compat/kotlin/CompatKotlin.java index 3682f29..ae085bb 100644 --- a/src/main/scala/io/izzel/taboolib/compat/kotlin/CompatKotlin.java +++ b/src/main/scala/io/izzel/taboolib/compat/kotlin/CompatKotlin.java @@ -16,8 +16,7 @@ public class CompatKotlin { public static Object getCompanion(Class pluginClass) { try { return Reflection.getValue(null, TabooLibAPI.getPluginBridge().getClass(pluginClass.getName().substring(0, pluginClass.getName().indexOf("$Companion"))), true, "Companion"); - } catch (Throwable t) { - t.printStackTrace(); + } catch (Throwable ignored) { } return null; } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectHelper.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectHelper.java index ed76371..92fbb02 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectHelper.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectHelper.java @@ -52,7 +52,7 @@ public class TInjectHelper { } } // Nothing - else if (instance.isEmpty()) { + if (instance.isEmpty()) { TLogger.getGlobalLogger().error(field.getName() + " is not a static field. (" + pluginClass.getName() + ")"); } return instance; @@ -60,22 +60,22 @@ public class TInjectHelper { public static List getInstance(Method method, Class pluginClass, Plugin plugin) { List instance = Lists.newArrayList(); - // Object - if (CompatKotlin.getInstance(pluginClass) != null) { - instance.add(CompatKotlin.getInstance(pluginClass)); - } - // Companion Object - else if (CompatKotlin.isCompanion(pluginClass)) { - instance.add(CompatKotlin.getCompanion(pluginClass)); - } // Static - else if (Modifier.isStatic(method.getModifiers())) { + if (Modifier.isStatic(method.getModifiers())) { instance.add(null); } // No Static else if (!Modifier.isStatic(method.getModifiers())) { + // Object + if (CompatKotlin.getInstance(pluginClass) != null) { + instance.add(CompatKotlin.getInstance(pluginClass)); + } + // Companion Object + else if (CompatKotlin.isCompanion(pluginClass)) { + instance.add(CompatKotlin.getCompanion(pluginClass)); + } // Main - if (pluginClass.equals(plugin.getClass())) { + else if (pluginClass.equals(plugin.getClass())) { instance.add(plugin); } // TInject @@ -84,7 +84,7 @@ public class TInjectHelper { } } // Nothing - else if (instance.isEmpty()) { + if (instance.isEmpty()) { TLogger.getGlobalLogger().error(method.getName() + " is not a static method. (" + pluginClass.getName() + ")"); } return instance; diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java index eae1ed6..383c5dd 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TInjectLoader.java @@ -16,7 +16,6 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.util.Map; /** @@ -59,17 +58,19 @@ public class TInjectLoader implements TabooLibLoader.Loader { field.set(instance, config); if (!args.reload().isEmpty()) { try { - Method declaredMethod = pluginClass.getDeclaredMethod(args.reload()); - declaredMethod.setAccessible(true); - config.listener(() -> { - try { - declaredMethod.invoke(instance); - } catch (Throwable t) { - t.printStackTrace(); + Ref.getDeclaredMethods(pluginClass).forEach(method -> { + if (method.getName().equals(args.reload())) { + method.setAccessible(true); + config.listener(() -> { + try { + method.invoke(instance); + } catch (Throwable t) { + t.printStackTrace(); + } + }); + TabooLibLoader.runTask(config::runListener); } }); - TabooLibLoader.runTask(config::runListener); - } catch (NoSuchMethodException ignore) { } catch (Throwable t) { t.printStackTrace(); } diff --git a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java index 2688428..09ca9bf 100644 --- a/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java +++ b/src/main/scala/io/izzel/taboolib/module/inject/TScheduleLoader.java @@ -4,6 +4,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import io.izzel.taboolib.TabooLib; import io.izzel.taboolib.TabooLibLoader; +import io.izzel.taboolib.util.Ref; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; @@ -63,7 +64,12 @@ public class TScheduleLoader implements TabooLibLoader.Loader { try { method.invoke(instance); } catch (Throwable t) { - t.printStackTrace(); + try { + method.invoke(Ref.UNSAFE.allocateInstance(pluginClass)); + } catch (Throwable t2) { + t.printStackTrace(); + t2.printStackTrace(); + } } } }))); diff --git a/src/main/scala/io/izzel/taboolib/module/locale/TLocale.java b/src/main/scala/io/izzel/taboolib/module/locale/TLocale.java index 31725b5..6150c1d 100644 --- a/src/main/scala/io/izzel/taboolib/module/locale/TLocale.java +++ b/src/main/scala/io/izzel/taboolib/module/locale/TLocale.java @@ -15,6 +15,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -32,80 +33,88 @@ public class TLocale { return Arrays.stream(obj).map(String::valueOf).toArray(String[]::new); } - static void sendTo(String path, CommandSender sender, String[] args, Class callerClass) { - TLocaleLoader.sendTo(Ref.getCallerPlugin(callerClass), path, sender, args); + static void sendTo0(Collection sender, String path, String... args) { + sender.forEach(i -> TLocaleLoader.sendTo(Ref.getCallerPlugin(), path, i, args)); } - static String asString(String path, Class callerClass, String... args) { - return TLocaleLoader.asString(Ref.getCallerPlugin(callerClass), path, args); + static String asString0(String path, String... args) { + try { + return TLocaleLoader.asString(Ref.getCallerPlugin(), path, args); + } catch (Exception e) { + TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); + TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); + return "§4Error: " + path; + } } - static List asStringList(String path, Class callerClass, String... args) { - return TLocaleLoader.asStringList(Ref.getCallerPlugin(callerClass), path, args); + static List asStringList0(String path, String... args) { + try { + return TLocaleLoader.asStringList(Ref.getCallerPlugin(), path, args); + } catch (Exception e) { + TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); + TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); + return Collections.singletonList("§4Error: " + path); + } } public static void sendTo(CommandSender sender, String path, Object... args) { - Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, toArray(args), clazz)); + sendTo0(Collections.singletonList(sender), path, toArray(args)); } public static void sendTo(CommandSender sender, String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz)); + sendTo0(Collections.singletonList(sender), path, args); + } + + public static void sendTo(CommandSender sender, String path) { + sendTo0(Collections.singletonList(sender), path); } public static void sendToConsole(String path, Object... args) { - Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), toArray(args), clazz)); + sendTo0(Collections.singletonList(Bukkit.getConsoleSender()), path, toArray(args)); } public static void sendToConsole(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), args, clazz)); + sendTo0(Collections.singletonList(Bukkit.getConsoleSender()), path, args); + } + + public static void sendToConsole(String path) { + sendTo0(Collections.singletonList(Bukkit.getConsoleSender()), path); } public static void broadcast(String path, Object... args) { - Ref.getCallerClass(3).ifPresent(clazz -> Bukkit.getOnlinePlayers().forEach(player -> sendTo(path, player, toArray(args), clazz))); + sendTo0(Bukkit.getOnlinePlayers(), path, toArray(args)); } public static void broadcast(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> Bukkit.getOnlinePlayers().forEach(player -> sendTo(path, player, args, clazz))); + sendTo0(Bukkit.getOnlinePlayers(), path, args); + } + + public static void broadcast(String path) { + sendTo0(Bukkit.getOnlinePlayers(), path); } public static String asString(String path, Object... args) { - try { - return asString(path, Ref.getCallerClass(3).orElse(TabooLib.class), toArray(args)); - } catch (Exception e) { - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); - return "§4<" + path + "§4>"; - } + return asString0(path, toArray(args)); } public static String asString(String path, String... args) { - try { - return asString(path, Ref.getCallerClass(3).orElse(TabooLib.class), args); - } catch (Exception e) { - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); - return "§4<" + path + "§4>"; - } + return asString0(path, args); + } + + public static String asString(String path) { + return asString0(path); } public static List asStringList(String path, Object... args) { - try { - return asStringList(path, Ref.getCallerClass(3).orElse(TabooLib.class), toArray(args)); - } catch (Exception e) { - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); - return Collections.singletonList("§4<" + path + "§4>"); - } + return asStringList0(path, toArray(args)); } public static List asStringList(String path, String... args) { - try { - return asStringList(path, Ref.getCallerClass(3).orElse(TabooLib.class), args); - } catch (Exception e) { - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("FETCH-LOCALE-ERROR"), path)); - TabooLib.getLogger().error(Strings.replaceWithOrder(TabooLib.getInst().getInternal().getString("LOCALE-ERROR-REASON"), e.getMessage())); - return Collections.singletonList("§4<" + path + "§4>"); - } + return asStringList0(path, args); + } + + public static List asStringList(String path) { + return asStringList0(path); } public static void reload() { @@ -176,31 +185,31 @@ public class TLocale { public static final class Logger extends TLocale { public static void info(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).info(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).info(locale)); } public static void warn(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).warn(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).warn(locale)); } public static void error(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).error(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).error(locale)); } public static void fatal(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).fatal(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).fatal(locale)); } public static void fine(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).fine(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).fine(locale)); } public static void finest(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).finest(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).finest(locale)); } public static void verbose(String path, String... args) { - Ref.getCallerClass(3).ifPresent(clazz -> asStringList(path, clazz, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin(clazz)).verbose(locale))); + asStringList(path, args).forEach(locale -> TLoggerManager.getLogger(Ref.getCallerPlugin()).verbose(locale)); } } } diff --git a/src/main/scala/io/izzel/taboolib/module/locale/TLocaleInstance.java b/src/main/scala/io/izzel/taboolib/module/locale/TLocaleInstance.java index 9d84a1d..e17765d 100644 --- a/src/main/scala/io/izzel/taboolib/module/locale/TLocaleInstance.java +++ b/src/main/scala/io/izzel/taboolib/module/locale/TLocaleInstance.java @@ -51,7 +51,7 @@ class TLocaleInstance { public void sendTo(String path, CommandSender sender, String... args) { try { - map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).forEach(tSender -> { + map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(plugin, path))).forEach(tSender -> { if (Bukkit.isPrimaryThread() || Objects.equals(System.getProperty("tlib.forceAsync"), "true")) { tSender.sendTo(sender, args); } else { @@ -65,11 +65,11 @@ class TLocaleInstance { } public String asString(String path, String... args) { - return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).get(0).asString(args); + return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(plugin, path))).get(0).asString(args); } public List asStringList(String path, String... args) { - return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(path))).get(0).asStringList(args); + return map.getOrDefault(path, ImmutableList.of(TLocaleSerialize.getEmpty(plugin, path))).get(0).asStringList(args); } private static boolean isListString(List list) { diff --git a/src/main/scala/io/izzel/taboolib/module/locale/TLocaleSerialize.java b/src/main/scala/io/izzel/taboolib/module/locale/TLocaleSerialize.java index 7f3b662..51decd7 100644 --- a/src/main/scala/io/izzel/taboolib/module/locale/TLocaleSerialize.java +++ b/src/main/scala/io/izzel/taboolib/module/locale/TLocaleSerialize.java @@ -1,7 +1,10 @@ package io.izzel.taboolib.module.locale; +import io.izzel.taboolib.TabooLib; +import io.izzel.taboolib.TabooLibAPI; import org.bukkit.command.CommandSender; import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.plugin.Plugin; import java.util.Collections; import java.util.List; @@ -47,7 +50,7 @@ public abstract class TLocaleSerialize implements TLocaleSender, ConfigurationSe }; } - static TLocaleSerialize getEmpty(String path) { + static TLocaleSerialize getEmpty(Plugin plugin, String path) { return new TLocaleSerialize() { @Override @@ -57,17 +60,29 @@ public abstract class TLocaleSerialize implements TLocaleSender, ConfigurationSe @Override public void sendTo(CommandSender sender, String... args) { - sender.sendMessage("§8<" + path + "§8>"); + if (TabooLibAPI.isDependTabooLib(plugin)) { + TLocaleLoader.sendTo(TabooLib.getPlugin(), path, sender, args); + } else { + sender.sendMessage("§8Notfound: " + path); + } } @Override public String asString(String... args) { - return "§8<" + path + "§8>"; + if (TabooLibAPI.isDependTabooLib(plugin)) { + return TLocaleLoader.asString(TabooLib.getPlugin(), path, args); + } else { + return "§8Notfound: " + path; + } } @Override public List asStringList(String... args) { - return Collections.singletonList("§4<" + path + "§4>"); + if (TabooLibAPI.isDependTabooLib(plugin)) { + return TLocaleLoader.asStringList(TabooLib.getPlugin(), path, args); + } else { + return Collections.singletonList("§8Notfound: " + path); + } } }; } diff --git a/src/main/scala/io/izzel/taboolib/module/locale/logger/TLogger.java b/src/main/scala/io/izzel/taboolib/module/locale/logger/TLogger.java index f74b152..f29f29c 100644 --- a/src/main/scala/io/izzel/taboolib/module/locale/logger/TLogger.java +++ b/src/main/scala/io/izzel/taboolib/module/locale/logger/TLogger.java @@ -33,11 +33,11 @@ public class TLogger { } public static TLogger getUnformatted(Plugin plugin) { - return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", plugin, TLogger.FINE); + return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", plugin, TLogger.VERBOSE); } public static TLogger getUnformatted(String name) { - return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", name, TLogger.FINE); + return new TLogger("§8[§3§l{0}§8][§r{1}§8] §f{2}", name, TLogger.VERBOSE); } public String getPattern() { diff --git a/src/main/scala/io/izzel/taboolib/module/locale/logger/TLoggerManager.java b/src/main/scala/io/izzel/taboolib/module/locale/logger/TLoggerManager.java index 0522804..f2dbdf1 100644 --- a/src/main/scala/io/izzel/taboolib/module/locale/logger/TLoggerManager.java +++ b/src/main/scala/io/izzel/taboolib/module/locale/logger/TLoggerManager.java @@ -2,23 +2,14 @@ package io.izzel.taboolib.module.locale.logger; import org.bukkit.plugin.Plugin; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class TLoggerManager { - private static final Map map = new HashMap<>(); - - public static void setDefaultLogger(Plugin plugin, TLogger logger) { - map.put(plugin, logger); - } + private static final Map map = new ConcurrentHashMap<>(); public static TLogger getLogger(Plugin plugin) { - TLogger logger = map.get(plugin); - if (logger == null) { - logger = TLogger.getUnformatted(plugin); - map.put(plugin, logger); - } - return logger; + return map.computeIfAbsent(plugin.getName(), n -> TLogger.getUnformatted(plugin)); } } diff --git a/src/main/scala/io/izzel/taboolib/util/Ref.java b/src/main/scala/io/izzel/taboolib/util/Ref.java index ca8f123..20a06d6 100644 --- a/src/main/scala/io/izzel/taboolib/util/Ref.java +++ b/src/main/scala/io/izzel/taboolib/util/Ref.java @@ -2,15 +2,18 @@ package io.izzel.taboolib.util; import com.google.gson.annotations.SerializedName; import io.izzel.taboolib.TabooLib; +import io.izzel.taboolib.TabooLibAPI; import io.izzel.taboolib.util.asm.AsmAnalyser; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; +import sun.misc.Unsafe; import sun.reflect.Reflection; import javax.annotation.concurrent.ThreadSafe; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -20,9 +23,21 @@ import java.util.stream.Collectors; public class Ref { private static final Map> cachedFields = new ConcurrentHashMap<>(); + private static final Map> cacheMethods = new ConcurrentHashMap<>(); + private static final Map cachePlugin = new ConcurrentHashMap<>(); public static final int ACC_BRIDGE = 0x0040; public static final int ACC_SYNTHETIC = 0x1000; + public static final Unsafe UNSAFE = getUnsafe(); + + static Unsafe getUnsafe() { + try { + return (Unsafe) io.izzel.taboolib.util.Reflection.getValue(null, Unsafe.class, true, "theUnsafe"); + } catch (Throwable t) { + t.printStackTrace(); + } + return null; + } public static List getDeclaredFields(Class clazz) { return getDeclaredFields(clazz, 0, true); @@ -68,6 +83,50 @@ public class Ref { } } + public static List getDeclaredMethods(Class clazz) { + return getDeclaredMethods(clazz, 0, true); + } + + public static List getDeclaredMethods(String clazz, int excludeModifiers, boolean cache) { + try { + return getDeclaredMethods(Class.forName(clazz), excludeModifiers, cache); + } catch (ClassNotFoundException e) { + return Collections.emptyList(); + } + } + + public static List getDeclaredMethods(Class clazz, int excludeModifiers, boolean cache) { + try { + List methods; + if ((methods = cacheMethods.get(clazz.getName())) != null) { + return methods; + } + 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); + methods = analyser.getMethods().stream().map(name -> { + try { + return clazz.getDeclaredMethod(name); + } catch (Throwable ignored) { + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + if (cache) { + cacheMethods.putIfAbsent(clazz.getName(), methods); + } + return methods; + } catch (Exception | Error e) { + try { + List list = Arrays.stream(clazz.getDeclaredMethods()) + .filter(field -> (field.getModifiers() & excludeModifiers) == 0).collect(Collectors.toList()); + cacheMethods.putIfAbsent(clazz.getName(), list); + return list; + } catch (Error err) { + return Collections.emptyList(); + } + } + } + public static Optional> getCallerClass(int depth) { return Optional.ofNullable(CallerClass.impl.getCallerClass(depth + 1)); } @@ -93,23 +152,43 @@ public class Ref { return Optional.empty(); } + public static Plugin getCallerPlugin() { + return getCallerPlugin(getCallerClass()); + } + public static Plugin getCallerPlugin(Class callerClass) { if (callerClass.getName().startsWith("io.izzel.taboolib") || callerClass.getName().startsWith("io.izzel.tlibscala")) { return TabooLib.getPlugin(); } try { - return JavaPlugin.getProvidingPlugin(callerClass); + return cachePlugin.computeIfAbsent(callerClass.getName(), n -> JavaPlugin.getProvidingPlugin(callerClass)); } catch (Exception ignored) { + return cachePlugin.computeIfAbsent(callerClass.getName(), n -> { + try { + ClassLoader loader = callerClass.getClassLoader(); + Field pluginF = loader.getClass().getDeclaredField("plugin"); + pluginF.setAccessible(true); + Object o = pluginF.get(loader); + return (JavaPlugin) o; + } catch (Exception e) { + return TabooLib.getPlugin(); + } + }); + } + } + + public static Class getCallerClass() { + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + for (StackTraceElement element : elements) { try { - ClassLoader loader = callerClass.getClassLoader(); - Field pluginF = loader.getClass().getDeclaredField("plugin"); - pluginF.setAccessible(true); - Object o = pluginF.get(loader); - return (JavaPlugin) o; - } catch (Exception e) { - return TabooLib.getPlugin(); + Class clazz = TabooLibAPI.getPluginBridge().getClass(element.getClassName()); + if (TabooLibAPI.isDependTabooLib(getCallerPlugin(clazz))) { + return clazz; + } + } catch (Throwable ignored) { } } + return TabooLib.class; } public static void forcedAccess(Field field) { @@ -160,5 +239,4 @@ public class Ref { } } } - } diff --git a/src/main/scala/io/izzel/taboolib/util/asm/AsmAnalyser.java b/src/main/scala/io/izzel/taboolib/util/asm/AsmAnalyser.java index e1a81e2..088c7e4 100644 --- a/src/main/scala/io/izzel/taboolib/util/asm/AsmAnalyser.java +++ b/src/main/scala/io/izzel/taboolib/util/asm/AsmAnalyser.java @@ -2,6 +2,7 @@ package io.izzel.taboolib.util.asm; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import java.util.ArrayList; @@ -10,6 +11,7 @@ import java.util.List; public class AsmAnalyser extends ClassVisitor implements Opcodes { private final List fields = new ArrayList<>(); + private final List methods = new ArrayList<>(); private final int excludeModifier; @@ -26,7 +28,19 @@ public class AsmAnalyser extends ClassVisitor implements Opcodes { return super.visitField(access, name, descriptor, signature, value); } + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + if ((access & excludeModifier) == 0) { + methods.add(name); + } + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + public List getFields() { return fields; } + + public List getMethods() { + return methods; + } }