/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.carbon.issue.tracker.mgt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.carbon.issue.tracker.adapter.api.GenericCredentials;
import org.wso2.carbon.issue.tracker.adapter.api.GenericIssue;
import org.wso2.carbon.issue.tracker.adapter.api.GenericIssueType;
import org.wso2.carbon.issue.tracker.adapter.api.GenericPriority;
import org.wso2.carbon.issue.tracker.adapter.exceptions.IssueTrackerException;
import org.wso2.carbon.issue.tracker.core.*;
import org.wso2.carbon.jira.reporting.JiraIssueReporter;
import org.wso2.carbon.registry.common.services.RegistryAbstractAdmin;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.utils.DataPaginator;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class IssueTrackerAdmin extends RegistryAbstractAdmin {
private final static Log log = LogFactory.getLog(IssueTrackerAdmin.class);
/**
* admin service to capture credentials and login
*
* @param credentials
* @return
* @throws IssueTrackerException
*/
public String login(GenericCredentials credentials) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
String token = null;
try {
token = reporter.login(credentials);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in login.", e, log);
}
return token;
}
/**
* admin service to validate credentials
*
* @param credentials
* @return
* @throws IssueTrackerException
*/
public String validateCredentials(GenericCredentials credentials) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
String token = null;
try {
token = reporter.login(credentials);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in login.", e, log);
}
return token;
}
public void captureAccountInfo(AccountInfo accountInfo) throws IssueTrackerException {
Registry registry = getGovernanceRegistry();
RegistryResourceHandler.persistCredentials(registry, accountInfo);
}
/**
* admin service to obtain JIRA account names from registry
*
* @return
* @throws IssueTrackerException
*/
public List<String> getAccountNames() throws IssueTrackerException {
Registry registry = getGovernanceRegistry();
List<AccountInfo> accountInfoList = RegistryResourceHandler.getAccounts(registry);
List<String> serverNameList = new ArrayList<String>();
for (AccountInfo s : accountInfoList) {
serverNameList.add(s.getKey());
}
return serverNameList;
}
/**
* admin service to obtain JIRA account information from the registry
*
* @return
* @throws IssueTrackerException
*/
public List<AccountInfo> getAccountInfo() throws IssueTrackerException {
Registry registry = getGovernanceRegistry();
List<AccountInfo> accountInfoList = null;
try {
accountInfoList = RegistryResourceHandler.getAccounts(registry);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in retrieving account info from registry", e, log);
}
return accountInfoList;
}
/**
* admin service to obtain account credentials given account name
*
* @param name
* @return
* @throws IssueTrackerException
*/
public GenericCredentials getAccountCredentials(String name) throws IssueTrackerException {
List<AccountInfo> accountInfoList = null;
GenericCredentials credentials = new GenericCredentials();
try {
accountInfoList = this.getAccountInfo();
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in retrieving account info from registry", e, log);
}
if (null != accountInfoList) {
for (AccountInfo info : accountInfoList) {
if (name.equals(info.getKey())) {
credentials.setUrl(info.getCredentials().getUrl());
credentials.setUsername(info.getCredentials().getUsername());
credentials.setPassword(info.getCredentials().getPassword());
break;
}
}
}
return credentials;
}
public AccountInfo getAccount(String name) throws IssueTrackerException {
List<AccountInfo> accountInfoList = null;
GenericCredentials credentials = new GenericCredentials();
AccountInfo accountInfo = null;
try {
accountInfoList = this.getAccountInfo();
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in retrieving account info from registry", e, log);
}
if (null != accountInfoList) {
for (AccountInfo info : accountInfoList) {
if (name.equals(info.getKey())) {
accountInfo = info;
break;
}
}
}
return accountInfo;
}
/**
* admin service to capture issue info and report to JIRA
*
* @param genericIssue
* @param token
* @param url
* @return
* @throws IssueTrackerException
*/
public String captureIssueInfo(GenericIssue genericIssue, String token, String url) throws IssueTrackerException {
String issueKey = null;
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
try {
issueKey = reporter.reportIssue(genericIssue, token, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error in reporting the issue", e, log);
}
return issueKey;
}
/**
* method to obtain project names as a JSONArray
*
* @param token
* @param url
* @return
* @throws IssueTrackerException
*/
private JSONArray getProjectNames(String token, String url) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
List<String> projectNames = null;
try {
projectNames = reporter.getJiraProjects(token, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error retrieving project names.", e, log);
}
JSONArray jsonArray = new JSONArray();
if (projectNames != null) {
for (String name : projectNames) {
jsonArray.put(name);
}
}
return jsonArray;
}
/**
* method to add issue types to JSONObject
*
* @param token
* @param jsonObject
* @param url
* @return
* @throws IssueTrackerException
*/
private JSONObject getIssueTypes(String token, JSONObject jsonObject, String url) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
List<GenericIssueType> issueTypes = null;
try {
issueTypes = reporter.getIssueTypes(token, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error obtaining issue types", e, log);
}
JSONArray issueNames = new JSONArray();
JSONArray issueID = new JSONArray();
if (issueTypes != null) {
for (GenericIssueType type : issueTypes) {
issueNames.put(type.getIssueType());
issueID.put(type.getId());
}
}
try {
jsonObject.put("issueId", issueID);
jsonObject.put("issueType", issueNames);
} catch (JSONException e) {
ExceptionHandler.handleException("Error creating JSON object for issue type.", e, log);
}
return jsonObject;
}
/**
* method to add priority types to JSONObject
*
* @param token
* @param jsonObject
* @param url
* @return
* @throws IssueTrackerException
*/
private JSONObject getPriorityTypes(String token, JSONObject jsonObject, String url) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
List<GenericPriority> priorities = null;
try {
priorities = reporter.getPriorityTypes(token, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error obtaining priority types", e, log);
}
JSONArray priorityNames = new JSONArray();
JSONArray priorityId = new JSONArray();
if (priorities != null) {
for (GenericPriority priority : priorities) {
priorityNames.put(priority.getName());
priorityId.put(priority.getId());
}
}
try {
jsonObject.put("priorityName", priorityNames);
jsonObject.put("priorityId", priorityId);
} catch (JSONException e) {
ExceptionHandler.handleException("Error creating JSON object for priority types.", e, log);
}
return jsonObject;
}
/**
* method to obtain project names and issue types as json string
*
* @param accountName
* @param url
* @return
* @throws org.wso2.carbon.issue.tracker.adapter.exceptions.IssueTrackerException
*
*/
public String getAccountSpecificData(String accountName, String url) throws IssueTrackerException {
AccountInfo accountInfo = this.getAccount(accountName);
String token = this.login(accountInfo.getCredentials());
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("project", this.getProjectNames(token, url));
jsonObject = this.getIssueTypes(token, jsonObject, url);
jsonObject = this.getPriorityTypes(token, jsonObject, url);
} catch (JSONException e) {
ExceptionHandler.handleException("Error constructing json object", e, log);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error obtaining project and issue types ", e, log);
}
return jsonObject.toString();
}
public String getAccountSpecificDetails(GenericCredentials credentials) throws IssueTrackerException {
String token = this.login(credentials);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("project", this.getProjectNames(token, credentials.getUrl()));
jsonObject = this.getIssueTypes(token, jsonObject, credentials.getUrl());
jsonObject = this.getPriorityTypes(token, jsonObject, credentials.getUrl());
} catch (JSONException e) {
ExceptionHandler.handleException("Error constructing json object", e, log);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error obtaining project and issue types ", e, log);
}
return jsonObject.toString();
}
/**
* admin service to delete accounts
*
* @param key
* @return
* @throws IssueTrackerException
*/
public boolean deleteAccount(String key) throws IssueTrackerException {
boolean isDeleted = false;
String path = IssueTrackerConstants.ISSUE_TRACKERS_RESOURCE_PATH + key;
Registry registry = getGovernanceRegistry();
try {
registry.delete(path);
isDeleted = true;
} catch (RegistryException e) {
ExceptionHandler.handleException("Unable to delete " + key + " from registry", e, log);
}
return isDeleted;
}
/**
* admin service to retrieve issues
*
* @param token
* @param url
* @param maxResults
* @return
* @throws IssueTrackerException
*/
public List<GenericIssue> retrieveIssues(String token, String url, int maxResults) throws IssueTrackerException {
List<GenericIssue> genericIssues = new ArrayList<GenericIssue>();
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
try {
genericIssues = reporter.retrieveIssuesByQuery(token, url, maxResults);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Unable to retrieve issues for ", e, log);
}
return genericIssues;
}
/**
* admin service to attach files
*
* @param token
* @param issueKey
* @param attachmentData
* @param url
* @return
* @throws IssueTrackerException
* @throws java.io.IOException
*/
public boolean attachFiles(String token, String issueKey, AttachmentData[] attachmentData, String url) throws IssueTrackerException, IOException {
List<String> fileNames = new ArrayList<String>();
List<String> data = new ArrayList<String>();
for (AttachmentData attachment : attachmentData) {
String fileName = attachment.getFileName();
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
fileNames.add(attachment.getFileName());
if ("png".equals(fileExtension) || "jpg".equals(fileExtension) || "jpeg".equals(fileExtension)
|| "gif".equals(fileExtension)) {
FileOutputStream fileOutputStream = null;
try {
File tempAttachment = new File(System.getProperty(IssueTrackerConstants.JAVA_IO_TEMP_DIR) + "/" + attachment.getFileName());
fileOutputStream = new FileOutputStream(tempAttachment);
attachment.getDataHandler().writeTo(fileOutputStream);
fileOutputStream.close();
BufferedImage _image = ImageIO.read(tempAttachment);
if (_image != null) {
java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream();
ImageIO.write(_image, "jpg", os);
byte[] bytes = os.toByteArray();
String image = new sun.misc.BASE64Encoder().encode(bytes);
data.add(image);
os.close();
boolean isDeleted = tempAttachment.delete();
}
} catch (IOException e) {
ExceptionHandler.handleException("Unable to attach images ", e, log);
} finally {
if (fileOutputStream != null) {
fileOutputStream.close();
}
}
} else {
try {
InputStream inputStream = attachment.getDataHandler().getDataSource().getInputStream();
byte[] bytes = new byte[inputStream.available()];
int size = inputStream.read(bytes);
String base64String = new sun.misc.BASE64Encoder().encode(new String(bytes).getBytes());
data.add(base64String);
} catch (IOException e) {
ExceptionHandler.handleException("Unable to read attachments ", e, log);
}
}
}
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
String[] fileNameArray = fileNames.toArray(new String[fileNames.size()]);
String[] dataArray = data.toArray(new String[data.size()]);
return reporter.attachFiles(token, issueKey, fileNameArray, dataArray, url);
}
/**
* admin service to attach bundle.info file
*
* @param token
* @param issueKey
* @param url
* @return
* @throws IssueTrackerException
*/
public boolean attachBundleInfo(String token, String issueKey, String url) throws IssueTrackerException {
boolean success = false;
String carbonHome = new File("").getAbsolutePath();
String bundlesInfoPath = carbonHome + IssueTrackerConstants.BUNDLE_INFO_PATH +
IssueTrackerConstants.BUNDLE_INFO_FILE_NAME;
File bundleInfoFile = new File(bundlesInfoPath);
if (bundleInfoFile.exists()) {
AttachmentData[] attachmentData = new AttachmentData[1];
AttachmentData data = new AttachmentData();
data.setFileName(IssueTrackerConstants.BUNDLE_INFO_FILE_NAME);
DataHandler dataHandler = new DataHandler(new FileDataSource(bundleInfoFile));
data.setDataHandler(dataHandler);
attachmentData[0] = data;
try {
success = attachFiles(token, issueKey, attachmentData, url);
} catch (IssueTrackerException e) {
String msg = "Unable to attach bundles.info file " + carbonHome +
IssueTrackerConstants.BUNDLE_INFO_PATH + IssueTrackerConstants.BUNDLE_INFO_FILE_NAME;
ExceptionHandler.handleException(msg, e, log);
} catch (IOException e) {
String msg = "Unable to attach bundles.info file " + carbonHome +
IssueTrackerConstants.BUNDLE_INFO_PATH + IssueTrackerConstants.BUNDLE_INFO_FILE_NAME;
ExceptionHandler.handleException(msg, e, log);
}
}
return success;
}
/**
* admin service to attach thread dump to the issue
*
* @param token
* @param issueKey
* @param url
* @return
* @throws IssueTrackerException
*/
public boolean attachThreadDump(String token, String issueKey, String url) throws IssueTrackerException {
boolean success = false;
ThreadDump threadDump = new ThreadDump();
try {
File file = threadDump.saveThreadDump();
if (file.exists()) {
AttachmentData[] attachmentData = new AttachmentData[1];
AttachmentData data = new AttachmentData();
data.setFileName(IssueTrackerConstants.THREAD_DUMP_FILE_NAME);
DataHandler dataHandler = new DataHandler(new FileDataSource(file));
data.setDataHandler(dataHandler);
attachmentData[0] = data;
success = attachFiles(token, issueKey, attachmentData, url);
}
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Unable to attach bundles.info file", e, log);
} catch (IOException e) {
ExceptionHandler.handleException("Unable to attach bundles.info file", e, log);
}
return success;
}
/**
* admin service to attach log file to the issue
*
* @param token
* @param issueKey
* @param url
* @return
* @throws IssueTrackerException
*/
public boolean attachLogFile(String token, String issueKey, String url) throws IssueTrackerException {
boolean success = false;
String carbonHome = new File("").getAbsolutePath();
String logFilePath = carbonHome + IssueTrackerConstants.LOG_FILE_PATH + IssueTrackerConstants.LOG_FILE_NAME;
File logFile = new File(logFilePath);
if (logFile.exists()) {
AttachmentData[] attachmentData = new AttachmentData[1];
AttachmentData data = new AttachmentData();
data.setFileName(IssueTrackerConstants.LOG_FILE_NAME);
DataHandler dataHandler = new DataHandler(new FileDataSource(logFilePath));
data.setDataHandler(dataHandler);
attachmentData[0] = data;
try {
success = attachFiles(token, issueKey, attachmentData, url);
} catch (IssueTrackerException e) {
String msg = "Unable to attach file " + carbonHome +
IssueTrackerConstants.LOG_FILE_PATH + IssueTrackerConstants.LOG_FILE_NAME;
ExceptionHandler.handleException(msg, e, log);
} catch (IOException e) {
String msg = "Unable to attach file " + carbonHome +
IssueTrackerConstants.LOG_FILE_PATH + IssueTrackerConstants.LOG_FILE_NAME;
ExceptionHandler.handleException(msg, e, log);
}
}
return success;
}
/**
* admin service to obtain issue count from a filter
*
* @param token
* @param url
* @return
* @throws IssueTrackerException
*/
public long getIssueCount(String token, String url) throws IssueTrackerException {
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
long count = 0;
try {
count = reporter.getIssueCount(token, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error retrieving issue count.", e, log);
}
return count;
}
/**
* admin service to obtain paginated issue info
*
* @param pageNumber
* @param token
* @param url
* @return
* @throws Exception
*/
public PaginatedIssueInfo getPaginatedIssueInfo(int pageNumber, String token, String url) throws Exception {
//page numbers starts from zero
//1 is added to see whether there are more pages
int maxNumberOfResults = (pageNumber + 1) * IssueTrackerConstants.ISSUES_PER_PAGE +
IssueTrackerConstants.ISSUES_PER_PAGE * 3 + 1;
List<GenericIssue> issueInfoList = retrieveIssues(token, url, maxNumberOfResults);
// Pagination
PaginatedIssueInfo paginatedIssueInfo = new PaginatedIssueInfo();
DataPaginator.doPaging(pageNumber, issueInfoList, paginatedIssueInfo);
return paginatedIssueInfo;
}
/**
* admin service to delete issues
*
* @param token authn token
* @param issueKey issue key
* @param url JIRA url
* @return true if the issue is deleted
* @throws IssueTrackerException thrown in case of a failure to establish the connection with JiraSoapService or an
* erron in deleting the issue.
*/
public boolean deleteIssue(String token, String issueKey, String url) throws IssueTrackerException {
boolean isIssueDeleted = false;
JiraIssueReporter reporter = JiraIssueReporter.getInstance();
try {
isIssueDeleted = reporter.deleteIssues(token, issueKey, url);
} catch (IssueTrackerException e) {
ExceptionHandler.handleException("Error deleting the issue " + issueKey + ".", e, log);
}
return isIssueDeleted;
}
}