File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\core\src\main\java\hudson\cli\declarative\CLIRegisterer.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2010, 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
26 import hudson.Extension;
27 import hudson.ExtensionComponent;
28 import hudson.ExtensionFinder;
29 import hudson.Util;
30 import hudson.cli.CLICommand;
31 import hudson.cli.CloneableCLICommand;
32 import hudson.model.Hudson;
33 import jenkins.ExtensionComponentSet;
34 import jenkins.ExtensionRefreshException;
35 import jenkins.model.Jenkins;
36 import hudson.remoting.Channel;
37 import hudson.security.CliAuthenticator;
38 import org.acegisecurity.Authentication;
39 import org.acegisecurity.context.SecurityContext;
40 import org.acegisecurity.context.SecurityContextHolder;
41 import org.jvnet.hudson.annotation_indexer.Index;
42 import org.jvnet.localizer.ResourceBundleHolder;
43 import org.kohsuke.args4j.ClassParser;
44 import org.kohsuke.args4j.CmdLineParser;
45 import org.kohsuke.args4j.CmdLineException;
46
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.PrintStream;
50 import java.lang.reflect.InvocationTargetException;
51 import java.lang.reflect.Method;
52 import java.lang.reflect.Modifier;
53 import java.util.ArrayList;
54 import java.util.Collection;
55 import java.util.Collections;
56 import java.util.List;
57 import java.util.Locale;
58 import java.util.Stack;
59 import static java.util.logging.Level.SEVERE;
60 import java.util.logging.Logger;
61
62 /**
63 * Discover {@link CLIMethod}s and register them as {@link CLICommand} implementations.
64 *
65 * @author Kohsuke Kawaguchi
66 */
67 @Extension
68 public class CLIRegisterer extends ExtensionFinder {
69 @Override
70 public ExtensionComponentSet refresh() throws ExtensionRefreshException {
71 // TODO: this is not complex. just bit tedious.
72 return ExtensionComponentSet.EMPTY;
73 }
74
75 public <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson jenkins) {
76 if (type==CLICommand.class)
77 return (List)discover(jenkins);
78 else
79 return Collections.emptyList();
80 }
81
82 /**
83 * Finds a resolved method annotated with {@link CLIResolver}.
84 */
85 private Method findResolver(Class type) throws IOException {
86 List<Method> resolvers = Util.filter(Index.list(CLIResolver.class, Jenkins.getInstance().getPluginManager().uberClassLoader), Method.class);
87 for ( ; type!=null; type=type.getSuperclass())
88 for (Method m : resolvers)
89 if (m.getReturnType()==type)
90 return m;
91 return null;
92 }
93
94 private List<ExtensionComponent<CLICommand>> discover(final Jenkins hudson) {
95 LOGGER.fine("Listing up @CLIMethod");
96 List<ExtensionComponent<CLICommand>> r = new ArrayList<ExtensionComponent<CLICommand>>();
97
98 try {
99 for ( final Method m : Util.filter(Index.list(CLIMethod.class, hudson.getPluginManager().uberClassLoader),Method.class)) {
100 try {
101 // command name
102 final String name = m.getAnnotation(CLIMethod.class).name();
103
104 final ResourceBundleHolder res = loadMessageBundle(m);
105 res.format("CLI."+name+".shortDescription"); // make sure we have the resource, to fail early
106
107 r.add(new ExtensionComponent<CLICommand>(new CloneableCLICommand() {
108 @Override
109 public String getName() {
110 return name;
111 }
112
113 public String getShortDescription() {
114 // format by using the right locale
115 return res.format("CLI."+name+".shortDescription");
116 }
117
118 @Override
119 public int main(List<String> args, Locale locale, InputStream stdin, PrintStream stdout, PrintStream stderr) {
120 this.stdout = stdout;
121 this.stderr = stderr;
122 this.locale = locale;
123
124 registerOptionHandlers();
125 CmdLineParser parser = new CmdLineParser(null);
126 try {
127 SecurityContext sc = SecurityContextHolder.getContext();
128 Authentication old = sc.getAuthentication();
129 try {
130 // build up the call sequence
131 Stack<Method> chains = new Stack<Method>();
132 Method method = m;
133 while (true) {
134 chains.push(method);
135 if (Modifier.isStatic(method.getModifiers()))
136 break; // the chain is complete.
137
138 // the method in question is an instance method, so we need to resolve the instance by using another resolver
139 Class<?> type = method.getDeclaringClass();
140 method = findResolver(type);
141 if (method==null) {
142 stderr.println("Unable to find the resolver method annotated with @CLIResolver for "+type);
143 return 1;
144 }
145 }
146
147 List<MethodBinder> binders = new ArrayList<MethodBinder>();
148
149 while (!chains.isEmpty())
150 binders.add(new MethodBinder(chains.pop(),this,parser));
151
152 // authentication
153 CliAuthenticator authenticator = Jenkins.getInstance().getSecurityRealm().createCliAuthenticator(this);
154 new ClassParser().parse(authenticator,parser);
155
156 // fill up all the binders
157 parser.parseArgument(args);
158
159 Authentication auth = authenticator.authenticate();
160 if (auth== Jenkins.ANONYMOUS)
161 auth = loadStoredAuthentication();
162 sc.setAuthentication(auth); // run the CLI with the right credential
163 hudson.checkPermission(Jenkins.READ);
164
165 // resolve them
166 Object instance = null;
167 for (MethodBinder binder : binders)
168 instance = binder.call(instance);
169
170 if (instance instanceof Integer)
171 return (Integer) instance;
172 else
173 return 0;
174 } catch (InvocationTargetException e) {
175 Throwable t = e.getTargetException();
176 if (t instanceof Exception)
177 throw (Exception) t;
178 throw e;
179 } finally {
180 sc.setAuthentication(old); // restore
181 }
182 } catch (CmdLineException e) {
183 stderr.println(e.getMessage());
184 printUsage(stderr,parser);
185 return 1;
186 } catch (Exception e) {
187 e.printStackTrace(stderr);
188 return 1;
189 }
190 }
191
192 protected int run() throws Exception {
193 throw new UnsupportedOperationException();
194 }
195 }));
196 } catch (ClassNotFoundException e) {
197 LOGGER.log(SEVERE,"Failed to process @CLIMethod: "+m,e);
198 }
199 }
200 } catch (IOException e) {
201 LOGGER.log(SEVERE, "Failed to discvoer @CLIMethod",e);
202 }
203
204 return r;
205 }
206
207 /**
208 * Locates the {@link ResourceBundleHolder} for this CLI method.
209 */
210 private ResourceBundleHolder loadMessageBundle(Method m) throws ClassNotFoundException {
211 Class c = m.getDeclaringClass();
212 Class<?> msg = c.getClassLoader().loadClass(c.getName().substring(0, c.getName().lastIndexOf(".")) + ".Messages");
213 return ResourceBundleHolder.get(msg);
214 }
215
216 private static final Logger LOGGER = Logger.getLogger(CLIRegisterer.class.getName());
217 }
218