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.anttasks;
20  
21  import java.io.File;
22  import java.io.FilenameFilter;
23  import java.io.PrintWriter;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.List;
29  import java.util.stream.Collectors;
30  
31  import org.apache.rat.ConfigurationException;
32  import org.apache.rat.Defaults;
33  import org.apache.rat.ReportConfiguration;
34  import org.apache.rat.Reporter;
35  import org.apache.rat.configuration.Format;
36  import org.apache.rat.configuration.LicenseReader;
37  import org.apache.rat.configuration.MatcherReader;
38  import org.apache.rat.license.LicenseSetFactory;
39  import org.apache.rat.utils.Log;
40  import org.apache.tools.ant.BuildException;
41  import org.apache.tools.ant.Project;
42  import org.apache.tools.ant.Task;
43  import org.apache.tools.ant.taskdefs.LogOutputStream;
44  import org.apache.tools.ant.types.EnumeratedAttribute;
45  import org.apache.tools.ant.types.Resource;
46  import org.apache.tools.ant.types.ResourceCollection;
47  import org.apache.tools.ant.types.resources.Union;
48  
49  /**
50   * A basic Ant task that generates a report on all files specified by the nested
51   * resource collection(s).
52   *
53   * <p>
54   * IHeaderMatcher(s) can be specified as nested elements as well.
55   * </p>
56   *
57   * <p>
58   * The attribute <code>format</code> defines the output format and can take the
59   * values
60   * <ul>
61   * <li>xml - Rat's native XML output.</li>
62   * <li>styled - transforms the XML output using the given stylesheet. The
63   * stylesheet attribute must be set as well if this attribute is used.</li>
64   * <li>plain - plain text using Rat's built-in stylesheet. This is the
65   * default.</li>
66   * </ul>
67   */
68  public class Report extends Task {
69  
70      private final Defaults.Builder defaultsBuilder;
71      private final ReportConfiguration configuration;
72      private final List<License> licenses = new ArrayList<>();
73      private final List<Family> families = new ArrayList<>();
74      /**
75       * will hold any nested resource collection
76       */
77      private Union nestedResources;
78  
79      public Report() {
80          configuration = new ReportConfiguration(new Logger());
81          configuration.setOut(() -> new LogOutputStream(this, Project.MSG_INFO));
82          defaultsBuilder = Defaults.builder();
83      }
84  
85      /**
86       * Adds resources that will be checked.
87       * 
88       * @param rc resource to check.
89       */
90      public void add(ResourceCollection rc) {
91          if (nestedResources == null) {
92              nestedResources = new Union();
93          }
94          nestedResources.add(rc);
95      }
96  
97      public void setInputFileFilter(FilenameFilter inputFileFilter) {
98          configuration.setInputFileFilter(inputFileFilter);
99      }
100 
101     public void setReportFile(File reportFile) {
102         configuration.setOut(reportFile);
103     }
104 
105     public void addLicense(License lic) {
106         licenses.add(lic);
107     }
108 
109     public void addFamily(Family family) {
110         families.add(family);
111     }
112 
113     /**
114      * 
115      * @param styleSheet
116      * @deprecated use {@link #addStyleSheet(Resource)}
117      */
118     @Deprecated
119     public void addStylesheet(Resource styleSheet) {
120         addStyleSheet(styleSheet);
121     }
122 
123     /**
124      * Adds a given style sheet to the report.
125      * @param styleSheet style sheet to use in this report.
126      */
127     public void addStyleSheet(Resource styleSheet) {
128         configuration.setStyleSheet(styleSheet::getInputStream);
129         configuration.setStyleReport(true);
130     }
131 
132     public void setStyleReport(boolean styleReport) {
133         configuration.setStyleReport(styleReport);
134     }
135 
136     /**
137      * 
138      * @param style
139      * @deprecated use #setStyleReport
140      */
141     @Deprecated
142     public void setFormat(String style) {
143         setStyleReport("styled".equalsIgnoreCase(style));
144 
145     }
146 
147     public void setLicenses(File fileName) {
148         try {
149             URL url = fileName.toURI().toURL();
150             Format fmt = Format.fromFile(fileName);
151             MatcherReader mReader = fmt.matcherReader();
152             if (mReader != null) {
153                 mReader.addMatchers(url);
154             }
155             LicenseReader lReader = fmt.licenseReader();
156             if (lReader != null) {
157                 lReader.addLicenses(url);
158                 configuration.addLicenses(lReader.readLicenses());
159                 configuration.addApprovedLicenseCategories(lReader.approvedLicenseId());
160             }
161         } catch (MalformedURLException e) {
162             throw new BuildException("Can not read license file " + fileName, e);
163         }
164     }
165 
166     /**
167      * @param useDefaultLicenses Whether to add the default list of license
168      * matchers.
169      */
170     public void setUseDefaultLicenses(boolean useDefaultLicenses) {
171         if (!useDefaultLicenses) {
172             defaultsBuilder.noDefault();
173         }
174     }
175 
176     public void setAddApprovedLicense(String familyCategory) {
177         configuration.addApprovedLicenseCategory(familyCategory);
178     }
179 
180     public void addAddApprovedLicense(String familyCategory) {
181         configuration.addApprovedLicenseCategory(familyCategory);
182     }
183 
184     public void setRemoveApprovedLicense(String familyCategory) {
185         configuration.removeApprovedLicenseCategory(familyCategory);
186     }
187 
188     public void setRemoveApprovedLicense(String[] familyCategory) {
189         configuration.removeApprovedLicenseCategories(Arrays.asList(familyCategory));
190     }
191 
192     public void setCopyrightMessage(String copyrightMessage) {
193         configuration.setCopyrightMessage(copyrightMessage);
194     }
195 
196     public void setAddLicenseHeaders(AddLicenseHeaders setting) {
197         configuration.setAddLicenseHeaders(setting.getNative());
198     }
199 
200     public void setAddDefaultDefinitions(File fileName) {
201         try {
202             defaultsBuilder.add(fileName);
203         } catch (MalformedURLException e) {
204             throw new BuildException("Can not open additional default definitions: " + fileName.toString(), e);
205         }
206     }
207 
208     public ReportConfiguration getConfiguration() {
209         Defaults defaults = defaultsBuilder.build();
210 
211         configuration.setFrom(defaults);
212         configuration.setReportable(new ResourceCollectionContainer(nestedResources));
213         families.stream().map(Family::build).forEach(configuration::addFamily);
214         licenses.stream().map(License::asBuilder)
215                 .forEach(l -> configuration.addApprovedLicenseCategory(configuration.addLicense(l).getLicenseFamily()));
216         return configuration;
217     }
218 
219     /**
220      * Generates the report.
221      */
222     @Override
223     public void execute() {
224         try {
225             Reporter.report(validate(getConfiguration()));
226         } catch (BuildException e) {
227             throw e;
228         } catch (Exception ioex) {
229             throw new BuildException(ioex);
230         }
231     }
232 
233     /**
234      * validates the task's configuration.
235      */
236     private ReportConfiguration validate(ReportConfiguration cfg) {
237         try {
238             cfg.validate(s -> log(s, Project.MSG_WARN));
239         } catch (ConfigurationException e) {
240             throw new BuildException(e.getMessage(), e.getCause());
241         }
242         if (nestedResources == null) {
243             throw new BuildException("You must specify at least one file to create the report for.");
244         }
245         return cfg;
246     }
247 
248     /**
249      * Type for the addLicenseHeaders attribute.
250      */
251     public static class AddLicenseHeaders extends EnumeratedAttribute {
252         static final String TRUE = "true";
253         static final String FALSE = "false";
254         static final String FORCED = "forced";
255 
256         public AddLicenseHeaders() {
257         }
258 
259         public AddLicenseHeaders(String s) {
260             setValue(s);
261         }
262 
263         @Override
264         public String[] getValues() {
265             return new String[] { TRUE, FALSE, FORCED };
266         }
267 
268         public org.apache.rat.config.AddLicenseHeaders getNative() {
269             return org.apache.rat.config.AddLicenseHeaders.valueOf(getValue().toUpperCase());
270         }
271     }
272 
273     /**
274      * Type for the addLicenseHeaders attribute.
275      */
276     public static class ApprovalFilter extends EnumeratedAttribute {
277 
278         public ApprovalFilter() {
279         }
280 
281         public ApprovalFilter(String s) {
282             setValue(s);
283         }
284 
285         @Override
286         public String[] getValues() {
287             return Arrays.stream(LicenseSetFactory.LicenseFilter.values()).map(LicenseSetFactory.LicenseFilter::name)
288                     .collect(Collectors.toList()).toArray(new String[LicenseSetFactory.LicenseFilter.values().length]);
289         }
290 
291         public LicenseSetFactory.LicenseFilter internalFilter() {
292             return LicenseSetFactory.LicenseFilter.valueOf(getValue());
293         }
294     }
295     
296     private class Logger implements Log {
297 
298         private void write(int level, String msg) {
299             try (PrintWriter pw = new PrintWriter(new LogOutputStream(Report.this, level)))
300             {
301                pw.write(msg);
302             }
303         }
304 
305         @Override
306         public void log(Level level, String msg) {
307             switch (level) {
308             case DEBUG:
309                 write(Project.MSG_DEBUG, msg);
310                 break;
311             case INFO:
312                 write(Project.MSG_INFO, msg);
313                 break;
314             case WARN:
315                 write(Project.MSG_WARN, msg);
316                 break;
317             case ERROR:
318                 write(Project.MSG_ERR, msg);
319                 break;
320 			case OFF:
321 				break;
322 			default:
323 				break;
324             }
325         }
326         
327     }
328 }