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