Add multi plugin watcher
This commit is contained in:
parent
1b4997869d
commit
8d3a85d472
8 changed files with 300 additions and 103 deletions
|
|
@ -17,13 +17,13 @@ import net.frankheijden.serverutils.common.commands.arguments.PluginArgument;
|
||||||
import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument;
|
import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument;
|
||||||
import net.frankheijden.serverutils.common.config.MessagesResource;
|
import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
||||||
import net.frankheijden.serverutils.common.entities.results.AbstractResult;
|
|
||||||
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.results.Result;
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
|
|
@ -73,7 +73,11 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
|
||||||
))
|
))
|
||||||
.handler(this::handleReloadPlugin));
|
.handler(this::handleReloadPlugin));
|
||||||
manager.command(buildSubcommand(builder, "watchplugin")
|
manager.command(buildSubcommand(builder, "watchplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(new PluginsArgument<>(
|
||||||
|
true,
|
||||||
|
"plugins",
|
||||||
|
new PluginsArgument.PluginsParser<>(plugin, arrayCreator, getRawPath("watchplugin"))
|
||||||
|
))
|
||||||
.handler(this::handleWatchPlugin));
|
.handler(this::handleWatchPlugin));
|
||||||
manager.command(buildSubcommand(builder, "unwatchplugin")
|
manager.command(buildSubcommand(builder, "unwatchplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(getArgument("plugin"))
|
||||||
|
|
@ -256,24 +260,23 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
|
||||||
|
|
||||||
private void handleWatchPlugin(CommandContext<C> context) {
|
private void handleWatchPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
P pluginArg = context.get("plugin");
|
List<P> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
if (checkDependingPlugins(context, sender, plugins, "watchplugin")) {
|
||||||
String pluginId = pluginManager.getPluginId(pluginArg);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractResult result = pluginManager.watchPlugin(sender, pluginId);
|
WatchResult result = plugin.getWatchManager().watchPlugins(sender, plugins);
|
||||||
result.sendTo(sender, "watch", pluginId);
|
result.sendTo(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnwatchPlugin(CommandContext<C> context) {
|
private void handleUnwatchPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
P pluginArg = context.get("plugin");
|
P pluginArg = context.get("plugin");
|
||||||
|
|
||||||
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
String pluginId = plugin.getPluginManager().getPluginId(pluginArg);
|
||||||
String pluginId = pluginManager.getPluginId(pluginArg);
|
WatchResult result = plugin.getWatchManager().unwatchPluginsAssociatedWith(pluginId);
|
||||||
|
result.sendTo(sender);
|
||||||
AbstractResult result = pluginManager.unwatchPlugin(pluginId);
|
|
||||||
result.sendTo(sender, "unwatch", pluginId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePluginInfo(CommandContext<C> context) {
|
private void handlePluginInfo(CommandContext<C> context) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
||||||
import net.frankheijden.serverutils.common.managers.UpdateManager;
|
import net.frankheijden.serverutils.common.managers.UpdateManager;
|
||||||
|
import net.frankheijden.serverutils.common.managers.WatchManager;
|
||||||
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
||||||
import net.frankheijden.serverutils.common.providers.ResourceProvider;
|
import net.frankheijden.serverutils.common.providers.ResourceProvider;
|
||||||
import net.frankheijden.serverutils.common.utils.FileUtils;
|
import net.frankheijden.serverutils.common.utils.FileUtils;
|
||||||
|
|
@ -24,6 +25,7 @@ import net.frankheijden.serverutils.common.utils.FileUtils;
|
||||||
public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
|
public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
|
||||||
|
|
||||||
private final UpdateManager updateManager = new UpdateManager();
|
private final UpdateManager updateManager = new UpdateManager();
|
||||||
|
private final WatchManager<P, T> watchManager = new WatchManager<>(this);
|
||||||
private CommandsResource commandsResource;
|
private CommandsResource commandsResource;
|
||||||
private ConfigResource configResource;
|
private ConfigResource configResource;
|
||||||
private MessagesResource messagesResource;
|
private MessagesResource messagesResource;
|
||||||
|
|
@ -57,6 +59,10 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
|
||||||
return updateManager;
|
return updateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WatchManager<P, T> getWatchManager() {
|
||||||
|
return watchManager;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Logger getLogger();
|
public abstract Logger getLogger();
|
||||||
|
|
||||||
public abstract File getDataFolder();
|
public abstract File getDataFolder();
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,60 @@
|
||||||
package net.frankheijden.serverutils.common.entities.results;
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
|
import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
public enum WatchResult implements AbstractResult {
|
public enum WatchResult implements AbstractResult {
|
||||||
|
|
||||||
START,
|
START,
|
||||||
CHANGE,
|
CHANGE,
|
||||||
|
ALREADY_WATCHING,
|
||||||
NOT_WATCHING,
|
NOT_WATCHING,
|
||||||
|
FILE_DELETED,
|
||||||
|
DELETED_FILE_IS_CREATED,
|
||||||
STOPPED;
|
STOPPED;
|
||||||
|
|
||||||
/**
|
private List<String> args = null;
|
||||||
* Retrieves the associated message of the result
|
|
||||||
* and sends it to a CommandSender.
|
public WatchResult arg(String arg) {
|
||||||
* @param sender The receiver.
|
return args(Collections.singletonList(arg));
|
||||||
* @param action The action which let to the result.
|
}
|
||||||
* @param what An associated variable.
|
|
||||||
*/
|
public WatchResult args(List<String> args) {
|
||||||
|
this.args = args;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendTo(ServerCommandSender<?> sender, String action, String what) {
|
public void sendTo(ServerCommandSender<?> sender, String action, String what) {
|
||||||
ServerUtilsApp.getPlugin().getMessagesResource().sendMessage(
|
arg(what);
|
||||||
sender,
|
sendTo(sender);
|
||||||
"serverutils.watcher." + this.name().toLowerCase(),
|
}
|
||||||
"%what%", what
|
|
||||||
);
|
/**
|
||||||
|
* Sends the result(s) to the console and specified sender.
|
||||||
|
*/
|
||||||
|
public void sendTo(ServerCommandSender<?> sender) {
|
||||||
|
String path = "serverutils.watchplugin." + this.name().toLowerCase();
|
||||||
|
List<String[]> sendArguments = new ArrayList<>();
|
||||||
|
if (args == null || args.isEmpty()) {
|
||||||
|
sendArguments.add(new String[0]);
|
||||||
|
} else {
|
||||||
|
for (String what : args) {
|
||||||
|
sendArguments.add(new String[] { "%what%", what });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagesResource messages = ServerUtilsApp.getPlugin().getMessagesResource();
|
||||||
|
ServerCommandSender<?> console = ServerUtilsApp.getPlugin().getChatProvider().getConsoleSender();
|
||||||
|
for (String[] replacements : sendArguments) {
|
||||||
|
messages.sendMessage(sender, path, replacements);
|
||||||
|
if (sender.isPlayer()) {
|
||||||
|
messages.sendMessage(console, path, replacements);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,14 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
|
||||||
import net.frankheijden.serverutils.common.entities.results.AbstractResult;
|
|
||||||
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResult;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.results.Result;
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
|
||||||
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
import net.frankheijden.serverutils.common.providers.PluginProvider;
|
import net.frankheijden.serverutils.common.providers.PluginProvider;
|
||||||
import net.frankheijden.serverutils.common.tasks.PluginWatcherTask;
|
|
||||||
import net.frankheijden.serverutils.common.utils.DependencyUtils;
|
import net.frankheijden.serverutils.common.utils.DependencyUtils;
|
||||||
|
|
||||||
public abstract class AbstractPluginManager<P, D extends ServerUtilsPluginDescription> implements PluginProvider<P, D> {
|
public abstract class AbstractPluginManager<P, D extends ServerUtilsPluginDescription> implements PluginProvider<P, D> {
|
||||||
|
|
@ -294,23 +289,4 @@ public abstract class AbstractPluginManager<P, D extends ServerUtilsPluginDescri
|
||||||
|
|
||||||
return DependencyUtils.determineOrder(dependencyMap);
|
return DependencyUtils.determineOrder(dependencyMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts watching the specified plugin for changes.
|
|
||||||
* Reloads the plugin if a change is detected.
|
|
||||||
*/
|
|
||||||
public AbstractResult watchPlugin(ServerCommandSender<?> sender, String pluginId) {
|
|
||||||
if (getPlugin(pluginId).isPresent()) return Result.NOT_EXISTS;
|
|
||||||
ServerUtilsApp.getPlugin().getTaskManager()
|
|
||||||
.runTaskAsynchronously(pluginId, new PluginWatcherTask(sender, pluginId));
|
|
||||||
return WatchResult.START;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops watching the plugin for changes.
|
|
||||||
*/
|
|
||||||
public AbstractResult unwatchPlugin(String pluginId) {
|
|
||||||
if (ServerUtilsApp.getPlugin().getTaskManager().cancelTask(pluginId)) return WatchResult.STOPPED;
|
|
||||||
return WatchResult.NOT_WATCHING;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package net.frankheijden.serverutils.common.managers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
|
import net.frankheijden.serverutils.common.tasks.PluginWatcherTask;
|
||||||
|
|
||||||
|
public class WatchManager<P, T> {
|
||||||
|
|
||||||
|
private final ServerUtilsPlugin<P, T, ?, ?, ?> plugin;
|
||||||
|
private final Map<String, WatchTask> watchTasks;
|
||||||
|
|
||||||
|
public WatchManager(ServerUtilsPlugin<P, T, ?, ?, ?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.watchTasks = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts watching the specified plugin and reloads it when a change is detected.
|
||||||
|
*/
|
||||||
|
public WatchResult watchPlugins(ServerCommandSender<?> sender, List<P> plugins) {
|
||||||
|
List<String> pluginIds = new ArrayList<>(plugins.size());
|
||||||
|
for (P watchPlugin : plugins) {
|
||||||
|
String pluginId = plugin.getPluginManager().getPluginId(watchPlugin);
|
||||||
|
if (watchTasks.containsKey(pluginId)) {
|
||||||
|
return WatchResult.ALREADY_WATCHING.arg(pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginIds.add(plugin.getPluginManager().getPluginId(watchPlugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID key = UUID.randomUUID();
|
||||||
|
plugin.getTaskManager().runTaskAsynchronously(
|
||||||
|
key.toString(),
|
||||||
|
new PluginWatcherTask<>(plugin, sender, plugins)
|
||||||
|
);
|
||||||
|
|
||||||
|
WatchTask watchTask = new WatchTask(key, pluginIds);
|
||||||
|
for (String pluginId : pluginIds) {
|
||||||
|
watchTasks.put(pluginId, watchTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WatchResult.START.args(pluginIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops watching plugins for changes.
|
||||||
|
*/
|
||||||
|
public WatchResult unwatchPluginsAssociatedWith(String pluginId) {
|
||||||
|
WatchTask task = watchTasks.get(pluginId);
|
||||||
|
if (task != null && plugin.getTaskManager().cancelTask(task.key.toString())) {
|
||||||
|
task.pluginIds.forEach(watchTasks::remove);
|
||||||
|
return WatchResult.STOPPED.args(task.pluginIds);
|
||||||
|
}
|
||||||
|
return WatchResult.NOT_WATCHING.arg(pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class WatchTask {
|
||||||
|
|
||||||
|
private final UUID key;
|
||||||
|
private final List<String> pluginIds;
|
||||||
|
|
||||||
|
private WatchTask(UUID key, List<String> pluginIds) {
|
||||||
|
this.key = key;
|
||||||
|
this.pluginIds = pluginIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,34 @@
|
||||||
package net.frankheijden.serverutils.common.tasks;
|
package net.frankheijden.serverutils.common.tasks;
|
||||||
|
|
||||||
import com.sun.nio.file.SensitivityWatchEventModifier;
|
import com.sun.nio.file.SensitivityWatchEventModifier;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
|
||||||
import net.frankheijden.serverutils.common.entities.AbstractTask;
|
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
|
||||||
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
|
||||||
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
|
||||||
import net.frankheijden.serverutils.common.utils.FileUtils;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.ClosedWatchServiceException;
|
import java.nio.file.ClosedWatchServiceException;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardWatchEventKinds;
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
import java.nio.file.WatchEvent;
|
import java.nio.file.WatchEvent;
|
||||||
import java.nio.file.WatchKey;
|
import java.nio.file.WatchKey;
|
||||||
import java.nio.file.WatchService;
|
import java.nio.file.WatchService;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import net.frankheijden.serverutils.common.entities.AbstractTask;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
|
import net.frankheijden.serverutils.common.utils.FileUtils;
|
||||||
|
|
||||||
public class PluginWatcherTask extends AbstractTask {
|
public class PluginWatcherTask<P, T> extends AbstractTask {
|
||||||
|
|
||||||
private static final WatchEvent.Kind<?>[] EVENTS = new WatchEvent.Kind[]{
|
private static final WatchEvent.Kind<?>[] EVENTS = new WatchEvent.Kind[]{
|
||||||
StandardWatchEventKinds.ENTRY_CREATE,
|
StandardWatchEventKinds.ENTRY_CREATE,
|
||||||
|
|
@ -28,32 +36,33 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
StandardWatchEventKinds.ENTRY_DELETE
|
StandardWatchEventKinds.ENTRY_DELETE
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ServerUtilsPlugin<?, ?, ?, ?, ?> plugin = ServerUtilsApp.getPlugin();
|
private final ServerUtilsPlugin<P, T, ?, ?, ?> plugin;
|
||||||
private final AbstractPluginManager<?, ?> pluginManager = plugin.getPluginManager();
|
|
||||||
private final ChatProvider<?, ?> chatProvider = plugin.getChatProvider();
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final AbstractTaskManager taskManager = plugin.getTaskManager();
|
|
||||||
|
|
||||||
private final ServerCommandSender<?> sender;
|
private final ServerCommandSender<?> sender;
|
||||||
private final String pluginName;
|
private final Map<String, WatchEntry> fileNameToWatchEntryMap;
|
||||||
private final AtomicBoolean run;
|
private final Map<String, WatchEntry> pluginIdToWatchEntryMap;
|
||||||
private File file;
|
|
||||||
private String hash;
|
|
||||||
private long hashTimestamp = 0;
|
|
||||||
|
|
||||||
|
private final AtomicBoolean run = new AtomicBoolean(true);
|
||||||
private WatchService watchService;
|
private WatchService watchService;
|
||||||
private Object task = null;
|
private T task = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new PluginWatcherTask for the specified plugin.
|
* Constructs a new PluginWatcherTask for the specified plugin.
|
||||||
*
|
|
||||||
* @param pluginName The name of the plugin.
|
|
||||||
*/
|
*/
|
||||||
public PluginWatcherTask(ServerCommandSender<?> sender, String pluginName) {
|
public PluginWatcherTask(ServerUtilsPlugin<P, T, ?, ?, ?> plugin, ServerCommandSender<?> sender, List<P> plugins) {
|
||||||
|
this.plugin = plugin;
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.pluginName = pluginName;
|
this.fileNameToWatchEntryMap = new HashMap<>();
|
||||||
this.file = pluginManager.getPluginFile(pluginName).orElse(null);
|
this.pluginIdToWatchEntryMap = new HashMap<>();
|
||||||
this.run = new AtomicBoolean(true);
|
|
||||||
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
|
for (P watchPlugin : plugins) {
|
||||||
|
File file = pluginManager.getPluginFile(watchPlugin);
|
||||||
|
|
||||||
|
WatchEntry entry = new WatchEntry(pluginManager.getPluginId(watchPlugin));
|
||||||
|
entry.update(file);
|
||||||
|
|
||||||
|
this.fileNameToWatchEntryMap.put(file.getName(), entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -61,34 +70,21 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
||||||
this.watchService = watchService;
|
this.watchService = watchService;
|
||||||
|
|
||||||
File folder = pluginManager.getPluginsFolder();
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
folder.toPath().register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
Path basePath = pluginManager.getPluginsFolder().toPath();
|
||||||
|
basePath.register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
||||||
|
|
||||||
while (run.get()) {
|
while (run.get()) {
|
||||||
WatchKey key = watchService.take();
|
WatchKey key = watchService.take();
|
||||||
for (WatchEvent<?> event : key.pollEvents()) {
|
for (WatchEvent<?> event : key.pollEvents()) {
|
||||||
if (file.getName().equals(event.context().toString())) {
|
Path path = basePath.resolve((Path) event.context());
|
||||||
if (task != null) {
|
|
||||||
taskManager.cancelTask(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
String previousHash = hash;
|
if (!Files.isDirectory(path)) {
|
||||||
long previousHashTimestamp = hashTimestamp;
|
handleWatchEvent(path);
|
||||||
|
|
||||||
hash = FileUtils.getHash(file.toPath());
|
|
||||||
hashTimestamp = System.currentTimeMillis();
|
|
||||||
task = ServerUtilsApp.getPlugin().getTaskManager().runTaskLater(() -> {
|
|
||||||
if (hash.equals(previousHash) || previousHashTimestamp < hashTimestamp - 1000L) {
|
|
||||||
send(WatchResult.CHANGE);
|
|
||||||
|
|
||||||
pluginManager.reloadPlugin(pluginName);
|
|
||||||
file = pluginManager.getPluginFile(pluginName).orElse(null);
|
|
||||||
}
|
|
||||||
}, 10L);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file == null || !key.reset()) {
|
if ((fileNameToWatchEntryMap.isEmpty() && pluginIdToWatchEntryMap.isEmpty()) || !key.reset()) {
|
||||||
send(WatchResult.STOPPED);
|
send(WatchResult.STOPPED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -102,10 +98,93 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleWatchEvent(Path path) {
|
||||||
|
String fileName = path.getFileName().toString();
|
||||||
|
WatchEntry entry = fileNameToWatchEntryMap.get(fileName);
|
||||||
|
|
||||||
|
if (entry == null && Files.exists(path)) {
|
||||||
|
Optional<? extends ServerUtilsPluginDescription> descriptionOptional;
|
||||||
|
try {
|
||||||
|
descriptionOptional = plugin.getPluginManager().getPluginDescription(path.toFile());
|
||||||
|
} catch (InvalidPluginDescriptionException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptionOptional.isPresent()) {
|
||||||
|
ServerUtilsPluginDescription description = descriptionOptional.get();
|
||||||
|
WatchEntry foundEntry = pluginIdToWatchEntryMap.remove(description.getId());
|
||||||
|
if (foundEntry != null) {
|
||||||
|
send(WatchResult.DELETED_FILE_IS_CREATED.arg(foundEntry.pluginId));
|
||||||
|
fileNameToWatchEntryMap.put(fileName, foundEntry);
|
||||||
|
|
||||||
|
if (pluginIdToWatchEntryMap.isEmpty()) {
|
||||||
|
entry = foundEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry != null) {
|
||||||
|
checkWatchEntry(entry, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkWatchEntry(WatchEntry entry, String fileName) {
|
||||||
|
if (task != null) {
|
||||||
|
plugin.getTaskManager().cancelTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
|
Optional<File> fileOptional = pluginManager.getPluginFile(entry.pluginId);
|
||||||
|
if (!fileOptional.isPresent()) {
|
||||||
|
send(WatchResult.FILE_DELETED.arg(entry.pluginId));
|
||||||
|
|
||||||
|
fileNameToWatchEntryMap.remove(fileName);
|
||||||
|
pluginIdToWatchEntryMap.put(entry.pluginId, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String previousHash = entry.hash;
|
||||||
|
long previousTimestamp = entry.timestamp;
|
||||||
|
entry.update(fileOptional.get());
|
||||||
|
|
||||||
|
task = plugin.getTaskManager().runTaskLater(() -> {
|
||||||
|
if (entry.hash.equals(previousHash) || previousTimestamp < entry.timestamp - 1000L) {
|
||||||
|
send(WatchResult.CHANGE);
|
||||||
|
|
||||||
|
List<P> plugins = new ArrayList<>(fileNameToWatchEntryMap.size());
|
||||||
|
Map<String, WatchEntry> retainedWatchEntries = new HashMap<>();
|
||||||
|
for (WatchEntry oldEntry : fileNameToWatchEntryMap.values()) {
|
||||||
|
Optional<P> pluginOptional = pluginManager.getPlugin(oldEntry.pluginId);
|
||||||
|
if (!pluginOptional.isPresent()) continue;
|
||||||
|
|
||||||
|
plugins.add(pluginOptional.get());
|
||||||
|
retainedWatchEntries.put(oldEntry.pluginId, oldEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNameToWatchEntryMap.clear();
|
||||||
|
|
||||||
|
PluginResults<P> reloadResults = pluginManager.reloadPlugins(plugins);
|
||||||
|
reloadResults.sendTo(sender, "reload");
|
||||||
|
|
||||||
|
for (PluginResult<P> reloadResult : reloadResults) {
|
||||||
|
if (!reloadResult.isSuccess()) continue;
|
||||||
|
|
||||||
|
P reloadedPlugin = reloadResult.getPlugin();
|
||||||
|
String pluginId = pluginManager.getPluginId(reloadedPlugin);
|
||||||
|
|
||||||
|
WatchEntry retainedEntry = retainedWatchEntries.get(pluginId);
|
||||||
|
String pluginFileName = pluginManager.getPluginFile(reloadedPlugin).getName();
|
||||||
|
fileNameToWatchEntryMap.put(pluginFileName, retainedEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 10L);
|
||||||
|
}
|
||||||
|
|
||||||
private void send(WatchResult result) {
|
private void send(WatchResult result) {
|
||||||
result.sendTo(sender, null, pluginName);
|
result.sendTo(sender);
|
||||||
if (sender.isPlayer()) {
|
if (sender.isPlayer()) {
|
||||||
result.sendTo(chatProvider.getConsoleSender(), null, pluginName);
|
result.sendTo(plugin.getChatProvider().getConsoleSender());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,4 +197,20 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class WatchEntry {
|
||||||
|
|
||||||
|
private final String pluginId;
|
||||||
|
private String hash = null;
|
||||||
|
private long timestamp = 0L;
|
||||||
|
|
||||||
|
public WatchEntry(String pluginId) {
|
||||||
|
this.pluginId = pluginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(File file) {
|
||||||
|
this.hash = FileUtils.getHash(file.toPath());
|
||||||
|
this.timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,17 @@
|
||||||
"main": "watchplugin",
|
"main": "watchplugin",
|
||||||
"aliases": ["wp"],
|
"aliases": ["wp"],
|
||||||
"permission": "serverutils.watchplugin",
|
"permission": "serverutils.watchplugin",
|
||||||
"description": "Watches the specified plugin for changes.",
|
"description": "Watches the specified plugin(s) for changes.",
|
||||||
"display-in-help": true
|
"display-in-help": true,
|
||||||
|
"flags": {
|
||||||
|
"force": {
|
||||||
|
"main": "force",
|
||||||
|
"aliases": ["f"],
|
||||||
|
"permission": "serverutils.watchplugin",
|
||||||
|
"description": "Force watches the specified plugin(s) for changes.",
|
||||||
|
"display-in-help": false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"unwatchplugin": {
|
"unwatchplugin": {
|
||||||
"main": "unwatchplugin",
|
"main": "unwatchplugin",
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,14 @@
|
||||||
"last_separator": " &cand ",
|
"last_separator": " &cand ",
|
||||||
"override": "&cUse \"&4/%command%&c\" to force command execution."
|
"override": "&cUse \"&4/%command%&c\" to force command execution."
|
||||||
},
|
},
|
||||||
"watcher": {
|
"watchplugin": {
|
||||||
"start": "&3Started watching &b%what%&3!",
|
"start": "&3Started watching &b%what%&3!",
|
||||||
"change": "&3Change detected for plugin &b%what%&3, reloading now...",
|
"change": "&3Changes detected, reloading plugins now...",
|
||||||
"stopped": "&3Stopped watching &b%what%&3!",
|
"stopped": "&3Stopped watching &b%what%&3!",
|
||||||
"not_watching": "&cWe aren't watching that plugin!"
|
"file_deleted": "&cPlugin file &4%what%&c has been deleted! Waiting for plugin to show up...",
|
||||||
|
"deleted_file_is_created": "&3Plugin file &b%what%&3 has shown up again!",
|
||||||
|
"already_watching": "&cYou are already watching &4%what%&c!",
|
||||||
|
"not_watching": "&cYou are not watching &4%what%&c!"
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"available": "&8&m------------=&r&8[ &b&lServerUtils Update&r &8]&m=--------------\n &3Current version: &b%old%\n &3New version: &b%new%\n &3Release info: &b%info%\n&8&m-------------------------------------------------",
|
"available": "&8&m------------=&r&8[ &b&lServerUtils Update&r &8]&m=--------------\n &3Current version: &b%old%\n &3New version: &b%new%\n &3Release info: &b%info%\n&8&m-------------------------------------------------",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue