View Javadoc
1   package org.apache.maven.plugin.github;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.issues.Issue;
23  import org.apache.maven.plugin.logging.Log;
24  import org.apache.maven.project.MavenProject;
25  import org.apache.maven.settings.Server;
26  import org.apache.maven.settings.Settings;
27  
28  import org.eclipse.egit.github.core.Label;
29  import org.eclipse.egit.github.core.client.GitHubClient;
30  import org.eclipse.egit.github.core.service.IssueService;
31  
32  import java.io.IOException;
33  import java.net.MalformedURLException;
34  import java.net.URL;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  /**
41   * @since 2.8
42   */
43  public class GitHubDownloader
44  {
45  
46      /**
47       * The github client.
48       */
49      private GitHubClient client;
50  
51      /**
52       * A boolean to indicate if we should include open issues as well
53       */
54      private boolean includeOpenIssues;
55  
56      /**
57       * A boolean to indicate if we should only include issues with milestones
58       */
59      private boolean onlyMilestoneIssues;
60  
61      /**
62       * The owner/organization of the github repo.
63       */
64      private String githubOwner;
65  
66      /**
67       * The name of the github repo.
68       */
69      private String githubRepo;
70  
71      /**
72       * The url to the github repo's issue management
73       */
74      private String githubIssueURL;
75  
76      public GitHubDownloader( MavenProject project, String githubScheme, int githubPort, boolean includeOpenIssues,
77                               boolean onlyMilestoneIssues )
78                                   throws MalformedURLException
79      {
80          this.includeOpenIssues = includeOpenIssues;
81          this.onlyMilestoneIssues = onlyMilestoneIssues;
82  
83          URL githubURL = new URL( project.getIssueManagement().getUrl() );
84  
85          // The githubclient prefers to connect to 'github.com' using the api domain, unlike github enterprise
86          // which can connect fine using its domain, so for github.com use empty constructor
87          if ( githubURL.getHost().equalsIgnoreCase( "github.com" ) )
88          {
89              this.client = new GitHubClient();
90          }
91          else
92          {
93              this.client = new GitHubClient( githubURL.getHost(), githubPort, githubScheme );
94          }
95  
96          this.githubIssueURL = project.getIssueManagement().getUrl();
97          if ( !this.githubIssueURL.endsWith( "/" ) )
98          {
99              this.githubIssueURL = this.githubIssueURL + "/";
100         }
101 
102         String urlPath = githubURL.getPath();
103         if ( urlPath.startsWith( "/" ) )
104         {
105             urlPath = urlPath.substring( 1 );
106         }
107 
108         if ( urlPath.endsWith( "/" ) )
109         {
110             urlPath = urlPath.substring( 0, urlPath.length() - 2 );
111         }
112 
113         String[] urlPathParts = urlPath.split( "/" );
114 
115         if ( urlPathParts.length != 3 )
116         {
117             throw new MalformedURLException( "GitHub issue management URL must look like, "
118                 + "[GITHUB_DOMAIN]/[OWNER]/[REPO]/issues" );
119         }
120 
121         this.githubOwner = urlPathParts[0];
122         this.githubRepo = urlPathParts[1];
123     }
124 
125     protected Issue createIssue( org.eclipse.egit.github.core.Issue githubIssue )
126     {
127         Issue issue = new Issue();
128 
129         issue.setKey( String.valueOf( githubIssue.getNumber() ) );
130         issue.setId( String.valueOf( githubIssue.getNumber() ) );
131 
132         issue.setLink( this.githubIssueURL + githubIssue.getNumber() );
133 
134         issue.setCreated( githubIssue.getCreatedAt() );
135 
136         issue.setUpdated( githubIssue.getUpdatedAt() );
137 
138         if ( githubIssue.getAssignee() != null )
139         {
140             if ( githubIssue.getAssignee().getName() != null )
141             {
142                 issue.setAssignee( githubIssue.getAssignee().getName() );
143             }
144             else
145             {
146                 issue.setAssignee( githubIssue.getAssignee().getLogin() );
147             }
148         }
149 
150         issue.setTitle( githubIssue.getTitle() );
151 
152         issue.setSummary( githubIssue.getBody() );
153 
154         if ( githubIssue.getMilestone() != null )
155         {
156             issue.addFixVersion( githubIssue.getMilestone().getTitle() );
157         }
158 
159         issue.setReporter( githubIssue.getUser().getLogin() );
160 
161         if ( githubIssue.getClosedAt() != null )
162         {
163             issue.setStatus( "closed" );
164         }
165         else
166         {
167             issue.setStatus( "open" );
168         }
169 
170         List<Label> labels = githubIssue.getLabels();
171         if ( labels != null && !labels.isEmpty() )
172         {
173             issue.setType( labels.get( 0 ).getName() );
174         }
175 
176         return issue;
177     }
178 
179     public List<Issue> getIssueList()
180         throws IOException
181     {
182         List<Issue> issueList = new ArrayList<Issue>();
183 
184         IssueService service = new IssueService( client );
185         Map<String, String> issueFilter = new HashMap<String, String>();
186 
187         if ( includeOpenIssues )
188         {
189             // Adding open issues
190 
191             for ( org.eclipse.egit.github.core.Issue issue : service.getIssues( githubOwner, githubRepo, issueFilter ) )
192             {
193                 if ( !onlyMilestoneIssues || issue.getMilestone() != null )
194                 {
195                     issueList.add( createIssue( issue ) );
196                 }
197             }
198         }
199 
200         // Adding closed issues
201 
202         issueFilter.put( "state", "closed" );
203 
204         for ( org.eclipse.egit.github.core.Issue issue : service.getIssues( githubOwner, githubRepo, issueFilter ) )
205         {
206             if ( !onlyMilestoneIssues || issue.getMilestone() != null )
207             {
208                 issueList.add( createIssue( issue ) );
209             }
210         }
211 
212         return issueList;
213     }
214 
215     public void configureAuthentication( String githubAPIServerId, Settings settings, Log log )
216     {
217         boolean configured = false;
218 
219         List<Server> servers = settings.getServers();
220 
221         for ( Server server : servers )
222         {
223             if ( server.getId().equals( githubAPIServerId ) )
224             {
225                 String user = server.getUsername();
226                 String password = server.getPassword();
227                 this.client.setCredentials( user, password );
228 
229                 configured = true;
230                 break;
231             }
232         }
233 
234         if ( !configured )
235         {
236             log.warn( "Can't find server id [" + githubAPIServerId + "] configured in githubAPIServerId." );
237         }
238     }
239 
240 }