package edu.ncsu.dlf.servlet; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import edu.ncsu.dlf.database.DBAbstraction; import edu.ncsu.dlf.database.DatabaseFactory; import edu.ncsu.dlf.model.Repo; import edu.ncsu.dlf.model.Review; import edu.ncsu.dlf.utils.HttpUtils; import org.eclipse.egit.github.core.Issue; import org.eclipse.egit.github.core.Label; import org.eclipse.egit.github.core.Repository; import org.eclipse.egit.github.core.User; import org.eclipse.egit.github.core.client.GitHubClient; import org.eclipse.egit.github.core.service.CollaboratorService; import org.eclipse.egit.github.core.service.IssueService; import org.eclipse.egit.github.core.service.LabelService; import org.eclipse.egit.github.core.service.RepositoryService; import org.eclipse.egit.github.core.service.UserService; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class ReviewRequestServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { String body = HttpUtils.getRequestBody(req); GitHubClient client = new GitHubClient(); client.setOAuth2Token(req.getParameter("access_token")); UserService userService = new UserService(client); List<Review> newReviews = createNewReviews(body, userService); IssueService issueService = new IssueService(client); RepositoryService repoService = new RepositoryService(client); CollaboratorService collaboratorService = new CollaboratorService(client); Review aReview = newReviews.get(0); //all these reviews have the same requester and repo involved User reviewRequester = userService.getUser(aReview.requester.login); Repository gitRepo = repoService.getRepository(aReview.repo.repoOwner, aReview.repo.repoName); boolean isOrg = "Organization".equals(reviewRequester.getType()); //addCommentsToPDF(pathToPaper, paper); JSONObject returnJson = new JSONObject(); for(Review review : newReviews) { if(!isOrg) { try { collaboratorService.addCollaborator(gitRepo, review.reviewer.login); } catch (Exception e) { if (!returnJson.has("message")) returnJson.put("message", "However, we could not add the reviewer(s) as collaborator(s). " + "This happens if you don't own the repo you are making a request for."); System.out.println("Could not add collaborator, maybe you don't own the repo?"); } } try { Label reviewRequestLabel = makeOrGetReviewRequestLabel(client, review.repo); createReviewRequestIssue(reviewRequestLabel, review, issueService, userService); DBAbstraction database = DatabaseFactory.getDatabase(); database.addReviewToDatastore(review); } catch(IOException e) { resp.sendError(417); return; } } resp.setStatus(200); resp.setContentType("application/json"); returnJson.write(resp.getWriter()); } catch (Exception e) { e.printStackTrace(); resp.setStatus(500); } } private Label makeOrGetReviewRequestLabel(GitHubClient client, Repo repo) { Label reviewRequestLabel = new Label().setColor("009800").setName("Review Request"); LabelService labelService = new LabelService(client); try { reviewRequestLabel = labelService.getLabel(repo.repoOwner, repo.repoName, "Review Request"); } catch(IOException e) { System.out.println("Review Request Label not found. Going to create it"); try { reviewRequestLabel = labelService.createLabel(repo.repoOwner, repo.repoName, reviewRequestLabel); } catch (IOException e1) { e1.printStackTrace(); //this is a bigger problem } } return reviewRequestLabel; } private void createReviewRequestIssue(Label reviewRequestLabel, Review review, IssueService issueService, UserService userService) throws IOException { Issue issue = new Issue(); issue.setTitle("Reviewer - " + review.reviewer.login); List<Label> labels = new ArrayList<>(); labels.add(reviewRequestLabel); issue.setLabels(labels); issue.setAssignee(userService.getUser(review.reviewer.login)); String downloadLink = "https://github.com/" + review.repo.repoOwner + '/' + review.repo.repoName + "/raw/master/" + review.pathToPaperInRepo; issue.setBody("@" + review.reviewer.login + " has been requested to review this paper by @"+review.requester.login+".\n" + "Click [here](" + downloadLink + ") to download the paper\n" + "Click [here](" + review.linkToReviewPaper + ") to upload your review."); issueService.createIssue(review.repo.repoOwner, review.repo.repoName, issue); } private List<Review> createNewReviews(String body, UserService userService) throws JSONException, IOException { JSONObject data = new JSONObject(body); JSONArray reviewersJson = data.getJSONArray("reviewers"); String repoOwner = data.getString("owner"); String repoName = data.getString("repo"); String pathToPaper = data.getString("pathToPaper"); String paper = data.getString("paper"); String requesterLogin = data.getString("login"); String customLabels = data.getString("customLabels"); List<String> parsedCustomLabels = parseCustomLabels(customLabels); //all reviews will have the same labels String pathToPaperInRepo = pathToPaper + "/" + paper; String linkToRespondToReview = "/?repoName=" + repoName + "&writer=" + repoOwner + "&paper=" + pathToPaperInRepo; List<Review> newReviews = new ArrayList<>(); for(int i=0; i<reviewersJson.length(); i++) { String reviewerLogin = reviewersJson.getString(i); Review newReview = new Review(requesterLogin, repoOwner, reviewerLogin, repoName, pathToPaperInRepo, linkToRespondToReview, userService); newReview.setCustomLabels(parsedCustomLabels); newReviews.add(newReview); } return newReviews; } private static List<String> parseCustomLabels(String customLabels) { Pattern pattern = Pattern.compile("\\[.+?\\]"); Matcher m = pattern.matcher(customLabels); List<String> retVal = new ArrayList<>(); while (m.find()) { String labelWithBrackets = m.group(); retVal.add(labelWithBrackets.substring(1, labelWithBrackets.length()-1)); } return retVal; } @SuppressWarnings("unused") private void addCommentsToPDF(String pathToPaper, String paper) { // TODO See https://github.com/DeveloperLiberationFront/Pdf-Reviewer/issues/20 // Should add a comment to the front of the pdf with a memo about tags } @Override protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // handle the DELETE request GitHubClient client = new GitHubClient(); client.setOAuth2Token(req.getParameter("access_token")); String repoOwner = req.getParameter("writer"); String reviewer = req.getParameter("reviewer"); String repoName = req.getParameter("repo"); Repo repo = new Repo(repoOwner, repoName); String closeComment = "@" + reviewer + " is no longer reviewing this paper."; ReviewSubmitServlet.closeReviewIssue(client, repo, reviewer, closeComment); DBAbstraction database = DatabaseFactory.getDatabase(); database.removeReviewFromDatastore(reviewer, repo); } }