You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2013/04/12 15:58:21 UTC
svn commit: r1467272 - in /karaf/trunk/shell:
console/src/main/java/org/apache/karaf/shell/console/completer/
help/src/main/java/org/apache/karaf/shell/help/impl/
Author: jbonofre
Date: Fri Apr 12 13:58:21 2013
New Revision: 1467272
URL: http://svn.apache.org/r1467272
Log:
[KARAF-2121] Add support for displaying gogo commands in Karaf shell help
Modified:
karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java
karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java
karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java
karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java
karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java
Modified: karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java?rev=1467272&r1=1467271&r2=1467272&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java (original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java Fri Apr 12 13:58:21 2013
@@ -75,6 +75,7 @@ public class CommandNamesCompleter imple
commands.add(name);
if (name.indexOf(':') > 0) {
commands.add(name.substring(0, name.indexOf(':')));
+ commands.add(name.substring(name.indexOf(':') + 1));
}
}
}
Modified: karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java?rev=1467272&r1=1467271&r2=1467272&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java (original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java Fri Apr 12 13:58:21 2013
@@ -102,6 +102,7 @@ public class CommandsCompleter implement
}
try {
completers.add(new ArgumentCompleter(session, (CommandWithAction) function, command));
+ completers.add(new CommandNamesCompleter(session));
} catch (Throwable t) {
LOGGER.debug("Unable to create completers for command '" + command + "'", t);
}
Modified: karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java?rev=1467272&r1=1467271&r2=1467272&view=diff
==============================================================================
--- karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java (original)
+++ karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java Fri Apr 12 13:58:21 2013
@@ -20,13 +20,11 @@ package org.apache.karaf.shell.help.impl
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.*;
import jline.Terminal;
+import org.apache.felix.gogo.runtime.CommandProxy;
import org.apache.felix.gogo.runtime.CommandSessionImpl;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Function;
@@ -79,6 +77,14 @@ public class CommandListHelpProvider imp
name = name.substring(2);
}
commands.put(name, description);
+ } else if (function instanceof CommandProxy) {
+ Hashtable<String, HelpSystem.GogoCommandHelper> helpers = (Hashtable<String, HelpSystem.GogoCommandHelper>) session.get(HelpSystem.GOGO_COMMAND_HELPERS);
+ if (helpers != null) {
+ HelpSystem.GogoCommandHelper helper = helpers.get(name);
+ if (helper != null) {
+ commands.put(name, helper.getDescription());
+ }
+ }
}
}
return commands;
Modified: karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java?rev=1467272&r1=1467271&r2=1467272&view=diff
==============================================================================
--- karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java (original)
+++ karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java Fri Apr 12 13:58:21 2013
@@ -17,25 +17,39 @@
*/
package org.apache.karaf.shell.help.impl;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.*;
+import jline.Terminal;
+import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Descriptor;
import org.apache.karaf.shell.console.HelpProvider;
+import org.apache.karaf.shell.console.NameScoping;
+import org.apache.karaf.shell.util.IndentFormatter;
import org.apache.karaf.util.InterpolationHelper;
+import org.fusesource.jansi.Ansi;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
public class HelpSystem implements HelpProvider {
private BundleContext context;
+ Hashtable<String, GogoCommandHelper> helpers = new Hashtable<String, GogoCommandHelper>();
public HelpSystem(BundleContext context) {
this.context = context;
+ try {
+ ServiceTracker commandTracker = trackOSGiCommands(context);
+ commandTracker.open();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@SuppressWarnings("unchecked")
@@ -55,6 +69,8 @@ public class HelpSystem implements HelpP
}
public String getHelp(final CommandSession session, String path) {
+ session.put(GOGO_COMMAND_HELPERS, helpers);
+
if (path == null) {
path = "%root%";
}
@@ -81,5 +97,115 @@ public class HelpSystem implements HelpP
}
return help;
}
-
+
+ public static String GOGO_COMMAND_HELPERS = "gogocommand_helpers";
+
+ private ServiceTracker trackOSGiCommands(final BundleContext context) throws InvalidSyntaxException {
+ Filter filter = context.createFilter(String.format("(&(%s=*)(%s=*))", CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION));
+
+ return new ServiceTracker(context, filter, null) {
+
+ @Override
+ public Object addingService(ServiceReference reference) {
+ Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
+ Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+ List<Object> commands = new ArrayList<Object>();
+
+ Object commandObject = context.getService(reference);
+
+ if (scope != null && function != null) {
+ if (function.getClass().isArray()) {
+ for (Object f : ((Object[]) function)) {
+ GogoCommandHelper gogoCommandHelper = new GogoCommandHelper(commandObject, (String) scope, f.toString());
+ helpers.put(scope + ":" + f.toString(), gogoCommandHelper);
+ }
+ } else {
+ GogoCommandHelper gogoCommandHelper = new GogoCommandHelper(commandObject, (String) scope, function.toString());
+ helpers.put(scope + ":" + function.toString(), gogoCommandHelper);
+ }
+ return commands;
+ }
+ return null;
+ }
+
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ super.removedService(reference, service);
+ }
+ };
+ }
+
+ class GogoCommandHelper {
+
+ private Object commandObject;
+ private String scope;
+ private String function;
+ private String description = "";
+
+ public GogoCommandHelper(Object commandObject, String scope, String function) {
+ this.commandObject = commandObject;
+ this.scope = scope;
+ this.function = function;
+
+ for (Method m : commandObject.getClass().getMethods()) {
+ if (m.getName().equals(function)) {
+ Descriptor descriptor = m.getAnnotation(Descriptor.class);
+ if (descriptor != null) {
+ description = descriptor.value();
+ }
+ }
+ }
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void printUsage(CommandSession session, PrintStream out) {
+ Terminal term = session != null ? (Terminal) session.get(".jline.terminal") : null;
+ int termWidth = term != null ? term.getWidth() : 80;
+ boolean globalScope = NameScoping.isGlobalScope(session, scope);
+
+ Hashtable<String, String> arguments = new Hashtable<String, String>();
+ for (Method m : commandObject.getClass().getMethods()) {
+ if (m.getName().equals(function)) {
+ Annotation[][] annotations = m.getParameterAnnotations();
+ int i = 0;
+ for (Class<?> paramClass : m.getParameterTypes()) {
+ String argumentDescription = "";
+ for (Annotation annotation : annotations[i++]) {
+ if (annotation.annotationType().equals(Descriptor.class)) {
+ argumentDescription = ((Descriptor) annotation).value();
+ break;
+ }
+ }
+ arguments.put(paramClass.getSimpleName(), argumentDescription);
+ }
+ }
+ }
+ out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("DESCRIPTION").a(Ansi.Attribute.RESET));
+ out.print(" ");
+ if (globalScope) {
+ out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(function).a(Ansi.Attribute.RESET));
+ } else {
+ out.println(Ansi.ansi().a(scope).a(":").a(Ansi.Attribute.INTENSITY_BOLD).a(function).a(Ansi.Attribute.RESET));
+ }
+ out.println();
+ out.print("\t");
+ out.println(getDescription());
+ out.println();
+
+ if (arguments.size() > 0) {
+ out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("ARGUMENTS").a(Ansi.Attribute.RESET));
+ for (String argumentName : arguments.keySet()) {
+ out.print(" ");
+ out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(argumentName).a(Ansi.Attribute.RESET));
+ IndentFormatter.printFormatted(" ", arguments.get(argumentName), termWidth, out);
+ }
+ out.println();
+ }
+ }
+
+ }
+
}
Modified: karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java?rev=1467272&r1=1467271&r2=1467272&view=diff
==============================================================================
--- karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java (original)
+++ karaf/trunk/shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java Fri Apr 12 13:58:21 2013
@@ -20,12 +20,19 @@ package org.apache.karaf.shell.help.impl
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
import java.util.Set;
+import org.apache.felix.gogo.runtime.CommandProxy;
import org.apache.felix.gogo.runtime.CommandSessionImpl;
import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Function;
import org.apache.felix.service.threadio.ThreadIO;
+import org.apache.karaf.shell.console.BundleContextAware;
import org.apache.karaf.shell.console.HelpProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
public class SingleCommandHelpProvider implements HelpProvider {
@@ -49,7 +56,19 @@ public class SingleCommandHelpProvider i
ByteArrayOutputStream baos = new ByteArrayOutputStream();
io.setStreams(new ByteArrayInputStream(new byte[0]), new PrintStream(baos, true), new PrintStream(baos, true));
try {
- session.execute(path + " --help");
+ Function function = (Function) session.get(path);
+ function = unproxy(function);
+ if (function != null && function instanceof CommandProxy) {
+ Hashtable<String, HelpSystem.GogoCommandHelper> helpers = (Hashtable<String, HelpSystem.GogoCommandHelper>) session.get(HelpSystem.GOGO_COMMAND_HELPERS);
+ if (helpers != null) {
+ HelpSystem.GogoCommandHelper gogoCommandHelper = helpers.get(path);
+ if (gogoCommandHelper != null) {
+ gogoCommandHelper.printUsage(session, session.getConsole());
+ }
+ }
+ } else {
+ session.execute(path + " --help");
+ }
} catch (Throwable t) {
t.printStackTrace();
} finally {
@@ -59,4 +78,29 @@ public class SingleCommandHelpProvider i
}
return null;
}
+
+ protected Function unproxy(Function function) {
+ try {
+ if (function.getClass().getName().contains("CommandProxy")) {
+ Field contextField = function.getClass().getDeclaredField("context");
+ Field referenceField = function.getClass().getDeclaredField("reference");
+ contextField.setAccessible(true);
+ referenceField.setAccessible(true);
+ BundleContext context = (BundleContext) contextField.get(function);
+ ServiceReference reference = (ServiceReference) referenceField.get(function);
+ Object target = context.getService(reference);
+ try {
+ if (target instanceof Function) {
+ function = (Function) target;
+ }
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+ } catch (Throwable t) {
+ // nothing to do
+ }
+ return function;
+ }
+
}