mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-23 18:55:11 +01:00
#1467 Fix export issues (style, encoding)
- Override yaml file resource to ensure that lines aren't wrapped - Override yaml file reader to ensure the file is always read as UTF-8
This commit is contained in:
parent
f714e9d564
commit
760a2a909c
@ -0,0 +1,131 @@
|
|||||||
|
package fr.xephi.authme.message.updater;
|
||||||
|
|
||||||
|
import ch.jalu.configme.exception.ConfigMeException;
|
||||||
|
import ch.jalu.configme.resource.PropertyReader;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplication of ConfigMe's {@link ch.jalu.configme.resource.YamlFileReader} with a character encoding
|
||||||
|
* fix in {@link #reload}.
|
||||||
|
*/
|
||||||
|
public class MessageMigraterPropertyReader implements PropertyReader {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
private Map<String, Object> root;
|
||||||
|
/** See same field in {@link ch.jalu.configme.resource.YamlFileReader} for details. */
|
||||||
|
private boolean hasObjectAsRoot = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param file the file to load
|
||||||
|
*/
|
||||||
|
public MessageMigraterPropertyReader(File file) {
|
||||||
|
this.file = file;
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getObject(String path) {
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
return hasObjectAsRoot ? root.get("") : root;
|
||||||
|
}
|
||||||
|
Object node = root;
|
||||||
|
String[] keys = path.split("\\.");
|
||||||
|
for (String key : keys) {
|
||||||
|
node = getIfIsMap(key, node);
|
||||||
|
if (node == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getTypedObject(String path, Class<T> clazz) {
|
||||||
|
Object value = getObject(path);
|
||||||
|
if (clazz.isInstance(value)) {
|
||||||
|
return clazz.cast(value);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(String path, Object value) {
|
||||||
|
Objects.requireNonNull(path);
|
||||||
|
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
root.clear();
|
||||||
|
root.put("", value);
|
||||||
|
hasObjectAsRoot = true;
|
||||||
|
} else if (hasObjectAsRoot) {
|
||||||
|
throw new ConfigMeException("The root path is a bean property; you cannot set values to any subpath. "
|
||||||
|
+ "Modify the bean at the root or set a new one instead.");
|
||||||
|
} else {
|
||||||
|
setValueInChildPath(path, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value at the given path. This method is used when the root is a map and not a specific object.
|
||||||
|
*
|
||||||
|
* @param path the path to set the value at
|
||||||
|
* @param value the value to set
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void setValueInChildPath(String path, Object value) {
|
||||||
|
Map<String, Object> node = root;
|
||||||
|
String[] keys = path.split("\\.");
|
||||||
|
for (int i = 0; i < keys.length - 1; ++i) {
|
||||||
|
Object child = node.get(keys[i]);
|
||||||
|
if (child instanceof Map<?, ?>) {
|
||||||
|
node = (Map<String, Object>) child;
|
||||||
|
} else { // child is null or some other value - replace with map
|
||||||
|
Map<String, Object> newEntry = new HashMap<>();
|
||||||
|
node.put(keys[i], newEntry);
|
||||||
|
if (value == null) {
|
||||||
|
// For consistency, replace whatever value/null here with an empty map,
|
||||||
|
// but if the value is null our work here is done.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node = newEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// node now contains the parent map (existing or newly created)
|
||||||
|
if (value == null) {
|
||||||
|
node.remove(keys[keys.length - 1]);
|
||||||
|
} else {
|
||||||
|
node.put(keys[keys.length - 1], value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
try (FileInputStream fis = new FileInputStream(file);
|
||||||
|
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
|
||||||
|
|
||||||
|
Object obj = new Yaml().load(isr);
|
||||||
|
root = obj == null ? new HashMap<>() : (Map<String, Object>) obj;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ConfigMeException("Could not read file '" + file + "'", e);
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new ConfigMeException("Top-level is not a map in '" + file + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getIfIsMap(String key, Object value) {
|
||||||
|
if (value instanceof Map<?, ?>) {
|
||||||
|
return ((Map<?, ?>) value).get(key);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,16 @@
|
|||||||
package fr.xephi.authme.message.updater;
|
package fr.xephi.authme.message.updater;
|
||||||
|
|
||||||
import ch.jalu.configme.SettingsManager;
|
import ch.jalu.configme.SettingsManager;
|
||||||
|
import ch.jalu.configme.beanmapper.leafproperties.LeafPropertiesGenerator;
|
||||||
|
import ch.jalu.configme.configurationdata.PropertyListBuilder;
|
||||||
import ch.jalu.configme.properties.Property;
|
import ch.jalu.configme.properties.Property;
|
||||||
import ch.jalu.configme.properties.StringProperty;
|
import ch.jalu.configme.properties.StringProperty;
|
||||||
import ch.jalu.configme.resource.YamlFileResource;
|
import ch.jalu.configme.resource.YamlFileResource;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -40,7 +44,7 @@ public class MessageUpdater {
|
|||||||
*/
|
*/
|
||||||
boolean migrateAndSave(File userFile, JarMessageSource jarMessageSource) {
|
boolean migrateAndSave(File userFile, JarMessageSource jarMessageSource) {
|
||||||
// YamlConfiguration escapes all special characters when saving, making the file hard to use, so use ConfigMe
|
// YamlConfiguration escapes all special characters when saving, making the file hard to use, so use ConfigMe
|
||||||
YamlFileResource userResource = new YamlFileResource(userFile);
|
YamlFileResource userResource = new MigraterYamlFileResource(userFile);
|
||||||
SettingsManager settingsManager = SettingsManager.createWithProperties(userResource, null, TEXT_PROPERTIES);
|
SettingsManager settingsManager = SettingsManager.createWithProperties(userResource, null, TEXT_PROPERTIES);
|
||||||
|
|
||||||
// Step 1: Migrate any old keys in the file to the new paths
|
// Step 1: Migrate any old keys in the file to the new paths
|
||||||
@ -81,10 +85,53 @@ public class MessageUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static List<Property<String>> buildPropertyEntriesForMessageKeys() {
|
private static List<Property<String>> buildPropertyEntriesForMessageKeys() {
|
||||||
ImmutableList.Builder<Property<String>> listBuilder = ImmutableList.builder();
|
StringPropertyListBuilder builder = new StringPropertyListBuilder();
|
||||||
for (MessageKey messageKey : MessageKey.values()) {
|
for (MessageKey messageKey : MessageKey.values()) {
|
||||||
listBuilder.add(new StringProperty(messageKey.getKey(), ""));
|
builder.add(messageKey.getKey());
|
||||||
|
}
|
||||||
|
return ImmutableList.copyOf(builder.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a {@link PropertyListBuilder} for easier construction of string properties.
|
||||||
|
* ConfigMe's property list builder ensures that properties are grouped together by path.
|
||||||
|
*/
|
||||||
|
private static final class StringPropertyListBuilder {
|
||||||
|
private PropertyListBuilder propertyListBuilder = new PropertyListBuilder();
|
||||||
|
|
||||||
|
void add(String path) {
|
||||||
|
propertyListBuilder.add(new StringProperty(path, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Property<String>> create() {
|
||||||
|
return (List) propertyListBuilder.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension of {@link YamlFileResource} to fine-tune the export style.
|
||||||
|
*/
|
||||||
|
private static final class MigraterYamlFileResource extends YamlFileResource {
|
||||||
|
|
||||||
|
private Yaml singleQuoteYaml;
|
||||||
|
|
||||||
|
MigraterYamlFileResource(File file) {
|
||||||
|
super(file, new MessageMigraterPropertyReader(file), new LeafPropertiesGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Yaml getSingleQuoteYaml() {
|
||||||
|
if (singleQuoteYaml == null) {
|
||||||
|
DumperOptions options = new DumperOptions();
|
||||||
|
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||||
|
options.setAllowUnicode(true);
|
||||||
|
options.setDefaultScalarStyle(DumperOptions.ScalarStyle.SINGLE_QUOTED);
|
||||||
|
// Overridden setting: don't split lines
|
||||||
|
options.setSplitLines(false);
|
||||||
|
singleQuoteYaml = new Yaml(options);
|
||||||
|
}
|
||||||
|
return singleQuoteYaml;
|
||||||
}
|
}
|
||||||
return listBuilder.build();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user