From 5928310f07ac2514853edb278d1b0602e519db89 Mon Sep 17 00:00:00 2001 From: Adetunji Samuel Date: Sun, 17 Mar 2024 20:41:26 +0000 Subject: [PATCH 1/2] Convert 'JiraAPI' to Java --- .../JiraAPI.groovy | 102 ------------ .../JiraAPI.java | 155 ++++++++++++++++++ 2 files changed, 155 insertions(+), 102 deletions(-) delete mode 100644 src/main/groovy/io/jenkins/infra/repository_permissions_updater/JiraAPI.groovy create mode 100644 src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java diff --git a/src/main/groovy/io/jenkins/infra/repository_permissions_updater/JiraAPI.groovy b/src/main/groovy/io/jenkins/infra/repository_permissions_updater/JiraAPI.groovy deleted file mode 100644 index b5f04efc25..0000000000 --- a/src/main/groovy/io/jenkins/infra/repository_permissions_updater/JiraAPI.groovy +++ /dev/null @@ -1,102 +0,0 @@ -package io.jenkins.infra.repository_permissions_updater - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings -import groovy.json.JsonSlurper - -import java.nio.charset.StandardCharsets -import java.util.logging.Level -import java.util.logging.Logger - -@SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Something related to Groovy -abstract class JiraAPI implements Definition.IssueTracker.JiraComponentSource { - public static final Logger LOGGER = Logger.getLogger(JiraAPI.class.getName()) - /** - * URL to Jira - */ - private static final String JIRA_URL = System.getProperty('jiraUrl', 'https://issues.jenkins.io') - /** - * URL to Jira components API - */ - private static final String JIRA_COMPONENTS_URL = JIRA_URL + '/rest/api/2/project/JENKINS/components' - /** - * URL to Jira user API - */ - private static final String JIRA_USE_URL = JIRA_URL + '/rest/api/2/user' - - abstract String getComponentId(String componentName); - - abstract boolean isUserPresent(String username); - - /* Singleton support */ - private static JiraAPI INSTANCE = null - static synchronized JiraAPI getInstance() { - if (INSTANCE == null) { - INSTANCE = new JiraImpl() - } - return INSTANCE - } - - private static class JiraImpl extends JiraAPI { - - private Map componentNamesToIds - - private Map userMapping = new HashMap<>() - - @SuppressFBWarnings("SE_NO_SERIALVERSIONID") - private void ensureDataLoaded() { - if (componentNamesToIds == null) { - componentNamesToIds = new HashMap<>(); - - LOGGER.log(Level.INFO, "Retrieving components from Jira...") - URL url = new URL(JIRA_COMPONENTS_URL) - HttpURLConnection conn = (HttpURLConnection) url.openConnection() - - conn.setRequestMethod('GET') - conn.connect() - String text = conn.getInputStream().getText() - - def json = new JsonSlurper().parseText(text) - - json.each { - def id = it.id - def name = it.name - LOGGER.log(Level.FINE, "Identified Jira component with ID '${id}' and name '${name}'") - componentNamesToIds.put(name, id) - } - } - } - - @Override - String getComponentId(String componentName) { - ensureDataLoaded() - return componentNamesToIds.get(componentName) - } - - @Override - boolean isUserPresent(String username) { - return userMapping.computeIfAbsent(username, { u -> isUserPresentInternal(u) }) - } - - private static boolean isUserPresentInternal(String username) { - if (!username.matches(/[a-zA-Z0-9_]+/)) { - LOGGER.log(Level.WARNING, "Rejecting user name for Jira lookup: " + username) - return false // Do not allow unusual user names, protect from any shenanigans - } - - LOGGER.log(Level.INFO, "Checking whether user exists in Jira: " + username) - - URL url = new URL(JIRA_USE_URL + "?username=${username}") - HttpURLConnection conn = (HttpURLConnection) url.openConnection() - - conn.setRequestMethod('GET') - conn.setRequestProperty('Authorization', 'Basic ' + Base64.getEncoder().encodeToString((System.getenv("JIRA_USERNAME") + ':' + System.getenv("JIRA_PASSWORD")).getBytes(StandardCharsets.UTF_8))) - conn.connect() - - def code = conn.getResponseCode() - if (code == 200) { - return true - } - return false - } - } -} diff --git a/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java b/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java new file mode 100644 index 0000000000..cf8c2200be --- /dev/null +++ b/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java @@ -0,0 +1,155 @@ +package io.jenkins.infra.repository_permissions_updater; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +abstract public class JiraAPI implements Definition.IssueTracker.JiraComponentSource { + + public static final Logger LOGGER = Logger.getLogger( + JiraAPI.class.getName() + ); + + /** + * URL to Jira + */ + private static final String JIRA_URL = System.getProperty("jiraUrl", "https://issues.jenkins.io"); + /** + * URL to Jira components API + */ + private static final String JIRA_COMPONENTS_URL = JIRA_URL + "/rest/api/2/project/JENKINS/components"; + /** + * URL to Jira user API + */ + private static final String JIRA_USER_URL = JIRA_URL + "/rest/api/2/user"; + + public abstract String getComponentId(String componentName); + + abstract boolean isUserPresent(String username); + + /* Singleton support */ + private static JiraAPI INSTANCE = null; + + static synchronized JiraAPI getInstance(){ + if (INSTANCE == null) { + INSTANCE = new JiraImpl(); + } + return INSTANCE; + } + @SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD", justification = "requests are necessary") + private static class JiraImpl extends JiraAPI { + + private Map componentNamesToIds = new HashMap<>(); + private Map userMapping = new HashMap<>(); + + private void ensureDataLoaded() + { + if (!componentNamesToIds.isEmpty()) { + return; + } + + LOGGER.log(Level.INFO, "Retrieving components from Jira..."); + try { + URL url = new URL(JIRA_COMPONENTS_URL); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.connect(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream() , StandardCharsets.UTF_8)); + StringBuilder response = new StringBuilder(); + + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + + Type ResponseType = new TypeToken + >>() {}.getType(); + + Gson gson = new Gson(); + + List> data = gson.fromJson(response.toString(), ResponseType); + + for (Map map : data) { + + String id = map.get("id"); + String name = map.get("name"); + + LOGGER.log(Level.FINE, + String.format("Identified Jira component with ID '%s' and name '%s", + id, name)); + + componentNamesToIds.put(name, id); + + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + @Override + public String getComponentId(String componentName) { + ensureDataLoaded(); + return componentNamesToIds.get(componentName); + } + + @Override + boolean isUserPresent(String username) { + return userMapping.computeIfAbsent(username, u -> isUserPresentInternal(u) ); + } + + private static boolean isUserPresentInternal(String username) { + if (!username.matches("/[a-zA-Z0-9_]+/")) + { + LOGGER.log(Level.WARNING, + String.format("Rejecting user name for Jira lookup: %s", username)); + return false; + } + try { + URL url = new URL(String.format( + "%s?username=%s", JIRA_USER_URL, username + )); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + conn.setRequestMethod("GET"); + conn.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString((System.getenv("JIRA_USERNAME") + ':' + System.getenv("JIRA_PASSWORD")).getBytes(StandardCharsets.UTF_8))); + + conn.connect(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) + return true; + + + } catch (IOException e) { + throw new RuntimeException(e); + } + + return false; + } + } + + + + + +} From c6a3a25b1dd4b85f57f3ce1dfe97d71ee886c4ba Mon Sep 17 00:00:00 2001 From: Adetunji Samuel Date: Sun, 17 Mar 2024 21:26:51 +0000 Subject: [PATCH 2/2] Convert 'JiraAPI' to Java: fix json parsing err --- .../JiraAPI.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java b/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java index cf8c2200be..a5a44ab6ba 100644 --- a/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java +++ b/src/main/java/io/jenkins/infra/repository_permissions_updater/JiraAPI.java @@ -1,7 +1,7 @@ package io.jenkins.infra.repository_permissions_updater; import com.google.common.reflect.TypeToken; -import com.google.gson.Gson; +import com.google.gson.*; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -80,26 +80,22 @@ private void ensureDataLoaded() } reader.close(); - Type ResponseType = new TypeToken - >>() {}.getType(); + String text = response.toString(); - Gson gson = new Gson(); - - List> data = gson.fromJson(response.toString(), ResponseType); - - for (Map map : data) { - - String id = map.get("id"); - String name = map.get("name"); + JsonElement jsonElement = JsonParser.parseString(text); + JsonArray jsonArray = jsonElement.getAsJsonArray(); + for (JsonElement element : jsonArray) { + JsonObject jsonObject = element.getAsJsonObject(); + String id = jsonObject.get("id").getAsString(); + String name = jsonObject.get("name").getAsString(); LOGGER.log(Level.FINE, String.format("Identified Jira component with ID '%s' and name '%s", id, name)); - componentNamesToIds.put(name, id); - } + } catch (IOException e) { throw new RuntimeException(e); }