1 package org.apache.maven.plugin.changes;
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.IOException;
24 import java.net.URL;
25 import java.text.SimpleDateFormat;
26 import java.util.Collections;
27 import java.util.Date;
28 import java.util.Iterator;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Properties;
32 import java.util.ResourceBundle;
33
34 import org.apache.commons.collections.map.CaseInsensitiveMap;
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.reporting.MavenReportException;
37 import org.apache.maven.shared.filtering.MavenFileFilter;
38 import org.apache.maven.shared.filtering.MavenFileFilterRequest;
39 import org.apache.maven.shared.filtering.MavenFilteringException;
40 import org.codehaus.plexus.util.FileUtils;
41 import org.codehaus.plexus.util.IOUtil;
42 import org.codehaus.plexus.util.ReaderFactory;
43 import org.codehaus.plexus.util.StringUtils;
44 import org.codehaus.plexus.util.xml.XmlStreamReader;
45
46
47
48
49
50
51
52
53
54 public class ChangesMojo
55 extends AbstractChangesReport
56 {
57
58
59
60
61
62
63
64 private boolean addActionDate;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 private boolean escapeHTML;
85
86
87
88
89
90
91
92
93
94 private File filteredOutputDirectory;
95
96
97
98
99
100
101
102 private boolean filteringChanges;
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 private String issueLinkTemplate;
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 private Map issueLinkTemplatePerSystem;
143
144
145
146
147
148 private MavenFileFilter mavenFileFilter;
149
150
151
152
153
154
155
156
157 private String publishDateFormat;
158
159
160
161
162
163
164
165
166 private String publishDateLocale;
167
168
169
170
171
172
173
174 protected MavenSession session;
175
176
177
178
179
180
181 private String system;
182
183
184
185
186
187
188
189
190 private String teamlist;
191
192
193
194
195
196 private String url;
197
198
199
200
201
202
203 private File xmlPath;
204
205 private CaseInsensitiveMap caseInsensitiveIssueLinkTemplatePerSystem;
206
207
208
209
210
211 public boolean canGenerateReport()
212 {
213 return xmlPath.isFile();
214 }
215
216 public void executeReport( Locale locale )
217 throws MavenReportException
218 {
219
220 if ( !xmlPath.exists() )
221 {
222 getLog().warn( "changes.xml file " + xmlPath.getAbsolutePath() + " does not exist." );
223 return;
224 }
225 if ( filteringChanges )
226 {
227 if ( !filteredOutputDirectory.exists() )
228 {
229 filteredOutputDirectory.mkdirs();
230 }
231 XmlStreamReader xmlStreamReader = null;
232 try
233 {
234
235 xmlStreamReader = ReaderFactory.newXmlReader( xmlPath );
236 String encoding = xmlStreamReader.getEncoding();
237 File resultFile = new File( filteredOutputDirectory, "changes.xml" );
238 Date now = new Date();
239 SimpleDateFormat simpleDateFormat =
240 new SimpleDateFormat( publishDateFormat, new Locale( publishDateLocale ) );
241 Properties additionalProperties = new Properties();
242 additionalProperties.put( "publishDate", simpleDateFormat.format( now ) );
243 MavenFileFilterRequest mavenFileFilterRequest =
244 new MavenFileFilterRequest( xmlPath, resultFile, true, project, Collections.EMPTY_LIST, false,
245 encoding, session, additionalProperties );
246 mavenFileFilter.copyFile( mavenFileFilterRequest );
247 xmlPath = resultFile;
248 }
249 catch ( IOException e )
250 {
251 throw new MavenReportException( "Exception during filtering changes file : " + e.getMessage(), e );
252 }
253 catch ( MavenFilteringException e )
254 {
255 throw new MavenReportException( "Exception during filtering changes file : " + e.getMessage(), e );
256 }
257 finally
258 {
259 if ( xmlStreamReader != null )
260 {
261 IOUtil.close( xmlStreamReader );
262 }
263 }
264
265 }
266
267 ChangesXML changesXml = new ChangesXML( xmlPath, getLog() );
268 ChangesReportGenerator report = new ChangesReportGenerator( changesXml.getReleaseList() );
269
270 report.setAuthor( changesXml.getAuthor() );
271 report.setTitle( changesXml.getTitle() );
272
273 report.setEscapeHTML ( escapeHTML );
274
275
276
277 if ( issueLinkTemplatePerSystem == null )
278 {
279 caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap();
280 }
281 else
282 {
283 caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap( issueLinkTemplatePerSystem );
284 }
285
286
287
288 addIssueLinkTemplate( ChangesReportGenerator.DEFAULT_ISSUE_SYSTEM_KEY, issueLinkTemplate );
289 addIssueLinkTemplate( "Bitbucket", "%URL%/issue/%ISSUE%" );
290 addIssueLinkTemplate( "Bugzilla", "%URL%/show_bug.cgi?id=%ISSUE%" );
291 addIssueLinkTemplate( "GitHub", "%URL%/%ISSUE%" );
292 addIssueLinkTemplate( "GoogleCode", "%URL%/detail?id=%ISSUE%" );
293 addIssueLinkTemplate( "JIRA", "%URL%/%ISSUE%" );
294 addIssueLinkTemplate( "Mantis", "%URL%/view.php?id=%ISSUE%" );
295 addIssueLinkTemplate( "MKS", "%URL%/viewissue?selection=%ISSUE%" );
296 addIssueLinkTemplate( "Redmine", "%URL%/issues/show/%ISSUE%" );
297 addIssueLinkTemplate( "Scarab", "%URL%/issues/id/%ISSUE%" );
298 addIssueLinkTemplate( "SourceForge", "http://sourceforge.net/support/tracker.php?aid=%ISSUE%" );
299 addIssueLinkTemplate( "Trac", "%URL%/ticket/%ISSUE%" );
300 addIssueLinkTemplate( "Trackplus", "%URL%/printItem.action?key=%ISSUE%" );
301 addIssueLinkTemplate( "YouTrack", "%URL%/issue/%ISSUE%" );
302
303
304
305
306 logIssueLinkTemplatePerSystem( caseInsensitiveIssueLinkTemplatePerSystem );
307
308 report.setIssueLinksPerSystem( caseInsensitiveIssueLinkTemplatePerSystem );
309
310 report.setSystem( system );
311
312 report.setTeamlist ( teamlist );
313
314 report.setUrl( url );
315
316 report.setAddActionDate( addActionDate );
317
318 if ( StringUtils.isEmpty( url ) )
319 {
320 getLog().warn( "No issue management URL defined in POM. Links to your issues will not work correctly." );
321 }
322
323 report.doGenerateReport( getBundle( locale ), getSink() );
324
325
326 copyStaticResources();
327 }
328
329 public String getDescription( Locale locale )
330 {
331 return getBundle( locale ).getString( "report.issues.description" );
332 }
333
334 public String getName( Locale locale )
335 {
336 return getBundle( locale ).getString( "report.issues.name" );
337 }
338
339 public String getOutputName()
340 {
341 return "changes-report";
342 }
343
344
345
346
347
348
349
350
351
352
353
354
355
356 private void addIssueLinkTemplate( String system, String issueLinkTemplate )
357 {
358 if ( caseInsensitiveIssueLinkTemplatePerSystem == null )
359 {
360 caseInsensitiveIssueLinkTemplatePerSystem = new CaseInsensitiveMap();
361 }
362 if ( !caseInsensitiveIssueLinkTemplatePerSystem.containsKey( system ) )
363 {
364 caseInsensitiveIssueLinkTemplatePerSystem.put( system, issueLinkTemplate );
365 }
366 }
367
368 private void copyStaticResources()
369 throws MavenReportException
370 {
371 final String pluginResourcesBase = "org/apache/maven/plugin/changes";
372 String resourceNames[] = {
373 "images/add.gif",
374 "images/fix.gif",
375 "images/icon_help_sml.gif",
376 "images/remove.gif",
377 "images/rss.png",
378 "images/update.gif" };
379 try
380 {
381 getLog().debug( "Copying static resources." );
382 for ( int i = 0; i < resourceNames.length; i++ )
383 {
384 URL url = this.getClass().getClassLoader().getResource( pluginResourcesBase + "/" + resourceNames[i] );
385 FileUtils.copyURLToFile( url, new File( getReportOutputDirectory(), resourceNames[i] ) );
386 }
387 }
388 catch ( IOException e )
389 {
390 throw new MavenReportException( "Unable to copy static resources." );
391 }
392 }
393
394 private ResourceBundle getBundle( Locale locale )
395 {
396 return ResourceBundle.getBundle( "changes-report", locale, this.getClass().getClassLoader() );
397 }
398
399 protected String getTeamlist()
400 {
401 return teamlist;
402 }
403
404 private void logIssueLinkTemplatePerSystem( Map issueLinkTemplatePerSystem )
405 {
406 if ( getLog().isDebugEnabled() )
407 {
408 if ( issueLinkTemplatePerSystem == null )
409 {
410 getLog().debug( "No issueLinkTemplatePerSystem configuration was found" );
411 }
412 else
413 {
414 Iterator iterator = issueLinkTemplatePerSystem.entrySet().iterator();
415 while ( iterator.hasNext() )
416 {
417 Map.Entry entry = (Map.Entry) iterator.next();
418 getLog().debug( "issueLinkTemplatePerSystem[" + entry.getKey() + "] = " + entry.getValue() );
419 }
420 }
421 }
422 }
423 }