diff --git a/Jenkinsfile b/Jenkinsfile index 09032da7..d9d0b0b2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,6 +6,7 @@ buildPlugin( forkCount: '1C', // run this number of tests in parallel for faster feedback. If the number terminates with a 'C', the value will be multiplied by the number of available CPU cores useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests configurations: [ + [platform: 'linux', jdk: 17], [platform: 'linux', jdk: 21], [platform: 'windows', jdk: 17], ]) diff --git a/pom.xml b/pom.xml index d042e81e..7f2809cc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 4.86 + 5.4 @@ -52,8 +52,9 @@ jenkinsci/${project.artifactId}-plugin 5.2.7 4.7.2 - - 2.440.3 + + 2.479 + ${jenkins.baseline}.3 false @@ -61,8 +62,8 @@ io.jenkins.tools.bom - bom-2.440.x - 3234.v5ca_5154341ef + bom-${jenkins.baseline}.x + 3875.v1df09947cde6 pom import @@ -71,11 +72,6 @@ atlassian-plugins-core 5.3.12 - - org.json - json - 20240303 - @@ -234,6 +230,10 @@ io.jenkins.plugins joda-time-api + + io.jenkins.plugins + json-api + org.apache.maven maven-artifact diff --git a/src/main/java/hudson/plugins/jira/CredentialsHelper.java b/src/main/java/hudson/plugins/jira/CredentialsHelper.java index d3397b60..e8809df7 100644 --- a/src/main/java/hudson/plugins/jira/CredentialsHelper.java +++ b/src/main/java/hudson/plugins/jira/CredentialsHelper.java @@ -12,6 +12,7 @@ import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.Descriptor.FormException; import hudson.model.Item; import hudson.model.Queue; import hudson.model.queue.Tasks; @@ -53,7 +54,7 @@ protected static StandardUsernamePasswordCredentials lookupSystemCredentials( } protected static StandardUsernamePasswordCredentials migrateCredentials( - @NonNull String username, String password, @CheckForNull URL url) { + @NonNull String username, String password, @CheckForNull URL url) throws FormException { List credentials = CredentialsMatchers.filter( CredentialsProvider.lookupCredentials( StandardUsernamePasswordCredentials.class, diff --git a/src/main/java/hudson/plugins/jira/JiraSite.java b/src/main/java/hudson/plugins/jira/JiraSite.java index b95b6a93..9b6b96e2 100644 --- a/src/main/java/hudson/plugins/jira/JiraSite.java +++ b/src/main/java/hudson/plugins/jira/JiraSite.java @@ -34,6 +34,7 @@ import hudson.Util; import hudson.model.AbstractDescribableImpl; import hudson.model.Descriptor; +import hudson.model.Descriptor.FormException; import hudson.model.Item; import hudson.model.ItemGroup; import hudson.model.Job; @@ -306,7 +307,8 @@ public JiraSite( boolean updateJiraIssueForAllStatus, @CheckForNull String groupVisibility, @CheckForNull String roleVisibility, - boolean useHTTPAuth) { + boolean useHTTPAuth) + throws FormException { this( url, alternativeUrl, @@ -332,7 +334,8 @@ public JiraSite( boolean updateJiraIssueForAllStatus, String groupVisibility, String roleVisibility, - boolean useHTTPAuth) { + boolean useHTTPAuth) + throws FormException { this( url, alternativeUrl, @@ -646,8 +649,9 @@ public void setUpdateJiraIssueForAllStatus(boolean updateJiraIssueForAllStatus) } @SuppressWarnings("unused") - protected Object readResolve() { + protected Object readResolve() throws FormException { JiraSite jiraSite; + if (credentialsId == null && userName != null && password != null) { // Migrate credentials jiraSite = new JiraSite( url, diff --git a/src/test/java/com/atlassian/httpclient/apache/httpcomponents/ApacheAsyncHttpClientTest.java b/src/test/java/com/atlassian/httpclient/apache/httpcomponents/ApacheAsyncHttpClientTest.java index 5a33cbfa..405bda4f 100644 --- a/src/test/java/com/atlassian/httpclient/apache/httpcomponents/ApacheAsyncHttpClientTest.java +++ b/src/test/java/com/atlassian/httpclient/apache/httpcomponents/ApacheAsyncHttpClientTest.java @@ -10,25 +10,24 @@ import hudson.ProxyConfiguration; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Base64; import java.util.Date; import java.util.Optional; import java.util.concurrent.TimeUnit; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import jenkins.model.Jenkins; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.Content; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.util.Callback; import org.junit.After; import org.junit.Assert; import org.junit.Rule; @@ -151,7 +150,7 @@ public void simple_post_with_proxy() throws Exception { Assert.assertEquals("FOO", testHandler.postReceived); } - public class ProxyTestHandler extends AbstractHandler { + public static class ProxyTestHandler extends Handler.Abstract { String postReceived; @@ -164,55 +163,50 @@ public class ProxyTestHandler extends AbstractHandler { final String realm = "test_realm"; @Override - public void handle( - String target, - org.eclipse.jetty.server.Request jettyRequest, - HttpServletRequest request, - HttpServletResponse response) - throws IOException, ServletException { + public boolean handle( + org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response, Callback callback) + throws IOException { final String credentials = Base64.getEncoder().encodeToString((user + ":" + password).getBytes("UTF-8")); - jettyRequest.setHandled(true); - - String authorization = request.getHeader(HttpHeader.PROXY_AUTHORIZATION.asString()); + String authorization = request.getHeaders().get(HttpHeader.PROXY_AUTHORIZATION.asString()); if (authorization == null) { response.setStatus(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407); - response.setHeader(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + realm + "\""); - return; + response.getHeaders().add(HttpHeader.PROXY_AUTHENTICATE.asString(), "Basic realm=\"" + realm + "\""); + callback.succeeded(); + return true; } else { String prefix = "Basic "; if (authorization.startsWith(prefix)) { String attempt = authorization.substring(prefix.length()); if (!credentials.equals(attempt)) { - return; + callback.succeeded(); + return true; } } } if (StringUtils.equalsIgnoreCase("post", request.getMethod())) { - postReceived = IOUtils.toString(request.getReader()); + postReceived = Content.Source.asString(request, StandardCharsets.UTF_8); } - response.getWriter().write(CONTENT_RESPONSE); + Content.Sink.write(response, true, CONTENT_RESPONSE, callback); + return true; } } - public class TestHandler extends AbstractHandler { + public static class TestHandler extends Handler.Abstract { String postReceived; @Override - public void handle( - String target, - org.eclipse.jetty.server.Request jettyRequest, - HttpServletRequest request, - HttpServletResponse response) - throws IOException, ServletException { - jettyRequest.setHandled(true); + public boolean handle( + org.eclipse.jetty.server.Request request, org.eclipse.jetty.server.Response response, Callback callback) + throws IOException { if (StringUtils.equalsIgnoreCase("post", request.getMethod())) { - postReceived = IOUtils.toString(request.getReader()); + postReceived = Content.Source.asString(request, StandardCharsets.UTF_8); } - response.getWriter().write(CONTENT_RESPONSE); + Content.Sink.write(response, true, CONTENT_RESPONSE, callback); + return true; } } diff --git a/src/test/java/hudson/plugins/jira/CredentialsHelperTest.java b/src/test/java/hudson/plugins/jira/CredentialsHelperTest.java index b8b2612f..2044f951 100644 --- a/src/test/java/hudson/plugins/jira/CredentialsHelperTest.java +++ b/src/test/java/hudson/plugins/jira/CredentialsHelperTest.java @@ -13,6 +13,7 @@ import com.cloudbees.plugins.credentials.domains.DomainSpecification; import com.cloudbees.plugins.credentials.domains.HostnameSpecification; import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; +import hudson.model.Descriptor.FormException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -29,7 +30,7 @@ public class CredentialsHelperTest { public JenkinsRule r = new JenkinsRule(); @Test - public void lookupSystemCredentials() throws IOException { + public void lookupSystemCredentials() throws IOException, FormException { assertNull(CredentialsHelper.lookupSystemCredentials("nonexistent-credentials-id", null)); StandardUsernamePasswordCredentials c = @@ -41,7 +42,7 @@ public void lookupSystemCredentials() throws IOException { } @Test - public void lookupSystemCredentialsWithDomainRestriction() throws IOException { + public void lookupSystemCredentialsWithDomainRestriction() throws IOException, FormException { Domain domain = new Domain( "example", "test domain", @@ -56,7 +57,7 @@ public void lookupSystemCredentialsWithDomainRestriction() throws IOException { } @Test - public void migrateCredentials() throws MalformedURLException { + public void migrateCredentials() throws MalformedURLException, FormException { assertThat( CredentialsProvider.lookupStores(r.jenkins).iterator().next().getCredentials(Domain.global()), empty()); @@ -70,7 +71,7 @@ public void migrateCredentials() throws MalformedURLException { } @Test - public void migrateCredentialsWithExsitingCredentials() throws IOException { + public void migrateCredentialsWithExsitingCredentials() throws IOException, FormException { Domain domain = new Domain( "example", "test domain", diff --git a/src/test/java/hudson/plugins/jira/DescriptorImplTest.java b/src/test/java/hudson/plugins/jira/DescriptorImplTest.java index 5cd71416..6c8267c9 100644 --- a/src/test/java/hudson/plugins/jira/DescriptorImplTest.java +++ b/src/test/java/hudson/plugins/jira/DescriptorImplTest.java @@ -21,6 +21,7 @@ import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; +import hudson.model.Descriptor.FormException; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Item; @@ -60,7 +61,7 @@ public class DescriptorImplTest { JiraSite.Builder builder = spy(new JiraSite.Builder()); @Test - public void doFillCredentialsIdItems() throws IOException { + public void doFillCredentialsIdItems() throws IOException, FormException { MockFolder dummy = r.createFolder("dummy"); r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); diff --git a/src/test/java/hudson/plugins/jira/JiraSiteSecurity1029Test.java b/src/test/java/hudson/plugins/jira/JiraSiteSecurity1029Test.java index 06acae62..8aff6474 100644 --- a/src/test/java/hudson/plugins/jira/JiraSiteSecurity1029Test.java +++ b/src/test/java/hudson/plugins/jira/JiraSiteSecurity1029Test.java @@ -13,6 +13,9 @@ import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; import hudson.model.Item; import hudson.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URI; import java.net.URL; @@ -20,17 +23,14 @@ import java.util.Arrays; import java.util.Base64; import java.util.HashMap; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; import net.sf.json.JSONObject; +import org.eclipse.jetty.ee9.servlet.DefaultServlet; +import org.eclipse.jetty.ee9.servlet.ServletContextHandler; +import org.eclipse.jetty.ee9.servlet.ServletHolder; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; import org.htmlunit.HttpMethod; import org.htmlunit.Page; import org.htmlunit.WebRequest; diff --git a/src/test/java/hudson/plugins/jira/JiraSiteTest.java b/src/test/java/hudson/plugins/jira/JiraSiteTest.java index cb63c2bb..10bca2c2 100644 --- a/src/test/java/hudson/plugins/jira/JiraSiteTest.java +++ b/src/test/java/hudson/plugins/jira/JiraSiteTest.java @@ -24,6 +24,7 @@ import com.cloudbees.plugins.credentials.domains.DomainSpecification; import com.cloudbees.plugins.credentials.domains.HostnameSpecification; import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; +import hudson.model.Descriptor.FormException; import hudson.model.FreeStyleProject; import hudson.model.Job; import hudson.plugins.jira.model.JiraIssue; @@ -62,7 +63,7 @@ public void init() throws MalformedURLException { } @Test - public void createSessionWithProvidedCredentials() { + public void createSessionWithProvidedCredentials() throws FormException { JiraSite site = new JiraSite( validPrimaryUrl, null, @@ -82,7 +83,7 @@ public void createSessionWithProvidedCredentials() { @Test @Issue("JENKINS-64083") - public void createSessionWithGlobalCredentials() { + public void createSessionWithGlobalCredentials() throws FormException { JiraSite site = new JiraSite( validPrimaryUrl, null, @@ -101,7 +102,7 @@ public void createSessionWithGlobalCredentials() { } @Test - public void createSessionReturnsNullIfCredentialsIsNull() { + public void createSessionReturnsNullIfCredentialsIsNull() throws FormException { JiraSite site = new JiraSite( validPrimaryUrl, null, @@ -120,7 +121,7 @@ public void createSessionReturnsNullIfCredentialsIsNull() { } @Test - public void deserializeMigrateCredentials() throws MalformedURLException { + public void deserializeMigrateCredentials() throws MalformedURLException, FormException { JiraSiteOld old = new JiraSiteOld( validPrimaryUrl, null, ANY_USER, ANY_PASSWORD, false, false, null, false, null, null, true); @@ -153,7 +154,7 @@ public void deserializeMigrateCredentials() throws MalformedURLException { } @Test - public void deserializeNormal() throws IOException { + public void deserializeNormal() throws IOException, FormException { Domain domain = new Domain( "example", "test domain", @@ -207,7 +208,8 @@ private static class JiraSiteOld extends JiraSite { boolean updateJiraIssueForAllStatus, String groupVisibility, String roleVisibility, - boolean useHTTPAuth) { + boolean useHTTPAuth) + throws FormException { super( url, alternativeUrl, @@ -226,7 +228,7 @@ private static class JiraSiteOld extends JiraSite { @Test @WithoutJenkins - public void alternativeURLNotNull() { + public void alternativeURLNotNull() throws FormException { JiraSite site = new JiraSite( validPrimaryUrl, exampleOrg,