1 package org.apache.maven.plugin.announcement;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.OutputStreamWriter;
25 import java.io.Writer;
26 import java.util.Collections;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30
31 import org.apache.maven.plugin.AbstractMojo;
32 import org.apache.maven.plugin.MojoExecutionException;
33 import org.apache.maven.plugin.changes.ChangesXML;
34 import org.apache.maven.plugin.jira.JiraXML;
35 import org.apache.maven.plugins.changes.model.Action;
36 import org.apache.maven.plugins.changes.model.Release;
37 import org.apache.maven.project.MavenProject;
38 import org.apache.maven.settings.Settings;
39 import org.apache.velocity.Template;
40 import org.apache.velocity.VelocityContext;
41 import org.apache.velocity.app.VelocityEngine;
42 import org.apache.velocity.context.Context;
43 import org.apache.velocity.exception.ResourceNotFoundException;
44 import org.apache.velocity.exception.VelocityException;
45 import org.codehaus.plexus.util.ReaderFactory;
46 import org.codehaus.plexus.util.StringUtils;
47 import org.codehaus.plexus.velocity.VelocityComponent;
48
49
50
51
52
53
54
55
56
57 public class AnnouncementMojo
58 extends AbstractMojo
59 {
60 private static final String SNAPSHOT_SUFFIX = "-SNAPSHOT";
61
62
63
64
65
66
67
68 private File outputDirectory;
69
70
71
72
73
74 private String groupId;
75
76
77
78
79
80 private String artifactId;
81
82
83
84
85
86
87
88 private String version;
89
90
91
92
93
94
95
96 private String url;
97
98
99
100
101
102
103
104 private String packaging;
105
106
107
108
109
110
111
112 private String finalName;
113
114
115
116
117
118
119
120
121 private String urlDownload;
122
123
124
125
126
127
128
129 private File xmlPath;
130
131
132
133
134
135
136
137
138 private String developmentTeam;
139
140
141
142
143
144
145
146 private String introduction;
147
148
149
150
151
152
153
154 private VelocityComponent velocity;
155
156
157
158
159
160
161
162 private String template;
163
164
165
166
167
168
169
170
171
172
173
174 private String templateDirectory;
175
176
177
178
179
180
181
182
183 private String basedir;
184
185 private ChangesXML xml;
186
187
188
189
190
191
192
193
194
195
196
197
198 private MavenProject project;
199
200
201
202
203
204
205
206
207 private Settings settings;
208
209
210
211
212
213
214
215 private boolean generateJiraAnnouncement;
216
217
218
219
220
221
222
223
224
225
226
227 private String statusIds;
228
229
230
231
232
233
234
235
236
237
238
239 private String resolutionIds;
240
241
242
243
244
245
246
247
248 private File jiraXML;
249
250
251
252
253
254
255
256
257
258
259
260 private int maxEntries;
261
262
263
264
265
266
267
268 private String jiraUser;
269
270
271
272
273
274
275
276 private String jiraPassword;
277
278
279
280
281
282
283
284 private String templateEncoding;
285
286
287
288
289
290
291
292
293 private boolean jiraMerge;
294
295
296
297
298
299
300
301
302 private Map announceParameters;
303
304
305
306
307
308
309
310
311
312
313 public void execute()
314 throws MojoExecutionException
315 {
316 if ( this.jiraMerge )
317 {
318 ChangesXML changesXML = new ChangesXML( getXmlPath(), getLog() );
319 List changesReleases = changesXML.getReleaseList();
320 List jiraReleases = getJiraReleases();
321 List mergedReleases = mergeReleases( changesReleases, jiraReleases );
322 doGenerate( mergedReleases );
323 }
324 else
325 {
326 if ( !generateJiraAnnouncement )
327 {
328 if ( getXmlPath().exists() )
329 {
330 setXml( new ChangesXML( getXmlPath(), getLog() ) );
331
332 getLog().info( "Creating announcement file from " + getXmlPath() + "..." );
333
334 doGenerate( getXml().getReleaseList() );
335 }
336 else
337 {
338 getLog().warn( "changes.xml file " + getXmlPath().getAbsolutePath() + " does not exist." );
339 }
340 }
341 else
342 {
343 doJiraGenerate();
344 }
345 }
346 }
347
348
349
350
351
352
353
354 public void doGenerate( List releases )
355 throws MojoExecutionException
356 {
357 doGenerate( releases, getLatestRelease( releases ) );
358 }
359
360 protected void doGenerate( List releases, Release release )
361 throws MojoExecutionException
362 {
363 try
364 {
365 Context context = new VelocityContext();
366
367 if ( getIntroduction() == null || getIntroduction().equals( "" ) )
368 {
369 setIntroduction( getUrl() );
370 }
371
372 context.put( "releases", releases );
373
374 context.put( "groupId", getGroupId() );
375
376 context.put( "artifactId", getArtifactId() );
377
378 context.put( "version", getVersion() );
379
380 context.put( "packaging", getPackaging() );
381
382 context.put( "url", getUrl() );
383
384 context.put( "release", release );
385
386 context.put( "introduction", getIntroduction() );
387
388 context.put( "developmentTeam", getDevelopmentTeam() );
389
390 context.put( "finalName", getFinalName() );
391
392 context.put( "urlDownload", getUrlDownload() );
393
394 context.put( "project", project );
395
396 if ( announceParameters == null )
397 {
398
399 context.put( "announceParameters", Collections.EMPTY_MAP );
400 }
401 else
402 {
403 context.put( "announceParameters", announceParameters );
404 }
405
406
407 processTemplate( context, getOutputDirectory(), template );
408 }
409 catch ( ResourceNotFoundException rnfe )
410 {
411 throw new MojoExecutionException( "Resource not found.", rnfe );
412 }
413 catch ( VelocityException ve )
414 {
415 throw new MojoExecutionException( ve.toString(), ve );
416 }
417 }
418
419
420
421
422
423
424
425
426
427 public Release getLatestRelease( List releases )
428 throws MojoExecutionException
429 {
430 boolean isFound = false;
431
432 Release release = null;
433
434
435 String pomVersion = getVersion();
436 if ( pomVersion != null && pomVersion.endsWith( SNAPSHOT_SUFFIX ) )
437 {
438 pomVersion = pomVersion.substring( 0, pomVersion.length() - SNAPSHOT_SUFFIX.length() );
439 }
440 getLog().debug( "Found " + releases.size() + " releases." );
441
442 for ( int i = 0; i < releases.size(); i++ )
443 {
444 release = (Release) releases.get( i );
445 if ( getLog().isDebugEnabled() )
446 {
447 getLog().debug( "The release: " + release.getVersion()
448 + " has " + release.getActions().size() + " actions." );
449 }
450
451 if ( release.getVersion() != null && release.getVersion().equals( pomVersion ) )
452 {
453 isFound = true;
454 if ( getLog().isDebugEnabled() )
455 {
456 getLog().debug( "Found the correct release: " + release.getVersion() );
457 logRelease( release );
458 }
459 return release;
460 }
461 }
462
463 release = getRelease( releases, pomVersion );
464 isFound = ( release != null );
465
466 if ( !isFound )
467 {
468 throw new MojoExecutionException( "Couldn't find the release '" + pomVersion
469 + "' among the supplied releases." );
470 }
471 else
472 {
473
474 }
475 return release;
476 }
477
478
479 protected Release getRelease( List releases, String version )
480 {
481 Release release = null;
482 for ( int i = 0; i < releases.size(); i++ )
483 {
484 release = (Release) releases.get( i );
485 if ( getLog().isDebugEnabled() )
486 {
487 getLog().debug( "The release: " + release.getVersion()
488 + " has " + release.getActions().size() + " actions." );
489 }
490
491 if ( release.getVersion() != null && release.getVersion().equals( version ) )
492 {
493 if ( getLog().isDebugEnabled() )
494 {
495 getLog().debug( "Found the correct release: " + release.getVersion() );
496 logRelease( release );
497 }
498 return release;
499 }
500 }
501 return null;
502 }
503
504 private void logRelease( Release release )
505 {
506 Action action;
507 for ( Iterator iterator = release.getActions().iterator(); iterator.hasNext(); )
508 {
509 action = (Action) iterator.next();
510 getLog().debug( "o " + action.getType() );
511 getLog().debug( "issue : " + action.getIssue() );
512 getLog().debug( "action : " + action.getAction() );
513 getLog().debug( "dueTo : " + action.getDueTo() );
514 }
515 }
516
517
518
519
520
521
522
523
524
525 public void processTemplate( Context context, File outputDirectory, String template )
526 throws ResourceNotFoundException, VelocityException, MojoExecutionException
527 {
528 File f;
529
530 try
531 {
532 f = new File( outputDirectory, template );
533
534 if ( !f.getParentFile().exists() )
535 {
536 f.getParentFile().mkdirs();
537 }
538
539 VelocityEngine engine = velocity.getEngine();
540
541 engine.setApplicationAttribute( "baseDirectory", basedir );
542
543 if ( StringUtils.isEmpty( templateEncoding ) )
544 {
545 templateEncoding = ReaderFactory.FILE_ENCODING;
546 getLog().warn(
547 "File encoding has not been set, using platform encoding " + templateEncoding
548 + ", i.e. build is platform dependent!" );
549 }
550
551 Writer writer = new OutputStreamWriter( new FileOutputStream( f ), templateEncoding );
552
553 Template velocityTemplate = engine.getTemplate( templateDirectory + "/" + template, templateEncoding );
554
555 velocityTemplate.merge( context, writer );
556
557 writer.flush();
558
559 writer.close();
560
561 getLog().info( "Created template " + f );
562 }
563
564 catch ( ResourceNotFoundException rnfe )
565 {
566 throw new ResourceNotFoundException( "Template not found. ( " + templateDirectory + "/" + template + " )" );
567 }
568 catch ( VelocityException ve )
569 {
570 throw new VelocityException( ve.toString() );
571 }
572
573 catch ( Exception e )
574 {
575 if ( e.getCause() != null )
576 {
577 getLog().warn( e.getCause() );
578 }
579 throw new MojoExecutionException( e.toString(), e.getCause() );
580 }
581 }
582
583 public void doJiraGenerate()
584 throws MojoExecutionException
585 {
586 List releases = getJiraReleases();
587
588 getLog().info( "Creating announcement file from JIRA releases..." );
589
590 doGenerate( releases );
591 }
592
593 protected List getJiraReleases()
594 throws MojoExecutionException
595 {
596 JiraDownloader jiraDownloader = new JiraDownloader();
597
598 File jiraXMLFile = jiraXML;
599
600 jiraDownloader.setLog( getLog() );
601
602 jiraDownloader.setOutput( jiraXMLFile );
603
604 jiraDownloader.setStatusIds( statusIds );
605
606 jiraDownloader.setResolutionIds( resolutionIds );
607
608 jiraDownloader.setMavenProject( project );
609
610 jiraDownloader.setSettings( settings );
611
612 jiraDownloader.setNbEntries( maxEntries );
613
614 jiraDownloader.setJiraUser( jiraUser );
615
616 jiraDownloader.setJiraPassword( jiraPassword );
617
618 try
619 {
620 jiraDownloader.doExecute();
621
622 if ( jiraXMLFile.exists() )
623 {
624 JiraXML jiraParser = new JiraXML( jiraXMLFile );
625
626 List issues = jiraParser.getIssueList();
627
628 return JiraXML.getReleases( issues );
629 }
630 else
631 {
632 getLog().warn( "jira file " + jiraXMLFile.getPath() + " doesn't exists " );
633 }
634 return Collections.EMPTY_LIST;
635 }
636 catch ( Exception e )
637 {
638 throw new MojoExecutionException( "Failed to extract JIRA issues from the downloaded file", e );
639 }
640 }
641
642 protected List mergeReleases( List changesReleases, List jiraReleases )
643 {
644 if ( changesReleases == null && jiraReleases == null )
645 {
646 return Collections.EMPTY_LIST;
647 }
648 if ( changesReleases == null )
649 {
650 return jiraReleases;
651 }
652 if ( jiraReleases == null )
653 {
654 return changesReleases;
655 }
656
657 for ( Iterator iterator = changesReleases.iterator(); iterator.hasNext(); )
658 {
659 Release release = (Release) iterator.next();
660 Release jiraRelease = getRelease( jiraReleases, release.getVersion() );
661 if ( jiraRelease != null )
662 {
663 if ( jiraRelease.getActions() != null )
664 {
665 release.getActions().addAll( jiraRelease.getActions() );
666 }
667 }
668 }
669 return changesReleases;
670 }
671
672
673
674
675
676 public File getXmlPath()
677 {
678 return xmlPath;
679 }
680
681 public void setXmlPath( File xmlPath )
682 {
683 this.xmlPath = xmlPath;
684 }
685
686 public File getOutputDirectory()
687 {
688 return outputDirectory;
689 }
690
691 public void setOutputDirectory( File outputDirectory )
692 {
693 this.outputDirectory = outputDirectory;
694 }
695
696 public String getGroupId()
697 {
698 return groupId;
699 }
700
701 public void setGroupId( String groupId )
702 {
703 this.groupId = groupId;
704 }
705
706 public String getArtifactId()
707 {
708 return artifactId;
709 }
710
711 public void setArtifactId( String artifactId )
712 {
713 this.artifactId = artifactId;
714 }
715
716 public String getVersion()
717 {
718 return version;
719 }
720
721 public void setVersion( String version )
722 {
723 this.version = version;
724 }
725
726 public String getUrl()
727 {
728 return url;
729 }
730
731 public void setUrl( String url )
732 {
733 this.url = url;
734 }
735
736 public ChangesXML getXml()
737 {
738 return xml;
739 }
740
741 public void setXml( ChangesXML xml )
742 {
743 this.xml = xml;
744 }
745
746 public String getPackaging()
747 {
748 return packaging;
749 }
750
751 public void setPackaging( String packaging )
752 {
753 this.packaging = packaging;
754 }
755
756 public String getDevelopmentTeam()
757 {
758 return developmentTeam;
759 }
760
761 public void setDevelopmentTeam( String developmentTeam )
762 {
763 this.developmentTeam = developmentTeam;
764 }
765
766 public String getIntroduction()
767 {
768 return introduction;
769 }
770
771 public void setIntroduction( String introduction )
772 {
773 this.introduction = introduction;
774 }
775
776 public VelocityComponent getVelocity()
777 {
778 return velocity;
779 }
780
781 public void setVelocity( VelocityComponent velocity )
782 {
783 this.velocity = velocity;
784 }
785
786 public String getFinalName()
787 {
788 return finalName;
789 }
790
791 public void setFinalName( String finalName )
792 {
793 this.finalName = finalName;
794 }
795
796 public String getUrlDownload()
797 {
798 return urlDownload;
799 }
800
801 public void setUrlDownload( String urlDownload )
802 {
803 this.urlDownload = urlDownload;
804 }
805 }