暂时不能用的 @Config
This commit is contained in:
		
							
								
								
									
										8
									
								
								.idea/dictionaries/csh20.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/dictionaries/csh20.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
<component name="ProjectDictionaryState">
 | 
			
		||||
  <dictionary name="csh20">
 | 
			
		||||
    <words>
 | 
			
		||||
      <w>unserialize</w>
 | 
			
		||||
      <w>unserializer</w>
 | 
			
		||||
    </words>
 | 
			
		||||
  </dictionary>
 | 
			
		||||
</component>
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
package com.ilummc.tlib;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import com.ilummc.tlib.annotations.ConfigNode;
 | 
			
		||||
import com.ilummc.tlib.bean.Property;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
@@ -9,7 +8,6 @@ import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
@Config(name = "cfg.yml", charset = "GBK")
 | 
			
		||||
public class ExampleMain extends JavaPlugin {
 | 
			
		||||
 | 
			
		||||
    @ConfigNode("enableUpdate")
 | 
			
		||||
    private Property<Boolean> update = Property.of(false);
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package com.ilummc.tlib;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import com.ilummc.tlib.annotations.Dependency;
 | 
			
		||||
import com.ilummc.tlib.annotations.Logger;
 | 
			
		||||
import com.ilummc.tlib.inject.DependencyInjector;
 | 
			
		||||
@@ -20,9 +21,15 @@ public class TLib {
 | 
			
		||||
    @Logger("§3[§6TLib§3|{1}§3] §f{2}")
 | 
			
		||||
    private TLogger tLogger;
 | 
			
		||||
 | 
			
		||||
    private TLibConfig config;
 | 
			
		||||
 | 
			
		||||
    private TLib() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TLibConfig getConfig() {
 | 
			
		||||
        return config;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TLogger getLogger() {
 | 
			
		||||
        return tLogger;
 | 
			
		||||
    }
 | 
			
		||||
@@ -48,4 +55,14 @@ public class TLib {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Config(name = "tlib.yml")
 | 
			
		||||
    public class TLibConfig {
 | 
			
		||||
 | 
			
		||||
        private int downloadPoolSize = 4;
 | 
			
		||||
 | 
			
		||||
        public int getDownloadPoolSize() {
 | 
			
		||||
            return downloadPoolSize;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
import java.lang.reflect.Modifier;
 | 
			
		||||
 | 
			
		||||
@Target(ElementType.TYPE)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@@ -15,12 +16,10 @@ public @interface Config {
 | 
			
		||||
 | 
			
		||||
    boolean saveOnExit() default false;
 | 
			
		||||
 | 
			
		||||
    boolean readOnly() default true;
 | 
			
		||||
 | 
			
		||||
    boolean fixUnicode() default true;
 | 
			
		||||
 | 
			
		||||
    String charset() default "UTF-8";
 | 
			
		||||
 | 
			
		||||
    boolean listenChanges() default false;
 | 
			
		||||
 | 
			
		||||
    int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
package com.ilummc.tlib.annotations;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
public @interface ConfigNode {
 | 
			
		||||
 | 
			
		||||
    String value();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/main/java/com/ilummc/tlib/bean/PropertyTypeAdaptor.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/main/java/com/ilummc/tlib/bean/PropertyTypeAdaptor.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
package com.ilummc.tlib.bean;
 | 
			
		||||
 | 
			
		||||
import com.google.gson.JsonDeserializationContext;
 | 
			
		||||
import com.google.gson.JsonDeserializer;
 | 
			
		||||
import com.google.gson.JsonElement;
 | 
			
		||||
import com.google.gson.JsonParseException;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Type;
 | 
			
		||||
 | 
			
		||||
public class PropertyTypeAdaptor implements JsonDeserializer<Property> {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Property deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -55,7 +55,7 @@ public class TDependency {
 | 
			
		||||
                .url(dl == null ? url + "/" + groupId.replace('.', '/') + "/" +
 | 
			
		||||
                        artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl)
 | 
			
		||||
                .file(target)
 | 
			
		||||
                .setThreads(8)
 | 
			
		||||
                .setThreads(TLib.getTLib().getConfig().getDownloadPoolSize())
 | 
			
		||||
                .setOnStart(event -> lock.lock())
 | 
			
		||||
                .setOnConnected(event -> TLib.getTLib().getLogger().info("  正在下载 " + String.join(":",
 | 
			
		||||
                        new String[]{groupId, artifactId, version}) +
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,7 @@
 | 
			
		||||
package com.ilummc.tlib.inject;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
import com.ilummc.tlib.annotations.Dependencies;
 | 
			
		||||
import com.ilummc.tlib.annotations.Dependency;
 | 
			
		||||
import com.ilummc.tlib.annotations.Logger;
 | 
			
		||||
import com.ilummc.tlib.annotations.PluginInstance;
 | 
			
		||||
import com.ilummc.tlib.annotations.*;
 | 
			
		||||
import com.ilummc.tlib.dependency.TDependency;
 | 
			
		||||
import com.ilummc.tlib.util.TLogger;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
@@ -31,12 +28,25 @@ public class DependencyInjector {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectConfig(Plugin plugin, Object o) {
 | 
			
		||||
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
            try {
 | 
			
		||||
                Config config;
 | 
			
		||||
                if ((config = field.getType().getAnnotation(Config.class)) != null) {
 | 
			
		||||
                    field.setAccessible(true);
 | 
			
		||||
                    Object obj = TConfigInjector.loadConfig(plugin, field.getType());
 | 
			
		||||
                    if (obj != null) {
 | 
			
		||||
                        TLib.getTLib().getLogger().info("插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件成功加载");
 | 
			
		||||
                        field.set(o, obj);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (IllegalAccessException ignored) {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectLogger(Plugin plugin, Object o) {
 | 
			
		||||
        try {
 | 
			
		||||
            for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
        for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
            try {
 | 
			
		||||
                Logger logger;
 | 
			
		||||
                if ((logger = field.getAnnotation(Logger.class)) != null) {
 | 
			
		||||
                    field.getType().asSubclass(TLogger.class);
 | 
			
		||||
@@ -45,8 +55,8 @@ public class DependencyInjector {
 | 
			
		||||
                        field.setAccessible(true);
 | 
			
		||||
                    field.set(o, tLogger);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception ignored) {
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception ignored) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,161 @@
 | 
			
		||||
package com.ilummc.tlib.inject;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.common.io.Files;
 | 
			
		||||
import com.google.gson.Gson;
 | 
			
		||||
import com.google.gson.GsonBuilder;
 | 
			
		||||
import com.google.gson.annotations.SerializedName;
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
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.plugin.Plugin;
 | 
			
		||||
import org.yaml.snakeyaml.DumperOptions;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
public class TConfigInjector {
 | 
			
		||||
 | 
			
		||||
    public static Object loadConfig(Plugin plugin, Class<?> clazz) {
 | 
			
		||||
        try {
 | 
			
		||||
            Config config = clazz.getAnnotation(Config.class);
 | 
			
		||||
            Validate.notNull(config);
 | 
			
		||||
            File file = new File(plugin.getDataFolder(), config.name());
 | 
			
		||||
            if (!file.exists()) if (config.fromJar()) plugin.saveResource(config.name(), true);
 | 
			
		||||
            else saveConfig(plugin, clazz);
 | 
			
		||||
            return unserialize(plugin, clazz);
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败");
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Object unserialize(Plugin plugin, Class<?> clazz) {
 | 
			
		||||
        try {
 | 
			
		||||
            Config config = clazz.getAnnotation(Config.class);
 | 
			
		||||
            Validate.notNull(config);
 | 
			
		||||
            return new GsonBuilder().disableHtmlEscaping().excludeFieldsWithModifiers(config.excludeModifiers())
 | 
			
		||||
                    .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 注解");
 | 
			
		||||
            return null;
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            try {
 | 
			
		||||
                return clazz.newInstance();
 | 
			
		||||
            } catch (InstantiationException | IllegalAccessException e1) {
 | 
			
		||||
                TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败");
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Map<String, Object> serialize(Plugin plugin, Class<?> clazz) {
 | 
			
		||||
        try {
 | 
			
		||||
            Constructor constructor = clazz.getConstructor();
 | 
			
		||||
            constructor.setAccessible(true);
 | 
			
		||||
            Config config = clazz.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() + " 序列化失败:没有无参构造方法");
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败:没有 @Config 注解");
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.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);
 | 
			
		||||
        Validate.notNull(config);
 | 
			
		||||
        File target = new File(plugin.getDataFolder(), config.name());
 | 
			
		||||
        if (!target.exists()) target.createNewFile();
 | 
			
		||||
        DumperOptions options = new DumperOptions();
 | 
			
		||||
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
 | 
			
		||||
        Yaml yaml = new Yaml(options);
 | 
			
		||||
        String str = yaml.dump(obj);
 | 
			
		||||
        byte[] arr = str.getBytes(config.charset());
 | 
			
		||||
        Files.write(arr, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final List<Class> primitiveType = Lists.newArrayList(Integer.class,
 | 
			
		||||
            Double.class, Float.class, Boolean.class, Short.class, Byte.class, Character.class, Long.class, String.class);
 | 
			
		||||
 | 
			
		||||
    private static class Serializer {
 | 
			
		||||
 | 
			
		||||
        private HashMap<String, Object> map;
 | 
			
		||||
        private Object o;
 | 
			
		||||
        private int modifiers;
 | 
			
		||||
 | 
			
		||||
        private Serializer(HashMap<String, Object> map, Object o, int modifiers) {
 | 
			
		||||
            this.map = map;
 | 
			
		||||
            this.o = o;
 | 
			
		||||
            this.modifiers = modifiers;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private HashMap<String, Object> get() {
 | 
			
		||||
            for (Field field : o.getClass().getDeclaredFields()) {
 | 
			
		||||
                if ((field.getModifiers() & modifiers) == 0 && !field.isSynthetic())
 | 
			
		||||
                    try {
 | 
			
		||||
                        SerializedName node = field.getAnnotation(SerializedName.class);
 | 
			
		||||
                        if (!field.isAccessible()) field.setAccessible(true);
 | 
			
		||||
                        Object obj = field.get(o);
 | 
			
		||||
                        map.put(node == null ? field.getName() : node.value(), serialize(obj));
 | 
			
		||||
                    } catch (Exception ignored) {
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            return map;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @SuppressWarnings({"unchecked"})
 | 
			
		||||
        private Object serialize(Object o) {
 | 
			
		||||
            try {
 | 
			
		||||
                if (o.getClass().isPrimitive() || primitiveType.contains(o.getClass())) {
 | 
			
		||||
                    return o;
 | 
			
		||||
                } else if (o.getClass().isArray()) {
 | 
			
		||||
                    List list = new ArrayList();
 | 
			
		||||
                    int len = (int) o.getClass().getField("length").get(o);
 | 
			
		||||
                    for (int i = 0; i < len; i++) {
 | 
			
		||||
                        list.add(serialize(Array.get(o, i)));
 | 
			
		||||
                    }
 | 
			
		||||
                    return list;
 | 
			
		||||
                } else if (o instanceof Collection) {
 | 
			
		||||
                    return ((Collection) o).stream().map(this::serialize).collect(Collectors.toList());
 | 
			
		||||
                } else if (o instanceof Map) {
 | 
			
		||||
                    Map<String, Object> map = new LinkedHashMap<>();
 | 
			
		||||
                    ((Map) o).forEach((o1, o2) -> map.put((String) o1, serialize(o2)));
 | 
			
		||||
                    return map;
 | 
			
		||||
                } else if (o instanceof ConfigurationSerializable) {
 | 
			
		||||
                    Map map = new LinkedHashMap();
 | 
			
		||||
                    map.put("==", o.getClass().getName());
 | 
			
		||||
                    map.putAll(((ConfigurationSerializable) o).serialize());
 | 
			
		||||
                    return map;
 | 
			
		||||
                } else if (o instanceof Property) {
 | 
			
		||||
                    return serialize(((Property) o).get());
 | 
			
		||||
                } else {
 | 
			
		||||
                    return new Serializer(new HashMap<>(), o, modifiers).get();
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception ignored) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user