配置文件及文件监听变化
This commit is contained in:
		@@ -4,6 +4,7 @@ import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import com.ilummc.tlib.annotations.Dependency;
 | 
			
		||||
import com.ilummc.tlib.annotations.Logger;
 | 
			
		||||
import com.ilummc.tlib.inject.DependencyInjector;
 | 
			
		||||
import com.ilummc.tlib.inject.TConfigWatcher;
 | 
			
		||||
import com.ilummc.tlib.inject.TLibPluginManager;
 | 
			
		||||
import com.ilummc.tlib.util.TLogger;
 | 
			
		||||
import me.skymc.taboolib.Main;
 | 
			
		||||
@@ -23,6 +24,8 @@ public class TLib {
 | 
			
		||||
 | 
			
		||||
    private TLibConfig config;
 | 
			
		||||
 | 
			
		||||
    private TConfigWatcher configWatcher = new TConfigWatcher();
 | 
			
		||||
 | 
			
		||||
    private TLib() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +37,10 @@ public class TLib {
 | 
			
		||||
        return tLogger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TConfigWatcher getConfigWatcher() {
 | 
			
		||||
        return configWatcher;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static TLib getTLib() {
 | 
			
		||||
        return tLib;
 | 
			
		||||
    }
 | 
			
		||||
@@ -55,8 +62,13 @@ public class TLib {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Config(name = "tlib.yml")
 | 
			
		||||
    public class TLibConfig {
 | 
			
		||||
    public static void unload() {
 | 
			
		||||
        tLib.getConfigWatcher().unregisterAll();
 | 
			
		||||
        DependencyInjector.eject(Main.getInst(), tLib);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Config(name = "tlib.yml", listenChanges = true)
 | 
			
		||||
    public static class TLibConfig {
 | 
			
		||||
 | 
			
		||||
        private int downloadPoolSize = 4;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@ import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
 | 
			
		||||
public class DependencyInjector {
 | 
			
		||||
@@ -24,7 +26,26 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static void onDisable(Plugin plugin) {
 | 
			
		||||
        ejectConfig(plugin, plugin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void eject(Plugin plugin, Object o) {
 | 
			
		||||
        ejectConfig(plugin, o);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void ejectConfig(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
            Config config;
 | 
			
		||||
            if ((config = field.getType().getAnnotation(Config.class)) != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    field.setAccessible(true);
 | 
			
		||||
                    TConfigInjector.saveConfig(plugin, o);
 | 
			
		||||
                    TLib.getTLib().getLogger().info("插件 " + plugin + " 的配置 " + config.name() + " 已保存");
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置 " + config.name() + " 保存失败");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectConfig(Plugin plugin, Object o) {
 | 
			
		||||
@@ -37,6 +58,25 @@ public class DependencyInjector {
 | 
			
		||||
                    if (obj != null) {
 | 
			
		||||
                        TLib.getTLib().getLogger().info("插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件成功加载");
 | 
			
		||||
                        field.set(o, obj);
 | 
			
		||||
                        if (config.listenChanges()) {
 | 
			
		||||
                            TLib.getTLib().getLogger().info("开始监听插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件");
 | 
			
		||||
                            TLib.getTLib().getConfigWatcher().addOnListen(
 | 
			
		||||
                                    new File(plugin.getDataFolder(), config.name()),
 | 
			
		||||
                                    obj,
 | 
			
		||||
                                    object -> {
 | 
			
		||||
                                        try {
 | 
			
		||||
                                            Object newObj = TConfigInjector.loadConfig(plugin, object.getClass());
 | 
			
		||||
                                            for (Field f : newObj.getClass().getDeclaredFields()) {
 | 
			
		||||
                                                f.setAccessible(true);
 | 
			
		||||
                                                f.set(obj, f.get(newObj));
 | 
			
		||||
                                            }
 | 
			
		||||
                                            TLib.getTLib().getLogger().info("插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件成功重载");
 | 
			
		||||
                                        } catch (Exception ignored) {
 | 
			
		||||
                                            TLib.getTLib().getLogger().warn("插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件重载时发生错误");
 | 
			
		||||
                                        }
 | 
			
		||||
                                    }
 | 
			
		||||
                            );
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (IllegalAccessException ignored) {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import com.ilummc.tlib.bean.Property;
 | 
			
		||||
import org.apache.commons.lang3.Validate;
 | 
			
		||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
 | 
			
		||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
import org.yaml.snakeyaml.DumperOptions;
 | 
			
		||||
import org.yaml.snakeyaml.Yaml;
 | 
			
		||||
@@ -17,9 +18,7 @@ import org.yaml.snakeyaml.Yaml;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Array;
 | 
			
		||||
import java.lang.reflect.Constructor;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
@@ -50,7 +49,7 @@ public class TConfigInjector {
 | 
			
		||||
                    .create().fromJson(new Gson().toJson(new Yaml()
 | 
			
		||||
                            .dump(Files.toString(new File(plugin.getDataFolder(), config.name()), Charset.forName(config.charset())))), clazz);
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解或文件不存在");
 | 
			
		||||
            return null;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            try {
 | 
			
		||||
@@ -62,28 +61,24 @@ public class TConfigInjector {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Map<String, Object> serialize(Plugin plugin, Class<?> clazz) {
 | 
			
		||||
    public static Map<String, Object> serialize(Plugin plugin, Object object) {
 | 
			
		||||
        try {
 | 
			
		||||
            Constructor constructor = clazz.getConstructor();
 | 
			
		||||
            constructor.setAccessible(true);
 | 
			
		||||
            Config config = clazz.getAnnotation(Config.class);
 | 
			
		||||
            Config config = object.getClass().getAnnotation(Config.class);
 | 
			
		||||
            Validate.notNull(config);
 | 
			
		||||
            return new Serializer(new LinkedHashMap<>(), constructor.newInstance(), config.excludeModifiers()).get();
 | 
			
		||||
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败:没有无参构造方法");
 | 
			
		||||
            return new Serializer(new LinkedHashMap<>(), object, config.excludeModifiers()).get();
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败:没有 @Config 注解");
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + object.getClass().getSimpleName() + " 序列化失败:没有 @Config 注解");
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败");
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + object.getClass().getSimpleName() + " 序列化失败");
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void saveConfig(Plugin plugin, Class<?> clazz) throws IOException, NullPointerException {
 | 
			
		||||
        Object obj = serialize(plugin, clazz);
 | 
			
		||||
        Validate.notNull(obj);
 | 
			
		||||
        Config config = clazz.getAnnotation(Config.class);
 | 
			
		||||
    public static void saveConfig(Plugin plugin, Object object) throws IOException, NullPointerException {
 | 
			
		||||
        Config config = object.getClass().getAnnotation(Config.class);
 | 
			
		||||
        Validate.notNull(config);
 | 
			
		||||
        Object obj = serialize(plugin, object);
 | 
			
		||||
        Validate.notNull(obj);
 | 
			
		||||
        File target = new File(plugin.getDataFolder(), config.name());
 | 
			
		||||
        if (!target.exists()) target.createNewFile();
 | 
			
		||||
        DumperOptions options = new DumperOptions();
 | 
			
		||||
@@ -143,7 +138,8 @@ public class TConfigInjector {
 | 
			
		||||
                    return map;
 | 
			
		||||
                } else if (o instanceof ConfigurationSerializable) {
 | 
			
		||||
                    Map map = new LinkedHashMap();
 | 
			
		||||
                    map.put("==", o.getClass().getName());
 | 
			
		||||
                    map.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY,
 | 
			
		||||
                            ConfigurationSerialization.getAlias((Class<? extends ConfigurationSerializable>) o.getClass()));
 | 
			
		||||
                    map.putAll(((ConfigurationSerializable) o).serialize());
 | 
			
		||||
                    return map;
 | 
			
		||||
                } else if (o instanceof Property) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								src/main/java/com/ilummc/tlib/inject/TConfigWatcher.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/main/java/com/ilummc/tlib/inject/TConfigWatcher.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
package com.ilummc.tlib.inject;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
import org.apache.commons.lang3.tuple.Triple;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.*;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
import java.util.concurrent.ScheduledExecutorService;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
public class TConfigWatcher {
 | 
			
		||||
 | 
			
		||||
    private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
 | 
			
		||||
 | 
			
		||||
    private Map<WatchService, Triple<File, Object, Consumer<Object>>> map = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    public TConfigWatcher() {
 | 
			
		||||
        service.scheduleAtFixedRate(() -> {
 | 
			
		||||
            map.forEach((service, triple) -> {
 | 
			
		||||
                WatchKey key;
 | 
			
		||||
                while ((key = service.poll()) != null) {
 | 
			
		||||
                    for (WatchEvent<?> watchEvent : key.pollEvents()) {
 | 
			
		||||
                        if (triple.getLeft().getName().equals(Objects.toString(watchEvent.context())))
 | 
			
		||||
                            triple.getRight().accept(triple.getMiddle());
 | 
			
		||||
                    }
 | 
			
		||||
                    key.reset();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }, 1000, 100, TimeUnit.MILLISECONDS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addOnListen(File file, Object obj, Consumer<Object> consumer) {
 | 
			
		||||
        try {
 | 
			
		||||
            WatchService service = FileSystems.getDefault().newWatchService();
 | 
			
		||||
            file.getParentFile().toPath().register(service, StandardWatchEventKinds.ENTRY_MODIFY);
 | 
			
		||||
            map.put(service, Triple.of(file, obj, consumer));
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void unregisterAll() {
 | 
			
		||||
        service.shutdown();
 | 
			
		||||
        map.forEach((service, pair) -> {
 | 
			
		||||
            try {
 | 
			
		||||
                service.close();
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package com.ilummc.tlib.inject;
 | 
			
		||||
 | 
			
		||||
import me.skymc.taboolib.Main;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.event.Event;
 | 
			
		||||
import org.bukkit.event.EventPriority;
 | 
			
		||||
@@ -15,6 +16,8 @@ public class TLibPluginManager implements PluginManager {
 | 
			
		||||
 | 
			
		||||
    private final PluginManager instance;
 | 
			
		||||
 | 
			
		||||
    private final Main main = (Main) Main.getInst();
 | 
			
		||||
 | 
			
		||||
    public TLibPluginManager() {
 | 
			
		||||
        instance = Bukkit.getPluginManager();
 | 
			
		||||
    }
 | 
			
		||||
@@ -56,7 +59,10 @@ public class TLibPluginManager implements PluginManager {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void disablePlugins() {
 | 
			
		||||
        instance.disablePlugins();
 | 
			
		||||
        for (Plugin plugin : getPlugins()) {
 | 
			
		||||
            if (plugin != main) disablePlugin(plugin);
 | 
			
		||||
        }
 | 
			
		||||
        disablePlugin(main);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -26,37 +26,37 @@ public class TLogger {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void verbose(String msg) {
 | 
			
		||||
        if (level >= VERBOSE)
 | 
			
		||||
        if (level <= VERBOSE)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§f全部", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void finest(String msg) {
 | 
			
		||||
        if (level >= FINEST)
 | 
			
		||||
        if (level <= FINEST)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§e良好", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void fine(String msg) {
 | 
			
		||||
        if (level >= FINE)
 | 
			
		||||
        if (level <= FINE)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§a正常", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void info(String msg) {
 | 
			
		||||
        if (level >= INFO)
 | 
			
		||||
        if (level <= INFO)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§b信息", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void warn(String msg) {
 | 
			
		||||
        if (level >= WARN)
 | 
			
		||||
        if (level <= WARN)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§6警告", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void error(String msg) {
 | 
			
		||||
        if (level >= ERROR)
 | 
			
		||||
        if (level <= ERROR)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§c错误", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void fatal(String msg) {
 | 
			
		||||
        if (level >= FATAL)
 | 
			
		||||
        if (level <= FATAL)
 | 
			
		||||
            Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§4致命错误", msg));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -275,6 +275,8 @@ public class Main extends JavaPlugin implements Listener {
 | 
			
		||||
			connection.closeConnection();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		TLib.unload();
 | 
			
		||||
		
 | 
			
		||||
		// 关闭服务器
 | 
			
		||||
		Bukkit.shutdown();
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user