package argelbargel.jenkins.plugins.gitlab_branch_source.api; import org.apache.commons.lang.StringUtils; import org.gitlab.api.GitlabAPI; import org.gitlab.api.http.Query; import org.gitlab.api.models.GitlabBranch; import org.gitlab.api.models.GitlabCommit; import org.gitlab.api.models.GitlabGroup; import org.gitlab.api.models.GitlabProject; import org.gitlab.api.models.GitlabProjectHook; import org.gitlab.api.models.GitlabRepositoryTree; import org.gitlab.api.models.GitlabSystemHook; import org.gitlab.api.models.GitlabTag; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLEncoder; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import java.util.logging.Logger; import static argelbargel.jenkins.plugins.gitlab_branch_source.api.GitLabProjectSelector.VISIBLE; import static argelbargel.jenkins.plugins.gitlab_branch_source.api.GitLabProjectVisibility.ALL; public final class GitLabAPI { private static final String PATH_SEP = "/"; public static GitLabAPI connect(String url, String token, boolean ignoreCertificateErrors, int requestTimeout) throws GitLabAPIException { try { GitlabAPI delegate = GitlabAPI.connect(url, token); delegate.ignoreCertificateErrors(ignoreCertificateErrors); return new GitLabAPI(delegate); } catch (Exception e) { throw new GitLabAPIException(e); } } private static final Logger LOGGER = Logger.getLogger(GitLabAPI.class.getName()); private final GitlabAPI delegate; private GitLabAPI(GitlabAPI delegate) { this.delegate = delegate; } public String getVersion() throws GitLabAPIException { try { return delegate.retrieve().to("/version", GitLabVersion.class).toString(); } catch (IOException e) { throw new GitLabAPIException(e); } } public GitLabProject getProject(int id) throws GitLabAPIException { return getProject((Serializable) id); } public GitLabProject getProject(String name) throws GitLabAPIException { return getProject((Serializable) encode(name)); } private GitLabProject getProject(Serializable nameOrId) throws GitLabAPIException { try { String tailUrl = GitlabProject.URL + "/" + nameOrId; return delegate.retrieve().to(tailUrl, GitLabProject.class); } catch (FileNotFoundException e) { throw new NoSuchElementException("unknown project " + nameOrId); } catch (IOException e) { throw new GitLabAPIException(e); } } public List<GitlabBranch> getBranches(int id) throws GitLabAPIException { return getBranches((Serializable) id); } private List<GitlabBranch> getBranches(Serializable nameOrId) throws GitLabAPIException { try { return delegate.getBranches(nameOrId); } catch (Exception e) { throw new GitLabAPIException(e); } } public GitlabBranch getBranch(int projectId, String branch) throws GitLabAPIException { try { String tailUrl = GitlabProject.URL + PATH_SEP + projectId + GitlabBranch.URL + PATH_SEP + URLEncoder.encode(branch, "UTF-8"); tailUrl = tailUrl.replaceAll("//", "/"); return delegate.retrieve().to(tailUrl, GitlabBranch.class); } catch (FileNotFoundException e) { throw new NoSuchElementException("unknown branch " + branch); } catch (Exception e) { throw new GitLabAPIException(e); } } public List<GitlabTag> getTags(int id) throws GitLabAPIException { return getTags((Serializable) id); } private List<GitlabTag> getTags(Serializable nameOrId) throws GitLabAPIException { try { return delegate.getTags(nameOrId); } catch (IOException e) { throw new GitLabAPIException(e); } } public GitlabTag getTag(int projectId, String tag) throws GitLabAPIException { try { String tailUrl = GitlabProject.URL + PATH_SEP + projectId + GitlabTag.URL + PATH_SEP + URLEncoder.encode(tag, "UTF-8"); return delegate.retrieve().to(tailUrl, GitlabTag.class); } catch (FileNotFoundException e) { throw new NoSuchElementException("unknown tag " + tag); } catch (Exception e) { throw new GitLabAPIException(e); } } public List<GitLabMergeRequest> getMergeRequests(int projectId) throws GitLabAPIException { try { String tailUrl = "/projects/" + projectId + "/merge_requests?state=opened"; return delegate.retrieve() .getAll(tailUrl, GitLabMergeRequest[].class); } catch (Exception e) { throw new GitLabAPIException(e); } } public GitLabMergeRequest getMergeRequest(int projectId, String mergeRequestId) throws GitLabAPIException { return getMergeRequest(projectId, Integer.parseInt(mergeRequestId)); } public GitLabMergeRequest getMergeRequest(int projectId, int mergeRequestId) throws GitLabAPIException { try { String tailUrl = "/projects/" + projectId + "/merge_requests/" + mergeRequestId; return delegate.retrieve().to(tailUrl, GitLabMergeRequest.class); } catch (FileNotFoundException e) { throw new NoSuchElementException("unknown merge-request for project " + projectId + ": " + mergeRequestId); } catch (Exception e) { throw new GitLabAPIException(e); } } public List<GitLabProject> findProjects(String group, GitLabProjectSelector selector, GitLabProjectVisibility visibility, String searchPattern) throws GitLabAPIException { LOGGER.fine("finding projects for group" + group + ", " + selector + ", " + visibility + ", " + searchPattern + "..."); return findProjects(projectUrl(group, selector, visibility, searchPattern)); } public List<GitLabProject> findProjects(GitLabProjectSelector selector, GitLabProjectVisibility visibility, String searchPattern) throws GitLabAPIException { LOGGER.fine("finding projects for " + selector + ", " + visibility + ", " + searchPattern + "..."); return findProjects(projectUrl(selector, visibility, searchPattern)); } private List<GitLabProject> findProjects(String url) throws GitLabAPIException { try { return delegate .retrieve() .getAll(url, GitLabProject[].class); } catch (Exception e) { throw new GitLabAPIException(e); } } public GitLabGroup getGroup(int id) throws GitLabAPIException { try { return delegate.retrieve().to(GitlabGroup.URL + PATH_SEP + id, GitLabGroup.class); } catch (Exception e) { throw new GitLabAPIException(e); } } public GitlabCommit getCommit(int id, String ref) throws GitLabAPIException { try { return delegate.getCommit(id, ref); } catch (Exception e) { throw new GitLabAPIException(e); } } public List<GitlabRepositoryTree> getTree(int id, String ref, String path) throws GitLabAPIException { try { Query query = new Query() .appendIf("path", path) .appendIf("ref", ref); query.append("per_page","10000"); String tailUrl = GitlabProject.URL + "/" + id + "/repository" + GitlabRepositoryTree.URL + query.toString(); LOGGER.fine("tailurl: " + tailUrl); GitlabRepositoryTree[] tree = delegate.retrieve().to(tailUrl, GitlabRepositoryTree[].class); return Arrays.asList(tree); } catch (Exception e) { throw new GitLabAPIException(e); } } public GitlabSystemHook registerSystemHook(URL url) throws GitLabAPIException { try { return registerSystemHook(url.toString()); } catch (IOException e) { throw new GitLabAPIException(e); } } private GitlabSystemHook registerSystemHook(String url) throws IOException { LOGGER.fine("registering system-hook " + url + "..."); for (GitlabSystemHook hook : delegate.getSystemHooks()) { if (hook.getUrl().equals(url)) { return hook; } } return delegate.dispatch() .with("url", url) .with("push_events", false) .to("/hooks", GitlabSystemHook.class); } public boolean unregisterSystemHook(URL url) throws GitLabAPIException { try { return unregisterSystemHook(url.toString()); } catch (IOException e) { throw new GitLabAPIException(e); } } private boolean unregisterSystemHook(String url) throws IOException { LOGGER.finer("looking up system-hooks..."); for (GitlabSystemHook hook : delegate.getSystemHooks()) { if (hook.getUrl().equals(url)) { LOGGER.fine("un-registering system-hook " + url + "..."); delegate.deleteSystemHook(hook.getId()); return true; } } return false; } public GitlabProjectHook registerProjectHook(URL url, int projectId) throws GitLabAPIException { try { return registerProjectHook(url.toString(), projectId); } catch (IOException e) { throw new GitLabAPIException(e); } } private GitlabProjectHook registerProjectHook(String url, int projectId) throws IOException { LOGGER.fine("registering project-hook for project " + projectId + ": " + url + "..."); for (GitlabProjectHook hook : delegate.getProjectHooks(projectId)) { if (hook.getUrl().equals(url)) { return hook; } } return delegate.addProjectHook(projectId, url, true, false, true, true, false); } public boolean unregisterProjectHook(URL url, int projectId) throws GitLabAPIException { try { return unregisterProjectHook(url.toString(), projectId); } catch (IOException e) { throw new GitLabAPIException(e); } } private boolean unregisterProjectHook(String url, int projectId) throws IOException { LOGGER.finer("looking up project-hooks for project " + projectId + "..."); for (GitlabProjectHook hook : delegate.getProjectHooks(projectId)) { if (hook.getUrl().equals(url)) { LOGGER.fine("un-registering project-hook for project " + projectId + ": " + url + "..."); String tailUrl = GitlabProject.URL + PATH_SEP + hook.getProjectId() + GitlabProjectHook.URL + PATH_SEP + hook.getId(); delegate.retrieve().method("DELETE").to(tailUrl, GitlabProjectHook[].class); return true; } } return false; } private String projectUrl(String group, GitLabProjectSelector selector, GitLabProjectVisibility visibility, String searchPattern) { StringBuilder urlBuilder = new StringBuilder(GitlabGroup.URL).append(PATH_SEP).append(group).append(GitLabProject.URL).append("?membership=true"); if (!VISIBLE.equals(selector)) { urlBuilder.append("&").append(selector.id()).append("=true"); } if (!ALL.equals(visibility)) { urlBuilder.append("&visibility=").append(visibility.id()); } if (!StringUtils.isEmpty(searchPattern)) { urlBuilder.append("&search=").append(searchPattern); } return urlBuilder.toString(); } private String projectUrl(GitLabProjectSelector selector, GitLabProjectVisibility visibility, String searchPattern) { StringBuilder urlBuilder = new StringBuilder(GitlabProject.URL).append("?membership=true"); if (!VISIBLE.equals(selector)) { urlBuilder.append("&").append(selector.id()).append("=true"); } if (!ALL.equals(visibility)) { urlBuilder.append("&visibility=").append(visibility.id()); } if (!StringUtils.isEmpty(searchPattern)) { urlBuilder.append("&search=").append(searchPattern); } return urlBuilder.toString(); } private String encode(String in) throws GitLabAPIException { try { return URLEncoder.encode(in, "utf-8"); } catch (UnsupportedEncodingException e) { throw new GitLabAPIException(e); } } }