Implemented config save and reload

Always caching config value if it hasn't been cached
This commit is contained in:
Norbi Peti 2019-03-13 13:47:49 +01:00
parent 7289385a33
commit 25b9caa903
8 changed files with 77 additions and 20 deletions

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />

View file

@ -1,6 +1,7 @@
package buttondevteam.core;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.architecture.ButtonPlugin;
import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.Command2.Subcommand;
@ -24,7 +25,10 @@ public class ComponentCommand extends ICommand2MC {
@Subcommand
public boolean enable(CommandSender sender, Plugin plugin, String component) {
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
if (plugin instanceof ButtonPlugin)
((ButtonPlugin) plugin).justReload();
else
plugin.reloadConfig(); //Reload config so the new config values are read - All changes are saved to disk on disable
return enable_disable(sender, plugin, component, true);
}

View file

@ -34,9 +34,10 @@ public final class ComponentManager {
/**
* Unregister all components of a plugin that are enabled - called on {@link ButtonPlugin} disable
*/
public static void unregComponents(ButtonPlugin plugin) {
@SuppressWarnings("unchecked")
public static <T extends ButtonPlugin> void unregComponents(T plugin) {
while (!plugin.getComponentStack().empty()) //Unregister in reverse order
Component.unregisterComponent(plugin, plugin.getComponentStack().pop()); //Components are pushed on register
Component.unregisterComponent(plugin, (Component<T>) plugin.getComponentStack().pop()); //Components are pushed on register
componentsEnabled = false;
}

View file

@ -0,0 +1,14 @@
package buttondevteam.core;
import buttondevteam.lib.chat.Command2;
import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.chat.ICommand2MC;
import org.bukkit.command.CommandSender;
@CommandClass
public class ThorpeCommand extends ICommand2MC {
@Command2.Subcommand //TODO: Main permissions (groups) like 'mod'
public void reload(CommandSender sender) {
MainPlugin.Instance.reloadConfig();
}
}

View file

@ -20,10 +20,10 @@ public abstract class ButtonPlugin extends JavaPlugin {
@Getter(AccessLevel.PROTECTED)
private IHaveConfig data; //TODO
/**
* Used to unregister components in the right order
* Used to unregister components in the right order - and to reload configs
*/
@Getter
private Stack<Component> componentStack = new Stack<>();
private Stack<Component<?>> componentStack = new Stack<>();
protected abstract void pluginEnable();
@ -40,9 +40,7 @@ public abstract class ButtonPlugin extends JavaPlugin {
@Override
public final void onEnable() {
var section = super.getConfig().getConfigurationSection("global");
if (section == null) section = super.getConfig().createSection("global");
iConfig = new IHaveConfig(section, this::saveConfig);
loadConfig();
try {
pluginEnable();
} catch (Exception e) {
@ -50,6 +48,12 @@ public abstract class ButtonPlugin extends JavaPlugin {
}
}
private void loadConfig() {
var section = super.getConfig().getConfigurationSection("global");
if (section == null) section = super.getConfig().createSection("global");
iConfig = new IHaveConfig(section, this::saveConfig);
}
@Override
public final void onDisable() {
try {
@ -63,4 +67,19 @@ public abstract class ButtonPlugin extends JavaPlugin {
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
}
}
@Override
public void reloadConfig() {
justReload();
loadConfig();
componentStack.forEach(c -> Component.updateConfig(this, c));
}
public void justReload() {
if (ConfigData.saveNow(getConfig())) {
getLogger().warning("Saved pending configuration changes to the file, didn't reload (try again).");
return;
}
super.reloadConfig();
}
}

View file

@ -140,7 +140,7 @@ public abstract class Component<TP extends JavaPlugin> {
}
}
private static void updateConfig(JavaPlugin plugin, Component component) {
public static void updateConfig(JavaPlugin plugin, Component component) {
if (plugin.getConfig() != null) { //Production
var compconf = plugin.getConfig().getConfigurationSection("components");
if (compconf == null) compconf = plugin.getConfig().createSection("components");
@ -237,10 +237,10 @@ public abstract class Component<TP extends JavaPlugin> {
var cs=c.getConfigurationSection(key);
if(cs==null) cs=c.createSection(key);
val res = cs.getValues(false).entrySet().stream().filter(e -> e.getValue() instanceof ConfigurationSection)
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue())));
.collect(Collectors.toMap(Map.Entry::getKey, kv -> new IHaveConfig((ConfigurationSection) kv.getValue(), getPlugin()::saveConfig)));
if (res.size() == 0) {
for (val entry : defaultProvider.entrySet()) {
val conf = new IHaveConfig(cs.createSection(entry.getKey()));
val conf = new IHaveConfig(cs.createSection(entry.getKey()), getPlugin()::saveConfig);
entry.getValue().accept(conf);
res.put(entry.getKey(), conf);
}

View file

@ -2,12 +2,12 @@ package buttondevteam.lib.architecture;
import buttondevteam.core.MainPlugin;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.Array;
@ -23,7 +23,7 @@ import java.util.function.Function;
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
public class ConfigData<T> {
private static final HashMap<Configuration, BukkitTask> saveTasks= new HashMap<>();
private static final HashMap<Configuration, SaveTask> saveTasks = new HashMap<>();
/**
* May be null for testing
*/
@ -45,8 +45,12 @@ public class ConfigData<T> {
* The config value should not change outside this instance
*/
private T value;
/**
* Whether the default value is saved in the yaml
*/
private boolean saved = false;
//This constructor is needed because it sets the getter and setter
public ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
this.config = config;
this.path = path;
@ -88,9 +92,9 @@ public class ConfigData<T> {
else if (def instanceof Double)
val = ((Number) val).doubleValue();
}
if (val instanceof List && def.getClass().isArray())
if (val instanceof List && def != null && def.getClass().isArray())
val = ((List<T>) val).toArray((T[]) Array.newInstance(def.getClass().getComponentType(), 0));
return (T) val;
return value = (T) val; //Always cache, if not cached yet
}
public void set(T value) {
@ -102,15 +106,32 @@ public class ConfigData<T> {
config.set(path, val);
if(!saveTasks.containsKey(config.getRoot())) {
synchronized (saveTasks) {
saveTasks.put(config.getRoot(), Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
synchronized (saveTasks) {
saveTasks.remove(config.getRoot());
saveAction.run();
}
}, 100));
}, 100), saveAction));
}
}
}
this.value = value;
}
@AllArgsConstructor
private static class SaveTask {
BukkitTask task;
Runnable saveAction;
}
public static boolean saveNow(Configuration config) {
SaveTask st = saveTasks.get(config);
if (st != null) {
st.task.cancel();
saveTasks.remove(config);
st.saveAction.run();
return true;
}
return false;
}
}

View file

@ -13,8 +13,6 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.21" level="project" />
<orderEntry type="library" name="Maven: org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.json-simple:json-simple:1.1.1" level="project" />