View Javadoc

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  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     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         if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() )
430         {
431             getLog().info( "Skipping the announcement generation in this project because it's not the Execution Root" );
432         }
433         else
434         {
435             if ( issueManagementSystems == null )
436             {
437                 issueManagementSystems = new ArrayList<String>();
438             }
439 
440             // Handle deprecated parameters, in a backward compatible way
441             if ( issueManagementSystems.isEmpty() )
442             {
443                 if ( this.jiraMerge )
444                 {
445                     issueManagementSystems.add( CHANGES_XML );
446                     issueManagementSystems.add( JIRA );
447                 }
448                 else if ( generateJiraAnnouncement )
449                 {
450                     issueManagementSystems.add( JIRA );
451                 }
452                 else
453                 {
454                     issueManagementSystems.add( CHANGES_XML );
455                 }
456             }
457             
458             // Fetch releases from the configured issue management systems
459             List<Release> releases = null;
460             if ( issueManagementSystems.contains( CHANGES_XML ) )
461             {
462                 if ( getXmlPath().exists() )
463                 {
464                     ChangesXML changesXML = new ChangesXML( getXmlPath(), getLog() );
465                     List<Release> changesReleases = releaseUtils.convertReleaseList( changesXML.getReleaseList() );
466                     releases = releaseUtils.mergeReleases( releases, changesReleases );
467                     getLog().info( "Including issues from file " + getXmlPath() + " in announcement..." );
468                 }
469                 else
470                 {
471                     getLog().warn( "changes.xml file " + getXmlPath().getAbsolutePath() + " does not exist." );
472                 }
473             }
474 
475             if ( issueManagementSystems.contains( JIRA ) )
476             {
477                 if ( ProjectUtils.validateIfIssueManagementComplete( project, JIRA, "JIRA announcement", getLog() ) )
478                 {
479                     List<Release> jiraReleases = getJiraReleases();
480                     releases = releaseUtils.mergeReleases( releases, jiraReleases );
481                     getLog().info( "Including issues from JIRA in announcement..." );
482                 }
483                 else
484                 {
485                     throw new MojoExecutionException(
486                         "Something is wrong with the Issue Management section. See previous error messages." );
487                 }
488             }
489 
490             if ( issueManagementSystems.contains( TRAC ) )
491             {
492                 if ( ProjectUtils.validateIfIssueManagementComplete( project, TRAC, "Trac announcement", getLog() ) )
493                 {
494                     List<Release> tracReleases = getTracReleases();
495                     releases = releaseUtils.mergeReleases( releases, tracReleases );
496                     getLog().info( "Including issues from Trac in announcement..." );
497                 }
498                 else
499                 {
500                     throw new MojoExecutionException(
501                         "Something is wrong with the Issue Management section. See previous error messages." );
502                 }
503             }
504 
505             if ( issueManagementSystems.contains( GIT_HUB ) )
506             {
507                 if ( ProjectUtils.validateIfIssueManagementComplete( project, GIT_HUB, "GitHub announcement", getLog() ) )
508                 {
509                     List<Release> gitHubReleases = getGitHubReleases();
510                     releases = releaseUtils.mergeReleases( releases, gitHubReleases );
511                     getLog().info( "Including issues from GitHub in announcement..." );
512                 }
513                 else
514                 {
515                     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             if ( releases == null || releases.isEmpty() )
531             {
532                 throw new MojoExecutionException(
533                     "No releases found in any of the configured issue management systems." );
534             }
535             else
536             {
537                 doGenerate( releases );
538             }
539         }
540     }
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         String version = ( versionPrefix == null ? "" : versionPrefix ) + getVersion();
552 
553         getLog().debug( "Generating announcement for version [" + version + "]. Found these releases: "
554                         + ReleaseUtils.toString( releases ) );
555 
556         doGenerate( releases, releaseUtils.getLatestRelease( releases, version ) );
557     }
558 
559     protected void doGenerate( List<Release> releases, Release release )
560         throws MojoExecutionException
561     {
562         try
563         {
564             ToolManager toolManager = new ToolManager( true );
565             Context context = toolManager.createContext();
566 
567             if ( getIntroduction() == null || getIntroduction().equals( "" ) )
568             {
569                 setIntroduction( getUrl() );
570             }
571 
572             context.put( "releases", releases );
573 
574             context.put( "groupId", getGroupId() );
575 
576             context.put( "artifactId", getArtifactId() );
577 
578             context.put( "version", getVersion() );
579 
580             context.put( "packaging", getPackaging() );
581 
582             context.put( "url", getUrl() );
583 
584             context.put( "release", release );
585 
586             context.put( "introduction", getIntroduction() );
587 
588             context.put( "developmentTeam", getDevelopmentTeam() );
589 
590             context.put( "finalName", getFinalName() );
591 
592             context.put( "urlDownload", getUrlDownload() );
593 
594             context.put( "project", project );
595 
596             if ( announceParameters == null )
597             {
598                 // empty Map to prevent NPE in velocity execution
599                 context.put( "announceParameters", Collections.EMPTY_MAP );
600             }
601             else
602             {
603                 context.put( "announceParameters", announceParameters );
604             }
605 
606 
607             processTemplate( context, getOutputDirectory(), template, announcementFile );
608         }
609         catch ( ResourceNotFoundException rnfe )
610         {
611             throw new MojoExecutionException( "Resource not found.", rnfe );
612         }
613         catch ( VelocityException ve )
614         {
615             throw new MojoExecutionException( ve.toString(), ve );
616         }
617     }
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         if ( StringUtils.isEmpty( announcementFile ) )
635         {
636             announcementFile = template;
637         }
638 
639         try
640         {
641             f = new File( outputDirectory, announcementFile );
642 
643             if ( !f.getParentFile().exists() )
644             {
645                 f.getParentFile().mkdirs();
646             }
647 
648             VelocityEngine engine = velocity.getEngine();
649 
650             engine.setApplicationAttribute( "baseDirectory", basedir );
651 
652             if ( StringUtils.isEmpty( templateEncoding ) )
653             {
654                 templateEncoding =  ReaderFactory.FILE_ENCODING;
655                 getLog().warn(
656                                "File encoding has not been set, using platform encoding " + templateEncoding
657                                    + ", i.e. build is platform dependent!" );
658             }
659 
660             Writer writer = new OutputStreamWriter( new FileOutputStream( f ), templateEncoding );
661 
662             Template velocityTemplate = engine.getTemplate( templateDirectory + "/" + template, templateEncoding );
663 
664             velocityTemplate.merge( context, writer );
665 
666             writer.flush();
667 
668             writer.close();
669 
670             getLog().info( "Created template " + f );
671         }
672 
673         catch ( ResourceNotFoundException rnfe )
674         {
675             throw new ResourceNotFoundException( "Template not found. ( " + templateDirectory + "/" + template + " )" );
676         }
677         catch ( VelocityException ve )
678         {
679             throw new VelocityException( ve.toString() );
680         }
681 
682         catch ( Exception e )
683         {
684             if ( e.getCause() != null )
685             {
686                 getLog().warn( e.getCause() );
687             }
688             throw new MojoExecutionException( e.toString(), e.getCause() );
689         }
690     }
691 
692     protected List<Release> getJiraReleases()
693         throws MojoExecutionException
694     {
695         AbstractJiraDownloader jiraDownloader = new AdaptiveJiraDownloader();
696 
697         File jiraXMLFile = jiraXML;
698 
699         jiraDownloader.setLog( getLog() );
700 
701         jiraDownloader.setOutput( jiraXMLFile );
702 
703         jiraDownloader.setStatusIds( statusIds );
704 
705         jiraDownloader.setResolutionIds( resolutionIds );
706 
707         jiraDownloader.setMavenProject( project );
708 
709         jiraDownloader.setSettings( settings );
710 
711         jiraDownloader.setNbEntries( maxEntries );
712 
713         jiraDownloader.setFilter( filter );
714 
715         jiraDownloader.setJiraUser( jiraUser );
716 
717         jiraDownloader.setJiraPassword( jiraPassword );
718 
719         jiraDownloader.setWebUser( webUser );
720 
721         jiraDownloader.setWebPassword( webPassword );
722 
723         try
724         {
725             jiraDownloader.doExecute();
726 
727             List<Issue> issueList = jiraDownloader.getIssueList();
728 
729             if ( StringUtils.isNotEmpty( versionPrefix ) )
730             {
731                 int originalNumberOfIssues = issueList.size();
732                 issueList = IssueUtils.filterIssuesWithVersionPrefix( issueList, versionPrefix );
733                 getLog().debug( "Filtered out " + issueList.size() + " issues of " + originalNumberOfIssues
734                     + " that matched the versionPrefix '" + versionPrefix + "'." );
735             }
736 
737             return getReleases( issueList, new JIRAIssueManagmentSystem() );
738         }
739         catch ( Exception e )
740         {
741             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         if ( issueTypes != null ) 
749         {
750             ims.applyConfiguration( issueTypes );
751         }
752         if ( issues.isEmpty() )
753         {
754             return Collections.emptyList();
755         }
756         else
757         {
758             IssueAdapter adapter = new IssueAdapter( ims );
759             return adapter.getReleases( issues );
760         }
761     }
762 
763     protected List<Release> getTracReleases()
764         throws MojoExecutionException
765     {
766         TracDownloader issueDownloader = new TracDownloader();
767 
768         issueDownloader.setProject( project );
769 
770         issueDownloader.setQuery( tracQuery );
771 
772         issueDownloader.setTracPassword( tracPassword );
773 
774         issueDownloader.setTracUser( tracUser );
775 
776         try
777         {
778             return getReleases( issueDownloader.getIssueList(), new TracIssueManagmentSystem() );
779         }
780         catch ( Exception e )
781         {
782             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             GitHubDownloader issueDownloader =
792                 new GitHubDownloader( project, githubAPIScheme, githubAPIPort, false, true );
793             return getReleases( issueDownloader.getIssueList(), new GitHubIssueManagementSystem() );
794         }
795         catch ( Exception e )
796         {
797             throw new MojoExecutionException( "Failed to extract issues from GitHub.", e );
798         }
799     }
800 
801     /*
802      * accessors
803      */
804 
805     public String getArtifactId()
806     {
807         return artifactId;
808     }
809 
810     public void setArtifactId( String artifactId )
811     {
812         this.artifactId = artifactId;
813     }
814 
815     public String getDevelopmentTeam()
816     {
817         return developmentTeam;
818     }
819 
820     public void setDevelopmentTeam( String developmentTeam )
821     {
822         this.developmentTeam = developmentTeam;
823     }
824 
825     public String getFinalName()
826     {
827         return finalName;
828     }
829 
830     public void setFinalName( String finalName )
831     {
832         this.finalName = finalName;
833     }
834 
835     public String getGroupId()
836     {
837         return groupId;
838     }
839 
840     public void setGroupId( String groupId )
841     {
842         this.groupId = groupId;
843     }
844 
845     public String getIntroduction()
846     {
847         return introduction;
848     }
849 
850     public void setIntroduction( String introduction )
851     {
852         this.introduction = introduction;
853     }
854     
855     public void setIssueTypes( Map<String, String> issueTypes )
856     {
857 		this.issueTypes = issueTypes;
858 	}
859 
860     public Map<String, String> getIssueTypes()
861     {
862 		return issueTypes;
863 	}
864 
865     public File getOutputDirectory()
866     {
867         return outputDirectory;
868     }
869 
870     public void setOutputDirectory( File outputDirectory )
871     {
872         this.outputDirectory = outputDirectory;
873     }
874 
875     public String getPackaging()
876     {
877         return packaging;
878     }
879 
880     public void setPackaging( String packaging )
881     {
882         this.packaging = packaging;
883     }
884 
885     public String getUrl()
886     {
887         return url;
888     }
889 
890     public void setUrl( String url )
891     {
892         this.url = url;
893     }
894 
895     public String getUrlDownload()
896     {
897         return urlDownload;
898     }
899 
900     public void setUrlDownload( String urlDownload )
901     {
902         this.urlDownload = urlDownload;
903     }
904 
905     public VelocityComponent getVelocity()
906     {
907         return velocity;
908     }
909 
910     public void setVelocity( VelocityComponent velocity )
911     {
912         this.velocity = velocity;
913     }
914 
915     public String getVersion()
916     {
917         return version;
918     }
919 
920     public void setVersion( String version )
921     {
922         this.version = version;
923     }
924 
925     public ChangesXML getXml()
926     {
927         return xml;
928     }
929 
930     public void setXml( ChangesXML xml )
931     {
932         this.xml = xml;
933     }
934 
935     public File getXmlPath()
936     {
937         return xmlPath;
938     }
939 
940     public void setXmlPath( File xmlPath )
941     {
942         this.xmlPath = xmlPath;
943     }
944 }