/hudson-core/src/main/java/hudson/cli/declarative/MethodBinder.java

http://github.com/hudson/hudson · Java · 148 lines · 88 code · 22 blank · 38 comment · 6 complexity · b149d5c3183c29ebe0570d2ede1fcbc1 MD5 · raw file

  1. /*
  2. * The MIT License
  3. *
  4. * Copyright (c) 2004-2009, Sun Microsystems, Inc.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. package hudson.cli.declarative;
  25. import hudson.util.ReflectionUtils;
  26. import hudson.util.ReflectionUtils.Parameter;
  27. import org.kohsuke.args4j.Argument;
  28. import org.kohsuke.args4j.CmdLineException;
  29. import org.kohsuke.args4j.CmdLineParser;
  30. import org.kohsuke.args4j.Option;
  31. import org.kohsuke.args4j.spi.Setter;
  32. import org.kohsuke.args4j.spi.OptionHandler;
  33. import java.lang.annotation.Annotation;
  34. import java.lang.reflect.InvocationTargetException;
  35. import java.lang.reflect.Method;
  36. import java.util.List;
  37. /**
  38. * Binds method parameters to CLI arguments and parameters via args4j.
  39. * Once the parser fills in the instance state, {@link #call(Object)}
  40. * can be used to invoke a method.
  41. *
  42. * @author Kohsuke Kawaguchi
  43. */
  44. class MethodBinder {
  45. private final Method method;
  46. private final Object[] arguments;
  47. /**
  48. * @param method
  49. */
  50. public MethodBinder(Method method, CmdLineParser parser) {
  51. this.method = method;
  52. List<Parameter> params = ReflectionUtils.getParameters(method);
  53. arguments = new Object[params.size()];
  54. // to work in cooperation with earlier arguments, add bias to all the ones that this one defines.
  55. final int bias = parser.getArguments().size();
  56. for (final Parameter p : params) {
  57. final int index = p.index();
  58. // TODO: collection and map support
  59. Setter setter = new Setter() {
  60. public void addValue(Object value) throws CmdLineException {
  61. arguments[index] = value;
  62. }
  63. public Class getType() {
  64. return p.type();
  65. }
  66. public boolean isMultiValued() {
  67. return false;
  68. }
  69. };
  70. Option option = p.annotation(Option.class);
  71. if (option!=null) {
  72. parser.addOption(setter,option);
  73. }
  74. Argument arg = p.annotation(Argument.class);
  75. if (arg!=null) {
  76. if (bias>0) arg = new ArgumentImpl(arg,bias);
  77. parser.addArgument(setter,arg);
  78. }
  79. if (p.type().isPrimitive())
  80. arguments[index] = ReflectionUtils.getVmDefaultValueForPrimitiveType(p.type());
  81. }
  82. }
  83. public Object call(Object instance) throws Exception {
  84. try {
  85. return method.invoke(instance,arguments);
  86. } catch (InvocationTargetException e) {
  87. Throwable t = e.getTargetException();
  88. if (t instanceof Exception)
  89. throw (Exception) t;
  90. throw e;
  91. }
  92. }
  93. /**
  94. * {@link Argument} implementation that adds a bias to {@link #index()}.
  95. */
  96. @SuppressWarnings({"ClassExplicitlyAnnotation"})
  97. private static final class ArgumentImpl implements Argument {
  98. private final Argument base;
  99. private final int bias;
  100. private ArgumentImpl(Argument base, int bias) {
  101. this.base = base;
  102. this.bias = bias;
  103. }
  104. public String usage() {
  105. return base.usage();
  106. }
  107. public String metaVar() {
  108. return base.metaVar();
  109. }
  110. public boolean required() {
  111. return base.required();
  112. }
  113. public Class<? extends OptionHandler> handler() {
  114. return base.handler();
  115. }
  116. public int index() {
  117. return base.index()+bias;
  118. }
  119. public boolean multiValued() {
  120. return base.multiValued();
  121. }
  122. public Class<? extends Annotation> annotationType() {
  123. return base.annotationType();
  124. }
  125. }
  126. }