Added auto suggestion in the reload command

This commit is contained in:
themode 2020-11-06 23:35:31 +01:00
parent 69f424eb6a
commit 8c8ba37947
2 changed files with 50 additions and 29 deletions

View File

@ -65,7 +65,7 @@ public class ExtensionManager {
// remove invalid extensions // remove invalid extensions
discoveredExtensions.removeIf(ext -> ext.loadStatus != DiscoveredExtension.LoadStatus.LOAD_SUCCESS); discoveredExtensions.removeIf(ext -> ext.loadStatus != DiscoveredExtension.LoadStatus.LOAD_SUCCESS);
for(DiscoveredExtension discoveredExtension : discoveredExtensions) { for (DiscoveredExtension discoveredExtension : discoveredExtensions) {
try { try {
setupClassLoader(discoveredExtension); setupClassLoader(discoveredExtension);
} catch (Exception e) { } catch (Exception e) {
@ -187,9 +187,9 @@ public class ExtensionManager {
} }
// add dependents to pre-existing extensions, so that they can easily be found during reloading // add dependents to pre-existing extensions, so that they can easily be found during reloading
for(String dependency : discoveredExtension.getDependencies()) { for (String dependency : discoveredExtension.getDependencies()) {
Extension dep = extensions.get(dependency.toLowerCase()); Extension dep = extensions.get(dependency.toLowerCase());
if(dep == null) { if (dep == null) {
log.warn("Dependency {} of {} is null? This means the extension has been loaded without its dependency, which could cause issues later.", dependency, discoveredExtension.getName()); log.warn("Dependency {} of {} is null? This means the extension has been loaded without its dependency, which could cause issues later.", dependency, discoveredExtension.getName());
} else { } else {
dep.getDescription().getDependents().add(discoveredExtension.getName()); dep.getDescription().getDependents().add(discoveredExtension.getName());
@ -213,7 +213,7 @@ public class ExtensionManager {
continue; continue;
} }
DiscoveredExtension extension = discoverFromJar(file); DiscoveredExtension extension = discoverFromJar(file);
if(extension != null && extension.loadStatus == DiscoveredExtension.LoadStatus.LOAD_SUCCESS) { if (extension != null && extension.loadStatus == DiscoveredExtension.LoadStatus.LOAD_SUCCESS) {
extensions.add(extension); extensions.add(extension);
} }
} }
@ -274,7 +274,7 @@ public class ExtensionManager {
// Specifies an extension we don't have. // Specifies an extension we don't have.
if (dependencyExtension == null) { if (dependencyExtension == null) {
// attempt to see if it is not already loaded (happens with dynamic (re)loading) // attempt to see if it is not already loaded (happens with dynamic (re)loading)
if(extensions.containsKey(dependencyName.toLowerCase())) { if (extensions.containsKey(dependencyName.toLowerCase())) {
return extensions.get(dependencyName.toLowerCase()).getDescription().getOrigin(); return extensions.get(dependencyName.toLowerCase()).getDescription().getOrigin();
} else { } else {
log.error("Extension {} requires an extension called {}.", discoveredExtension.getName(), dependencyName); log.error("Extension {} requires an extension called {}.", discoveredExtension.getName(), dependencyName);
@ -400,24 +400,24 @@ public class ExtensionManager {
public MinestomExtensionClassLoader newClassLoader(@NotNull DiscoveredExtension extension, @NotNull URL[] urls) { public MinestomExtensionClassLoader newClassLoader(@NotNull DiscoveredExtension extension, @NotNull URL[] urls) {
MinestomRootClassLoader root = MinestomRootClassLoader.getInstance(); MinestomRootClassLoader root = MinestomRootClassLoader.getInstance();
MinestomExtensionClassLoader loader = new MinestomExtensionClassLoader(extension.getName(), urls, root); MinestomExtensionClassLoader loader = new MinestomExtensionClassLoader(extension.getName(), urls, root);
if(extension.getDependencies().length == 0) { if (extension.getDependencies().length == 0) {
// orphaned extension, we can insert it directly // orphaned extension, we can insert it directly
root.addChild(loader); root.addChild(loader);
} else { } else {
// we need to keep track that it has actually been inserted // we need to keep track that it has actually been inserted
// even though it should always be (due to the order in which extensions are loaders), it is an additional layer of """security""" // even though it should always be (due to the order in which extensions are loaders), it is an additional layer of """security"""
boolean foundOne = false; boolean foundOne = false;
for(String dependency : extension.getDependencies()) { for (String dependency : extension.getDependencies()) {
if(extensionLoaders.containsKey(dependency.toLowerCase())) { if (extensionLoaders.containsKey(dependency.toLowerCase())) {
MinestomExtensionClassLoader parentLoader = extensionLoaders.get(dependency.toLowerCase()); MinestomExtensionClassLoader parentLoader = extensionLoaders.get(dependency.toLowerCase());
parentLoader.addChild(loader); parentLoader.addChild(loader);
foundOne = true; foundOne = true;
} }
} }
if(!foundOne) { if (!foundOne) {
log.error("Could not load extension {}, could not find any parent inside classloader hierarchy.", extension.getName()); log.error("Could not load extension {}, could not find any parent inside classloader hierarchy.", extension.getName());
throw new RuntimeException("Could not load extension "+extension.getName()+", could not find any parent inside classloader hierarchy."); throw new RuntimeException("Could not load extension " + extension.getName() + ", could not find any parent inside classloader hierarchy.");
} }
} }
return loader; return loader;
@ -480,7 +480,7 @@ public class ExtensionManager {
// remove as dependent of other extensions // remove as dependent of other extensions
// this avoids issues where a dependent extension fails to reload, and prevents the base extension to reload too // this avoids issues where a dependent extension fails to reload, and prevents the base extension to reload too
for(Extension e : extensionList) { for (Extension e : extensionList) {
e.getDescription().getDependents().remove(ext.getDescription().getName()); e.getDescription().getDependents().remove(ext.getDescription().getName());
} }
@ -502,12 +502,12 @@ public class ExtensionManager {
public void reload(String extensionName) { public void reload(String extensionName) {
Extension ext = extensions.get(extensionName.toLowerCase()); Extension ext = extensions.get(extensionName.toLowerCase());
if(ext == null) { if (ext == null) {
throw new IllegalArgumentException("Extension "+extensionName+" is not currently loaded."); throw new IllegalArgumentException("Extension " + extensionName + " is not currently loaded.");
} }
File originalJar = ext.getDescription().getOrigin().getOriginalJar(); File originalJar = ext.getDescription().getOrigin().getOriginalJar();
if(originalJar == null) { if (originalJar == null) {
log.error("Cannot reload extension {} that is not from a .jar file!", extensionName); log.error("Cannot reload extension {} that is not from a .jar file!", extensionName);
return; return;
} }
@ -516,11 +516,11 @@ public class ExtensionManager {
List<String> dependents = new LinkedList<>(ext.getDescription().getDependents()); // copy dependents list List<String> dependents = new LinkedList<>(ext.getDescription().getDependents()); // copy dependents list
List<File> originalJarsOfDependents = new LinkedList<>(); List<File> originalJarsOfDependents = new LinkedList<>();
for(String dependentID : dependents) { for (String dependentID : dependents) {
Extension dependentExt = extensions.get(dependentID.toLowerCase()); Extension dependentExt = extensions.get(dependentID.toLowerCase());
File dependentOriginalJar = dependentExt.getDescription().getOrigin().getOriginalJar(); File dependentOriginalJar = dependentExt.getDescription().getOrigin().getOriginalJar();
originalJarsOfDependents.add(dependentOriginalJar); originalJarsOfDependents.add(dependentOriginalJar);
if(dependentOriginalJar == null) { if (dependentOriginalJar == null) {
log.error("Cannot reload extension {} that is not from a .jar file!", dependentID); log.error("Cannot reload extension {} that is not from a .jar file!", dependentID);
return; return;
} }
@ -542,7 +542,7 @@ public class ExtensionManager {
DiscoveredExtension rediscoveredExtension = discoverFromJar(originalJar); DiscoveredExtension rediscoveredExtension = discoverFromJar(originalJar);
extensionsToReload.add(rediscoveredExtension); extensionsToReload.add(rediscoveredExtension);
for(File dependentJar : originalJarsOfDependents) { for (File dependentJar : originalJarsOfDependents) {
// rediscover dependent extension to reload // rediscover dependent extension to reload
log.info("Rediscover dependent extension (depends on {}) from jar {}", extensionName, dependentJar.getAbsolutePath()); log.info("Rediscover dependent extension (depends on {}) from jar {}", extensionName, dependentJar.getAbsolutePath());
extensionsToReload.add(discoverFromJar(dependentJar)); extensionsToReload.add(discoverFromJar(dependentJar));
@ -553,8 +553,8 @@ public class ExtensionManager {
} }
public boolean loadDynamicExtension(File jarFile) throws FileNotFoundException { public boolean loadDynamicExtension(File jarFile) throws FileNotFoundException {
if(!jarFile.exists()) { if (!jarFile.exists()) {
throw new FileNotFoundException("File '"+jarFile.getAbsolutePath()+"' does not exists. Cannot load extension."); throw new FileNotFoundException("File '" + jarFile.getAbsolutePath() + "' does not exists. Cannot load extension.");
} }
log.info("Discover dynamic extension from jar {}", jarFile.getAbsolutePath()); log.info("Discover dynamic extension from jar {}", jarFile.getAbsolutePath());
@ -584,12 +584,12 @@ public class ExtensionManager {
// reload extensions // reload extensions
log.info("Actually load extension {}", toReload.getName()); log.info("Actually load extension {}", toReload.getName());
Extension loadedExtension = attemptSingleLoad(toReload); Extension loadedExtension = attemptSingleLoad(toReload);
if(loadedExtension != null) { if (loadedExtension != null) {
newExtensions.add(loadedExtension); newExtensions.add(loadedExtension);
} }
} }
if(newExtensions.isEmpty()) { if (newExtensions.isEmpty()) {
log.error("No extensions to load, skipping callbacks"); log.error("No extensions to load, skipping callbacks");
return false; return false;
} }
@ -604,12 +604,12 @@ public class ExtensionManager {
public void unloadExtension(String extensionName) { public void unloadExtension(String extensionName) {
Extension ext = extensions.get(extensionName.toLowerCase()); Extension ext = extensions.get(extensionName.toLowerCase());
if(ext == null) { if (ext == null) {
throw new IllegalArgumentException("Extension "+extensionName+" is not currently loaded."); throw new IllegalArgumentException("Extension " + extensionName + " is not currently loaded.");
} }
List<String> dependents = new LinkedList<>(ext.getDescription().getDependents()); // copy dependents list List<String> dependents = new LinkedList<>(ext.getDescription().getDependents()); // copy dependents list
for(String dependentID : dependents) { for (String dependentID : dependents) {
Extension dependentExt = extensions.get(dependentID.toLowerCase()); Extension dependentExt = extensions.get(dependentID.toLowerCase());
log.info("Unloading dependent extension {} (because it depends on {})", dependentID, extensionName); log.info("Unloading dependent extension {} (because it depends on {})", dependentID, extensionName);
unload(dependentExt); unload(dependentExt);

View File

@ -8,14 +8,29 @@ import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.extensions.Extension; import net.minestom.server.extensions.Extension;
import net.minestom.server.extensions.ExtensionManager; import net.minestom.server.extensions.ExtensionManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
public class ReloadExtensionCommand extends Command { public class ReloadExtensionCommand extends Command {
// the extensions name as an array
private static String[] extensionsName;
static {
List<String> extensionsName = MinecraftServer.getExtensionManager().getExtensions()
.stream()
.map(extension -> extension.getDescription().getName())
.collect(Collectors.toList());
ReloadExtensionCommand.extensionsName = extensionsName.toArray(new String[0]);
}
public ReloadExtensionCommand() { public ReloadExtensionCommand() {
super("reload"); super("reload");
@ -34,11 +49,11 @@ public class ReloadExtensionCommand extends Command {
private void execute(CommandSender sender, Arguments arguments) { private void execute(CommandSender sender, Arguments arguments) {
String name = join(arguments.getStringArray("extensionName")); String name = join(arguments.getStringArray("extensionName"));
sender.sendMessage("extensionName = "+name+"...."); sender.sendMessage("extensionName = " + name + "....");
ExtensionManager extensionManager = MinecraftServer.getExtensionManager(); ExtensionManager extensionManager = MinecraftServer.getExtensionManager();
Extension ext = extensionManager.getExtension(name); Extension ext = extensionManager.getExtension(name);
if(ext != null) { if (ext != null) {
try { try {
extensionManager.reload(name); extensionManager.reload(name);
} catch (Throwable t) { } catch (Throwable t) {
@ -55,7 +70,7 @@ public class ReloadExtensionCommand extends Command {
} }
} }
} else { } else {
sender.sendMessage("Extension '"+name+"' does not exist."); sender.sendMessage("Extension '" + name + "' does not exist.");
} }
} }
@ -63,11 +78,17 @@ public class ReloadExtensionCommand extends Command {
sender.sendMessage("'" + extension + "' is not a valid extension name!"); sender.sendMessage("'" + extension + "' is not a valid extension name!");
} }
@Nullable
@Override
public String[] onDynamicWrite(@NotNull String text) {
return extensionsName;
}
private String join(String[] extensionNameParts) { private String join(String[] extensionNameParts) {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
for (int i = 0; i < extensionNameParts.length; i++) { for (int i = 0; i < extensionNameParts.length; i++) {
String s = extensionNameParts[i]; String s = extensionNameParts[i];
if(i != 0) { if (i != 0) {
b.append(" "); b.append(" ");
} }
b.append(s); b.append(s);