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;
|
||||
|
||||
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.StringProperty;
|
||||
import ch.jalu.configme.resource.YamlFileResource;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@ -40,7 +44,7 @@ public class MessageUpdater {
|
||||
*/
|
||||
boolean migrateAndSave(File userFile, JarMessageSource jarMessageSource) {
|
||||
// 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);
|
||||
|
||||
// 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() {
|
||||
ImmutableList.Builder<Property<String>> listBuilder = ImmutableList.builder();
|
||||
StringPropertyListBuilder builder = new StringPropertyListBuilder();
|
||||
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