Update
This commit is contained in:
parent
058ff6c141
commit
b2e1813cff
@ -6,7 +6,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = 'me.skymc'
|
||||
version = '5.26'
|
||||
version = '5.27'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
@ -52,6 +52,12 @@ public class TabooLib {
|
||||
logger = TLogger.getUnformatted("TabooLib");
|
||||
// 配置文件从 config.yml 修改为 settings.yml 防止与老版本插件冲突
|
||||
config = TConfig.create(getPlugin(), "settings.yml");
|
||||
// 配置更新
|
||||
try {
|
||||
config.migrate();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
// 加载版本号
|
||||
try {
|
||||
version = NumberConversions.toDouble(IO.readFully(Files.getResource("__resources__/version"), StandardCharsets.UTF_8));
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.izzel.taboolib.module.config;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
@ -7,12 +8,14 @@ import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.module.locale.TLocale;
|
||||
import io.izzel.taboolib.module.locale.logger.TLogger;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.KV;
|
||||
import io.izzel.taboolib.util.Ref;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -24,12 +27,16 @@ import java.util.Map;
|
||||
*/
|
||||
public class TConfig extends YamlConfiguration {
|
||||
|
||||
private static Map<String, List<File>> files = Maps.newHashMap();
|
||||
private File file;
|
||||
private List<Runnable> runnable = Lists.newArrayList();
|
||||
private static final Map<String, List<File>> files = Maps.newHashMap();
|
||||
private final Plugin plugin;
|
||||
private final File file;
|
||||
private final List<Runnable> runnable = Lists.newArrayList();
|
||||
private final List<KV<String, String[]>> migrate = Lists.newArrayList();
|
||||
private String path;
|
||||
|
||||
private TConfig(File file, Plugin plugin) {
|
||||
files.computeIfAbsent(plugin.getName(), name -> new ArrayList<>()).add(file);
|
||||
this.plugin = plugin;
|
||||
this.file = file;
|
||||
reload();
|
||||
TConfigWatcher.getInst().addSimpleListener(this.file, this::reload);
|
||||
@ -53,7 +60,9 @@ public class TConfig extends YamlConfiguration {
|
||||
if (!file.exists()) {
|
||||
Files.releaseResource(plugin, path, false);
|
||||
}
|
||||
return create(file, plugin);
|
||||
TConfig conf = create(file, plugin);
|
||||
conf.path = path;
|
||||
return conf;
|
||||
}
|
||||
|
||||
public String getStringColored(String path) {
|
||||
@ -89,6 +98,25 @@ public class TConfig extends YamlConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
public TConfig migrate() {
|
||||
Preconditions.checkNotNull(path, "path not exists");
|
||||
try (FileInputStream fileInputStream = new FileInputStream(file)) {
|
||||
List<String> migrate = TConfigMigrate.migrate(fileInputStream, Files.getResourceChecked(plugin, path));
|
||||
if (migrate != null) {
|
||||
Files.write(file, w -> {
|
||||
for (String line : migrate) {
|
||||
w.write(line);
|
||||
w.newLine();
|
||||
}
|
||||
});
|
||||
load(file);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
|
@ -0,0 +1,152 @@
|
||||
package io.izzel.taboolib.module.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.izzel.taboolib.module.db.local.SecuredFile;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import io.izzel.taboolib.util.KV;
|
||||
import io.izzel.taboolib.util.Strings;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2020-04-27 21:02
|
||||
*/
|
||||
public class TConfigMigrate {
|
||||
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
|
||||
|
||||
public static List<String> migrate(InputStream current, InputStream source) {
|
||||
boolean migrated = false;
|
||||
List<String> content = Files.readToList(current);
|
||||
String cc = String.join("\n", content);
|
||||
String cs = String.join("\n", Files.readToList(source));
|
||||
SecuredFile c = SecuredFile.loadConfiguration(cc);
|
||||
SecuredFile s = SecuredFile.loadConfiguration(cs);
|
||||
String hash1 = Strings.hashKeyForDisk(cs, "sha-1");
|
||||
String hash2 = "";
|
||||
for (String line : content) {
|
||||
if (line.startsWith("# HASH ")) {
|
||||
hash2 = line.substring("# HASH ".length()).trim().split(" ")[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Objects.equals(hash1, hash2)) {
|
||||
return null;
|
||||
}
|
||||
List<KV<String, String[]>> update = Lists.newArrayList();
|
||||
List<KV<String, Object>> contrast = contrast(c.getValues(true), s.getValues(true));
|
||||
for (KV<String, Object> pair : contrast) {
|
||||
int index = pair.getKey().lastIndexOf(".");
|
||||
if (pair.getValue() == null) {
|
||||
Object data = s.get(pair.getKey());
|
||||
String[] nodes = pair.getKey().split("\\.");
|
||||
int regex = 0;
|
||||
int match = 0;
|
||||
int find = -1;
|
||||
for (int i = 0; i < content.size(); i++) {
|
||||
String line = content.get(i);
|
||||
for (int j = regex; j < nodes.length; j++) {
|
||||
if (line.matches("( *)(['\"])?(" + nodes[j] + ")(['\"])?:(.*)")) {
|
||||
match++;
|
||||
find = i;
|
||||
regex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (find == -1) {
|
||||
update.add(new KV<>(pair.getKey(), SecuredFile.dump(data).split("\n")));
|
||||
} else {
|
||||
String space = Strings.copy(" ", nodes.length - 1);
|
||||
String[] dumpList = SecuredFile.dump(data).split("\n");
|
||||
if (dumpList.length > 1) {
|
||||
IntStream.range(0, dumpList.length).forEach(j -> dumpList[j] = space + " # " + dumpList[j]);
|
||||
}
|
||||
ArrayUtil.addAutoExpand(content, find + 1, space + "# ------------------------- #\n" + space + "# UPDATE " + dateFormat.format(System.currentTimeMillis()) + " #\n" + space + "# ------------------------- #", "");
|
||||
if (dumpList.length == 1) {
|
||||
ArrayUtil.addAutoExpand(content, find + 2, space + "# " + pair.getKey().substring(index + 1) + ": " + dumpList[0] + "\n", "");
|
||||
} else {
|
||||
ArrayUtil.addAutoExpand(content, find + 2, space + "# " + pair.getKey().substring(index + 1) + ":", "");
|
||||
ArrayUtil.addAutoExpand(content, find + 3, String.join("\n# ", dumpList) + "\n", "");
|
||||
}
|
||||
migrated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (update.size() > 0) {
|
||||
content.add("");
|
||||
content.add("# ------------------------- #\n" + "# UPDATE " + dateFormat.format(System.currentTimeMillis()) + " #\n" + "# ------------------------- #");
|
||||
for (KV<String, String[]> pair : update) {
|
||||
if (pair.getValue().length == 1) {
|
||||
content.add("# " + pair.getKey() + ": " + pair.getValue()[0]);
|
||||
} else {
|
||||
content.add("# " + pair.getKey() + ":");
|
||||
content.add(String.join("\n# ", pair.getValue()));
|
||||
}
|
||||
}
|
||||
migrated = true;
|
||||
}
|
||||
if (migrated) {
|
||||
if (hash2.isEmpty()) {
|
||||
content.add("");
|
||||
content.add("# --------------------------------------------- #");
|
||||
content.add("# HASH " + hash1 + " #");
|
||||
content.add("# --------------------------------------------- #");
|
||||
} else {
|
||||
for (int i = 0; i < content.size(); i++) {
|
||||
String line = content.get(i);
|
||||
if (line.startsWith("# HASH ")) {
|
||||
content.set(i, "# HASH " + hash1 + " #");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return migrated ? content : null;
|
||||
}
|
||||
|
||||
public static List<KV<String, Object>> contrast(Map<?, ?> current, Map<?, ?> source) {
|
||||
List<String> deleted = Lists.newArrayList();
|
||||
List<KV<String, Object>> difference = Lists.newArrayList();
|
||||
// change & add
|
||||
for (Map.Entry<?, ?> entry : current.entrySet()) {
|
||||
if (entry.getValue() instanceof ConfigurationSection) {
|
||||
continue;
|
||||
}
|
||||
if (entry.getValue() instanceof Map && source.get(entry.getKey()) instanceof Map) {
|
||||
List<KV<String, Object>> contrast = contrast((Map<?, ?>) entry.getValue(), (Map<?, ?>) source.get(entry.getKey()));
|
||||
for (KV<String, Object> pair : contrast) {
|
||||
pair.setKey(entry.getKey() + "." + pair.getKey());
|
||||
}
|
||||
difference.addAll(contrast);
|
||||
} else if (!Objects.equals(entry.getValue(), source.get(entry.getKey()))) {
|
||||
difference.add(new KV<>(entry.getKey().toString(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
// delete
|
||||
for (Map.Entry<?, ?> entry : source.entrySet()) {
|
||||
if (deleted.stream().anyMatch(delete -> entry.getKey().toString().startsWith(delete) && delete.split("\\.").length < entry.getKey().toString().split("\\.").length)) {
|
||||
continue;
|
||||
}
|
||||
if (entry.getValue() instanceof Map && current.get(entry.getKey()) instanceof Map) {
|
||||
List<KV<String, Object>> contrast = contrast((Map<?, ?>) entry.getValue(), (Map<?, ?>) source.get(entry.getKey()));
|
||||
for (KV<String, Object> pair : contrast) {
|
||||
pair.setKey(entry.getKey() + "." + pair.getKey());
|
||||
}
|
||||
difference.addAll(contrast);
|
||||
} else if (!current.containsKey(entry.getKey())) {
|
||||
deleted.add(entry.getKey().toString());
|
||||
difference.add(new KV<>(entry.getKey().toString(), null));
|
||||
}
|
||||
}
|
||||
return difference;
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class TConfigWatcher {
|
||||
|
||||
private static TConfigWatcher configWatcher = new TConfigWatcher();
|
||||
private final static TConfigWatcher configWatcher = new TConfigWatcher();
|
||||
private final ScheduledExecutorService service = Executors.newScheduledThreadPool(1, new BasicThreadFactory.Builder().namingPattern("TConfigWatcherService-%d").build());
|
||||
private final Map<WatchService, Triple<File, Object, Consumer<Object>>> map = new HashMap<>();
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
package io.izzel.taboolib.module.db.local;
|
||||
|
||||
import io.izzel.taboolib.module.lite.SimpleReflection;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -11,7 +13,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Author sky, yumc
|
||||
* @Since 2020-02-28 11:14
|
||||
*/
|
||||
public class SecuredFile extends YamlConfiguration {
|
||||
@ -39,7 +41,7 @@ public class SecuredFile extends YamlConfiguration {
|
||||
public void load(File file) throws InvalidConfigurationException {
|
||||
String content = Files.readFromFile(file);
|
||||
try {
|
||||
super.loadFromString(Files.readFromFile(file));
|
||||
loadFromString(content);
|
||||
} catch (InvalidConfigurationException t) {
|
||||
Files.copy(file, new File(file.getParent(), file.getName() + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis()) + ".bak"));
|
||||
throw t;
|
||||
@ -60,6 +62,21 @@ public class SecuredFile extends YamlConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveToString() {
|
||||
return super.saveToString();
|
||||
}
|
||||
|
||||
public static String dump(Object data) {
|
||||
Yaml yaml = (Yaml) SimpleReflection.getFieldValueChecked(YamlConfiguration.class, new YamlConfiguration(), "yaml", true);
|
||||
try {
|
||||
return yaml.dump(data);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static SecuredFile loadConfiguration(String contents) {
|
||||
SecuredFile config = new SecuredFile();
|
||||
try {
|
||||
|
@ -31,6 +31,8 @@ public @interface TInject {
|
||||
|
||||
State state() default State.NONE;
|
||||
|
||||
boolean autoMigrate() default false;
|
||||
|
||||
enum State {
|
||||
|
||||
LOADING, STARTING, ACTIVATED, NONE
|
||||
|
@ -28,7 +28,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class TInjectLoader implements TabooLibLoader.Loader {
|
||||
|
||||
private static Map<Class<?>, TInjectTask> injectTypes = Maps.newLinkedHashMap();
|
||||
private static final Map<Class<?>, TInjectTask> injectTypes = Maps.newLinkedHashMap();
|
||||
|
||||
static {
|
||||
// Instance Inject
|
||||
@ -91,6 +91,9 @@ public class TInjectLoader implements TabooLibLoader.Loader {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (args.autoMigrate()) {
|
||||
config.migrate();
|
||||
}
|
||||
TabooLibLoader.runTask(config::runListener);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -73,6 +73,22 @@ public class ArrayUtil {
|
||||
return arrayNew;
|
||||
}
|
||||
|
||||
public static <T> List<T> setAutoExpand(List<T> list, int index, T element, T def) {
|
||||
while (list.size() <= index) {
|
||||
list.add(def);
|
||||
}
|
||||
list.set(index, element);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> List<T> addAutoExpand(List<T> list, int index, T element, T def) {
|
||||
while (list.size() <= index) {
|
||||
list.add(def);
|
||||
}
|
||||
list.add(index, element);
|
||||
return list;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousSystemArraycopy")
|
||||
public static <T> T arrayExpand(T oldArray, int expand) {
|
||||
int length = Array.getLength(oldArray);
|
||||
|
@ -21,6 +21,7 @@ import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@ -70,6 +71,10 @@ public class Files {
|
||||
return plugin instanceof InternalPlugin ? getTabooLibResource(filename) : plugin.getClass().getClassLoader().getResourceAsStream(filename);
|
||||
}
|
||||
|
||||
public static InputStream getResourceChecked(Plugin plugin, String filename) {
|
||||
return plugin instanceof InternalPlugin ? getResource(plugin, "__resources__/" + filename) : getResource(filename);
|
||||
}
|
||||
|
||||
public static InputStream getTabooLibResource(String filename) {
|
||||
return getCanonicalResource(TabooLib.getPlugin(), filename);
|
||||
}
|
||||
@ -273,6 +278,24 @@ public class Files {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> readToList(File file) {
|
||||
try (FileInputStream fin = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fin, StandardCharsets.UTF_8); BufferedReader bin = new BufferedReader(isr)) {
|
||||
return bin.lines().collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static List<String> readToList(InputStream inputStream) {
|
||||
try (InputStreamReader isr = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bin = new BufferedReader(isr)) {
|
||||
return bin.lines().collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static String readFromStream(InputStream in) {
|
||||
return readFromStream(in, 1024, StandardCharsets.UTF_8);
|
||||
}
|
||||
@ -296,7 +319,9 @@ public class Files {
|
||||
}
|
||||
|
||||
public static void read(File file, ReadHandle readHandle) {
|
||||
try (FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader)) {
|
||||
try (FileInputStream fileInputStream = new FileInputStream(file);
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
readHandle.read(bufferedReader);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
@ -304,7 +329,8 @@ public class Files {
|
||||
}
|
||||
|
||||
public static void read(InputStream in, ReadHandle readHandle) {
|
||||
try (InputStreamReader inputStreamReader = new InputStreamReader(in); BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
try (InputStreamReader inputStreamReader = new InputStreamReader(in, StandardCharsets.UTF_8);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
readHandle.read(bufferedReader);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
@ -312,7 +338,9 @@ public class Files {
|
||||
}
|
||||
|
||||
public static void write(File file, WriteHandle writeHandle) {
|
||||
try (FileWriter fileWriter = new FileWriter(file); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
|
||||
writeHandle.write(bufferedWriter);
|
||||
bufferedWriter.flush();
|
||||
} catch (Throwable t) {
|
||||
@ -321,7 +349,9 @@ public class Files {
|
||||
}
|
||||
|
||||
public static void writeAppend(File file, WriteHandle writeHandle) {
|
||||
try (FileWriter fileWriter = new FileWriter(file, true); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(file, true);
|
||||
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
|
||||
writeHandle.write(bufferedWriter);
|
||||
bufferedWriter.flush();
|
||||
} catch (Throwable t) {
|
||||
@ -330,7 +360,8 @@ public class Files {
|
||||
}
|
||||
|
||||
public static void write(OutputStream out, WriteHandle writeHandle) {
|
||||
try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out); BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
|
||||
try (OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
|
||||
writeHandle.write(bufferedWriter);
|
||||
bufferedWriter.flush();
|
||||
} catch (Throwable t) {
|
||||
|
@ -60,9 +60,13 @@ public class Strings {
|
||||
}
|
||||
|
||||
public static String hashKeyForDisk(String key) {
|
||||
return hashKeyForDisk(key, "MD5");
|
||||
}
|
||||
|
||||
public static String hashKeyForDisk(String key, String type) {
|
||||
String cacheKey;
|
||||
try {
|
||||
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
|
||||
final MessageDigest mDigest = MessageDigest.getInstance(type);
|
||||
mDigest.update(key.getBytes());
|
||||
cacheKey = bytesToHexString(mDigest.digest());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
Loading…
Reference in New Issue
Block a user