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>

Reply via email to