diff --git a/Core/build.gradle b/Core/build.gradle index ae9dc17d4..fbd344d1b 100644 --- a/Core/build.gradle +++ b/Core/build.gradle @@ -1,5 +1,7 @@ dependencies { + testCompile 'junit:junit:4.12' compile 'org.yaml:snakeyaml:1.16' + compile 'com.google.code.gson:gson:2.2.4' } sourceCompatibility = 1.7 diff --git a/Core/src/main/java/com/intellectualcrafters/plot/PS.java b/Core/src/main/java/com/intellectualcrafters/plot/PS.java index ecd84d490..6e2c33621 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/PS.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/PS.java @@ -8,7 +8,11 @@ import com.intellectualcrafters.plot.commands.WE_Anywhere; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.Configuration; import com.intellectualcrafters.plot.config.Settings; -import com.intellectualcrafters.plot.database.*; +import com.intellectualcrafters.plot.database.DBFunc; +import com.intellectualcrafters.plot.database.Database; +import com.intellectualcrafters.plot.database.MySQL; +import com.intellectualcrafters.plot.database.SQLManager; +import com.intellectualcrafters.plot.database.SQLite; import com.intellectualcrafters.plot.flag.AbstractFlag; import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.flag.FlagValue; @@ -16,22 +20,67 @@ import com.intellectualcrafters.plot.generator.GeneratorWrapper; import com.intellectualcrafters.plot.generator.HybridPlotWorld; import com.intellectualcrafters.plot.generator.HybridUtils; import com.intellectualcrafters.plot.generator.IndependentPlotGenerator; -import com.intellectualcrafters.plot.object.*; -import com.intellectualcrafters.plot.util.*; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotAnalysis; +import com.intellectualcrafters.plot.object.PlotArea; +import com.intellectualcrafters.plot.object.PlotCluster; +import com.intellectualcrafters.plot.object.PlotFilter; +import com.intellectualcrafters.plot.object.PlotId; +import com.intellectualcrafters.plot.object.PlotManager; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.RegionWrapper; +import com.intellectualcrafters.plot.object.RunnableVal; +import com.intellectualcrafters.plot.util.AbstractTitle; +import com.intellectualcrafters.plot.util.ChatManager; +import com.intellectualcrafters.plot.util.ChunkManager; +import com.intellectualcrafters.plot.util.CommentManager; +import com.intellectualcrafters.plot.util.EconHandler; +import com.intellectualcrafters.plot.util.EventUtil; +import com.intellectualcrafters.plot.util.ExpireManager; +import com.intellectualcrafters.plot.util.InventoryUtil; +import com.intellectualcrafters.plot.util.MainUtil; +import com.intellectualcrafters.plot.util.MathMan; +import com.intellectualcrafters.plot.util.PlotGamemode; +import com.intellectualcrafters.plot.util.PlotWeather; +import com.intellectualcrafters.plot.util.ReflectionUtils; +import com.intellectualcrafters.plot.util.SchematicHandler; +import com.intellectualcrafters.plot.util.SetQueue; +import com.intellectualcrafters.plot.util.SetupUtils; +import com.intellectualcrafters.plot.util.StringMan; +import com.intellectualcrafters.plot.util.TaskManager; +import com.intellectualcrafters.plot.util.UUIDHandler; +import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.area.QuadMap; import com.plotsquared.listener.WESubscriber; import com.sk89q.worldedit.WorldEdit; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; -import java.sql.Connection; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -44,10 +93,10 @@ import java.util.zip.ZipInputStream; * @author boy0001 | Empire92 */ public class PS { - + // protected static: private static PS instance; - private HashSet plotareaHashCheck = new HashSet(); + private HashSet plotareaHashCheck = new HashSet<>(); private boolean plotareaHasCollision = false; /** * All plot areas (quick global access) @@ -81,9 +130,8 @@ public class PS { private String PLATFORM = null; private String LAST_VERSION; private Database database; - private Connection connection; private Thread thread; - + /** * Initialize PlotSquared with the desired Implementation class * @param imp_class @@ -135,7 +183,7 @@ public class PS { WorldEdit.getInstance().getEventBus().register(new WESubscriber()); MainCommand.getInstance().createCommand(new WE_Anywhere()); } - + // Events IMP.registerCommands(); IMP.registerPlayerEvents(); @@ -162,22 +210,22 @@ public class PS { @Override public void run() { for (final Plot plot : getPlots()) { - if ((plot.hasOwner()) && (plot.temp != -1)) { + if (plot.hasOwner() && (plot.temp != -1)) { if (UUIDHandler.getName(plot.owner) == null) { UUIDHandler.implementation.unknown.add(plot.owner); } } } - + // Auto clearing if (Settings.AUTO_CLEAR) { ExpireManager.runTask(); } - + // PlotMe if (Settings.CONVERT_PLOTME || Settings.CACHE_PLOTME) { TaskManager.runTaskLater(new Runnable() { - + @Override public void run() { if (IMP.initPlotMeConverter()) { @@ -214,12 +262,12 @@ public class PS { AbstractTitle.TITLE_CLASS = IMP.initTitleManager(); // Chat ChatManager.manager = IMP.initChatManager(); - + // Check for updates TaskManager.runTaskAsync(new Runnable() { @Override public void run() { - final URL url = getUpdate(); + final URL url = Updater.getUpdate(); if (url != null) { update = url; } else if ((LAST_VERSION != null) && !StringMan.join(VERSION, ".").equals(LAST_VERSION)) { @@ -227,7 +275,7 @@ public class PS { } } }); - + // World generators: final ConfigurationSection section = config.getConfigurationSection("worlds"); if (section != null) { @@ -256,7 +304,7 @@ public class PS { } }, 1); } - + // Copy files copyFile("automerge.js", "scripts"); copyFile("town.template", "templates"); @@ -270,7 +318,7 @@ public class PS { e.printStackTrace(); } } - + /** * Get the instance of PlotSquared * @@ -279,7 +327,7 @@ public class PS { public static PS get() { return instance; } - + /** * Log a message to the IPlotMain logger * @@ -289,7 +337,7 @@ public class PS { public static void log(final Object message) { get().IMP.log(StringMan.getString(message)); } - + public static void stacktrace() { System.err.println(StringMan.join(new Exception().getStackTrace(), "\n\tat ")); } @@ -332,8 +380,9 @@ public class PS { } /** - * Get the platform this is running on (Bukkit, Sponge) - * @return + *

Get the server platform this plugin is running on this is running on. + * This will be either Bukkit or Sponge

+ * @return The server platform */ public String getPlatform() { return PLATFORM; @@ -343,12 +392,12 @@ public class PS { * Get the database object * * @return Database object - * @see #getConnection() Get the database connection + * @see Database#getConnection() To get the database connection */ public Database getDatabase() { return database; } - + /** * Update the global reference * to a plot object @@ -358,7 +407,7 @@ public class PS { public boolean updatePlot(final Plot plot) { return plot.getArea().addPlot(plot); } - + /** * Get the relevant plot area for a location.
* - If there is only one plot area globally that will be returned
@@ -423,7 +472,7 @@ public class PS { } } } - + public PlotArea getPlotArea(String world, String id) { PlotArea[] areas = plotareamap.get(world); if (areas == null) { @@ -442,7 +491,7 @@ public class PS { return null; } } - + public PlotArea getPlotAreaAbs(String world, String id) { PlotArea[] areas = plotareamap.get(world); if (areas == null) { @@ -482,7 +531,7 @@ public class PS { return null; } } - + public Set getPlotAreas(String world, RegionWrapper region) { QuadMap areas = plotareagrid.get(world); return areas != null ? areas.get(region) : new HashSet(); @@ -491,7 +540,7 @@ public class PS { /** * Get the plot area which contains a location.
* - If the plot area does not contain a location, null will be returned - * + * * @param loc * @return */ @@ -555,7 +604,7 @@ public class PS { public PlotManager getPlotManager(Plot plot) { return plot.getArea().manager; } - + public PlotManager getPlotManager(Location loc) { PlotArea pa = getPlotAreaAbs(loc); return pa != null ? pa.manager : null; @@ -630,7 +679,7 @@ public class PS { } map.add(plotarea); } - + /** * Remove a plot world reference * @@ -650,7 +699,7 @@ public class PS { } setPlotsTmp(area); } - + public void removePlotAreas(String world) { for (PlotArea area : getPlotAreas(world)) { removePlotArea(area); @@ -674,7 +723,7 @@ public class PS { } clusters_tmp.put(area.toString(), area.getClusters()); } - + public Set getClusters(String world) { HashSet set = new HashSet<>(); if (Settings.ENABLE_CLUSTERS) { @@ -810,7 +859,7 @@ public class PS { result.addAll(overflow); return result; } - + /** * Sort plots by hashcode * @param plots @@ -864,7 +913,7 @@ public class PS { } return result; } - + /** * Sort plots by creation timestamp * @param input @@ -1034,7 +1083,7 @@ public class PS { return result; } } - + /** * @deprecated Unchecked, use {@link #sortPlots(Collection, SortType, PlotArea)} instead which will in turn call this * @param input @@ -1127,7 +1176,7 @@ public class PS { } return toReturn; } - + /** * Get all the plots owned by a player name * @param world @@ -1149,7 +1198,7 @@ public class PS { final UUID uuid = UUIDHandler.getUUID(player, null); return getPlots(area, uuid); } - + /** * Get all plots by a PlotPlayer * @param world @@ -1160,7 +1209,7 @@ public class PS { final UUID uuid = player.getUUID(); return getPlots(world, uuid); } - + /** * Get all plots by a PlotPlayer * @param area @@ -1171,7 +1220,7 @@ public class PS { final UUID uuid = player.getUUID(); return getPlots(area, uuid); } - + /** * Get all plots by a UUID in a world * @param world @@ -1189,7 +1238,7 @@ public class PS { } return new HashSet<>(myplots); } - + /** * Get all plots by a UUID in an area * @param area @@ -1207,7 +1256,7 @@ public class PS { } return new HashSet<>(myplots); } - + /** * Use {@link #hasPlotArea(String)}
* Note: Worlds may have more than one plot area @@ -1251,7 +1300,7 @@ public class PS { return plotareamap.containsKey(world); } } - + public Collection getPlots(final String world) { final HashSet set = new HashSet<>(); foreachPlotArea(world, new RunnableVal() { @@ -1262,15 +1311,15 @@ public class PS { }); return set; } - + public Collection getPlots(final PlotArea area) { return area == null ? new HashSet() : area.getPlots(); } - + public Plot getPlot(PlotArea area, final PlotId id) { return area == null ? null : (id == null ? null : area.getPlot(id)); } - + /** * Get the plots for a PlotPlayer * @param player @@ -1279,7 +1328,7 @@ public class PS { public Set getPlots(final PlotPlayer player) { return getPlots(player.getUUID()); } - + /** * Get the plots for a UUID * @param uuid @@ -1297,7 +1346,7 @@ public class PS { }); return new HashSet<>(myplots); } - + /** * Get the plots for a UUID * @param uuid @@ -1315,7 +1364,7 @@ public class PS { }); return new HashSet<>(myplots); } - + /** * Unregister a plot from local memory (does not call DB) * @param plot @@ -1340,7 +1389,7 @@ public class PS { } return false; } - + /** * This method is called by the PlotGenerator class normally
* - Initializes the PlotArea and PlotManager classes
@@ -1566,7 +1615,7 @@ public class PS { } } } - + /** * Setup the configuration for a plot world based on world arguments
* e.g. /mv create normal -g PlotSquared: @@ -1651,86 +1700,42 @@ public class PS { } return true; } - + public boolean canUpdate(final String current, final String other) { final String s1 = normalisedVersion(current); final String s2 = normalisedVersion(other); final int cmp = s1.compareTo(s2); return cmp < 0; } - + public String normalisedVersion(final String version) { - return normalisedVersion(version, ".", 4); - } - - public String normalisedVersion(final String version, final String sep, final int maxWidth) { - final String[] split = Pattern.compile(sep, Pattern.LITERAL).split(version); + final String[] split = Pattern.compile(".", Pattern.LITERAL).split(version); final StringBuilder sb = new StringBuilder(); for (final String s : split) { - sb.append(String.format("%" + maxWidth + 's', s)); + sb.append(String.format("%" + 4 + 's', s)); } return sb.toString(); } - - /** - * Gets the default update URL, or null if the plugin is up to date - * @return - */ - public URL getUpdate() { - final String pom = "https://raw.githubusercontent.com/IntellectualSites/PlotSquared/master/pom.xml"; - try { - final URL page = new URL(pom); - final URLConnection con = page.openConnection(); - final String agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1"; - con.addRequestProperty("User-Agent", agent); - String line; - try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { - while ((line = in.readLine()) != null) { - line = line.trim(); - if (line.startsWith("")) { - line = line.replaceAll("[^\\d.]", ""); - break; - } - } - } - if (!canUpdate(config.getString("version"), line)) { - PS.debug("&7PlotSquared is already up to date!"); - return null; - } - String dl = "https://raw.githubusercontent.com/IntellectualSites/PlotSquared/master/target/PlotSquared-${PLATFORM}.jar"; - dl = dl.replaceAll(Pattern.quote("${PLATFORM}"), getPlatform()); - log("&6PlotSquared v" + line + " is available:"); - log("&8 - &3Use: &7/plot update"); - log("&8 - &3Or: &7" + dl); - return new URL(dl); - } catch (IOException e) { - e.printStackTrace(); - log("&dCould not check for updates (0)"); - log("&7 - Manually check for updates: " + pom); - } - return null; - } - + public boolean update(final PlotPlayer sender, final URL url) { - if (url == null) { - return false; - } try { final String name = FILE.getName(); final File newJar = new File("plugins/update/" + name); MainUtil.sendMessage(sender, "$1Downloading from provided URL: &7" + url); - MainUtil.sendMessage(sender, "$2 - User-Agent: " + "Mozilla/4.0"); final URLConnection con = url.openConnection(); - con.addRequestProperty("User-Agent", "Mozilla/4.0"); - final InputStream stream = con.getInputStream(); - final File parent = newJar.getParentFile(); - if (!parent.exists()) { - parent.mkdirs(); + try (InputStream stream = con.getInputStream()) { + final File parent = newJar.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + MainUtil.sendMessage(sender, "$2 - Output: " + newJar); + if (newJar.delete()) { + MainUtil.sendMessage(sender, "Failed to update PlotSquared"); + MainUtil.sendMessage(sender, "Jar file failed to delete."); + MainUtil.sendMessage(sender, " - Please update manually"); + } + Files.copy(stream, newJar.toPath()); } - MainUtil.sendMessage(sender, "$2 - Output: " + newJar); - newJar.delete(); - Files.copy(stream, newJar.toPath()); - stream.close(); MainUtil.sendMessage(sender, "$1The update will take effect when the server is restarted next"); return true; } catch (IOException e) { @@ -1742,15 +1747,7 @@ public class PS { } return false; } - - /** - * Get the database connection - * @return The database connection - */ - public Connection getConnection() { - return connection; - } - + /** * Copy a file from inside the jar to a location * @param file Name of the file inside PlotSquared.jar @@ -1803,7 +1800,7 @@ public class PS { log("&cCould not save " + file); } } - + private Map> getPlotsRaw() { HashMap> map = new HashMap<>(); for (PlotArea area : plotareas) { @@ -1885,7 +1882,7 @@ public class PS { IMP.disable(); } } - + /** * Setup the default flags for PlotSquared
* - Create the flags @@ -1996,7 +1993,7 @@ public class PS { }); FlagManager.addFlag(new AbstractFlag("description", new FlagValue.StringValue()), true); } - + /** * Setup the default configuration (settings.yml) */ @@ -2254,7 +2251,7 @@ public class PS { Settings.MERGE_REMOVES_ROADS = config.getBoolean("merge.remove-terrain"); Settings.AUTO_PURGE = config.getBoolean("auto-purge", false); } - + /** * Setup all configuration files
* - Config: settings.yml
@@ -2315,7 +2312,7 @@ public class PS { e.printStackTrace(); } } - + /** * Setup the storage file (load + save missing nodes) */ @@ -2346,11 +2343,11 @@ public class PS { Settings.DB.SQLITE_DB = storage.getString("sqlite.db"); Settings.DB.PREFIX = storage.getString("prefix"); } - + /** * Show startup debug information */ - public void showDebug() { + private void showDebug() { if (Settings.DEBUG) { final Map settings = new HashMap<>(); settings.put("Kill Road Mobs", "" + Settings.KILL_ROAD_MOBS); @@ -2367,7 +2364,7 @@ public class PS { } } } - + /** * Setup the style.yml file */ @@ -2384,7 +2381,7 @@ public class PS { } } } - + /** * Get the java version * @return Java version as a double @@ -2392,13 +2389,13 @@ public class PS { public double getJavaVersion() { return Double.parseDouble(System.getProperty("java.specification.version")); } - + public void foreachPlotArea(RunnableVal runnable) { for (PlotArea area : plotareas) { runnable.run(area); } } - + public void foreachPlot(final RunnableVal runnable) { for (PlotArea area : plotareas) { for (Plot plot : area.getPlots()) { @@ -2406,7 +2403,7 @@ public class PS { } } } - + public void foreachPlotRaw(final RunnableVal runnable) { for (PlotArea area : plotareas) { for (Plot plot : area.getPlots()) { @@ -2463,7 +2460,7 @@ public class PS { Collections.addAll(set, plotareas); return set; } - + /** * @deprecated Since worlds can have multiple plot areas * @return Set of world names @@ -2476,7 +2473,7 @@ public class PS { } return set; } - + public boolean isAugmented(String world) { PlotArea[] areas = plotareamap.get(world); if (areas == null) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/Updater.java b/Core/src/main/java/com/intellectualcrafters/plot/Updater.java new file mode 100644 index 000000000..dbfe55aaf --- /dev/null +++ b/Core/src/main/java/com/intellectualcrafters/plot/Updater.java @@ -0,0 +1,85 @@ +package com.intellectualcrafters.plot; + +import static com.intellectualcrafters.plot.PS.log; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +public class Updater { + + private static String readUrl(String urlString) { + BufferedReader reader = null; + try { + URL url = new URL(urlString); + reader = new BufferedReader(new InputStreamReader(url.openStream())); + StringBuilder buffer = new StringBuilder(); + int read; + char[] chars = new char[1024]; + while ((read = reader.read(chars)) != -1) { + buffer.append(chars, 0, read); + } + + return buffer.toString(); + } catch (IOException e) { + log("&dCould not check for updates (0)"); + e.printStackTrace(); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } + + public static URL getUpdate() { + String str = readUrl("https://api.github.com/repos/IntellectualSites/PlotSquared/releases/latest"); + Gson gson = new Gson(); + URL url = null; + Release release = gson.fromJson(str, Release.class); + String downloadURL = String.format("PlotSquared-%s%n.jar", PS.get().getPlatform()); + List assets = release.assets; + for (Release.Asset asset : assets) { + if (asset.name.equals(downloadURL)) { + try { + url = new URL(asset.downloadUrl); + break; + } catch (MalformedURLException e) { + e.printStackTrace(); + log("&dCould not check for updates (0)"); + log("&7 - Manually check for updates: https://github.com/IntellectualSites/PlotSquared/releases"); + } + } + } + if (!PS.get().canUpdate(PS.get().config.getString("version"), release.name)) { + PS.debug("&7PlotSquared is already up to date!"); + return null; + } + log("&6PlotSquared " + release.tagName + " is available:"); + log("&8 - &3Use: &7/plot update"); + log("&8 - &3Or: &7" + downloadURL); + return url; + } + + + private static class Release { + public String name; + @SerializedName("tag_name") String tagName; + List assets; + static class Asset { + public String name; + @SerializedName("browser_download_url") String downloadUrl; + } + + } +} diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Update.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Update.java index 899c9ee22..999fa284f 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/commands/Update.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Update.java @@ -20,15 +20,15 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// package com.intellectualcrafters.plot.commands; -import java.net.MalformedURLException; -import java.net.URL; - import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.util.MainUtil; import com.plotsquared.general.commands.CommandDeclaration; +import java.net.MalformedURLException; +import java.net.URL; + @CommandDeclaration( command = "update", permission = "plots.admin.command.update", diff --git a/Core/src/test/java/com/intellectualcrafters/plot/UpdaterTest.java b/Core/src/test/java/com/intellectualcrafters/plot/UpdaterTest.java new file mode 100644 index 000000000..85aa46bd0 --- /dev/null +++ b/Core/src/test/java/com/intellectualcrafters/plot/UpdaterTest.java @@ -0,0 +1,64 @@ +package com.intellectualcrafters.plot; + +import static com.intellectualcrafters.plot.PS.log; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.List; + +public class UpdaterTest { + + @org.junit.Test + public void getUpdate() throws Exception { + String str = null; + BufferedReader reader = null; + try { + URL url = new URL("https://api.github.com/repos/IntellectualSites/PlotSquared/releases/latest"); + reader = new BufferedReader(new InputStreamReader(url.openStream())); + StringBuilder buffer = new StringBuilder(); + int read; + char[] chars = new char[1024]; + while ((read = reader.read(chars)) != -1) { + buffer.append(chars, 0, read); + } + + str = buffer.toString(); + } catch (IOException e) { + log("&dCould not check for updates (0)"); + e.printStackTrace(); + } finally { + try { + if (reader != null) { + reader.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + if (str == null) { + return; + } + Gson gson = new Gson(); + Release release = gson.fromJson(str, Release.class); + System.out.println(release.name); + for (Release.Assets asset : release.assets) { + System.out.println(asset.name); + System.out.println(asset.downloadUrl); + } + } + private static class Release { + String name; + List assets; + private static class Assets { + String name; + @SerializedName("browser_download_url") String downloadUrl; + } + + } + +} \ No newline at end of file