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;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.io.OutputStreamWriter;
27  import java.io.PrintWriter;
28  import java.io.Writer;
29  import java.nio.charset.StandardCharsets;
30  
31  import javax.xml.parsers.DocumentBuilderFactory;
32  import javax.xml.transform.OutputKeys;
33  import javax.xml.transform.Transformer;
34  import javax.xml.transform.TransformerException;
35  import javax.xml.transform.TransformerFactory;
36  import javax.xml.transform.dom.DOMSource;
37  import javax.xml.transform.stream.StreamResult;
38  import javax.xml.transform.stream.StreamSource;
39  
40  import org.apache.commons.io.function.IOSupplier;
41  import org.apache.rat.api.RatException;
42  import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
43  import org.apache.rat.report.RatReport;
44  import org.apache.rat.report.claim.ClaimStatistic;
45  import org.apache.rat.report.xml.XmlReportFactory;
46  import org.apache.rat.report.xml.writer.IXmlWriter;
47  import org.apache.rat.report.xml.writer.impl.base.XmlWriter;
48  import org.w3c.dom.Document;
49  
50  /**
51   * Class that executes the report as defined in a ReportConfiguration and stores
52   * the result for later handleing.
53   */
54  public class Reporter {
55  
56      /**
57       * Format used for listing license families
58       */
59      private static final String LICENSE_FAMILY_FORMAT = "\t%s: %s%n";
60  
61      /**
62       * Format used for listing licenses.
63       */
64      private static final String LICENSE_FORMAT = "%s:\t%s%n\t\t%s%n";
65  
66      private final Document document;
67      private final ClaimStatistic statistic;
68      private final ReportConfiguration configuration;
69  
70      /**
71       * Create the reporter.
72       * @param configuration the configuration to use.
73       * @throws RatException on error.
74       */
75      public Reporter(ReportConfiguration configuration) throws RatException {
76          this.configuration = configuration;
77          try {
78              if (configuration.getReportable() != null) {
79                  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
80                  Writer outputWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
81                  try (IXmlWriter writer = new XmlWriter(outputWriter)) {
82                      statistic = new ClaimStatistic();
83                      RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration);
84                      report.startReport();
85                      configuration.getReportable().run(report);
86                      report.endReport();
87  
88                      InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
89                      document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
90                  }
91              } else {
92                  document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
93                  statistic = new ClaimStatistic();
94              }
95          } catch (Exception e) {
96              throw RatException.makeInstance(e);
97          }
98      }
99  
100     /**
101      * Get the claim statistics from the run.
102      * @return the claim statistics.
103      */
104     public ClaimStatistic getClaimsStatistic() {
105         return statistic;
106     }
107 
108     /**
109      * Outputs the report using the stylesheet and output specified in the configuraiton.
110      * @throws RatException on error.
111      */
112     public void output() throws RatException {
113         if (configuration.isStyleReport()) {
114             output(configuration.getStyleSheet(), configuration.getOutput());
115         } else {
116             output(null, configuration.getOutput());
117         }
118     }
119 
120     /**
121      * Outputs the report to the specified output useing the optional stylesheet.
122      * @param stylesheet the style sheet to use for XSLT formatting, may be null for XML output.
123      * @param output the output stream to write to.
124      * @throws RatException one error.
125      */
126     public void output(IOSupplier<InputStream> stylesheet, IOSupplier<OutputStream> output) throws RatException {
127         InputStream styleIn = null;
128         TransformerFactory tf = TransformerFactory.newInstance();
129         Transformer transformer;
130         try (OutputStream out=output.get()){
131             if (stylesheet != null) {
132                 styleIn = stylesheet.get();
133                 transformer = tf.newTransformer(new StreamSource(styleIn));
134             } else {
135                 transformer = tf.newTransformer();
136                 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
137                 transformer.setOutputProperty(OutputKeys.METHOD, "xml");
138                 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
139                 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
140                 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
141             }
142 
143             transformer.transform(new DOMSource(document),
144                     new StreamResult(new OutputStreamWriter(out, "UTF-8")));
145         } catch (TransformerException | IOException e) {
146             throw new RatException(e);
147         } finally {
148             if (styleIn != null) {
149                 try {
150                     styleIn.close();
151                 } catch (IOException e) {
152                     configuration.getLog().error("Error closing stylesheet", e);
153                 }
154             }
155         }
156     }
157 
158     /**
159      * lists the license families information on the configured output stream.
160      * 
161      * @param configuration The configuration for the system
162      * @throws IOException if PrintWriter can not be retrieved from configuration.
163      */
164     public static void listLicenseFamilies(ReportConfiguration configuration, LicenseFilter filter) throws IOException {
165         try (PrintWriter pw = configuration.getWriter().get()) {
166             pw.format("Families (%s):%n", filter);
167             configuration.getLicenseFamilies(filter)
168                     .forEach(x -> pw.format(LICENSE_FAMILY_FORMAT, x.getFamilyCategory(), x.getFamilyName()));
169             pw.println();
170         }
171     }
172 
173     /**
174      * lists the licenses on the configured output stream.
175      * 
176      * @param configuration The configuration for the system
177      * @throws IOException if PrintWriter can not be retrieved from configuration.
178      */
179     public static void listLicenses(ReportConfiguration configuration, LicenseFilter filter) throws IOException {
180         try (PrintWriter pw = configuration.getWriter().get()) {
181             pw.format("Licenses (%s):%n", filter);
182             configuration.getLicenses(filter)
183                     .forEach(lic -> pw.format(LICENSE_FORMAT, lic.getLicenseFamily().getFamilyCategory(),
184                             lic.getLicenseFamily().getFamilyName(), lic.getNote()));
185             pw.println();
186         }
187     }
188 
189 }