From be278ad78196c4388b7e732226f19f7fe0796788 Mon Sep 17 00:00:00 2001 From: Sauilitired Date: Tue, 23 Sep 2014 19:02:17 +0200 Subject: [PATCH] Improved flag system. --- .idea/sqldialects.xml | 7 + .idea/workspace.xml | 725 ++++++++++-------- .../plot/AbstractFlag.java | 18 + .../com/intellectualcrafters/plot/Flag.java | 19 +- .../plot/FlagManager.java | 45 ++ .../intellectualcrafters/plot/Metrics.java | 671 ++++++++++++++++ .../intellectualcrafters/plot/PlotMain.java | 83 +- .../intellectualcrafters/plot/Settings.java | 17 +- .../plot/WorldGenerator.java | 4 +- .../intellectualcrafters/plot/XPopulator.java | 1 + .../plot/database/DBFunc.java | 296 +++---- .../plot/database/FlatFileManager.java | 7 + .../plot/database/SQLite.java | 103 +++ 13 files changed, 1517 insertions(+), 479 deletions(-) create mode 100644 .idea/sqldialects.xml create mode 100644 PlotSquared/src/com/intellectualcrafters/plot/AbstractFlag.java create mode 100644 PlotSquared/src/com/intellectualcrafters/plot/FlagManager.java create mode 100644 PlotSquared/src/com/intellectualcrafters/plot/Metrics.java create mode 100644 PlotSquared/src/com/intellectualcrafters/plot/database/FlatFileManager.java create mode 100644 PlotSquared/src/com/intellectualcrafters/plot/database/SQLite.java diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 000000000..0f0956929 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index aca2d4b7a..b38151cfb 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -12,9 +12,19 @@ - + + + + + + + - + + + + + @@ -38,77 +48,61 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + @@ -117,49 +111,75 @@ - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + + + + + + + + + + + @@ -191,7 +211,14 @@ @@ -440,10 +493,12 @@ - + + + @@ -467,14 +522,10 @@ - - - - + + + - + - + - - - + + + - - + + - + @@ -837,7 +895,8 @@ - @@ -849,128 +908,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1058,14 +995,14 @@ - - - + + + @@ -1095,20 +1032,6 @@ - - - - - - - - - - - - - - @@ -1124,13 +1047,6 @@ - - - - - - - @@ -1138,27 +1054,10 @@ - - - - - - - - - - - - - - - - - @@ -1198,7 +1097,6 @@ - @@ -1207,64 +1105,289 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PlotSquared/src/com/intellectualcrafters/plot/AbstractFlag.java b/PlotSquared/src/com/intellectualcrafters/plot/AbstractFlag.java new file mode 100644 index 000000000..747322e33 --- /dev/null +++ b/PlotSquared/src/com/intellectualcrafters/plot/AbstractFlag.java @@ -0,0 +1,18 @@ +package com.intellectualcrafters.plot; + +/** + * Created by Citymonstret on 2014-09-23. + */ +public class AbstractFlag { + + private final String key; + + public AbstractFlag(String key) { + this.key = key; + } + + public String getKey() { + return this.key; + } + +} diff --git a/PlotSquared/src/com/intellectualcrafters/plot/Flag.java b/PlotSquared/src/com/intellectualcrafters/plot/Flag.java index d8ea16439..53d32bdc1 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/Flag.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/Flag.java @@ -4,20 +4,21 @@ import org.apache.commons.lang.StringUtils; import org.bukkit.ChatColor; public class Flag { - private String key; + private AbstractFlag key; private String value; - public Flag(String key, String value) { - if (!StringUtils.isAlphanumeric(key) || !StringUtils.isAlphanumeric(ChatColor.stripColor(value).replace(" ", ""))) + public Flag(AbstractFlag key, String value) { + if (!StringUtils.isAlphanumeric(ChatColor.stripColor(value).replace(" ", ""))) throw new IllegalArgumentException("Flag must be alphanumerical"); - if (key.length()>16) - throw new IllegalArgumentException("Key must be <= 16 characters"); + /*if (key.length()>16) + throw new IllegalArgumentException("Key must be <= 16 characters");*/ if (value.length()>48) throw new IllegalArgumentException("Value must be <= 48 characters"); - this.key = key.toLowerCase(); + this.key = key; this.value = value; } + public AbstractFlag getAbstractFlag() { return this.key; } public String getKey() { - return this.key; + return this.key.getKey(); } public String getValue() { return this.value; @@ -25,7 +26,7 @@ public class Flag { @Override public String toString() { if (this.value.equals("")) { - return this.key; + return this.key.getKey(); } return this.key+":"+this.value; } @@ -42,6 +43,6 @@ public class Flag { } @Override public int hashCode() { - return key.hashCode(); + return key.getKey().hashCode(); } } diff --git a/PlotSquared/src/com/intellectualcrafters/plot/FlagManager.java b/PlotSquared/src/com/intellectualcrafters/plot/FlagManager.java new file mode 100644 index 000000000..619e86424 --- /dev/null +++ b/PlotSquared/src/com/intellectualcrafters/plot/FlagManager.java @@ -0,0 +1,45 @@ +package com.intellectualcrafters.plot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class FlagManager { + + private static ArrayList flags; + + public static boolean addFlag(AbstractFlag flag) { + if(getFlag(flag.getKey()) != null) { + return false; + } + return flags.add(flag); + } + + public static List getFlags() { + return flags; + } + + public static AbstractFlag getFlag(String string) { + for(AbstractFlag flag : flags) { + if(flag.getKey().equalsIgnoreCase(string)) { + return flag; + } + } + return null; + } + + public static AbstractFlag getFlag(String string, boolean create) { + if(getFlag(string) == null && create) { + AbstractFlag flag = new AbstractFlag(string); + return flag; + } + return getFlag(string); + } + + public static List getPlotFlags(Plot plot) { + Set plotFlags = plot.settings.getFlags(); + List flags = new ArrayList<>(); + for(Flag flag : plotFlags) flags.add(flag.getAbstractFlag()); + return flags; + } +} diff --git a/PlotSquared/src/com/intellectualcrafters/plot/Metrics.java b/PlotSquared/src/com/intellectualcrafters/plot/Metrics.java new file mode 100644 index 000000000..4ba7697a9 --- /dev/null +++ b/PlotSquared/src/com/intellectualcrafters/plot/Metrics.java @@ -0,0 +1,671 @@ +package com.intellectualcrafters.plot; + +/* +* Copyright 2011-2013 Tyler Blair. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and contributors and should not be interpreted as representing official policies, +* either expressed or implied, of anybody else. +*/ + +import org.bukkit.Bukkit; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.scheduler.BukkitTask; + +import java.io.*; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.*; +import java.util.logging.Level; +import java.util.zip.GZIPOutputStream; + +public class Metrics { + /** + * The current revision number + */ + private final static int REVISION = 7; + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://report.mcstats.org"; + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/plugin/%s"; + /** + * Interval of time to ping (in minutes) + */ + private static final int PING_INTERVAL = 15; + /** + * The plugin this metrics submits for + */ + private final Plugin plugin; + /** + * All of the custom graphs to submit to metrics + */ + private final Set graphs = Collections.synchronizedSet(new HashSet()); + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + /** + * The plugin configuration file + */ + private final File configurationFile; + /** + * Unique server id + */ + private final String guid; + /** + * Debug mode + */ + private final boolean debug; + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + /** + * The scheduled task + */ + private volatile BukkitTask task = null; + + public Metrics(final Plugin plugin) throws IOException { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + this.plugin = plugin; +// load the config + configurationFile = getConfigFile(); + configuration = YamlConfiguration.loadConfiguration(configurationFile); +// add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + configuration.addDefault("debug", false); +// Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); + } +// Load the guid then + guid = configuration.getString("guid"); + debug = configuration.getBoolean("debug", false); + } + + /** + * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics + * website. Plotters can be added to the graph object returned. + * + * @param name The name of the graph + * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given + */ + public Graph createGraph(final String name) { + if (name == null) { + throw new IllegalArgumentException("Graph name cannot be null"); + } +// Construct the graph object + final Graph graph = new Graph(name); +// Now we can add our graph + graphs.add(graph); +// and return back + return graph; + } + + /** + * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend + * + * @param graph The name of the graph + */ + public void addGraph(final Graph graph) { + if (graph == null) { + throw new IllegalArgumentException("Graph cannot be null"); + } + graphs.add(graph); + } + + /** + * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the + * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 + * ticks. + * + * @return True if statistics measuring is running, otherwise false. + */ + public boolean start() { + synchronized (optOutLock) { +// Did we opt out? + if (isOptOut()) { + return false; + } +// Is metrics already running? + if (task != null) { + return true; + } +// Begin hitting the server with glorious data + task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + private boolean firstPost = true; + + public void run() { + try { +// This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) { +// Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && task != null) { + task.cancel(); + task = null; +// Tell all plotters to stop gathering information. + for (Graph graph : graphs) { + graph.onOptOut(); + } + } + } +// We use the inverse of firstPost because if it is the first time we are posting, +// it is not a interval ping, so it evaluates to FALSE +// Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); +// After the first post we set firstPost to false +// Each post thereafter will be a ping + firstPost = false; + } catch (IOException e) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + } + }, 0, PING_INTERVAL * 1200); + return true; + } + } + + /** + * Has the server owner denied plugin metrics? + * + * @return true if metrics should be opted out of it + */ + public boolean isOptOut() { + synchronized (optOutLock) { + try { +// Reload the metrics file + configuration.load(getConfigFile()); + } catch (IOException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } catch (InvalidConfigurationException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } + return configuration.getBoolean("opt-out", false); + } + } + + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws java.io.IOException + */ + public void enable() throws IOException { +// This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { +// Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } +// Enable Task, if it is not running + if (task == null) { + start(); + } + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws java.io.IOException + */ + public void disable() throws IOException { +// This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { +// Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } +// Disable Task, if it is running + if (task != null) { + task.cancel(); + task = null; + } + } + } + + /** + * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status + * + * @return the File object for the config file + */ + public File getConfigFile() { +// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use +// is to abuse the plugin object we already have +// plugin.getDataFolder() => base/plugins/PluginA/ +// pluginsFolder => base/plugins/ +// The base is not necessarily relative to the startup directory. + File pluginsFolder = plugin.getDataFolder().getParentFile(); +// return => base/plugins/PluginMetrics/config.yml + return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); + } + + /** + * Generic method that posts a plugin to the metrics website + */ + private void postPlugin(final boolean isPing) throws IOException { +// Server software specific section + PluginDescriptionFile description = plugin.getDescription(); + String pluginName = description.getName(); + boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled + String pluginVersion = description.getVersion(); + String serverVersion = Bukkit.getVersion(); + int playersOnline = Bukkit.getServer().getOnlinePlayers().length; +// END server software specific section -- all code below does not use any code outside of this class / Java +// Construct the post data + StringBuilder json = new StringBuilder(1024); + json.append('{'); +// The plugin's description file containg all of the plugin data such as name, version, author, etc + appendJSONPair(json, "guid", guid); + appendJSONPair(json, "plugin_version", pluginVersion); + appendJSONPair(json, "server_version", serverVersion); + appendJSONPair(json, "players_online", Integer.toString(playersOnline)); +// New data as of R6 + String osname = System.getProperty("os.name"); + String osarch = System.getProperty("os.arch"); + String osversion = System.getProperty("os.version"); + String java_version = System.getProperty("java.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); +// normalize os arch .. amd64 -> x86_64 + if (osarch.equals("amd64")) { + osarch = "x86_64"; + } + appendJSONPair(json, "osname", osname); + appendJSONPair(json, "osarch", osarch); + appendJSONPair(json, "osversion", osversion); + appendJSONPair(json, "cores", Integer.toString(coreCount)); + appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); + appendJSONPair(json, "java_version", java_version); +// If we're pinging, append it + if (isPing) { + appendJSONPair(json, "ping", "1"); + } + if (graphs.size() > 0) { + synchronized (graphs) { + json.append(','); + json.append('"'); + json.append("graphs"); + json.append('"'); + json.append(':'); + json.append('{'); + boolean firstGraph = true; + final Iterator iter = graphs.iterator(); + while (iter.hasNext()) { + Graph graph = iter.next(); + StringBuilder graphJson = new StringBuilder(); + graphJson.append('{'); + for (Plotter plotter : graph.getPlotters()) { + appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); + } + graphJson.append('}'); + if (!firstGraph) { + json.append(','); + } + json.append(escapeJSON(graph.getName())); + json.append(':'); + json.append(graphJson); + firstGraph = false; + } + json.append('}'); + } + } +// close json + json.append('}'); +// Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); +// Connect to the website + URLConnection connection; +// Mineshafter creates a socks proxy, so we can safely bypass it +// It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + byte[] uncompressed = json.toString().getBytes(); + byte[] compressed = gzip(json.toString()); +// Headers + connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.setDoOutput(true); + if (debug) { + System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); + } +// Write the data + OutputStream os = connection.getOutputStream(); + os.write(compressed); + os.flush(); +// Now read the response + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String response = reader.readLine(); +// close resources + os.close(); + reader.close(); + if (response == null || response.startsWith("ERR") || response.startsWith("7")) { + if (response == null) { + response = "null"; + } else if (response.startsWith("7")) { + response = response.substring(response.startsWith("7,") ? 2 : 1); + } + throw new IOException(response); + } else { +// Is this the first update this hour? + if (response.equals("1") || response.contains("This is your first update this hour")) { + synchronized (graphs) { + final Iterator iter = graphs.iterator(); + while (iter.hasNext()) { + final Graph graph = iter.next(); + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } + } + } + } + } + } + + /** + * GZip compress a string of bytes + * + * @param input + * @return + */ + public static byte[] gzip(String input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzos = null; + try { + gzos = new GZIPOutputStream(baos); + gzos.write(input.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (gzos != null) try { + gzos.close(); + } catch (IOException ignore) { + } + } + return baos.toByteArray(); + } + + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return true if mineshafter is installed on the server + */ + private boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Appends a json encoded key/value pair to the given string builder. + * + * @param json + * @param key + * @param value + * @throws UnsupportedEncodingException + */ + private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { + boolean isValueNumeric = false; + try { + if (value.equals("0") || !value.endsWith("0")) { + Double.parseDouble(value); + isValueNumeric = true; + } + } catch (NumberFormatException e) { + isValueNumeric = false; + } + if (json.charAt(json.length() - 1) != '{') { + json.append(','); + } + json.append(escapeJSON(key)); + json.append(':'); + if (isValueNumeric) { + json.append(value); + } else { + json.append(escapeJSON(value)); + } + } + + /** + * Escape a string to create a valid JSON string + * + * @param text + * @return + */ + private static String escapeJSON(String text) { + StringBuilder builder = new StringBuilder(); + builder.append('"'); + for (int index = 0; index < text.length(); index++) { + char chr = text.charAt(index); + switch (chr) { + case '"': + case '\\': + builder.append('\\'); + builder.append(chr); + break; + case '\b': + builder.append("\\b"); + break; + case '\t': + builder.append("\\t"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + default: + if (chr < ' ') { + String t = "000" + Integer.toHexString(chr); + builder.append("\\u" + t.substring(t.length() - 4)); + } else { + builder.append(chr); + } + break; + } + } + builder.append('"'); + return builder.toString(); + } + + /** + * Encode text as UTF-8 + * + * @param text the text to encode + * @return the encoded text, as UTF-8 + */ + private static String urlEncode(final String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } + + /** + * Represents a custom graph on the website + */ + public static class Graph { + /** + * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is + * rejected + */ + private final String name; + /** + * The set of plotters that are contained within this graph + */ + private final Set plotters = new LinkedHashSet(); + + private Graph(final String name) { + this.name = name; + } + + /** + * Gets the graph's name + * + * @return the Graph's name + */ + public String getName() { + return name; + } + + /** + * Add a plotter to the graph, which will be used to plot entries + * + * @param plotter the plotter to add to the graph + */ + public void addPlotter(final Plotter plotter) { + plotters.add(plotter); + } + + /** + * Remove a plotter from the graph + * + * @param plotter the plotter to remove from the graph + */ + public void removePlotter(final Plotter plotter) { + plotters.remove(plotter); + } + + /** + * Gets an unmodifiable set of the plotter objects in the graph + * + * @return an unmodifiable {@link java.util.Set} of the plotter objects + */ + public Set getPlotters() { + return Collections.unmodifiableSet(plotters); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Graph)) { + return false; + } + final Graph graph = (Graph) object; + return graph.name.equals(name); + } + + /** + * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. + */ + protected void onOptOut() { + } + } + + /** + * Interface used to collect custom data for a plugin + */ + public static abstract class Plotter { + /** + * The plot's name + */ + private final String name; + + /** + * Construct a plotter with the default plot name + */ + public Plotter() { + this("Default"); + } + + /** + * Construct a plotter with a specific plot name + * + * @param name the name of the plotter to use, which will show up on the website + */ + public Plotter(final String name) { + this.name = name; + } + + /** + * Get the current value for the plotted point. Since this function defers to an external function it may or may + * not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called + * from any thread so care should be taken when accessing resources that need to be synchronized. + * + * @return the current value for the point to be plotted. + */ + public abstract int getValue(); + + /** + * Get the column name for the plotted point + * + * @return the plotted point's column name + */ + public String getColumnName() { + return name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Plotter)) { + return false; + } + final Plotter plotter = (Plotter) object; + return plotter.name.equals(name) && plotter.getValue() == getValue(); + } + } +} diff --git a/PlotSquared/src/com/intellectualcrafters/plot/PlotMain.java b/PlotSquared/src/com/intellectualcrafters/plot/PlotMain.java index be5a9fb0c..c7ad39463 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/PlotMain.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/PlotMain.java @@ -10,7 +10,6 @@ package com.intellectualcrafters.plot; import ca.mera.CameraAPI; - import com.intellectualcrafters.plot.Logger.LogLevel; import com.intellectualcrafters.plot.Settings.Web; import com.intellectualcrafters.plot.commands.Camera; @@ -18,14 +17,13 @@ import com.intellectualcrafters.plot.commands.MainCommand; import com.intellectualcrafters.plot.database.DBFunc; import com.intellectualcrafters.plot.database.MySQL; import com.intellectualcrafters.plot.database.PlotMeConverter; +import com.intellectualcrafters.plot.database.SQLite; import com.intellectualcrafters.plot.events.PlayerTeleportToPlotEvent; import com.intellectualcrafters.plot.events.PlotDeleteEvent; import com.intellectualcrafters.plot.listeners.PlayerEvents; import com.intellectualcrafters.plot.listeners.WorldEditListener; import com.sk89q.worldedit.bukkit.WorldEditPlugin; - import me.confuser.barapi.BarAPI; - import org.bukkit.*; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; @@ -354,17 +352,39 @@ public class PlotMain extends JavaPlugin { Logger.setup(log); Logger.add(LogLevel.GENERAL, "Logger enabled"); } + + private static double getJavaVersion() { + return Double.parseDouble(System.getProperty("java.specification.version")); + } + /** * On Load. - * TODO: Load updates async */ @Override @SuppressWarnings("deprecation") public void onEnable() { setupLogger(); + //Check for outdated java version. + if(getJavaVersion() < 1.7) { + sendConsoleSenderMessage(C.PREFIX.s() + "&cYour java version is outdated. Please update to at least 1.7."); + sendConsoleSenderMessage(C.PREFIX.s() + "&cURL: &6https://java.com/en/download/index.jsp"); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + configs(); + if(Settings.METRICS) { + try { + Metrics metrics = new Metrics(this); + metrics.start(); + sendConsoleSenderMessage(C.PREFIX.s() + "&6Metrics enabled."); + } catch(Exception e) { + sendConsoleSenderMessage(C.PREFIX.s() + "&cFailed to load up metrics."); + } + } + // TODO make this configurable PlotWorld.BLOCKS = new ArrayList<>(Arrays.asList(new Material[]{ ACACIA_STAIRS, BEACON, BEDROCK, @@ -416,7 +436,7 @@ public class PlotMain extends JavaPlugin { DatabaseMetaData meta = connection.getMetaData(); ResultSet res = meta.getTables(null, null, "plot", null); if(!res.next()) - DBFunc.createTables(); + DBFunc.createTables("mysql"); } } catch (ClassNotFoundException | SQLException e) { Logger.add(LogLevel.DANGER, "MySQL connection failed."); @@ -430,6 +450,24 @@ public class PlotMain extends JavaPlugin { } else if (Settings.DB.USE_MONGO) { sendConsoleSenderMessage(C.PREFIX.s() + "MongoDB is not yet implemented"); + } else if (Settings.DB.USE_SQLITE) { + try { + connection = new SQLite(this, Settings.DB.SQLITE_DB + ".db").openConnection(); + { + DatabaseMetaData meta = connection.getMetaData(); + ResultSet res = meta.getTables(null, null, "plot", null); + if(!res.next()) + DBFunc.createTables("sqlite"); + } + } catch (ClassNotFoundException | SQLException e) { + Logger.add(LogLevel.DANGER, "SQLite connection failed"); + sendConsoleSenderMessage(C.PREFIX.s() + "&cFailed to open SQLite connection. The plugin will disable itself."); + sendConsoleSenderMessage("&9==== Here is an ugly stacktrace, if you are interested in those things ==="); + e.printStackTrace(); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + plots = DBFunc.getPlots(); } else { Logger.add(LogLevel.DANGER, "No storage type is set."); sendConsoleSenderMessage(C.PREFIX + "&cNo storage type is set!"); @@ -651,17 +689,20 @@ public class PlotMain extends JavaPlugin { e.printStackTrace(); } { - Settings.DB.USE_MYSQL = true; - Settings.DB.USER = storage.getString("mysql_user"); - Settings.DB.PASSWORD = storage.getString("mysql_password"); - Settings.DB.HOST_NAME = storage.getString("mysql_host"); - Settings.DB.PORT = storage.getString("mysql_port"); - Settings.DB.DATABASE = storage.getString("mysql_database"); + Settings.DB.USE_MYSQL = storage.getBoolean("mysql.use"); + Settings.DB.USER = storage.getString("mysql.user"); + Settings.DB.PASSWORD = storage.getString("mysql.password"); + Settings.DB.HOST_NAME = storage.getString("mysql.host"); + Settings.DB.PORT = storage.getString("mysql.port"); + Settings.DB.DATABASE = storage.getString("mysql.database"); + Settings.DB.USE_SQLITE = storage.getBoolean("sqlite.use"); + Settings.DB.SQLITE_DB = storage.getString("sqlite.db"); } { + Settings.METRICS = config.getBoolean("metrics"); //Web - Web.ENABLED = config.getBoolean("web.enabled"); - Web.PORT = config.getInt("web.port"); + //Web.ENABLED = config.getBoolean("web.enabled"); + //Web.PORT = config.getInt("web.port"); } } @@ -720,10 +761,11 @@ public class PlotMain extends JavaPlugin { private static void setupConfig() { config.set("version", config_ver); Map options = new HashMap(); - options.put("auto_update", false); + //options.put("auto_update", false); options.put("kill_road_mobs", Settings.KILL_ROAD_MOBS_DEFAULT); options.put("web.enabled", Web.ENABLED); options.put("web.port", Web.PORT); + options.put("metrics", true); for (Entry node : options.entrySet()) { if (!config.contains(node.getKey())) { config.set(node.getKey(), node.getValue()); @@ -753,11 +795,14 @@ public class PlotMain extends JavaPlugin { private static void setupStorage() { storage.set("version", storage_ver); Map options = new HashMap(); - options.put("mysql_host", "localhost"); - options.put("mysql_port", "3306"); - options.put("mysql_user", "root"); - options.put("mysql_password", "password"); - options.put("mysql_database", "plot_db"); + options.put("mysql.use", true); + options.put("sqlite.use", false); + options.put("sqllite.db", "storage"); + options.put("mysql.host", "localhost"); + options.put("mysql.port", "3306"); + options.put("mysql.user", "root"); + options.put("mysql.password", "password"); + options.put("mysql.database", "plot_db"); for (Entry node : options.entrySet()) { if (!storage.contains(node.getKey())) { storage.set(node.getKey(), node.getValue()); diff --git a/PlotSquared/src/com/intellectualcrafters/plot/Settings.java b/PlotSquared/src/com/intellectualcrafters/plot/Settings.java index 3e09cbe94..75538a616 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/Settings.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/Settings.java @@ -9,11 +9,6 @@ package com.intellectualcrafters.plot; -import org.bukkit.Material; - -import java.util.ArrayList; -import java.util.List; - /** * Updater and DB settings * @author Citymonstret @@ -21,6 +16,7 @@ import java.util.List; * @author Empire92 */ public class Settings { + public static boolean METRICS = true; /** * plot specific resource pack */ @@ -42,6 +38,7 @@ public class Settings { public static class Update { /** * Update plugin? + * @deprecated */ public static boolean AUTO_UPDATE = false; } @@ -58,11 +55,13 @@ public class Settings { */ public static class DB { public static boolean USE_MONGO = false; /* TODO: Implement Mongo */; - public static boolean USE_MYSQL = true; /* NOTE: Fixed connector */ + public static boolean USE_SQLITE = false; + public static boolean USE_MYSQL = true; /* NOTE: Fixed connector */ + public static String SQLITE_DB = "storage"; public static String HOST_NAME = "localhost"; public static String PORT = "3306"; - public static String DATABASE = "plot_db"; - public static String USER = "root"; - public static String PASSWORD = "password"; + public static String DATABASE = "plot_db"; + public static String USER = "root"; + public static String PASSWORD = "password"; } } \ No newline at end of file diff --git a/PlotSquared/src/com/intellectualcrafters/plot/WorldGenerator.java b/PlotSquared/src/com/intellectualcrafters/plot/WorldGenerator.java index a3d66637d..f2599a737 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/WorldGenerator.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/WorldGenerator.java @@ -113,9 +113,9 @@ public class WorldGenerator extends ChunkGenerator { for (int i = 0; i < default_flags.length; i++) { String current = default_flags_string[i]; if (current.contains(",")) - default_flags[i] = new Flag(current.split(",")[0], current.split(",")[1]); + default_flags[i] = new Flag(FlagManager.getFlag(current.split(",")[0], true), current.split(",")[1]); else - default_flags[i] = new Flag(current, ""); + default_flags[i] = new Flag(FlagManager.getFlag(current, true), ""); } plotworld.DEFAULT_FLAGS = default_flags; diff --git a/PlotSquared/src/com/intellectualcrafters/plot/XPopulator.java b/PlotSquared/src/com/intellectualcrafters/plot/XPopulator.java index b6f219b1b..c491b1b9b 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/XPopulator.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/XPopulator.java @@ -15,6 +15,7 @@ import java.util.Random; */ public class XPopulator extends BlockPopulator { private SetBlockFast setBlockClass = null; + public XPopulator() { try { setBlockClass = new SetBlockFast(); diff --git a/PlotSquared/src/com/intellectualcrafters/plot/database/DBFunc.java b/PlotSquared/src/com/intellectualcrafters/plot/database/DBFunc.java index 7491b7ef2..904583a15 100644 --- a/PlotSquared/src/com/intellectualcrafters/plot/database/DBFunc.java +++ b/PlotSquared/src/com/intellectualcrafters/plot/database/DBFunc.java @@ -8,6 +8,7 @@ */ package com.intellectualcrafters.plot.database; + import com.intellectualcrafters.plot.*; import com.intellectualcrafters.plot.Logger.LogLevel; import org.bukkit.OfflinePlayer; @@ -22,14 +23,13 @@ import java.util.UUID; import static com.intellectualcrafters.plot.PlotMain.connection; /** - * * @author Citymonstret - * */ public class DBFunc { /** * Set Plot owner + * * @param plot * @param uuid */ @@ -44,7 +44,7 @@ public class DBFunc { statement.setInt(3, plot.id.y); statement.executeUpdate(); statement.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); Logger.add(LogLevel.DANGER, "Could not set owner for plot " + plot.id); } @@ -54,6 +54,7 @@ public class DBFunc { /** * Create a plot + * * @param plot */ public static void createPlot(Plot plot) { @@ -74,59 +75,86 @@ public class DBFunc { /** * Create tables + * * @throws SQLException */ - public static void createTables() throws SQLException{ + public static void createTables(String database) throws SQLException { + boolean mysql = database.equals("mysql"); + Statement stmt = connection.createStatement(); - stmt.addBatch( - "CREATE TABLE IF NOT EXISTS `plot` (" + - "`id` int(11) NOT NULL AUTO_INCREMENT," + - "`plot_id_x` int(11) NOT NULL," + - "`plot_id_z` int(11) NOT NULL," + - "`owner` varchar(45) NOT NULL," + - "`world` varchar(45) NOT NULL," + - "`timestamp` timestamp not null DEFAULT CURRENT_TIMESTAMP," + - "PRIMARY KEY (`id`)" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); - stmt.addBatch( - "CREATE TABLE IF NOT EXISTS `plot_helpers` (" + - "`plot_plot_id` int(11) NOT NULL," + - "`user_uuid` varchar(40) NOT NULL" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8" - ); + if (mysql) { + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot` (" + + "`id` INT(11) NOT NULL AUTO_INCREMENT," + + "`plot_id_x` INT(11) NOT NULL," + + "`plot_id_z` INT(11) NOT NULL," + + "`owner` VARCHAR(45) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP," + + "PRIMARY KEY (`id`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0"); + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot_denied` (" + + "`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8" + ); + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot_settings` (" + + " `plot_plot_id` INT(11) NOT NULL," + + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + + " `rain` INT(1) DEFAULT 0," + + " `custom_time` TINYINT(1) DEFAULT '0'," + + " `time` INT(11) DEFAULT '8000'," + + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + + " `flags` VARCHAR(512) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`plot_plot_id`)," + + " UNIQUE KEY `unique_alias` (`alias`)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8" + ); + stmt.addBatch( + "ALTER TABLE `plot_settings` ADD CONSTRAINT `plot_settings_ibfk_1` FOREIGN KEY (`plot_plot_id`) REFERENCES `plot` (`id`) ON DELETE CASCADE" + ); - stmt.addBatch( - "CREATE TABLE IF NOT EXISTS `plot_denied` (" + - "`plot_plot_id` int(11) NOT NULL," + - "`user_uuid` varchar(40) NOT NULL" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8" - ); - - stmt.addBatch( - "CREATE TABLE IF NOT EXISTS `plot_settings` (" + - " `plot_plot_id` INT(11) NOT NULL," + - " `biome` VARCHAR(45) DEFAULT 'FOREST'," + - " `rain` INT(1) DEFAULT 0," + - " `custom_time` TINYINT(1) DEFAULT '0'," + - " `time` INT(11) DEFAULT '8000'," + - " `deny_entry` TINYINT(1) DEFAULT '0'," + - " `alias` VARCHAR(50) DEFAULT NULL," + - " `flags` VARCHAR(512) DEFAULT NULL," + - " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + - " PRIMARY KEY (`plot_plot_id`)," + - " UNIQUE KEY `unique_alias` (`alias`)" + - ") ENGINE=InnoDB DEFAULT CHARSET=utf8" - ); - - stmt.addBatch( - "ALTER TABLE `plot_settings` ADD CONSTRAINT `plot_settings_ibfk_1` FOREIGN KEY (`plot_plot_id`) REFERENCES `plot` (`id`) ON DELETE CASCADE" - ); + } else { + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot` (" + + "`id` INTEGER(11) PRIMARY KEY," + + "`plot_id_x` INT(11) NOT NULL," + + "`plot_id_z` INT(11) NOT NULL," + + "`owner` VARCHAR(45) NOT NULL," + + "`world` VARCHAR(45) NOT NULL," + + "`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP)" + ); + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot_denied` (" + + "`plot_plot_id` INT(11) NOT NULL," + + "`user_uuid` VARCHAR(40) NOT NULL" + + ")" + ); + stmt.addBatch( + "CREATE TABLE IF NOT EXISTS `plot_settings` (" + + " `plot_plot_id` INT(11) NOT NULL," + + " `biome` VARCHAR(45) DEFAULT 'FOREST'," + + " `rain` INT(1) DEFAULT 0," + + " `custom_time` TINYINT(1) DEFAULT '0'," + + " `time` INT(11) DEFAULT '8000'," + + " `deny_entry` TINYINT(1) DEFAULT '0'," + + " `alias` VARCHAR(50) DEFAULT NULL," + + " `flags` VARCHAR(512) DEFAULT NULL," + + " `position` VARCHAR(50) NOT NULL DEFAULT 'DEFAULT'," + + " PRIMARY KEY (`plot_plot_id`)" + + ")" + ); + } stmt.executeBatch(); stmt.clearBatch(); stmt.close(); - + /** * Adding missing columns (for older versions) * + get current columns (continue if they do not match the current number of columns) @@ -134,8 +162,8 @@ public class DBFunc { * - create column (plot_id_x,plot_id_z,world) * - populate plot_id_x, plot_id_z with data from plot_id * - populate world column with PlotMain.config.getString("plot_world") - which will be set from previous release; - */ - + */ + /** * `plot` */ @@ -160,16 +188,17 @@ public class DBFunc { /** * Delete a plot + * * @param plot */ public static void delete(final String world, final Plot plot) { - boolean result = PlotMain.removePlot(world,plot.id); + boolean result = PlotMain.removePlot(world, plot.id); if (result) { runTask(new Runnable() { @Override public void run() { PreparedStatement stmt = null; - int id = getId(world,plot.id); + int id = getId(world, plot.id); try { stmt = connection.prepareStatement("DELETE FROM `plot_settings` WHERE `plot_plot_id` = ?"); stmt.setInt(1, id); @@ -194,6 +223,7 @@ public class DBFunc { /** * Create plot settings + * * @param id * @param plot */ @@ -208,7 +238,7 @@ public class DBFunc { stmt.setInt(1, id); stmt.executeUpdate(); stmt.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); } @@ -260,15 +290,14 @@ public class DBFunc { }*/ /** - * * @return */ - public static HashMap> getPlots() { + public static HashMap> getPlots() { try { DatabaseMetaData data = connection.getMetaData(); ResultSet rs = data.getColumns(null, null, "plot", "plot_id"); boolean execute = rs.next(); - if(execute) { + if (execute) { Statement statement = connection.createStatement(); statement.addBatch( "ALTER IGNORE TABLE `plot` ADD `plot_id_x` int(11) DEFAULT 0" @@ -278,16 +307,16 @@ public class DBFunc { ); statement.addBatch( "UPDATE `plot` SET\n" + - " `plot_id_x` = IF(" + - " LOCATE(';', `plot_id`) > 0," + - " SUBSTRING(`plot_id`, 1, LOCATE(';', `plot_id`) - 1)," + - " `plot_id`" + - " )," + - " `plot_id_z` = IF(" + - " LOCATE(';', `plot_id`) > 0," + - " SUBSTRING(`plot_id`, LOCATE(';', `plot_id`) + 1)," + - " NULL" + - " )" + " `plot_id_x` = IF(" + + " LOCATE(';', `plot_id`) > 0," + + " SUBSTRING(`plot_id`, 1, LOCATE(';', `plot_id`) - 1)," + + " `plot_id`" + + " )," + + " `plot_id_z` = IF(" + + " LOCATE(';', `plot_id`) > 0," + + " SUBSTRING(`plot_id`, LOCATE(';', `plot_id`) + 1)," + + " NULL" + + " )" ); statement.addBatch( "ALTER TABLE `plot` DROP `plot_id`" @@ -298,11 +327,11 @@ public class DBFunc { statement.executeBatch(); statement.close(); } - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } - HashMap> plots = new HashMap>(); - HashMap worldMap = new HashMap(); + HashMap> plots = new HashMap>(); + HashMap worldMap = new HashMap(); Statement stmt = null; try { stmt = connection.createStatement(); @@ -312,30 +341,29 @@ public class DBFunc { Plot p; World w; while (r.next()) { - plot_id = new PlotId(r.getInt("plot_id_x"),r.getInt("plot_id_z")); + plot_id = new PlotId(r.getInt("plot_id_x"), r.getInt("plot_id_z")); id = r.getInt("id"); String worldname = r.getString("world"); // Quicker to get cache the UUID to the World than to convert each time. HashMap settings = getSettings(id); UUID owner = UUID.fromString(r.getString("owner")); Biome plotBiome = Biome.valueOf((String) settings.get("biome")); - if(plotBiome == null) plotBiome = Biome.FOREST; + if (plotBiome == null) plotBiome = Biome.FOREST; String[] flags_string; if (settings.get("flags") == null) - flags_string = new String[] {}; + flags_string = new String[]{}; else flags_string = ((String) settings.get("flags")).split(","); Flag[] flags = new Flag[flags_string.length]; - for (int i = 0; i helpers = plotHelpers(id); ArrayList denied = plotDenied(id); //boolean changeTime = ((Short) settings.get("custom_time") == 0) ? false : true; @@ -346,17 +374,16 @@ public class DBFunc { //boolean rain = Integer.parseInt(settings.get("rain").toString()) == 1 ? true : false; boolean rain = false; String alias = (String) settings.get("alias"); - if(alias == null || alias.equalsIgnoreCase("NEW")) alias = ""; + if (alias == null || alias.equalsIgnoreCase("NEW")) alias = ""; PlotHomePosition position = null; - for(PlotHomePosition plotHomePosition : PlotHomePosition.values()) - if(plotHomePosition.isMatching((String)settings.get("position"))) position = plotHomePosition; - if(position == null) position = PlotHomePosition.DEFAULT; - + for (PlotHomePosition plotHomePosition : PlotHomePosition.values()) + if (plotHomePosition.isMatching((String) settings.get("position"))) position = plotHomePosition; + if (position == null) position = PlotHomePosition.DEFAULT; + p = new Plot(plot_id, owner, plotBiome, helpers, denied, /*changeTime*/ false, time, rain, alias, position, flags, worldname); if (plots.containsKey(worldname)) { plots.get(worldname).put((plot_id), p); - } - else { + } else { HashMap map = new HashMap(); map.put((plot_id), p); plots.put(worldname, map); @@ -371,11 +398,10 @@ public class DBFunc { } /** - * * @param plot * @param rain */ - public static void setWeather(final String world, final Plot plot, final boolean rain) { + public static void setWeather(final String world, final Plot plot, final boolean rain) { plot.settings.setRain(rain); runTask(new Runnable() { @Override @@ -387,21 +413,22 @@ public class DBFunc { stmt.setInt(2, getId(world, plot.id)); stmt.execute(); stmt.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); Logger.add(LogLevel.WARNING, "Could not set weather for plot " + plot.id); } } }); } - public static void setFlags(final String world, final Plot plot, final Flag[] flags) { + + public static void setFlags(final String world, final Plot plot, final Flag[] flags) { plot.settings.setFlags(flags); final StringBuilder flag_string = new StringBuilder(); int i = 0; - for (Flag flag:flags) { - if (i!=0) + for (Flag flag : flags) { + if (i != 0) flag_string.append(","); - flag_string.append(flag.getKey()+":"+flag.getValue()); + flag_string.append(flag.getKey() + ":" + flag.getValue()); i++; } runTask(new Runnable() { @@ -413,7 +440,7 @@ public class DBFunc { stmt.setInt(2, getId(world, plot.id)); stmt.execute(); stmt.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); Logger.add(LogLevel.WARNING, "Could not set flag for plot " + plot.id); } @@ -422,7 +449,6 @@ public class DBFunc { } /** - * * @param plot * @param alias */ @@ -438,7 +464,7 @@ public class DBFunc { stmt.setInt(2, getId(world, plot.id)); stmt.executeUpdate(); stmt.close(); - } catch(SQLException e) { + } catch (SQLException e) { Logger.add(LogLevel.WARNING, "Failed to set alias for plot " + plot.id); e.printStackTrace(); } @@ -448,7 +474,6 @@ public class DBFunc { } /** - * * @param r */ private static void runTask(Runnable r) { @@ -456,11 +481,10 @@ public class DBFunc { } /** - * * @param plot * @param position */ - public static void setPosition(final String world,final Plot plot, final String position) { + public static void setPosition(final String world, final Plot plot, final String position) { plot.settings.setPosition(PlotHomePosition.valueOf(position)); runTask(new Runnable() { @Override @@ -472,7 +496,7 @@ public class DBFunc { stmt.setInt(2, getId(world, plot.id)); stmt.executeUpdate(); stmt.close(); - } catch(SQLException e) { + } catch (SQLException e) { Logger.add(LogLevel.WARNING, "Failed to set position for plot " + plot.id); e.printStackTrace(); } @@ -481,7 +505,6 @@ public class DBFunc { } /** - * * @param id * @return */ @@ -494,19 +517,19 @@ public class DBFunc { ResultSet r = stmt.executeQuery(); String var; Object val; - while(r.next()) { + while (r.next()) { var = "biome"; val = r.getObject(var); - h.put(var,val); + h.put(var, val); var = "rain"; val = r.getObject(var); - h.put(var,val); + h.put(var, val); var = "custom_time"; val = r.getObject(var); h.put(var, val); var = "time"; val = r.getObject(var); - h.put(var,val); + h.put(var, val); var = "deny_entry"; val = r.getObject(var); h.put(var, (short) 0); @@ -520,9 +543,10 @@ public class DBFunc { val = r.getObject(var); h.put(var, val); } - stmt.close();; - } catch(SQLException e) { - Logger.add(LogLevel.WARNING, "Failed to load settings for plot: " + id); + stmt.close(); + ; + } catch (SQLException e) { + Logger.add(LogLevel.WARNING, "Failed to load settings for plot: " + id); e.printStackTrace(); } return h; @@ -534,7 +558,6 @@ public class DBFunc { public static UUID everyone = UUID.fromString("1-1-3-3-7"); /** - * * @param id * @return */ @@ -546,12 +569,12 @@ public class DBFunc { stmt.setInt(1, id); ResultSet r = stmt.executeQuery(); UUID u; - while(r.next()) { + while (r.next()) { u = UUID.fromString(r.getString("user_uuid")); l.add(u); } stmt.close(); - } catch(Exception e) { + } catch (Exception e) { Logger.add(LogLevel.DANGER, "Failed to load denied for plot: " + id); e.printStackTrace(); } @@ -559,35 +582,33 @@ public class DBFunc { } /** - * - * @param id + * @param id * @return */ - private static ArrayList plotHelpers(int id) { - ArrayList l = new ArrayList(); - Statement stmt = null; - try { - stmt = connection.createStatement(); - ResultSet r = stmt.executeQuery("SELECT `user_uuid` FROM `plot_helpers` WHERE `plot_plot_id` = " + id); - UUID u; - while(r.next()) { - u = UUID.fromString(r.getString("user_uuid")); - l.add(u); - } - stmt.close(); - } catch (SQLException e) { - Logger.add(LogLevel.WARNING, "Failed to load helpers for plot: " + id); - e.printStackTrace(); - } - return l; - } + private static ArrayList plotHelpers(int id) { + ArrayList l = new ArrayList(); + Statement stmt = null; + try { + stmt = connection.createStatement(); + ResultSet r = stmt.executeQuery("SELECT `user_uuid` FROM `plot_helpers` WHERE `plot_plot_id` = " + id); + UUID u; + while (r.next()) { + u = UUID.fromString(r.getString("user_uuid")); + l.add(u); + } + stmt.close(); + } catch (SQLException e) { + Logger.add(LogLevel.WARNING, "Failed to load helpers for plot: " + id); + e.printStackTrace(); + } + return l; + } /** - * * @param plot * @param player */ - public static void removeHelper(final String world,final Plot plot, final OfflinePlayer player) { + public static void removeHelper(final String world, final Plot plot, final OfflinePlayer player) { runTask(new Runnable() { @Override public void run() { @@ -597,7 +618,7 @@ public class DBFunc { statement.setString(2, player.getUniqueId().toString()); statement.executeUpdate(); statement.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); Logger.add(LogLevel.WARNING, "Failed to remove helper for plot " + plot.id); } @@ -606,11 +627,10 @@ public class DBFunc { } /** - * * @param plot * @param player */ - public static void setHelper(final String world,final Plot plot, final OfflinePlayer player) { + public static void setHelper(final String world, final Plot plot, final OfflinePlayer player) { runTask(new Runnable() { @Override public void run() { @@ -620,7 +640,7 @@ public class DBFunc { statement.setString(2, player.getUniqueId().toString()); statement.executeUpdate(); statement.close(); - } catch(SQLException e) { + } catch (SQLException e) { Logger.add(LogLevel.WARNING, "Failed to set helper for plot " + plot.id); e.printStackTrace(); } @@ -629,7 +649,6 @@ public class DBFunc { } /** - * * @param plot * @param player */ @@ -643,7 +662,7 @@ public class DBFunc { statement.setString(2, player.getUniqueId().toString()); statement.executeUpdate(); statement.close(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); Logger.add(LogLevel.WARNING, "Failed to remove denied for plot " + plot.id); } @@ -652,7 +671,6 @@ public class DBFunc { } /** - * * @param plot * @param player */ @@ -666,7 +684,7 @@ public class DBFunc { statement.setString(2, player.getUniqueId().toString()); statement.executeUpdate(); statement.close(); - } catch(SQLException e) { + } catch (SQLException e) { Logger.add(LogLevel.WARNING, "Failed to set denied for plot " + plot.id); e.printStackTrace(); } diff --git a/PlotSquared/src/com/intellectualcrafters/plot/database/FlatFileManager.java b/PlotSquared/src/com/intellectualcrafters/plot/database/FlatFileManager.java new file mode 100644 index 000000000..916f9b9dd --- /dev/null +++ b/PlotSquared/src/com/intellectualcrafters/plot/database/FlatFileManager.java @@ -0,0 +1,7 @@ +package com.intellectualcrafters.plot.database; + +/** + * Created by Citymonstret on 2014-09-23. + */ +public class FlatFileManager { +} diff --git a/PlotSquared/src/com/intellectualcrafters/plot/database/SQLite.java b/PlotSquared/src/com/intellectualcrafters/plot/database/SQLite.java new file mode 100644 index 000000000..da20ce8ac --- /dev/null +++ b/PlotSquared/src/com/intellectualcrafters/plot/database/SQLite.java @@ -0,0 +1,103 @@ +package com.intellectualcrafters.plot.database; + +import org.bukkit.plugin.Plugin; + +import java.io.File; +import java.io.IOException; +import java.sql.*; +import java.util.logging.Level; + +/** + * Connects to and uses a SQLite database + * @author Citymonstret + * @author tips48 + */ +public class SQLite extends Database { + + private Connection connection; + private final String dbLocation; + /** + * Creates a new SQLite instance + * + * @param plugin + * Plugin instance + * @param dbLocation + * Location of the Database (Must end in .db) + */ + public SQLite(Plugin plugin, String dbLocation) { + super(plugin); + this.dbLocation = dbLocation; + } + @Override + public Connection openConnection() throws SQLException, + ClassNotFoundException { + if (checkConnection()) { + return connection; + } + if (!plugin.getDataFolder().exists()) { + plugin.getDataFolder().mkdirs(); + } + File file = new File(plugin.getDataFolder(), dbLocation); + if (!(file.exists())) { + try { + file.createNewFile(); + } catch (IOException e) { + plugin.getLogger().log(Level.SEVERE, + "Unable to create database!"); + } + } + Class.forName("org.sqlite.JDBC"); + connection = DriverManager + .getConnection("jdbc:sqlite:" + + plugin.getDataFolder().toPath().toString() + "/" + + dbLocation); + return connection; + } + + @Override + public boolean checkConnection() throws SQLException { + return connection != null && !connection.isClosed(); + } + + @Override + public Connection getConnection() { + return connection; + } + + @Override + public boolean closeConnection() throws SQLException { + if (connection == null) { + return false; + } + connection.close(); + return true; + } + + @Override + public ResultSet querySQL(String query) throws SQLException, + ClassNotFoundException { + if (checkConnection()) { + openConnection(); + } + + Statement statement = connection.createStatement(); + + ResultSet result = statement.executeQuery(query); + + return result; + } + + @Override + public int updateSQL(String query) throws SQLException, + ClassNotFoundException { + if (checkConnection()) { + openConnection(); + } + + Statement statement = connection.createStatement(); + + int result = statement.executeUpdate(query); + + return result; + } +} \ No newline at end of file