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

org.apache.maven.dotnet.CpdMojo Maven / Gradle / Ivy

Go to download

A plugin that provides general build and test facilities for .Net projects and solutions

There is a newer version: 1.2
Show newest version
/*
 * Maven and Sonar plugin for .Net
 * Copyright (C) 2010 Jose Chillan and Alexandre Victoor
 * mailto: [email protected] or [email protected]
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */

package org.apache.maven.dotnet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import net.sourceforge.pmd.cpd.CPD;
import net.sourceforge.pmd.cpd.CSVRenderer;
import net.sourceforge.pmd.cpd.CsLanguage;
import net.sourceforge.pmd.cpd.Renderer;
import net.sourceforge.pmd.cpd.XMLRenderer;

import org.apache.maven.dotnet.commons.project.SourceFile;
import org.apache.maven.dotnet.commons.project.VisualStudioProject;
import org.apache.maven.dotnet.commons.project.VisualStudioSolution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils;

/**
 * Maven plugin for dotnet cpd analysis. Contains copy/paste code from class
 * CpdReport (it was impossible to inherit from AbstractDotNetMojo and CpdReport
 * at the same time)
 * 
 * @goal cpd
 * @phase site
 * @description generates a report on copy/paste or duplicated code in a C#
 *              project or solution
 * 
 * 
 * @author Alexandre Victoor
 * 
 */
public class CpdMojo extends AbstractDotNetMojo {

  /**
   * The minimum number of tokens that need to be duplicated before it causes a
   * violation.
   * 
   * @parameter expression="${minimumTokens}" default-value="50"
   */
  private int minimumTokens;

  /**
   * Skip the CPD report generation. Most useful on the command line via
   * "-Dcpd.skip=true".
   * 
   * @parameter expression="${cpd.skip}" default-value="false"
   * @since 2.1
   */
  private boolean skip;

  /**
   * The file encoding to use when reading the Java sources.
   * 
   * @parameter expression="${encoding}"
   *            default-value="${project.build.sourceEncoding}"
   * @since 2.3
   */
  private String sourceEncoding;

  /**
   * The output directory for the final HTML report. Note that this parameter is
   * only evaluated if the goal is run directly from the command line or during
   * the default lifecycle. If the goal is run indirectly as part of a site
   * generation, the output directory configured in the Maven Site Plugin is
   * used instead.
   * 
   * @parameter expression="${project.reporting.outputDirectory}"
   * @required
   */
  protected File outputReportingDirectory;

  /**
   * Set the output format type, in addition to the HTML report. Must be one of:
   * "none", "csv", "xml", "txt" or the full class name of the PMD renderer to
   * use. See the net.sourceforge.pmd.renderers package javadoc for available
   * renderers. XML is required if the pmd:check goal is being used.
   * 
   * @parameter expression="${format}" default-value="xml"
   */
  protected String format = "xml";

  /**
   * Run PMD on the tests.
   * 
   * @parameter default-value="false"
   * @since 2.2
   */
  protected boolean includeTests;

  /**
   * Whether to build an aggregated report at the root, or build individual
   * reports.
   * 
   * @parameter expression="${aggregate}" default-value="false"
   * @since 2.2
   */
  protected boolean aggregate;
  
  /**
   * List of the excluded projects, using ',' as delimiter. C# files
   * of these projects will be ignored.
   * 
   * @parameter expression="${skippedProjects}"
   */
  private String skippedProjects;

  /**
   * @see org.apache.maven.reporting.AbstractMavenReport#getProject()
   */
  protected MavenProject getProject() {

    return project;
  }

  /**
   * Convenience method to get the list of files where the CPD tool will be
   * executed
   * 
   * @return a List of the files where the PMD tool will be executed
   * @throws java.io.IOException
   * @throws MojoExecutionException
   */
  protected Map getFilesToProcess()
      throws MojoExecutionException {
    Map fileMap = new HashMap();
    FilenameFilter filter = new CsLanguage().getFileFilter();
    
    Set skippedProjectSet = new HashSet();
    if (skippedProjects!=null) {
      skippedProjectSet.addAll(Arrays.asList(StringUtils.split(skippedProjects,",")));
    }
    
    List projects = getVisualSolution().getProjects();
    for (VisualStudioProject visualStudioProject : projects) {
      if (visualStudioProject.isTest() && !includeTests) {
        getLog()
            .debug("skipping test project " + visualStudioProject.getName());
        
      } else if (skippedProjectSet.contains(visualStudioProject.getName())) {
        getLog().info("Skipping project " + visualStudioProject.getName());
        
      } else {
        Collection sources = visualStudioProject.getSourceFiles();
        for (SourceFile sourceFile : sources) {
          if (filter.accept(sourceFile.getFile().getParentFile(),
              sourceFile.getName())) {
            fileMap.put(sourceFile.getFile(), sourceFile);
          }
        }
      }
    }
    return fileMap;
  }

  /**
   * @see org.apache.maven.reporting.AbstractMavenReport#canGenerateReport()
   */
  public boolean canGenerateReport() {

    if (aggregate && !project.isExecutionRoot()) {
      return false;
    }

    // if format is XML, we need to output it even if the file list is empty
    // so the "check" goals can check for failures
    if ("xml".equals(format)) {
      return true;
    }
    try {
      Map filesToProcess = getFilesToProcess();
      if (filesToProcess.isEmpty()) {
        return false;
      }
    } catch (MojoExecutionException e) {
      getLog().error(e);
    }
    return true;
  }

  /**
   * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
   */
  protected String getOutputReportingDirectory() {

    return outputReportingDirectory.getAbsolutePath();
  }

  /**
   * @throws MojoExecutionException
   * @see org.apache.maven.reporting.AbstractMavenReport#executeReport(java.util.Locale)
   */
  public void executeReport() throws MojoExecutionException {

    if (!skip && canGenerateReport()) {
      ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
      try {
        Thread.currentThread().setContextClassLoader(
            this.getClass().getClassLoader());

        CPD cpd = new CPD(minimumTokens, new CsLanguage());
        try {
          Map files = getFilesToProcess();

          if (StringUtils.isNotEmpty(sourceEncoding)) {
            cpd.setEncoding(sourceEncoding);
          } else if (!files.isEmpty()) {
            getLog()
                .warn(
                    "File encoding has not been set, using platform encoding , i.e. build is platform dependent!");
          }

          Set fileSet = files.keySet();
          for (File file : fileSet) {
            cpd.add(file);
          }

        } catch (UnsupportedEncodingException e) {
          throw new MojoExecutionException("Encoding '" + sourceEncoding
              + "' is not supported.", e);
        } catch (IOException e) {
          throw new MojoExecutionException(e.getMessage(), e);
        }
        cpd.go();

        writeNonHtml(cpd);

      } finally {
        Thread.currentThread().setContextClassLoader(origLoader);
      }

    }
  }

  void writeNonHtml(CPD cpd) throws MojoExecutionException {

    Renderer r = createRenderer();
    String buffer = r.render(cpd.getMatches());
    try {
      outputDirectory.mkdirs();
      FileOutputStream tStream = new FileOutputStream(new File(outputDirectory,
          "cpd." + format));
      Writer writer = new OutputStreamWriter(tStream, "UTF-8");
      writer.write(buffer, 0, buffer.length());
      writer.close();

      File siteDir = new File(outputDirectory, "site");
      siteDir.mkdirs();
      writer = new FileWriter(new File(siteDir, "cpd." + format));
      writer.write(buffer, 0, buffer.length());
      writer.close();

    } catch (IOException ioe) {
      throw new MojoExecutionException(ioe.getMessage(), ioe);
    }
  }

  /**
   * @see org.apache.maven.reporting.MavenReport#getOutputName()
   */
  public String getOutputName() {

    return "cpd";
  }

  /**
   * Create and return the correct renderer for the output type.
   * 
   * @return the renderer based on the configured output
   * @throws org.apache.maven.reporting.MavenReportException
   *           if no renderer found for the output type
   */
  public Renderer createRenderer() throws MojoExecutionException {

    Renderer renderer = null;
    if ("xml".equals(format)) {
      renderer = new XMLRenderer("UTF-8");
    } else if ("csv".equals(format)) {
      renderer = new CSVRenderer();
    } else if (!"".equals(format) && !"none".equals(format)) {
      try {
        renderer = (Renderer) Class.forName(format).newInstance();
      } catch (Exception e) {
        throw new MojoExecutionException("Can't find the custom format "
            + format + ": " + e.getClass().getName());
      }
    }

    if (renderer == null) {
      throw new MojoExecutionException("Can't create report with format of "
          + format);
    }

    return renderer;
  }

  @Override
  protected void executeProject(VisualStudioProject visualProject)
      throws MojoExecutionException, MojoFailureException {

    Log log = getLog();
    log.info("executeProject " + visualProject);

  }

  @Override
  protected void executeSolution(VisualStudioSolution visualSolution)
      throws MojoExecutionException, MojoFailureException {

    Log log = getLog();
    log.info("executeSolution " + visualSolution);
    executeReport();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy