package com.perforce.ts.rest; import com.atlassian.jira.rest.client.api.JiraRestClient; import com.atlassian.jira.rest.client.api.RestClientException; import com.atlassian.jira.rest.client.api.SearchRestClient; import com.atlassian.jira.rest.client.api.domain.Issue; import com.atlassian.jira.rest.client.api.domain.Project; import com.atlassian.jira.rest.client.api.domain.SearchResult; import com.atlassian.jira.rest.client.api.domain.ServerInfo; import com.atlassian.jira.rest.client.api.domain.input.FieldInput; import com.atlassian.jira.rest.client.api.domain.input.IssueInput; import com.atlassian.jira.rest.client.api.domain.util.ErrorCollection; import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory; import java.net.URI; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.joda.time.DateTime; /** * For testing connections: * connects to a jira server using REST, basic auth * (optional) retrieves an issue * (options) updates the issue's summary * . * * @author jbrown */ public class RestConnect { private final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory(); private final TimeCommand timer = new TimeCommand(); /** * connect to JIRA and (optionally) retrieve an issue * * @param url * @param user * @param password * @param issueName optional. Retrieve if found. * @param updateSummary optional. Append this String to the summary and update it. * @return 0 for success, 1 for issue not found * @throws Exception */ public int connectAndRun(String url, String user, String password, String issueName, String updateSummary) throws Exception { URI jiraServerUri = new URI(url); timer.start(); JiraRestClient restClient = factory.createWithBasicHttpAuthentication(jiraServerUri, user, password); timer.stop(); System.out.println(timer + "::Connected to " + jiraServerUri); restClientManager = new RestClientManager(url, user, password); System.out.println("Running get server date"); timer.start(); try { String serverDate = getServerDate(); timer.stop(); System.out.println(timer + ":0:Server Date: " + serverDate); } catch (Exception exception) { timer.stop(); System.err.println(timer + "-1:" + exception.getMessage()); exception.printStackTrace(); } if (issueName != null && issueName.length() > 2) { try { timer.start(); Issue issue = getIssue(restClient, issueName); timer.stop(); System.out.println(timer + ":0:retrieve " + issueName); if (issue == null) { System.out.println(" Issue '" + issueName + "' not found."); return 2; } String summary = issue.getSummary(); System.out.println(" Issue '" + issueName + "' found: " + summary); if (updateSummary != null) { summary = summary + updateSummary; List<FieldInput> fields = new ArrayList(); fields.add(new FieldInput("summary", summary)); timer.start(); updateIssue(issue, fields); System.out.println(timer + "::Issue updated"); timer.stop(); timer.start(); issue = getIssue(restClient, issueName); timer.stop(); System.out.println(timer + "::Issue refreshed"); if (issue != null) { System.out.println(" Issue '" + issueName + "' updated, summary now: " + issue.getSummary()); } } } finally { restClient.close(); } } return 0; } public static final Integer DEFAULT_BATCH_SIZE = 100; public static final Integer DEFAULT_BATCH_SLEEP = 0; /** * connect to JIRA and (optionally) retrieve an issue * * @param url JIRA URL * @param user * @param password * @param jqlQueries one or more jql Strings to search for * @return number of issues found * @throws Exception */ public int connectAndQuery(String url, String user, String password, String... jqlQueries) throws Exception { String batch_size = System.getProperty("batch_size"); batchSize = convertToInt(batch_size, DEFAULT_BATCH_SIZE); String batch_sleep = System.getProperty("batch_sleep"); batchSleep = convertToInt(batch_sleep, DEFAULT_BATCH_SLEEP); URI jiraServerUri = new URI(url); timer.start(); restClientManager = new RestClientManager(url, user, password); timer.stop(); System.out.println(timer + "::Connected to " + jiraServerUri); for (String jqlQuery : jqlQueries) { System.out.println("Running query: " + jqlQuery + "(batch_size=" + batchSize + ", batch_sleep=" + batchSleep + ")"); timer.start(); int rows = 0; String msg; // do stuff try { Map<String, Integer> issues = search(jqlQuery); rows = issues.size(); msg = jqlQuery; StringBuilder sb = new StringBuilder(40); for (String key : issues.keySet()) { sb.append(key).append(" "); } msg = jqlQuery + "::" + sb.toString(); } catch (Exception ex) { rows = -1; msg = ex.getMessage(); ex.printStackTrace(); } timer.stop(); System.out.println(timer + ":" + rows + ":" + msg); } return 0; } /** * Returns an issue. Returns null if issue not found. Other problems throw an * RestClientException * * @param restClient * @param issueName * @return */ private Issue getIssue(JiraRestClient restClient, String issueName) throws RestClientException { Issue issue = null; try { issue = restClient.getIssueClient().getIssue(issueName).claim(); } catch (RestClientException e) { Collection<ErrorCollection> errs = e.getErrorCollections(); for (ErrorCollection err : errs) { if (err.getStatus() == 404) { return (Issue)null; } } throw e; } return issue; } /** * * * Update an issue with the fieldInputs * * @param issue previously retrieved Issue * @param fieldInputs fields to update with their new values. * @throws Exception */ private void updateIssue(Issue issue, List<FieldInput> fieldInputs) throws Exception { if (restClientManager == null) { throw new Exception("Error occurred while connecting to the JIRA server: " + "rest client manager initialization error."); } // Create issue input with specified fields IssueInput issueInput = IssueInput.createWithFields(fieldInputs.toArray( new FieldInput[fieldInputs.size()])); // Update the given fields on the issue restClientManager.getExtendedIssueClient().update(issue, issueInput).claim(); } // all calls go through here. RestClientManager restClientManager = null; // for formatting of server's datetime public static final String DATE_PATTERN = "yyyy/MM/dd HH:mm:ss"; /** * String representation of jira server's datatime. * Use -Duser.timezone if needed (match the jira timezone) * * @return String representation of jira server's datatime. * @throws Exception */ public String getServerDate() throws Exception { DateFormat format = new SimpleDateFormat(DATE_PATTERN); Date serverDate = null; ServerInfo serverInfo = restClientManager.getExtendedMetadataClient().getServerInfo().claim(); if (serverInfo != null) { DateTime serverTime = serverInfo.getServerTime(); if (serverTime != null) { serverDate = serverTime.toDate(); } else { throw new Exception("getServerTime() is null: see https://community.perforce.com/s/article/14945"); } } else { throw new Exception("serverInfo is null!"); } return format.format(serverDate); } private int batchSize = DEFAULT_BATCH_SIZE; private int batchSleep = 0; public Map<String, Integer> search(String jql) { /** * put returned issues into a Map to weed out duplications. * Duplicates can happen if the pagesize (batchCnt) overlaps on the last page: see the rest * api's javadoc. */ Map<String, Integer> issues = new HashMap(); SearchRestClient searchClient = restClientManager.getSearchClient(); String qmsg; final TimeCommand timex = new TimeCommand(); int cnt = batchSize; int cntSoFar = 0; int loopCnt = 0; boolean interrupted = false; while (cnt == batchSize && ! interrupted) { loopCnt += 1; if (loopCnt > 1 && batchSleep > 0) { try { System.out.println(" sleeping " + batchSleep + "ms"); Thread.sleep(batchSleep); } catch (InterruptedException ex) { // punt System.out.println(" Interrupted sleep: ignored."); interrupted = true; continue; } } qmsg = "Query " + loopCnt; timex.start(); System.out.println("Start: " + qmsg); SearchResult searchResult = searchClient.searchJql(jql, batchSize, cntSoFar, null).claim(); timex.stop(); System.out.println("Finished: " + qmsg + " " + timex); cnt = 0; for (Issue issue : searchResult.getIssues()) { ++cnt; ++cntSoFar; if (null == issues.get(issue.getKey())) { issues.put(issue.getKey(), null); } else { System.out.println("Found dup " + issue.getKey()); } } System.out.println(" issues found = " + cnt); } return issues; } /** * connect to JIRA and (optionally) see if you have access to the project(s) * * @param url JIRA URL * @param user * @param password * @param projects * @return list of project and results. * @throws Exception */ public List<String> getProjects(String url, String user, String password, String... projects) throws Exception { URI jiraServerUri = new URI(url); timer.start(); restClientManager = new RestClientManager(url, user, password); timer.stop(); System.out.println(timer + "::Connected to " + jiraServerUri + " as user " + user); List<String> foundProjects = new ArrayList<>(); for (String project : projects) { Project proj = null; String res = ""; try { // proj = restClientManager.getProjectClient().getProject(project).claim(); SearchResult result = restClientManager.getSearchClient().searchJql("project = " + project + " and updated < '2006/1/1'", 1, 0, null).claim(); res = (result != null ? Integer.toString(result.getTotal()) : "null"); } catch (RestClientException ex) { res = "exception "; // 404 if the project does not exist. // ex.printStackTrace(); Collection<ErrorCollection> errs = ex.getErrorCollections(); for (ErrorCollection err : errs) { res += err.getStatus() + ","; } res += (ex.getMessage().length() < 100 ? ex.getMessage() : ex.getMessage().substring(0, 99) + " ..."); } foundProjects.add(project + " lookup: " + res); } return foundProjects; } private static int convertToInt(String number, Integer default_number) { Integer parsedInt = default_number; try { if (number != null && number.length() > 0) { parsedInt = Integer.parseInt(number); if (parsedInt < 0) { parsedInt = default_number; } } } catch (NumberFormatException e) { System.out.println("Invalid integer string: " + number + ", using default " + default_number); parsedInt = default_number; } return parsedInt; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 24983 | Joel Brown | Print the' stack trace to see where the java.net.SocketTimeoutException is happening. | ||
#3 | 24980 | Joel Brown |
Add query functionalty for testing query response times. Code pattern matches 2018.1 p4dtg's jira-rest plugin. |
||
#2 | 12542 | Joel Brown | Break out chain of calls into separate lines so we can find where the 'null' pops up. | ||
#1 | 12538 | Joel Brown | Test program for JIRA REST connections, useful for troubleshooting p4dtg's JIRA-REST plugin. |