| /* |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| */ |
| package org.apache.rat; |
| |
| import org.apache.commons.cli.*; |
| import org.apache.commons.io.FileUtils; |
| import org.apache.commons.io.filefilter.NotFileFilter; |
| import org.apache.commons.io.filefilter.OrFileFilter; |
| import org.apache.commons.io.filefilter.RegexFileFilter; |
| import org.apache.commons.io.filefilter.WildcardFileFilter; |
| import org.apache.rat.api.RatException; |
| import org.apache.rat.report.IReportable; |
| import org.apache.rat.report.RatReport; |
| import org.apache.rat.report.claim.ClaimStatistic; |
| import org.apache.rat.report.xml.XmlReportFactory; |
| import org.apache.rat.report.xml.writer.IXmlWriter; |
| import org.apache.rat.report.xml.writer.impl.base.XmlWriter; |
| import org.apache.rat.walker.ArchiveWalker; |
| import org.apache.rat.walker.DirectoryWalker; |
| |
| import javax.xml.transform.TransformerConfigurationException; |
| import java.io.*; |
| import java.util.List; |
| |
| |
| public class Report { |
| private static final String EXCLUDE_CLI = "e"; |
| private static final char EXCLUDE_FILE_CLI = 'E'; |
| private static final char STYLESHEET_CLI = 's'; |
| private static final String HELP = "h"; |
| |
| public static final void main(String args[]) throws Exception { |
| final ReportConfiguration configuration = new ReportConfiguration(); |
| configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); |
| configuration.setApproveDefaultLicenses(true); |
| Options opts = buildOptions(); |
| |
| DefaultParser parser = new DefaultParser(); |
| CommandLine cl = null; |
| try { |
| cl = parser.parse(opts, args); |
| } catch (ParseException e) { |
| System.err.println("Please use the \"--help\" option to see a list of valid commands and options"); |
| System.exit(1); |
| return; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE for "cl" |
| } |
| |
| if (cl.hasOption(HELP)) { |
| printUsage(opts); |
| } |
| |
| args = cl.getArgs(); |
| if (args == null || args.length != 1) { |
| printUsage(opts); |
| } else { |
| Report report = new Report(args[0]); |
| |
| if (cl.hasOption('a') || cl.hasOption('A')) { |
| configuration.setAddingLicenses(true); |
| configuration.setAddingLicensesForced(cl.hasOption('f')); |
| configuration.setCopyrightMessage(cl.getOptionValue("c")); |
| } |
| |
| if (cl.hasOption(EXCLUDE_CLI)) { |
| String[] excludes = cl.getOptionValues(EXCLUDE_CLI); |
| if (excludes != null) { |
| final FilenameFilter filter = new NotFileFilter(new WildcardFileFilter(excludes)); |
| report.setInputFileFilter(filter); |
| } |
| } else if (cl.hasOption(EXCLUDE_FILE_CLI)) { |
| String excludeFileName = cl.getOptionValue(EXCLUDE_FILE_CLI); |
| if (excludeFileName != null) { |
| List<String> excludes = FileUtils.readLines(new File(excludeFileName)); |
| final OrFileFilter orFilter = new OrFileFilter(); |
| for (String exclude : excludes) { |
| orFilter.addFileFilter(new RegexFileFilter(exclude)); |
| } |
| final FilenameFilter filter = new NotFileFilter(orFilter); |
| report.setInputFileFilter(filter); |
| } |
| } |
| if (cl.hasOption('x')) { |
| report.report(System.out, configuration); |
| } else { |
| if (!cl.hasOption(STYLESHEET_CLI)) { |
| report.styleReport(System.out, configuration); |
| } else { |
| String[] style = cl.getOptionValues(STYLESHEET_CLI); |
| if (style.length != 1) { |
| System.err.println("please specify a single stylesheet"); |
| System.exit(1); |
| } |
| try { |
| report(System.out, |
| report.getDirectory(System.out), |
| new FileInputStream(style[0]), |
| configuration); |
| } catch (FileNotFoundException fnfe) { |
| System.err.println("stylesheet " + style[0] |
| + " doesn't exist"); |
| System.exit(1); |
| } |
| } |
| } |
| } |
| } |
| |
| private static Options buildOptions() { |
| Options opts = new Options(); |
| |
| Option help = new Option(HELP, "help", false, |
| "Print help for the Rat command line interface and exit"); |
| opts.addOption(help); |
| |
| OptionGroup addLicenseGroup = new OptionGroup(); |
| String addLicenseDesc = "Add the default license header to any file with an unknown license that is not in the exclusion list. " + |
| "By default new files will be created with the license header, " + |
| "to force the modification of existing files use the --force option."; |
| |
| // RAT-85/RAT-203: Deprecated! added only for convenience and for backwards compatibility |
| Option addLicence = new Option( |
| "a", |
| "addLicence", |
| false, |
| addLicenseDesc); |
| addLicenseGroup.addOption(addLicence); |
| Option addLicense = new Option( |
| "A", |
| "addLicense", |
| false, |
| addLicenseDesc); |
| addLicenseGroup.addOption(addLicense); |
| opts.addOptionGroup(addLicenseGroup); |
| |
| Option write = new Option( |
| "f", |
| "force", |
| false, |
| "Forces any changes in files to be written directly to the source files (i.e. new files are not created)"); |
| opts.addOption(write); |
| |
| Option copyright = new Option( |
| "c", |
| "copyright", |
| true, |
| "The copyright message to use in the license headers, usually in the form of \"Copyright 2008 Foo\""); |
| opts.addOption(copyright); |
| |
| final Option exclude = Option.builder(EXCLUDE_CLI) |
| .argName("expression") |
| .longOpt("exclude") |
| .hasArgs() |
| .desc("Excludes files matching wildcard <expression>. " + |
| "Note that --dir is required when using this parameter. " + |
| "Allows multiple arguments.") |
| .build(); |
| opts.addOption(exclude); |
| |
| @SuppressWarnings("static-access") // ignore OptionBuilder design fault |
| final Option excludeFile = OptionBuilder |
| .withArgName("fileName") |
| .withLongOpt("exclude-file") |
| .hasArgs() |
| .withDescription("Excludes files matching regular expression in <file> " + |
| "Note that --dir is required when using this parameter. ") |
| .create(EXCLUDE_FILE_CLI); |
| opts.addOption(excludeFile); |
| |
| Option dir = new Option( |
| "d", |
| "dir", |
| false, |
| "Used to indicate source when using --exclude"); |
| opts.addOption(dir); |
| |
| OptionGroup outputType = new OptionGroup(); |
| |
| Option xml = new Option( |
| "x", |
| "xml", |
| false, |
| "Output the report in raw XML format. Not compatible with -s"); |
| outputType.addOption(xml); |
| |
| Option xslt = new Option(String.valueOf(STYLESHEET_CLI), |
| "stylesheet", |
| true, |
| "XSLT stylesheet to use when creating the" |
| + " report. Not compatible with -x"); |
| outputType.addOption(xslt); |
| opts.addOptionGroup(outputType); |
| |
| return opts; |
| } |
| |
| private static final void printUsage(Options opts) { |
| HelpFormatter f = new HelpFormatter(); |
| String header = "Options"; |
| |
| StringBuilder footer = new StringBuilder(); |
| footer.append("\nNOTE:\n"); |
| footer.append("Rat is really little more than a grep ATM\n"); |
| footer.append("Rat is also rather memory hungry ATM\n"); |
| footer.append("Rat is very basic ATM\n"); |
| footer.append("Rat highlights possible issues\n"); |
| footer.append("Rat reports require interpretation\n"); |
| footer.append("Rat often requires some tuning before it runs well against a project\n"); |
| footer.append("Rat relies on heuristics: it may miss issues\n"); |
| |
| f.printHelp("java rat.report [options] [DIR|TARBALL]", |
| header, opts, footer.toString(), false); |
| System.exit(0); |
| } |
| |
| private final String baseDirectory; |
| |
| private FilenameFilter inputFileFilter = null; |
| |
| private Report(String baseDirectory) { |
| this.baseDirectory = baseDirectory; |
| } |
| |
| /** |
| * Gets the current filter used to select files. |
| * |
| * @return current file filter, or null when no filter has been set |
| */ |
| public FilenameFilter getInputFileFilter() { |
| return inputFileFilter; |
| } |
| |
| /** |
| * Sets the current filter used to select files. |
| * |
| * @param inputFileFilter filter, or null when no filter has been set |
| */ |
| public void setInputFileFilter(FilenameFilter inputFileFilter) { |
| this.inputFileFilter = inputFileFilter; |
| } |
| |
| /** |
| * @param out - the output stream to receive the styled report |
| * @return the currently collected numerical statistics. |
| * @throws Exception in case of errors. |
| * @deprecated use {@link #report(PrintStream, ReportConfiguration)} instead |
| */ |
| @Deprecated |
| public ClaimStatistic report(PrintStream out) throws Exception { |
| final ReportConfiguration configuration = new ReportConfiguration(); |
| configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); |
| configuration.setApproveDefaultLicenses(true); |
| return report(out, configuration); |
| } |
| |
| /** |
| * @param out - the output stream to receive the styled report |
| * @param configuration - current configuration options. |
| * @return the currently collected numerical statistics. |
| * @throws Exception in case of errors. |
| * @since Rat 0.8 |
| */ |
| public ClaimStatistic report(PrintStream out, |
| ReportConfiguration configuration) |
| throws Exception { |
| final IReportable base = getDirectory(out); |
| if (base != null) { |
| return report(base, new OutputStreamWriter(out), configuration); |
| } |
| return null; |
| } |
| |
| private IReportable getDirectory(PrintStream out) { |
| File base = new File(baseDirectory); |
| if (!base.exists()) { |
| out.print("ERROR: "); |
| out.print(baseDirectory); |
| out.print(" does not exist.\n"); |
| return null; |
| } |
| |
| if (base.isDirectory()) { |
| return new DirectoryWalker(base, inputFileFilter); |
| } |
| |
| try { |
| return new ArchiveWalker(base, inputFileFilter); |
| } catch (IOException ex) { |
| out.print("ERROR: "); |
| out.print(baseDirectory); |
| out.print(" is not valid gzip data.\n"); |
| return null; |
| } |
| } |
| |
| /** |
| * Output a report in the default style and default license |
| * header matcher. |
| * |
| * @param out - the output stream to receive the styled report |
| * @throws Exception in case of errors. |
| * @deprecated use {@link #styleReport(PrintStream, ReportConfiguration)} instead |
| */ |
| @Deprecated |
| public void styleReport(PrintStream out) throws Exception { |
| final ReportConfiguration configuration = new ReportConfiguration(); |
| configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); |
| configuration.setApproveDefaultLicenses(true); |
| styleReport(out, configuration); |
| } |
| |
| /** |
| * Output a report in the default style and default license |
| * header matcher. |
| * |
| * @param out - the output stream to receive the styled report |
| * @param configuration the configuration to use |
| * @throws Exception in case of errors. |
| * @since Rat 0.8 |
| */ |
| public void styleReport(PrintStream out, |
| ReportConfiguration configuration) |
| throws Exception { |
| final IReportable base = getDirectory(out); |
| if (base != null) { |
| InputStream style = Defaults.getDefaultStyleSheet(); |
| report(out, base, style, configuration); |
| } |
| } |
| |
| /** |
| * Output a report that is styled using a defined stylesheet. |
| * |
| * @param out the stream to write the report to |
| * @param base the files or directories to report on |
| * @param style an input stream representing the stylesheet to use for styling the report |
| * @param pConfiguration current report configuration. |
| * @throws IOException in case of I/O errors. |
| * @throws TransformerConfigurationException in case of XML errors. |
| * @throws InterruptedException in case of threading errors. |
| * @throws RatException in case of internal errors. |
| */ |
| public static void report(PrintStream out, IReportable base, final InputStream style, |
| ReportConfiguration pConfiguration) |
| throws IOException, TransformerConfigurationException, InterruptedException, RatException { |
| report(new OutputStreamWriter(out), base, style, pConfiguration); |
| } |
| |
| /** |
| * Output a report that is styled using a defined stylesheet. |
| * |
| * @param out the writer to write the report to |
| * @param base the files or directories to report on |
| * @param style an input stream representing the stylesheet to use for styling the report |
| * @param pConfiguration current report configuration. |
| * @return the currently collected numerical statistics. |
| * @throws IOException in case of I/O errors. |
| * @throws TransformerConfigurationException in case of XML errors. |
| * @throws InterruptedException in case of threading errors. |
| * @throws RatException in case of internal errors. |
| */ |
| public static ClaimStatistic report(Writer out, IReportable base, final InputStream style, |
| ReportConfiguration pConfiguration) |
| throws IOException, TransformerConfigurationException, InterruptedException, RatException { |
| PipedReader reader = new PipedReader(); |
| PipedWriter writer = new PipedWriter(reader); |
| ReportTransformer transformer = new ReportTransformer(out, style, reader); |
| Thread transformerThread = new Thread(transformer); |
| transformerThread.start(); |
| final ClaimStatistic statistic = report(base, writer, pConfiguration); |
| writer.flush(); |
| writer.close(); |
| transformerThread.join(); |
| return statistic; |
| } |
| |
| /** |
| * @param container the files or directories to report on |
| * @param out the writer to write the report to |
| * @param pConfiguration current report configuration. |
| * @return the currently collected numerical statistics. |
| * @throws IOException in case of I/O errors. |
| * @throws RatException in case of internal errors. |
| */ |
| public static ClaimStatistic report(final IReportable container, final Writer out, |
| ReportConfiguration pConfiguration) throws IOException, RatException { |
| IXmlWriter writer = new XmlWriter(out); |
| final ClaimStatistic statistic = new ClaimStatistic(); |
| RatReport report = XmlReportFactory.createStandardReport(writer, statistic, pConfiguration); |
| report.startReport(); |
| container.run(report); |
| report.endReport(); |
| writer.closeDocument(); |
| return statistic; |
| } |
| } |