Package com.basistech.m2e.code.quality.pmd

Source Code of com.basistech.m2e.code.quality.pmd.EclipsePmdProjectConfigurator

/*******************************************************************************
* Copyright 2010 Mohan KR
* Copyright 2010 Basis Technology Corp.
*
* Licensed 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 com.basistech.m2e.code.quality.pmd;

import static com.basistech.m2e.code.quality.pmd.PmdEclipseConstants.MAVEN_PLUGIN_ARTIFACTID;
import static com.basistech.m2e.code.quality.pmd.PmdEclipseConstants.MAVEN_PLUGIN_GROUPID;
import static com.basistech.m2e.code.quality.pmd.PmdEclipseConstants.PMD_RULESET_FILE;
import static com.basistech.m2e.code.quality.pmd.PmdEclipseConstants.PMD_SETTINGS_FILE;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.sourceforge.pmd.PMDException;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RuleSetNotFoundException;
import net.sourceforge.pmd.RuleSetReferenceId;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import net.sourceforge.pmd.eclipse.runtime.builder.PMDNature;
import net.sourceforge.pmd.eclipse.runtime.properties.IProjectProperties;
import net.sourceforge.pmd.eclipse.runtime.properties.IProjectPropertiesManager;
import net.sourceforge.pmd.eclipse.runtime.properties.PropertiesException;
import net.sourceforge.pmd.eclipse.runtime.writer.WriterException;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecution;
import org.codehaus.plexus.util.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
//import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.basistech.m2e.code.quality.shared.AbstractMavenPluginProjectConfigurator;
import com.basistech.m2e.code.quality.shared.MavenPluginWrapper;
import com.basistech.m2e.code.quality.shared.ResourceResolver;

public class EclipsePmdProjectConfigurator extends
    AbstractMavenPluginProjectConfigurator {
//  private static final String PMD_NATURE = "net.sourceforge.pmd.eclipse.plugin.pmdNature";
  private static final String JAVA_NATURE = "org.eclipse.jdt.core.javanature";
  private static final Logger log = LoggerFactory
      .getLogger(EclipsePmdProjectConfigurator.class);

  // create a rule set factory for instantiating rule sets
  private RuleSetFactory factory = new RuleSetFactory();

  @Override
  protected String getMavenPluginGroupId() {
    return MAVEN_PLUGIN_GROUPID;
  }

  @Override
  protected String getMavenPluginArtifactId() {
    return MAVEN_PLUGIN_ARTIFACTID;
  }

  @Override
  protected String[] getMavenPluginGoal() {
    return new String[] { "check" };
  }

  @Override
  protected void handleProjectConfigurationChange(final MavenSession session,
      final IMavenProjectFacade mavenProjectFacade,
      final IProject project, final IProgressMonitor monitor,
      final MavenPluginWrapper mavenPluginWrapper) throws CoreException {

    final MojoExecution execution = findMojoExecution(mavenPluginWrapper);
    MojoExecution pmdGoalExecution = findForkedExecution(execution,
        "org.apache.maven.plugins", "maven-pmd-plugin", "pmd");
    final MavenPluginConfigurationTranslator pluginCfgTranslator = MavenPluginConfigurationTranslator
        .newInstance(this, session,
            mavenProjectFacade.getMavenProject(),
            mavenPluginWrapper, pmdGoalExecution, project);

    this.createOrUpdateEclipsePmdConfiguration(session, mavenPluginWrapper,
        project, pluginCfgTranslator, monitor);

    addPMDNature(project, monitor);
  }

 

  // private static boolean addPMDNatureHere(final IProject project,
  // final IProgressMonitor monitor) throws CoreException {
  // boolean success = false;
  //
  // // unlike the one inside PMD, this carefully does NOT check for the
  // prerequisite
  // // Java nature, in case we end up in the wrong order.
  // if (project.hasNature(JAVA_NATURE) && !project.hasNature(PMD_NATURE)) {
  // final IProjectDescription description = project.getDescription();
  // final String[] natureIds = description.getNatureIds();
  // String[] newNatureIds = new String[natureIds.length + 1];
  // System.arraycopy(natureIds, 0, newNatureIds, 0, natureIds.length);
  // newNatureIds[natureIds.length] = PMD_NATURE;
  // description.setNatureIds(newNatureIds);
  // project.setDescription(description, monitor);
  // success = true;
  // }
  //
  // return success;
  // }

  private void addPMDNature(final IProject project,
      final IProgressMonitor monitor) throws CoreException {
    if (project.hasNature(JAVA_NATURE)) {
      try {
        PMDNature.addPMDNature(project, monitor);
      } catch (CoreException pmdNatureProblem) {
        log.error("PMD plugin threw exception adding PMD nature",
            pmdNatureProblem);
        throw pmdNatureProblem;
      }
    }
  }

  @Override
  protected void unconfigureEclipsePlugin(final IProject project,
      final IProgressMonitor monitor) throws CoreException {
    IProjectPropertiesManager mgr = PMDPlugin.getDefault()
        .getPropertiesManager();
    try {
      IProjectProperties projectProperties = mgr
          .loadProjectProperties(project);
      projectProperties.setPmdEnabled(false);
      projectProperties.setRuleSetStoredInProject(false);
      mgr.storeProjectProperties(projectProperties);
    } catch (PropertiesException ex) {
    }

    PMDNature.removePMDNature(project, monitor);
    // delete .pmdruleset if any
    final IResource pmdRulesetResource = project.getFile(PMD_RULESET_FILE);
    pmdRulesetResource.delete(IResource.FORCE, monitor);

    // delete .pmd if any
    final IResource pmdPropertiesResource = project
        .getFile(PMD_SETTINGS_FILE);
    pmdPropertiesResource.delete(IResource.FORCE, monitor);
  }

  /**
   * Configures the PMD plugin based on the POM contents
   *
   * @throws CoreException
   *             if the creation failed.
   */
  private void createOrUpdateEclipsePmdConfiguration(
      final MavenSession session, final MavenPluginWrapper pluginWrapper,
      final IProject project,
      final MavenPluginConfigurationTranslator pluginCfgTranslator,
      final IProgressMonitor monitor) throws CoreException {

    final MojoExecution execution = findMojoExecution(pluginWrapper);
    ResourceResolver resourceResolver = ResourceResolver
        .newInstance(getPluginClassRealm(session, execution));
    try{
      final RuleSet ruleset = this.createPmdRuleSet(pluginCfgTranslator,
          resourceResolver);

      this.buildAndAddPmdExcludeAndIncludePatternToRuleSet(
          pluginCfgTranslator, ruleset);

      // persist the ruleset to a file under the project.
      final File rulesetFile = writeRuleSet(
          project.getFile(PMD_RULESET_FILE), ruleset, monitor);

      try {
        final IProjectPropertiesManager mgr = PMDPlugin.getDefault()
            .getPropertiesManager();
        final IProjectProperties projectProperties = mgr
            .loadProjectProperties(project);
        projectProperties.setPmdEnabled(true);
        projectProperties.setRuleSetFile(rulesetFile.getAbsolutePath());
        projectProperties.setRuleSetStoredInProject(true);
        mgr.storeProjectProperties(projectProperties);
      } catch (PropertiesException ex) {
        // remove the files
        this.unconfigureEclipsePlugin(project, monitor);
      }
    } catch (PMDException ex) {
          //nothing to do, skip configuration
    }
  }

  private RuleSet createPmdRuleSet(
      final MavenPluginConfigurationTranslator pluginCfgTranslator,
      final ResourceResolver resourceResolver) throws CoreException, PMDException {

    final RuleSet ruleSet = new RuleSet();
    ruleSet.setName("M2Eclipse PMD RuleSet");

    final List<String> rulesetStringLocations = pluginCfgTranslator.getRulesets();

    for (final String loc : rulesetStringLocations) {
      RuleSetReferenceId ruleSetReferenceId = new RuleSetReferenceId(loc);
      final URL resolvedLocation = resourceResolver.resolveLocation(ruleSetReferenceId.getRuleSetFileName());

      if(resolvedLocation == null) {
        throw new PMDException(String.format("Failed to resolve RuleSet from location [%s],SKIPPING Eclipse PMD configuration", loc));
      }

      RuleSet ruleSetAtLocations;
      try {
        RuleSetReferenceId resolvedRuleSetReference = new RuleSetReferenceId(loc) {
          @Override
          public InputStream getInputStream(ClassLoader arg0) throws RuleSetNotFoundException {
            try {
              return resolvedLocation.openStream();
            } catch (IOException e) {
              // ignore them.
            }
            log.warn("No ruleset found for {}", loc);
            return null;
          }
        };
        ruleSetAtLocations = this.factory.createRuleSet(resolvedRuleSetReference);
        ruleSet.addRuleSet(ruleSetAtLocations);
      } catch (RuleSetNotFoundException e) {
        log.error("Couldn't find ruleset {}", loc, e);
      }
    }

    return ruleSet;
  }

  /**
   * Serializes the ruleset for configuring eclipse PMD plugin.
   *
   * @param rulesetFile
   *            the ruleset File resource.
   * @param ruleSet
   *            the {@code RuleSet} instance.
   * @param monitor
   *            the Progress monitor instance.
   * @return the {@code File} instance of the ruleset file.
   * @throws CoreException
   */
  private File writeRuleSet(final IFile rulesetFile, final RuleSet ruleSet,
      final IProgressMonitor monitor) throws CoreException {
    final PMDPlugin pmdPlugin = PMDPlugin.getDefault();

    BufferedOutputStream outputStream = null;
    ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
    try {
      outputStream = new BufferedOutputStream(new FileOutputStream(
          rulesetFile.getLocation().toFile()));
      pmdPlugin.getRuleSetWriter().write(byteArrayStream, ruleSet);

      // ..and now we have two problems
      String fixedXml = byteArrayStream.toString()
          .replaceAll("\\<exclude\\>(.*)\\</exclude\\>",
              "<exclude name=\"$1\"/>");

      outputStream.write(fixedXml.getBytes());
      outputStream.close();

      rulesetFile.refreshLocal(IResource.DEPTH_ZERO, monitor);
    } catch (IOException ex) {
      //
    } catch (WriterException ex) {
      //
    }
    return rulesetFile.getLocation().toFile();
  }

  private void buildAndAddPmdExcludeAndIncludePatternToRuleSet(
      final MavenPluginConfigurationTranslator pluginCfgTranslator,
      final RuleSet ruleset) {
    final List<String> excludeRoots = pluginCfgTranslator.getExcludeRoots();
    final List<String> includeRoots = pluginCfgTranslator.getIncludeRoots();
    final List<String> includePatterns = pluginCfgTranslator.getIncludes();

    // 1. check to see if any includes are specified. If they are then
    // to line up with the behavior of maven-pmd-plugin, excludes
    // don't make any sense at all or more specifically it is (ignored).
    final boolean includesSpecified = includePatterns.size() > 0;
    final Set<String> excludeRootsSet = new HashSet<String>();
    excludeRootsSet.addAll(excludeRoots);

    if (includesSpecified) {
      // Add all includeRoots to excludeRoots.
      // Add all includeRoots too..
      excludeRootsSet.addAll(includeRoots);
    } else {
      final List<String> excludePatterns = pluginCfgTranslator
          .getExcludes();
      // 2.) As per spec. add excludes pattern to all *includeRoots*.
      for (String ir : includeRoots) {
        for (String ep : excludePatterns) {
          String fullPattern = ".*" + ir + ep;
          ruleset.addExcludePattern(StringUtils.replace(fullPattern,
              ".*.*", ".*"));
        }
      }
    }
    // 1.) Do the excludeRoots first
    for (String er : excludeRootsSet) {
      ruleset.addExcludePattern(".*" + er);
    }
    // 3.) Now all includes
    for (String ir : includeRoots) {
      for (String ip : includePatterns) {
        String fullPattern = ".*" + ir + ip;
        ruleset.addIncludePattern(StringUtils.replace(fullPattern,
            ".*.*", ".*"));
      }
    }
  }

  private MojoExecution findMojoExecution(
      final MavenPluginWrapper mavenPluginWrapper) throws CoreException {
    final List<MojoExecution> mojoExecutions = mavenPluginWrapper
        .getMojoExecutions();
    if (mojoExecutions.size() != 1) {
      throw new CoreException(new Status(IStatus.ERROR,
          PmdEclipseConstants.PLUGIN_ID,
          "Wrong number of executions. Expected 1. Found "
              + mojoExecutions.size()));
    }
    final MojoExecution execution = mojoExecutions.get(0);
    return execution;
  }

}
TOP

Related Classes of com.basistech.m2e.code.quality.pmd.EclipsePmdProjectConfigurator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.