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:
Brad Larson
2012-07-10 09:43:31 -05:00
parent 2b41c9c739
commit 0c9418c3f5
3 changed files with 74 additions and 16 deletions

View File

@@ -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;
}
}

View File

@@ -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() {

View File

@@ -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) {