/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.github.server.rest;
import org.eclipse.che.api.core.ApiException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.git.exception.GitException;
import org.eclipse.che.api.ssh.shared.dto.GenerateSshPairRequest;
import org.eclipse.che.api.ssh.shared.model.SshPair;
import org.eclipse.che.plugin.github.server.GitHubDTOFactory;
import org.eclipse.che.plugin.github.server.GitHubFactory;
import org.eclipse.che.plugin.github.server.GitHubKeyUploader;
import org.eclipse.che.plugin.github.shared.Collaborators;
import org.eclipse.che.plugin.github.shared.GitHubIssueCommentInput;
import org.eclipse.che.plugin.github.shared.GitHubPullRequest;
import org.eclipse.che.plugin.github.shared.GitHubPullRequestCreationInput;
import org.eclipse.che.plugin.github.shared.GitHubPullRequestList;
import org.eclipse.che.plugin.github.shared.GitHubRepository;
import org.eclipse.che.plugin.github.shared.GitHubRepositoryList;
import org.eclipse.che.plugin.github.shared.GitHubUser;
import org.eclipse.che.plugin.ssh.key.SshServiceClient;
import org.kohsuke.github.GHIssueState;
import org.kohsuke.github.GHPullRequest;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.List;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
/**
* REST service to get the list of repositories from GitHub (where sample projects are located).
*
* @author Oksana Vereshchaka
* @author Stéphane Daviet
* @author Kevin Pollet
* @author Igor vinokur
*/
@Path("/github")
public class GitHubService {
@Inject
private GitHubFactory gitHubFactory;
@Inject
private GitHubDTOFactory gitHubDTOFactory;
@Inject
private GitHubKeyUploader githubKeyUploader;
@Inject
private SshServiceClient sshServiceClient;
private static final Logger LOG = LoggerFactory.getLogger(GitHubService.class);
@GET
@Path("repositories/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepository getUserRepository(@PathParam("user") String user, @PathParam("repository") String repository)
throws ApiException {
try {
return gitHubDTOFactory.createRepository(gitHubFactory.connect().getUser(user).getRepository(repository));
} catch (IOException e) {
LOG.error("Get user info error", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("list/user")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepositoryList listRepositoriesByUser(@QueryParam("username") String userName) throws ApiException {
try {
return gitHubDTOFactory.createRepositoriesList(gitHubFactory.connect().getUser(userName).listRepositories());
} catch (IOException e) {
LOG.error("Get list repositories by user fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("list/org")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepositoryList listRepositoriesByOrganization(@QueryParam("organization") String organization) throws ApiException {
try {
return gitHubDTOFactory.createRepositoriesList(gitHubFactory.connect().getOrganization(organization).listRepositories());
} catch (IOException e) {
LOG.error("Get list repositories by organization fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("list/account")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepositoryList listRepositoriesByAccount(@QueryParam("account") String account) throws ApiException {
GitHub gitHub = gitHubFactory.connect();
try {
//First, try to retrieve organization repositories:
return gitHubDTOFactory.createRepositoriesList(gitHub.getOrganization(account).listRepositories());
} catch (IOException ioException) {
LOG.error("Get list repositories by account fail", ioException);
//If account is not organization, then try by user name:
try {
return gitHubDTOFactory.createRepositoriesList(gitHub.getUser(account).listRepositories());
} catch (IOException exception) {
LOG.error("Get list repositories by account fail", exception);
throw new ServerException(exception.getMessage());
}
}
}
@GET
@Path("list")
@Produces(MediaType.APPLICATION_JSON)
public List<GitHubRepository> listRepositories() throws ApiException {
try {
return gitHubDTOFactory.createRepositoriesList(gitHubFactory.connect().getMyself().listRepositories()).getRepositories();
} catch (IOException e) {
LOG.error("Get list repositories fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("forks/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepositoryList forks(@PathParam("user") String user, @PathParam("repository") String repository) throws ApiException {
GitHubRepositoryList gitHubRepositoryList;
try {
gitHubRepositoryList = gitHubDTOFactory.createRepositoriesList();
for (GHRepository ghRepository : gitHubFactory.connect().getMyself().listRepositories()) {
if (ghRepository.isFork() && ghRepository.getName().equals(repository)) {
gitHubRepositoryList = gitHubDTOFactory.createRepositoriesList(ghRepository);
break;
}
}
} catch (IOException e) {
LOG.error("Get forks fail", e);
throw new ServerException(e.getMessage());
}
return gitHubRepositoryList;
}
@GET
@Path("createfork/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubRepository fork(@PathParam("user") String user, @PathParam("repository") String repository) throws ApiException {
try {
return gitHubDTOFactory.createRepository(gitHubFactory.connect().getUser(user).getRepository(repository).fork());
} catch (IOException e) {
LOG.error("Fork fail", e);
throw new ServerException(e.getMessage());
}
}
@POST
@Path("issuecomments/{user}/{repository}/{issue}")
@Produces(MediaType.APPLICATION_JSON)
public void commentIssue(@PathParam("user") String user,
@PathParam("repository") String repository,
@PathParam("issue") String issue,
GitHubIssueCommentInput input) throws ApiException {
try {
gitHubFactory.connect().getUser(user).getRepository(repository).getIssue(Integer.getInteger(issue)).comment(input.getBody());
} catch (IOException e) {
LOG.error("Comment issue fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("pullrequests/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubPullRequestList listPullRequestsByRepository(@PathParam("user") String user,
@PathParam("repository") String repository,
@QueryParam("head") String head)
throws ApiException {
try {
return gitHubDTOFactory.createPullRequestsList(gitHubFactory.connect()
.getUser(user)
.getRepository(repository)
.queryPullRequests()
.head(head)
.state(GHIssueState.OPEN)
.list());
} catch (IOException e) {
LOG.error("Getting list of pull request by repositories", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("pullrequests/{user}/{repository}/{pullRequestId}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubPullRequestList getPullRequestsById(@PathParam("user") String user, @PathParam("repository") String repository, @PathParam("pullRequestId") String pullRequestId)
throws ApiException {
try {
return gitHubDTOFactory.createPullRequestsList(gitHubFactory.connect().getUser(user).getRepository(repository)
.getPullRequest(Integer.valueOf(pullRequestId)));
} catch (IOException e) {
LOG.error("Getting list of pull request by id", e);
throw new ServerException(e.getMessage());
}
}
@POST
@Path("pullrequest/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubPullRequest createPullRequest(@PathParam("user") String user, @PathParam("repository") String repository, GitHubPullRequestCreationInput input)
throws ApiException {
try {
GHPullRequest pullRequest = gitHubFactory.connect().getUser(user).getRepository(repository).createPullRequest(
input.getTitle(), input.getHead(), input.getBase(), input.getBody());
return gitHubDTOFactory.createPullRequest(pullRequest);
} catch (Exception e) {
if (!e.getMessage().contains("No commits between master and master")) {
LOG.error("Creating pull request fail", e);
}
throw new ServerException(e.getMessage());
}
}
@PUT
@Path("pullrequest/{user}/{repository}/{pullRequestId}")
@Produces(MediaType.APPLICATION_JSON)
public GitHubPullRequest updatePullRequest(@PathParam("user")
String user,
@PathParam("repository")
String repository,
@PathParam("pullRequestId")
String pullRequestId,
GitHubPullRequest pullRequest) throws ServerException,
UnauthorizedException {
try {
final GHPullRequest ghPullRequest = gitHubFactory.connect()
.getUser(user)
.getRepository(repository)
.getPullRequest(Integer.valueOf(pullRequestId));
final String body = pullRequest.getBody();
if (body != null && !body.equals(ghPullRequest.getBody())) {
ghPullRequest.setBody(body);
}
final String title = pullRequest.getTitle();
if (title != null && !title.equals(ghPullRequest.getTitle())) {
ghPullRequest.setTitle(title);
}
return gitHubDTOFactory.createPullRequest(ghPullRequest);
} catch (IOException ioEx) {
throw new ServerException(ioEx.getMessage());
}
}
@GET
@Path("orgs")
@Produces(MediaType.APPLICATION_JSON)
public List<GitHubUser> listOrganizations() throws ApiException {
try {
return gitHubDTOFactory.createCollaborators(gitHubFactory.connect().getMyself().getAllOrganizations()).getCollaborators();
} catch (IOException e) {
LOG.error("Getting list of available organizations fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("user")
@Produces(MediaType.APPLICATION_JSON)
public GitHubUser getUserInfo() throws ApiException {
try {
return gitHubDTOFactory.createUser(gitHubFactory.connect().getMyself());
} catch (IOException e) {
LOG.error("Getting user info fail", e);
throw new ServerException(e.getMessage());
}
}
@GET
@Path("collaborators/{user}/{repository}")
@Produces(MediaType.APPLICATION_JSON)
public Collaborators collaborators(@PathParam("user") String user, @PathParam("repository") String repository) throws ApiException {
try {
return gitHubDTOFactory.createCollaborators(gitHubFactory.connect().getUser(user).getRepository(repository).getCollaborators());
} catch (IOException e) {
LOG.error("Get collaborators fail", e);
throw new ServerException(e.getMessage());
}
}
@POST
@Path("ssh/generate")
public void updateSSHKey() throws ApiException {
final String host = "github.com";
SshPair sshPair = null;
try {
sshPair = sshServiceClient.getPair("vcs", host);
} catch (NotFoundException ignored) {
}
if (sshPair != null) {
if (sshPair.getPublicKey() == null) {
sshServiceClient.removePair("vcs", host);
sshPair = sshServiceClient.generatePair(newDto(GenerateSshPairRequest.class).withService("vcs")
.withName(host));
}
} else {
sshPair = sshServiceClient.generatePair(newDto(GenerateSshPairRequest.class).withService("vcs")
.withName(host));
}
// update public key
try {
githubKeyUploader.uploadKey(sshPair.getPublicKey());
} catch (IOException e) {
LOG.error("Upload github ssh key fail", e);
throw new GitException(e.getMessage(), e);
}
}
}