diff --git a/core/pom.xml b/core/pom.xml index cd9db51e1212dee576441ac42096baaa94f761b2..c8b36ad3de095204322dcaf700e181f487e2fc62 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -338,7 +338,7 @@ THE SOFTWARE. args4j args4j - 2.0.13 + 2.0.16 org.jvnet.hudson diff --git a/core/src/main/java/hudson/cli/DeleteJobCommand.java b/core/src/main/java/hudson/cli/DeleteJobCommand.java deleted file mode 100644 index 1dfe6c03277227c92e1123b62de6734b5525ee4b..0000000000000000000000000000000000000000 --- a/core/src/main/java/hudson/cli/DeleteJobCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2004-2009, Sun Microsystems, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package hudson.cli; - -import hudson.model.TopLevelItem; -import hudson.Extension; -import org.kohsuke.args4j.Argument; - -/** - * Deletes a job. - * @author Kohsuke Kawaguchi - */ -@Extension -public class DeleteJobCommand extends CLICommand { - @Override - public String getShortDescription() { - return "Deletes a job"; - } - - @Argument - public TopLevelItem job; - - protected int run() throws Exception { - job.delete(); - return 0; - } -} - diff --git a/core/src/main/java/hudson/cli/DisableJobCommand.java b/core/src/main/java/hudson/cli/DisableJobCommand.java deleted file mode 100644 index 29bb6bb2d9efe0ce39720d47eac1a479f7e9df33..0000000000000000000000000000000000000000 --- a/core/src/main/java/hudson/cli/DisableJobCommand.java +++ /dev/null @@ -1,25 +0,0 @@ -package hudson.cli; - -import hudson.Extension; -import hudson.model.AbstractProject; -import org.kohsuke.args4j.Argument; - -/** - * Disables a job. - * - * @author Kohsuke Kawaguchi - */ -@Extension -public class DisableJobCommand extends CLICommand { - @Argument - public AbstractProject src; - - public String getShortDescription() { - return "Disables a job"; - } - - protected int run() throws Exception { - src.makeDisabled(true); - return 0; - } -} diff --git a/core/src/main/java/hudson/cli/EnableJobCommand.java b/core/src/main/java/hudson/cli/EnableJobCommand.java deleted file mode 100644 index 45986984edad07b705e9cc06f9e1c8e829711f24..0000000000000000000000000000000000000000 --- a/core/src/main/java/hudson/cli/EnableJobCommand.java +++ /dev/null @@ -1,25 +0,0 @@ -package hudson.cli; - -import hudson.Extension; -import hudson.model.AbstractProject; -import org.kohsuke.args4j.Argument; - -/** - * Enables a job. - * - * @author Kohsuke Kawaguchi - */ -@Extension -public class EnableJobCommand extends CLICommand { - @Argument - public AbstractProject src; - - public String getShortDescription() { - return "Enables a previously disabled job"; - } - - protected int run() throws Exception { - src.makeDisabled(false); - return 0; - } -} diff --git a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java index 2f303570874ef6963ab8d4ddd3d2b9b3d11434b1..1fe7516c471b55a73112d166bf8af32b7f026a7a 100644 --- a/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java +++ b/core/src/main/java/hudson/cli/declarative/CLIRegisterer.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package hudson.cli.declarative; import hudson.Extension; @@ -8,8 +31,12 @@ import hudson.cli.CloneableCLICommand; import hudson.model.Hudson; import org.jvnet.hudson.annotation_indexer.Index; import org.jvnet.localizer.ResourceBundleHolder; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.CmdLineException; import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -17,6 +44,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Locale; import static java.util.logging.Level.SEVERE; import java.util.logging.Logger; @@ -34,6 +62,18 @@ public class CLIRegisterer extends ExtensionFinder { return Collections.emptyList(); } + /** + * Finds a resolved method annotated with {@link CLIResolver}. + */ + private Method findResolver(Class type) throws IOException { + List resolvers = Util.filter(Index.list(CLIResolver.class, Hudson.getInstance().getPluginManager().uberClassLoader), Method.class); + for ( ; type!=null; type=type.getSuperclass()) + for (Method m : resolvers) + if (m.getReturnType()==type) + return m; + return null; + } + private List discover(final Hudson hudson) { LOGGER.fine("Listing up @CLIMethod"); List r = new ArrayList(); @@ -55,30 +95,50 @@ public class CLIRegisterer extends ExtensionFinder { public String getShortDescription() { // format by using the right locale - return res.format(name+".shortDescription"); + return res.format("CLI."+name+".shortDescription"); } - protected int run() throws Exception { + @Override + public int main(List args, Locale locale, InputStream stdin, PrintStream stdout, PrintStream stderr) { + CmdLineParser parser = new CmdLineParser(null); try { - m.invoke(resolve(m.getDeclaringClass())); - return 0; - } catch (InvocationTargetException e) { - Throwable t = e.getTargetException(); - if (t instanceof Exception) - throw (Exception) t; - throw e; + try { + MethodBinder resolver = null; + if (!Modifier.isStatic(m.getModifiers())) { + // decide which instance receives the method call + Method r = findResolver(m.getDeclaringClass()); + if (r==null) { + stderr.println("Unable to find the resolver method annotated with @CLIResolver for "+m.getReturnType()); + return 1; + } + resolver = new MethodBinder(r,parser); + } + + MethodBinder invoker = new MethodBinder(m, parser); + + parser.parseArgument(args); + + Object instance = resolver==null ? null : resolver.call(null); + invoker.call(instance); + return 0; + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (t instanceof Exception) + throw (Exception) t; + throw e; + } + } catch (CmdLineException e) { + stderr.println(e.getMessage()); + printUsage(stderr,parser); + return 1; + } catch (Exception e) { + e.printStackTrace(stderr); + return 1; } } - /** - * Finds an instance to invoke a CLI method on. - */ - private Object resolve(Class type) { - if (Modifier.isStatic(m.getModifiers())) - return null; - - // TODO: support resolver - return hudson; + protected int run() throws Exception { + throw new UnsupportedOperationException(); } }); } catch (ClassNotFoundException e) { diff --git a/core/src/main/java/hudson/cli/ClearQueueCommand.java b/core/src/main/java/hudson/cli/declarative/CLIResolver.java similarity index 59% rename from core/src/main/java/hudson/cli/ClearQueueCommand.java rename to core/src/main/java/hudson/cli/declarative/CLIResolver.java index 58d7cf5499aa7c71e2dc60278edb77a10863a212..7794ad6984de7b8d39bc13f568ecadc3f65eaadc 100644 --- a/core/src/main/java/hudson/cli/ClearQueueCommand.java +++ b/core/src/main/java/hudson/cli/declarative/CLIResolver.java @@ -21,24 +21,33 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package hudson.cli; +package hudson.cli.declarative; -import hudson.Extension; -import hudson.model.Hudson; +import hudson.cli.CLICommand; +import org.jvnet.hudson.annotation_indexer.Indexed; +import org.kohsuke.args4j.CmdLineException; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; /** - * Clears the job queue. + * Annotates a resolver method that binds a portion of the command line arguments and parameters + * to an instance whose {@link CLIMethod} is invoked for the final processing. + * + *

+ * The resolver method shall never return null --- it should instead indicate a failure by throwing + * {@link CmdLineException}. * * @author Kohsuke Kawaguchi + * @see CLICommand + * @since 1.321 */ -@Extension -public class ClearQueueCommand extends CLICommand { - public String getShortDescription() { - return "Clears the job queue"; - } - - protected int run() throws Exception { - Hudson.getInstance().getQueue().clear(); - return 0; - } +@Indexed +@Retention(RUNTIME) +@Target({METHOD}) +@Documented +public @interface CLIResolver { } diff --git a/core/src/main/java/hudson/cli/declarative/MethodBinder.java b/core/src/main/java/hudson/cli/declarative/MethodBinder.java new file mode 100644 index 0000000000000000000000000000000000000000..5a343acc657a7a5097206307647ecea9206f18c9 --- /dev/null +++ b/core/src/main/java/hudson/cli/declarative/MethodBinder.java @@ -0,0 +1,97 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.cli.declarative; + +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.CmdLineException; +import org.kohsuke.args4j.CmdLineParser; +import org.kohsuke.args4j.Option; +import org.kohsuke.args4j.spi.Setter; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +/** + * Binds method parameters to CLI arguments and parameters via args4j. + * Once the parser fills in the instance state, {@link #call(Object)} + * can be used to invoke a method. + * + * @author Kohsuke Kawaguchi + */ +class MethodBinder { + + private final Method method; + private final Object[] arguments; + + /** + * @param method + */ + public MethodBinder(Method method, CmdLineParser parser) { + this.method = method; + + Type[] params = method.getGenericParameterTypes(); + final Class[] paramTypes = method.getParameterTypes(); + arguments = new Object[params.length]; + + Annotation[][] pa = method.getParameterAnnotations(); + for (int i=0; i,R extends A save(); } + @CLIMethod(name="disable-job") + public void disable() throws IOException { + makeDisabled(true); + } + + @CLIMethod(name="enable-job") + public void enable() throws IOException { + makeDisabled(false); + } + @Override public BallColor getIconColor() { if(isDisabled()) diff --git a/core/src/main/java/hudson/model/Queue.java b/core/src/main/java/hudson/model/Queue.java index cd27ec7dc3e1e3cdcdf48312921126bb265e3791..c761781ae26ede0e338ea54d5f70c2aba0ad3207 100644 --- a/core/src/main/java/hudson/model/Queue.java +++ b/core/src/main/java/hudson/model/Queue.java @@ -28,6 +28,8 @@ import hudson.ExtensionList; import hudson.ExtensionPoint; import hudson.Util; import hudson.XmlFile; +import hudson.cli.declarative.CLIMethod; +import hudson.cli.declarative.CLIResolver; import hudson.remoting.AsyncFutureImpl; import hudson.model.AbstractProject; import hudson.model.Node.Mode; @@ -298,6 +300,7 @@ public class Queue extends ResourceController implements Saveable { /** * Wipes out all the items currently in the queue, as if all of them are cancelled at once. */ + @CLIMethod(name="clear-queue") public synchronized void clear() { for (WaitingItem i : waitingList) i.onCancelled(); @@ -1565,4 +1568,9 @@ public class Queue extends ResourceController implements Saveable { clear(); } } + + @CLIResolver + public static Queue getInstance() { + return Hudson.getInstance().getQueue(); + } } diff --git a/core/src/main/resources/hudson/model/Messages.properties b/core/src/main/resources/hudson/model/Messages.properties index 364bbc0d27ad9531126bbbfb6466ce61e5d0ad69..bbe9a44ec842b9522670a7a101397e63b12546d7 100644 --- a/core/src/main/resources/hudson/model/Messages.properties +++ b/core/src/main/resources/hudson/model/Messages.properties @@ -24,6 +24,7 @@ AbstractBuild.BuildingRemotely=Building remotely on {0} AbstractBuild.BuildingOnMaster=Building on master AbstractBuild.KeptBecause=kept because of {0} +AbstractItem.NoSuchJobExists=No such job ''{0}'' exists. Perhaps you meant ''{1}''? AbstractProject.NewBuildForWorkspace=Scheduling a new build to get a workspace. AbstractProject.Pronoun=Project AbstractProject.Aborted=Aborted @@ -55,6 +56,11 @@ BallColor.Pending=Pending BallColor.Success=Success BallColor.Unstable=Unstable +CLI.clear-queue.shortDescription=Clears the build queue +CLI.delete-job.shortDescription=Deletes a job +CLI.disable-job.shortDescription=Disables a job +CLI.enable-job.shortDescription=Enables a job + Computer.Caption=Slave {0} Computer.Permissions.Title=Slave Computer.ConfigurePermission.Description=This permission allows users to configure slaves. diff --git a/remoting/pom.xml b/remoting/pom.xml index 07ebf83d0d8cafec4a1d8631441c0fb3db9b3caf..84b61ecdbab6735d7fa6180aa3c8de7852d98313 100644 --- a/remoting/pom.xml +++ b/remoting/pom.xml @@ -125,7 +125,7 @@ THE SOFTWARE. args4j args4j - 2.0.13 + 2.0.16 provided