From 37dfa992eb1a6aba5e25b791703001f7516d5b63 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Sat, 13 May 2017 06:21:05 -0400 Subject: [PATCH] Offering default methods on ParameterizedJob (#2864) * Offering default methods on ParameterizedJob. * Javadoc typo. * Cleaner use of default methods in ParameterizedJob. * Need to pick up https://github.com/infradna/bridge-method-injector/pull/15 to be able to build. * Using new type bounds. * bridge-method-injector 1.17 --- .../java/hudson/model/AbstractProject.java | 80 ++--------- core/src/main/java/hudson/model/Project.java | 5 - .../main/java/hudson/triggers/Trigger.java | 2 +- .../jenkins/model/ParameterizedJobMixIn.java | 133 +++++++++++++++--- .../jenkins/model/lazy/LazyBuildMixIn.java | 7 + .../java/jenkins/triggers/SCMTriggerItem.java | 2 +- pom.xml | 2 +- 7 files changed, 131 insertions(+), 100 deletions(-) diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 7e003bfca9..032715acd9 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -138,7 +138,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST; * @see AbstractBuild */ @SuppressWarnings("rawtypes") -public abstract class AbstractProject

,R extends AbstractBuild> extends Job implements BuildableItem, LazyBuildMixIn.LazyLoadingJob, ParameterizedJobMixIn.ParameterizedJob { +public abstract class AbstractProject

,R extends AbstractBuild> extends Job implements BuildableItem, LazyBuildMixIn.LazyLoadingJob, ParameterizedJobMixIn.ParameterizedJob { /** * {@link SCM} associated with the project. @@ -287,15 +287,6 @@ public abstract class AbstractProject

,R extends A return buildMixIn; } - private ParameterizedJobMixIn getParameterizedJobMixIn() { - return new ParameterizedJobMixIn() { - @SuppressWarnings("unchecked") // untypable - @Override protected P asJob() { - return (P) AbstractProject.this; - } - }; - } - @Override public synchronized void save() throws IOException { super.save(); @@ -468,7 +459,7 @@ public abstract class AbstractProject

,R extends A */ public String getBuildNowText() { // For compatibility, still use the deprecated replacer if specified. - return AlternativeUiTextProvider.get(BUILD_NOW_TEXT, this, getParameterizedJobMixIn().getBuildNowText()); + return AlternativeUiTextProvider.get(BUILD_NOW_TEXT, this, ParameterizedJobMixIn.ParameterizedJob.super.getBuildNowText()); } /** @@ -800,39 +791,6 @@ public abstract class AbstractProject

,R extends A Jenkins.getInstance().rebuildDependencyGraphAsync(); } - /** - * @deprecated - * Use {@link #scheduleBuild(Cause)}. Since 1.283 - */ - @Deprecated - public boolean scheduleBuild() { - return getParameterizedJobMixIn().scheduleBuild(); - } - - /** - * @deprecated - * Use {@link #scheduleBuild(int, Cause)}. Since 1.283 - */ - @Deprecated - public boolean scheduleBuild(int quietPeriod) { - return getParameterizedJobMixIn().scheduleBuild(quietPeriod); - } - - /** - * Schedules a build of this project. - * - * @return - * true if the project is added to the queue. - * false if the task was rejected from the queue (such as when the system is being shut down.) - */ - public boolean scheduleBuild(Cause c) { - return getParameterizedJobMixIn().scheduleBuild(c); - } - - public boolean scheduleBuild(int quietPeriod, Cause c) { - return getParameterizedJobMixIn().scheduleBuild(quietPeriod, c); - } - /** * Schedules a build. * @@ -869,14 +827,13 @@ public abstract class AbstractProject

,R extends A * For the convenience of the caller, this collection can contain null, and those will be silently ignored. * @since 1.383 */ - @SuppressWarnings("unchecked") @WithBridgeMethods(Future.class) public QueueTaskFuture scheduleBuild2(int quietPeriod, Cause c, Collection actions) { List queueActions = new ArrayList(actions); if (c != null) { queueActions.add(new CauseAction(c)); } - return getParameterizedJobMixIn().scheduleBuild2(quietPeriod, queueActions.toArray(new Action[queueActions.size()])); + return scheduleBuild2(quietPeriod, queueActions.toArray(new Action[queueActions.size()])); } /** @@ -902,6 +859,11 @@ public abstract class AbstractProject

,R extends A return scheduleBuild2(quietPeriod, c, new Action[0]); } + @Override + public QueueTaskFuture scheduleBuild2(int quietPeriod, Action... actions) { + return ParameterizedJobMixIn.ParameterizedJob.super.scheduleBuild2(quietPeriod, actions); + } + /** * Schedules a polling of this project. */ @@ -1741,21 +1703,11 @@ public abstract class AbstractProject

,R extends A return buildMixIn.createHistoryWidget(); } - public boolean isParameterized() { - return getParameterizedJobMixIn().isParameterized(); - } - // // // actions // // - /** - * Schedules a new build command. - */ - public void doBuild( StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay ) throws IOException, ServletException { - getParameterizedJobMixIn().doBuild(req, rsp, delay); - } /** @deprecated use {@link #doBuild(StaplerRequest, StaplerResponse, TimeDuration)} */ @Deprecated @@ -1784,14 +1736,6 @@ public abstract class AbstractProject

,R extends A } } - /** - * Supports build trigger with parameters via an HTTP GET or POST. - * Currently only String parameters are supported. - */ - public void doBuildWithParameters(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { - getParameterizedJobMixIn().doBuildWithParameters(req, rsp, delay); - } - /** @deprecated use {@link #doBuildWithParameters(StaplerRequest, StaplerResponse, TimeDuration)} */ @Deprecated public void doBuildWithParameters(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { @@ -1807,14 +1751,6 @@ public abstract class AbstractProject

,R extends A rsp.sendRedirect("."); } - /** - * Cancels a scheduled build. - */ - @RequirePOST - public void doCancelQueue( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { - getParameterizedJobMixIn().doCancelQueue(req, rsp); - } - @Override protected void submit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { super.submit(req,rsp); diff --git a/core/src/main/java/hudson/model/Project.java b/core/src/main/java/hudson/model/Project.java index 1b5fe37254..b969b9942c 100644 --- a/core/src/main/java/hudson/model/Project.java +++ b/core/src/main/java/hudson/model/Project.java @@ -26,7 +26,6 @@ package hudson.model; import hudson.Util; import hudson.model.Descriptor.FormException; -import hudson.model.queue.QueueTaskFuture; import hudson.scm.SCM; import hudson.tasks.BuildStep; import hudson.tasks.BuildWrapper; @@ -109,10 +108,6 @@ public abstract class Project

,B extends Build> return this; } - @Override public QueueTaskFuture scheduleBuild2(int quietPeriod, Action... actions) { - return scheduleBuild2(quietPeriod, null, actions); - } - @Override public SCMTrigger getSCMTrigger() { return getTrigger(SCMTrigger.class); } diff --git a/core/src/main/java/hudson/triggers/Trigger.java b/core/src/main/java/hudson/triggers/Trigger.java index e578de8898..b37fd7ce05 100644 --- a/core/src/main/java/hudson/triggers/Trigger.java +++ b/core/src/main/java/hudson/triggers/Trigger.java @@ -266,7 +266,7 @@ public abstract class Trigger implements Describable> } // Process all triggers, except SCMTriggers when synchronousPolling is set - for (ParameterizedJobMixIn.ParameterizedJob p : inst.allItems(ParameterizedJobMixIn.ParameterizedJob.class)) { + for (ParameterizedJobMixIn.ParameterizedJob p : inst.allItems(ParameterizedJobMixIn.ParameterizedJob.class)) { for (Trigger t : p.getTriggers().values()) { if (!(t instanceof SCMTrigger && scmd.synchronousPolling)) { if (t !=null && t.spec != null && t.tabs != null) { diff --git a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java index c148d1fc98..75f195367a 100644 --- a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java +++ b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java @@ -53,6 +53,7 @@ import javax.annotation.CheckForNull; import javax.servlet.ServletException; import static javax.servlet.http.HttpServletResponse.SC_CREATED; import static javax.servlet.http.HttpServletResponse.SC_CONFLICT; +import jenkins.triggers.SCMTriggerItem; import jenkins.util.TimeDuration; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -65,10 +66,11 @@ import org.kohsuke.stapler.interceptor.RequirePOST; /** * Allows a {@link Job} to make use of {@link ParametersDefinitionProperty} and be scheduled in various ways. * Stateless so there is no need to keep an instance of it in a field. + * Besides implementing {@link ParameterizedJob}, you should override {@link Job#makeSearchIndex} to call {@link #extendSearchIndex}. * @since 1.556 */ @SuppressWarnings("unchecked") // AbstractItem.getParent does not correctly override; scheduleBuild2 inherently untypable -public abstract class ParameterizedJobMixIn & ParameterizedJobMixIn.ParameterizedJob & Queue.Task, RunT extends Run & Queue.Executable> { +public abstract class ParameterizedJobMixIn & ParameterizedJobMixIn.ParameterizedJob & Queue.Task, RunT extends Run & Queue.Executable> { protected abstract JobT asJob(); @@ -95,11 +97,7 @@ public abstract class ParameterizedJobMixIn & Param } /** - * Provides a standard implementation of an optional method of the same name in a {@link Job} type to schedule a build with the ability to wait for its result. - * That job method is often used during functional tests ({@code JenkinsRule.assertBuildStatusSuccess}). - * @param quietPeriod seconds to wait before starting (normally 0) - * @param actions various actions to associate with the scheduling, such as {@link ParametersAction} or {@link CauseAction} - * @return a handle by which you may wait for the build to complete (or just start); or null if the build was not actually scheduled for some reason + * Standard implementation of {@link ParameterizedJob#scheduleBuild2}. */ public final @CheckForNull QueueTaskFuture scheduleBuild2(int quietPeriod, Action... actions) { Queue.Item i = scheduleBuild2(quietPeriod, Arrays.asList(actions)); @@ -161,15 +159,14 @@ public abstract class ParameterizedJobMixIn & Param } /** - * A job should define a method of the same signature for use from {@link BuildButtonColumn}. + * Standard implementation of {@link ParameterizedJob#isParameterized}. */ public final boolean isParameterized() { return asJob().getProperty(ParametersDefinitionProperty.class) != null; } /** - * Schedules a new build command. - * Create a method on your job with the same signature and delegate to this. + * Standard implementation of {@link ParameterizedJob#doBuild}. */ @SuppressWarnings("deprecation") public final void doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { @@ -206,9 +203,7 @@ public abstract class ParameterizedJobMixIn & Param } /** - * Supports build trigger with parameters via an HTTP GET or POST. - * Currently only String parameters are supported. - * Create a method on your job with the same signature and delegate to this. + * Standard implementation of {@link ParameterizedJob#doBuildWithParameters}. */ @SuppressWarnings("deprecation") public final void doBuildWithParameters(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { @@ -226,8 +221,7 @@ public abstract class ParameterizedJobMixIn & Param } /** - * Cancels a scheduled build. - * Create a method on your job marked {@link RequirePOST} but with the same signature and delegate to this. + * Standard implementation of {@link ParameterizedJob#doCancelQueue}. */ @RequirePOST public final void doCancelQueue( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { @@ -275,7 +269,6 @@ public abstract class ParameterizedJobMixIn & Param /** * Suggested implementation of {@link ParameterizedJob#getBuildNowText}. - * Uses {@link #BUILD_NOW_TEXT}. */ public final String getBuildNowText() { return isParameterized() ? AlternativeUiTextProvider.get(BUILD_NOW_TEXT, asJob(), Messages.ParameterizedJobMixIn_build_with_parameters()) @@ -294,7 +287,7 @@ public abstract class ParameterizedJobMixIn & Param if (!(job instanceof ParameterizedJob)) { return null; } - for (Trigger t : ((ParameterizedJob) job).getTriggers().values()) { + for (Trigger t : ((ParameterizedJob) job).getTriggers().values()) { if (clazz.isInstance(t)) { return clazz.cast(t); } @@ -303,16 +296,42 @@ public abstract class ParameterizedJobMixIn & Param } /** - * Marker for job using this mixin. + * Marker for job using this mixin, and default implementations of many methods. */ - public interface ParameterizedJob extends hudson.model.Queue.Task, hudson.model.Item { + public interface ParameterizedJob & ParameterizedJobMixIn.ParameterizedJob & Queue.Task, RunT extends Run & Queue.Executable> extends BuildableItem { + + /** + * Creates a helper object. + * (Would have been done entirely as an interface with default methods had this been designed for Java 8.) + */ + default ParameterizedJobMixIn getParameterizedJobMixIn() { + return new ParameterizedJobMixIn() { + @SuppressWarnings("unchecked") // untypable + @Override protected JobT asJob() { + return (JobT) ParameterizedJob.this; + } + }; + } @SuppressWarnings("deprecation") @CheckForNull hudson.model.BuildAuthorizationToken getAuthToken(); - int getQuietPeriod(); + /** + * Quiet period for the job. + * @return by default, {@link Jenkins#getQuietPeriod} + */ + default int getQuietPeriod() { + return Jenkins.getInstance().getQuietPeriod(); + } - String getBuildNowText(); + /** + * Text to display for a build button. + * Uses {@link #BUILD_NOW_TEXT}. + * @see ParameterizedJobMixIn#getBuildNowText + */ + default String getBuildNowText() { + return getParameterizedJobMixIn().getBuildNowText(); + } /** * Gets currently configured triggers. @@ -322,6 +341,80 @@ public abstract class ParameterizedJobMixIn & Param */ Map> getTriggers(); + /** + * @deprecated use {@link #scheduleBuild(Cause)} + */ + @Deprecated + @Override + default boolean scheduleBuild() { + return getParameterizedJobMixIn().scheduleBuild(); + } + + @Override + default boolean scheduleBuild(Cause c) { + return getParameterizedJobMixIn().scheduleBuild(c); + } + + /** + * @deprecated use {@link #scheduleBuild(int, Cause)} + */ + @Deprecated + @Override + default boolean scheduleBuild(int quietPeriod) { + return getParameterizedJobMixIn().scheduleBuild(quietPeriod); + } + + @Override + default boolean scheduleBuild(int quietPeriod, Cause c) { + return getParameterizedJobMixIn().scheduleBuild(quietPeriod, c); + } + + /** + * Provides a standard implementation of {@link SCMTriggerItem#scheduleBuild2} to schedule a build with the ability to wait for its result. + * That job method is often used during functional tests ({@code JenkinsRule.assertBuildStatusSuccess}). + * @param quietPeriod seconds to wait before starting (normally 0) + * @param actions various actions to associate with the scheduling, such as {@link ParametersAction} or {@link CauseAction} + * @return a handle by which you may wait for the build to complete (or just start); or null if the build was not actually scheduled for some reason + */ + @CheckForNull + default QueueTaskFuture scheduleBuild2(int quietPeriod, Action... actions) { + return getParameterizedJobMixIn().scheduleBuild2(quietPeriod, actions); + } + + /** + * Schedules a new build command. + * @see ParameterizedJobMixIn#doBuild + */ + default void doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { + getParameterizedJobMixIn().doBuild(req, rsp, delay); + } + + /** + * Supports build trigger with parameters via an HTTP GET or POST. + * Currently only String parameters are supported. + * @see ParameterizedJobMixIn#doBuildWithParameters + */ + default void doBuildWithParameters(StaplerRequest req, StaplerResponse rsp, @QueryParameter TimeDuration delay) throws IOException, ServletException { + getParameterizedJobMixIn().doBuildWithParameters(req, rsp, delay); + } + + /** + * Cancels a scheduled build. + * @see ParameterizedJobMixIn#doCancelQueue + */ + @RequirePOST + default void doCancelQueue(StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException { + getParameterizedJobMixIn().doCancelQueue(req, rsp); + } + + /** + * For use from {@link BuildButtonColumn}. + * @see ParameterizedJobMixIn#isParameterized + */ + default boolean isParameterized() { + return getParameterizedJobMixIn().isParameterized(); + } + } } diff --git a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java index bd727d5d58..547735f524 100644 --- a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java +++ b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java @@ -271,10 +271,17 @@ public abstract class LazyBuildMixIn & Queue.Task & */ public interface LazyLoadingJob & Queue.Task & LazyBuildMixIn.LazyLoadingJob, RunT extends Run & LazyLoadingRun> { LazyBuildMixIn getLazyBuildMixIn(); + // not offering default implementation for _getRuns(), removeRun(R), getBuild(String), getBuildByNumber(int), getFirstBuild(), getLastBuild(), getNearestBuild(int), getNearestOldBuild(int), or createHistoryWidget() since they are defined in Job + // nor for createExecutable() since that typically calls isDisabled() first } + /** + * Marker for a {@link Run} which uses this mixin. + */ public interface LazyLoadingRun & Queue.Task & LazyBuildMixIn.LazyLoadingJob, RunT extends Run & LazyLoadingRun> { RunMixIn getRunMixIn(); + // not offering default implementations for createReference() or dropLinks() since they are protected + // nor for getPreviousBuild() or getNextBuild() since they are defined in Run } /** diff --git a/core/src/main/java/jenkins/triggers/SCMTriggerItem.java b/core/src/main/java/jenkins/triggers/SCMTriggerItem.java index 7a1cb1db27..a06e6fb7f0 100644 --- a/core/src/main/java/jenkins/triggers/SCMTriggerItem.java +++ b/core/src/main/java/jenkins/triggers/SCMTriggerItem.java @@ -57,7 +57,7 @@ public interface SCMTriggerItem { /** @see jenkins.model.ParameterizedJobMixIn.ParameterizedJob#getQuietPeriod */ int getQuietPeriod(); - /** @see ParameterizedJobMixIn#scheduleBuild2 */ + /** @see jenkins.model.ParameterizedJobMixIn.ParameterizedJob#scheduleBuild2 */ @CheckForNull QueueTaskFuture scheduleBuild2(int quietPeriod, Action... actions); /** diff --git a/pom.xml b/pom.xml index aed5f17f68..b355b659ff 100644 --- a/pom.xml +++ b/pom.xml @@ -467,7 +467,7 @@ THE SOFTWARE. com.infradna.tool bridge-method-injector - 1.15 + 1.17 org.codehaus.mojo -- GitLab