Add option to list disabled plugins
After disabling a plugin, it can now be viewed in the ls command by specifying the --all (-a) argument. This will be more useful once we add an ssh command to re-enabled plugins which are disabled. Change-Id: I4100cd9df4ebfac87b2099ef2c916b99ef55c978 Signed-off-by: Brad Larson <bklarson@gmail.com>
This commit is contained in:
@@ -40,6 +40,9 @@ public class ListPlugins {
|
||||
@Option(name = "--format", metaVar = "FMT", usage = "Output display format")
|
||||
private OutputFormat format = OutputFormat.TEXT;
|
||||
|
||||
@Option(name = "--all", aliases = {"-a"}, usage = "List all plugins, including disabled plugins")
|
||||
private boolean all;
|
||||
|
||||
@Inject
|
||||
protected ListPlugins(PluginLoader pluginLoader) {
|
||||
this.pluginLoader = pluginLoader;
|
||||
@@ -67,7 +70,7 @@ public class ListPlugins {
|
||||
|
||||
Map<String, PluginInfo> output = Maps.newTreeMap();
|
||||
|
||||
List<Plugin> plugins = Lists.newArrayList(pluginLoader.getPlugins());
|
||||
List<Plugin> plugins = Lists.newArrayList(pluginLoader.getPlugins(all));
|
||||
Collections.sort(plugins, new Comparator<Plugin>() {
|
||||
@Override
|
||||
public int compare(Plugin a, Plugin b) {
|
||||
@@ -76,20 +79,22 @@ public class ListPlugins {
|
||||
});
|
||||
|
||||
if (!format.isJson()) {
|
||||
stdout.format("%-30s %-10s\n", "Name", "Version");
|
||||
stdout.format("%-30s %-10s %-8s\n", "Name", "Version", "Status");
|
||||
stdout
|
||||
.print("----------------------------------------------------------------------\n");
|
||||
.print("-------------------------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
for (Plugin p : plugins) {
|
||||
PluginInfo info = new PluginInfo();
|
||||
info.version = p.getVersion();
|
||||
info.disabled = p.isDisabled() ? true : null;
|
||||
|
||||
if (format.isJson()) {
|
||||
output.put(p.getName(), info);
|
||||
} else {
|
||||
stdout.format("%-30s %-10s\n", p.getName(),
|
||||
Strings.nullToEmpty(info.version));
|
||||
stdout.format("%-30s %-10s %-8s\n", p.getName(),
|
||||
Strings.nullToEmpty(info.version),
|
||||
p.isDisabled() ? "DISABLED" : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,5 +108,9 @@ public class ListPlugins {
|
||||
|
||||
private static class PluginInfo {
|
||||
String version;
|
||||
// disabled is only read via reflection when building the json output. We
|
||||
// do not want to show a compiler error that it isn't used.
|
||||
@SuppressWarnings("unused")
|
||||
Boolean disabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public class Plugin {
|
||||
private final File dataDir;
|
||||
private final ApiType apiType;
|
||||
private final ClassLoader classLoader;
|
||||
private final boolean disabled;
|
||||
private Class<? extends Module> sysModule;
|
||||
private Class<? extends Module> sshModule;
|
||||
private Class<? extends Module> httpModule;
|
||||
@@ -119,6 +120,7 @@ public class Plugin {
|
||||
this.dataDir = dataDir;
|
||||
this.apiType = apiType;
|
||||
this.classLoader = classLoader;
|
||||
this.disabled = srcJar.getName().endsWith(".disabled");
|
||||
this.sysModule = sysModule;
|
||||
this.sshModule = sshModule;
|
||||
this.httpModule = httpModule;
|
||||
@@ -165,6 +167,10 @@ public class Plugin {
|
||||
return snapshot.lastModified() != jar.lastModified();
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void start(PluginGuiceEnvironment env) throws Exception {
|
||||
Injector root = newRootInjector(env);
|
||||
manager = new LifecycleManager();
|
||||
@@ -294,13 +300,15 @@ public class Plugin {
|
||||
}
|
||||
|
||||
public void add(RegistrationHandle handle) {
|
||||
if (handle instanceof ReloadableRegistrationHandle) {
|
||||
if (reloadableHandles == null) {
|
||||
reloadableHandles = Lists.newArrayList();
|
||||
if (manager != null) {
|
||||
if (handle instanceof ReloadableRegistrationHandle) {
|
||||
if (reloadableHandles == null) {
|
||||
reloadableHandles = Lists.newArrayList();
|
||||
}
|
||||
reloadableHandles.add((ReloadableRegistrationHandle<?>) handle);
|
||||
}
|
||||
reloadableHandles.add((ReloadableRegistrationHandle<?>) handle);
|
||||
manager.add(handle);
|
||||
}
|
||||
manager.add(handle);
|
||||
}
|
||||
|
||||
List<ReloadableRegistrationHandle<?>> getReloadableHandles() {
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.lang.ref.ReferenceQueue;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -67,6 +68,7 @@ public class PluginLoader implements LifecycleListener {
|
||||
private final PluginGuiceEnvironment env;
|
||||
private final ServerInformationImpl srvInfoImpl;
|
||||
private final ConcurrentMap<String, Plugin> running;
|
||||
private final ConcurrentMap<String, Plugin> disabled;
|
||||
private final Map<String, FileSnapshot> broken;
|
||||
private final ReferenceQueue<ClassLoader> cleanupQueue;
|
||||
private final ConcurrentMap<CleanupHandle, Boolean> cleanupHandles;
|
||||
@@ -85,6 +87,7 @@ public class PluginLoader implements LifecycleListener {
|
||||
env = pe;
|
||||
srvInfoImpl = sii;
|
||||
running = Maps.newConcurrentMap();
|
||||
disabled = Maps.newConcurrentMap();
|
||||
broken = Maps.newHashMap();
|
||||
cleanupQueue = new ReferenceQueue<ClassLoader>();
|
||||
cleanupHandles = Maps.newConcurrentMap();
|
||||
@@ -100,8 +103,14 @@ public class PluginLoader implements LifecycleListener {
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<Plugin> getPlugins() {
|
||||
return running.values();
|
||||
public Iterable<Plugin> getPlugins(boolean all) {
|
||||
if (!all) {
|
||||
return running.values();
|
||||
} else {
|
||||
ArrayList<Plugin> plugins = new ArrayList<Plugin>(running.values());
|
||||
plugins.addAll(disabled.values());
|
||||
return plugins;
|
||||
}
|
||||
}
|
||||
|
||||
public void installPluginFromStream(String name, InputStream in)
|
||||
@@ -178,6 +187,15 @@ public class PluginLoader implements LifecycleListener {
|
||||
|
||||
active.stop();
|
||||
running.remove(name);
|
||||
try {
|
||||
FileSnapshot snapshot = FileSnapshot.save(off);
|
||||
Plugin offPlugin = loadPlugin(name, off, snapshot);
|
||||
disabled.put(name, offPlugin);
|
||||
} catch (Throwable e) {
|
||||
// This shouldn't happen, as the plugin was loaded earlier.
|
||||
log.warn(String.format("Cannot load disabled plugin %s", name),
|
||||
e.getCause());
|
||||
}
|
||||
}
|
||||
cleanInBackground();
|
||||
}
|
||||
@@ -205,6 +223,7 @@ public class PluginLoader implements LifecycleListener {
|
||||
p.stop();
|
||||
}
|
||||
running.clear();
|
||||
disabled.clear();
|
||||
broken.clear();
|
||||
if (cleanupHandles.size() > running.size()) {
|
||||
System.gc();
|
||||
@@ -250,6 +269,7 @@ public class PluginLoader implements LifecycleListener {
|
||||
public synchronized void rescan() {
|
||||
List<File> jars = scanJarsInPluginsDirectory();
|
||||
stopRemovedPlugins(jars);
|
||||
dropRemovedDisabledPlugins(jars);
|
||||
|
||||
for (File jar : jars) {
|
||||
String name = nameOf(jar);
|
||||
@@ -292,14 +312,20 @@ public class PluginLoader implements LifecycleListener {
|
||||
oldPlugin.stop();
|
||||
running.remove(name);
|
||||
}
|
||||
newPlugin.start(env);
|
||||
if (!newPlugin.isDisabled()) {
|
||||
newPlugin.start(env);
|
||||
}
|
||||
if (reload) {
|
||||
env.onReloadPlugin(oldPlugin, newPlugin);
|
||||
oldPlugin.stop();
|
||||
} else {
|
||||
} else if (!newPlugin.isDisabled()) {
|
||||
env.onStartPlugin(newPlugin);
|
||||
}
|
||||
running.put(name, newPlugin);
|
||||
if (!newPlugin.isDisabled()) {
|
||||
running.put(name, newPlugin);
|
||||
} else {
|
||||
disabled.put(name, newPlugin);
|
||||
}
|
||||
broken.remove(name);
|
||||
} catch (Throwable err) {
|
||||
broken.put(name, snapshot);
|
||||
@@ -318,6 +344,16 @@ public class PluginLoader implements LifecycleListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void dropRemovedDisabledPlugins(List<File> jars) {
|
||||
Set<String> unload = Sets.newHashSet(disabled.keySet());
|
||||
for (File jar : jars) {
|
||||
unload.remove(nameOf(jar));
|
||||
}
|
||||
for (String name : unload) {
|
||||
disabled.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized int processPendingCleanups() {
|
||||
CleanupHandle h;
|
||||
while ((h = (CleanupHandle) cleanupQueue.poll()) != null) {
|
||||
@@ -336,6 +372,9 @@ public class PluginLoader implements LifecycleListener {
|
||||
|
||||
private static String nameOf(File jar) {
|
||||
String name = jar.getName();
|
||||
if (name.endsWith(".disabled")) {
|
||||
name = name.substring(0, name.lastIndexOf('.'));
|
||||
}
|
||||
int ext = name.lastIndexOf('.');
|
||||
return 0 < ext ? name.substring(0, ext) : name;
|
||||
}
|
||||
@@ -430,7 +469,9 @@ public class PluginLoader implements LifecycleListener {
|
||||
File[] matches = pluginsDir.listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.getName().endsWith(".jar") && pathname.isFile();
|
||||
String n = pathname.getName();
|
||||
return (n.endsWith(".jar") || n.endsWith(".jar.disabled"))
|
||||
&& pathname.isFile();
|
||||
}
|
||||
});
|
||||
if (matches == null) {
|
||||
|
||||
Reference in New Issue
Block a user