Coverage Report - org.apache.maven.plugin.jira.JiraMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
JiraMojo
79%
62/78
50%
8/16
2.333
 
 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.commons.lang.StringUtils;
 23  
 import org.apache.maven.plugin.changes.AbstractChangesReport;
 24  
 import org.apache.maven.plugin.changes.ProjectUtils;
 25  
 import org.apache.maven.plugin.issues.Issue;
 26  
 import org.apache.maven.plugin.issues.IssueUtils;
 27  
 import org.apache.maven.plugin.issues.IssuesReportGenerator;
 28  
 import org.apache.maven.plugin.issues.IssuesReportHelper;
 29  
 import org.apache.maven.plugins.annotations.Component;
 30  
 import org.apache.maven.plugins.annotations.Mojo;
 31  
 import org.apache.maven.plugins.annotations.Parameter;
 32  
 import org.apache.maven.reporting.MavenReportException;
 33  
 import org.apache.maven.settings.Settings;
 34  
 
 35  
 import java.io.File;
 36  
 import java.util.HashMap;
 37  
 import java.util.List;
 38  
 import java.util.Locale;
 39  
 import java.util.Map;
 40  
 import java.util.ResourceBundle;
 41  
 
 42  
 /**
 43  
  * Goal which downloads issues from the Issue Tracking System and generates a report.
 44  
  *
 45  
  * @author <a href="mailto:jruiz@exist.com">Johnny R. Ruiz III</a>
 46  
  * @version $Id: JiraMojo.java 1412155 2012-11-21 15:47:19Z bimargulies $
 47  
  */
 48  
 @Mojo( name = "jira-report", threadSafe = true )
 49  4
 public class JiraMojo
 50  
     extends AbstractChangesReport
 51  
 {
 52  
     /**
 53  
      * Valid JIRA columns.
 54  
      */
 55  2
     private static final Map<String,Integer> JIRA_COLUMNS = new HashMap<String,Integer>( 16 );
 56  
 
 57  
     static
 58  
     {
 59  2
         JIRA_COLUMNS.put( "Assignee",  Integer.valueOf( IssuesReportHelper.COLUMN_ASSIGNEE ) );
 60  2
         JIRA_COLUMNS.put( "Component", Integer.valueOf( IssuesReportHelper.COLUMN_COMPONENT ) );
 61  2
         JIRA_COLUMNS.put( "Created", Integer.valueOf( IssuesReportHelper.COLUMN_CREATED ) );
 62  2
         JIRA_COLUMNS.put( "Fix Version", Integer.valueOf( IssuesReportHelper.COLUMN_FIX_VERSION ) );
 63  2
         JIRA_COLUMNS.put( "Id", Integer.valueOf( IssuesReportHelper.COLUMN_ID ) );
 64  2
         JIRA_COLUMNS.put( "Key", Integer.valueOf( IssuesReportHelper.COLUMN_KEY ) );
 65  2
         JIRA_COLUMNS.put( "Priority", Integer.valueOf( IssuesReportHelper.COLUMN_PRIORITY ) );
 66  2
         JIRA_COLUMNS.put( "Reporter", Integer.valueOf( IssuesReportHelper.COLUMN_REPORTER ) );
 67  2
         JIRA_COLUMNS.put( "Resolution", Integer.valueOf( IssuesReportHelper.COLUMN_RESOLUTION ) );
 68  2
         JIRA_COLUMNS.put( "Status", Integer.valueOf( IssuesReportHelper.COLUMN_STATUS ) );
 69  2
         JIRA_COLUMNS.put( "Summary", Integer.valueOf( IssuesReportHelper.COLUMN_SUMMARY ) );
 70  2
         JIRA_COLUMNS.put( "Type", Integer.valueOf( IssuesReportHelper.COLUMN_TYPE ) );
 71  2
         JIRA_COLUMNS.put( "Updated", Integer.valueOf( IssuesReportHelper.COLUMN_UPDATED ) );
 72  2
         JIRA_COLUMNS.put( "Version", Integer.valueOf( IssuesReportHelper.COLUMN_VERSION ) );
 73  2
     }
 74  
 
 75  
     /**
 76  
      * Sets the names of the columns that you want in the report. The columns
 77  
      * will appear in the report in the same order as you specify them here.
 78  
      * Multiple values can be separated by commas.
 79  
      * <p>
 80  
      * Valid columns are: <code>Assignee</code>, <code>Component</code>,
 81  
      * <code>Created</code>, <code>Fix Version</code>, <code>Id</code>,
 82  
      * <code>Key</code>, <code>Priority</code>, <code>Reporter</code>,
 83  
      * <code>Resolution</code>, <code>Status</code>, <code>Summary</code>,
 84  
      * <code>Type</code>, <code>Updated</code> and <code>Version</code>.
 85  
      * </p>
 86  
      *
 87  
      * @since 2.0
 88  
      */
 89  
     @Parameter( defaultValue = "Key,Summary,Status,Resolution,Assignee" )
 90  
     private String columnNames;
 91  
 
 92  
     /**
 93  
      * Use the JIRA query language instead of the JIRA query based on HTTP parameters. 
 94  
      * From JIRA 5.1 and up only JQL is supported. JIRA 4.4 supports both JQL and URL parameter based queries.
 95  
      * From 5.1.1 this is obsolete, since REST queries only use JQL.
 96  
      *
 97  
      * @since 2.8
 98  
      */
 99  
     @Parameter( defaultValue = "false" )
 100  
     private boolean useJql;
 101  
 
 102  
     /**
 103  
      * Since JIRA 5.1.1, it is no longer possible to construct a URL that downloads RSS. Meanwhile
 104  
      * JIRA added a REST API in 4.2. By default, this plugin uses the REST API if available.
 105  
      * Setting this parameter to true forces it to attempt to use RSS.
 106  
      *
 107  
      * @since 2.9
 108  
      */
 109  
     @Parameter( defaultValue = "false")
 110  
     private boolean forceRss;
 111  
     
 112  
     /**
 113  
      * Sets the component(s) that you want to limit your report to include.
 114  
      * Multiple values can be separated by commas (such as 10011,10012).
 115  
      * If this is set to empty - that means all components will be included.
 116  
      */
 117  
     @Parameter( defaultValue = "" )
 118  
     private String component;
 119  
 
 120  
     /**
 121  
      * Defines the filter parameters to restrict which issues are retrieved
 122  
      * from JIRA. The filter parameter uses the same format of url
 123  
      * parameters that is used in a JIRA search.
 124  
      */
 125  
     @Parameter( defaultValue = "" )
 126  
     private String filter;
 127  
 
 128  
     /**
 129  
      * Sets the fix version id(s) that you want to limit your report to include.
 130  
      * These are JIRA's internal version ids, <b>NOT</b> the human readable display ones.
 131  
      * Multiple fix versions can be separated by commas.
 132  
      * If this is set to empty - that means all fix versions will be included.
 133  
      *
 134  
      * @since 2.0
 135  
      */
 136  
     @Parameter( defaultValue = "" )
 137  
     private String fixVersionIds;
 138  
 
 139  
     /**
 140  
      * The pattern used by dates in the JIRA XML-file. This is used to parse
 141  
      * the Created and Updated fields.
 142  
      *
 143  
      * @since 2.4
 144  
      */
 145  
     @Parameter( defaultValue = "EEE, d MMM yyyy HH:mm:ss Z" )
 146  
     private String jiraDatePattern;
 147  
 
 148  
     /**
 149  
      * Defines the JIRA password for authentication into a private JIRA installation.
 150  
      */
 151  
     @Parameter( defaultValue = "" )
 152  
     private String jiraPassword;
 153  
 
 154  
     /**
 155  
      * Defines the JIRA username for authentication into a private JIRA installation.
 156  
      */
 157  
     @Parameter( defaultValue = "" )
 158  
     private String jiraUser;
 159  
 
 160  
     /**
 161  
      * Path to the JIRA XML file, which will be parsed.
 162  
      */
 163  
     @Parameter( defaultValue = "${project.build.directory}/jira-results.xml", required = true, readonly = true )
 164  
     private File jiraXmlPath;
 165  
 
 166  
     /**
 167  
      * Maximum number of entries to be fetched from JIRA.
 168  
      */
 169  
     @Parameter( defaultValue = "100" )
 170  
     private int maxEntries;
 171  
 
 172  
     /**
 173  
      * If you only want to show issues for the current version in the report.
 174  
      * The current version being used is <code>${project.version}</code> minus
 175  
      * any "-SNAPSHOT" suffix.
 176  
      *
 177  
      * @since 2.0
 178  
      */
 179  
     @Parameter( defaultValue = "false" )
 180  
     private boolean onlyCurrentVersion;
 181  
 
 182  
     /**
 183  
      * Sets the priority(s) that you want to limit your report to include.
 184  
      * Valid statuses are <code>Blocker</code>, <code>Critical</code>,
 185  
      * <code>Major</code>, <code>Minor</code> and <code>Trivial</code>.
 186  
      * Multiple values can be separated by commas.
 187  
      * If this is set to empty - that means all priorities will be included.
 188  
      */
 189  
     @Parameter( defaultValue = "" )
 190  
     private String priorityIds;
 191  
 
 192  
     /**
 193  
      * Sets the resolution(s) that you want to fetch from JIRA.
 194  
      * Valid resolutions are: <code>Unresolved</code>, <code>Fixed</code>,
 195  
      * <code>Won't Fix</code>, <code>Duplicate</code>, <code>Incomplete</code>
 196  
      * and <code>Cannot Reproduce</code>.
 197  
      * Multiple values can be separated by commas.
 198  
      * <p>
 199  
      * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter had no
 200  
      * default value.
 201  
      * </p>
 202  
      */
 203  
     @Parameter( defaultValue = "Fixed" )
 204  
     private String resolutionIds;
 205  
 
 206  
     /**
 207  
      * Settings XML configuration.
 208  
      */
 209  
     @Component
 210  
     private Settings settings;
 211  
 
 212  
     /**
 213  
      * If set to <code>true</code>, then the JIRA report will not be generated.
 214  
      * 
 215  
      * @since 2.8
 216  
      */
 217  
     @Parameter( property = "changes.jira.skip", defaultValue = "false" )
 218  
     private boolean skip;
 219  
 
 220  
     /**
 221  
      * Sets the column names that you want to sort the report by. Add
 222  
      * <code>DESC</code> following the column name
 223  
      * to specify <i>descending</i> sequence. For
 224  
      * example <code>Fix Version DESC, Type</code> sorts first by
 225  
      * the Fix Version in descending order and then by Type in
 226  
      * ascending order. By default sorting is done in ascending order, but is
 227  
      * possible to specify <code>ASC</code> for consistency. The previous
 228  
      * example would then become <code>Fix Version DESC, Type ASC</code>.
 229  
      * <p>
 230  
      * Valid columns are: <code>Assignee</code>, <code>Component</code>,
 231  
      * <code>Created</code>, <code>Fix Version</code>, <code>Id</code>,
 232  
      * <code>Key</code>, <code>Priority</code>, <code>Reporter</code>,
 233  
      * <code>Resolution</code>, <code>Status</code>, <code>Summary</code>,
 234  
      * <code>Type</code>, <code>Updated</code> and <code>Version</code>.
 235  
      * </p>
 236  
      * <p>
 237  
      * <strong>Note:</strong> If you are using JIRA 4 you need to put your
 238  
      * sort column names in the reverse order. The handling of this changed
 239  
      * between JIRA 3 and JIRA 4. The current default value is suitable for
 240  
      * JIRA 3. This may change in the future, so please configure your sort
 241  
      * column names in an order that works for your own JIRA version. If you
 242  
      * use JQL, by setting the <code>useJql</code> parameter to
 243  
      * <code>true</code>, then the order of the fields are in normal order
 244  
      * again. Starting with JIRA 5.1 you have to use JQL.
 245  
      * </p>
 246  
      *
 247  
      * @since 2.0
 248  
      */
 249  
     @Parameter( defaultValue = "Priority DESC, Created DESC" )
 250  
     private String sortColumnNames;
 251  
 
 252  
     /**
 253  
      * Sets the status(es) that you want to fetch from JIRA.
 254  
      * Valid statuses are: <code>Open</code>, <code>In Progress</code>,
 255  
      * <code>Reopened</code>, <code>Resolved</code> and <code>Closed</code>.
 256  
      * Multiple values can be separated by commas.
 257  
      * <p>
 258  
      * If your installation of JIRA uses custom status IDs, you can reference
 259  
      * them here by their numeric values.
 260  
      * You can obtain them on the Statuses page
 261  
      * (in 4.0.2 it's under Administration > Issue Settings > Statuses)
 262  
      * - just hover over the Edit link for the status you want and
 263  
      * you'll see something like
 264  
      * &lt;your JIRA URL&gt;/secure/admin/EditStatus!default.jspa?id=12345;
 265  
      * in this case the value is 12345.
 266  
      * </p>
 267  
      * <p>
 268  
      * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter had no
 269  
      * default value.
 270  
      * </p>
 271  
      */
 272  
     @Parameter( defaultValue = "Closed" )
 273  
     private String statusIds;
 274  
 
 275  
     /**
 276  
      * Sets the types(s) that you want to limit your report to include.
 277  
      * Valid types are: <code>Bug</code>, <code>New Feature</code>,
 278  
      * <code>Task</code>, <code>Improvement</code>, <code>Wish</code>,
 279  
      * <code>Test</code> and <code>Sub-task</code>.
 280  
      * Multiple values can be separated by commas.
 281  
      * If this is set to empty - that means all types will be included.
 282  
      *
 283  
      * @since 2.0
 284  
      */
 285  
     @Parameter( defaultValue = "" )
 286  
     private String typeIds;
 287  
 
 288  
     /**
 289  
      * The prefix used when naming versions in JIRA.
 290  
      * <p>
 291  
      * If you have a project in JIRA with several components that have different
 292  
      * release cycles, it is an often used pattern to prefix the version with
 293  
      * the name of the component, e.g. maven-filtering-1.0 etc. To fetch issues
 294  
      * from JIRA for a release of the "maven-filtering" component you would need
 295  
      * to set this parameter to "maven-filtering-".
 296  
      * </p>
 297  
      *
 298  
      * @since 2.4
 299  
      */
 300  
     @Parameter( defaultValue = "" )
 301  
     private String versionPrefix;
 302  
 
 303  
     /**
 304  
      * Defines the http password for basic authentication into the JIRA webserver.
 305  
      */
 306  
     @Parameter( defaultValue = "" )
 307  
     private String webPassword;
 308  
 
 309  
     /**
 310  
      * Defines the http user for basic authentication into the JIRA webserver.
 311  
      */
 312  
     @Parameter( defaultValue = "" )
 313  
     private String webUser;
 314  
     
 315  
     /*
 316  
      * Used for tests.
 317  
      */
 318  
     private AbstractJiraDownloader mockDownloader;
 319  
 
 320  
     /* --------------------------------------------------------------------- */
 321  
     /* Public methods                                                        */
 322  
     /* --------------------------------------------------------------------- */
 323  
 
 324  
     /**
 325  
      * @see org.apache.maven.reporting.AbstractMavenReport#canGenerateReport()
 326  
      */
 327  
     public boolean canGenerateReport()
 328  
     {
 329  6
         if ( skip )
 330  
         {
 331  2
             return false;
 332  
         }
 333  4
         if ( mockDownloader != null ) 
 334  
         {
 335  4
             return true;
 336  
         }
 337  0
         return ProjectUtils.validateIfIssueManagementComplete( project, "JIRA", "JIRA Report", getLog() );
 338  
     }
 339  
 
 340  
     public void executeReport( Locale locale )
 341  
         throws MavenReportException
 342  
     {
 343  
         // Validate parameters
 344  2
         List<Integer> columnIds = IssuesReportHelper.getColumnIds( columnNames, JIRA_COLUMNS );
 345  2
         if ( columnIds.isEmpty() )
 346  
         {
 347  
             // This can happen if the user has configured column names and they are all invalid
 348  0
             throw new MavenReportException(
 349  
                 "maven-changes-plugin: None of the configured columnNames '" + columnNames + "' are valid." );
 350  
         }
 351  
 
 352  
         try
 353  
         {
 354  
             // Download issues
 355  
             AbstractJiraDownloader issueDownloader;
 356  2
             if ( mockDownloader != null )
 357  
             {
 358  2
                 issueDownloader = mockDownloader;
 359  
             }
 360  
             else
 361  
             {
 362  0
                 AdaptiveJiraDownloader downloader = new AdaptiveJiraDownloader();
 363  0
                 downloader.setForceClassic( forceRss );
 364  0
                 issueDownloader = downloader;
 365  
             }
 366  2
             configureIssueDownloader( issueDownloader );
 367  2
             issueDownloader.doExecute();
 368  
 
 369  2
             List<Issue> issueList = issueDownloader.getIssueList();
 370  
 
 371  2
             if ( StringUtils.isNotEmpty( versionPrefix ) )
 372  
             {
 373  0
                 int originalNumberOfIssues = issueList.size();
 374  0
                 issueList = IssueUtils.filterIssuesWithVersionPrefix( issueList, versionPrefix );
 375  0
                 getLog().debug( "Filtered out " + issueList.size() + " issues of " + originalNumberOfIssues
 376  
                     + " that matched the versionPrefix '" + versionPrefix + "'." );
 377  
             }
 378  
 
 379  2
             if ( onlyCurrentVersion )
 380  
             {
 381  0
                 String version = ( versionPrefix == null ? "" : versionPrefix ) + project.getVersion();
 382  0
                 issueList = IssueUtils.getIssuesForVersion( issueList, version );
 383  0
                 getLog().info( "The JIRA Report will contain issues only for the current version." );
 384  
             }
 385  
 
 386  
             // Generate the report
 387  2
             IssuesReportGenerator report = new IssuesReportGenerator( IssuesReportHelper.toIntArray( columnIds ) );
 388  
 
 389  2
             if ( issueList.isEmpty() )
 390  
             {
 391  0
                 report.doGenerateEmptyReport( getBundle( locale ), getSink() );
 392  
             }
 393  
             else
 394  
             {
 395  2
                 report.doGenerateReport( getBundle( locale ), getSink(), issueList );
 396  
             }
 397  
         }
 398  0
         catch ( Exception e )
 399  
         {
 400  0
             getLog().warn( e );
 401  2
         }
 402  2
     }
 403  
 
 404  
     public String getDescription( Locale locale )
 405  
     {
 406  0
         return getBundle( locale ).getString( "report.issues.description" );
 407  
     }
 408  
 
 409  
     public String getName( Locale locale )
 410  
     {
 411  2
         return getBundle( locale ).getString( "report.issues.name" );
 412  
     }
 413  
 
 414  
     public String getOutputName()
 415  
     {
 416  4
         return "jira-report";
 417  
     }
 418  
 
 419  
     /* --------------------------------------------------------------------- */
 420  
     /* Private methods                                                       */
 421  
     /* --------------------------------------------------------------------- */
 422  
 
 423  
     private ResourceBundle getBundle( Locale locale )
 424  
     {
 425  4
         return ResourceBundle.getBundle( "jira-report", locale, this.getClass().getClassLoader() );
 426  
     }
 427  
 
 428  
     private void configureIssueDownloader( AbstractJiraDownloader issueDownloader )
 429  
     {
 430  2
         issueDownloader.setLog( getLog() );
 431  
 
 432  2
         issueDownloader.setMavenProject( project );
 433  
 
 434  2
         issueDownloader.setOutput( jiraXmlPath );
 435  
 
 436  2
         issueDownloader.setNbEntries( maxEntries );
 437  
 
 438  2
         issueDownloader.setComponent( component );
 439  
 
 440  2
         issueDownloader.setFixVersionIds( fixVersionIds );
 441  
 
 442  2
         issueDownloader.setStatusIds( statusIds );
 443  
 
 444  2
         issueDownloader.setResolutionIds( resolutionIds );
 445  
 
 446  2
         issueDownloader.setPriorityIds( priorityIds );
 447  
 
 448  2
         issueDownloader.setSortColumnNames( sortColumnNames );
 449  
 
 450  2
         issueDownloader.setFilter( filter );
 451  
 
 452  2
         issueDownloader.setJiraDatePattern( jiraDatePattern );
 453  
 
 454  2
         issueDownloader.setJiraUser( jiraUser );
 455  
 
 456  2
         issueDownloader.setJiraPassword( jiraPassword );
 457  
 
 458  2
         issueDownloader.setTypeIds( typeIds );
 459  
 
 460  2
         issueDownloader.setWebUser( webUser );
 461  
 
 462  2
         issueDownloader.setWebPassword( webPassword );
 463  
 
 464  2
         issueDownloader.setSettings( settings );
 465  
 
 466  2
         issueDownloader.setUseJql( useJql );
 467  
         
 468  2
         issueDownloader.setOnlyCurrentVersion( onlyCurrentVersion );
 469  
         
 470  2
         issueDownloader.setVersionPrefix( versionPrefix );
 471  2
     }
 472  
 
 473  
     public void setMockDownloader( AbstractJiraDownloader mockDownloader )
 474  
     {
 475  2
         this.mockDownloader = mockDownloader;
 476  2
     }
 477  
 
 478  
     public AbstractJiraDownloader getMockDownloader()
 479  
     {
 480  0
         return mockDownloader;
 481  
     }
 482  
 }