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.maven.plugins.pmd.exec;
20  
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStreamWriter;
25  import java.io.Writer;
26  import java.util.function.Consumer;
27  import java.util.function.Predicate;
28  
29  import net.sourceforge.pmd.cpd.CPDReport;
30  import net.sourceforge.pmd.cpd.CPDReportRenderer;
31  import net.sourceforge.pmd.cpd.Match;
32  import net.sourceforge.pmd.cpd.XMLRenderer;
33  import org.apache.maven.plugins.pmd.ExcludeDuplicationsFromFile;
34  import org.apache.maven.reporting.MavenReportException;
35  import org.codehaus.plexus.util.FileUtils;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  class CpdReportConsumer implements Consumer<CPDReport> {
40      private static final Logger LOG = LoggerFactory.getLogger(CpdReportConsumer.class);
41  
42      private final CpdRequest request;
43      private final ExcludeDuplicationsFromFile excludeDuplicationsFromFile;
44  
45      CpdReportConsumer(CpdRequest request, ExcludeDuplicationsFromFile excludeDuplicationsFromFile) {
46          this.request = request;
47          this.excludeDuplicationsFromFile = excludeDuplicationsFromFile;
48      }
49  
50      @Override
51      public void accept(CPDReport report) {
52          try {
53              // always create XML format. we need to output it even if the file list is empty or we have no
54              // duplications so that the "check" goals can check for violations
55              writeXmlReport(report);
56  
57              // HTML format is handled by maven site report, XML format has already been rendered.
58              // a renderer is only needed for other formats
59              String format = request.getFormat();
60              if (!"html".equals(format) && !"xml".equals(format)) {
61                  writeFormattedReport(report);
62              }
63          } catch (IOException | MavenReportException e) {
64              throw new RuntimeException(e);
65          }
66      }
67  
68      private void writeXmlReport(CPDReport cpd) throws IOException {
69          File targetFile = writeReport(cpd, new XMLRenderer(request.getOutputEncoding()), "xml");
70          if (request.isIncludeXmlInSite()) {
71              File siteDir = new File(request.getReportOutputDirectory());
72              if (!siteDir.exists() && !siteDir.mkdirs()) {
73                  throw new IOException("Couldn't create report output directory: " + siteDir);
74              }
75              FileUtils.copyFile(targetFile, new File(siteDir, "cpd.xml"));
76          }
77      }
78  
79      private void writeFormattedReport(CPDReport cpd) throws IOException, MavenReportException {
80          CPDReportRenderer r = CpdExecutor.createRenderer(request.getFormat(), request.getOutputEncoding());
81          writeReport(cpd, r, request.getFormat());
82      }
83  
84      private File writeReport(CPDReport cpd, CPDReportRenderer renderer, String extension) throws IOException {
85          if (renderer == null) {
86              return null;
87          }
88  
89          File targetDir = new File(request.getTargetDirectory());
90          if (!targetDir.exists() && !targetDir.mkdirs()) {
91              throw new IOException("Couldn't create report output directory: " + targetDir);
92          }
93  
94          File targetFile = new File(targetDir, "cpd." + extension);
95          try (Writer writer = new OutputStreamWriter(new FileOutputStream(targetFile), request.getOutputEncoding())) {
96              renderer.render(cpd.filterMatches(filterMatches()), writer);
97              writer.flush();
98          }
99          return targetFile;
100     }
101 
102     private Predicate<Match> filterMatches() {
103         return (Match match) -> {
104             LOG.debug(
105                     "Filtering duplications. Using {} configured exclusions.",
106                     excludeDuplicationsFromFile.countExclusions());
107 
108             if (excludeDuplicationsFromFile.isExcludedFromFailure(match)) {
109                 LOG.debug("Excluded {} duplications.", match);
110                 return false;
111             } else {
112                 return true;
113             }
114         };
115     }
116 }