mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-13 07:10:03 +01:00
Fixed Update downloading, old jar deletion still broken
This commit is contained in:
parent
4e0f1b38f1
commit
0ff4e22a02
@ -36,6 +36,7 @@ public class PlanCommand extends TreeCmdNode {
|
||||
new ListCommand(),
|
||||
new AnalyzeCommand(),
|
||||
new NetworkCommand(),
|
||||
new ListServersCommand(plugin)
|
||||
},
|
||||
new CommandNode[]{
|
||||
new WebUserCommand(plugin, registerCommand, this),
|
||||
|
@ -6,17 +6,22 @@ import com.djrapitops.plan.command.commands.manage.ManageConDebugCommand;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.database.databases.operation.FetchOperations;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.request.CheckConnectionRequest;
|
||||
import com.djrapitops.plan.system.info.request.UpdateCancelRequest;
|
||||
import com.djrapitops.plan.system.info.request.UpdateRequest;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plan.system.settings.locale.Locale;
|
||||
import com.djrapitops.plan.system.settings.locale.Msg;
|
||||
import com.djrapitops.plan.system.update.VersionCheckSystem;
|
||||
import com.djrapitops.plan.system.update.VersionInfo;
|
||||
import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandNode;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.CommandUtils;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
import com.djrapitops.plugin.task.RunnableFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -32,13 +37,13 @@ public class UpdateCommand extends CommandNode {
|
||||
|
||||
public UpdateCommand() {
|
||||
super("update", Permissions.MANAGE.getPermission(), CommandType.ALL);
|
||||
setArguments("[-update]/[cancel]");
|
||||
setArguments("[-u]/[cancel]");
|
||||
setShortHelp("Get change log link or update plugin.");
|
||||
setInDepthHelp(
|
||||
"/plan update",
|
||||
" Used to update the plugin on the next shutdown\n",
|
||||
" /plan update - get change log link",
|
||||
" /plan update -update - Schedule update to happen on all network servers that are online next time they reboot.",
|
||||
" /plan update -u - Schedule update to happen on all network servers that are online next time they reboot.",
|
||||
" /plan update cancel - Cancel scheduled update on servers that haven't rebooted yet."
|
||||
);
|
||||
}
|
||||
@ -62,24 +67,40 @@ public class UpdateCommand extends CommandNode {
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendLink("Change Log v" + available.getVersion().toString() + ": ", "Click me", available.getChangeLogUrl());
|
||||
String message = "Change Log v" + available.getVersion().toString() + ": ";
|
||||
String url = available.getChangeLogUrl();
|
||||
if (CommandUtils.isConsole(sender)) {
|
||||
sender.sendMessage(message + url);
|
||||
} else {
|
||||
sender.sendMessage(message);
|
||||
sender.sendLink(" ", Locale.get(Msg.CMD_INFO_CLICK_ME).toString(), url);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
String firstArgument = args[0];
|
||||
if ("-update".equals(firstArgument)) {
|
||||
handleUpdate(sender, args);
|
||||
} else if ("cancel".equals(firstArgument)) {
|
||||
cancel(sender);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown argument, use '-update' or 'cancel'");
|
||||
}
|
||||
RunnableFactory.createNew("Update Command Task", new AbsRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if ("-u".equals(firstArgument)) {
|
||||
handleUpdate(sender, args);
|
||||
} else if ("cancel".equals(firstArgument)) {
|
||||
handleCancel(sender);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown argument, use '-u' or 'cancel'");
|
||||
}
|
||||
} finally {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}).runTaskAsynchronously();
|
||||
}
|
||||
|
||||
private void cancel(ISender sender) {
|
||||
private void handleCancel(ISender sender) {
|
||||
try {
|
||||
cancel(sender, Database.getActive().fetch().getServers());
|
||||
sender.sendMessage("§aUpdate has been cancelled.");
|
||||
sender.sendMessage("§aCancel operation performed.");
|
||||
} catch (DBException e) {
|
||||
sender.sendMessage("§cDatabase error occurred, cancel could not be performed.");
|
||||
Log.toLog(this.getClass().getName(), e);
|
||||
@ -90,24 +111,28 @@ public class UpdateCommand extends CommandNode {
|
||||
sender.sendMessage("§aYou can cancel the update on servers that haven't rebooted yet with /plan update cancel.");
|
||||
sender.sendMessage("Checking that all servers are online..");
|
||||
if (!checkNetworkStatus(sender)) {
|
||||
sender.sendMessage("§cNot all servers were online or accessible, you can still update available servers using -force as a 2nd argument.");
|
||||
if (args.length <= 1 || !"-force".equals(args[1])) {
|
||||
sender.sendMessage("§cNot all servers were online or accessible, you can still update available servers using /plan -update -force");
|
||||
if (args.length > 1 && "-force".equals(args[1])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
List<Server> servers = Database.getActive().fetch().getServers();
|
||||
update(sender, servers);
|
||||
update(sender, servers, args);
|
||||
} catch (DBException e) {
|
||||
Log.toLog(this.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void update(ISender sender, List<Server> servers) {
|
||||
private void update(ISender sender, List<Server> servers, String[] args) {
|
||||
for (Server server : servers) {
|
||||
if (update(sender, server)) {
|
||||
sender.sendMessage("§a" + server.getName() + " scheduled for update.");
|
||||
} else {
|
||||
if (args.length > 1 && "-force".equals(args[1])) {
|
||||
sender.sendMessage("§e" + server.getName() + " failed to update, -force specified, continuing update.");
|
||||
continue;
|
||||
}
|
||||
sender.sendMessage("§cUpdate failed on a server, cancelling update on all servers..");
|
||||
cancel(sender, servers);
|
||||
sender.sendMessage("§cUpdate cancelled.");
|
||||
@ -149,7 +174,7 @@ public class UpdateCommand extends CommandNode {
|
||||
|
||||
private boolean update(ISender sender, Server server) {
|
||||
try {
|
||||
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new CheckConnectionRequest(), server);
|
||||
InfoSystem.getInstance().getConnectionSystem().sendInfoRequest(new UpdateRequest(), server);
|
||||
return true;
|
||||
} catch (BadRequestException e) {
|
||||
sender.sendMessage("§c" + server.getName() + " has Allow-Update set to false, aborting update.");
|
||||
@ -186,6 +211,7 @@ public class UpdateCommand extends CommandNode {
|
||||
FetchOperations fetch = Database.getActive().fetch();
|
||||
Optional<Server> bungeeInformation = fetch.getBungeeInformation();
|
||||
if (!bungeeInformation.isPresent()) {
|
||||
sender.sendMessage("Bungee address not found in the database, assuming this is not a network.");
|
||||
return true;
|
||||
}
|
||||
Map<UUID, Server> bukkitServers = fetch.getBukkitServers();
|
||||
|
@ -81,9 +81,9 @@ public abstract class PlanSystem implements SubSystem {
|
||||
checkSubSystemInitialization();
|
||||
|
||||
SubSystem[] systems = new SubSystem[]{
|
||||
versionCheckSystem,
|
||||
fileSystem,
|
||||
configSystem,
|
||||
versionCheckSystem,
|
||||
databaseSystem,
|
||||
webServerSystem,
|
||||
processing,
|
||||
|
@ -5,12 +5,10 @@ import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.utility.Version;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Shutdown hook that updates the plugin on server shutdown.
|
||||
@ -22,64 +20,59 @@ import java.nio.channels.ReadableByteChannel;
|
||||
public class ShutdownUpdateHook extends Thread {
|
||||
|
||||
private static boolean activated = false;
|
||||
private static File newJar;
|
||||
|
||||
private static Set<File> toDelete = new HashSet<>();
|
||||
|
||||
private static boolean isActivated() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
private static void activate(ShutdownUpdateHook hook) {
|
||||
public static void activate() {
|
||||
activated = true;
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
|
||||
public static void deActivate() {
|
||||
activated = false;
|
||||
Log.infoColor("§aUpdate has been cancelled.");
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (isActivated()) {
|
||||
return;
|
||||
}
|
||||
Log.infoColor("§aUpdate has been scheduled, The new jar will be downloaded on server shutdown.");
|
||||
activate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!activated) {
|
||||
return;
|
||||
}
|
||||
activated = false;
|
||||
VersionInfo available = VersionCheckSystem.getInstance().getNewVersionAvailable();
|
||||
|
||||
if (!Version.isNewVersionAvailable(new Version(VersionCheckSystem.getCurrentVersion()), available.getVersion())) {
|
||||
return;
|
||||
}
|
||||
|
||||
File dataFolder = PlanPlugin.getInstance().getDataFolder();
|
||||
File pluginsFolder = Check.isSpongeAvailable()
|
||||
? dataFolder.getParentFile()
|
||||
: new File(dataFolder.getParentFile().getParentFile(), "mods");
|
||||
if (pluginsFolder == null || !pluginsFolder.isDirectory()) {
|
||||
System.out.println("Could not get plugin folder for Plan.");
|
||||
return;
|
||||
}
|
||||
File newFileLocation = new File(pluginsFolder, "Plan-" + available.getVersion() + ".jar");
|
||||
|
||||
try {
|
||||
downloadNewJar(available, newFileLocation);
|
||||
deleteOldJar(pluginsFolder, newFileLocation);
|
||||
File pluginsFolder = getPluginsFolder();
|
||||
newJar = new File(pluginsFolder, "Plan-" + available.getVersion() + ".jar");
|
||||
|
||||
downloadNewJar(available, newJar);
|
||||
registerOldJarForDeletion(pluginsFolder, newJar);
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass().getName(), e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteOldJar(File pluginsFolder, File newFileLocation) {
|
||||
private static File getPluginsFolder() throws FileNotFoundException {
|
||||
File dataFolder = PlanPlugin.getInstance().getDataFolder();
|
||||
File pluginsFolder = Check.isSpongeAvailable()
|
||||
? new File(dataFolder.getParentFile().getParentFile().getPath(), "mods")
|
||||
: new File(dataFolder.getParentFile().getPath());
|
||||
if (!pluginsFolder.isDirectory()) {
|
||||
throw new FileNotFoundException("Could not get plugin folder for Plan.");
|
||||
}
|
||||
return pluginsFolder;
|
||||
}
|
||||
|
||||
public static void deActivate() {
|
||||
activated = false;
|
||||
Log.infoColor("§aUpdate has been cancelled.");
|
||||
|
||||
if (newJar != null && newJar.exists()) {
|
||||
if (!newJar.delete()) {
|
||||
newJar.deleteOnExit();
|
||||
}
|
||||
}
|
||||
toDelete.clear();
|
||||
}
|
||||
|
||||
public static void registerOldJarForDeletion(File pluginsFolder, File newFileLocation) throws FileNotFoundException {
|
||||
File[] files = pluginsFolder.listFiles();
|
||||
if (files == null) {
|
||||
System.out.println("Could not delete old jar.");
|
||||
return;
|
||||
throw new FileNotFoundException("Could not delete old jar.");
|
||||
}
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
@ -88,17 +81,51 @@ public class ShutdownUpdateHook extends Thread {
|
||||
|| fileName.equals("Plan.jar");
|
||||
boolean isNewJar = fileName.equals(newFileLocation.getName());
|
||||
if (isPlanJar && !isNewJar) {
|
||||
file.deleteOnExit();
|
||||
toDelete.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadNewJar(VersionInfo available, File newFileLocation) throws IOException {
|
||||
public static void downloadNewJar(VersionInfo available, File newFileLocation) throws IOException {
|
||||
URL downloadFrom = new URL(available.getDownloadUrl());
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
in = new BufferedInputStream(downloadFrom.openStream());
|
||||
fout = new FileOutputStream(newFileLocation);
|
||||
|
||||
ReadableByteChannel rbc = Channels.newChannel(downloadFrom.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(newFileLocation);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
final byte data[] = new byte[1024];
|
||||
int count;
|
||||
while ((count = in.read(data, 0, 1024)) != -1) {
|
||||
fout.write(data, 0, count);
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (isActivated()) {
|
||||
return;
|
||||
}
|
||||
Log.infoColor("§aUpdate has been scheduled, Downloading new jar.. Restart server to take effect.");
|
||||
activate();
|
||||
Runtime.getRuntime().addShutdownHook(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (File f : toDelete
|
||||
) {
|
||||
if (!f.delete()) {
|
||||
f.deleteOnExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -55,10 +55,13 @@ public class VersionCheckSystem implements SubSystem {
|
||||
}
|
||||
VersionInfo newestVersion = versions.get(0);
|
||||
if (Version.isNewVersionAvailable(new Version(currentVersion), newestVersion.getVersion())) {
|
||||
newVersionAvailable = newestVersion;
|
||||
String notification =
|
||||
"New Release (" + newestVersion.getVersion().toString() + ") is available and can be updated " +
|
||||
"to using update subcommand." + (newestVersion.isRelease() ? "" : " This is a DEV release.");
|
||||
Log.info(notification);
|
||||
Log.infoColor("§a----------------------------------------");
|
||||
Log.infoColor("§a" + notification);
|
||||
Log.infoColor("§a----------------------------------------");
|
||||
NotificationCenter.addNotification(newestVersion.isRelease() ? Priority.HIGH : Priority.MEDIUM, notification);
|
||||
} else {
|
||||
Log.info("You're using the latest version.");
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.djrapitops.plan.system.update;
|
||||
|
||||
import com.djrapitops.plugin.api.utility.Version;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* //TODO Class Javadoc Comment
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class ShutdownUpdateHookTest {
|
||||
|
||||
@ClassRule
|
||||
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void downloadNewJar() throws IOException {
|
||||
File newJar = new File(temporaryFolder.getRoot(), "Plan-4.2.0.jar");
|
||||
ShutdownUpdateHook.downloadNewJar(new VersionInfo(
|
||||
true,
|
||||
new Version("4.2.0"),
|
||||
"https://github.com/Rsl1122/Plan-PlayerAnalytics/releases/download/4.2.0/Plan-4.2.0.jar",
|
||||
""
|
||||
), newJar
|
||||
);
|
||||
|
||||
assertTrue(newJar.exists());
|
||||
|
||||
ShutdownUpdateHook.registerOldJarForDeletion(temporaryFolder.getRoot(), new File(temporaryFolder.getRoot(), "Plan-4.2.0-b1.jar"));
|
||||
|
||||
assertFalse(newJar.exists());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user