1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat;
20
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FilenameFilter;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStreamWriter;
28 import java.io.PipedReader;
29 import java.io.PipedWriter;
30 import java.io.PrintStream;
31 import java.io.Writer;
32
33 import javax.xml.transform.TransformerConfigurationException;
34
35 import org.apache.commons.cli.CommandLine;
36 import org.apache.commons.cli.HelpFormatter;
37 import org.apache.commons.cli.Option;
38 import org.apache.commons.cli.OptionBuilder;
39 import org.apache.commons.cli.OptionGroup;
40 import org.apache.commons.cli.Options;
41 import org.apache.commons.cli.ParseException;
42 import org.apache.commons.cli.PosixParser;
43 import org.apache.commons.io.filefilter.NotFileFilter;
44 import org.apache.commons.io.filefilter.WildcardFileFilter;
45 import org.apache.rat.api.RatException;
46 import org.apache.rat.report.IReportable;
47 import org.apache.rat.report.RatReport;
48 import org.apache.rat.report.claim.ClaimStatistic;
49 import org.apache.rat.report.xml.XmlReportFactory;
50 import org.apache.rat.report.xml.writer.IXmlWriter;
51 import org.apache.rat.report.xml.writer.impl.base.XmlWriter;
52 import org.apache.rat.walker.ArchiveWalker;
53 import org.apache.rat.walker.DirectoryWalker;
54
55
56 public class Report {
57 private static final char EXCLUDE_CLI = 'e';
58 private static final char STYLESHEET_CLI = 's';
59
60
61 public static final void main(String args[]) throws Exception {
62 final ReportConfiguration configuration = new ReportConfiguration();
63 Options opts = buildOptions();
64
65 PosixParser parser = new PosixParser();
66 CommandLine cl = null;
67 try {
68 cl = parser.parse(opts, args);
69 } catch (ParseException e) {
70 System.err.println("Please use the \"--help\" option to see a list of valid commands and options");
71 System.exit(1);
72 }
73
74 if (cl.hasOption('h')) {
75 printUsage(opts);
76 }
77
78 args = cl.getArgs();
79 if (args == null || args.length != 1) {
80 printUsage(opts);
81 } else {
82 Report report = new Report(args[0]);
83
84 if (cl.hasOption('a')) {
85 configuration.setAddingLicenses(true);
86 configuration.setAddingLicensesForced(cl.hasOption('f'));
87 configuration.setCopyrightMessage(cl.getOptionValue("c"));
88 }
89
90 if (cl.hasOption(EXCLUDE_CLI)) {
91 String[] excludes = cl.getOptionValues(EXCLUDE_CLI);
92 if (excludes != null) {
93 final FilenameFilter filter = new NotFileFilter(new WildcardFileFilter(excludes));
94 report.setInputFileFilter(filter);
95 }
96 }
97
98 if (cl.hasOption('x')) {
99 report.report(System.out);
100 } else {
101 if (!cl.hasOption(STYLESHEET_CLI)) {
102 report.styleReport(System.out);
103 } else {
104 String[] style = cl.getOptionValues(STYLESHEET_CLI);
105 if (style.length != 1) {
106 System.err.println("please specify a single stylesheet");
107 System.exit(1);
108 }
109 try {
110 configuration.setHeaderMatcher(Defaults.createDefaultMatcher());
111 report(System.out,
112 report.getDirectory(System.out),
113 new FileInputStream(style[0]),
114 configuration);
115 } catch (FileNotFoundException fnfe) {
116 System.err.println("stylesheet " + style[0]
117 + " doesn't exist");
118 System.exit(1);
119 }
120 }
121 }
122 }
123 }
124
125 private static Options buildOptions() {
126 Options opts = new Options();
127
128 Option help = new Option("h", "help", false,
129 "Print help for the RAT command line interface and exit");
130 opts.addOption(help);
131
132 Option addLicence = new Option(
133 "a",
134 "addLicence",
135 false,
136 "Add the default licence header to any file with an unknown licence that is not in the exclusion list. By default new files will be created with the licence header, to force the modification of existing files use the --force option.");
137 opts.addOption(addLicence);
138
139 Option write = new Option(
140 "f",
141 "force",
142 false,
143 "Forces any changes in files to be written directly to the source files (i.e. new files are not created)");
144 opts.addOption(write);
145
146 Option copyright = new Option(
147 "c",
148 "copyright",
149 true,
150 "The copyright message to use in the licence headers, usually in the form of \"Copyright 2008 Foo\"");
151 opts.addOption(copyright);
152
153 final Option exclude = OptionBuilder
154 .withArgName("expression")
155 .withLongOpt("exclude")
156 .hasArgs()
157 .withDescription("Excludes files matching <expression>. " +
158 "Note that --dir is required when using this parameter. " +
159 "Allows multiple arguments.")
160 .create(EXCLUDE_CLI);
161 opts.addOption(exclude);
162
163 Option dir = new Option(
164 "d",
165 "dir",
166 false,
167 "Used to indicate source when using --exclude");
168 opts.addOption(dir);
169
170 OptionGroup outputType = new OptionGroup();
171
172 Option xml = new Option(
173 "x",
174 "xml",
175 false,
176 "Output the report in raw XML format. Not compatible with -s");
177 outputType.addOption(xml);
178
179 Option xslt = new Option(String.valueOf(STYLESHEET_CLI),
180 "stylesheet",
181 true,
182 "XSLT stylesheet to use when creating the"
183 + " report. Not compatible with -x");
184 outputType.addOption(xslt);
185 opts.addOptionGroup(outputType);
186
187 return opts;
188 }
189
190 private static final void printUsage(Options opts) {
191 HelpFormatter f = new HelpFormatter();
192 String header = "Options";
193
194 StringBuffer footer = new StringBuffer("\n");
195 footer.append("NOTE:\n");
196 footer.append("RAT is really little more than a grep ATM\n");
197 footer.append("RAT is also rather memory hungry ATM\n");
198 footer.append("RAT is very basic ATM\n");
199 footer.append("RAT highlights possible issues\n");
200 footer.append("RAT reports require intepretation\n");
201 footer.append("RAT often requires some tuning before it runs well against a project\n");
202 footer.append("RAT relies on heuristics: it may miss issues\n");
203
204 f.printHelp("java rat.report [options] [DIR|TARBALL]",
205 header, opts, footer.toString(), false);
206 System.exit(0);
207 }
208
209 private final String baseDirectory;
210
211 private FilenameFilter inputFileFilter = null;
212
213 private Report(String baseDirectory) {
214 this.baseDirectory = baseDirectory;
215 }
216
217
218
219
220
221 public FilenameFilter getInputFileFilter() {
222 return inputFileFilter;
223 }
224
225
226
227
228
229 public void setInputFileFilter(FilenameFilter inputFileFilter) {
230 this.inputFileFilter = inputFileFilter;
231 }
232
233 public ClaimStatistic report(PrintStream out) throws Exception {
234 final IReportable base = getDirectory(out);
235 if (base != null) {
236 final ReportConfiguration configuration = new ReportConfiguration();
237 configuration.setHeaderMatcher(Defaults.createDefaultMatcher());
238 return report(base, new OutputStreamWriter(out), configuration);
239 }
240 return null;
241 }
242
243 private IReportable getDirectory(PrintStream out) {
244 File base = new File(baseDirectory);
245 if (!base.exists()) {
246 out.print("ERROR: ");
247 out.print(baseDirectory);
248 out.print(" does not exist.\n");
249 return null;
250 }
251
252 if (base.isDirectory()) {
253 return new DirectoryWalker(base, inputFileFilter);
254 }
255
256 try {
257 return new ArchiveWalker(base, inputFileFilter);
258 } catch (IOException ex) {
259 out.print("ERROR: ");
260 out.print(baseDirectory);
261 out.print(" is not valid gzip data.\n");
262 return null;
263 }
264 }
265
266
267
268
269
270
271
272
273 public void styleReport(PrintStream out) throws Exception {
274 final IReportable base = getDirectory(out);
275 if (base != null) {
276 InputStream style = Defaults.getDefaultStyleSheet();
277 final ReportConfiguration configuration = new ReportConfiguration();
278 configuration.setHeaderMatcher(Defaults.createDefaultMatcher());
279 report(out, base, style, configuration);
280 }
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296 public static void report(PrintStream out, IReportable base, final InputStream style,
297 ReportConfiguration pConfiguration)
298 throws IOException, TransformerConfigurationException, InterruptedException, RatException {
299 report(new OutputStreamWriter(out), base, style, pConfiguration);
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 public static ClaimStatistic report(Writer out, IReportable base, final InputStream style,
318 ReportConfiguration pConfiguration)
319 throws IOException, TransformerConfigurationException, FileNotFoundException, InterruptedException, RatException {
320 PipedReader reader = new PipedReader();
321 PipedWriter writer = new PipedWriter(reader);
322 ReportTransformer transformer = new ReportTransformer(out, style, reader);
323 Thread transformerThread = new Thread(transformer);
324 transformerThread.start();
325 final ClaimStatistic statistic = report(base, writer, pConfiguration);
326 writer.flush();
327 writer.close();
328 transformerThread.join();
329 return statistic;
330 }
331
332
333
334
335
336
337
338
339
340
341 public static ClaimStatistic report(final IReportable container, final Writer out,
342 ReportConfiguration pConfiguration) throws IOException, RatException {
343 IXmlWriter writer = new XmlWriter(out);
344 final ClaimStatistic statistic = new ClaimStatistic();
345 RatReport report = XmlReportFactory.createStandardReport(writer, statistic, pConfiguration);
346 report.startReport();
347 container.run(report);
348 report.endReport();
349 writer.closeDocument();
350 return statistic;
351 }
352 }