Repository: camel Updated Branches: refs/heads/master 22c7edc0c -> 97c4ffea8
CAMEL-7777 GitHub component Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f0f341e2 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f0f341e2 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f0f341e2 Branch: refs/heads/master Commit: f0f341e24b252a946bc3649d352072a44fa32c56 Parents: 22c7edc Author: Brett Meyer <br...@3riverdev.com> Authored: Wed Sep 17 14:19:10 2014 -0400 Committer: Willem Jiang <willem.ji...@gmail.com> Committed: Mon Sep 22 16:18:01 2014 +0800 ---------------------------------------------------------------------- components/camel-github/pom.xml | 67 ++++++++ .../camel/component/github/GitHubComponent.java | 34 ++++ .../camel/component/github/GitHubEndpoint.java | 171 +++++++++++++++++++ .../github/consumer/AbstractGitHubConsumer.java | 44 +++++ .../github/consumer/CommitConsumer.java | 71 ++++++++ .../component/github/consumer/ConsumerType.java | 31 ++++ .../consumer/PullRequestCommentConsumer.java | 95 +++++++++++ .../github/consumer/PullRequestConsumer.java | 75 ++++++++ .../component/github/consumer/TagConsumer.java | 65 +++++++ .../github/producer/AbstractGitHubProducer.java | 44 +++++ .../component/github/producer/ProducerType.java | 31 ++++ .../producer/PullRequestCommentProducer.java | 69 ++++++++ .../services/org/apache/camel/component/github | 18 ++ .../src/main/resources/log4j.properties | 16 ++ components/pom.xml | 1 + 15 files changed, 832 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-github/pom.xml b/components/camel-github/pom.xml new file mode 100644 index 0000000..ef37419 --- /dev/null +++ b/components/camel-github/pom.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor + license agreements. See the NOTICE file distributed with this work for additional + information regarding copyright ownership. The ASF 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. --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>2.15-SNAPSHOT</version> + </parent> + + <artifactId>camel-github</artifactId> + <packaging>bundle</packaging> + <name>Camel :: GitHub</name> + + <properties> + <camel.osgi.export.pkg>org.apache.camel.component.github.*</camel.osgi.export.pkg> + <camel.osgi.export.service>org.apache.camel.spi.ComponentResolver;component=github</camel.osgi.export.service> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.mylyn.github</groupId> + <artifactId>org.eclipse.egit.github.core</artifactId> + <version>2.1.5</version> + <scope>provided</scope> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <scope>test</scope> + </dependency> + + <!-- logging --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubComponent.java b/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubComponent.java new file mode 100644 index 0000000..aa3d038 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubComponent.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github; + +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.impl.DefaultComponent; + +/** + * Represents the component that manages {@link GitHubEndpoint}. + */ +public class GitHubComponent extends DefaultComponent { + + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + Endpoint endpoint = new GitHubEndpoint(uri, this); + setProperties(endpoint, parameters); + return endpoint; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubEndpoint.java b/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubEndpoint.java new file mode 100644 index 0000000..8070d48 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/GitHubEndpoint.java @@ -0,0 +1,171 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github; + +import java.util.regex.Pattern; + +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.component.github.consumer.CommitConsumer; +import org.apache.camel.component.github.consumer.ConsumerType; +import org.apache.camel.component.github.consumer.PullRequestCommentConsumer; +import org.apache.camel.component.github.consumer.PullRequestConsumer; +import org.apache.camel.component.github.consumer.TagConsumer; +import org.apache.camel.component.github.producer.ProducerType; +import org.apache.camel.component.github.producer.PullRequestCommentProducer; +import org.apache.camel.impl.DefaultEndpoint; + +/** + * The endpoint encapsulates portions of the GitHub API, relying on the org.eclipse.egit.github.core Java SDK. + * Available endpoint URIs include: + * + * CONSUMERS + * github://pullRequest (new pull requests) + * github://pullRequestComment (new pull request comments) + * github://commit/[branch] (new commits) + * github://tag (new tags) + * + * PRODUCERS + * github://pullRequestComment (create a new pull request comment; see PullRequestCommentProducer for header requirements) + * + * The endpoints will respond with org.eclipse.egit.github.core-provided POJOs (PullRequest, CommitComment, + * RepositoryTag, RepositoryCommit, etc.) + * + * Note: Rather than webhooks, this endpoint relies on simple polling. Reasons include: + * - concerned about reliability/stability if this somehow relied on an exposed, embedded server (Jetty?) + * - the types of payloads we're polling aren't typically large (plus, paging is available in the API) + * - need to support apps running somewhere not publicly accessible where a webhook would fail + */ +public class GitHubEndpoint extends DefaultEndpoint { + + private String username = null; + + private String password = null; + + private String oauthToken = null; + + private String repoOwner = null; + + private String repoName = null; + + public GitHubEndpoint(String uri, GitHubComponent component) { + super(uri, component); + } + + public Producer createProducer() throws Exception { + String uri = getEndpointUri(); + String[] uriSplit = splitUri(getEndpointUri()); + + if (uriSplit.length > 0) { + switch (ProducerType.fromUri(uriSplit[0])) { + case PULLREQUESTCOMMENT: + return new PullRequestCommentProducer(this); + default: + break; + } + } + + throw new IllegalArgumentException("Cannot create any producer with uri " + uri + + ". A producer type was not provided (or an incorrect pairing was used)."); + } + + public Consumer createConsumer(Processor processor) throws Exception { + String uri = getEndpointUri(); + String[] uriSplit = splitUri(getEndpointUri()); + + if (uriSplit.length > 0) { + switch (ConsumerType.fromUri(uriSplit[0])) { + case COMMIT: + if (uriSplit.length >= 2 && uriSplit[1].length() > 1) { + return new CommitConsumer(uriSplit[1], this, processor); + } else { + throw new IllegalArgumentException("Must provide a branch name when using the COMMIT consumer. github://commit/[branch name]?[options]"); + } + case PULLREQUEST: + return new PullRequestConsumer(this, processor); + case PULLREQUESTCOMMENT: + return new PullRequestCommentConsumer(this, processor); + case TAG: + return new TagConsumer(this, processor); + default: + break; + } + } + + throw new IllegalArgumentException("Cannot create any consumer with uri " + uri + + ". A consumer type was not provided (or an incorrect pairing was used)."); + } + + public boolean isSingleton() { + return true; + } + + private static String[] splitUri(String uri) { + Pattern p1 = Pattern.compile("github:(//)*"); + Pattern p2 = Pattern.compile("\\?.*"); + + uri = p1.matcher(uri).replaceAll(""); + uri = p2.matcher(uri).replaceAll(""); + + return uri.split("/"); + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getOauthToken() { + return oauthToken; + } + + public void setOauthToken(String oauthToken) { + this.oauthToken = oauthToken; + } + + public boolean hasOauth() { + return oauthToken != null && oauthToken.length() > 0; + } + + public String getRepoOwner() { + return repoOwner; + } + + public void setRepoOwner(String repoOwner) { + this.repoOwner = repoOwner; + } + + public String getRepoName() { + return repoName; + } + + public void setRepoName(String repoName) { + this.repoName = repoName; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/AbstractGitHubConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/AbstractGitHubConsumer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/AbstractGitHubConsumer.java new file mode 100644 index 0000000..a33852c --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/AbstractGitHubConsumer.java @@ -0,0 +1,44 @@ +package org.apache.camel.component.github.consumer; + +import org.apache.camel.Processor; +import org.apache.camel.component.github.GitHubEndpoint; +import org.apache.camel.impl.ScheduledPollConsumer; +import org.eclipse.egit.github.core.Repository; +import org.eclipse.egit.github.core.service.GitHubService; +import org.eclipse.egit.github.core.service.RepositoryService; + +public abstract class AbstractGitHubConsumer extends ScheduledPollConsumer { + + private final GitHubEndpoint endpoint; + + private RepositoryService repositoryService = null; + + private Repository repository = null; + + public AbstractGitHubConsumer(GitHubEndpoint endpoint, Processor processor) throws Exception { + super(endpoint, processor); + this.endpoint = endpoint; + + repositoryService = new RepositoryService(); + initService(repositoryService); + repository = repositoryService.getRepository(endpoint.getRepoOwner(), endpoint.getRepoName()); + } + + protected void initService(GitHubService service) { + if (endpoint.hasOauth()) { + service.getClient().setOAuth2Token(endpoint.getOauthToken()); + } else { + service.getClient().setCredentials(endpoint.getUsername(), endpoint.getPassword()); + } + } + + protected RepositoryService getRepositoryService() { + return repositoryService; + } + + protected Repository getRepository() { + return repository; + } + + protected abstract int poll() throws Exception; +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/CommitConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/CommitConsumer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/CommitConsumer.java new file mode 100644 index 0000000..71492d7 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/CommitConsumer.java @@ -0,0 +1,71 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.github.GitHubEndpoint; +import org.eclipse.egit.github.core.RepositoryCommit; +import org.eclipse.egit.github.core.service.CommitService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CommitConsumer extends AbstractGitHubConsumer { + private static final transient Logger LOG = LoggerFactory.getLogger(CommitConsumer.class); + + private CommitService commitService = null; + + private List<String> commitHashes = new ArrayList<String>(); + + public CommitConsumer(String branchName, GitHubEndpoint endpoint, Processor processor) throws Exception { + super(endpoint, processor); + + commitService = new CommitService(); + initService(commitService); + + LOG.info("GitHub CommitConsumer: Indexing current commits..."); + List<RepositoryCommit> commits = commitService.getCommits(getRepository(), branchName, null); + for (RepositoryCommit commit : commits) { + commitHashes.add(commit.getSha()); + } + } + + @Override + protected int poll() throws Exception { + List<RepositoryCommit> commits = commitService.getCommits(getRepository()); + // In the end, we want tags oldest to newest. + Stack<RepositoryCommit> newCommits = new Stack<RepositoryCommit>(); + for (RepositoryCommit commit : commits) { + if (!commitHashes.contains(commit.getSha())) { + newCommits.push(commit); + commitHashes.add(commit.getSha()); + } + } + + while(!newCommits.empty()) { + RepositoryCommit newCommit = newCommits.pop(); + Exchange e = getEndpoint().createExchange(); + e.getIn().setBody(newCommit); + getProcessor().process(e); + } + return newCommits.size(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/ConsumerType.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/ConsumerType.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/ConsumerType.java new file mode 100644 index 0000000..5c7251f --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/ConsumerType.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.consumer; + +public enum ConsumerType { + + COMMIT, PULLREQUEST, PULLREQUESTCOMMENT, TAG, UNKNOWN; + + public static ConsumerType fromUri(String uri) { + for (ConsumerType consumerType : ConsumerType.values()) { + if (consumerType.name().equalsIgnoreCase(uri)) { + return consumerType; + } + } + return ConsumerType.UNKNOWN; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestCommentConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestCommentConsumer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestCommentConsumer.java new file mode 100644 index 0000000..85e7a9a --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestCommentConsumer.java @@ -0,0 +1,95 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.github.GitHubEndpoint; +import org.eclipse.egit.github.core.Comment; +import org.eclipse.egit.github.core.CommitComment; +import org.eclipse.egit.github.core.PullRequest; +import org.eclipse.egit.github.core.service.IssueService; +import org.eclipse.egit.github.core.service.PullRequestService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PullRequestCommentConsumer extends AbstractGitHubConsumer { + private static final transient Logger LOG = LoggerFactory.getLogger(PullRequestCommentConsumer.class); + + private PullRequestService pullRequestService = null; + + private IssueService issueService = null; + + private List<Long> commentIds = new ArrayList<Long>(); + + public PullRequestCommentConsumer(GitHubEndpoint endpoint, Processor processor) throws Exception { + super(endpoint, processor); + + pullRequestService = new PullRequestService(); + initService(pullRequestService); + issueService = new IssueService(); + initService(issueService); + + LOG.info("GitHub PullRequestCommentConsumer: Indexing current pull request comments..."); + List<PullRequest> pullRequests = pullRequestService.getPullRequests(getRepository(), "open"); + for (PullRequest pullRequest : pullRequests) { + List<CommitComment> commitComments = pullRequestService.getComments(getRepository(), pullRequest.getNumber()); + for (Comment comment : commitComments) { + commentIds.add(comment.getId()); + } + List<Comment> comments = issueService.getComments(getRepository(), pullRequest.getNumber()); + for (Comment comment : comments) { + commentIds.add(comment.getId()); + } + } + } + + @Override + protected int poll() throws Exception { + List<PullRequest> pullRequests = pullRequestService.getPullRequests(getRepository(), "open"); + // In the end, we want comments oldest to newest. + Stack<Comment> newComments = new Stack<Comment>(); + for (PullRequest pullRequest : pullRequests) { + List<CommitComment> commitComments = pullRequestService.getComments(getRepository(), pullRequest.getNumber()); + for (Comment comment : commitComments) { + if (!commentIds.contains(comment.getId())) { + newComments.add(comment); + commentIds.add(comment.getId()); + } + } + List<Comment> comments = issueService.getComments(getRepository(), pullRequest.getNumber()); + for (Comment comment : comments) { + if (!commentIds.contains(comment.getId())) { + newComments.add(comment); + commentIds.add(comment.getId()); + } + } + } + + while(!newComments.empty()) { + Comment newComment = newComments.pop(); + Exchange e = getEndpoint().createExchange(); + e.getIn().setBody(newComment); + getProcessor().process(e); + } + return newComments.size(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestConsumer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestConsumer.java new file mode 100644 index 0000000..97673c3 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/PullRequestConsumer.java @@ -0,0 +1,75 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.consumer; + +import java.util.List; +import java.util.Stack; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.github.GitHubEndpoint; +import org.eclipse.egit.github.core.PullRequest; +import org.eclipse.egit.github.core.service.PullRequestService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PullRequestConsumer extends AbstractGitHubConsumer { + private static final transient Logger LOG = LoggerFactory.getLogger(PullRequestConsumer.class); + + private PullRequestService pullRequestService = null; + + private int lastOpenPullRequest = 0; + + public PullRequestConsumer(GitHubEndpoint endpoint, Processor processor) throws Exception { + super(endpoint, processor); + + pullRequestService = new PullRequestService(); + initService(pullRequestService); + + LOG.info("GitHub PullRequestConsumer: Indexing current pull requests..."); + List<PullRequest> pullRequests = pullRequestService.getPullRequests(getRepository(), "open"); + if (pullRequests.size() > 0) { + lastOpenPullRequest = pullRequests.get(0).getNumber(); + } + } + + @Override + protected int poll() throws Exception { + List<PullRequest> openPullRequests = pullRequestService.getPullRequests(getRepository(), "open"); + // In the end, we want PRs oldest to newest. + Stack<PullRequest> newPullRequests = new Stack<PullRequest>(); + for (PullRequest pullRequest : openPullRequests) { + if (pullRequest.getNumber() > lastOpenPullRequest) { + newPullRequests.push(pullRequest); + } else { + break; + } + } + + if (newPullRequests.size() > 0) { + lastOpenPullRequest = openPullRequests.get(0).getNumber(); + } + + while(!newPullRequests.empty()) { + PullRequest newPullRequest = newPullRequests.pop(); + Exchange e = getEndpoint().createExchange(); + e.getIn().setBody(newPullRequest); + getProcessor().process(e); + } + return newPullRequests.size(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/TagConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/TagConsumer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/TagConsumer.java new file mode 100644 index 0000000..7f21604 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/consumer/TagConsumer.java @@ -0,0 +1,65 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.github.GitHubEndpoint; +import org.eclipse.egit.github.core.RepositoryTag; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TagConsumer extends AbstractGitHubConsumer { + private static final transient Logger LOG = LoggerFactory.getLogger(TagConsumer.class); + + private List<String> tagNames = new ArrayList<String>(); + + public TagConsumer(GitHubEndpoint endpoint, Processor processor) throws Exception { + super(endpoint, processor); + + LOG.info("GitHub TagConsumer: Indexing current tags..."); + List<RepositoryTag> tags = getRepositoryService().getTags(getRepository()); + for (RepositoryTag tag : tags) { + tagNames.add(tag.getName()); + } + } + + @Override + protected int poll() throws Exception { + List<RepositoryTag> tags = getRepositoryService().getTags(getRepository()); + // In the end, we want tags oldest to newest. + Stack<RepositoryTag> newTags = new Stack<RepositoryTag>(); + for (RepositoryTag tag : tags) { + if (!tagNames.contains(tag.getName())) { + newTags.push(tag); + tagNames.add(tag.getName()); + } + } + + while(!newTags.empty()) { + RepositoryTag newTag = newTags.pop(); + Exchange e = getEndpoint().createExchange(); + e.getIn().setBody(newTag); + getProcessor().process(e); + } + return newTags.size(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/producer/AbstractGitHubProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/producer/AbstractGitHubProducer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/AbstractGitHubProducer.java new file mode 100644 index 0000000..3858849 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/AbstractGitHubProducer.java @@ -0,0 +1,44 @@ +package org.apache.camel.component.github.producer; + +import org.apache.camel.Exchange; +import org.apache.camel.component.github.GitHubEndpoint; +import org.apache.camel.impl.DefaultProducer; +import org.eclipse.egit.github.core.Repository; +import org.eclipse.egit.github.core.service.GitHubService; +import org.eclipse.egit.github.core.service.RepositoryService; + +public abstract class AbstractGitHubProducer extends DefaultProducer { + + private final GitHubEndpoint endpoint; + + private RepositoryService repositoryService = null; + + private Repository repository = null; + + public AbstractGitHubProducer(GitHubEndpoint endpoint) throws Exception { + super(endpoint); + this.endpoint = endpoint; + + repositoryService = new RepositoryService(); + initService(repositoryService); + repository = repositoryService.getRepository(endpoint.getRepoOwner(), endpoint.getRepoName()); + } + + protected void initService(GitHubService service) { + if (endpoint.hasOauth()) { + service.getClient().setOAuth2Token(endpoint.getOauthToken()); + } else { + service.getClient().setCredentials(endpoint.getUsername(), endpoint.getPassword()); + } + } + + protected RepositoryService getRepositoryService() { + return repositoryService; + } + + protected Repository getRepository() { + return repository; + } + + public abstract void process(Exchange exchange) throws Exception; +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/producer/ProducerType.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/producer/ProducerType.java b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/ProducerType.java new file mode 100644 index 0000000..009ea42 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/ProducerType.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.producer; + +public enum ProducerType { + + PULLREQUESTCOMMENT, UNKNOWN; + + public static ProducerType fromUri(String uri) { + for (ProducerType producerType : ProducerType.values()) { + if (producerType.name().equalsIgnoreCase(uri)) { + return producerType; + } + } + return ProducerType.UNKNOWN; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/java/org/apache/camel/component/github/producer/PullRequestCommentProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/java/org/apache/camel/component/github/producer/PullRequestCommentProducer.java b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/PullRequestCommentProducer.java new file mode 100644 index 0000000..1029b52 --- /dev/null +++ b/components/camel-github/src/main/java/org/apache/camel/component/github/producer/PullRequestCommentProducer.java @@ -0,0 +1,69 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.camel.component.github.producer; + +import org.apache.camel.Exchange; +import org.apache.camel.component.github.GitHubEndpoint; +import org.eclipse.egit.github.core.Comment; +import org.eclipse.egit.github.core.service.IssueService; +import org.eclipse.egit.github.core.service.PullRequestService; + +/** + * Producer endpoint that adds one of two types of comments on a GitHub pullrequest: + * + * 1.) Response to an in-line comment made on a pull request commit review. To use, include the + * "GitHubInResponseTo" header, identifying the comment ID (integer) that you're responding to. + * 2.) General comment on the pull request issue itself. + * + * Both endpoints require the "GitHubPullRequest" header, identifying the pull request number (integer). + */ +public class PullRequestCommentProducer extends AbstractGitHubProducer { + private PullRequestService pullRequestService = null; + + private IssueService issueService = null; + + public PullRequestCommentProducer(GitHubEndpoint endpoint) throws Exception { + super(endpoint); + + pullRequestService = new PullRequestService(); + initService(pullRequestService); + issueService = new IssueService(); + initService(issueService); + } + + public void process(Exchange exchange) throws Exception { + Integer pullRequestNumber = exchange.getIn().getHeader("GitHubPullRequest", Integer.class); + Integer inResponseTo = exchange.getIn().getHeader("GitHubInResponseTo", Integer.class); + String text = exchange.getIn().getBody(String.class); + + Comment response; + if (inResponseTo != null && inResponseTo > 0) { + response = pullRequestService.replyToComment(getRepository(), pullRequestNumber, inResponseTo, text); + } else { + // Otherwise, just comment on the pull request itself. + response = issueService.createComment(getRepository(), pullRequestNumber, text); + } + + // support InOut + if (exchange.getPattern().isOutCapable()) { + // copy the header of in message to the out message + exchange.getOut().copyFrom(exchange.getIn()); + exchange.getOut().setBody(response); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/resources/META-INF/services/org/apache/camel/component/github ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/resources/META-INF/services/org/apache/camel/component/github b/components/camel-github/src/main/resources/META-INF/services/org/apache/camel/component/github new file mode 100644 index 0000000..5e25a16 --- /dev/null +++ b/components/camel-github/src/main/resources/META-INF/services/org/apache/camel/component/github @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF 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. +# + +class=org.apache.camel.component.github.GitHubComponent http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/camel-github/src/main/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/components/camel-github/src/main/resources/log4j.properties b/components/camel-github/src/main/resources/log4j.properties new file mode 100644 index 0000000..4621723 --- /dev/null +++ b/components/camel-github/src/main/resources/log4j.properties @@ -0,0 +1,16 @@ + +# +# The logging properties used +# +log4j.rootLogger=INFO, out + +# uncomment the following line to turn on Camel debugging +#log4j.logger.org.apache.camel=DEBUG + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n +#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n + +log4j.throwableRenderer=org.apache.log4j.EnhancedThrowableRenderer \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/f0f341e2/components/pom.xml ---------------------------------------------------------------------- diff --git a/components/pom.xml b/components/pom.xml index dd8e8c4..cd8b16f 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -95,6 +95,7 @@ <module>camel-ftp</module> <module>camel-gae</module> <module>camel-geocoder</module> + <module>camel-github</module> <module>camel-google-drive</module> <module>camel-gora</module> <module>camel-gson</module>