geforkt von Mirrors/Velocity
Improve code style, grammar and other fixes
Dieser Commit ist enthalten in:
Ursprung
fdc83261cb
Commit
85e43727cf
@ -3,7 +3,6 @@ package com.velocitypowered.proxy.config;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -11,9 +10,12 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.AtomicMoveNotSupportedException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -35,7 +37,6 @@ public class AnnotatedConfig {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
public @interface Table {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
@ -45,7 +46,6 @@ public class AnnotatedConfig {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
public @interface Comment {
|
||||
|
||||
String[] value();
|
||||
}
|
||||
|
||||
@ -55,7 +55,6 @@ public class AnnotatedConfig {
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
public @interface ConfigKey {
|
||||
|
||||
String value();
|
||||
}
|
||||
|
||||
@ -65,96 +64,125 @@ public class AnnotatedConfig {
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
public @interface IsMap {
|
||||
}
|
||||
public @interface IsMap {}
|
||||
|
||||
/**
|
||||
* Indicates that a field is a string converted to byte[]
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
||||
public @interface StringAsBytes {
|
||||
}
|
||||
public @interface StringAsBytes {}
|
||||
|
||||
/**
|
||||
* Indicates that a field should be skiped
|
||||
* Indicates that a field should be skipped
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface Ignore {
|
||||
}
|
||||
public @interface Ignore {}
|
||||
|
||||
/**
|
||||
* Dumps this configuration to list of strings using {@link #dumpConfig(Object)}
|
||||
* @return configuration dump
|
||||
*/
|
||||
public List<String> dumpConfig() {
|
||||
List<String> lines = new ArrayList<>();
|
||||
dumpFields(this, lines);
|
||||
return lines;
|
||||
return dumpConfig(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump all field and they annotations to List
|
||||
* Creates TOML configuration from supplied <pre>dumpable</pre> object.
|
||||
*
|
||||
* @param toSave object those we need to dump
|
||||
* @param lines a list where store dumped lines
|
||||
* @param dumpable object which is going to be dumped
|
||||
* @throws RuntimeException if reading field value(s) fail
|
||||
* @return string list of configuration file lines
|
||||
*/
|
||||
private void dumpFields(Object toSave, List<String> lines) {
|
||||
|
||||
private static List<String> dumpConfig(Object dumpable) {
|
||||
List<String> lines = new ArrayList<>();
|
||||
try {
|
||||
for (Field field : toSave.getClass().getDeclaredFields()) {
|
||||
if (field.getAnnotation(Ignore.class) != null) { //Skip this field
|
||||
for (Field field : dumpable.getClass().getDeclaredFields()) {
|
||||
// Skip fields with @Ignore annotation
|
||||
if (field.getAnnotation(Ignore.class) != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make field accessible
|
||||
field.setAccessible(true);
|
||||
|
||||
// Add comments
|
||||
Comment comment = field.getAnnotation(Comment.class);
|
||||
if (comment != null) { //Add comments
|
||||
if (comment != null) {
|
||||
for (String line : comment.value()) {
|
||||
lines.add("# " + line);
|
||||
}
|
||||
}
|
||||
ConfigKey key = field.getAnnotation(ConfigKey.class); //Get a key name for config
|
||||
String name = key == null ? field.getName() : key.value(); // Use a field name if name in annotation is not present
|
||||
field.setAccessible(true); // Make field accessible
|
||||
|
||||
// Get a key name for config
|
||||
ConfigKey key = field.getAnnotation(ConfigKey.class);
|
||||
String name = key == null ? field.getName() : key.value(); // Use field name if @ConfigKey annotation is not present
|
||||
|
||||
// Check if field is table.
|
||||
Table table = field.getAnnotation(Table.class);
|
||||
if (table != null) { // Check if field is table.
|
||||
lines.add(table.value()); // Write [name]
|
||||
dumpFields(field.get(toSave), lines); // dump fields of table class
|
||||
} else {
|
||||
if (field.getAnnotation(IsMap.class) != null) { // check if field is map
|
||||
Map<String, ?> map = (Map<String, ?>) field.get(toSave);
|
||||
for (Entry<String, ?> entry : map.entrySet()) {
|
||||
lines.add(safeKey(entry.getKey()) + " = " + toString(entry.getValue())); // Save a map data
|
||||
}
|
||||
lines.add(""); //Add empty line
|
||||
continue;
|
||||
}
|
||||
Object value = field.get(toSave);
|
||||
if (field.getAnnotation(StringAsBytes.class) != null) { // Check if field is a byte[] representation of a string
|
||||
value = new String((byte[]) value, StandardCharsets.UTF_8);
|
||||
}
|
||||
lines.add(name + " = " + toString(value)); // save field to config
|
||||
lines.add(""); // add empty line
|
||||
if (table != null) {
|
||||
lines.add(table.value()); // Write [name]
|
||||
lines.addAll(dumpConfig(field.get(dumpable))); // dump fields of table
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.getAnnotation(IsMap.class) != null) { // check if field is map
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ?> map = (Map<String, ?>) field.get(dumpable);
|
||||
for (Entry<String, ?> entry : map.entrySet()) {
|
||||
lines.add(entry.getKey() + " = " + serialize(entry.getValue())); // Save map data
|
||||
}
|
||||
lines.add(""); //Add empty line
|
||||
continue;
|
||||
}
|
||||
|
||||
Object value = field.get(dumpable);
|
||||
|
||||
// Check if field is a byte[] representation of a string
|
||||
if (field.getAnnotation(StringAsBytes.class) != null) {
|
||||
value = new String((byte[]) value, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
// Save field to config
|
||||
lines.add(name + " = " + serialize(value));
|
||||
lines.add(""); // add empty line
|
||||
}
|
||||
} catch (IllegalAccessException | IllegalArgumentException | SecurityException e) {
|
||||
throw new RuntimeException("Can not dump config", e);
|
||||
throw new RuntimeException("Could not dump configuration", e);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private String toString(Object value) {
|
||||
/**
|
||||
* Serializes <pre>value</pre> so it could be parsed by TOML specification
|
||||
*
|
||||
* @param value object to serialize
|
||||
* @return Serialized object
|
||||
*/
|
||||
private static String serialize(Object value) {
|
||||
if (value instanceof List) {
|
||||
Collection<?> listValue = (Collection<?>) value;
|
||||
List<?> listValue = (List<?>) value;
|
||||
if (listValue.isEmpty()) {
|
||||
return "[]";
|
||||
}
|
||||
|
||||
StringBuilder m = new StringBuilder();
|
||||
m.append("[");
|
||||
|
||||
for (Object obj : listValue) {
|
||||
m.append(System.lineSeparator()).append(" ").append(toString(obj)).append(",");
|
||||
m.append(System.lineSeparator()).append(" ").append(serialize(obj)).append(",");
|
||||
}
|
||||
|
||||
m.deleteCharAt(m.length() - 1).append(System.lineSeparator()).append("]");
|
||||
return m.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Enum) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof String) {
|
||||
String stringValue = (String) value;
|
||||
if (stringValue.isEmpty()) {
|
||||
@ -162,6 +190,7 @@ public class AnnotatedConfig {
|
||||
}
|
||||
return "\"" + stringValue.replace("\n", "\\n") + "\"";
|
||||
}
|
||||
|
||||
return value != null ? value.toString() : "null";
|
||||
}
|
||||
|
||||
@ -173,23 +202,24 @@ public class AnnotatedConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves lines to file
|
||||
* Writes list of strings to file
|
||||
*
|
||||
* @param lines Lines to save
|
||||
* @param to A path of file where to save lines
|
||||
* @throws IOException if lines is empty or was error during saving
|
||||
* @param lines list of strings to write
|
||||
* @param to Path of file where lines should be written
|
||||
* @throws IOException if error occurred during writing
|
||||
* @throws IllegalArgumentException if <pre>lines</pre> is empty list
|
||||
*/
|
||||
public static void saveConfig(List<String> lines, Path to) throws IOException {
|
||||
if (lines.isEmpty()) {
|
||||
throw new IOException("Can not save config because list is empty");
|
||||
throw new IllegalArgumentException("lines cannot be empty");
|
||||
}
|
||||
Path temp = new File(to.toFile().getParent(), "__tmp").toPath();
|
||||
|
||||
Path temp = to.getParent().resolve(to.getFileName().toString() + "__tmp");
|
||||
Files.write(temp, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE);
|
||||
try {
|
||||
Files.move(temp, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
||||
} catch (AtomicMoveNotSupportedException e) {
|
||||
Files.move(temp, to, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren