Merge branch 'stable-2.13'
* stable-2.13:
Replace Atlassian Library with vanilla HTTP calls
Cleanup wsdl stuff, no longer used with Rest-API
Change-Id: I4935818816d59ef00d2614df66094cd54779b419
diff --git a/BUILD b/BUILD
index a17d7dc..8762bf6 100644
--- a/BUILD
+++ b/BUILD
@@ -14,10 +14,6 @@
],
deps = [
"//plugins/its-base",
- "@atlassian_httpclient_apache_httpcomponents//jar",
- "@atlassian_util_concurrent//jar",
- "@jira_rest_java_client_api//jar",
- "@jira_rest_java_client_core//jar",
],
)
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
deleted file mode 100644
index aac67ce..0000000
--- a/external_plugin_deps.bzl
+++ /dev/null
@@ -1,214 +0,0 @@
-load("//tools/bzl:maven_jar.bzl", "maven_jar", "MAVEN_LOCAL")
-
-ATLASSIAN_REPO = 'https://maven.atlassian.com/repository/public/'
-
-def external_plugin_deps():
- maven_jar(
- name = 'jira_rest_java_client_core',
- artifact = 'com.atlassian.jira:jira-rest-java-client-core:3.0.0',
- deps = [
- '@atlassian_httpclient_apache_httpcomponents//jar',
- '@atlassian_util_concurrent//jar',
- '@httpmime//jar',
- '@jersey_client//jar',
- '@jersey_json//jar',
- '@jira_rest_java_client_api//jar',
- ],
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'atlassian_httpclient_apache_httpcomponents',
- artifact = 'com.atlassian.httpclient:atlassian-httpclient-apache-httpcomponents:0.13.2',
- deps = [
- '@atlassian_event//jar',
- '@atlassian_httpclient_api//jar',
- '@httpasyncclient//jar',
- '@httpasyncclient_cache//jar',
- '@httpclient_cache//jar',
- '@httpcore//jar',
- '@httpcore_nio//jar',
- '@sal_api//jar',
- '@log_api//jar',
- '@spring_context//jar',
- ],
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'spring_context',
- artifact = 'org.springframework:spring-context:2.5.6',
- deps = [
- '@aopalliance//jar',
- '@spring_core//jar',
- '@spring_beans//jar',
- ],
- sha1 = '983416e612875bdcf877dad4c9d5d77ae37e06ee',
- exclude = ["META-INF/license.txt"],
- )
-
- maven_jar(
- name = 'spring_beans',
- artifact = 'org.springframework:spring-beans:2.5.6',
- sha1 = '449ea46b27426eb846611a90b2fb8b4dcf271191',
- exclude = ["META-INF/license.txt"],
- )
-
- maven_jar(
- name = 'spring_core',
- artifact = 'org.springframework:spring-core:2.5.6',
- sha1 = 'c450bc49099430e13d21548d1e3d1a564b7e35e9',
- exclude = ["META-INF/license.txt"],
- )
-
- maven_jar(
- name = 'httpclient_cache',
- artifact = 'org.apache.httpcomponents:httpclient-cache:4.4.1',
- sha1 = '6c9ba9c38bca8742d5745bb27bcd4b9c7542ea24',
- deps = [
- '@httpclient//jar:neverlink',
- ],
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'httpasyncclient_cache',
- artifact = 'org.apache.httpcomponents:httpasyncclient-cache:4.1.1',
- sha1 = '93601cc6fe8f4b042260c6cda9d52fffb62ae31a',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name ='atlassian_event',
- artifact = 'com.atlassian.event:atlassian-event:2.2.0',
- sha1 = 'c7a1b83e92fdb05e02ba717fbce3b7551ce945f7',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'sal_api',
- artifact = 'com.atlassian.sal:sal-api:2.7.0',
- sha1 = 'b0d49ec14b5c823c24821bfbc8cd618525390a1b',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'atlassian_httpclient_api',
- artifact = 'com.atlassian.httpclient:atlassian-httpclient-api:0.13.2',
- deps = [
- '@atlassian_httpclient_spi//jar',
- ],
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'atlassian_httpclient_spi',
- artifact = 'com.atlassian.httpclient:atlassian-httpclient-spi:0.13.2',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'atlassian_util_concurrent',
- artifact = 'com.atlassian.util.concurrent:atlassian-util-concurrent:2.4.0-M9',
- sha1 = 'e8469a31d1999f5459a2c5a61234755f625fc3f7',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'jira_rest_java_client_api',
- artifact = 'com.atlassian.jira:jira-rest-java-client-api:3.0.0',
- repository = ATLASSIAN_REPO,
- )
-
- maven_jar(
- name = 'jersey_client',
- artifact = 'com.sun.jersey:jersey-client:1.5',
- deps = [
- '@jersey_core//jar',
- ],
- sha1 = '4dc285245a495c2682b743c81cb67a7d1e8b2e7d',
- )
-
- maven_jar(
- name = 'jersey_core',
- artifact = 'com.sun.jersey:jersey-core:1.5',
- sha1 = '955fa871051acd23841ff75087b190278228920a',
- )
-
- maven_jar(
- name = 'jersey_json',
- artifact = 'com.sun.jersey:jersey-json:1.5',
- deps = [
- '@jackson_core_asl//jar',
- '@jackson_mapper_asl//jar',
- '@jackson_xc//jar',
- '@jaxb_impl//jar',
- '@jettison//jar',
- ],
- sha1 = '8d77a3d4277016277cb85b98c179a2a7e9ec6dfb',
- )
-
- maven_jar(
- name = 'jettison',
- artifact = 'org.codehaus.jettison:jettison:1.1',
- deps = [
- '@stax_api_1//jar',
- ],
- sha1 = '1a01a2a1218fcf9faa2cc2a6ced025bdea687262',
- )
-
- maven_jar(
- name = 'stax_api_1',
- artifact = 'stax:stax-api:1.0.1',
- sha1 = '49c100caf72d658aca8e58bd74a4ba90fa2b0d70',
- attach_source = False,
- )
-
- maven_jar(
- name = 'jaxb_impl',
- artifact = 'com.sun.xml.bind:jaxb-impl:2.2.3',
- deps = [
- '@jaxb_api//jar',
- ],
- sha1 = '565307a5e9c563666418e70b22c07886104e6ba7',
- )
-
- maven_jar(
- name = 'jaxb_api',
- artifact = 'javax.xml.bind:jaxb-api:2.2.2',
- deps = [
- '@stax_api_2//jar',
- ],
- sha1 = 'aeb3021ca93dde265796d82015beecdcff95bf09',
- )
-
- maven_jar(
- name = 'stax_api_2',
- artifact = 'javax.xml.stream:stax-api:1.0-2',
- sha1 = 'd6337b0de8b25e53e81b922352fbea9f9f57ba0b',
- attach_source = False,
- )
-
- maven_jar(
- name = 'jackson_core_asl',
- artifact = 'org.codehaus.jackson:jackson-core-asl:1.5.5',
- sha1 = 'beb1ba1c1b84c2f2c54b8f1ce63224ca0f98334d',
- )
-
- maven_jar(
- name = 'jackson_mapper_asl',
- artifact = 'org.codehaus.jackson:jackson-mapper-asl:1.5.5',
- sha1 = '908a1589e4ef52dc81252bc18d678bd232423c10',
- )
-
- maven_jar(
- name = 'jackson_jaxrs',
- artifact = 'org.codehaus.jackson:jackson-jaxrs:1.5.5',
- sha1 = '2141d77b65d5bb36a2cdafb1010b8704c3fd4585',
- )
-
- maven_jar(
- name = 'jackson_xc',
- artifact = 'org.codehaus.jackson:jackson-xc:1.5.5',
- sha1 = '58811cfa31b5355d0146aae33b3fc3fee661d5bc',
- )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
index e0c8bea..c0340a2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/InitJira.java
@@ -14,16 +14,12 @@
package com.googlesource.gerrit.plugins.its.jira;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.pgm.init.api.AllProjectsConfig;
import com.google.gerrit.pgm.init.api.AllProjectsNameOnInitProvider;
+import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.Section;
-import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -32,10 +28,12 @@
import org.eclipse.jgit.errors.ConfigInvalidException;
+import java.io.IOException;
+import java.util.Arrays;
+
/** Initialize the GitRepositoryManager configuration section. */
@Singleton
class InitJira extends InitIts {
- private static final String COMMENT_LINK_SECTION = "commentLink";
private final String pluginName;
private final Section.Factory sections;
private final InitFlags flags;
@@ -125,7 +123,7 @@
new JiraClient(jiraUrl, jiraUsername, jiraPassword).sysInfo().getVersion();
ui.message("[OK]\n");
return true;
- } catch (URISyntaxException e) {
+ } catch (IOException e) {
ui.message("*FAILED* (%s)\n", e.toString());
return false;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
index 348c135..c0d7376 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2013 The Android Open Source Project
+// Copyright (C) 2013 - 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,133 +14,145 @@
package com.googlesource.gerrit.plugins.its.jira;
-import com.atlassian.jira.rest.client.api.IssueRestClient;
-import com.atlassian.jira.rest.client.api.JiraRestClient;
-import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
-import com.atlassian.jira.rest.client.api.RestClientException;
-import com.atlassian.jira.rest.client.api.domain.Comment;
-import com.atlassian.jira.rest.client.api.domain.Issue;
-import com.atlassian.jira.rest.client.api.domain.ServerInfo;
-import com.atlassian.jira.rest.client.api.domain.Transition;
-import com.atlassian.jira.rest.client.api.domain.input.TransitionInput;
-import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
-import com.atlassian.util.concurrent.Promise;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+
+import com.google.gson.Gson;
+
import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraComment;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraIssue;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraProject;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraRestApi;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraRestApiProvider;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraServerInfo;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraTransition;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.List;
-/**
- * Jira Rest Client.
- */
public class JiraClient {
private static final Logger log = LoggerFactory.getLogger(JiraClient.class);
- private JiraRestClient client = null;
+ private final JiraRestApiProvider apiBuilder;
+ private final Gson gson;
/**
- * @param url jira url
+ * @param url jira url
* @param user username of the jira user
* @param pass password of the jira user
- * @throws URISyntaxException
*/
- public JiraClient(String url, String user, String pass) throws URISyntaxException {
- URI jiraUri = new URI(url);
- log.debug("Trying to access Jira at " + jiraUri);
- JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
- client = factory.createWithBasicHttpAuthentication(jiraUri, user, pass);
- log.debug("Initialized jira client " + client);
- }
-
- /**
- * @param issueKey Issue id
- * @return Issueobjekt by issue id
- * @throws RestClientException
- */
- public Issue getIssue(String issueKey) throws RestClientException {
- IssueRestClient issueClient = this.client.getIssueClient();
- return issueClient.getIssue(issueKey).claim();
+ public JiraClient(String url, String user, String pass)
+ throws MalformedURLException {
+ this.apiBuilder = new JiraRestApiProvider(url, user, pass);
+ this.gson = new Gson();
}
/**
* @param issueKey Jira Issue key
* @return true if issue exists
*/
- public boolean issueExists(String issueKey) throws RestClientException {
- boolean ret = true;
- try{
- getIssue(issueKey);
- } catch (RestClientException e) {
- if (e.getStatusCode().get() == 404){
+ public boolean issueExists(String issueKey) throws IOException {
+ JiraRestApi<JiraIssue> api = apiBuilder.getIssue();
+
+ api.doGet("/" + issueKey, HTTP_OK,
+ new int[] {HTTP_NOT_FOUND, HTTP_FORBIDDEN});
+ Integer code = api.getResponseCode();
+ switch (code) {
+ case HTTP_OK:
+ return true;
+ case HTTP_NOT_FOUND:
log.error("Issue " + issueKey + " not found ");
- ret = false;
- } else {
- throw e;
- }
+ return false;
+ case HTTP_FORBIDDEN:
+ log.error("No permission to read Issue " + issueKey);
+ return false;
+ default:
+ // Cannot happen due to passCodes filter
+ throw new IOException(
+ "Unexpected HTTP code received:" + code.toString());
}
- return ret;
}
/**
* @param issueKey Jira Issue key
* @return Iterable of available transitions
- * @throws RestClientException
+ * @throws IOException
*/
- public Iterable<Transition> getTransitions(String issueKey) throws RestClientException {
- return client.getIssueClient().getTransitions(getIssue(issueKey)).claim();
+ public List<JiraTransition.Item> getTransitions(String issueKey)
+ throws IOException {
+
+ JiraRestApi<JiraTransition> api =
+ apiBuilder.get(JiraTransition.class, "/issue");
+ return Arrays.asList(
+ api.doGet("/" + issueKey + "/transitions", HTTP_OK).transitions);
}
/**
* @param issueKey Jira Issue key
- * @param comment Comment to be added
- * @throws RestClientException
+ * @param comment String to be added
+ * @throws IOException
*/
- public void addComment(String issueKey, Comment comment) throws RestClientException, URISyntaxException {
- log.debug("Trying to add comment for issue " + issueKey);
- Issue issue = getIssue(issueKey);
- URI issueUri;
- issueUri = new URI(issue.getSelf().toString() + "/comment/");
- IssueRestClient issueClient = client.getIssueClient();
- Promise<Void> promise = issueClient.addComment(issueUri, comment);
- promise.claim();
- log.debug("Comment added to issue " + issueKey);
+ public void addComment(String issueKey, String comment) throws IOException {
+
+ if (issueExists(issueKey)) {
+ log.debug("Trying to add comment for issue {}", issueKey);
+ apiBuilder.getIssue().doPost("/" + issueKey + "/comment",
+ gson.toJson(new JiraComment(comment)), HTTP_CREATED);
+ log.debug("Comment added to issue {}", issueKey);
+ } else {
+ log.error("Issue {} does not exist or no access permission", issueKey);
+ }
}
/**
- * @param issueKey Jira Issue key
- * @param transition Transition to perform
+ * @param issueKey Jira Issue key
+ * @param transition JiraTransition.Item to perform
* @return true if successful
*/
- public boolean doTransition(String issueKey, String transition) throws RestClientException, InvalidTransitionException {
- Transition t = getTransitionByName(getTransitions(issueKey), transition);
+ public boolean doTransition(String issueKey, String transition)
+ throws IOException, InvalidTransitionException {
+ log.debug("Making transition to {} for {}", transition, issueKey);
+ JiraTransition.Item t = getTransitionByName(issueKey, transition);
if (t == null) {
- throw new InvalidTransitionException("Action " + transition
- + " not executable on issue " + issueKey);
+ throw new InvalidTransitionException(
+ "Action " + transition + " not executable on issue " + issueKey);
}
- TransitionInput input;
- input = new TransitionInput(t.getId());
- log.debug("Setting transition input to: " + input.toString());
- client.getIssueClient().transition(getIssue(issueKey), input).claim();
- return true;
+ log.debug("Transition issue {} to '{}' ({})", issueKey, transition,
+ t.getId());
+ return apiBuilder.getIssue().doPost("/" + issueKey + "/transitions",
+ gson.toJson(new JiraTransition(t)), HTTP_NO_CONTENT);
}
/**
* @return Serverinformation of jira
*/
- public ServerInfo sysInfo() throws RestClientException {
- return client.getMetadataClient().getServerInfo().claim();
+ public JiraServerInfo sysInfo() throws IOException {
+ return apiBuilder.getServerInfo().doGet("", HTTP_OK);
}
- private Transition getTransitionByName(Iterable<Transition> transitions, String transition) {
- Transition ret = null;
- for (Transition t : transitions) {
+ /**
+ * @return List of all projects we have access to in jira
+ */
+ public JiraProject[] getProjects() throws IOException {
+ return apiBuilder.getProjects().doGet("", HTTP_OK);
+ }
+
+ private JiraTransition.Item getTransitionByName(String issueKey,
+ String transition) throws IOException {
+ for (JiraTransition.Item t : getTransitions(issueKey)) {
if (transition.equals(t.getName())) {
- ret = t;
- break;
+ return t;
}
}
- return ret;
+ return null;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
index fc76fc0..2f8da02 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
@@ -14,17 +14,21 @@
package com.googlesource.gerrit.plugins.its.jira;
-import com.atlassian.jira.rest.client.api.domain.Comment;
-import com.atlassian.jira.rest.client.api.domain.ServerInfo;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
+
+import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraProject;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraServerInfo;
+
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.Callable;
@@ -45,12 +49,16 @@
@Inject
public JiraItsFacade(@PluginName String pluginName,
- @GerritServerConfig Config cfg) {
+ @GerritServerConfig Config cfg) {
this.pluginName = pluginName;
try {
this.gerritConfig = cfg;
- ServerInfo info = client().sysInfo();
- log.info("Connected to JIRA at {}, reported version is {}", info.getBaseUri(), info.getVersion());
+ JiraServerInfo info = client().sysInfo();
+ log.info("Connected to JIRA at {}, reported version is {}",
+ info.getBaseUri(), info.getVersion());
+ for (JiraProject p : client().getProjects()) {
+ log.info("Found project: {} (key: {})", p.getName(), p.getKey());
+ }
} catch (Exception ex) {
log.warn("Jira is currently not available", ex);
}
@@ -59,33 +67,35 @@
@Override
public String healthCheck(final Check check) throws IOException {
- return execute(new Callable<String>(){
+ return execute(new Callable<String>() {
@Override
public String call() throws Exception {
- if (check.equals(Check.ACCESS))
- return healthCheckAccess();
- else
- return healthCheckSysinfo();
- }});
+ if (check.equals(Check.ACCESS)) return healthCheckAccess();
+ return healthCheckSysinfo();
+ }
+ });
}
@Override
- public void addComment(final String issueKey, final String comment) throws IOException {
+ public void addComment(final String issueKey, final String comment)
+ throws IOException {
- execute(new Callable<String>(){
+ execute(new Callable<String>() {
@Override
public String call() throws Exception {
log.debug("Adding comment {} to issue {}", comment, issueKey);
- client().addComment(issueKey, Comment.valueOf(comment));
+ client().addComment(issueKey, comment);
log.debug("Added comment {} to issue {}", comment, issueKey);
return issueKey;
- }});
+ }
+ });
}
@Override
- public void addRelatedLink(final String issueKey, final URL relatedUrl, String description)
- throws IOException {
- addComment(issueKey, "Related URL: " + createLinkForWebui(relatedUrl.toExternalForm(), description));
+ public void addRelatedLink(final String issueKey, final URL relatedUrl,
+ String description) throws IOException {
+ addComment(issueKey, "Related URL: "
+ + createLinkForWebui(relatedUrl.toExternalForm(), description));
}
@Override
@@ -98,12 +108,14 @@
log.debug("Performing action {} on issue {}", actionName, issueKey);
doPerformAction(issueKey, actionName);
return issueKey;
- }});
+ }
+ });
}
private void doPerformAction(final String issueKey, final String actionName)
- throws IOException {
- log.debug("Trying to perform action: " + actionName + " on issue " + issueKey);
+ throws IOException, InvalidTransitionException {
+ log.debug(
+ "Trying to perform action: " + actionName + " on issue " + issueKey);
boolean ret = client().doTransition(issueKey, actionName);
if (ret) {
log.debug("Action " + actionName + " successful on Issue " + issueKey);
@@ -118,54 +130,47 @@
@Override
public Boolean call() throws Exception {
return client().issueExists(issueKey);
- }});
+ }
+ });
}
- private JiraClient client() throws IOException {
+ private JiraClient client() throws MalformedURLException {
if (client == null) {
- try {
- log.debug("Connecting to jira at {}", getUrl());
- client = new JiraClient(getUrl(), getUsername(), getPassword());
- log.debug("Authenticating as User {}", getUsername());
- } catch (Exception e) {
- log.info("Unable to connect to " + getUrl() + " as "
- + getUsername());
- throw new IOException(e);
- }
+ log.debug("Connecting to jira at {}", getUrl());
+ client = new JiraClient(getUrl(), getUsername(), getPassword());
+ log.debug("Authenticating as User {}", getUsername());
}
return client;
}
private <P> P execute(Callable<P> function) throws IOException {
int attempt = 0;
- while(true) {
+ while (true) {
try {
return function.call();
} catch (Exception ex) {
if (isRecoverable(ex) && ++attempt < MAX_ATTEMPTS) {
- log.debug("Call failed - retrying, attempt {} of {}", attempt, MAX_ATTEMPTS);
+ log.debug("Call failed - retrying, attempt {} of {}", attempt,
+ MAX_ATTEMPTS);
continue;
}
- if (ex instanceof IOException)
- throw ((IOException)ex);
- else
- throw new IOException(ex);
+ if (ex instanceof IOException) throw ((IOException) ex);
+ throw new IOException(ex);
}
}
}
+
private boolean isRecoverable(Exception ex) {
String className = ex.getClass().getName();
return className.startsWith("java.net");
}
private String getPassword() {
- return gerritConfig.getString(pluginName, null,
- GERRIT_CONFIG_PASSWORD);
+ return gerritConfig.getString(pluginName, null, GERRIT_CONFIG_PASSWORD);
}
private String getUsername() {
- return gerritConfig.getString(pluginName, null,
- GERRIT_CONFIG_USERNAME);
+ return gerritConfig.getString(pluginName, null, GERRIT_CONFIG_USERNAME);
}
private String getUrl() {
@@ -179,14 +184,18 @@
private String healthCheckAccess() throws IOException {
client().sysInfo();
- final String result = "{\"status\"=\"ok\",\"username\"=\"" + getUsername() + "\"}";
+ final String result =
+ "{\"status\"=\"ok\",\"username\"=\"" + getUsername() + "\"}";
log.debug("Healtheck on access result: {}", result);
return result;
}
private String healthCheckSysinfo() throws IOException {
- ServerInfo info = client().sysInfo();
- final String result = "{\"status\"=\"ok\",\"system\"=\"Jira\",\"version\"=\""+info.getVersion()+"\",\"url\"=\""+getUrl()+"\",\"build\"=\""+info.getBuildNumber()+"\"}";
+ JiraServerInfo info = client().sysInfo();
+ final String result =
+ "{\"status\"=\"ok\",\"system\"=\"Jira\",\"version\"=\""
+ + info.getVersion() + "\",\"url\"=\"" + getUrl() + "\",\"build\"=\""
+ + info.getBuildNumber() + "\"}";
log.debug("Healtheck on sysinfo result: {}", result);
return result;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraSession.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraSession.java
deleted file mode 100644
index 2609ddf..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraSession.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2013 The Android Open Source Project
-//
-// 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.googlesource.gerrit.plugins.its.jira;
-
-public class JiraSession {
-
- private final String username;
- private final String token;
-
- public JiraSession(final String username, final String loginToken) {
- super();
- this.username = username;
- this.token = loginToken;
- }
-
- public String getUsername() {
- return username;
- }
-
- public String getToken() {
- return token;
- }
-
- public String toString() {
- return "username="+username+", token="+token;
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraComment.java
new file mode 100644
index 0000000..e3e2f0e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraComment.java
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+public class JiraComment {
+
+ final String body;
+
+ public JiraComment(String body) {
+ this.body = body;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssue.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssue.java
new file mode 100644
index 0000000..8a22098
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraIssue.java
@@ -0,0 +1,20 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+public class JiraIssue {
+ String id;
+ String key;
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraProject.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraProject.java
new file mode 100644
index 0000000..d244cb4
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraProject.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+public class JiraProject {
+
+ String id;
+ String key;
+ String name;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApi.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApi.java
new file mode 100644
index 0000000..581f40b
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApi.java
@@ -0,0 +1,161 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+import com.google.gson.Gson;
+
+import java.util.Base64;
+import org.apache.commons.lang.ArrayUtils;
+import org.eclipse.jgit.util.HttpSupport;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.URL;
+
+/**
+ * Jira Rest Client.
+ */
+public class JiraRestApi<T> {
+ private static final String BASE_PREFIX = "/rest/api/2";
+ private final URL baseUrl;
+ private final String auth;
+ private final Gson gson;
+
+ private final Class<T> classOfT;
+ private final String classPrefix;
+ private T data;
+ private int responseCode;
+
+ /**
+ * @param url jira url
+ * @param user username of the jira user
+ * @param pass password of the jira user
+ */
+ JiraRestApi(URL url, String user, String pass, Class<T> classOfT,
+ String classPrefix) {
+ String auth = user + ":" + pass;
+ this.auth = new String(Base64.getEncoder().encodeToString(auth.getBytes()));
+ this.baseUrl = url;
+ this.gson = new Gson();
+ this.classOfT = classOfT;
+ this.classPrefix = classPrefix;
+ }
+
+ public int getResponseCode() {
+ return responseCode;
+ }
+
+ /**
+ * Do a simple GET request. Object of type 'T' is returned containing the
+ * parsed JSON data
+ *
+ * @param passCode HTTP response code required to mark this GET as success
+ * @param failCodes HTTP response codes allowed and not fail on unexcepted
+ * response
+ * @throws IOException generated if unexpected failCode is returned
+ */
+ public T doGet(String spec, int passCode, int[] failCodes)
+ throws IOException {
+ HttpURLConnection conn = prepHttpConnection(spec, false);
+ try {
+ if (validateResponse(conn, passCode, failCodes)) {
+ readIncomingData(conn);
+ }
+ return data;
+ } finally {
+ conn.disconnect();
+ }
+ }
+
+ public T doGet(String spec, int passCode) throws IOException {
+ return doGet(spec, passCode, null);
+ }
+
+ /**
+ * Do a simple POST request.
+ */
+ public boolean doPost(String spec, String jsonInput, int passCode)
+ throws IOException {
+ HttpURLConnection conn = prepHttpConnection(spec, true);
+ try {
+ writePostData(jsonInput, conn);
+ return validateResponse(conn, passCode, null);
+ } finally {
+ conn.disconnect();
+ }
+ }
+
+ private HttpURLConnection prepHttpConnection(String spec,
+ boolean isPostRequest) throws IOException {
+ URL url = new URL(baseUrl, BASE_PREFIX + classPrefix + spec);
+ ProxySelector proxySelector = ProxySelector.getDefault();
+ Proxy proxy = HttpSupport.proxyFor(proxySelector, url);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
+ conn.setRequestProperty("Authorization", "Basic " + auth);
+ conn.setRequestProperty("Content-Type", "application/json");
+ if (isPostRequest) {
+ conn.setRequestMethod("POST");
+ conn.setDoOutput(true);
+ } else {
+ conn.setRequestMethod("GET");
+ }
+ return conn;
+ }
+
+ /**
+ * Write the Read the returned data from the HTTP connection.
+ */
+ private void writePostData(String postData, HttpURLConnection conn)
+ throws IOException {
+ if (postData != null) {
+ try (OutputStream os = conn.getOutputStream()) {
+ os.write(postData.getBytes());
+ os.flush();
+ }
+ }
+ }
+
+ /**
+ * Read the returned data from the HTTP connection.
+ */
+ private void readIncomingData(HttpURLConnection conn) throws IOException {
+ try (InputStreamReader isr = new InputStreamReader(conn.getInputStream())) {
+ data = gson.fromJson(isr, classOfT);
+ }
+ }
+
+ /**
+ * Checks if the connection returned one of the provides pass or fail Codes.
+ * If not, an IOException exception is thrown. If it was part of the list,
+ * then the actual response code is returned. returns true if valid response
+ * is returned, otherwise false
+ */
+ private boolean validateResponse(HttpURLConnection conn, int passCode,
+ int[] failCodes) throws IOException {
+ responseCode = conn.getResponseCode();
+ if (responseCode == passCode) {
+ return true;
+ }
+ if ((failCodes == null)
+ || (!ArrayUtils.contains(failCodes, responseCode))) {
+ throw new IOException("Request failed");
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java
new file mode 100644
index 0000000..54ce637
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraRestApiProvider.java
@@ -0,0 +1,33 @@
+package com.googlesource.gerrit.plugins.its.jira.restapi;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class JiraRestApiProvider {
+ private final URL url;
+ private final String user;
+ private final String pass;
+
+ public JiraRestApiProvider(String url, String user, String pass)
+ throws MalformedURLException {
+ this.url = new URL(url);
+ this.user = user;
+ this.pass = pass;
+ }
+
+ public <T> JiraRestApi<T> get(Class<T> classOfT, String classPrefix) {
+ return new JiraRestApi<>(url, user, pass, classOfT, classPrefix);
+ }
+
+ public JiraRestApi<JiraIssue> getIssue() {
+ return get(JiraIssue.class, "/issue");
+ }
+
+ public JiraRestApi<JiraServerInfo> getServerInfo() {
+ return get(JiraServerInfo.class, "/serverInfo");
+ }
+
+ public JiraRestApi<JiraProject[]> getProjects() {
+ return get(JiraProject[].class, "/project");
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraServerInfo.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraServerInfo.java
new file mode 100644
index 0000000..9b2fe79
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraServerInfo.java
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+public class JiraServerInfo {
+
+ String baseUrl;
+ String version;
+ String deploymentType;
+ String buildNumber;
+ String buildDate;
+ String serverTime;
+ String scmInfo;
+ String serverTitle;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getBuildNumber() {
+ return buildNumber;
+ }
+
+ public String getBaseUri() {
+ return baseUrl;
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraTransition.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraTransition.java
new file mode 100644
index 0000000..4bbad2c
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/restapi/JiraTransition.java
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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.googlesource.gerrit.plugins.its.jira.restapi;
+
+public class JiraTransition {
+
+ // 'Get Transactions' require a list of items
+ public Item[] transitions;
+
+ // 'Do Transaction' require a single item
+ Item transition;
+
+ public JiraTransition(Item transition) {
+ this.transition = transition;
+ }
+
+ public static class Item {
+ String name;
+ String id;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getId() {
+ return id;
+ }
+ }
+}
diff --git a/src/main/resources/Documentation/build.md b/src/main/resources/Documentation/build.md
index 20e452f..1235321 100644
--- a/src/main/resources/Documentation/build.md
+++ b/src/main/resources/Documentation/build.md
@@ -7,17 +7,6 @@
[plugins/its-base](https://gerrit-review.googlesource.com/#/admin/projects/plugins/its-base)
to the `plugins` directory of Gerrit's source tree.
-Put the external dependency Bazel build file into the Gerrit /plugins directory,
-replacing the existing empty one.
-
-```
- cd gerrit/plugins
- rm external_plugin_deps.bzl
- cd @PLUGIN@
- cp external_plugin_deps.bzl ../
- cd ../../
-```
-
Then issue
```