Coverage Report - org.apache.maven.plugin.announcement.AnnouncementMojo
 
Classes in this File Line Coverage Branch Coverage Complexity
AnnouncementMojo
40%
75/186
35%
19/54
2.417
 
 1  
 package org.apache.maven.plugin.announcement;
 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.MojoExecutionException;
 23  
 import org.apache.maven.plugin.changes.ChangesXML;
 24  
 import org.apache.maven.plugin.changes.IssueAdapter;
 25  
 import org.apache.maven.plugin.changes.ProjectUtils;
 26  
 import org.apache.maven.plugin.changes.ReleaseUtils;
 27  
 import org.apache.maven.plugin.github.GitHubDownloader;
 28  
 import org.apache.maven.plugin.github.GitHubIssueManagementSystem;
 29  
 import org.apache.maven.plugin.issues.Issue;
 30  
 import org.apache.maven.plugin.issues.IssueManagementSystem;
 31  
 import org.apache.maven.plugin.issues.IssueUtils;
 32  
 import org.apache.maven.plugin.jira.AbstractJiraDownloader;
 33  
 import org.apache.maven.plugin.jira.AdaptiveJiraDownloader;
 34  
 import org.apache.maven.plugin.jira.JIRAIssueManagmentSystem;
 35  
 import org.apache.maven.plugin.trac.TracDownloader;
 36  
 import org.apache.maven.plugin.trac.TracIssueManagmentSystem;
 37  
 import org.apache.maven.plugins.annotations.Component;
 38  
 import org.apache.maven.plugins.annotations.Mojo;
 39  
 import org.apache.maven.plugins.annotations.Parameter;
 40  
 import org.apache.maven.plugins.annotations.ResolutionScope;
 41  
 import org.apache.maven.plugins.changes.model.Release;
 42  
 import org.apache.maven.project.MavenProject;
 43  
 import org.apache.maven.settings.Settings;
 44  
 import org.apache.velocity.Template;
 45  
 import org.apache.velocity.app.VelocityEngine;
 46  
 import org.apache.velocity.context.Context;
 47  
 import org.apache.velocity.exception.ResourceNotFoundException;
 48  
 import org.apache.velocity.exception.VelocityException;
 49  
 import org.apache.velocity.tools.ToolManager;
 50  
 import org.codehaus.plexus.util.ReaderFactory;
 51  
 import org.codehaus.plexus.util.StringUtils;
 52  
 import org.codehaus.plexus.velocity.VelocityComponent;
 53  
 
 54  
 import java.io.File;
 55  
 import java.io.FileOutputStream;
 56  
 import java.io.OutputStreamWriter;
 57  
 import java.io.Writer;
 58  
 import java.util.ArrayList;
 59  
 import java.util.Collections;
 60  
 import java.util.List;
 61  
 import java.util.Map;
 62  
 
 63  
 /**
 64  
  * Goal which generate an announcement from the announcement template.
 65  
  *
 66  
  * @author aramirez@exist.com
 67  
  * @version $Id: AnnouncementMojo.java 1428434 2013-01-03 16:12:02Z dennisl $
 68  
  * @since 2.0-beta-2
 69  
  */
 70  
 @Mojo( name = "announcement-generate", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true )
 71  2
 public class AnnouncementMojo
 72  
     extends AbstractAnnouncementMojo
 73  
 {
 74  
     private static final String CHANGES_XML = "changes.xml";
 75  
 
 76  
     private static final String JIRA = "JIRA";
 77  
 
 78  
     private static final String TRAC = "Trac";
 79  
 
 80  
     private static final String GIT_HUB = "GitHub";
 81  
 
 82  
     /**
 83  
      * The name of the file which will contain the generated announcement. If
 84  
      * no value is specified the plugin will use the name of the template.
 85  
      *
 86  
      * @since 2.4
 87  
      */
 88  
     @Parameter( property = "changes.announcementFile" )
 89  
     private String announcementFile;
 90  
 
 91  
     /**
 92  
      * Map of custom parameters for the announcement.
 93  
      * This Map will be passed to the template.
 94  
      *
 95  
      * @since 2.1
 96  
      */
 97  
     @Parameter
 98  
     private Map announceParameters;
 99  
 
 100  
     /**
 101  
      */
 102  
     @Parameter( property = "project.artifactId", readonly = true )
 103  
     private String artifactId;
 104  
 
 105  
     /**
 106  
      * Name of the team that develops the artifact.
 107  
      * This parameter will be passed to the template.
 108  
      */
 109  
     @Parameter( property = "changes.developmentTeam", defaultValue = "${project.name} team", required = true )
 110  
     private String developmentTeam;
 111  
 
 112  
     /**
 113  
      * The name of the artifact to be used in the announcement.
 114  
      */
 115  
     @Parameter( property = "changes.finalName", defaultValue = "${project.build.finalName}", required = true )
 116  
     private String finalName;
 117  
 
 118  
     /**
 119  
      */
 120  
     @Parameter( property = "project.groupId", readonly = true )
 121  
     private String groupId;
 122  
 
 123  
     /**
 124  
      * Short description or introduction of the released artifact.
 125  
      * This parameter will be passed to the template.
 126  
      */
 127  
     @Parameter( defaultValue = "${project.description}" )
 128  
     private String introduction;
 129  
 
 130  
     /**
 131  
      * A list of issue management systems to fetch releases from. This parameter
 132  
      * replaces the parameters <code>generateJiraAnnouncement</code> and
 133  
      * <code>jiraMerge</code>.
 134  
      * <p>
 135  
      * Valid values are: <code>changes.xml</code> and <code>JIRA</code>.
 136  
      * </p>
 137  
      * <strong>Note:</strong> Only one issue management system that is
 138  
      * configured in &lt;project&gt;/&lt;issueManagement&gt; can be used. This
 139  
      * currently means that you can combine a changes.xml file with one other
 140  
      * issue management system.
 141  
      *
 142  
      * @since 2.4
 143  
      */
 144  
     @Parameter
 145  
     private List<String> issueManagementSystems;
 146  
 
 147  
     /**
 148  
      * Maps issues types to action types for grouping issues in announcements.
 149  
      * If issue types are not defined for a action type then the default issue type
 150  
      * will be applied.
 151  
      * <p>
 152  
      * Valid action types: <code>add</code>, <code>fix</code> and <code>update</code>.
 153  
      * </p>
 154  
      *
 155  
      * @since 2.6
 156  
      */
 157  
     @Parameter
 158  
     private Map<String, String> issueTypes;
 159  
 
 160  
     /**
 161  
      * Directory where the announcement file will be generated.
 162  
      */
 163  
     @Parameter( defaultValue = "${project.build.directory}/announcement", required = true )
 164  
     private File outputDirectory;
 165  
 
 166  
     /**
 167  
      * Packaging structure for the artifact.
 168  
      */
 169  
     @Parameter( property = "project.packaging", readonly = true )
 170  
     private String packaging;
 171  
 
 172  
     /**
 173  
      * The Maven Project.
 174  
      */
 175  
     @Component
 176  
     private MavenProject project;
 177  
 
 178  
     /**
 179  
      * The Velocity template used to format the announcement.
 180  
      */
 181  
     @Parameter( property = "changes.template", defaultValue = "announcement.vm", required = true )
 182  
     private String template;
 183  
 
 184  
     /**
 185  
      * Directory that contains the template.
 186  
      * <p>
 187  
      * <b>Note:</b> This directory must be a subdirectory of
 188  
      * <code>/src/main/resources/ or current project base directory</code>.
 189  
      * </p>
 190  
      */
 191  
     @Parameter( property = "changes.templateDirectory", defaultValue = "org/apache/maven/plugin/announcement",
 192  
                 required = true )
 193  
     private String templateDirectory;
 194  
 
 195  
     /**
 196  
      * The template encoding.
 197  
      *
 198  
      * @since 2.1
 199  
      */
 200  
     @Parameter( property = "changes.templateEncoding", defaultValue = "${project.build.sourceEncoding}" )
 201  
     private String templateEncoding;
 202  
 
 203  
     /**
 204  
      * Distribution URL of the artifact.
 205  
      * This parameter will be passed to the template.
 206  
      */
 207  
     @Parameter( property = "project.url" )
 208  
     private String url;
 209  
 
 210  
     /**
 211  
      * URL where the artifact can be downloaded. If not specified,
 212  
      * no URL is used.
 213  
      * This parameter will be passed to the template.
 214  
      */
 215  
     @Parameter
 216  
     private String urlDownload;
 217  
 
 218  
     /**
 219  
      * Velocity Component.
 220  
      */
 221  
     @Component( role = VelocityComponent.class, hint = "maven-changes-plugin" )
 222  
     private VelocityComponent velocity;
 223  
 
 224  
     /**
 225  
      * Version of the artifact.
 226  
      */
 227  
     @Parameter( property = "changes.version", defaultValue = "${project.version}", required = true )
 228  
     private String version;
 229  
 
 230  
     /**
 231  
      * The path of the changes.xml file.
 232  
      *
 233  
      * @parameter expression="${basedir}/src/changes/changes.xml"
 234  
      * @required
 235  
      */
 236  
     @Parameter( defaultValue = "${basedir}/src/changes/changes.xml" )
 237  
     private File xmlPath;
 238  
 
 239  
     //=======================================//
 240  
     //  JIRA-Announcement Needed Parameters  //
 241  
     //=======================================//
 242  
 
 243  
     /**
 244  
      * Defines the filter parameters to restrict which issues are retrieved
 245  
      * from JIRA. The filter parameter uses the same format of url
 246  
      * parameters that is used in a JIRA search.
 247  
      *
 248  
      * @since 2.4
 249  
      */
 250  
     @Parameter( defaultValue = "" )
 251  
     private String filter;
 252  
 
 253  
     /**
 254  
      * Flag to determine if the plugin will generate a JIRA announcement.
 255  
      *
 256  
      * @deprecated Since version 2.4 this parameter has been deprecated. Please use the issueManagementSystems parameter instead.
 257  
      */
 258  
     @Parameter( property = "generateJiraAnnouncement", defaultValue = "false", required = true )
 259  
     private boolean generateJiraAnnouncement;
 260  
 
 261  
     /**
 262  
      * If releases from JIRA should be merged with the releases from a
 263  
      * changes.xml file.
 264  
      *
 265  
      * @since 2.1
 266  
      * @deprecated Since version 2.4 this parameter has been deprecated. Please use the issueManagementSystems parameter instead.
 267  
      */
 268  
     @Parameter( property = "changes.jiraMerge", defaultValue = "false" )
 269  
     private boolean jiraMerge;
 270  
 
 271  
     /**
 272  
      * Defines the JIRA password for authentication into a private JIRA installation.
 273  
      *
 274  
      * @since 2.1
 275  
      */
 276  
     @Parameter( property = "changes.jiraPassword", defaultValue = "" )
 277  
     private String jiraPassword;
 278  
 
 279  
     /**
 280  
      * Defines the JIRA username for authentication into a private JIRA installation.
 281  
      *
 282  
      * @since 2.1
 283  
      */
 284  
     @Parameter( property = "changes.jiraUser", defaultValue = "" )
 285  
     private String jiraUser;
 286  
 
 287  
     /**
 288  
      * Path to the JIRA XML file, which will be parsed.
 289  
      */
 290  
     @Parameter( defaultValue = "${project.build.directory}/jira-announcement.xml", required = true, readonly = true )
 291  
     private File jiraXML;
 292  
 
 293  
     /**
 294  
      * The maximum number of issues to fetch from JIRA.
 295  
      * <p>
 296  
      * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter was
 297  
      * called "nbEntries".
 298  
      * </p>
 299  
      */
 300  
     @Parameter( property = "changes.maxEntries", defaultValue = "25", required = true )
 301  
     private int maxEntries;
 302  
 
 303  
     /**
 304  
      * Include issues from JIRA with these resolution ids. Multiple resolution
 305  
      * ids can be specified as a comma separated list of ids.
 306  
      * <p>
 307  
      * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter was
 308  
      * called "resolutionId".
 309  
      * </p>
 310  
      */
 311  
     @Parameter( property = "changes.resolutionIds", defaultValue = "Fixed" )
 312  
     private String resolutionIds;
 313  
 
 314  
     /**
 315  
      * Settings XML configuration.
 316  
      */
 317  
     @Component
 318  
     private Settings settings;
 319  
 
 320  
     /**
 321  
      * Include issues from JIRA with these status ids. Multiple status ids can
 322  
      * be specified as a comma separated list of ids.
 323  
      * <p>
 324  
      * <b>Note:</b> In versions 2.0-beta-3 and earlier this parameter was
 325  
      * called "statusId".
 326  
      * </p>
 327  
      */
 328  
     @Parameter( property = "changes.statusIds", defaultValue = "Closed" )
 329  
     private String statusIds;
 330  
 
 331  
     /**
 332  
      * Defines the http user for basic authentication into the JIRA webserver.
 333  
      *
 334  
      * @since 2.4
 335  
      */
 336  
     @Parameter( property = "changes.webUser", defaultValue = "" )
 337  
     private String webUser;
 338  
 
 339  
     /**
 340  
      * Defines the http password for basic authentication into the JIRA webserver.
 341  
      *
 342  
      * @since 2.4
 343  
      */
 344  
     @Parameter( property = "changes.webPassword", defaultValue = "" )
 345  
     private String webPassword;
 346  
 
 347  
     /**
 348  
      * The prefix used when naming versions in JIRA.
 349  
      * <p>
 350  
      * If you have a project in JIRA with several components that have different
 351  
      * release cycles, it is an often used pattern to prefix the version with
 352  
      * the name of the component, e.g. maven-filtering-1.0 etc. To fetch issues
 353  
      * from JIRA for a release of the "maven-filtering" component you would need
 354  
      * to set this parameter to "maven-filtering-".
 355  
      * </p>
 356  
      *
 357  
      * @since 2.5
 358  
      */
 359  
     @Parameter( property = "changes.versionPrefix", defaultValue = "" )
 360  
     private String versionPrefix;
 361  
 
 362  
     //=======================================//
 363  
     //  Trac Parameters                      //
 364  
     //=======================================//
 365  
 
 366  
     /**
 367  
      * Defines the Trac password for authentication into a private Trac
 368  
      * installation.
 369  
      *
 370  
      * @since 2.4
 371  
      */
 372  
     @Parameter( property = "changes.tracPassword", defaultValue = "" )
 373  
     private String tracPassword;
 374  
 
 375  
     /**
 376  
      * Defines the Trac query for searching for tickets.
 377  
      *
 378  
      * @since 2.4
 379  
      */
 380  
     @Parameter( defaultValue = "order=id" )
 381  
     private String tracQuery;
 382  
 
 383  
     /**
 384  
      * Defines the Trac username for authentication into a private Trac
 385  
      * installation.
 386  
      *
 387  
      * @since 2.4
 388  
      */
 389  
     @Parameter( property = "changes.tracUser", defaultValue = "" )
 390  
     private String tracUser;
 391  
 
 392  
     //=======================================//
 393  
     //  Github Parameters                    //
 394  
     //=======================================//
 395  
 
 396  
     /**
 397  
      * The scheme of your github api domain. Only use if using github enterprise.
 398  
      * 
 399  
      * @since 2.9
 400  
      */
 401  
     @Parameter( defaultValue = "http", property = "changes.githubAPIScheme")
 402  
     private String githubAPIScheme;
 403  
 
 404  
     /**
 405  
      * The port of your github api domain. Only use if using github enterprise.
 406  
      * 
 407  
      * @since 2.9
 408  
      */
 409  
     @Parameter( defaultValue = "80", property = "changes.githubAPIPort")
 410  
     private int githubAPIPort;
 411  
 
 412  2
     private ReleaseUtils releaseUtils = new ReleaseUtils( getLog() );
 413  
 
 414  
     private ChangesXML xml;
 415  
 
 416  
     //=======================================//
 417  
     //    announcement-generate execution    //
 418  
     //=======================================//
 419  
 
 420  
     /**
 421  
      * Generate the template
 422  
      *
 423  
      * @throws MojoExecutionException
 424  
      */
 425  
     public void execute()
 426  
         throws MojoExecutionException
 427  
     {
 428  
         // Run only at the execution root
 429  2
         if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() )
 430  
         {
 431  0
             getLog().info( "Skipping the announcement generation in this project because it's not the Execution Root" );
 432  
         }
 433  
         else
 434  
         {
 435  2
             if ( issueManagementSystems == null )
 436  
             {
 437  2
                 issueManagementSystems = new ArrayList<String>();
 438  
             }
 439  
 
 440  
             // Handle deprecated parameters, in a backward compatible way
 441  2
             if ( issueManagementSystems.isEmpty() )
 442  
             {
 443  2
                 if ( this.jiraMerge )
 444  
                 {
 445  0
                     issueManagementSystems.add( CHANGES_XML );
 446  0
                     issueManagementSystems.add( JIRA );
 447  
                 }
 448  2
                 else if ( generateJiraAnnouncement )
 449  
                 {
 450  0
                     issueManagementSystems.add( JIRA );
 451  
                 }
 452  
                 else
 453  
                 {
 454  2
                     issueManagementSystems.add( CHANGES_XML );
 455  
                 }
 456  
             }
 457  
             
 458  
             // Fetch releases from the configured issue management systems
 459  2
             List<Release> releases = null;
 460  2
             if ( issueManagementSystems.contains( CHANGES_XML ) )
 461  
             {
 462  2
                 if ( getXmlPath().exists() )
 463  
                 {
 464  2
                     ChangesXML changesXML = new ChangesXML( getXmlPath(), getLog() );
 465  2
                     List<Release> changesReleases = releaseUtils.convertReleaseList( changesXML.getReleaseList() );
 466  2
                     releases = releaseUtils.mergeReleases( releases, changesReleases );
 467  2
                     getLog().info( "Including issues from file " + getXmlPath() + " in announcement..." );
 468  2
                 }
 469  
                 else
 470  
                 {
 471  0
                     getLog().warn( "changes.xml file " + getXmlPath().getAbsolutePath() + " does not exist." );
 472  
                 }
 473  
             }
 474  
 
 475  2
             if ( issueManagementSystems.contains( JIRA ) )
 476  
             {
 477  0
                 if ( ProjectUtils.validateIfIssueManagementComplete( project, JIRA, "JIRA announcement", getLog() ) )
 478  
                 {
 479  0
                     List<Release> jiraReleases = getJiraReleases();
 480  0
                     releases = releaseUtils.mergeReleases( releases, jiraReleases );
 481  0
                     getLog().info( "Including issues from JIRA in announcement..." );
 482  0
                 }
 483  
                 else
 484  
                 {
 485  0
                     throw new MojoExecutionException(
 486  
                         "Something is wrong with the Issue Management section. See previous error messages." );
 487  
                 }
 488  
             }
 489  
 
 490  2
             if ( issueManagementSystems.contains( TRAC ) )
 491  
             {
 492  0
                 if ( ProjectUtils.validateIfIssueManagementComplete( project, TRAC, "Trac announcement", getLog() ) )
 493  
                 {
 494  0
                     List<Release> tracReleases = getTracReleases();
 495  0
                     releases = releaseUtils.mergeReleases( releases, tracReleases );
 496  0
                     getLog().info( "Including issues from Trac in announcement..." );
 497  0
                 }
 498  
                 else
 499  
                 {
 500  0
                     throw new MojoExecutionException(
 501  
                         "Something is wrong with the Issue Management section. See previous error messages." );
 502  
                 }
 503  
             }
 504  
 
 505  2
             if ( issueManagementSystems.contains( GIT_HUB ) )
 506  
             {
 507  0
                 if ( ProjectUtils.validateIfIssueManagementComplete( project, GIT_HUB, "GitHub announcement", getLog() ) )
 508  
                 {
 509  0
                     List<Release> gitHubReleases = getGitHubReleases();
 510  0
                     releases = releaseUtils.mergeReleases( releases, gitHubReleases );
 511  0
                     getLog().info( "Including issues from GitHub in announcement..." );
 512  0
                 }
 513  
                 else
 514  
                 {
 515  0
                     throw new MojoExecutionException(
 516  
                                                       "Something is wrong with the Issue Management section. See previous error messages." );
 517  
                 }
 518  
             }
 519  
 
 520  
             // @todo Add more issue management systems here.
 521  
 
 522  
             // Follow these steps:
 523  
             // 1. Add a constant for the name of the issue management system
 524  
             // 2. Add the @parameters needed to configure the issue management system
 525  
             // 3. Add a protected List get<IMSname>Releases() method that retrieves a list of releases
 526  
             // 4. Merge those releases into the "releases" variable
 527  
             // For help with these steps, you can have a look at how this has been done for JIRA or Trac
 528  
 
 529  
             // Generate the report
 530  2
             if ( releases == null || releases.isEmpty() )
 531  
             {
 532  0
                 throw new MojoExecutionException(
 533  
                     "No releases found in any of the configured issue management systems." );
 534  
             }
 535  
             else
 536  
             {
 537  2
                 doGenerate( releases );
 538  
             }
 539  
         }
 540  2
     }
 541  
 
 542  
     /**
 543  
      * Add the parameters to velocity context
 544  
      *
 545  
      * @param releases A <code>List</code> of <code>Release</code>s
 546  
      * @throws MojoExecutionException
 547  
      */
 548  
     public void doGenerate( List<Release> releases )
 549  
         throws MojoExecutionException
 550  
     {
 551  2
         String version = ( versionPrefix == null ? "" : versionPrefix ) + getVersion();
 552  
 
 553  2
         getLog().debug( "Generating announcement for version [" + version + "]. Found these releases: "
 554  
                         + ReleaseUtils.toString( releases ) );
 555  
 
 556  2
         doGenerate( releases, releaseUtils.getLatestRelease( releases, version ) );
 557  2
     }
 558  
 
 559  
     protected void doGenerate( List<Release> releases, Release release )
 560  
         throws MojoExecutionException
 561  
     {
 562  
         try
 563  
         {
 564  2
             ToolManager toolManager = new ToolManager( true );
 565  2
             Context context = toolManager.createContext();
 566  
 
 567  2
             if ( getIntroduction() == null || getIntroduction().equals( "" ) )
 568  
             {
 569  0
                 setIntroduction( getUrl() );
 570  
             }
 571  
 
 572  2
             context.put( "releases", releases );
 573  
 
 574  2
             context.put( "groupId", getGroupId() );
 575  
 
 576  2
             context.put( "artifactId", getArtifactId() );
 577  
 
 578  2
             context.put( "version", getVersion() );
 579  
 
 580  2
             context.put( "packaging", getPackaging() );
 581  
 
 582  2
             context.put( "url", getUrl() );
 583  
 
 584  2
             context.put( "release", release );
 585  
 
 586  2
             context.put( "introduction", getIntroduction() );
 587  
 
 588  2
             context.put( "developmentTeam", getDevelopmentTeam() );
 589  
 
 590  2
             context.put( "finalName", getFinalName() );
 591  
 
 592  2
             context.put( "urlDownload", getUrlDownload() );
 593  
 
 594  2
             context.put( "project", project );
 595  
 
 596  2
             if ( announceParameters == null )
 597  
             {
 598  
                 // empty Map to prevent NPE in velocity execution
 599  2
                 context.put( "announceParameters", Collections.EMPTY_MAP );
 600  
             }
 601  
             else
 602  
             {
 603  0
                 context.put( "announceParameters", announceParameters );
 604  
             }
 605  
 
 606  
 
 607  2
             processTemplate( context, getOutputDirectory(), template, announcementFile );
 608  
         }
 609  0
         catch ( ResourceNotFoundException rnfe )
 610  
         {
 611  0
             throw new MojoExecutionException( "Resource not found.", rnfe );
 612  
         }
 613  0
         catch ( VelocityException ve )
 614  
         {
 615  0
             throw new MojoExecutionException( ve.toString(), ve );
 616  2
         }
 617  2
     }
 618  
 
 619  
     /**
 620  
      * Create the velocity template
 621  
      *
 622  
      * @param context velocity context that has the parameter values
 623  
      * @param outputDirectory directory where the file will be generated
 624  
      * @param template velocity template which will the context be merged
 625  
      * @param announcementFile The file name of the generated announcement
 626  
      * @throws ResourceNotFoundException, VelocityException, IOException
 627  
      */
 628  
     public void processTemplate( Context context, File outputDirectory, String template, String announcementFile )
 629  
         throws ResourceNotFoundException, VelocityException, MojoExecutionException
 630  
     {
 631  
         File f;
 632  
 
 633  
         // Use the name of the template as a default value
 634  2
         if ( StringUtils.isEmpty( announcementFile ) )
 635  
         {
 636  2
             announcementFile = template;
 637  
         }
 638  
 
 639  
         try
 640  
         {
 641  2
             f = new File( outputDirectory, announcementFile );
 642  
 
 643  2
             if ( !f.getParentFile().exists() )
 644  
             {
 645  0
                 f.getParentFile().mkdirs();
 646  
             }
 647  
 
 648  2
             VelocityEngine engine = velocity.getEngine();
 649  
 
 650  2
             engine.setApplicationAttribute( "baseDirectory", basedir );
 651  
 
 652  2
             if ( StringUtils.isEmpty( templateEncoding ) )
 653  
             {
 654  2
                 templateEncoding =  ReaderFactory.FILE_ENCODING;
 655  2
                 getLog().warn(
 656  
                                "File encoding has not been set, using platform encoding " + templateEncoding
 657  
                                    + ", i.e. build is platform dependent!" );
 658  
             }
 659  
 
 660  2
             Writer writer = new OutputStreamWriter( new FileOutputStream( f ), templateEncoding );
 661  
 
 662  2
             Template velocityTemplate = engine.getTemplate( templateDirectory + "/" + template, templateEncoding );
 663  
 
 664  2
             velocityTemplate.merge( context, writer );
 665  
 
 666  2
             writer.flush();
 667  
 
 668  2
             writer.close();
 669  
 
 670  2
             getLog().info( "Created template " + f );
 671  
         }
 672  
 
 673  0
         catch ( ResourceNotFoundException rnfe )
 674  
         {
 675  0
             throw new ResourceNotFoundException( "Template not found. ( " + templateDirectory + "/" + template + " )" );
 676  
         }
 677  0
         catch ( VelocityException ve )
 678  
         {
 679  0
             throw new VelocityException( ve.toString() );
 680  
         }
 681  
 
 682  0
         catch ( Exception e )
 683  
         {
 684  0
             if ( e.getCause() != null )
 685  
             {
 686  0
                 getLog().warn( e.getCause() );
 687  
             }
 688  0
             throw new MojoExecutionException( e.toString(), e.getCause() );
 689  2
         }
 690  2
     }
 691  
 
 692  
     protected List<Release> getJiraReleases()
 693  
         throws MojoExecutionException
 694  
     {
 695  0
         AbstractJiraDownloader jiraDownloader = new AdaptiveJiraDownloader();
 696  
 
 697  0
         File jiraXMLFile = jiraXML;
 698  
 
 699  0
         jiraDownloader.setLog( getLog() );
 700  
 
 701  0
         jiraDownloader.setOutput( jiraXMLFile );
 702  
 
 703  0
         jiraDownloader.setStatusIds( statusIds );
 704  
 
 705  0
         jiraDownloader.setResolutionIds( resolutionIds );
 706  
 
 707  0
         jiraDownloader.setMavenProject( project );
 708  
 
 709  0
         jiraDownloader.setSettings( settings );
 710  
 
 711  0
         jiraDownloader.setNbEntries( maxEntries );
 712  
 
 713  0
         jiraDownloader.setFilter( filter );
 714  
 
 715  0
         jiraDownloader.setJiraUser( jiraUser );
 716  
 
 717  0
         jiraDownloader.setJiraPassword( jiraPassword );
 718  
 
 719  0
         jiraDownloader.setWebUser( webUser );
 720  
 
 721  0
         jiraDownloader.setWebPassword( webPassword );
 722  
 
 723  
         try
 724  
         {
 725  0
             jiraDownloader.doExecute();
 726  
 
 727  0
             List<Issue> issueList = jiraDownloader.getIssueList();
 728  
 
 729  0
             if ( StringUtils.isNotEmpty( versionPrefix ) )
 730  
             {
 731  0
                 int originalNumberOfIssues = issueList.size();
 732  0
                 issueList = IssueUtils.filterIssuesWithVersionPrefix( issueList, versionPrefix );
 733  0
                 getLog().debug( "Filtered out " + issueList.size() + " issues of " + originalNumberOfIssues
 734  
                     + " that matched the versionPrefix '" + versionPrefix + "'." );
 735  
             }
 736  
 
 737  0
             return getReleases( issueList, new JIRAIssueManagmentSystem() );
 738  
         }
 739  0
         catch ( Exception e )
 740  
         {
 741  0
             throw new MojoExecutionException( "Failed to extract issues from JIRA.", e );
 742  
         }
 743  
     }
 744  
 
 745  
     private List<Release> getReleases( List<Issue> issues, IssueManagementSystem ims )
 746  
         throws MojoExecutionException
 747  
     {
 748  0
         if ( issueTypes != null ) 
 749  
         {
 750  0
             ims.applyConfiguration( issueTypes );
 751  
         }
 752  0
         if ( issues.isEmpty() )
 753  
         {
 754  0
             return Collections.emptyList();
 755  
         }
 756  
         else
 757  
         {
 758  0
             IssueAdapter adapter = new IssueAdapter( ims );
 759  0
             return adapter.getReleases( issues );
 760  
         }
 761  
     }
 762  
 
 763  
     protected List<Release> getTracReleases()
 764  
         throws MojoExecutionException
 765  
     {
 766  0
         TracDownloader issueDownloader = new TracDownloader();
 767  
 
 768  0
         issueDownloader.setProject( project );
 769  
 
 770  0
         issueDownloader.setQuery( tracQuery );
 771  
 
 772  0
         issueDownloader.setTracPassword( tracPassword );
 773  
 
 774  0
         issueDownloader.setTracUser( tracUser );
 775  
 
 776  
         try
 777  
         {
 778  0
             return getReleases( issueDownloader.getIssueList(), new TracIssueManagmentSystem() );
 779  
         }
 780  0
         catch ( Exception e )
 781  
         {
 782  0
             throw new MojoExecutionException( "Failed to extract issues from Trac.", e );
 783  
         }
 784  
     }
 785  
 
 786  
     protected List<Release> getGitHubReleases()
 787  
         throws MojoExecutionException
 788  
     {
 789  
         try
 790  
         {
 791  0
             GitHubDownloader issueDownloader =
 792  
                 new GitHubDownloader( project, githubAPIScheme, githubAPIPort, false, true );
 793  0
             return getReleases( issueDownloader.getIssueList(), new GitHubIssueManagementSystem() );
 794  
         }
 795  0
         catch ( Exception e )
 796  
         {
 797  0
             throw new MojoExecutionException( "Failed to extract issues from GitHub.", e );
 798  
         }
 799  
     }
 800  
 
 801  
     /*
 802  
      * accessors
 803  
      */
 804  
 
 805  
     public String getArtifactId()
 806  
     {
 807  2
         return artifactId;
 808  
     }
 809  
 
 810  
     public void setArtifactId( String artifactId )
 811  
     {
 812  0
         this.artifactId = artifactId;
 813  0
     }
 814  
 
 815  
     public String getDevelopmentTeam()
 816  
     {
 817  2
         return developmentTeam;
 818  
     }
 819  
 
 820  
     public void setDevelopmentTeam( String developmentTeam )
 821  
     {
 822  0
         this.developmentTeam = developmentTeam;
 823  0
     }
 824  
 
 825  
     public String getFinalName()
 826  
     {
 827  2
         return finalName;
 828  
     }
 829  
 
 830  
     public void setFinalName( String finalName )
 831  
     {
 832  0
         this.finalName = finalName;
 833  0
     }
 834  
 
 835  
     public String getGroupId()
 836  
     {
 837  2
         return groupId;
 838  
     }
 839  
 
 840  
     public void setGroupId( String groupId )
 841  
     {
 842  0
         this.groupId = groupId;
 843  0
     }
 844  
 
 845  
     public String getIntroduction()
 846  
     {
 847  6
         return introduction;
 848  
     }
 849  
 
 850  
     public void setIntroduction( String introduction )
 851  
     {
 852  0
         this.introduction = introduction;
 853  0
     }
 854  
     
 855  
     public void setIssueTypes( Map<String, String> issueTypes )
 856  
     {
 857  0
                 this.issueTypes = issueTypes;
 858  0
         }
 859  
 
 860  
     public Map<String, String> getIssueTypes()
 861  
     {
 862  0
                 return issueTypes;
 863  
         }
 864  
 
 865  
     public File getOutputDirectory()
 866  
     {
 867  2
         return outputDirectory;
 868  
     }
 869  
 
 870  
     public void setOutputDirectory( File outputDirectory )
 871  
     {
 872  0
         this.outputDirectory = outputDirectory;
 873  0
     }
 874  
 
 875  
     public String getPackaging()
 876  
     {
 877  2
         return packaging;
 878  
     }
 879  
 
 880  
     public void setPackaging( String packaging )
 881  
     {
 882  0
         this.packaging = packaging;
 883  0
     }
 884  
 
 885  
     public String getUrl()
 886  
     {
 887  2
         return url;
 888  
     }
 889  
 
 890  
     public void setUrl( String url )
 891  
     {
 892  0
         this.url = url;
 893  0
     }
 894  
 
 895  
     public String getUrlDownload()
 896  
     {
 897  2
         return urlDownload;
 898  
     }
 899  
 
 900  
     public void setUrlDownload( String urlDownload )
 901  
     {
 902  0
         this.urlDownload = urlDownload;
 903  0
     }
 904  
 
 905  
     public VelocityComponent getVelocity()
 906  
     {
 907  0
         return velocity;
 908  
     }
 909  
 
 910  
     public void setVelocity( VelocityComponent velocity )
 911  
     {
 912  0
         this.velocity = velocity;
 913  0
     }
 914  
 
 915  
     public String getVersion()
 916  
     {
 917  4
         return version;
 918  
     }
 919  
 
 920  
     public void setVersion( String version )
 921  
     {
 922  0
         this.version = version;
 923  0
     }
 924  
 
 925  
     public ChangesXML getXml()
 926  
     {
 927  0
         return xml;
 928  
     }
 929  
 
 930  
     public void setXml( ChangesXML xml )
 931  
     {
 932  0
         this.xml = xml;
 933  0
     }
 934  
 
 935  
     public File getXmlPath()
 936  
     {
 937  6
         return xmlPath;
 938  
     }
 939  
 
 940  
     public void setXmlPath( File xmlPath )
 941  
     {
 942  0
         this.xmlPath = xmlPath;
 943  0
     }
 944  
 }