1 package org.apache.maven.plugin.jira;
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.doxia.siterenderer.Renderer;
23 import org.apache.maven.plugin.changes.AbstractChangesReport;
24 import org.apache.maven.project.MavenProject;
25 import org.apache.maven.reporting.MavenReportException;
26 import org.apache.maven.settings.Settings;
27
28 import java.io.File;
29 import java.util.Locale;
30 import java.util.ResourceBundle;
31
32 /**
33 * Goal which downloads issues from the Issue Tracking System and generates a report.
34 *
35 * @goal jira-report
36 * @author <a href="mailto:jruiz@exist.com">Johnny R. Ruiz III</a>
37 * @version $Id: JiraMojo.html 816584 2012-05-08 12:33:35Z hboutemy $
38 */
39 public class JiraMojo
40 extends AbstractChangesReport
41 {
42 /**
43 * Path to the JIRA XML file, which will be parsed.
44 *
45 * @parameter expression="${project.build.directory}/jira-results.xml "
46 * @required
47 * @readonly
48 */
49 private File jiraXmlPath;
50
51 /**
52 * Settings XML configuration.
53 *
54 * @parameter expression="${settings}"
55 * @required
56 * @readonly
57 */
58 private Settings settings;
59
60 /**
61 * Maximum number of entries to be fetched from JIRA.
62 *
63 * @parameter default-value=100
64 *
65 */
66 private int maxEntries;
67
68 /**
69 * Defines the filter parameters to restrict which issues are retrieved
70 * from JIRA. The filter parameter uses the same format of url
71 * parameters that is used in a JIRA search.
72 *
73 * @parameter default-value=""
74 */
75 private String filter;
76
77 /**
78 * Sets the fix version id(s) that you want to limit your report to include.
79 * These are JIRA's internal version ids, <b>NOT</b> the human readable display ones.
80 * Multiple fix versions can be separated by commas.
81 * If this is set to empty - that means all fix versions will be included.
82 *
83 * @parameter default-value=""
84 * @since 2.0
85 */
86 private String fixVersionIds;
87
88 /**
89 * Sets the status(es) that you want to fetch from JIRA.
90 * Valid statuses are: <code>Open</code>, <code>In Progress</code>,
91 * <code>Reopened</code>, <code>Resolved</code> and <code>Closed</code>.
92 * Multiple values can be separated by commas.
93 * <p>
94 * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter had no
95 * default value.
96 * </p>
97 *
98 * @parameter default-value="Closed"
99 */
100 private String statusIds;
101
102 /**
103 * Sets the resolution(s) that you want to fetch from JIRA.
104 * Valid resolutions are: <code>Unresolved</code>, <code>Fixed</code>,
105 * <code>Won't Fix</code>, <code>Duplicate</code>, <code>Incomplete</code>
106 * and <code>Cannot Reproduce</code>.
107 * Multiple values can be separated by commas.
108 * <p>
109 * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter had no
110 * default value.
111 * </p>
112 *
113 * @parameter default-value="Fixed"
114 */
115 private String resolutionIds;
116
117 /**
118 * Sets the priority(s) that you want to limit your report to include.
119 * Valid statuses are <code>Blocker</code>, <code>Critical</code>,
120 * <code>Major</code>, <code>Minor</code> and <code>Trivial</code>.
121 * Multiple values can be separated by commas.
122 * If this is set to empty - that means all priorities will be included.
123 *
124 * @parameter default-value=""
125 */
126 private String priorityIds;
127
128 /**
129 * Sets the component(s) that you want to limit your report to include.
130 * Multiple values can be separated by commas (such as 10011,10012).
131 * If this is set to empty - that means all components will be included.
132 *
133 * @parameter default-value=""
134 */
135 private String component;
136
137 /**
138 * Sets the types(s) that you want to limit your report to include.
139 * Valid types are: <code>Bug</code>, <code>New Feature</code>,
140 * <code>Task</code>, <code>Improvement</code>, <code>Wish</code>,
141 * <code>Test</code> and <code>Sub-task</code>.
142 * Multiple values can be separated by commas.
143 * If this is set to empty - that means all types will be included.
144 *
145 * @parameter default-value=""
146 * @since 2.0
147 */
148 private String typeIds;
149
150 /**
151 * Sets the column names that you want to show in the report. The columns
152 * will appear in the report in the same order as you specify them here.
153 * Multiple values can be separated by commas.
154 * <p>
155 * Valid columns are: <code>Key</code>, <code>Summary</code>,
156 * <code>Status</code>, <code>Resolution</code>, <code>Assignee</code>,
157 * <code>Reporter</code>, <code>Type</code>, <code>Priority</code>,
158 * <code>Version</code>, <code>Fix Version</code> and
159 * <code>Component</code>.
160 * </p>
161 *
162 * @parameter default-value="Key,Summary,Status,Resolution,Assignee"
163 * @since 2.0
164 */
165 private String columnNames;
166
167 /**
168 * Sets the column names that you want to sort the report by. Add
169 * <code>DESC</code> following the column name
170 * to specify <i>descending</i> sequence. For
171 * example <code>Fix Version DESC, Type</code> sorts first by
172 * the Fix Version in descending order and then by Type in
173 * ascending order. By default sorting is done in ascending order, but is
174 * possible to specify <code>ASC</code> for consistency. The previous
175 * example would then become <code>Fix Version DESC, Type ASC</code>.
176 * <p>
177 * Valid columns are: <code>Key</code>, <code>Summary</code>,
178 * <code>Status</code>, <code>Resolution</code>, <code>Assignee</code>,
179 * <code>Reporter</code>, <code>Type</code>, <code>Priority</code>,
180 * <code>Version</code>, <code>Fix Version</code>,
181 * <code>Component</code>, <code>Created</code> and
182 * <code>Updated</code>.
183 * </p>
184 *
185 * @parameter default-value="Priority DESC, Created DESC"
186 * @since 2.0
187 */
188 private String sortColumnNames;
189
190 /**
191 * Defines the JIRA username for authentication into a private JIRA installation.
192 *
193 * @parameter default-value=""
194 */
195 private String jiraUser;
196
197 /**
198 * Defines the JIRA password for authentication into a private JIRA installation.
199 *
200 * @parameter default-value=""
201 */
202 private String jiraPassword;
203
204 /**
205 * Defines the http user for basic authentication into the JIRA webserver.
206 *
207 * @parameter default-value=""
208 */
209 private String webUser;
210
211 /**
212 * Defines the http password for basic authentication into the JIRA webserver.
213 *
214 * @parameter default-value=""
215 */
216 private String webPassword;
217
218 /**
219 * If you only want to show issues for the current version in the report.
220 * The current version being used is <code>${project.version}</code> minus
221 * any "-SNAPSHOT" suffix.
222 *
223 * @parameter default-value="false"
224 * @since 2.0
225 */
226 private boolean onlyCurrentVersion;
227
228 /**
229 * @see org.apache.maven.reporting.AbstractMavenReport#canGenerateReport()
230 */
231 public boolean canGenerateReport()
232 {
233 return validateIfIssueManagementComplete();
234 }
235
236 public void executeReport( Locale locale )
237 throws MavenReportException
238 {
239 JiraDownloader jiraDownloader = new JiraDownloader();
240
241 setJiraDownloaderParameters( jiraDownloader );
242
243 JiraReportGenerator report;
244
245 try
246 {
247 jiraDownloader.doExecute();
248
249 if ( jiraXmlPath.isFile() )
250 {
251 report = new JiraReportGenerator( jiraXmlPath, columnNames, project.getVersion(),
252 onlyCurrentVersion );
253
254 report.doGenerateReport( getBundle( locale ), getSink(), getLog() );
255 }
256 else
257 {
258 report = new JiraReportGenerator();
259
260 report.doGenerateEmptyReport( getBundle( locale ), getSink() );
261 }
262 }
263 catch ( MavenReportException mre )
264 {
265 // Rethrow this error from JiraReportGenerator( String, String )
266 // so that the build fails
267 throw mre;
268 }
269 catch ( Exception e )
270 {
271 e.printStackTrace();
272 }
273 }
274
275 public String getName( Locale locale )
276 {
277 return getBundle( locale ).getString( "report.jira.name" );
278 }
279
280 public String getDescription( Locale locale )
281 {
282 return getBundle( locale ).getString( "report.jira.description" );
283 }
284
285 public String getOutputName()
286 {
287 return "jira-report";
288 }
289
290 private ResourceBundle getBundle( Locale locale )
291 {
292 return ResourceBundle.getBundle( "jira-report", locale, this.getClass().getClassLoader() );
293 }
294
295 private void setJiraDownloaderParameters( JiraDownloader jira )
296 {
297 jira.setLog( getLog() );
298
299 jira.setMavenProject( project );
300
301 jira.setOutput( jiraXmlPath );
302
303 jira.setNbEntries( maxEntries );
304
305 jira.setComponent( component );
306
307 jira.setFixVersionIds( fixVersionIds );
308
309 jira.setStatusIds( statusIds );
310
311 jira.setResolutionIds( resolutionIds );
312
313 jira.setPriorityIds( priorityIds );
314
315 jira.setSortColumnNames( sortColumnNames );
316
317 jira.setFilter( filter );
318
319 jira.setJiraUser( jiraUser );
320
321 jira.setJiraPassword( jiraPassword );
322
323 jira.setTypeIds( typeIds );
324
325 jira.setWebUser( webUser );
326
327 jira.setWebPassword( webPassword );
328
329 jira.setSettings( settings );
330 }
331
332 private boolean validateIfIssueManagementComplete()
333 {
334 if ( project.getIssueManagement() == null )
335 {
336 getLog().error( "No Issue Management set. No JIRA Report will be generated." );
337
338 return false;
339 }
340 else if ( ( project.getIssueManagement().getUrl() == null )
341 || ( project.getIssueManagement().getUrl().trim().equals( "" ) ) )
342 {
343 getLog().error( "No URL set in Issue Management. No JIRA Report will be generated." );
344
345 return false;
346 }
347 else if ( ( project.getIssueManagement().getSystem() != null )
348 && !( project.getIssueManagement().getSystem().equalsIgnoreCase( "jira" ) ) )
349 {
350 getLog().error( "The JIRA Report only supports JIRA. No JIRA Report will be generated." );
351
352 return false;
353 }
354 return true;
355 }
356 }