summaryrefslogtreecommitdiffstats
path: root/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java')
-rw-r--r--gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java135
1 files changed, 130 insertions, 5 deletions
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
index 11f380d2de..f2d07eda66 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -44,11 +44,15 @@ import java.io.StringWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
+import java.util.Set;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.IllegalAnnotationError;
@@ -58,8 +62,10 @@ import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.BooleanOptionHandler;
import org.kohsuke.args4j.spi.EnumOptionHandler;
import org.kohsuke.args4j.spi.FieldSetter;
+import org.kohsuke.args4j.spi.MethodSetter;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.spi.Setters;
/**
* Extended command line parser which handles --foo=value arguments.
@@ -191,7 +197,7 @@ public class CmdLineParser {
return parser.help.value;
}
- public void parseArgument(final String... args) throws CmdLineException {
+ public void parseArgument(String... args) throws CmdLineException {
List<String> tmp = Lists.newArrayListWithCapacity(args.length);
for (int argi = 0; argi < args.length; argi++) {
final String str = args[argi];
@@ -228,7 +234,7 @@ public class CmdLineParser {
public void parseOptionMap(ListMultimap<String, String> params) throws CmdLineException {
List<String> tmp = Lists.newArrayListWithCapacity(2 * params.size());
- for (final String key : params.keySet()) {
+ for (String key : params.keySet()) {
String name = makeOption(key);
if (isBoolean(name)) {
@@ -253,6 +259,10 @@ public class CmdLineParser {
return findHandler(makeOption(name)) instanceof BooleanOptionHandler;
}
+ public void parseWithPrefix(String prefix, Object bean) {
+ parser.parseWithPrefix(prefix, bean);
+ }
+
private String makeOption(String name) {
if (!name.startsWith("-")) {
if (name.length() == 1) {
@@ -313,20 +323,135 @@ public class CmdLineParser {
throw new CmdLineException(parser, String.format("invalid boolean \"%s=%s\"", name, value));
}
+ private static class PrefixedOption implements Option {
+ String prefix;
+ Option o;
+
+ PrefixedOption(String prefix, Option o) {
+ this.prefix = prefix;
+ this.o = o;
+ }
+
+ @Override
+ public String name() {
+ return getPrefixedName(prefix, o.name());
+ }
+
+ @Override
+ public String[] aliases() {
+ String[] prefixedAliases = new String[o.aliases().length];
+ for (int i = 0; i < prefixedAliases.length; i++) {
+ prefixedAliases[i] = getPrefixedName(prefix, o.aliases()[i]);
+ }
+ return prefixedAliases;
+ }
+
+ @Override
+ public String usage() {
+ return o.usage();
+ }
+
+ @Override
+ public String metaVar() {
+ return o.metaVar();
+ }
+
+ @Override
+ public boolean required() {
+ return o.required();
+ }
+
+ @Override
+ public boolean hidden() {
+ return o.hidden();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Class<? extends OptionHandler> handler() {
+ return o.handler();
+ }
+
+ @Override
+ public String[] depends() {
+ return o.depends();
+ }
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return o.annotationType();
+ }
+
+ private static String getPrefixedName(String prefix, String name) {
+ return prefix + name;
+ }
+ }
+
private class MyParser extends org.kohsuke.args4j.CmdLineParser {
@SuppressWarnings("rawtypes")
private List<OptionHandler> optionsList;
private HelpOption help;
- MyParser(final Object bean) {
+ MyParser(Object bean) {
super(bean);
+ parseAdditionalOptions(bean, new HashSet<>());
ensureOptionsInitialized();
}
+ // NOTE: Argument annotations on bean are ignored.
+ public void parseWithPrefix(String prefix, Object bean) {
+ parseWithPrefix(prefix, bean, new HashSet<>());
+ }
+
+ private void parseWithPrefix(String prefix, Object bean, Set<Object> parsedBeans) {
+ if (!parsedBeans.add(bean)) {
+ return;
+ }
+ // recursively process all the methods/fields.
+ for (Class<?> c = bean.getClass(); c != null; c = c.getSuperclass()) {
+ for (Method m : c.getDeclaredMethods()) {
+ Option o = m.getAnnotation(Option.class);
+ if (o != null) {
+ addOption(new MethodSetter(this, bean, m), new PrefixedOption(prefix, o));
+ }
+ }
+ for (Field f : c.getDeclaredFields()) {
+ Option o = f.getAnnotation(Option.class);
+ if (o != null) {
+ addOption(Setters.create(f, bean), new PrefixedOption(prefix, o));
+ }
+ if (f.isAnnotationPresent(Options.class)) {
+ try {
+ parseWithPrefix(
+ prefix + f.getAnnotation(Options.class).prefix(), f.get(bean), parsedBeans);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAnnotationError(e);
+ }
+ }
+ }
+ }
+ }
+
+ private void parseAdditionalOptions(Object bean, Set<Object> parsedBeans) {
+ for (Class<?> c = bean.getClass(); c != null; c = c.getSuperclass()) {
+ for (Field f : c.getDeclaredFields()) {
+ if (f.isAnnotationPresent(Options.class)) {
+ Object additionalBean = null;
+ try {
+ additionalBean = f.get(bean);
+ } catch (IllegalAccessException e) {
+ throw new IllegalAnnotationError(e);
+ }
+ parseWithPrefix(f.getAnnotation(Options.class).prefix(), additionalBean, parsedBeans);
+ }
+ }
+ }
+ }
+
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
- protected OptionHandler createOptionHandler(final OptionDef option, final Setter setter) {
+ protected OptionHandler createOptionHandler(OptionDef option, Setter setter) {
if (isHandlerSpecified(option) || isEnum(setter) || isPrimitive(setter)) {
return add(super.createOptionHandler(option, setter));
}
@@ -353,7 +478,7 @@ public class CmdLineParser {
}
}
- private boolean isHandlerSpecified(final OptionDef option) {
+ private boolean isHandlerSpecified(OptionDef option) {
return option.handler() != OptionHandler.class;
}