Last active
July 12, 2018 18:50
-
-
Save Articdive/7edd4d8c420fc5c6aa8ff88d92256be1 to your computer and use it in GitHub Desktop.
CommentedConfiguration all important stuffs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.base.Charsets; | |
import com.google.common.io.Files; | |
import org.apache.commons.lang.Validate; | |
import org.bukkit.configuration.InvalidConfigurationException; | |
import org.bukkit.configuration.file.YamlConfiguration; | |
import org.bukkit.configuration.file.YamlConstructor; | |
import org.bukkit.configuration.file.YamlRepresenter; | |
import org.yaml.snakeyaml.DumperOptions; | |
import org.yaml.snakeyaml.Yaml; | |
import org.yaml.snakeyaml.representer.Representer; | |
import java.io.File; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStreamWriter; | |
import java.io.Writer; | |
import java.util.HashMap; | |
/** | |
* @author dumptruckman, LlmDL & Articdive | |
*/ | |
public class CommentedConfiguration extends YamlConfiguration { | |
private final DumperOptions yamlOptions = new DumperOptions(); | |
private final Representer yamlRepresenter = new YamlRepresenter(); | |
private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions); | |
private HashMap<String, String> comments; | |
private File file; | |
public CommentedConfiguration(File file) { | |
super(); | |
//this.load(file); | |
comments = new HashMap<>(); | |
this.file = file; | |
} | |
public boolean load() { | |
boolean loaded = true; | |
try { | |
this.load(file); | |
} catch (InvalidConfigurationException | IOException e) { | |
loaded = false; | |
} | |
return loaded; | |
} | |
public void save() { | |
boolean saved = true; | |
// Save the config just like normal | |
try { | |
/* | |
* Doing some saving of our own. We have found that the implementation of YAMLComfiguration used by Bukkit will attempt to | |
* cap strings at 80 characters long, forming new lines in some of our longer strings (channel_formats.) | |
*/ | |
this.save(file); | |
} catch (Exception e) { | |
saved = false; | |
} | |
// if there's comments to add and it saved fine, we need to add comments | |
if (!comments.isEmpty() && saved) { | |
// String array of each line in the config file | |
String[] yamlContents = FileMgmt.convertFileToString(file).split("[" + System.getProperty("line.separator") + "]"); | |
// This will hold the newly formatted line | |
StringBuilder newContents = new StringBuilder(); | |
// This holds the current path the lines are at in the config | |
String currentPath = ""; | |
// This flags if the line is a node or unknown text. | |
boolean node; | |
// The depth of the path. (number of words separated by periods - 1) | |
int depth = 0; | |
// Loop through the config lines | |
for (String line : yamlContents) { | |
// If the line is a node (and not something like a list value) | |
if (line.contains(": ") || (line.length() > 1 && line.charAt(line.length() - 1) == ':')) { | |
// This is a node so flag it as one | |
node = true; | |
// Grab the index of the end of the node name | |
int index; | |
index = line.indexOf(": "); | |
if (index < 0) { | |
index = line.length() - 1; | |
} | |
// If currentPath is empty, store the node name as the currentPath. (this is only on the first iteration, i think) | |
if (currentPath.isEmpty()) { | |
currentPath = line.substring(0, index); | |
} else { | |
// Calculate the whitespace preceding the node name | |
int whiteSpace = 0; | |
for (int n = 0; n < line.length(); n++) { | |
if (line.charAt(n) == ' ') { | |
whiteSpace++; | |
} else { | |
break; | |
} | |
} | |
// Find out if the current depth (whitespace * 2) is greater/lesser/equal to the previous depth | |
if (whiteSpace / 2 > depth) { | |
// Path is deeper. Add a . and the node name | |
currentPath += "." + line.substring(whiteSpace, index); | |
depth++; | |
} else if (whiteSpace / 2 < depth) { | |
// Path is shallower, calculate current depth from whitespace (whitespace / 2) and subtract that many levels from the currentPath | |
int newDepth = whiteSpace / 2; | |
for (int i = 0; i < depth - newDepth; i++) { | |
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), ""); | |
} | |
// Grab the index of the final period | |
int lastIndex = currentPath.lastIndexOf("."); | |
if (lastIndex < 0) { | |
// if there isn't a final period, set the current path to nothing because we're at root | |
currentPath = ""; | |
} else { | |
// If there is a final period, replace everything after it with nothing | |
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), ""); | |
currentPath += "."; | |
} | |
// Add the new node name to the path | |
currentPath += line.substring(whiteSpace, index); | |
// Reset the depth | |
depth = newDepth; | |
} else { | |
// Path is same depth, replace the last path node name to the current node name | |
int lastIndex = currentPath.lastIndexOf("."); | |
if (lastIndex < 0) { | |
// if there isn't a final period, set the current path to nothing because we're at root | |
currentPath = ""; | |
} else { | |
// If there is a final period, replace everything after it with nothing | |
currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), ""); | |
currentPath += "."; | |
} | |
//currentPath = currentPath.replace(currentPath.substring(currentPath.lastIndexOf(".")), ""); | |
currentPath += line.substring(whiteSpace, index); | |
} | |
} | |
} else | |
node = false; | |
if (node) { | |
String comment; | |
// If there's a comment for the current path, retrieve it and flag that path as already commented | |
comment = comments.get(currentPath); | |
if (comment != null) { | |
// Add the comment to the beginning of the current line | |
line = comment + System.getProperty("line.separator") + line + System.getProperty("line.separator"); | |
} else { | |
// Add a new line as it is a node, but has no comment | |
line += System.getProperty("line.separator"); | |
} | |
} | |
// Add the (modified) line to the total config String | |
newContents.append(line).append((!node) ? System.getProperty("line.separator") : ""); | |
} | |
/* | |
* Due to a bukkit bug we need to strip any extra new lines from the | |
* beginning of this file, else they will multiply. | |
*/ | |
while (newContents.toString().startsWith(System.getProperty("line.separator"))) | |
newContents = new StringBuilder(newContents.toString().replaceFirst(System.getProperty("line.separator"), "")); | |
// Write the string to the config file | |
FileMgmt.stringToFile(newContents.toString(), file); | |
} | |
} | |
/** | |
* Adds a comment just before the specified path. The comment can be | |
* multiple lines. An empty string will indicate a blank line. | |
* | |
* @param path Configuration path to add comment. | |
* @param commentLines Comments to add. One String per line. | |
*/ | |
public void addComment(String path, String... commentLines) { | |
StringBuilder commentstring = new StringBuilder(); | |
StringBuilder leadingSpaces = new StringBuilder(); | |
for (int n = 0; n < path.length(); n++) { | |
if (path.charAt(n) == '.') { | |
leadingSpaces.append(" "); | |
} | |
} | |
for (String line : commentLines) { | |
if (!line.isEmpty()) { | |
line = leadingSpaces + line; | |
} else { | |
line = ""; | |
} | |
if (commentstring.length() > 0) { | |
commentstring.append(System.getProperty("line.separator")); | |
} | |
commentstring.append(line); | |
} | |
comments.put(path, commentstring.toString()); | |
} | |
public void save(File file) throws IOException { | |
Validate.notNull(file, "File cannot be null"); | |
Files.createParentDirs(file); | |
String data = this.saveToString(); | |
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8)) { | |
writer.write(data); | |
} | |
} | |
@Override | |
public String saveToString() { | |
yamlOptions.setIndent(options().indent()); | |
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); | |
yamlOptions.setWidth(10000); | |
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); | |
String dump = yaml.dump(getValues(false)); | |
if (dump.equals(BLANK_CONFIG)) { | |
dump = ""; | |
} | |
return dump; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum ConfigNodes { | |
// Version: | |
VERSION_HEADER("version", ""), | |
VERSION( | |
"version.version", | |
"", | |
"# This is the current config version. Please do not edit."), | |
LAST_RUN_VERSION( | |
"version.last_run_version", | |
"", | |
"# This is the last version the config was run with, it's used to show changelogs! Please do not edit."), | |
// Database: | |
DATABASE_HEADER("database", "", | |
"############################################################", | |
"# +------------------------------------------------------+ #", | |
"# | Database Configuration | #", | |
"# +------------------------------------------------------+ #", | |
"############################################################"), | |
DATABASE_TABLE_PREFIX("database.table_prefix", "SWC_", "# Table prefix for SQL tables"), | |
// Database LOAD: | |
DATABASE_LOAD_HEADER("database.load", ""), | |
DATABASE_LOAD_TYPE("database.load.type", "h2", "# Load database type (options: h2, mysql)"), | |
DATABASE_LOAD_HOSTNAME("database.load.hostname", "localhost", "# Load database hostname"), | |
DATABASE_LOAD_PORT("database.load.port", "3306", "# Load database port"), | |
DATABASE_LOAD_SCHEMA_NAME("database.load.dbname", "townyeco", "# Load database schema / database"), | |
DATABASE_LOAD_USERNAME("database.load.username", "", "# Load database username"), | |
DATABASE_LOAD_PASSWORD("database.load.password", "", "# Load database password"), | |
// Database SAVE: | |
DATABASE_SAVE_HEADER("database.save", ""), | |
DATABASE_SAVE_TYPE("database.save.type", "h2", "# Save database type (options: h2, mysql)"), | |
DATABASE_SAVE_HOSTNAME("database.save.hostname", "localhost", "# Save database hostname"), | |
DATABASE_SAVE_PORT("database.save.port", "3306", "# Save database port"), | |
DATABASE_SAVE_SCHEMA_NAME("database.save.dbname", "townyeco", "# Save database schema / database"), | |
DATABASE_SAVE_USERNAME("database.save.username", "", "# Save database username"), | |
DATABASE_SAVE_PASSWORD("database.save.password", "", "# Save database password"); | |
private final String Root; | |
private final String Default; | |
private String[] comments; | |
ConfigNodes(String root, String def, String... comments) { | |
this.Root = root; | |
this.Default = def; | |
this.comments = comments; | |
} | |
/** | |
* Retrieves the root for a config option | |
* | |
* @return The root for a config option | |
*/ | |
public String getRoot() { | |
return Root; | |
} | |
/** | |
* Retrieves the default value for a config path | |
* | |
* @return The default value for a config path | |
*/ | |
public String getDefault() { | |
return Default; | |
} | |
/** | |
* Retrieves the comment for a config path | |
* | |
* @return The comments for a config path | |
*/ | |
public String[] getComments() { | |
if (comments != null) { | |
return comments; | |
} | |
String[] comments = new String[1]; | |
comments[0] = ""; | |
return comments; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.util.logging.Level; | |
public class ConfigurationHandler { | |
private static MainClass main; | |
private static CommentedConfiguration config, newConfig; | |
public static void initialize(MainClass main) { | |
ConfigurationHandler.main = main; | |
} | |
public static boolean loadSettings() { | |
FileMgmt.checkFolders(new String[]{ | |
main.getRootFolder(), | |
main.getRootFolder() + FileMgmt.fileSeparator() + "settings"}); | |
return ConfigurationHandler.loadConfig(); | |
} | |
private static boolean loadConfig() { | |
String filepath = main.getRootFolder() + FileMgmt.fileSeparator() + "settings" + FileMgmt.fileSeparator() + "config.yml"; | |
File file = FileMgmt.CheckYMLExists(new File(filepath)); | |
if (file != null) { | |
// read the config.yml into memory | |
config = new CommentedConfiguration(file); | |
if (!config.load()) { | |
main.getLogger().log(Level.SEVERE, "Failed to load config.yml"); | |
return false; | |
} | |
setDefaults(file); | |
config.save(); | |
} | |
return true; | |
} | |
/** | |
* Builds a new config reading old config data. | |
*/ | |
private static void setDefaults(File file) { | |
newConfig = new CommentedConfiguration(file); | |
newConfig.load(); | |
for (ConfigNodes root : ConfigNodes.values()) { | |
if (root.getComments().length > 0) { | |
addComment(root.getRoot(), root.getComments()); | |
} | |
if (root.getRoot().equals(ConfigNodes.VERSION.getRoot())) { | |
setNewProperty(root.getRoot(), main.getVersion()); | |
} else | |
setNewProperty(root.getRoot(), (config.get(root.getRoot().toLowerCase()) != null) ? config.get(root.getRoot().toLowerCase()) : root.getDefault()); | |
} | |
config = newConfig; | |
newConfig = null; | |
} | |
private static void addComment(String root, String... comments) { | |
newConfig.addComment(root.toLowerCase(), comments); | |
} | |
private static void setProperty(String root, Object value) { | |
config.set(root.toLowerCase(), value.toString()); | |
} | |
private static void setNewProperty(String root, Object value) { | |
if (value == null) { | |
// System.out.print("value is null for " + root.toLowerCase()); | |
value = ""; | |
} | |
newConfig.set(root.toLowerCase(), value.toString()); | |
} | |
/** | |
* Get's a value for a ConfigNode | |
* | |
* @param node - ConfigNode | |
* @return - Value for node | |
*/ | |
private static String getString(ConfigNodes node) { | |
return config.getString(node.getRoot().toLowerCase(), node.getDefault()); | |
} | |
/** | |
* Get's a value for a ConfigNode | |
* | |
* @param node - ConfigNode | |
* @return - Value for node (specifically boolean) | |
*/ | |
private static boolean getBoolean(ConfigNodes node) { | |
return Boolean.parseBoolean(config.getString(node.getRoot().toLowerCase(), node.getDefault())); | |
} | |
/** | |
* Get's a value for a ConfigNode | |
* | |
* @param node - ConfigNode | |
* @return - Value for node (specifically double) | |
*/ | |
private static double getDouble(ConfigNodes node) { | |
try { | |
return Double.parseDouble(config.getString(node.getRoot().toLowerCase(), node.getDefault()).trim()); | |
} catch (NumberFormatException e) { | |
main.getLogger().log(Level.SEVERE, "Could not get/read double for value: " + node.getRoot().toLowerCase()); | |
return 0.0; | |
} | |
} | |
/** | |
* Get's a value for a ConfigNode | |
* | |
* @param node - ConfigNode | |
* @return - Value for node (specifically int) | |
*/ | |
private static int getInt(ConfigNodes node) { | |
try { | |
return Integer.parseInt(config.getString(node.getRoot().toLowerCase(), node.getDefault()).trim()); | |
} catch (NumberFormatException e) { | |
main.getLogger().log(Level.SEVERE, "Could not get/read int for value: " + node.getRoot().toLowerCase()); | |
return 0; | |
} | |
} | |
public static String getDBTablePrefix() { | |
return getString(ConfigNodes.DATABASE_TABLE_PREFIX); | |
} | |
public static String getLoadDBType() { | |
return getString(ConfigNodes.DATABASE_LOAD_TYPE).toLowerCase(); | |
} | |
public static String getLoadDBHostname() { | |
return getString(ConfigNodes.DATABASE_LOAD_HOSTNAME); | |
} | |
public static String getLoadDBPort() { | |
return getString(ConfigNodes.DATABASE_LOAD_PORT); | |
} | |
public static String getLoadDBSchemaName() { | |
return getString(ConfigNodes.DATABASE_LOAD_SCHEMA_NAME); | |
} | |
public static String getLoadDBUsername() { | |
return getString(ConfigNodes.DATABASE_LOAD_USERNAME); | |
} | |
public static String getLoadDBPassword() { | |
return getString(ConfigNodes.DATABASE_LOAD_PASSWORD); | |
} | |
public static String getSaveDBType() { | |
return getString(ConfigNodes.DATABASE_SAVE_TYPE).toLowerCase(); | |
} | |
public static String getSaveDBHostname() { | |
return getString(ConfigNodes.DATABASE_SAVE_HOSTNAME); | |
} | |
public static String getSaveDBPort() { | |
return getString(ConfigNodes.DATABASE_SAVE_PORT); | |
} | |
public static String getSaveDBSchemaName() { | |
return getString(ConfigNodes.DATABASE_SAVE_SCHEMA_NAME); | |
} | |
public static String getSaveDBUsername() { | |
return getString(ConfigNodes.DATABASE_SAVE_USERNAME); | |
} | |
public static String getSaveDBPassword() { | |
return getString(ConfigNodes.DATABASE_SAVE_PASSWORD); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.OutputStreamWriter; | |
import java.io.Reader; | |
import java.io.StringWriter; | |
import java.io.Writer; | |
import java.util.logging.Level; | |
public class FileMgmt { | |
private static MainClass main; | |
public static void initialize(MainClass main) { | |
FileMgmt.main = main; | |
} | |
public static void checkFolders(String[] folders) { | |
for (String folder : folders) { | |
File f = new File(folder); | |
if (!(f.exists() && f.isDirectory())) { | |
f.getParentFile().mkdirs(); | |
f.mkdir(); | |
} | |
} | |
} | |
public static String fileSeparator() { | |
return System.getProperty("file.separator"); | |
} | |
public static File CheckYMLExists(File file) { | |
if (!file.exists()) { | |
try { | |
file.createNewFile(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
return file; | |
} | |
/** | |
* Pass a file and it will return it's contents as a string. | |
* | |
* @param file File to read. | |
* @return Contents of file. String will be empty in case of any errors. | |
*/ | |
public static String convertFileToString(File file) { | |
if (file != null && file.exists() && file.canRead() && !file.isDirectory()) { | |
Writer writer = new StringWriter(); | |
char[] buffer = new char[1024]; | |
try (InputStream is = new FileInputStream(file)) { | |
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); | |
int n; | |
while ((n = reader.read(buffer)) != -1) { | |
writer.write(buffer, 0, n); | |
} | |
reader.close(); | |
} catch (IOException e) { | |
main.getLogger().log(Level.SEVERE, "Exception: " + e.getMessage()); | |
} | |
return writer.toString(); | |
} else { | |
return ""; | |
} | |
} | |
/** | |
* Writes the contents of a string to a file. | |
* | |
* @param source String to write. | |
* @param file File to write to. | |
* @return True on success. | |
* @throws IOException | |
*/ | |
public static void stringToFile(String source, File file) { | |
try { | |
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); | |
out.write(source); | |
out.close(); | |
} catch (IOException e) { | |
main.getLogger().log(Level.SEVERE, "Exception: " + e.getMessage()); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import de.articdive.spigotormtemplate.utilities.FileMgmt; | |
import org.bukkit.Bukkit; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import java.util.logging.Level; | |
public final class MainClass extends JavaPlugin { | |
private String version; | |
@Override | |
public void onEnable() { | |
version = this.getDescription().getVersion(); | |
FileMgmt.initialize(this); | |
ConfigurationHandler.initialize(this); | |
// We need a configuration | |
if (!ConfigurationHandler.loadSettings()) { | |
getLogger().log(Level.SEVERE, "Configuration could not be loaded, disabling..."); | |
Bukkit.getPluginManager().disablePlugin(this); | |
return; | |
} | |
} | |
@Override | |
public void onDisable() { | |
// Plugin shutdown logic | |
} | |
public String getRootFolder() { | |
return this.getDataFolder().getPath(); | |
} | |
public String getVersion() { | |
return version; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment