Browse Source

0.9.22b: Добавлена функция автоматического обновления.

master
Stanislav Usenkov 9 years ago
parent
commit
2ee703c8f9
  1. 2
      pom.xml
  2. 1
      src/main/java/ru/simsonic/rscPermissions/API/Settings.java
  3. 9
      src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitEventListener.java
  4. 5
      src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java
  5. 27
      src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/CommandUpdate.java
  6. 28
      src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java
  7. 247
      src/main/java/ru/simsonic/rscPermissions/Updater/BukkitUpdater.java
  8. 10
      src/main/java/ru/simsonic/rscPermissions/Updater/Latest.java

2
pom.xml

@ -4,7 +4,7 @@
<groupId>ru.simsonic</groupId> <groupId>ru.simsonic</groupId>
<artifactId>rscPermissions</artifactId> <artifactId>rscPermissions</artifactId>
<version>0.9.20b</version> <version>0.9.22b</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>rscPermissions</name> <name>rscPermissions</name>

1
src/main/java/ru/simsonic/rscPermissions/API/Settings.java

@ -5,6 +5,7 @@ import ru.simsonic.rscCommonsLibrary.ConnectionMySQL.ConnectionParams;
public interface Settings public interface Settings
{ {
public static final String updaterURL = "http://simsonic.github.io/rscPermissions/latest.json";
public static final String chatPrefix = "{GOLD}[rscp] {_LS}"; public static final String chatPrefix = "{GOLD}[rscp] {_LS}";
public static final String separator = "."; public static final String separator = ".";
public static final String separatorRegExp = "\\."; public static final String separatorRegExp = "\\.";

9
src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitEventListener.java

@ -9,6 +9,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerExpChangeEvent; import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerLevelChangeEvent; import org.bukkit.event.player.PlayerLevelChangeEvent;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
@ -60,6 +61,14 @@ public class BukkitEventListener implements Listener
{ {
rscp.permissionManager.recalculatePlayer(event.getPlayer()); rscp.permissionManager.recalculatePlayer(event.getPlayer());
} }
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent event)
{
final Player player = event.getPlayer();
// Inform admins about updates
if(player.hasPermission("rscp.admin"))
rscp.updating.onAdminJoin(player, true);
}
@EventHandler @EventHandler
public void onPlayerExp(PlayerLevelChangeEvent event) public void onPlayerExp(PlayerLevelChangeEvent event)
{ {

5
src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/BukkitCommands.java

@ -23,6 +23,7 @@ public class BukkitCommands
private final CommandFetch cmdFetch; private final CommandFetch cmdFetch;
private final CommandDebug cmdDebug; private final CommandDebug cmdDebug;
private final CommandReload cmdReload; private final CommandReload cmdReload;
private final CommandUpdate cmdUpdate;
public final BukkitDatabaseFetcher threadFetchDatabaseContents; public final BukkitDatabaseFetcher threadFetchDatabaseContents;
public BukkitCommands(final BukkitPluginMain plugin) public BukkitCommands(final BukkitPluginMain plugin)
{ {
@ -31,6 +32,7 @@ public class BukkitCommands
cmdFetch = new CommandFetch(rscp); cmdFetch = new CommandFetch(rscp);
cmdDebug = new CommandDebug(rscp); cmdDebug = new CommandDebug(rscp);
cmdReload = new CommandReload(rscp); cmdReload = new CommandReload(rscp);
cmdUpdate = new CommandUpdate(rscp);
threadFetchDatabaseContents = new BukkitDatabaseFetcher(rscp); threadFetchDatabaseContents = new BukkitDatabaseFetcher(rscp);
} }
public Thread threadMigrateFromPExSQL(final CommandSender sender) public Thread threadMigrateFromPExSQL(final CommandSender sender)
@ -167,6 +169,9 @@ public class BukkitCommands
/* rscp reload */ /* rscp reload */
cmdReload.execute(sender); cmdReload.execute(sender);
return; return;
case "update":
cmdUpdate.execute(sender, args);
return;
case "help": case "help":
default: default:
break; break;

27
src/main/java/ru/simsonic/rscPermissions/Bukkit/Commands/CommandUpdate.java

@ -0,0 +1,27 @@
package ru.simsonic.rscPermissions.Bukkit.Commands;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import ru.simsonic.rscMinecraftLibrary.Bukkit.CommandAnswerException;
import ru.simsonic.rscPermissions.BukkitPluginMain;
public class CommandUpdate
{
private final BukkitPluginMain rscp;
CommandUpdate(BukkitPluginMain plugin)
{
this.rscp = plugin;
}
public void execute(CommandSender sender, String args[]) throws CommandAnswerException
{
if(sender.hasPermission("rscp.admin"))
{
if(args.length > 0 && "do".equals(args[0]))
{
rscp.updating.doUpdate(sender instanceof Player ? (Player)sender : null);
} else {
rscp.updating.checkUpdate(sender instanceof Player ? (Player)sender : null);
}
}
}
}

28
src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java

@ -6,11 +6,13 @@ import java.util.logging.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.mcstats.MetricsLite; import org.mcstats.MetricsLite;
import ru.simsonic.rscMinecraftLibrary.Bukkit.CommandAnswerException; import ru.simsonic.rscMinecraftLibrary.Bukkit.CommandAnswerException;
import ru.simsonic.rscMinecraftLibrary.Bukkit.GenericChatCodes; import ru.simsonic.rscMinecraftLibrary.Bukkit.GenericChatCodes;
import ru.simsonic.rscMinecraftLibrary.Bukkit.Tools;
import ru.simsonic.rscPermissions.API.Settings; import ru.simsonic.rscPermissions.API.Settings;
import ru.simsonic.rscPermissions.Bukkit.BukkitEventListener; import ru.simsonic.rscPermissions.Bukkit.BukkitEventListener;
import ru.simsonic.rscPermissions.Bukkit.BukkitPermissionManager; import ru.simsonic.rscPermissions.Bukkit.BukkitPermissionManager;
@ -23,20 +25,22 @@ import ru.simsonic.rscPermissions.Engine.Backends.BackendJson;
import ru.simsonic.rscPermissions.Engine.Backends.DatabaseContents; import ru.simsonic.rscPermissions.Engine.Backends.DatabaseContents;
import ru.simsonic.rscPermissions.Engine.InternalCache; import ru.simsonic.rscPermissions.Engine.InternalCache;
import ru.simsonic.rscPermissions.Engine.Phrases; import ru.simsonic.rscPermissions.Engine.Phrases;
import ru.simsonic.rscPermissions.Updater.BukkitUpdater;
public final class BukkitPluginMain extends JavaPlugin public final class BukkitPluginMain extends JavaPlugin
{ {
public static final Logger consoleLog = Bukkit.getLogger(); public static final Logger consoleLog = Bukkit.getLogger();
public final Settings settings = new BukkitPluginConfiguration(this); public final Settings settings = new BukkitPluginConfiguration(this);
public final BridgeForBukkitAPI bridgeForBukkit = new BridgeForBukkitAPI(this); public final BukkitUpdater updating = new BukkitUpdater(this, Settings.updaterURL, Settings.chatPrefix);
public final BukkitEventListener bukkitListener = new BukkitEventListener(this); public final BackendJson localStorage = new BackendJson(getDataFolder());
public final BackendJson localStorage = new BackendJson(getDataFolder()); public final BackendDatabase connection = new BackendDatabase(consoleLog);
public final BackendDatabase connection = new BackendDatabase(consoleLog); public final InternalCache internalCache = new InternalCache();
public final InternalCache internalCache = new InternalCache(); public final BukkitCommands commandHelper = new BukkitCommands(this);
public final BukkitPermissionManager permissionManager = new BukkitPermissionManager(this); public final BridgeForBukkitAPI bridgeForBukkit = new BridgeForBukkitAPI(this);
public final BukkitRegionProviders regionListProvider = new BukkitRegionProviders(this); public final BukkitEventListener bukkitListener = new BukkitEventListener(this);
private final RegionUpdateObserver regionUpdateObserver = new RegionUpdateObserver(this); public final BukkitPermissionManager permissionManager = new BukkitPermissionManager(this);
public final BukkitCommands commandHelper = new BukkitCommands(this); public final BukkitRegionProviders regionListProvider = new BukkitRegionProviders(this);
private final RegionUpdateObserver regionUpdateObserver = new RegionUpdateObserver(this);
private MetricsLite metrics; private MetricsLite metrics;
@Override @Override
public void onLoad() public void onLoad()
@ -51,6 +55,7 @@ public final class BukkitPluginMain extends JavaPlugin
{ {
// Read settings and setup components // Read settings and setup components
settings.readSettings(); settings.readSettings();
updating.onEnable();
bukkitListener.onEnable(); bukkitListener.onEnable();
internalCache.setDefaultGroup( internalCache.setDefaultGroup(
settings.getDefaultGroup(), settings.getDefaultGroup(),
@ -99,6 +104,9 @@ public final class BukkitPluginMain extends JavaPlugin
if(settings.getAutoReloadDelayTicks() > 0) if(settings.getAutoReloadDelayTicks() > 0)
commandHelper.threadFetchDatabaseContents.startDeamon(); commandHelper.threadFetchDatabaseContents.startDeamon();
// Done // Done
for(Player online : Tools.getOnlinePlayers())
if(online.hasPermission("rscm.admin"))
updating.onAdminJoin(online, false);
consoleLog.info(Phrases.PLUGIN_ENABLED.toString()); consoleLog.info(Phrases.PLUGIN_ENABLED.toString());
} }
@Override @Override

247
src/main/java/ru/simsonic/rscPermissions/Updater/BukkitUpdater.java

@ -0,0 +1,247 @@
package ru.simsonic.rscPermissions.Updater;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import ru.simsonic.rscCommonsLibrary.RestartableThread;
import ru.simsonic.rscMinecraftLibrary.Bukkit.GenericChatCodes;
public final class BukkitUpdater implements Listener
{
private final JavaPlugin plugin;
private final String latestURL;
private final HashSet<Player> staff = new HashSet<>();
private final String chatPrefix;
public BukkitUpdater(JavaPlugin plugin, String latestURL, String chatPrefix)
{
this.plugin = plugin;
this.latestURL = latestURL;
this.chatPrefix = chatPrefix;
}
public void onEnable()
{
plugin.getServer().getPluginManager().registerEvents(BukkitUpdater.this, plugin);
checkUpdate(null);
}
public void checkUpdate(Player sender)
{
if(sender != null)
staff.add(sender);
threadCheck.start();
}
public void doUpdate(Player sender)
{
if(sender != null)
staff.add(sender);
threadUpdate.start();
}
private final RestartableThread threadCheck = new RestartableThread()
{
@Override
public void run()
{
checkForUpdate();
final ArrayList<String> lines = latestToLines();
if(lines != null)
runLines(lines.toArray(new String[lines.size()]));
else
runLine("You are using the latest version.");
}
};
private final RestartableThread threadUpdate = new RestartableThread()
{
@Override
public void run()
{
runLine("Downloading update...");
if(downloadUpdate())
{
// SUCCESS
runLine("Installing update...");
installUpdate();
runLines(new String[]
{
"{_LG}Installation complete!",
"Please restart your server to avoid errors.",
});
} else {
// FAILED
runLines(new String[] {
"{_LR}Downloading error!",
"Cannot download update file. Please try later.",
});
}
}
};
private Latest latest = new Latest();
private void checkForUpdate()
{
try
{
this.latest = new Gson().fromJson(downloadJson(latestURL), Latest.class);
} catch(IOException ex) {
this.latest = new Latest();
}
if(latest.note == null)
latest.note = "New version: " + latest.version;
if(latest.notes == null)
latest.notes = new String[] { latest.note };
if(latest.version == null)
latest.version = plugin.getDescription().getVersion();
}
private void runLine(final String line)
{
runLines(new String[] { line });
}
private void runLines(final String[] lines)
{
final Runnable syncTask = new Runnable()
{
@Override
public synchronized void run()
{
// CONSOLE
final ConsoleCommandSender console = plugin.getServer().getConsoleSender();
for(String line : lines)
if(line != null)
console.sendMessage(GenericChatCodes.processStringStatic(chatPrefix + line));
// PLAYERS
for(Player online : staff)
for(String line : lines)
if(line != null)
online.sendMessage(GenericChatCodes.processStringStatic(chatPrefix + line));
notify();
}
};
try
{
synchronized(syncTask)
{
plugin.getServer().getScheduler().runTask(plugin, syncTask);
syncTask.wait();
}
} catch(InterruptedException ex) {
}
}
private ArrayList<String> latestToLines()
{
// THERE IS NO UPDATE
if(plugin.getDescription().getVersion().equals(latest.version))
return null;
// THERE IS AN UPDATE
final ArrayList<String> result = new ArrayList<>();
result.add("New "
+ (latest.snapshot ? "{_DS}snapshot {_LS}" : "{_WH}release {_LS}")
+ "version {_LG}" + latest.version + "{_LS} is available!");
result.addAll(Arrays.asList(latest.notes));
result.add("Apply this update with command {GOLD}/rscfjd update do");
return result;
}
public void onAdminJoin(Player player, boolean fromEvent)
{
staff.add(player);
if(fromEvent)
{
final ArrayList<String> lines = latestToLines();
if(lines != null)
for(String line : lines)
if(line != null)
player.sendMessage(GenericChatCodes.processStringStatic(chatPrefix + line));
}
}
@EventHandler
protected void onPlayerQuit(PlayerQuitEvent event)
{
staff.add(event.getPlayer());
}
@EventHandler
protected void onPlayerKick(PlayerKickEvent event)
{
staff.add(event.getPlayer());
}
private static String downloadJson(String url) throws IOException
{
try
{
final HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setUseCaches(false);
final int responseCode = connection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK)
return readUnicodeStream(connection.getInputStream());
throw new IOException(new StringBuilder()
.append(Integer.toString(responseCode))
.append("Erroneous result of executing web-method: ")
.append(connection.getResponseMessage())
.append("\r\n")
.append(readUnicodeStream(connection.getErrorStream()))
.toString());
} catch(JsonParseException | MalformedURLException ex) {
throw new IOException(ex);
} catch(IOException ex) {
throw ex;
}
}
private static String readUnicodeStream(InputStream is) throws IOException
{
try(ByteArrayOutputStream baos = new ByteArrayOutputStream())
{
final byte[] buffer = new byte[1024];
for(int length = 0; length != -1; length = is.read(buffer))
baos.write(buffer, 0, length);
return new String(baos.toByteArray(), "UTF-8");
}
}
private boolean downloadUpdate()
{
final File folder = plugin.getDataFolder().getParentFile();
final File target = new File(folder, plugin.getName() + "_v" + latest.version + ".jar");
try(FileOutputStream fos = new FileOutputStream(target))
{
final ReadableByteChannel rbc = Channels.newChannel(new URL(latest.url).openStream());
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.flush();
return true;
} catch(MalformedURLException ex) {
System.err.println(ex);
} catch(IOException ex) {
System.err.println(ex);
}
return false;
}
private void installUpdate()
{
// RENAME OLD VERSION
try
{
final String outdatedJarPath = plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
final File outdatedJarSrc = new File(outdatedJarPath);
final File outdatedJarDst = new File(outdatedJarPath + "-outdated");
outdatedJarSrc.renameTo(outdatedJarDst);
} catch(URISyntaxException ex) {
}
}
}

10
src/main/java/ru/simsonic/rscPermissions/Updater/Latest.java

@ -0,0 +1,10 @@
package ru.simsonic.rscPermissions.Updater;
public class Latest
{
public String version;
public String note;
public String[] notes;
public String url;
public boolean snapshot;
}
Loading…
Cancel
Save