From 96e7537e66f73f276d4d001fbc56006222a3a7b0 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Thu, 3 Oct 2024 09:18:59 -0700 Subject: [PATCH] Format repository with Spotless (#61) --- pom.xml | 334 ++++++------ .../hudson/plugins/notification/Endpoint.java | 55 +- .../hudson/plugins/notification/Format.java | 11 +- .../HudsonNotificationProperty.java | 82 ++- .../HudsonNotificationPropertyDescriptor.java | 52 +- .../plugins/notification/JobListener.java | 8 +- .../plugins/notification/NotifyStep.java | 200 ++++---- .../hudson/plugins/notification/Phase.java | 282 ++++++----- .../hudson/plugins/notification/Protocol.java | 108 ++-- .../hudson/plugins/notification/UrlInfo.java | 8 +- .../hudson/plugins/notification/Utils.java | 46 +- .../notification/model/BuildState.java | 117 ++--- .../plugins/notification/model/JobState.java | 120 ++--- .../plugins/notification/model/ScmState.java | 22 +- .../plugins/notification/model/TestState.java | 4 +- .../plugins/notification/PhaseTest.java | 479 ++++++++++-------- .../plugins/notification/ProtocolTest.java | 332 ++++++------ .../notification/test/HostnamePortTest.java | 4 +- 18 files changed, 1165 insertions(+), 1099 deletions(-) diff --git a/pom.xml b/pom.xml index 4739be3..02acc28 100644 --- a/pom.xml +++ b/pom.xml @@ -1,181 +1,177 @@ + 4.0.0 + + org.jenkins-ci.plugins + plugin + 4.88 + + - 4.0.0 + com.tikalk.hudson.plugins + notification + ${revision}${changelist} + hpi + Jenkins Notification plugin + Sends notifications about jobs phases and status + https://github.com/jenkinsci/${project.artifactId}-plugin - - org.jenkins-ci.plugins - plugin - 4.88 - - + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + - com.tikalk.hudson.plugins - notification - ${revision}${changelist} - hpi - Jenkins Notification plugin - Sends notifications about jobs phases and status - https://github.com/jenkinsci/${project.artifactId}-plugin + + + markb + Mark Berner + markb@tikalk.com + Tikal Knowledge + http://tikalk.com + + + hagzag + Haggai Philip Zagury + hagzag@tikalk.com + Tikal Knowledge + http://tikalk.com + + + evgenyg + Evgeny Goldin + evgenyg@gmail.com + AKQA + http://akqa.com + + + cohencil + Chen Cohen + chenc@tikalk.com + http://tikalk.com + + - - 1.19 - -SNAPSHOT - 2.472 - jenkinsci/${project.artifactId}-plugin - - 2250.v03a_1295b_0a_30 - 17 - + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - true - - - false - - - + + 1.19 + -SNAPSHOT + 2.472 + jenkinsci/${project.artifactId}-plugin + + 2250.v03a_1295b_0a_30 + 17 + false + - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - true - - - false - - - + + + + io.jenkins.tools.bom + bom-2.462.x + 3413.v0d896b_76a_30d + pom + import + + + - - - - io.jenkins.tools.bom - bom-2.462.x - 3413.v0d896b_76a_30d - import - pom - - - + + + io.jenkins.plugins + gson-api + + + org.jenkins-ci.plugins + credentials + + + org.jenkins-ci.plugins + git + + + org.jenkins-ci.plugins + junit + true + + + org.jenkins-ci.plugins + plain-credentials + + + org.jenkins-ci.plugins + s3 + 483.vcb_db_3dcee68f + true + + + org.apache.commons + commons-lang3 + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + + org.jenkins-ci + symbol-annotation + + + + + org.jenkins-ci.plugins + token-macro + true + + + net.sf.ezmorph + ezmorph + 1.0.6 + test + + + org.mockito + mockito-core + test + + - - - - io.jenkins.plugins - gson-api - - - org.jenkins-ci.plugins - git - - - org.jenkins-ci.plugins - credentials - - - org.jenkins-ci.plugins - junit - true - - - org.jenkins-ci.plugins - plain-credentials - - - - org.jenkins-ci.plugins - s3 - 483.vcb_db_3dcee68f - true - - - org.apache.httpcomponents - httpclient - - - org.apache.httpcomponents - httpcore - - - org.apache.commons - commons-lang3 - - - org.jenkins-ci - symbol-annotation - - - - - org.jenkins-ci.plugins - token-macro - true - - - net.sf.ezmorph - ezmorph - 1.0.6 - test - - - org.mockito - mockito-core - test - - + + + + true + + + false + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + - - - markb - Mark Berner - markb@tikalk.com - Tikal Knowledge - http://tikalk.com - - - hagzag - Haggai Philip Zagury - hagzag@tikalk.com - Tikal Knowledge - http://tikalk.com - - - evgenyg - Evgeny Goldin - evgenyg@gmail.com - AKQA - http://akqa.com - - - cohencil - Chen Cohen - chenc@tikalk.com - http://tikalk.com - - - - - scm:git:https://github.com/${gitHubRepo}.git - scm:git:git@github.com:${gitHubRepo}.git - ${scmTag} - https://github.com/${gitHubRepo} - - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - A business-friendly OSS license - - + + + + true + + + false + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + - diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java index 2886dd2..03f6fd0 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Endpoint.java @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.tikal.hudson.plugins.notification; import org.kohsuke.stapler.DataBoundConstructor; @@ -20,20 +19,20 @@ public class Endpoint { public static final Integer DEFAULT_TIMEOUT = 30000; - + public static final Integer DEFAULT_RETRIES = 0; public static final String DEFAULT_BRANCH = ".*"; private Protocol protocol = Protocol.HTTP; - + /** * json as default */ private Format format = Format.JSON; - + private UrlInfo urlInfo; - + // For backwards compatbility @Deprecated private transient String url; @@ -45,7 +44,7 @@ public class Endpoint { private Integer loglines = 0; private String buildNotes; - + private Integer retries = DEFAULT_RETRIES; private String branch = ".*"; @@ -61,23 +60,23 @@ public class Endpoint { */ @Deprecated public Endpoint(Protocol protocol, String url, String event, Format format, Integer timeout, Integer loglines) { - setProtocol( protocol ); - setUrlInfo( new UrlInfo(UrlType.PUBLIC, url) ); - setEvent( event ); - setFormat( format ); - setTimeout( timeout ); - setLoglines( loglines ); - } - + setProtocol(protocol); + setUrlInfo(new UrlInfo(UrlType.PUBLIC, url)); + setEvent(event); + setFormat(format); + setTimeout(timeout); + setLoglines(loglines); + } + /** * Adds a new endpoint for notifications * @param urlInfo Information about the target URL for the event. */ @DataBoundConstructor public Endpoint(UrlInfo urlInfo) { - setUrlInfo ( urlInfo ); + setUrlInfo(urlInfo); } - + public UrlInfo getUrlInfo() { if (this.urlInfo == null) { this.urlInfo = new UrlInfo(UrlType.PUBLIC, ""); @@ -99,7 +98,7 @@ public int getTimeout() { */ @DataBoundSetter public void setTimeout(Integer timeout) { - this.timeout = timeout; + this.timeout = timeout; } public Protocol getProtocol() { @@ -107,7 +106,7 @@ public Protocol getProtocol() { } /** - * Sets the protocol for the + * Sets the protocol for the * @param protocol Protocol to use. Valid values are: UDP, TCP, HTTP. Default is HTTP. * HTTP event target urls must start with 'http' */ @@ -116,7 +115,7 @@ public void setProtocol(Protocol protocol) { this.protocol = protocol; } - public String getEvent (){ + public String getEvent() { return event; } @@ -125,12 +124,12 @@ public String getEvent (){ * @param event 'STARTED' - Fire on job started. 'COMPLETED' - Fire on job completed. 'FINALIZED' - Fire on job finalized. */ @DataBoundSetter - public void setEvent ( String event ){ + public void setEvent(String event) { this.event = event; } - + public Format getFormat() { - if (this.format==null){ + if (this.format == null) { this.format = Format.JSON; } return format; @@ -174,11 +173,11 @@ public void setBuildNotes(String buildNotes) { public boolean isJson() { return getFormat() == Format.JSON; } - + public Integer getRetries() { return this.retries == null ? DEFAULT_RETRIES : this.retries; } - + /** * Number of retries before giving up on contacting an endpoint * @param retries - Number of retries. Default 0. @@ -187,11 +186,11 @@ public Integer getRetries() { public void setRetries(Integer retries) { this.retries = retries; } - + protected Object readResolve() { if (url != null) { - // Upgrade, this is a public URL - this.urlInfo = new UrlInfo(UrlType.PUBLIC, url); + // Upgrade, this is a public URL + this.urlInfo = new UrlInfo(UrlType.PUBLIC, url); } return this; } @@ -211,6 +210,6 @@ public void setBranch(final String branch) { @Override public String toString() { - return protocol+":"+urlInfo.getUrlOrId(); + return protocol + ":" + urlInfo.getUrlOrId(); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Format.java b/src/main/java/com/tikal/hudson/plugins/notification/Format.java index 702910b..e6e27cb 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Format.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Format.java @@ -18,25 +18,26 @@ import com.google.gson.GsonBuilder; import com.thoughtworks.xstream.XStream; import com.tikal.hudson.plugins.notification.model.JobState; - import java.io.IOException; public enum Format { XML { - private transient final XStream xstream = new XStream(); + private final transient XStream xstream = new XStream(); @Override protected byte[] serialize(JobState jobState) throws IOException { xstream.processAnnotations(JobState.class); - return xstream.toXML(jobState).getBytes( "UTF-8" ); + return xstream.toXML(jobState).getBytes("UTF-8"); } }, JSON { - private transient final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + private final transient Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); @Override protected byte[] serialize(JobState jobState) throws IOException { - return gson.toJson(jobState).getBytes( "UTF-8" ); + return gson.toJson(jobState).getBytes("UTF-8"); } }; diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java index dc5595a..e6eb959 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationProperty.java @@ -1,42 +1,40 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tikal.hudson.plugins.notification; - -import hudson.model.Job; -import hudson.model.JobProperty; -import org.kohsuke.stapler.DataBoundConstructor; - -import java.util.ArrayList; -import java.util.List; - -public class HudsonNotificationProperty extends - JobProperty> { - - public final List endpoints; - - @DataBoundConstructor - public HudsonNotificationProperty(List endpoints) { - this.endpoints = new ArrayList( endpoints ); - } - - public List getEndpoints() { - return endpoints; - } - - @SuppressWarnings( "CastToConcreteClass" ) - @Override - public HudsonNotificationPropertyDescriptor getDescriptor() { - return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); - } -} \ No newline at end of file +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification; + +import hudson.model.Job; +import hudson.model.JobProperty; +import java.util.ArrayList; +import java.util.List; +import org.kohsuke.stapler.DataBoundConstructor; + +public class HudsonNotificationProperty extends JobProperty> { + + public final List endpoints; + + @DataBoundConstructor + public HudsonNotificationProperty(List endpoints) { + this.endpoints = new ArrayList(endpoints); + } + + public List getEndpoints() { + return endpoints; + } + + @SuppressWarnings("CastToConcreteClass") + @Override + public HudsonNotificationPropertyDescriptor getDescriptor() { + return (HudsonNotificationPropertyDescriptor) super.getDescriptor(); + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java index 1b2bf3e..cc14de5 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/HudsonNotificationPropertyDescriptor.java @@ -27,6 +27,11 @@ import hudson.security.Permission; import hudson.util.FormValidation; import hudson.util.ListBoxModel; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import javax.annotation.Nonnull; import jenkins.model.Jenkins; import net.sf.json.JSON; import net.sf.json.JSONArray; @@ -37,13 +42,6 @@ import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import javax.annotation.Nonnull; - @Extension public final class HudsonNotificationPropertyDescriptor extends JobPropertyDescriptor { @@ -77,15 +75,15 @@ public String getDisplayName() { return "Hudson Job Notification"; } - public String getDefaultBranch(){ + public String getDefaultBranch() { return Endpoint.DEFAULT_BRANCH; } - public int getDefaultTimeout(){ + public int getDefaultTimeout() { return Endpoint.DEFAULT_TIMEOUT; } - - public int getDefaultRetries(){ + + public int getDefaultRetries() { return Endpoint.DEFAULT_RETRIES; } @@ -109,18 +107,16 @@ public HudsonNotificationProperty newInstance(StaplerRequest req, JSONObject for return new HudsonNotificationProperty(endpoints); } - + private Endpoint convertJson(JSONObject endpointObjectData) throws FormException { // Transform the data to get the public/secret URL data JSONObject urlInfoData = endpointObjectData.getJSONObject("urlInfo"); UrlInfo urlInfo; if (urlInfoData.containsKey("publicUrl")) { urlInfo = new UrlInfo(UrlType.PUBLIC, urlInfoData.getString("publicUrl")); - } - else if (urlInfoData.containsKey("secretUrl")) { + } else if (urlInfoData.containsKey("secretUrl")) { urlInfo = new UrlInfo(UrlType.SECRET, urlInfoData.getString("secretUrl")); - } - else { + } else { throw new FormException("Expected either a public url or secret url id", "urlInfo"); } @@ -136,34 +132,35 @@ else if (urlInfoData.containsKey("secretUrl")) { return endpoint; } - + public FormValidation doCheckPublicUrl( @QueryParameter(value = "publicUrl", fixEmpty = true) String publicUrl, - @RelativePath ("..") @QueryParameter(value = "protocol") String protocolParameter) { + @RelativePath("..") @QueryParameter(value = "protocol") String protocolParameter) { Protocol protocol = Protocol.valueOf(protocolParameter); return checkUrl(publicUrl, UrlType.PUBLIC, protocol); } - + public FormValidation doCheckSecretUrl( @QueryParameter(value = "secretUrl", fixEmpty = true) String publicUrl, - @RelativePath ("..") @QueryParameter(value = "protocol") String protocolParameter) { + @RelativePath("..") @QueryParameter(value = "protocol") String protocolParameter) { Protocol protocol = Protocol.valueOf(protocolParameter); return checkUrl(publicUrl, UrlType.SECRET, protocol); } - + private FormValidation checkUrl(String urlOrId, UrlType urlType, Protocol protocol) { String actualUrl = urlOrId; if (urlType == UrlType.SECRET && !StringUtils.isEmpty(actualUrl)) { actualUrl = Jenkins.get().getItems(ItemGroup.class).stream() .map(ig -> Utils.getSecretUrl(urlOrId, ig)) .filter(Objects::nonNull) - .findFirst().orElse(null); + .findFirst() + .orElse(null); // Get the credentials if (actualUrl == null) { return FormValidation.error("Could not find secret text credentials with id " + urlOrId); } } - + try { protocol.validateUrl(actualUrl); return FormValidation.ok(); @@ -175,19 +172,18 @@ private FormValidation checkUrl(String urlOrId, UrlType urlType, Protocol protoc return FormValidation.error(message); } } - + public ListBoxModel doFillSecretUrlItems(@AncestorInPath Item owner, @QueryParameter String secretUrl) { if (owner == null || !owner.hasPermission(Permission.CONFIGURE)) { return new StandardListBoxModel(); } - + // when configuring the job, you only want those credentials that are available to ACL.SYSTEM selectable // as we cannot select from a user's credentials unless they are the only user submitting the build // (which we cannot assume) thus ACL.SYSTEM is correct here. AbstractIdCredentialsListBoxModel model = new StandardListBoxModel() .includeEmptyValue() - .withAll( - CredentialsProvider.lookupCredentials( + .withAll(CredentialsProvider.lookupCredentials( StringCredentials.class, owner, ACL.SYSTEM, Collections.emptyList())); if (!StringUtils.isEmpty(secretUrl)) { // Select current value, add if missing @@ -198,7 +194,7 @@ public ListBoxModel doFillSecretUrlItems(@AncestorInPath Item owner, @QueryParam } } } - + return model; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java index c59cfb2..a2387f9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/JobListener.java @@ -14,9 +14,9 @@ package com.tikal.hudson.plugins.notification; import hudson.Extension; -import hudson.model.TaskListener; -import hudson.model.Run; import hudson.model.Executor; +import hudson.model.Run; +import hudson.model.TaskListener; import hudson.model.listeners.RunListener; @Extension @@ -30,7 +30,8 @@ public JobListener() { @Override public void onStarted(Run r, TaskListener listener) { Executor e = r.getExecutor(); - Phase.QUEUED.handle(r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L); + Phase.QUEUED.handle( + r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L); Phase.STARTED.handle(r, listener, r.getTimeInMillis()); } @@ -43,5 +44,4 @@ public void onCompleted(Run r, TaskListener listener) { public void onFinalized(Run r) { Phase.FINALIZED.handle(r, TaskListener.NULL, System.currentTimeMillis()); } - } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java index 7fde269..460e1c7 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/NotifyStep.java @@ -5,6 +5,11 @@ import hudson.Util; import hudson.model.Run; import hudson.model.TaskListener; +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import org.jenkinsci.plugins.workflow.graph.FlowNode; import org.jenkinsci.plugins.workflow.steps.Step; import org.jenkinsci.plugins.workflow.steps.StepContext; @@ -13,116 +18,115 @@ import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; +public class NotifyStep extends Step implements Serializable { + private static final long serialVersionUID = -2818860651754465006L; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; + @CheckForNull + private String notes; -public class NotifyStep extends Step implements Serializable { - private static final long serialVersionUID = -2818860651754465006L; - - @CheckForNull - private String notes; - - @CheckForNull - public String getNotes() { - return notes; - } - - @DataBoundSetter - public void setNotes(@CheckForNull String notes) { - this.notes = Util.fixEmpty(notes); - } - - @CheckForNull - private String phase = Phase.STARTED.name(); - - @CheckForNull - public String getPhase() { - return phase; - } - - @DataBoundSetter - public void setPhase(@CheckForNull String phase) { - this.phase = Util.fixEmpty(phase); - } - - @CheckForNull - private String loglines = "0"; - - @CheckForNull - public String getLoglines() { - return loglines; - } - - @DataBoundSetter - public void setLoglines(@CheckForNull String loglines) { - this.loglines = Util.fixEmpty(loglines); - } - - /** - * Creates a new instance of {@link NotifyStep}. - */ - @DataBoundConstructor - public NotifyStep() { - super(); - - // empty constructor required for Stapler - } - - @Override - public StepExecution start(final StepContext context) { - return new Execution(context, this); - } - - /** - * Actually performs the execution of the associated step. - */ - static class Execution extends StepExecution { - private static final long serialVersionUID = -2840020502160375407L; - - private final NotifyStep notifyStep; - - Execution(@Nonnull final StepContext context, final NotifyStep step) { - super(context); - notifyStep = step; + @CheckForNull + public String getNotes() { + return notes; } - @Override - public boolean start() throws Exception { - String logLines = notifyStep.getLoglines(); + @DataBoundSetter + public void setNotes(@CheckForNull String notes) { + this.notes = Util.fixEmpty(notes); + } - Phase.NONE.handle(Objects.requireNonNull(getContext().get(Run.class)), getContext().get(TaskListener.class), System.currentTimeMillis(), true, - notifyStep.getNotes(), Integer.parseInt(logLines != null ? logLines : "0"), Phase.valueOf(notifyStep.getPhase())); + @CheckForNull + private String phase = Phase.STARTED.name(); - getContext().onSuccess(null); + @CheckForNull + public String getPhase() { + return phase; + } - return true; + @DataBoundSetter + public void setPhase(@CheckForNull String phase) { + this.phase = Util.fixEmpty(phase); } - } - - /** - * Descriptor for this step: defines the context and the UI labels. - */ - @Extension - @SuppressWarnings("unused") // most methods are used by the corresponding jelly view - public static class Descriptor extends StepDescriptor { - @Override - public String getFunctionName() { - return "notifyEndpoints"; + + @CheckForNull + private String loglines = "0"; + + @CheckForNull + public String getLoglines() { + return loglines; } - @Nonnull - @Override - public String getDisplayName() { - return Messages.Notify_DisplayName(); + @DataBoundSetter + public void setLoglines(@CheckForNull String loglines) { + this.loglines = Util.fixEmpty(loglines); + } + + /** + * Creates a new instance of {@link NotifyStep}. + */ + @DataBoundConstructor + public NotifyStep() { + super(); + + // empty constructor required for Stapler } @Override - public Set> getRequiredContext() { - return Set.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class); + public StepExecution start(final StepContext context) { + return new Execution(context, this); + } + + /** + * Actually performs the execution of the associated step. + */ + static class Execution extends StepExecution { + private static final long serialVersionUID = -2840020502160375407L; + + private final NotifyStep notifyStep; + + Execution(@Nonnull final StepContext context, final NotifyStep step) { + super(context); + notifyStep = step; + } + + @Override + public boolean start() throws Exception { + String logLines = notifyStep.getLoglines(); + + Phase.NONE.handle( + Objects.requireNonNull(getContext().get(Run.class)), + getContext().get(TaskListener.class), + System.currentTimeMillis(), + true, + notifyStep.getNotes(), + Integer.parseInt(logLines != null ? logLines : "0"), + Phase.valueOf(notifyStep.getPhase())); + + getContext().onSuccess(null); + + return true; + } + } + + /** + * Descriptor for this step: defines the context and the UI labels. + */ + @Extension + @SuppressWarnings("unused") // most methods are used by the corresponding jelly view + public static class Descriptor extends StepDescriptor { + @Override + public String getFunctionName() { + return "notifyEndpoints"; + } + + @Nonnull + @Override + public String getDisplayName() { + return Messages.Notify_DisplayName(); + } + + @Override + public Set> getRequiredContext() { + return Set.of(FilePath.class, FlowNode.class, Run.class, TaskListener.class); + } } - } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java index d7411e8..5649bb9 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Phase.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Phase.java @@ -17,7 +17,6 @@ import com.tikal.hudson.plugins.notification.model.JobState; import com.tikal.hudson.plugins.notification.model.ScmState; import com.tikal.hudson.plugins.notification.model.TestState; - import hudson.EnvVars; import hudson.FilePath; import hudson.model.AbstractBuild; @@ -34,11 +33,6 @@ import hudson.scm.ChangeLogSet; import hudson.tasks.test.AbstractTestResultAction; import hudson.tasks.test.TestResult; -import jenkins.model.Jenkins; -import org.apache.commons.lang.StringUtils; - -import org.jenkinsci.plugins.tokenmacro.TokenMacro; - import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; @@ -46,30 +40,38 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import jenkins.model.Jenkins; +import org.apache.commons.lang.StringUtils; +import org.jenkinsci.plugins.tokenmacro.TokenMacro; - -@SuppressWarnings({ "unchecked", "rawtypes" }) +@SuppressWarnings({"unchecked", "rawtypes"}) public enum Phase { - QUEUED, STARTED, COMPLETED, FINALIZED, NONE; + QUEUED, + STARTED, + COMPLETED, + FINALIZED, + NONE; - private Result findLastBuildThatFinished(Run run){ + private Result findLastBuildThatFinished(Run run) { Run previousRun = run.getPreviousCompletedBuild(); - while(previousRun != null){ - Result previousResults = previousRun.getResult(); - if (previousResults == null) { - throw new IllegalStateException("Previous result can't be null here"); - } - if (previousResults.equals(Result.SUCCESS) || previousResults.equals(Result.FAILURE) || previousResults.equals(Result.UNSTABLE)){ - return previousResults; - } - previousRun = previousRun.getPreviousCompletedBuild(); + while (previousRun != null) { + Result previousResults = previousRun.getResult(); + if (previousResults == null) { + throw new IllegalStateException("Previous result can't be null here"); + } + if (previousResults.equals(Result.SUCCESS) + || previousResults.equals(Result.FAILURE) + || previousResults.equals(Result.UNSTABLE)) { + return previousResults; + } + previousRun = previousRun.getPreviousCompletedBuild(); } return null; - } + } - @SuppressWarnings( "CastToConcreteClass" ) + @SuppressWarnings("CastToConcreteClass") public void handle(Run run, TaskListener listener, long timestamp) { - handle(run, listener, timestamp, false, null, 0, this); + handle(run, listener, timestamp, false, null, 0, this); } /** @@ -80,128 +82,133 @@ public void handle(Run run, TaskListener listener, long timestamp) { * @param logger PrintStream used for logging. * @return True if URL is populated with a non-blank value, or a variable that expands into a URL. */ - private boolean isURLValid(String urlInputValue, String expandedUrl, PrintStream logger){ - boolean isValid= false; - //If Jenkins variable was used for URL, and it was unresolvable, log warning and return. + private boolean isURLValid(String urlInputValue, String expandedUrl, PrintStream logger) { + boolean isValid = false; + // If Jenkins variable was used for URL, and it was unresolvable, log warning and return. if (expandedUrl.contains("$")) { logger.printf("Ignoring sending notification due to unresolved variable: %s%n", urlInputValue); - }else if(StringUtils.isBlank(expandedUrl)){ + } else if (StringUtils.isBlank(expandedUrl)) { logger.println("URL is not set, ignoring call to send notification."); - }else{ - isValid=true; + } else { + isValid = true; } return isValid; } - - /** * Determines if the endpoint specified should be notified at the current job phase. */ - private boolean isRun( Endpoint endpoint, Result result, Result previousRunResult ) { + private boolean isRun(Endpoint endpoint, Result result, Result previousRunResult) { String event = endpoint.getEvent(); - if(event == null) - return true; - - switch(event){ - case "all": - return true; - case "failed": - if (result == null) {return false;} - return this.equals(FINALIZED) && result.equals(Result.FAILURE); - case "failedAndFirstSuccess": - if (result == null || !this.equals(FINALIZED)) {return false;} - if (result.equals(Result.FAILURE)) {return true;} - return previousRunResult != null && result.equals(Result.SUCCESS) - && previousRunResult.equals(Result.FAILURE); + if (event == null) { + return true; + } + + switch (event) { + case "all": + return true; + case "failed": + if (result == null) { + return false; + } + return this.equals(FINALIZED) && result.equals(Result.FAILURE); + case "failedAndFirstSuccess": + if (result == null || !this.equals(FINALIZED)) { + return false; + } + if (result.equals(Result.FAILURE)) { + return true; + } + return previousRunResult != null + && result.equals(Result.SUCCESS) + && previousRunResult.equals(Result.FAILURE); case "manual": - return false; - default: - return event.equals(this.toString().toLowerCase()); + return false; + default: + return event.equals(this.toString().toLowerCase()); } } - private JobState buildJobState(Job job, Run run, TaskListener listener, long timestamp, Endpoint target, Phase phase) - throws IOException, InterruptedException - { - Jenkins jenkins = Jenkins.getInstanceOrNull(); + private JobState buildJobState( + Job job, Run run, TaskListener listener, long timestamp, Endpoint target, Phase phase) + throws IOException, InterruptedException { + Jenkins jenkins = Jenkins.getInstanceOrNull(); assert jenkins != null; - String rootUrl = jenkins.getRootUrl(); - JobState jobState = new JobState(); - BuildState buildState = new BuildState(); - ScmState scmState = new ScmState(); - Result result = run.getResult(); - ParametersAction paramsAction = run.getAction(ParametersAction.class); - EnvVars environment = run.getEnvironment( listener ); - StringBuilder log = this.getLog(run, target); + String rootUrl = jenkins.getRootUrl(); + JobState jobState = new JobState(); + BuildState buildState = new BuildState(); + ScmState scmState = new ScmState(); + Result result = run.getResult(); + ParametersAction paramsAction = run.getAction(ParametersAction.class); + EnvVars environment = run.getEnvironment(listener); + StringBuilder log = this.getLog(run, target); - jobState.setName( job.getName()); + jobState.setName(job.getName()); jobState.setDisplayName(job.getDisplayName()); - jobState.setUrl( job.getUrl()); - jobState.setBuild( buildState ); - - buildState.setNumber( run.number ); - buildState.setQueueId( run.getQueueId() ); - buildState.setUrl( run.getUrl()); - buildState.setPhase( phase ); - buildState.setTimestamp( timestamp ); - buildState.setDuration( run.getDuration() ); - buildState.setScm( scmState ); - buildState.setLog( log ); + jobState.setUrl(job.getUrl()); + jobState.setBuild(buildState); + + buildState.setNumber(run.number); + buildState.setQueueId(run.getQueueId()); + buildState.setUrl(run.getUrl()); + buildState.setPhase(phase); + buildState.setTimestamp(timestamp); + buildState.setDuration(run.getDuration()); + buildState.setScm(scmState); + buildState.setLog(log); buildState.setNotes(resolveMacros(run, listener, target.getBuildNotes())); buildState.setTestSummary(getTestResults(run)); - if ( result != null ) { + if (result != null) { buildState.setStatus(result.toString()); } - if ( rootUrl != null ) { + if (rootUrl != null) { buildState.setFullUrl(rootUrl + run.getUrl()); } - buildState.updateArtifacts( job, run ); + buildState.updateArtifacts(job, run); - //TODO: Make this optional to reduce chat overload. - if ( paramsAction != null ) { + // TODO: Make this optional to reduce chat overload. + if (paramsAction != null) { EnvVars env = new EnvVars(); - for (ParameterValue value : paramsAction.getParameters()){ - if ( ! value.isSensitive()) { - value.buildEnvironment( run, env ); + for (ParameterValue value : paramsAction.getParameters()) { + if (!value.isSensitive()) { + value.buildEnvironment(run, env); } } buildState.setParameters(env); } - + BuildData build = job.getAction(BuildData.class); - if ( build != null ) { - if ( !build.remoteUrls.isEmpty() ) { + if (build != null) { + if (!build.remoteUrls.isEmpty()) { String url = build.remoteUrls.iterator().next(); - if ( url != null ) { - scmState.setUrl( url ); + if (url != null) { + scmState.setUrl(url); } } for (Map.Entry entry : build.buildsByBranchName.entrySet()) { - if ( entry.getValue().hudsonBuildNumber == run.number ) { - scmState.setBranch( entry.getKey() ); - scmState.setCommit( entry.getValue().revision.getSha1String() ); + if (entry.getValue().hudsonBuildNumber == run.number) { + scmState.setBranch(entry.getKey()); + scmState.setCommit(entry.getValue().revision.getSha1String()); } } } - - if ( environment.get( "GIT_URL" ) != null ) { - scmState.setUrl( environment.get( "GIT_URL" )); + + if (environment.get("GIT_URL") != null) { + scmState.setUrl(environment.get("GIT_URL")); } - - if ( environment.get( "GIT_BRANCH" ) != null ) { - scmState.setBranch( environment.get( "GIT_BRANCH" )); + if (environment.get("GIT_BRANCH") != null) { + scmState.setBranch(environment.get("GIT_BRANCH")); } - if ( environment.get( "GIT_COMMIT" ) != null ) { - scmState.setCommit( environment.get( "GIT_COMMIT" )); + if (environment.get("GIT_COMMIT") != null) { + scmState.setCommit(environment.get("GIT_COMMIT")); } scmState.setChanges(getChangedFiles(run)); @@ -215,9 +222,9 @@ private String resolveMacros(Run build, TaskListener listener, String text) { String result = text; try { Executor executor = build.getExecutor(); - if(executor != null) { + if (executor != null) { FilePath workspace = executor.getCurrentWorkspace(); - if(workspace != null) { + if (workspace != null) { result = TokenMacro.expandAll(build, workspace, listener, text); } } @@ -234,7 +241,7 @@ private TestState getTestResults(Run build) { TestState resultSummary = null; AbstractTestResultAction testAction = build.getAction(AbstractTestResultAction.class); - if(testAction != null) { + if (testAction != null) { int total = testAction.getTotalCount(); int failCount = testAction.getFailCount(); int skipCount = testAction.getSkipCount(); @@ -247,7 +254,6 @@ private TestState getTestResults(Run build) { resultSummary.setFailedTests(getFailedTestNames(testAction)); } - return resultSummary; } @@ -256,7 +262,7 @@ private List getFailedTestNames(AbstractTestResultAction testResultActio List results = testResultAction.getFailedTests(); - for(TestResult t : results) { + for (TestResult t : results) { failedTests.add(t.getFullName()); } @@ -266,14 +272,14 @@ private List getFailedTestNames(AbstractTestResultAction testResultActio private List getChangedFiles(Run run) { List affectedPaths = new ArrayList<>(); - if(run instanceof AbstractBuild) { + if (run instanceof AbstractBuild) { AbstractBuild build = (AbstractBuild) run; Object[] items = build.getChangeSet().getItems(); - if(items != null && items.length > 0) { - for(Object o : items) { - if(o instanceof ChangeLogSet.Entry) { + if (items != null && items.length > 0) { + for (Object o : items) { + if (o instanceof ChangeLogSet.Entry) { affectedPaths.addAll(((ChangeLogSet.Entry) o).getAffectedPaths()); } } @@ -286,10 +292,10 @@ private List getChangedFiles(Run run) { private List getCulprits(Run run) { List culprits = new ArrayList<>(); - if(run instanceof AbstractBuild) { + if (run instanceof AbstractBuild) { AbstractBuild build = (AbstractBuild) run; Set buildCulprits = build.getCulprits(); - for(User user : buildCulprits) { + for (User user : buildCulprits) { culprits.add(user.getId()); } } @@ -322,25 +328,34 @@ private StringBuilder getLog(Run run, Endpoint target) { return log; } - public void handle(Run run, TaskListener listener, long timestamp, boolean manual, final String buildNotes, final Integer logLines, Phase phase) { + public void handle( + Run run, + TaskListener listener, + long timestamp, + boolean manual, + final String buildNotes, + final Integer logLines, + Phase phase) { final Job job = run.getParent(); - final HudsonNotificationProperty property = (HudsonNotificationProperty) job.getProperty(HudsonNotificationProperty.class); - if ( property == null ) { + final HudsonNotificationProperty property = + (HudsonNotificationProperty) job.getProperty(HudsonNotificationProperty.class); + if (property == null) { return; } Result previousCompletedRunResults = findLastBuildThatFinished(run); - for ( Endpoint target : property.getEndpoints()) { - if ((!manual && !isRun(target, run.getResult(), previousCompletedRunResults)) || Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { + for (Endpoint target : property.getEndpoints()) { + if ((!manual && !isRun(target, run.getResult(), previousCompletedRunResults)) + || Utils.isEmpty(target.getUrlInfo().getUrlOrId())) { continue; } - if(Objects.nonNull(buildNotes)) { + if (Objects.nonNull(buildNotes)) { target.setBuildNotes(buildNotes); } - if(Objects.nonNull(logLines) && logLines != 0) { + if (Objects.nonNull(logLines) && logLines != 0) { target.setLoglines(logLines); } @@ -375,32 +390,43 @@ public void handle(Run run, TaskListener listener, long timestamp, boolean manua } final String branch = target.getBranch(); - if (!manual && environment.containsKey("BRANCH_NAME") && !environment.get("BRANCH_NAME").matches(branch)) { - listener.getLogger().printf("Environment variable %s with value %s does not match configured branch filter %s%n", "BRANCH_NAME", environment.get("BRANCH_NAME"), branch); + if (!manual + && environment.containsKey("BRANCH_NAME") + && !environment.get("BRANCH_NAME").matches(branch)) { + listener.getLogger() + .printf( + "Environment variable %s with value %s does not match configured branch filter %s%n", + "BRANCH_NAME", environment.get("BRANCH_NAME"), branch); continue; - }else if(!manual && !environment.containsKey("BRANCH_NAME") && !".*".equals(branch)){ + } else if (!manual && !environment.containsKey("BRANCH_NAME") && !".*".equals(branch)) { listener.getLogger().printf("Environment does not contain %s variable%n", "BRANCH_NAME"); continue; } listener.getLogger().printf("Notifying endpoint with %s%n", urlIdString); JobState jobState = buildJobState(job, run, listener, timestamp, target, phase); - target.getProtocol().send(expandedUrl, - target.getFormat().serialize(jobState), - target.getTimeout(), - target.isJson()); + target.getProtocol() + .send( + expandedUrl, + target.getFormat().serialize(jobState), + target.getTimeout(), + target.isJson()); } catch (Throwable error) { failed = true; - error.printStackTrace( listener.error( String.format( "Failed to notify endpoint with %s", urlIdString))); - listener.getLogger().printf("Failed to notify endpoint with %s - %s: %s%n", - urlIdString, error.getClass().getName(), error.getMessage()); + error.printStackTrace( + listener.error(String.format("Failed to notify endpoint with %s", urlIdString))); + listener.getLogger() + .printf( + "Failed to notify endpoint with %s - %s: %s%n", + urlIdString, error.getClass().getName(), error.getMessage()); if (triesRemaining > 0) { - listener.getLogger().printf( - "Reattempting to notify endpoint with %s (%d tries remaining)%n", urlIdString, triesRemaining); + listener.getLogger() + .printf( + "Reattempting to notify endpoint with %s (%d tries remaining)%n", + urlIdString, triesRemaining); } } - } - while (failed && --triesRemaining >= 0); + } while (failed && --triesRemaining >= 0); } } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java index dbda148..8f2e3b5 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Protocol.java @@ -13,23 +13,30 @@ */ package com.tikal.hudson.plugins.notification; - -import jenkins.model.Jenkins; - import java.io.IOException; import java.io.OutputStream; -import java.net.*; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URL; import java.nio.charset.Charset; import java.util.Base64; +import jenkins.model.Jenkins; public enum Protocol { - UDP { @Override protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); DatagramSocket socket = new DatagramSocket(); - DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + DatagramPacket packet = new DatagramPacket( + data, data.length, InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); socket.send(packet); } }, @@ -37,7 +44,8 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws @Override protected void send(String url, byte[] data, int timeout, boolean isJson) throws IOException { HostnamePort hostnamePort = HostnamePort.parseUrl(url); - SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); + SocketAddress endpoint = + new InetSocketAddress(InetAddress.getByName(hostnamePort.hostname), hostnamePort.port); Socket socket = new Socket(); socket.setSoTimeout(timeout); socket.connect(endpoint, timeout); @@ -53,35 +61,38 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws URL targetUrl = new URL(url); if (!targetUrl.getProtocol().startsWith("http")) { - throw new IllegalArgumentException("Not an http(s) url: " + url); + throw new IllegalArgumentException("Not an http(s) url: " + url); } // Verifying if the HTTP_PROXY is available final String httpProxyUrl = System.getenv().get("http_proxy"); URL proxyUrl = null; if (httpProxyUrl != null && httpProxyUrl.length() > 0) { - proxyUrl = new URL(httpProxyUrl); - if (!proxyUrl.getProtocol().startsWith("http")) { - throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); - } + proxyUrl = new URL(httpProxyUrl); + if (!proxyUrl.getProtocol().startsWith("http")) { + throw new IllegalArgumentException("Not an http(s) url: " + httpProxyUrl); + } } Proxy proxy = Proxy.NO_PROXY; if (Jenkins.getInstance() != null && Jenkins.getInstance().proxy != null) { - proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); + proxy = Jenkins.getInstance().proxy.createProxy(targetUrl.getHost()); } else if (proxyUrl != null) { - // Proxy connection to the address provided - final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; - proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); + // Proxy connection to the address provided + final int proxyPort = proxyUrl.getPort() > 0 ? proxyUrl.getPort() : 80; + proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUrl.getHost(), proxyPort)); } HttpURLConnection connection = (HttpURLConnection) targetUrl.openConnection(proxy); - connection.setRequestProperty("Content-Type", String.format( "application/%s;charset=UTF-8", isJson ? "json" : "xml" )); + connection.setRequestProperty( + "Content-Type", String.format("application/%s;charset=UTF-8", isJson ? "json" : "xml")); String userInfo = targetUrl.getUserInfo(); if (null != userInfo) { - String b64UserInfo = Base64.getEncoder().encodeToString(userInfo.getBytes(Charset.defaultCharset())); // TODO see if UTF-8 can be used instead of platform default encoding - String authorizationHeader = "Basic " + b64UserInfo; - connection.setRequestProperty("Authorization", authorizationHeader); + // TODO see if UTF-8 can be used instead of platform default encoding + String b64UserInfo = Base64.getEncoder().encodeToString(userInfo.getBytes(Charset.defaultCharset())); + + String authorizationHeader = "Basic " + b64UserInfo; + connection.setRequestProperty("Authorization", authorizationHeader); } connection.setFixedLengthStreamingMode(data.length); connection.setDoInput(true); @@ -90,45 +101,46 @@ protected void send(String url, byte[] data, int timeout, boolean isJson) throws connection.setReadTimeout(timeout); connection.connect(); try { - OutputStream output = connection.getOutputStream(); - try { - output.write(data); - output.flush(); - } finally { - output.close(); - } + OutputStream output = connection.getOutputStream(); + try { + output.write(data); + output.flush(); + } finally { + output.close(); + } } finally { - // Follow an HTTP Temporary Redirect if we get one, - // - // NB: Normally using the HttpURLConnection interface, we'd call - // connection.setInstanceFollowRedirects(true) to enable 307 redirect following but - // since we have the connection in streaming mode this does not work and we instead - // re-direct manually. - if (307 == connection.getResponseCode()) { - String location = connection.getHeaderField("Location"); - connection.disconnect(); - send(location, data,timeout, isJson); - } else { - connection.disconnect(); - } + // Follow an HTTP Temporary Redirect if we get one, + // + // NB: Normally using the HttpURLConnection interface, we'd call + // connection.setInstanceFollowRedirects(true) to enable 307 redirect following but + // since we have the connection in streaming mode this does not work and we instead + // re-direct manually. + if (307 == connection.getResponseCode()) { + String location = connection.getHeaderField("Location"); + connection.disconnect(); + send(location, data, timeout, isJson); + } else { + connection.disconnect(); + } } } @Override - public void validateUrl( String url ) { - //do not validate if Jenkins Variable is used. + public void validateUrl(String url) { + // do not validate if Jenkins Variable is used. if (!url.contains("$")) { try { // noinspection ResultOfObjectAllocationIgnored new URL(url); } catch (MalformedURLException e) { - throw new RuntimeException(String.format("%sUse http://hostname:port/path for endpoint URL", isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); + throw new RuntimeException(String.format( + "%sUse http://hostname:port/path for endpoint URL", + isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); } } } }; - protected abstract void send(String url, byte[] data, int timeout, boolean isJson) throws IOException; public void validateUrl(String url) { @@ -138,12 +150,12 @@ public void validateUrl(String url) { throw new Exception(); } } catch (Exception e) { - throw new RuntimeException( String.format( "%sUse hostname:port for endpoint URL", - isEmpty ( url ) ? "" : "Invalid URL '" + url + "'. " )); + throw new RuntimeException(String.format( + "%sUse hostname:port for endpoint URL", isEmpty(url) ? "" : "Invalid URL '" + url + "'. ")); } } - private static boolean isEmpty( String s ) { - return (( s == null ) || ( s.trim().length() < 1 )); + private static boolean isEmpty(String s) { + return ((s == null) || (s.trim().length() < 1)); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java b/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java index b5b7416..e9d98c1 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/UrlInfo.java @@ -22,14 +22,14 @@ * @author mmitche */ public class UrlInfo { - + private String urlOrId; private UrlType urlType; - + @DataBoundConstructor public UrlInfo(UrlType urlType, String urlOrId) { - setUrlOrId ( urlOrId ); - setUrlType ( urlType ); + setUrlOrId(urlOrId); + setUrlType(urlType); } public String getUrlOrId() { diff --git a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java index 8a203a6..afad471 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/Utils.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/Utils.java @@ -2,44 +2,32 @@ import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; import hudson.model.ItemGroup; import hudson.security.ACL; -import hudson.util.FormValidation; import hudson.util.Secret; import java.util.Arrays; import java.util.Collections; -import java.util.List; - -import jenkins.model.Jenkins; import org.jenkinsci.plugins.plaincredentials.StringCredentials; - /** * Helper utilities */ -public final class Utils -{ - private Utils () - { - } +public final class Utils { + private Utils() {} /** * Determines if any of Strings specified is either null or empty. * @param strings - Strings to check for empty (whitespace is trimmed) or null. * @return True if any string is empty */ - @SuppressWarnings( "MethodWithMultipleReturnPoints" ) - public static boolean isEmpty( String ... strings ) - { - if (( strings == null ) || ( strings.length < 1 )) { + @SuppressWarnings("MethodWithMultipleReturnPoints") + public static boolean isEmpty(String... strings) { + if ((strings == null) || (strings.length < 1)) { return true; } - for ( String s : strings ) - { - if (( s == null ) || ( s.trim().length() < 1 )) - { + for (String s : strings) { + if ((s == null) || (s.trim().length() < 1)) { return true; } } @@ -47,19 +35,16 @@ public static boolean isEmpty( String ... strings ) return false; } - /** * Verifies neither of Strings specified is null or empty. * @param strings Strings to check for empty (whitespace is trimmed) or null. * @throws java.lang.IllegalArgumentException Throws this exception if any string is empty. */ - @SuppressWarnings( "ReturnOfNull" ) - public static void verifyNotEmpty( String ... strings ) - { - if ( isEmpty( strings )) - { - throw new IllegalArgumentException( String.format( - "Some String arguments are null or empty: %s", Arrays.toString( strings ))); + @SuppressWarnings("ReturnOfNull") + public static void verifyNotEmpty(String... strings) { + if (isEmpty(strings)) { + throw new IllegalArgumentException( + String.format("Some String arguments are null or empty: %s", Arrays.toString(strings))); } } @@ -71,8 +56,9 @@ public static void verifyNotEmpty( String ... strings ) */ public static String getSecretUrl(String credentialId, ItemGroup itemGroup) { // Grab the secret text - StringCredentials creds = CredentialsMatchers.firstOrNull(CredentialsProvider.lookupCredentials( - StringCredentials.class, itemGroup, ACL.SYSTEM, Collections.emptyList()), + StringCredentials creds = CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials( + StringCredentials.class, itemGroup, ACL.SYSTEM, Collections.emptyList()), CredentialsMatchers.withId(credentialId)); if (creds == null) { return null; @@ -80,6 +66,4 @@ public static String getSecretUrl(String credentialId, ItemGroup itemGroup) { Secret secretUrl = creds.getSecret(); return secretUrl.getPlainText(); } - - } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java index 5cd7b42..546694f 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/BuildState.java @@ -13,7 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; -import static com.tikal.hudson.plugins.notification.Utils.*; +import static com.tikal.hudson.plugins.notification.Utils.isEmpty; +import static com.tikal.hudson.plugins.notification.Utils.verifyNotEmpty; + import com.tikal.hudson.plugins.notification.Phase; import hudson.model.AbstractBuild; import hudson.model.Job; @@ -21,12 +23,11 @@ import hudson.plugins.s3.Entry; import hudson.plugins.s3.S3BucketPublisher; import hudson.util.DescribableList; -import jenkins.model.Jenkins; - import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; +import jenkins.model.Jenkins; public class BuildState { @@ -58,9 +59,6 @@ public class BuildState { private TestState testSummary; - - - /** * Map of artifacts: file name => Map of artifact locations ( location name => artifact URL ) * --- @@ -142,10 +140,10 @@ public Map getParameters() { } public void setParameters(Map params) { - this.parameters = new HashMap( params ); + this.parameters = new HashMap(params); } - public Map> getArtifacts () { + public Map> getArtifacts() { return artifacts; } @@ -157,13 +155,11 @@ public String getDisplayName() { return displayName; } - public ScmState getScm () - { + public ScmState getScm() { return scm; } - public void setScm ( ScmState scmState ) - { + public void setScm(ScmState scmState) { this.scm = scmState; } @@ -196,58 +192,66 @@ public void setTestSummary(TestState testSummary) { * @param job Job to update * @param run Run to update */ - public void updateArtifacts ( Job job, Run run ) - { - updateArchivedArtifacts( run ); - updateS3Artifacts( job, run ); + public void updateArtifacts(Job job, Run run) { + updateArchivedArtifacts(run); + updateS3Artifacts(job, run); } - - private void updateArchivedArtifacts ( Run run ) - { - @SuppressWarnings( "unchecked" ) + private void updateArchivedArtifacts(Run run) { + @SuppressWarnings("unchecked") List buildArtifacts = run.getArtifacts(); - for ( Run.Artifact a : buildArtifacts ) { + for (Run.Artifact a : buildArtifacts) { String artifactUrl = Jenkins.getInstance().getRootUrl() + run.getUrl() + "artifact/" + a.getHref(); - updateArtifact( a.relativePath, "archive", artifactUrl ); + updateArtifact(a.relativePath, "archive", artifactUrl); } } + private void updateS3Artifacts(Job job, Run run) { + if (Jenkins.getInstance().getPlugin("s3") == null) { + return; + } + if (!(run instanceof AbstractBuild)) { + return; + } + if (isEmpty(job.getName())) { + return; + } - private void updateS3Artifacts ( Job job, Run run ) - { - if ( Jenkins.getInstance().getPlugin( "s3" ) == null ) { return; } - if ( ! ( run instanceof AbstractBuild )){ return; } - if ( isEmpty( job.getName())){ return; } - - DescribableList publishers = (( AbstractBuild ) run ).getProject().getPublishersList(); - S3BucketPublisher s3Publisher = ( S3BucketPublisher ) publishers.get( S3BucketPublisher.class ); + DescribableList publishers = ((AbstractBuild) run).getProject().getPublishersList(); + S3BucketPublisher s3Publisher = (S3BucketPublisher) publishers.get(S3BucketPublisher.class); - if ( s3Publisher == null ){ return; } + if (s3Publisher == null) { + return; + } - for ( Entry entry : s3Publisher.getEntries()) { + for (Entry entry : s3Publisher.getEntries()) { - if ( isEmpty( entry.sourceFile, entry.selectedRegion, entry.bucket )){ continue; } - String fileName = new File( entry.sourceFile ).getName(); - if ( isEmpty( fileName )){ continue; } + if (isEmpty(entry.sourceFile, entry.selectedRegion, entry.bucket)) { + continue; + } + String fileName = new File(entry.sourceFile).getName(); + if (isEmpty(fileName)) { + continue; + } // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/ - String bucketUrl = String.format( "https://s3-%s.amazonaws.com/%s", - entry.selectedRegion.toLowerCase().replace( '_', '-' ), - entry.bucket ); - - String fileUrl = entry.managedArtifacts ? - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi - String.format( "%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName ) : - // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi - String.format( "%s/%s", bucketUrl, fileName ); - - updateArtifact( fileName, "s3", fileUrl ); + String bucketUrl = String.format( + "https://s3-%s.amazonaws.com/%s", + entry.selectedRegion.toLowerCase().replace('_', '-'), entry.bucket); + + String fileUrl = entry.managedArtifacts + ? + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/jobs/notification-plugin/21/notification.hpi + String.format("%s/jobs/%s/%s/%s", bucketUrl, job.getName(), run.getNumber(), fileName) + : + // https://s3-eu-west-1.amazonaws.com/evgenyg-temp/notification.hpi + String.format("%s/%s", bucketUrl, fileName); + + updateArtifact(fileName, "s3", fileUrl); } } - /** * Updates an artifact URL. * @@ -255,20 +259,19 @@ private void updateS3Artifacts ( Job job, Run run ) * @param locationName artifact location name, like "s3" or "archive" * @param locationUrl artifact URL at the location specified */ - private void updateArtifact( String fileName, String locationName, String locationUrl ) - { - verifyNotEmpty( fileName, locationName, locationUrl ); + private void updateArtifact(String fileName, String locationName, String locationUrl) { + verifyNotEmpty(fileName, locationName, locationUrl); - if ( ! artifacts.containsKey( fileName )) { - artifacts.put( fileName, new HashMap()); + if (!artifacts.containsKey(fileName)) { + artifacts.put(fileName, new HashMap()); } - if ( artifacts.get( fileName ).containsKey( locationName )) { - throw new RuntimeException( String.format( - "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", - fileName, locationName, locationUrl, locationName, artifacts )); + if (artifacts.get(fileName).containsKey(locationName)) { + throw new RuntimeException(String.format( + "Adding artifacts mapping '%s/%s/%s' - artifacts Map already contains mapping of location '%s': %s", + fileName, locationName, locationUrl, locationName, artifacts)); } - artifacts.get( fileName ).put( locationName, locationUrl ); + artifacts.get(fileName).put(locationName, locationUrl); } } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java index a8bd06c..0a2d3c5 100755 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/JobState.java @@ -1,60 +1,60 @@ -/** - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.tikal.hudson.plugins.notification.model; - -import com.thoughtworks.xstream.annotations.XStreamAlias; - -@XStreamAlias("job") -public class JobState { - - private String name; - - private String displayName; - - private String url; - - private BuildState build; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public BuildState getBuild() { - return build; - } - - public void setBuild(BuildState build) { - this.build = build; - } -} +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.tikal.hudson.plugins.notification.model; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("job") +public class JobState { + + private String name; + + private String displayName; + + private String url; + + private BuildState build; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public BuildState getBuild() { + return build; + } + + public void setBuild(BuildState build) { + this.build = build; + } +} diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java index ac392cf..ecaa20a 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/ScmState.java @@ -13,11 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; - import java.util.List; -public class ScmState -{ +public class ScmState { private String url; private String branch; @@ -28,33 +26,27 @@ public class ScmState private List culprits; - public String getUrl () - { + public String getUrl() { return url; } - public void setUrl ( String url ) - { + public void setUrl(String url) { this.url = url; } - public String getBranch () - { + public String getBranch() { return branch; } - public void setBranch ( String branch ) - { + public void setBranch(String branch) { this.branch = branch; } - public String getCommit () - { + public String getCommit() { return commit; } - public void setCommit ( String commit ) - { + public void setCommit(String commit) { this.commit = commit; } diff --git a/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java b/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java index c11eeff..c4854c9 100644 --- a/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java +++ b/src/main/java/com/tikal/hudson/plugins/notification/model/TestState.java @@ -13,11 +13,9 @@ */ package com.tikal.hudson.plugins.notification.model; - import java.util.List; -public class TestState -{ +public class TestState { private int total; private int failed; private int passed; diff --git a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java index f8fc751..4ea4185 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/PhaseTest.java @@ -4,18 +4,30 @@ import static com.tikal.hudson.plugins.notification.UrlType.SECRET; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.isA; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; +import com.tikal.hudson.plugins.notification.model.JobState; +import hudson.EnvVars; +import hudson.model.Job; +import hudson.model.Result; +import hudson.model.Run; +import hudson.model.TaskListener; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Method; - -import com.tikal.hudson.plugins.notification.model.JobState; -import hudson.EnvVars; -import hudson.model.*; import jenkins.model.Jenkins; import org.junit.Test; - import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockedStatic; @@ -23,211 +35,260 @@ @RunWith(MockitoJUnitRunner.class) public class PhaseTest { - @Mock - private Run run; - @Mock - private Job job; - @Mock - private TaskListener listener; - @Mock - private HudsonNotificationProperty property; - @Mock - private Endpoint endpoint; - @Mock - private UrlInfo urlInfo; - @Mock - private EnvVars environment; - @Mock - private PrintStream logger; - @Mock - private Jenkins jenkins; - - @Test - public void testIsRun() throws ReflectiveOperationException { - Endpoint endPoint = new Endpoint(null); - Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); - isRunMethod.setAccessible(true); - - assertEquals("returns true for null endpoint event", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - - endPoint.setEvent("all"); - for (Phase phaseValue : Phase.values()) { - assertEquals("all Event returns true for Phase " + phaseValue.toString(), - isRunMethod.invoke(phaseValue, endPoint, null, null), Boolean.TRUE); + @Mock + private Run run; + + @Mock + private Job job; + + @Mock + private TaskListener listener; + + @Mock + private HudsonNotificationProperty property; + + @Mock + private Endpoint endpoint; + + @Mock + private UrlInfo urlInfo; + + @Mock + private EnvVars environment; + + @Mock + private PrintStream logger; + + @Mock + private Jenkins jenkins; + + @Test + public void testIsRun() throws ReflectiveOperationException { + Endpoint endPoint = new Endpoint(null); + Method isRunMethod = Phase.class.getDeclaredMethod("isRun", Endpoint.class, Result.class, Result.class); + isRunMethod.setAccessible(true); + + assertEquals( + "returns true for null endpoint event", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.TRUE); + + endPoint.setEvent("all"); + for (Phase phaseValue : Phase.values()) { + assertEquals( + "all Event returns true for Phase " + phaseValue.toString(), + isRunMethod.invoke(phaseValue, endPoint, null, null), + Boolean.TRUE); + } + + endPoint.setEvent("queued"); + assertEquals( + "queued Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "queued Event returns false for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("started"); + assertEquals( + "started Event returns true for Phase Started", + isRunMethod.invoke(Phase.STARTED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "started Event returns false for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("completed"); + assertEquals( + "completed Event returns true for Phase Completed", + isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "completed Event returns false for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("finalized"); + assertEquals( + "finalized Event returns true for Phase Finalized", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.TRUE); + assertEquals( + "finalized Event returns true for Phase Queued", + isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), + Boolean.FALSE); + + endPoint.setEvent("failed"); + assertEquals( + "failed Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + assertEquals( + "failed Event returns false for Phase Finalized and success status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), + Boolean.FALSE); + assertEquals( + "failed Event returns true for Phase Finalized and success failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), + Boolean.TRUE); + assertEquals( + "failed Event returns false for Phase not Finalized and success failure", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), + Boolean.FALSE); + + endPoint.setEvent("failedAndFirstSuccess"); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and no status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and failed status", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), + Boolean.TRUE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", + isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), + Boolean.FALSE); + assertEquals( + "failedAndFirstSuccess Event returns false for Phase not Finalized", + isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), + Boolean.FALSE); } - endPoint.setEvent("queued"); - assertEquals("queued Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.TRUE); - assertEquals("queued Event returns false for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.FALSE); - - endPoint.setEvent("started"); - assertEquals("started Event returns true for Phase Started", - isRunMethod.invoke(Phase.STARTED, endPoint, null, null), Boolean.TRUE); - assertEquals("started Event returns false for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("completed"); - assertEquals("completed Event returns true for Phase Completed", - isRunMethod.invoke(Phase.COMPLETED, endPoint, null, null), Boolean.TRUE); - assertEquals("completed Event returns false for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("finalized"); - assertEquals("finalized Event returns true for Phase Finalized", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.TRUE); - assertEquals("finalized Event returns true for Phase Queued", - isRunMethod.invoke(Phase.QUEUED, endPoint, null, null), Boolean.FALSE); - - - endPoint.setEvent("failed"); - assertEquals("failed Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failed Event returns false for Phase Finalized and success status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failed Event returns true for Phase Finalized and success failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failed Event returns false for Phase not Finalized and success failure", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.FAILURE, null), Boolean.FALSE); - - endPoint.setEvent("failedAndFirstSuccess"); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, null, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and no previous status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, null), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and no previous status and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, null), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and failed status", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.FAILURE, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns true for Phase Finalized and success status with previous status of failure", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.TRUE); - assertEquals("failedAndFirstSuccess Event returns false for Phase Finalized and success status with previous status of success", - isRunMethod.invoke(Phase.FINALIZED, endPoint, Result.SUCCESS, Result.SUCCESS), Boolean.FALSE); - assertEquals("failedAndFirstSuccess Event returns false for Phase not Finalized", - isRunMethod.invoke(Phase.COMPLETED, endPoint, Result.SUCCESS, Result.FAILURE), Boolean.FALSE); - } - - @Test - public void testRunNoProperty() { - when(run.getParent()).thenReturn(job); - - Phase.STARTED.handle(run, listener, 0L); - - verify(job).getProperty(HudsonNotificationProperty.class); - verifyNoInteractions(listener, endpoint, property); - } - - @Test - public void testRunNoPreviousRunUrlNull() { - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - - Phase.STARTED.handle(run, listener, 0L); - - verify(run).getPreviousCompletedBuild(); - verifyNoInteractions(listener); - } - - @Test - public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(run.getEnvironment(listener)).thenReturn(environment); - when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); - when(urlInfo.getUrlType()).thenReturn(PUBLIC); - when(environment.expand("$someUrl")).thenReturn("$someUrl"); - when(listener.getLogger()).thenReturn(logger); - - Phase.STARTED.handle(run, listener, 0L); - - verify(logger).printf("Ignoring sending notification due to unresolved variable: %s%n", "url '$someUrl'"); - verify(run).getPreviousCompletedBuild(); - } - - @Test - public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedException { - byte[] data = "data".getBytes(); - try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { - jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); - - Protocol httpProtocolSpy = spy(Protocol.HTTP); - when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); - doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); - - Format jsonFormatSpy = spy(Format.JSON); - JobState jobState = new JobState(); - when(endpoint.getFormat()).thenReturn(jsonFormatSpy); - doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); - assertEquals(data, jsonFormatSpy.serialize(jobState)); - - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(endpoint.getBranch()).thenReturn("branchName"); - when(run.getEnvironment(listener)).thenReturn(environment); - when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); - when(urlInfo.getUrlType()).thenReturn(PUBLIC); - when(environment.expand("$someUrl")).thenReturn("expandedUrl"); - when(environment.containsKey("BRANCH_NAME")).thenReturn(true); - when(environment.get("BRANCH_NAME")).thenReturn("branchName"); - when(listener.getLogger()).thenReturn(logger); - when(endpoint.getTimeout()).thenReturn(42); - - Phase.STARTED.handle(run, listener, 1L); - - verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); - verify(httpProtocolSpy).send("expandedUrl", data, 42, false); - verify(run).getPreviousCompletedBuild(); + @Test + public void testRunNoProperty() { + when(run.getParent()).thenReturn(job); + + Phase.STARTED.handle(run, listener, 0L); + + verify(job).getProperty(HudsonNotificationProperty.class); + verifyNoInteractions(listener, endpoint, property); } - } - - @Test - public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedException { - byte[] data = "data".getBytes(); - try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); - MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { - jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); - jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); - utilsMockedStatic.when(() -> Utils.getSecretUrl("credentialsId", jenkins)).thenReturn("$secretUrl"); - - Protocol httpProtocolSpy = spy(Protocol.HTTP); - when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); - doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); - - Format jsonFormatSpy = spy(Format.JSON); - JobState jobState = new JobState(); - when(endpoint.getFormat()).thenReturn(jsonFormatSpy); - doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); - assertEquals(data, jsonFormatSpy.serialize(jobState)); - - when(run.getParent()).thenReturn(job); - when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); - when(property.getEndpoints()).thenReturn(asList(endpoint)); - when(endpoint.getUrlInfo()).thenReturn(urlInfo); - when(endpoint.getBranch()).thenReturn(".*"); - when(run.getEnvironment(listener)).thenReturn(environment); - when(job.getParent()).thenReturn(jenkins); - when(urlInfo.getUrlOrId()).thenReturn("credentialsId"); - when(urlInfo.getUrlType()).thenReturn(SECRET); - when(environment.expand("$secretUrl")).thenReturn("secretUrl"); - when(listener.getLogger()).thenReturn(logger); - when(endpoint.getTimeout()).thenReturn(42); - - Phase.STARTED.handle(run, listener, 1L); - - verify(logger).printf( "Notifying endpoint with %s%n","credentials id 'credentialsId'"); - verify(httpProtocolSpy).send("secretUrl", data, 42, false); - verify(run).getPreviousCompletedBuild(); + + @Test + public void testRunNoPreviousRunUrlNull() { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + + Phase.STARTED.handle(run, listener, 0L); + + verify(run).getPreviousCompletedBuild(); + verifyNoInteractions(listener); + } + + @Test + public void testRunNoPreviousRunUrlTypePublicUnresolvedUrl() throws IOException, InterruptedException { + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("$someUrl"); + when(listener.getLogger()).thenReturn(logger); + + Phase.STARTED.handle(run, listener, 0L); + + verify(logger).printf("Ignoring sending notification due to unresolved variable: %s%n", "url '$someUrl'"); + verify(run).getPreviousCompletedBuild(); + } + + @Test + public void testRunPreviousRunUrlTypePublic() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn("branchName"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(urlInfo.getUrlOrId()).thenReturn("$someUrl"); + when(urlInfo.getUrlType()).thenReturn(PUBLIC); + when(environment.expand("$someUrl")).thenReturn("expandedUrl"); + when(environment.containsKey("BRANCH_NAME")).thenReturn(true); + when(environment.get("BRANCH_NAME")).thenReturn("branchName"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getTimeout()).thenReturn(42); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf("Notifying endpoint with %s%n", "url 'expandedUrl'"); + verify(httpProtocolSpy).send("expandedUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } + } + + @Test + public void testRunPreviousRunUrlTypeSecret() throws IOException, InterruptedException { + byte[] data = "data".getBytes(); + try (MockedStatic jenkinsMockedStatic = mockStatic(Jenkins.class); + MockedStatic utilsMockedStatic = mockStatic(Utils.class)) { + jenkinsMockedStatic.when(Jenkins::getInstanceOrNull).thenReturn(jenkins); + jenkinsMockedStatic.when(Jenkins::getInstance).thenReturn(jenkins); + utilsMockedStatic + .when(() -> Utils.getSecretUrl("credentialsId", jenkins)) + .thenReturn("$secretUrl"); + + Protocol httpProtocolSpy = spy(Protocol.HTTP); + when(endpoint.getProtocol()).thenReturn(httpProtocolSpy); + doNothing().when(httpProtocolSpy).send(anyString(), any(byte[].class), anyInt(), anyBoolean()); + + Format jsonFormatSpy = spy(Format.JSON); + JobState jobState = new JobState(); + when(endpoint.getFormat()).thenReturn(jsonFormatSpy); + doReturn(data).when(jsonFormatSpy).serialize(isA(JobState.class)); + assertEquals(data, jsonFormatSpy.serialize(jobState)); + + when(run.getParent()).thenReturn(job); + when(job.getProperty(HudsonNotificationProperty.class)).thenReturn(property); + when(property.getEndpoints()).thenReturn(asList(endpoint)); + when(endpoint.getUrlInfo()).thenReturn(urlInfo); + when(endpoint.getBranch()).thenReturn(".*"); + when(run.getEnvironment(listener)).thenReturn(environment); + when(job.getParent()).thenReturn(jenkins); + when(urlInfo.getUrlOrId()).thenReturn("credentialsId"); + when(urlInfo.getUrlType()).thenReturn(SECRET); + when(environment.expand("$secretUrl")).thenReturn("secretUrl"); + when(listener.getLogger()).thenReturn(logger); + when(endpoint.getTimeout()).thenReturn(42); + + Phase.STARTED.handle(run, listener, 1L); + + verify(logger).printf("Notifying endpoint with %s%n", "credentials id 'credentialsId'"); + verify(httpProtocolSpy).send("secretUrl", data, 42, false); + verify(run).getPreviousCompletedBuild(); + } } - } } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java index bff0ef7..abbea3a 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/ProtocolTest.java @@ -26,18 +26,6 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.io.CharStreams; -import junit.framework.TestCase; -import org.eclipse.jetty.ee8.servlet.ServletContextHandler; -import org.eclipse.jetty.ee8.servlet.ServletHolder; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; - -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -46,211 +34,221 @@ import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import junit.framework.TestCase; +import org.eclipse.jetty.ee8.servlet.ServletContextHandler; +import org.eclipse.jetty.ee8.servlet.ServletHolder; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; /** * @author Kohsuke Kawaguchi */ public class ProtocolTest extends TestCase { - static class Request { - private final String url; - private final String method; - private final String body; - private final String userInfo; - - Request(HttpServletRequest request) throws IOException { - this.url = request.getRequestURL().toString(); - this.method = request.getMethod(); - this.body = CharStreams.toString(request.getReader()); - String auth = request.getHeader("Authorization"); - this.userInfo = (null == auth) - ? null - : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; - } + static class Request { + private final String url; + private final String method; + private final String body; + private final String userInfo; + + Request(HttpServletRequest request) throws IOException { + this.url = request.getRequestURL().toString(); + this.method = request.getMethod(); + this.body = CharStreams.toString(request.getReader()); + String auth = request.getHeader("Authorization"); + this.userInfo = + (null == auth) ? null : new String(Base64.getDecoder().decode(auth.split(" ")[1])) + "@"; + } - Request(String url, String method, String body) { - this.url = url; - this.method = method; - this.body = body; - this.userInfo = null; - } + Request(String url, String method, String body) { + this.url = url; + this.method = method; + this.body = body; + this.userInfo = null; + } - @Override - public int hashCode() { - return Objects.hashCode(url, method, body); - } + @Override + public int hashCode() { + return Objects.hashCode(url, method, body); + } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Request)) { - return false; - } - Request other = (Request) obj; - return Objects.equal(url, other.url) - && Objects.equal(method, other.method) - && Objects.equal(body, other.body); - } + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Request)) { + return false; + } + Request other = (Request) obj; + return Objects.equal(url, other.url) + && Objects.equal(method, other.method) + && Objects.equal(body, other.body); + } - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("url", url) - .add("method", method) - .add("body", body) - .toString(); - } + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("url", url) + .add("method", method) + .add("body", body) + .toString(); + } - public String getUrl() { - return url; - } + public String getUrl() { + return url; + } - public String getUrlWithAuthority() { - if (null == userInfo) { - // Detect possible bug: userInfo never moved from URI to Authorization header - return null; - } - else { - return url.replaceFirst("^http://", "http://" + userInfo); - } + public String getUrlWithAuthority() { + if (null == userInfo) { + // Detect possible bug: userInfo never moved from URI to Authorization header + return null; + } else { + return url.replaceFirst("^http://", "http://" + userInfo); + } + } } - } - static class RecordingServlet extends HttpServlet { - private final BlockingQueue requests; + static class RecordingServlet extends HttpServlet { + private final BlockingQueue requests; - public RecordingServlet(BlockingQueue requests) { - this.requests = requests; - } + public RecordingServlet(BlockingQueue requests) { + this.requests = requests; + } - @Override - protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) - throws ServletException, IOException { + @Override + protected void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse) + throws ServletException, IOException { - Request request = new Request(httpRequest); - try { - requests.put(request); - } catch (InterruptedException e) { - throw new ServletException(e); - } + Request request = new Request(httpRequest); + try { + requests.put(request); + } catch (InterruptedException e) { + throw new ServletException(e); + } - doPost(request, httpResponse); - } + doPost(request, httpResponse); + } - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { - // noop + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + // noop + } } - } - static class RedirectHandler extends RecordingServlet { - private final String redirectURI; + static class RedirectHandler extends RecordingServlet { + private final String redirectURI; + + RedirectHandler(BlockingQueue requests, String redirectURI) { + super(requests); + this.redirectURI = redirectURI; + } - RedirectHandler(BlockingQueue requests, String redirectURI) { - super(requests); - this.redirectURI = redirectURI; + @Override + protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { + httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); + httpResponse.setHeader("Location", redirectURI); + } } - @Override - protected void doPost(Request request, HttpServletResponse httpResponse) throws IOException { - httpResponse.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT); - httpResponse.setHeader("Location", redirectURI); + private List servers; + + interface UrlFactory { + String getUrl(String path); } - } - private List servers; + private UrlFactory startServer(Servlet servlet, String path) throws Exception { + return startSecureServer(servlet, path, ""); + } - interface UrlFactory { - String getUrl(String path); - } + private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { + Server server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.setConnectors(new Connector[] {connector}); - private UrlFactory startServer(Servlet servlet, String path) throws Exception { - return startSecureServer(servlet, path, ""); - } + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + context.addServlet(new ServletHolder(servlet), path); + server.setHandler(context); - private UrlFactory startSecureServer(Servlet servlet, String path, String authority) throws Exception { - Server server = new Server(); - ServerConnector connector = new ServerConnector(server); - server.setConnectors(new Connector[] {connector}); + server.start(); + servers.add(server); - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - context.addServlet(new ServletHolder(servlet), path); - server.setHandler(context); + if (!authority.isEmpty()) { + authority += "@"; + } - server.start(); - servers.add(server); + final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); + return new UrlFactory() { + @Override + public String getUrl(String path) { + try { + return new URL(serverUrl, path).toExternalForm(); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + }; + } - if (!authority.isEmpty()) { - authority += "@"; + @Override + public void setUp() throws Exception { + servers = new LinkedList<>(); } - final URL serverUrl = new URL(String.format("http://%slocalhost:%d", authority, connector.getLocalPort())); - return new UrlFactory() { - public String getUrl(String path) { - try { - return new URL(serverUrl, path).toExternalForm(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(e); + @Override + public void tearDown() throws Exception { + for (Server server : servers) { + server.stop(); } - } - }; - } - - @Override - public void setUp() throws Exception { - servers = new LinkedList<>(); - } - - @Override - public void tearDown() throws Exception { - for (Server server : servers) { - server.stop(); } - } - public void testHttpPost() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPost() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes(), 30000, true); - assertEquals(new Request(uri, "POST", "Hello"), requests.take()); - assertTrue(requests.isEmpty()); - } + assertEquals(new Request(uri, "POST", "Hello"), requests.take()); + assertTrue(requests.isEmpty()); + } - public void testHttpPostWithBasicAuth() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPostWithBasicAuth() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); + UrlFactory urlFactory = startSecureServer(new RecordingServlet(requests), "/realpath", "fred:foo"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = urlFactory.getUrl("/realpath"); - Protocol.HTTP.send(uri, "Hello".getBytes(),30000, true); + String uri = urlFactory.getUrl("/realpath"); + Protocol.HTTP.send(uri, "Hello".getBytes(), 30000, true); - Request theRequest = requests.take(); - assertTrue(requests.isEmpty()); - assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); - } + Request theRequest = requests.take(); + assertTrue(requests.isEmpty()); + assertEquals(new Request(uri, "POST", "Hello").getUrl(), theRequest.getUrlWithAuthority()); + } - public void testHttpPostWithRedirects() throws Exception { - BlockingQueue requests = new LinkedBlockingQueue(); + public void testHttpPostWithRedirects() throws Exception { + BlockingQueue requests = new LinkedBlockingQueue(); - UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); + UrlFactory urlFactory = startServer(new RecordingServlet(requests), "/realpath"); - String redirectUri = urlFactory.getUrl("/realpath"); - UrlFactory redirectorUrlFactory = startServer(new RedirectHandler(requests, redirectUri), "/path"); + String redirectUri = urlFactory.getUrl("/realpath"); + UrlFactory redirectorUrlFactory = startServer(new RedirectHandler(requests, redirectUri), "/path"); - assertTrue(requests.isEmpty()); + assertTrue(requests.isEmpty()); - String uri = redirectorUrlFactory.getUrl("/path"); - Protocol.HTTP.send(uri, "RedirectMe".getBytes(),30000, true); + String uri = redirectorUrlFactory.getUrl("/path"); + Protocol.HTTP.send(uri, "RedirectMe".getBytes(), 30000, true); - assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); - assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); - assertTrue(requests.isEmpty()); - } + assertEquals(new Request(uri, "POST", "RedirectMe"), requests.take()); + assertEquals(new Request(redirectUri, "POST", "RedirectMe"), requests.take()); + assertTrue(requests.isEmpty()); + } } diff --git a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java index 8f80020..d2288b6 100644 --- a/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java +++ b/src/test/java/com/tikal/hudson/plugins/notification/test/HostnamePortTest.java @@ -13,12 +13,10 @@ */ package com.tikal.hudson.plugins.notification.test; +import com.tikal.hudson.plugins.notification.HostnamePort; import junit.framework.Assert; - import org.junit.Test; -import com.tikal.hudson.plugins.notification.HostnamePort; - public class HostnamePortTest { @Test