package com.lesstif.jira.services; import java.io.File; import java.io.IOException; import java.util.List; import lombok.Data; import org.apache.commons.configuration.ConfigurationException; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.type.TypeReference; import org.slf4j.Logger; import com.lesstif.jira.Constants; import com.lesstif.jira.JIRAHTTPClient; import com.lesstif.jira.issue.Attachment; import com.lesstif.jira.issue.Issue; import com.lesstif.jira.issue.IssueSearchResult; import com.lesstif.jira.issue.IssueType; import com.lesstif.jira.issue.Priority; import com.lesstif.jira.issue.WorklogElement; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.UniformInterfaceException; import com.sun.jersey.multipart.FormDataMultiPart; import com.sun.jersey.multipart.file.FileDataBodyPart; import java.net.URLEncoder; import org.apache.commons.lang.StringUtils; /** * @see * <a href="https://docs.atlassian.com/software/jira/docs/api/REST/latest/#d2e86">/rest/api/2/project</a> * * @author lesstif * */ @Data public class IssueService { private Logger logger = org.slf4j.LoggerFactory.getLogger(getClass()); private JIRAHTTPClient client = null; private Issue issue; public IssueService() throws ConfigurationException { client = new JIRAHTTPClient(); } public Issue getIssue(String issueKey) throws IOException { if (client == null) { throw new IllegalStateException("HTTP Client not Initailized"); } client.setResourceName(Constants.JIRA_RESOURCE_ISSUE + "/" + issueKey); ClientResponse response = client.get(); String content = response.getEntity(String.class); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<Issue> ref = new TypeReference<Issue>() { }; issue = mapper.readValue(content, ref); return issue; } public Issue createIssue(Issue issue) throws IOException { ObjectMapper mapper = new ObjectMapper(); //to ignore a field if its value is null mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); String content = mapper.writeValueAsString(issue); logger.debug("Content=" + content); client.setResourceName(Constants.JIRA_RESOURCE_ISSUE); ClientResponse response = client.post(content); content = response.getEntity(String.class); mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<Issue> ref = new TypeReference<Issue>() { }; Issue resIssue = mapper.readValue(content, ref); if (issue.hasAttachments()) { issue.setId(resIssue.getId()); List<Attachment> attachment = postAttachment(issue); resIssue.getFields().setAttachment(attachment); } return resIssue; } /** * Returns a list of all issue types visible to the user * * @return List list of IssueType * * @throws IOException json decoding failed */ public List<IssueType> getAllIssueTypes() throws IOException { client.setResourceName(Constants.JIRA_RESOURCE_ISSUETYPE); ClientResponse response = client.get(); String content = response.getEntity(String.class); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<List<IssueType>> ref = new TypeReference<List<IssueType>>() { }; List<IssueType> issueTypes = mapper.readValue(content, ref); return issueTypes; } public List<Priority> getAllPriorities() throws IOException { client.setResourceName(Constants.JIRA_RESOURCE_PRIORITY); ClientResponse response = client.get(); String content = response.getEntity(String.class); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<List<Priority>> ref = new TypeReference<List<Priority>>() { }; List<Priority> priorities = mapper.readValue(content, ref); return priorities; } /** * Add one or more attachments to an issue. * * @param issue Issue object * @return List * @throws JsonParseException json parsing failed * @throws JsonMappingException json mapping failed * @throws IOException general IO exception */ public List<Attachment> postAttachment(Issue issue) throws JsonParseException, JsonMappingException, IOException { List<File> files = issue.getFields().getFileList(); if (files == null || files.size() == 0) { throw new IllegalStateException("Oops! Attachment Not Found."); } if ((issue.getId() == null || issue.getId().isEmpty()) && (issue.getKey() == null || issue.getKey().isEmpty())) { throw new IllegalStateException("Oops! Issue id or Key not set."); } String idOrKey = issue.getId() == null ? issue.getKey() : issue.getId(); FormDataMultiPart form = new FormDataMultiPart(); for (int i = 0; i < files.size(); i++) { // The name of the multipart/form-data parameter that contains attachments must be "file" FileDataBodyPart fdp = new FileDataBodyPart("file", files.get(i)); form.bodyPart(fdp); } client.setResourceName(Constants.JIRA_RESOURCE_ISSUE + "/" + idOrKey + "/attachments"); ClientResponse response = client.postMultiPart(form); String content = response.getEntity(String.class); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<List<Attachment>> ref = new TypeReference<List<Attachment>>() { }; List<Attachment> res = mapper.readValue(content, ref); return res; } /** * Add one or more worklog to an issue. * * @param worklog Issue object * @param issue * @return List * @throws JsonParseException json parsing failed * @throws JsonMappingException json mapping failed * @throws IOException general IO exception */ public WorklogElement postWorklog(final WorklogElement worklog, final Issue issue) throws JsonParseException, JsonMappingException, IOException { String issueId = issue.getId(); if (StringUtils.isBlank(issueId)) { final String key = issue.getKey(); final Issue issueByKey = getIssue(key); issueId = issueByKey.getId(); } ObjectMapper mapper = new ObjectMapper(); //to ignore a field if its value is null mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); String content = mapper.writeValueAsString(worklog); final WorklogElement result = postWorklog(content, issueId); return result; } public WorklogElement postWorklog(String content, final String issueId) throws UniformInterfaceException, ClientHandlerException, IOException { ObjectMapper mapper; //content = "{\"comment\":\"I did some work here.\",\"started\":\"2016-03-23T04:22:37.471+0000\",\"timeSpentSeconds\":12000}"; logger.debug("Content=" + content); final String resource = Constants.JIRA_RESOURCE_ISSUE + "/" + issueId + "/worklog"; client.setResourceName(resource); ClientResponse response = client.post(content); content = response.getEntity(String.class); mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); TypeReference<WorklogElement> ref = new TypeReference<WorklogElement>() { }; WorklogElement resIssue = mapper.readValue(content, ref); return resIssue; } public IssueSearchResult getIssuesFromQuery(final String query) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); String content = URLEncoder.encode(query, "UTF-8"); logger.debug("Content=" + content); final String resource = "search?jql=" + content; logger.debug("resource=" + resource); client.setResourceName(resource); ClientResponse response = client.get(); content = response.getEntity(String.class); TypeReference<IssueSearchResult> ref = new TypeReference<IssueSearchResult>() { }; IssueSearchResult issues = mapper.readValue(content, ref); return issues; } }