From d6f44121b138515aafffaf68f3d3772a1d79d211 Mon Sep 17 00:00:00 2001 From: Bukkit/Spigot <noreply+git-bukkit@papermc.io> Date: Thu, 5 May 2011 16:52:50 -0400 Subject: [PATCH] Added support for an update on load feature for plugins. Thanks Raphfrk! Any files placed in the new (optional) update folder are automatically copied into the plugins directory the next time a reload happens. This allows safe updating of the plugin .jar files. By: EvilSeph <evilseph@unaligned.org> --- .../src/main/java/org/bukkit/Server.java | 8 +++ .../bukkit/plugin/SimplePluginManager.java | 17 +++++- .../main/java/org/bukkit/util/FileUtil.java | 59 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 paper-api/src/main/java/org/bukkit/util/FileUtil.java diff --git a/paper-api/src/main/java/org/bukkit/Server.java b/paper-api/src/main/java/org/bukkit/Server.java index e60e2a9744..70ec509a44 100644 --- a/paper-api/src/main/java/org/bukkit/Server.java +++ b/paper-api/src/main/java/org/bukkit/Server.java @@ -83,6 +83,14 @@ public interface Server { */ public int broadcastMessage(String message); + /** + * Gets the name of the update folder. The update folder is used to safely update + * plugins at the right moment on a plugin load. + * + * @return The name of the update folder + */ + public String getUpdateFolder(); + /** * Gets a player object by the given username * diff --git a/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java index 38345b26ad..2ee897fe58 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/paper-api/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -24,6 +24,8 @@ import org.bukkit.event.Event; import org.bukkit.event.Event.Priority; import org.bukkit.event.Listener; +import org.bukkit.util.FileUtil; + /** * Handles all plugin management from the Server */ @@ -33,6 +35,7 @@ public final class SimplePluginManager implements PluginManager { private final List<Plugin> plugins = new ArrayList<Plugin>(); private final Map<String, Plugin> lookupNames = new HashMap<String, Plugin>(); private final Map<Event.Type, SortedSet<RegisteredListener>> listeners = new EnumMap<Event.Type, SortedSet<RegisteredListener>>(Event.Type.class); + private static File updateDirectory = null; private final Comparator<RegisteredListener> comparer = new Comparator<RegisteredListener>() { public int compare(RegisteredListener i, RegisteredListener j) { int result = i.getPriority().compareTo(j.getPriority()); @@ -97,6 +100,10 @@ public final class SimplePluginManager implements PluginManager { LinkedList<File> filesList = new LinkedList(Arrays.asList(files)); + if (!(server.getUpdateFolder().equals(""))) { + updateDirectory = new File(directory, server.getUpdateFolder()); + } + while(!allFailed || finalPass) { allFailed = true; Iterator<File> itr = filesList.iterator(); @@ -164,6 +171,14 @@ public final class SimplePluginManager implements PluginManager { * @throws InvalidDescriptionException Thrown when the specified file contains an invalid description */ public synchronized Plugin loadPlugin(File file, boolean ignoreSoftDependencies) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { + File updateFile = null; + + if (updateDirectory != null && updateDirectory.isDirectory() && (updateFile = new File(updateDirectory, file.getName())).isFile()) { + if (FileUtil.copy(updateFile, file)) { + updateFile.delete(); + } + } + Set<Pattern> filters = fileAssociations.keySet(); Plugin result = null; @@ -279,7 +294,7 @@ public final class SimplePluginManager implements PluginManager { String author = "<NoAuthorGiven>"; if (plugin.getDescription().getAuthors().size() > 0) { - author = plugin.getDescription().getAuthors().get(0); + author = plugin.getDescription().getAuthors().get(0); } server.getLogger().log(Level.SEVERE, String.format( "Nag author: '%s' of '%s' about the following: %s", diff --git a/paper-api/src/main/java/org/bukkit/util/FileUtil.java b/paper-api/src/main/java/org/bukkit/util/FileUtil.java new file mode 100644 index 0000000000..66129c3985 --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/util/FileUtil.java @@ -0,0 +1,59 @@ +package org.bukkit.util; + +import java.nio.channels.FileChannel; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Class containing file utilities + */ + +public class FileUtil { + + /** + * This method copies one file to another location + * + * @param inFile the source filename + * @param outFile the target filename + * @return true on success + */ + + public static boolean copy(File inFile, File outFile) { + if (!inFile.exists()) { + return false; + } + + FileChannel in = null; + FileChannel out = null; + + try { + in = new FileInputStream(inFile).getChannel(); + out = new FileOutputStream(outFile).getChannel(); + + long pos = 0; + long size = in.size(); + + while (pos < size) { + pos += in.transferTo(pos, 10*1024*1024, out); + } + } catch (IOException ioe) { + return false; + } finally { + try { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } catch (IOException ioe) { + return false; + } + } + + return true; + + } +}