View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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.nio.charset.StandardCharsets;
25  import java.util.List;
26  
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.apache.maven.plugins.annotations.LifecyclePhase;
30  import org.apache.maven.plugins.annotations.Mojo;
31  import org.apache.maven.plugins.annotations.Parameter;
32  import org.apache.rat.ReportConfiguration;
33  import org.apache.rat.Reporter;
34  import org.apache.rat.commandline.Arg;
35  import org.apache.rat.commandline.StyleSheets;
36  import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
37  import org.apache.rat.report.claim.ClaimStatistic;
38  import org.apache.rat.utils.DefaultLog;
39  
40  import static java.lang.String.format;
41  
42  /**
43   * Run Rat to perform a violation check.
44   * <p>
45   *     This documentation mentions data types for some of the arguments. An <a href="data_types.html">explanation of the data types</a> is included
46   *     in this documentation package.
47   * </p>
48   */
49  @Mojo(name = "check", defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true)
50  public class RatCheckMojo extends AbstractRatMojo {
51  
52      /** The default output file if no other is specified.
53       * @deprecated Use &lt;outputFile&gt; instead.
54       */
55      @Deprecated
56      @Parameter(defaultValue = "${project.build.directory}/rat.txt")
57      private File defaultReportFile;
58  
59      /**
60       * Where to store the report.
61       * @deprecated Use 'out' property instead.
62       */
63      @Deprecated
64      @Parameter
65      public void setReportFile(final File reportFile) {
66          if (!reportFile.getParentFile().exists() && !reportFile.getParentFile().mkdirs()) {
67              getLog().error("Unable to create directory " + reportFile.getParentFile());
68          }
69          setOutputFile(reportFile.getAbsolutePath());
70      }
71  
72      /**
73       * Output style of the report. Use "plain" (the default) for a plain text report
74       * or "xml" for the raw XML report. Alternatively you can give the path of an
75       * XSL transformation that will be applied on the raw XML to produce the report
76       * written to the output file.
77       * @deprecated Use setStyleSheet or xml instead.
78       */
79      @Deprecated
80      @Parameter(property = "rat.outputStyle")
81      public void setReportStyle(final String value) {
82          if (value.equalsIgnoreCase("xml")) {
83              setXml(true);
84          } else if (value.equalsIgnoreCase("plain")) {
85              setStylesheet("plain-rat");
86          } else {
87              setStylesheet(value);
88          }
89      }
90  
91      /**
92       * Maximum number of files with unapproved licenses.
93       * @deprecated Use &lt;counterMax&gt;Unapproved:value&lt;/counterMax&gt;.
94       */
95      @Deprecated
96      @Parameter(property = "rat.numUnapprovedLicenses", defaultValue = "0")
97      private int numUnapprovedLicenses;
98  
99      /**
100      * Whether to add license headers; possible values are {@code forced},
101      * {@code true}, and {@code false} (default).
102      * @deprecated Use &lt;editLicense&gt; and &lt;editOverwrite&gt;.
103      */
104     @Deprecated
105     @Parameter(property = "rat.addLicenseHeaders")
106     public void setAddLicenseHeaders(final String addLicenseHeaders) {
107         switch (addLicenseHeaders.trim().toUpperCase()) {
108             case "FALSE":
109                 // do nothing;
110                 break;
111             case "TRUE":
112                 setAddLicense(true);
113                 break;
114             case "FORCED":
115                 setAddLicense(true);
116                 setForce(true);
117                 break;
118             default:
119                 throw new IllegalArgumentException("Unknown addlicense header: " + addLicenseHeaders);
120         }
121     }
122 
123     /**
124      * Copyright message to add to license headers.
125      * @deprecated Deprecated for removal since 0.17: Use &lt;editCopyright&gt; instead.
126      */
127     @Deprecated
128     @Parameter(property = "rat.copyrightMessage")
129     public void setCopyrightMessage(final String copyrightMessage) {
130         setCopyright(copyrightMessage);
131     }
132 
133     /**
134      * Will ignore RAT errors and display a log message if any. Its use is NOT
135      * RECOMMENDED, but quite convenient on occasion.
136      *
137      * @since 0.9
138      */
139     @Parameter(property = "rat.ignoreErrors", defaultValue = "false")
140     private boolean ignoreErrors;
141 
142     /**
143      * Whether to output the names of files that have unapproved licenses to the
144      * console. Defaults to {@code true} to ease builds in containers where you are
145      * unable to access rat.txt easily.
146      *
147      * @since 0.12
148      */
149     @Parameter(property = "rat.consoleOutput", defaultValue = "true")
150     private boolean consoleOutput;
151 
152     /** The reporter that this mojo uses */
153     private Reporter reporter;
154 
155     @Override
156     protected ReportConfiguration getConfiguration() throws MojoExecutionException {
157         ReportConfiguration result = super.getConfiguration();
158         if (numUnapprovedLicenses > 0) {
159             result.getClaimValidator().setMax(ClaimStatistic.Counter.UNAPPROVED, numUnapprovedLicenses);
160         }
161         return result;
162     }
163 
164         /**
165          * Invoked by Maven to execute the Mojo.
166          *
167          * @throws MojoFailureException if an error in the plugin configuration was
168          * detected.
169          * @throws MojoExecutionException if another error occurred while executing the
170          * plugin.
171          */
172     @Override
173     public void execute() throws MojoExecutionException, MojoFailureException {
174         if (skip) {
175             getLog().info("RAT will not execute since it is configured to be skipped via system property 'rat.skip'.");
176             return;
177         }
178 
179         if (getValues(Arg.OUTPUT_FILE).isEmpty()) {
180             setArg(Arg.OUTPUT_FILE.option().getLongOpt(), defaultReportFile.getAbsolutePath());
181         }
182 
183         ReportConfiguration config = getConfiguration();
184 
185         logLicenses(config.getLicenses(LicenseFilter.ALL));
186         try {
187             this.reporter = new Reporter(config);
188             reporter.output();
189             check(config);
190         } catch (MojoFailureException e) {
191             throw e;
192         } catch (Exception e) {
193             throw new MojoExecutionException(e.getMessage(), e);
194         }
195     }
196 
197     protected void check(final ReportConfiguration config) throws MojoFailureException {
198         ClaimStatistic statistics = reporter.getClaimsStatistic();
199         try {
200            reporter.writeSummary(DefaultLog.getInstance().asWriter());
201            if (config.getClaimValidator().hasErrors()) {
202                config.getClaimValidator().logIssues(statistics);
203                if (consoleOutput &&
204                        !config.getClaimValidator().isValid(ClaimStatistic.Counter.UNAPPROVED, statistics.getCounter(ClaimStatistic.Counter.UNAPPROVED))) {
205                    try {
206                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
207                        reporter.output(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet(), () -> baos);
208                        getLog().warn(baos.toString(StandardCharsets.UTF_8.name()));
209                    } catch (Exception e) {
210                        getLog().warn("Unable to print the files with unapproved licenses to the console.");
211                    }
212                }
213 
214                String msg = format("Counter(s) %s exceeded minimum or maximum values. See RAT report in: '%s'.",
215                        String.join(", ", config.getClaimValidator().listIssues(statistics)),
216                        getRatTxtFile());
217 
218                if (!ignoreErrors) {
219                    throw new RatCheckException(msg);
220                } else {
221                    getLog().info(msg);
222                }
223            }
224         } catch (IOException e) {
225            throw new MojoFailureException(e);
226        }
227     }
228 
229     /**
230      * Reads the location of the RAT text file from the Mojo.
231      *
232      * @return Value of the "reportFile" property.
233      * @throws MojoFailureException If no output file was specified.
234      */
235     public File getRatTxtFile() throws MojoFailureException {
236         List<String> args = getValues(Arg.OUTPUT_FILE);
237         if (args != null) {
238             return new File(args.get(0));
239         }
240         throw new MojoFailureException("No output file specified");
241     }
242 }