1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.mp;
20
21 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.OutputStreamWriter;
27 import java.io.Writer;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Files;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.Map;
34 import java.util.ResourceBundle;
35
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.artifact.repository.ArtifactRepository;
38 import org.apache.maven.doxia.sink.Sink;
39 import org.apache.maven.doxia.sink.SinkFactory;
40 import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
41 import org.apache.maven.doxia.site.decoration.DecorationModel;
42 import org.apache.maven.doxia.siterenderer.Renderer;
43 import org.apache.maven.doxia.siterenderer.RendererException;
44 import org.apache.maven.doxia.siterenderer.RenderingContext;
45 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
46 import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
47 import org.apache.maven.doxia.tools.SiteTool;
48 import org.apache.maven.doxia.tools.SiteToolException;
49 import org.apache.maven.execution.MavenSession;
50 import org.apache.maven.plugin.MojoExecutionException;
51 import org.apache.maven.plugins.annotations.Component;
52 import org.apache.maven.plugins.annotations.Mojo;
53 import org.apache.maven.plugins.annotations.Parameter;
54 import org.apache.maven.plugins.annotations.ResolutionScope;
55 import org.apache.maven.reporting.MavenMultiPageReport;
56 import org.apache.maven.reporting.MavenReportException;
57 import org.apache.rat.ReportConfiguration;
58 import org.apache.rat.Reporter;
59 import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
60 import org.codehaus.plexus.util.ReaderFactory;
61
62
63
64
65 @Mojo(name = "rat", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
66 public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageReport {
67
68
69
70
71
72
73
74 @Parameter(defaultValue = "${project.reporting.outputDirectory}", readonly = true, required = true)
75 protected File outputDirectory;
76
77
78
79
80 @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}", readonly = true)
81 private String inputEncoding;
82
83
84
85
86 @Parameter(property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}", readonly = true)
87 private String outputEncoding;
88
89
90
91
92 @Parameter(defaultValue = "${session}", readonly = true, required = true)
93 protected MavenSession session;
94
95
96
97
98 @Parameter(defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true)
99 protected List<ArtifactRepository> remoteRepositories;
100
101
102
103
104 @Component
105 protected SiteTool siteTool;
106
107
108
109
110 @Component
111 protected Renderer siteRenderer;
112
113
114
115
116 private Sink sink;
117
118
119
120
121 private SinkFactory sinkFactory;
122
123
124
125
126 private File reportOutputDirectory;
127
128
129
130
131
132
133
134
135 @Override
136 public void execute() throws MojoExecutionException {
137 if (!canGenerateReport()) {
138 return;
139 }
140
141 File outputDirectory = new File(getOutputDirectory());
142
143 String filename = getOutputName() + ".html";
144
145 Locale locale = Locale.getDefault();
146
147 try {
148 SiteRenderingContext siteContext = createSiteRenderingContext(locale);
149
150
151 getSiteRenderer().copyResources(siteContext, outputDirectory);
152
153
154 RenderingContext docRenderingContext = new RenderingContext(outputDirectory, filename, null);
155
156 SiteRendererSink sink = new SiteRendererSink(docRenderingContext);
157
158 generate(sink, null, locale);
159
160
161 if (!isExternalReport()) {
162 outputDirectory.mkdirs();
163
164 try (Writer writer = new OutputStreamWriter(
165 Files.newOutputStream(new File(outputDirectory, filename).toPath()), getOutputEncoding())) {
166
167 getSiteRenderer().mergeDocumentIntoSite(writer, sink, siteContext);
168 }
169 }
170
171
172 getSiteRenderer().copyResources(siteContext, outputDirectory);
173 } catch (RendererException | IOException | MavenReportException e) {
174 throw new MojoExecutionException(
175 "An error has occurred in " + getName(Locale.ENGLISH) + " report generation.", e);
176 }
177 }
178
179 private SiteRenderingContext createSiteRenderingContext(Locale locale) throws MavenReportException, IOException {
180 DecorationModel decorationModel = new DecorationModel();
181
182 Map<String, Object> templateProperties = new HashMap<>();
183
184 templateProperties.put("standalone", Boolean.TRUE);
185 templateProperties.put("project", getProject());
186 templateProperties.put("inputEncoding", getInputEncoding());
187 templateProperties.put("outputEncoding", getOutputEncoding());
188
189 for (Map.Entry<Object, Object> entry : getProject().getProperties().entrySet()) {
190 templateProperties.put((String) entry.getKey(), entry.getValue());
191 }
192
193 SiteRenderingContext context;
194 try {
195 Artifact skinArtifact = siteTool.getSkinArtifactFromRepository(session.getLocalRepository(),
196 remoteRepositories, decorationModel);
197
198 getLog().debug(
199 buffer().a("Rendering content with ").strong(skinArtifact.getId() + " skin").a('.').build());
200
201 context = siteRenderer.createContextForSkin(skinArtifact, templateProperties, decorationModel,
202 project.getName(), locale);
203 } catch (SiteToolException e) {
204 throw new MavenReportException("Failed to retrieve skin artifact", e);
205 } catch (RendererException e) {
206 throw new MavenReportException("Failed to create context for skin", e);
207 }
208
209
210 context.setRootDirectory(project.getBasedir());
211
212 return context;
213 }
214
215
216
217
218
219
220
221
222
223 @Deprecated
224 @Override
225 public void generate(org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
226 generate(sink, null, locale);
227 }
228
229
230
231
232
233
234
235
236
237 @Deprecated
238 public void generate(Sink sink, Locale locale) throws MavenReportException {
239 generate(sink, null, locale);
240 }
241
242
243
244
245
246
247
248
249
250
251 @Override
252 public void generate(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException {
253 if (!canGenerateReport()) {
254 getLog().info("This report cannot be generated as part of the current build. "
255 + "The report name should be referenced in this line of output.");
256 return;
257 }
258
259 this.sink = sink;
260
261 this.sinkFactory = sinkFactory;
262
263 executeReport(locale);
264
265 closeReport();
266 }
267
268
269
270
271 @Override
272 public String getCategoryName() {
273 return CATEGORY_PROJECT_REPORTS;
274 }
275
276 @Override
277 public File getReportOutputDirectory() {
278 if (reportOutputDirectory == null) {
279 reportOutputDirectory = new File(getOutputDirectory());
280 }
281
282 return reportOutputDirectory;
283 }
284
285 @Override
286 public void setReportOutputDirectory(File reportOutputDirectory) {
287 this.reportOutputDirectory = reportOutputDirectory;
288 this.outputDirectory = reportOutputDirectory;
289 }
290
291 protected String getOutputDirectory() {
292 return outputDirectory.getAbsolutePath();
293 }
294
295 protected Renderer getSiteRenderer() {
296 return siteRenderer;
297 }
298
299
300
301
302
303
304 protected String getInputEncoding() {
305 return (inputEncoding == null) ? ReaderFactory.FILE_ENCODING : inputEncoding;
306 }
307
308
309
310
311
312
313
314 protected String getOutputEncoding() {
315 return (outputEncoding == null) ? StandardCharsets.UTF_8.toString() : outputEncoding;
316 }
317
318
319
320
321 protected void closeReport() {
322 getSink().close();
323 }
324
325
326
327
328 public Sink getSink() {
329 return sink;
330 }
331
332
333
334
335 public SinkFactory getSinkFactory() {
336 return sinkFactory;
337 }
338
339
340
341
342
343 @Override
344 public boolean isExternalReport() {
345 return false;
346 }
347
348 @Override
349 public boolean canGenerateReport() {
350 return !skip;
351 }
352
353
354
355
356
357
358
359
360 private String getRatVersion() {
361
362 for (Artifact a : getProject().getDependencyArtifacts()) {
363 if ("rat-lib".equals(a.getArtifactId())) {
364 return a.getVersion();
365 }
366 }
367 return null;
368 }
369
370
371
372
373
374
375
376 protected void executeReport(Locale locale) throws MavenReportException {
377 ResourceBundle bundle = getBundle(locale);
378 final String title = bundle.getString("report.rat.title");
379 sink.head();
380 sink.title();
381 sink.text(title);
382 sink.title_();
383 sink.head_();
384
385 sink.body();
386
387 sink.section1();
388 sink.sectionTitle1();
389 sink.text(title);
390 sink.sectionTitle1_();
391
392 sink.paragraph();
393 sink.text(bundle.getString("report.rat.link") + " ");
394 sink.link(bundle.getString("report.rat.url"));
395 sink.text(bundle.getString("report.rat.fullName"));
396 sink.link_();
397 final String ratVersion = getRatVersion();
398 if (ratVersion != null) {
399 sink.text(" " + ratVersion);
400 }
401 sink.text(".");
402 sink.paragraph_();
403
404 sink.paragraph();
405 sink.verbatim(SinkEventAttributeSet.BOXED);
406 try {
407 ReportConfiguration config = getConfiguration();
408 config.setFrom(getDefaultsBuilder().build());
409
410 logLicenses(config.getLicenses(LicenseFilter.all));
411 ByteArrayOutputStream baos = new ByteArrayOutputStream();
412 config.setOut(()->baos);
413 Reporter.report(config);
414 sink.text(baos.toString());
415 } catch (Exception e) {
416 throw new MavenReportException(e.getMessage(), e);
417 }
418 sink.verbatim_();
419 sink.paragraph_();
420 sink.section1_();
421 sink.body_();
422 }
423
424
425
426
427
428
429
430 private ResourceBundle getBundle(Locale locale) {
431 return ResourceBundle.getBundle("org/apache/rat/mp/rat-report", locale, getClass().getClassLoader());
432 }
433
434
435
436
437
438
439
440
441 @Override
442 public String getDescription(Locale locale) {
443 return getBundle(locale).getString("report.rat.description");
444 }
445
446
447
448
449
450
451
452 @Override
453 public String getName(Locale locale) {
454 return getBundle(locale).getString("report.rat.name");
455 }
456
457
458
459
460
461
462 @Override
463 public String getOutputName() {
464 return "rat-report";
465 }
466 }