All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.hortis.sonar.mvn.mc.PMDCollector Maven / Gradle / Ivy

/*
 * This program is copyright (c) 2007 Hortis-GRC SA.
 * 
 * This file is part of Sonar.
 * Sonar is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version.
 * 
 * Sonar is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with Sonar; if not, write to the Free Software 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */
package ch.hortis.sonar.mvn.mc;

import ch.hortis.sonar.model.Metrics;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

/**
 * PMD / PMD-CPD reports collector
 */
public class PMDCollector implements MetricsCollector {

	private File pmdReport;

	private File pmdCpdReport;

	private Document pmdCpdDocument;

	private XPath pmdCpdXpath;

	private Document pmdDocument;

	private XPath pmdXpath;

	public void enableLogging(Log log) {
	}
  
  public boolean initialize(MavenProject project) throws MojoExecutionException {
    pmdReport = findPMDReportFile(project, "pmd.xml");
    pmdCpdReport = findPMDReportFile(project, "cpd.xml");
    boolean ok = false;
    try {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        if (pmdCpdReport != null ) {
          pmdCpdDocument = builder.parse(pmdCpdReport);
          pmdCpdXpath = XPathFactory.newInstance().newXPath();
          ok = true;
        }
        if (pmdReport!=null) {
          pmdDocument = builder.parse(pmdReport);
          pmdXpath = XPathFactory.newInstance().newXPath();
          ok = true;
        }
      } catch (Exception ex) {
        throw new MojoExecutionException("Error during PMD reports parsing", ex);
      }
    return ok;
  }

  public Collection collectMeasures() throws MojoExecutionException {
    Collection metrics = new ArrayList();
    try {
      if (pmdCpdReport!=null) {
        Collection tmp = parsePMDCpd(pmdCpdXpath, pmdCpdDocument);
        metrics.addAll(tmp);
      }

      if (pmdReport!=null) {
        Collection violations = parsePMD(pmdXpath, pmdDocument);
        metrics.addAll(violations);
      }

    } catch (Exception ex) {
      throw new MojoExecutionException("Error during PMD reports parsing", ex);
    }
    return metrics;
  }

	private Collection parsePMD(XPath xpath, Node root) throws XPathExpressionException {
    Integer errors = 0;
    errors += ( (Number)xpath.evaluate("count(/pmd/file/violation[@priority='1'])", root, XPathConstants.NUMBER ) ).intValue();
    errors += ( (Number)xpath.evaluate("count(/pmd/file/violation[@priority='2'])", root, XPathConstants.NUMBER ) ).intValue();
    
    Integer warnings = 0;
    warnings += ( (Number)xpath.evaluate("count(/pmd/file/violation[@priority='3'])", root, XPathConstants.NUMBER ) ).intValue();
    warnings += ( (Number)xpath.evaluate("count(/pmd/file/violation[@priority='4'])", root, XPathConstants.NUMBER ) ).intValue();
    
    Integer info = ( (Number)xpath.evaluate("count(/pmd/file/violation[@priority='5'])", root, XPathConstants.NUMBER ) ).intValue();
    
    Collection metrics = new ArrayList();
    metrics.add( new MetricData( Metrics.PMD_ERRORS, errors.doubleValue() ) );
    metrics.add( new MetricData( Metrics.PMD_WARNINGS, warnings.doubleValue() ) );
    metrics.add( new MetricData( Metrics.PMD_INFO, info.doubleValue() ) );
    return metrics;
	}

	private Collection parsePMDCpd(XPath xpath, Node root) throws XPathExpressionException {

		NodeList duplications = (NodeList) xpath.evaluate("/pmd-cpd/duplication", root, XPathConstants.NODESET);
		PMDCPDReportDataContainer projectContainer = new PMDCPDReportDataContainer();

		for (int i = 0; i < duplications.getLength(); i++) {
			Node duplication = duplications.item(i);

			Number lines = (Number) xpath.evaluate("@lines", duplication, XPathConstants.NUMBER);
			Number tokens = (Number) xpath.evaluate("@tokens", duplication, XPathConstants.NUMBER);
		  projectContainer.cumulate(1, lines, tokens);
		}
		return projectContainer.asMetrics();
	}

  private File findPMDReportFile(final MavenProject project, String fileName) {
    String pmdOutputDirectory = project.getBuild().getDirectory() + "/" + fileName;
    File file = new File(pmdOutputDirectory);
    if (file.exists()) {
      return file;
    }
    return null;
  }

	private class PMDCPDReportDataContainer {

		private double duplication;

		private double duplicatedLines;

		private double duplicatedTokens;

		private void cumulate(Number duplication, Number duplicatedLines, Number duplicatedTokens) {
			this.duplication += duplication.doubleValue();
			this.duplicatedLines += duplicatedLines.doubleValue();
			this.duplicatedTokens += duplicatedTokens.doubleValue();
		}

		private Collection asMetrics() {
			Collection metrics = new ArrayList();
			MetricData metric = new MetricData();
			metric.setMetric( Metrics.PMD_DUPLICATION );
			metric.setValue(duplication);
			metrics.add(metric);

			metric = new MetricData();
			metric.setMetric( Metrics.PMD_DUPLICATED_LINES );
			metric.setValue(duplicatedLines);
			metrics.add(metric);

			metric = new MetricData();
			metric.setMetric( Metrics.PMD_DUPLICATED_TOKENS );
			metric.setValue(duplicatedTokens);
			metrics.add(metric);

			return metrics;
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy