View Javadoc
1   package org.apache.rat.mp;
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.commons.io.IOUtils;
23  import org.apache.maven.plugin.MojoExecutionException;
24  import org.apache.maven.plugin.MojoFailureException;
25  import org.apache.maven.plugins.annotations.LifecyclePhase;
26  import org.apache.maven.plugins.annotations.Mojo;
27  import org.apache.maven.plugins.annotations.Parameter;
28  import org.apache.rat.Defaults;
29  import org.apache.rat.ReportConfiguration;
30  import org.apache.rat.config.AddLicenseHeaders;
31  import org.apache.rat.config.ReportFormat;
32  import org.apache.rat.report.claim.ClaimStatistic;
33  
34  import java.io.File;
35  import java.io.FileInputStream;
36  import java.io.FileNotFoundException;
37  import java.io.FileOutputStream;
38  import java.io.IOException;
39  import java.io.InputStream;
40  import java.io.OutputStreamWriter;
41  import java.io.Writer;
42  import java.nio.charset.Charset;
43  
44  /**
45   * Run Rat to perform a violation check.
46   */
47  @Mojo(name = "check", defaultPhase = LifecyclePhase.VALIDATE)
48  public class RatCheckMojo extends AbstractRatMojo {
49      /**
50       * Where to store the report.
51       */
52      @Parameter(property = "rat.outputFile", defaultValue = "${project.build.directory}/rat.txt")
53      private File reportFile;
54  
55      /**
56       * Output style of the report. Use "plain" (the default) for a plain text
57       * report or "xml" for the raw XML report. Alternatively you can give the
58       * path of an XSL transformation that will be applied on the raw XML to
59       * produce the report written to the output file.
60       */
61      @Parameter(property = "rat.outputStyle", defaultValue = "plain")
62      private String reportStyle;
63  
64      /**
65       * Maximum number of files with unapproved licenses.
66       */
67      @Parameter(property = "rat.numUnapprovedLicenses", defaultValue = "0")
68      private int numUnapprovedLicenses;
69  
70      /**
71       * Whether to add license headers; possible values are
72       * {@code forced}, {@code true}, and {@code false} (default).
73       */
74      @Parameter(property = "rat.addLicenseHeaders", defaultValue = "false")
75      private String addLicenseHeaders;
76  
77      /**
78       * Copyright message to add to license headers. This option is
79       * ignored, unless {@code addLicenseHeaders} is set to {@code true},
80       * or {@code forced}.
81       */
82      @Parameter(property = "rat.copyrightMessage")
83      private String copyrightMessage;
84  
85      /**
86       * Will ignore rat errors and display a log message if any.
87       * Its use is NOT RECOMMENDED, but quite convenient on occasion.
88       *
89       * @since 0.9
90       */
91      @Parameter(property = "rat.ignoreErrors", defaultValue = "false")
92      private boolean ignoreErrors;
93  
94      /**
95       * Whether to output the names of files that have unapproved licenses to the
96       * console.
97       *
98       * @since 0.12
99       */
100     @Parameter(property = "rat.consoleOutput", defaultValue = "false")
101     private boolean consoleOutput;
102 
103     private ClaimStatistic getRawReport()
104             throws MojoExecutionException, MojoFailureException {
105         Writer fw = null;
106         try {
107             fw = new OutputStreamWriter(
108                    new FileOutputStream(reportFile),
109                    Charset.forName("UTF-8"));
110             final ClaimStatistic statistic = createReport(fw, getStyleSheet());
111             fw.close();
112             fw = null;
113             return statistic;
114         } catch (IOException e) {
115             throw new MojoExecutionException(e.getMessage(), e);
116         } finally {
117             IOUtils.closeQuietly(fw);
118         }
119     }
120 
121     /**
122      * Returns the XSL stylesheet to be used for formatting the report.
123      *
124      * @return report stylesheet, or <code>null</code> for raw XML
125      * @throws MojoExecutionException if the stylesheet can not be found
126      * @see #reportStyle
127      */
128     private InputStream getStyleSheet() throws MojoExecutionException {
129         if (reportStyle == null || ReportFormat.PLAIN.is(reportStyle)) {
130             return Defaults.getPlainStyleSheet();
131         } else if (ReportFormat.XML.is(reportStyle)) {
132             return null;
133         } else {
134             try {
135                 return new FileInputStream(reportStyle);
136             } catch (FileNotFoundException e) {
137                 throw new MojoExecutionException(
138                         "Unable to find report stylesheet: " + reportStyle, e);
139             }
140         }
141     }
142 
143     /**
144      * Invoked by Maven to execute the Mojo.
145      *
146      * @throws MojoFailureException   An error in the plugin configuration was detected.
147      * @throws MojoExecutionException Another error occurred while executing the plugin.
148      */
149     public void execute() throws MojoExecutionException, MojoFailureException {
150         if (skip) {
151             getLog().info("RAT will not execute since it is configured to be skipped via system property 'rat.skip'.");
152             return;
153         }
154 
155         final File parent = reportFile.getParentFile();
156         if (!parent.mkdirs() && !parent.isDirectory()) {
157             throw new MojoExecutionException("Could not create report parent directory " + parent);
158         }
159 
160         final ClaimStatistic report = getRawReport();
161         check(report);
162     }
163 
164     protected void check(ClaimStatistic statistics)
165             throws MojoFailureException {
166         if (numUnapprovedLicenses > 0) {
167             getLog().info("You requested to accept " + numUnapprovedLicenses + " files with unapproved licenses.");
168         }
169 
170         int numApproved = statistics.getNumApproved();
171         getLog().info("Rat check: Summary over all files. Unapproved: " + statistics.getNumUnApproved() + //
172                 ", unknown: " + statistics.getNumUnknown() + //
173                 ", generated: " + statistics.getNumGenerated() + //
174                 ", approved: " + numApproved + //
175                 (numApproved > 0 ? " licenses." : " license."));
176 
177         if (numUnapprovedLicenses < statistics.getNumUnApproved()) {
178             if (consoleOutput) {
179                 try {
180                     getLog().warn(createReport(Defaults.getUnapprovedLicensesStyleSheet()).trim());
181                 } catch (MojoExecutionException e) {
182                     getLog().warn("Unable to print the files with unapproved licenses to the console.");
183                 }
184             }
185 
186             final String seeReport = " See RAT report in: " + reportFile;
187             if (!ignoreErrors) {
188                 throw new RatCheckException("Too many files with unapproved license: " + statistics.getNumUnApproved() + seeReport);
189             } else {
190                 getLog().warn("Rat check: " + statistics.getNumUnApproved() + " files with unapproved licenses." + seeReport);
191             }
192         }
193     }
194 
195     @Override
196     protected ReportConfiguration getConfiguration()
197             throws MojoFailureException, MojoExecutionException {
198         final ReportConfiguration configuration = super.getConfiguration();
199 
200         if (AddLicenseHeaders.FORCED.name().equalsIgnoreCase(addLicenseHeaders)) {
201             configuration.setAddingLicenses(true);
202             configuration.setAddingLicensesForced(true);
203             configuration.setCopyrightMessage(copyrightMessage);
204         } else if (AddLicenseHeaders.TRUE.name().equalsIgnoreCase(addLicenseHeaders)) {
205             configuration.setAddingLicenses(true);
206             configuration.setCopyrightMessage(copyrightMessage);
207         } else if (AddLicenseHeaders.FALSE.name().equalsIgnoreCase(addLicenseHeaders)) {
208             // Nothing to do
209         } else {
210             throw new MojoFailureException("Invalid value for addLicenseHeaders: Expected " + AddLicenseHeaders.getValuesForHelp() + ", got "
211                     + addLicenseHeaders);
212         }
213         return configuration;
214     }
215 }