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