
com.capitalone.dashboard.datafactory.jira.JiraDataFactoryImpl Maven / Gradle / Ivy
package com.capitalone.dashboard.datafactory.jira;
import com.atlassian.jira.rest.client.api.JiraRestClient;
import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
import com.atlassian.jira.rest.client.api.domain.BasicProject;
import com.atlassian.jira.rest.client.api.domain.Issue;
import com.atlassian.jira.rest.client.api.domain.SearchResult;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.atlassian.util.concurrent.Promise;
import com.google.common.collect.Lists;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@Component
public class JiraDataFactoryImpl implements JiraDataFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(JiraDataFactoryImpl.class);
protected JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
protected JiraRestClient client;
protected int pageSize;
protected int pageIndex;
protected String basicQuery;
/**
* Default constructor required for Spring (not used)
*/
public JiraDataFactoryImpl() {
// Intentionally empty for Spring
}
/**
* Default constructor, which sets page size to 1000 and page index to 0.
*
* @param jiraCredentials
* Jira x64 encoded credentials (see jira client library for
* details)
* @param jiraBaseUrl
* Jira base URL
*/
public JiraDataFactoryImpl(String jiraCredentials, String jiraBaseUrl) {
URI jiraUri;
try {
jiraUri = new URI(jiraBaseUrl);
} catch (URISyntaxException e) {
LOGGER.error("There was a problem reading the provide Jira base URI syntax");
jiraUri = null;
}
client = factory.createWithBasicHttpAuthentication(jiraUri,
this.decodeCredentials(jiraCredentials).get("username"),
this.decodeCredentials(jiraCredentials).get("password"));
this.pageSize = 1000;
this.pageIndex = 0;
}
/**
* Default constructor, which sets page size to 1000 and page index to 0.
*
* @param jiraCredentials
* Jira x64 encoded credentials (see jira client library for
* details)
* @param jiraBaseUrl
* Jira base URL
* @param jiraProxyUrl
* Jira proxy URL
* @param jiraProxyUrl
* Jira proxy port number
*/
public JiraDataFactoryImpl(String jiraCredentials, String jiraBaseUrl, String jiraProxyUrl,
String jiraProxyPort) {
URI jiraUri;
if (!StringUtils.isEmpty(jiraBaseUrl)) {
if (!StringUtils.isEmpty(jiraProxyUrl) && !StringUtils.isEmpty(jiraProxyPort)) {
jiraUri = this.createJiraConnection(jiraBaseUrl,
jiraProxyUrl + ":" + jiraProxyPort, this.decodeCredentials(jiraCredentials)
.get("username"),
this.decodeCredentials(jiraCredentials).get("password"));
} else {
try {
LOGGER.debug("Handling without authenticated proxy (fields were available in properties settings but were blank)");
jiraUri = new URI(jiraBaseUrl);
} catch (URISyntaxException e) {
LOGGER.error("There was a problem reading the provide Jira base URI syntax");
jiraUri = null;
}
}
client = factory.createWithBasicHttpAuthentication(jiraUri,
this.decodeCredentials(jiraCredentials).get("username"), this
.decodeCredentials(jiraCredentials).get("password"));
} else {
LOGGER.error("At runtime in a property setting at minimum, a valid Jira URI and basic authentication credentials must be provided");
}
this.pageSize = 1000;
this.pageIndex = 0;
}
/**
* Constructs Jira data factory, but defaults the page size to the page size
* parameter given, and the page index to 0.
*
* @param inPageSize
* A default page size to give the class on construction
* @param jiraCredentials
* Jira x64 encoded credentials (see jira client library for
* details)
* @param jiraBaseUrl
* Jira base URL
*/
public JiraDataFactoryImpl(int inPageSize, String jiraCredentials, String jiraBaseUrl) {
URI jiraUri;
try {
jiraUri = new URI(jiraBaseUrl);
} catch (URISyntaxException e) {
LOGGER.error("There was a problem reading the provide Jira base URI syntax");
jiraUri = null;
}
this.client = factory.createWithBasicHttpAuthentication(jiraUri,
this.decodeCredentials(jiraCredentials).get("username"),
this.decodeCredentials(jiraCredentials).get("password"));
this.pageSize = inPageSize;
pageIndex = 0;
}
/**
* Constructs Jira data factory, but defaults the page size to the page size
* parameter given, and the page index to 0.
*
* @param inPageSize
* A default page size to give the class on construction
* @param jiraCredentials
* Jira x64 encoded credentials (see jira client library for
* details)
* @param jiraBaseUrl
* Jira base URL
* @param jiraProxyUrl
* Jira proxy URL
* @param jiraProxyUrl
* Jira proxy port number
*/
public JiraDataFactoryImpl(int inPageSize, String jiraCredentials, String jiraBaseUrl,
String jiraProxyUrl, String jiraProxyPort) {
URI jiraUri;
if (!StringUtils.isEmpty(jiraBaseUrl)) {
if (!StringUtils.isEmpty(jiraProxyUrl) && !StringUtils.isEmpty(jiraProxyPort)) {
jiraUri = this.createJiraConnection(jiraBaseUrl,
jiraProxyUrl + ":" + jiraProxyPort, this.decodeCredentials(jiraCredentials)
.get("username"),
this.decodeCredentials(jiraCredentials).get("password"));
} else {
try {
LOGGER.debug("Handling without authenticated proxy (fields were available in properties settings but were blank)");
jiraUri = new URI(jiraBaseUrl);
} catch (URISyntaxException e) {
LOGGER.error("There was a problem reading the provide Jira base URI syntax");
jiraUri = null;
}
}
this.client = factory.createWithBasicHttpAuthentication(jiraUri, this
.decodeCredentials(jiraCredentials).get("username"),
this.decodeCredentials(jiraCredentials).get("password"));
} else {
LOGGER.error("At runtime in a property setting at minimum, a valid Jira URI and basic authentication credentials must be provided");
}
this.pageSize = inPageSize;
pageIndex = 0;
}
/**
* Sets the local query value on demand based on a given basic query.
*
* @param query
* A query in REST syntax as a String
* @return The saved REST-syntax basic query
*/
public String setQuery(String query) {
this.setBasicQuery(query);
return this.getBasicQuery();
}
/**
* Runs the jira-client library tools against a given REST-formatted query.
* This requires a pre-formatted paged query to run, and will not perform
* the paging for you - there are other helper methods for this.
*
* @return A formatted JSONArray response
*/
public List getJiraIssues() {
Iterable jiraRawRs = null;
List issues = new ArrayList();
Set fields = new LinkedHashSet();
fields.add("*all");
if (client != null) {
Promise promisedRs = client.getSearchClient().searchJql(
this.getBasicQuery(), this.getPageSize(), this.getPageIndex(), fields);
try {
jiraRawRs = promisedRs.claim().getIssues();
if (jiraRawRs != null) {
issues = Lists.newArrayList(jiraRawRs);
} else {
issues = new ArrayList();
}
} catch (Exception e) {
issues = new ArrayList();
LOGGER.warn("No result was available from Jira unexpectedly - defaulting to blank response. The reason for this fault is the following:"
+ e.getCause());
}
} else {
issues = null;
LOGGER.error("The response from Jira was blank or non existant - please check your property configurations");
}
return issues;
}
/**
* Runs the jira-client library tools against a given REST-formatted query.
* This works only for project/team-style values.
*
* @return A list of Jira projects/teams
*/
public List getJiraTeams() {
Iterable jiraRawRs = null;
List issues = new ArrayList();
if (client != null) {
Promise> promisedRs = client.getProjectClient().getAllProjects();
try {
jiraRawRs = promisedRs.claim();
if (jiraRawRs != null) {
issues = Lists.newArrayList(jiraRawRs);
} else {
issues = new ArrayList();
}
} catch (Exception e) {
issues = new ArrayList();
LOGGER.warn("No result was available from Jira unexpectedly - defaulting to blank response. The reason for this fault is the following:"
+ e.getCause());
}
} else {
issues = null;
LOGGER.error("The response from Jira was blank or non existant - please check your property configurations");
}
return issues;
}
/**
* Mutator method for page index.
*
* @param pageIndex
* Page index of query
*/
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
/**
* Accessor method for page index.
*
* @return Page index of query
*/
public int getPageIndex() {
return this.pageIndex;
}
/**
* Accessor method for basic query formatted object.
*
* @return Basic Jira REST query
*/
public String getBasicQuery() {
return this.basicQuery;
}
/**
* Mutator method for basic query formatted object.
*
* @param basicQuery
* Jira REST query
*/
private void setBasicQuery(String basicQuery) {
this.basicQuery = basicQuery;
}
/**
* Used for testing: Accessor Method to get currently set page size
*/
public int getPageSize() {
return this.pageSize;
}
/**
* Converts Jira basic authentication credentials from Base 64 string to a
* username/password map
*
* @param jiraBasicAuthCredentialsInBase64
* Base64-encoded single string in the following format:
* username:password
*
* A null parameter value will result in an empty hash map
* response (e.g., nothing gets decoded)
* @return Decoded username/password map of strings
*/
protected Map decodeCredentials(String jiraBasicAuthCredentialsInBase64) {
Map credMap = new LinkedHashMap();
if (jiraBasicAuthCredentialsInBase64 != null) {
StringTokenizer tokenizer = new StringTokenizer(new String(
Base64.decodeBase64(jiraBasicAuthCredentialsInBase64)), ":");
for (int i = 0; tokenizer.hasMoreTokens(); i++) {
if (i == 0) {
credMap.put("username", tokenizer.nextToken());
} else {
credMap.put("password", tokenizer.nextToken());
}
}
}
return credMap;
}
/**
* Generates an authenticated proxy connection URI and Jira URI for use in
* talking to Jira.
*
* @param jiraBaseUri
* A string representation of a Jira URI
* @param fullProxyUrl
* A string representation of a completed proxy URL:
* http://your.proxy.com:8080
* @param username
* A string representation of a username to be authenticated
* @param password
* A string representation of a password to be used in
* authentication
* @return A fully configured Jira URI with authenticated proxy connection
*/
protected URI createJiraConnection(String jiraBaseUri, String fullProxyUrl, String username,
String password) {
final String uname = username;
final String pword = password;
Proxy proxy = null;
URLConnection connection = null;
try {
if (!StringUtils.isEmpty(jiraBaseUri)) {
URL baseUrl = new URL(jiraBaseUri);
if (!StringUtils.isEmpty(fullProxyUrl)) {
URL proxyUrl = new URL(fullProxyUrl);
URI proxyUri = new URI(proxyUrl.getProtocol(), proxyUrl.getUserInfo(),
proxyUrl.getHost(), proxyUrl.getPort(), proxyUrl.getPath(),
proxyUrl.getQuery(), null);
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyUri.getHost(),
proxyUri.getPort()));
connection = baseUrl.openConnection(proxy);
if (!StringUtils.isEmpty(username) && (!StringUtils.isEmpty(password))) {
String creds = uname + ":" + pword;
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(uname, pword.toCharArray());
}
});
connection.setRequestProperty("Proxy-Authorization",
"Basic " + Base64.encodeBase64String((creds).getBytes()));
}
} else {
connection = baseUrl.openConnection();
}
} else {
LOGGER.error("The response from Jira was blank or non existant - please check your property configurations");
return null;
}
return connection.getURL().toURI();
} catch (URISyntaxException | IOException e) {
try {
LOGGER.error("There was a problem parsing or reading the proxy configuration settings during openning a Jira connection. Defaulting to a non-proxy URI.");
return new URI(jiraBaseUri);
} catch (URISyntaxException e1) {
LOGGER.error("Correction: The Jira connection base URI cannot be read!");
return null;
}
}
}
/**
* Destroys current Jira Client connection during asynchronous connection
*/
public void destroy() {
if (client != null) {
try {
this.client.close();
} catch (IOException e) {
LOGGER.error("There was a problem closing your Jira connection during query collection");
}
} else {
LOGGER.warn("No valid client was established to be destroyed");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy