PageRenderTime 26ms CodeModel.GetById 18ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/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 */
 24package hudson.cli.declarative;
 25
 26import hudson.util.ReflectionUtils;
 27import hudson.util.ReflectionUtils.Parameter;
 28import org.kohsuke.args4j.Argument;
 29import org.kohsuke.args4j.CmdLineException;
 30import org.kohsuke.args4j.CmdLineParser;
 31import org.kohsuke.args4j.Option;
 32import org.kohsuke.args4j.spi.Setter;
 33import org.kohsuke.args4j.spi.OptionHandler;
 34
 35import java.lang.annotation.Annotation;
 36import java.lang.reflect.InvocationTargetException;
 37import java.lang.reflect.Method;
 38import java.util.List;
 39
 40/**
 41 * Binds method parameters to CLI arguments and parameters via args4j.
 42 * Once the parser fills in the instance state, {@link #call(Object)}
 43 * can be used to invoke a method.
 44 *
 45 * @author Kohsuke Kawaguchi
 46 */
 47class MethodBinder {
 48
 49    private final Method method;
 50    private final Object[] arguments;
 51
 52    /**
 53     * @param method
 54     */
 55    public MethodBinder(Method method, CmdLineParser parser) {
 56        this.method = method;
 57
 58        List<Parameter> params = ReflectionUtils.getParameters(method);
 59        arguments = new Object[params.size()];
 60
 61        // to work in cooperation with earlier arguments, add bias to all the ones that this one defines.
 62        final int bias = parser.getArguments().size();
 63
 64        for (final Parameter p : params) {
 65            final int index = p.index();
 66
 67            // TODO: collection and map support
 68            Setter setter = new Setter() {
 69                public void addValue(Object value) throws CmdLineException {
 70                    arguments[index] = value;
 71                }
 72
 73                public Class getType() {
 74                    return p.type();
 75                }
 76
 77                public boolean isMultiValued() {
 78                    return false;
 79                }
 80            };
 81            Option option = p.annotation(Option.class);
 82            if (option!=null) {
 83                parser.addOption(setter,option);
 84            }
 85            Argument arg = p.annotation(Argument.class);
 86            if (arg!=null) {
 87                if (bias>0) arg = new ArgumentImpl(arg,bias);
 88                parser.addArgument(setter,arg);
 89            }
 90
 91            if (p.type().isPrimitive())
 92                arguments[index] = ReflectionUtils.getVmDefaultValueForPrimitiveType(p.type());
 93        }
 94    }
 95
 96    public Object call(Object instance) throws Exception {
 97        try {
 98            return method.invoke(instance,arguments);
 99        } catch (InvocationTargetException e) {
100            Throwable t = e.getTargetException();
101            if (t instanceof Exception)
102                throw (Exception) t;
103            throw e;
104        }
105    }
106
107    /**
108     * {@link Argument} implementation that adds a bias to {@link #index()}.
109     */
110    @SuppressWarnings({"ClassExplicitlyAnnotation"})
111    private static final class ArgumentImpl implements Argument {
112        private final Argument base;
113        private final int bias;
114
115        private ArgumentImpl(Argument base, int bias) {
116            this.base = base;
117            this.bias = bias;
118        }
119
120        public String usage() {
121            return base.usage();
122        }
123
124        public String metaVar() {
125            return base.metaVar();
126        }
127
128        public boolean required() {
129            return base.required();
130        }
131
132        public Class<? extends OptionHandler> handler() {
133            return base.handler();
134        }
135
136        public int index() {
137            return base.index()+bias;
138        }
139
140        public boolean multiValued() {
141            return base.multiValued();
142        }
143
144        public Class<? extends Annotation> annotationType() {
145            return base.annotationType();
146        }
147    }
148}