/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.maven.plugins.pmd;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import net.sourceforge.pmd.renderers.Renderer;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.plugins.pmd.exec.PmdExecutor;
import org.apache.maven.plugins.pmd.exec.PmdRequest;
import org.apache.maven.plugins.pmd.exec.PmdResult;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.shared.artifact.filter.resolve.AndFilter;
import org.apache.maven.shared.artifact.filter.resolve.ExclusionsFilter;
import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter;
import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
import org.apache.maven.toolchain.Toolchain;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.resource.ResourceManager;
import org.codehaus.plexus.resource.loader.FileResourceCreationException;
import org.codehaus.plexus.resource.loader.FileResourceLoader;
import org.codehaus.plexus.resource.loader.ResourceNotFoundException;
import org.codehaus.plexus.util.StringUtils;

/**
 * Creates a PMD site report based on the rulesets and configuration set in the plugin.
 * It can also generate a pmd output file aside from the site report in any of the following formats: xml, csv or txt.
 *
 * @author Brett Porter
 * @version $Id$
 * @since 2.0
 */
@Mojo(name = "pmd", threadSafe = true, requiresDependencyResolution = ResolutionScope.TEST)
public class PmdReport extends AbstractPmdReport {
    /**
     * The target JDK to analyze based on. Should match the source used in the compiler plugin. Valid values
     * with the default PMD version are
     * currently <code>1.3</code>, <code>1.4</code>, <code>1.5</code>, <code>1.6</code>, <code>1.7</code>,
     * <code>1.8</code>, <code>9</code>, <code>10</code>, <code>11</code>, <code>12</code>, <code>13</code>,
     * <code>14</code>, <code>15</code>, <code>16</code>, <code>17</code>, <code>18</code>, <code>19</code>,
     * and <code>20</code>.
     *
     * <p> You can override the default PMD version by specifying PMD as a dependency,
     * see <a href="examples/upgrading-PMD-at-runtime.html">Upgrading PMD at Runtime</a>.</p>
     *
     * <p>
     *   <b>Note:</b> this parameter is only used if the language parameter is set to <code>java</code>.
     * </p>
     */
    @Parameter(property = "targetJdk", defaultValue = "${maven.compiler.source}")
    private String targetJdk;

    /**
     * The programming language to be analyzed by PMD. Valid values are currently <code>java</code>,
     * <code>javascript</code> and <code>jsp</code>.
     *
     * @since 3.0
     */
    @Parameter(defaultValue = "java")
    private String language;

    /**
     * The rule priority threshold; rules with lower priority than this will not be evaluated.
     *
     * @since 2.1
     */
    @Parameter(property = "minimumPriority", defaultValue = "5")
    private int minimumPriority = 5;

    /**
     * Skip the PMD report generation. Most useful on the command line via "-Dpmd.skip=true".
     *
     * @since 2.1
     */
    @Parameter(property = "pmd.skip", defaultValue = "false")
    private boolean skip;

    /**
     * The PMD rulesets to use. See the
     * <a href="https://pmd.github.io/latest/pmd_rules_java.html">Stock Java Rulesets</a> for a
     * list of available rules.
     * Defaults to a custom ruleset provided by this maven plugin
     * (<code>/rulesets/java/maven-pmd-plugin-default.xml</code>).
     */
    @Parameter
    String[] rulesets = new String[] {"/rulesets/java/maven-pmd-plugin-default.xml"};

    /**
     * Controls whether the project's compile/test classpath should be passed to PMD to enable its type resolution
     * feature.
     *
     * @since 3.0
     */
    @Parameter(property = "pmd.typeResolution", defaultValue = "true")
    private boolean typeResolution;

    /**
     * Controls whether PMD will track benchmark information.
     *
     * @since 3.1
     */
    @Parameter(property = "pmd.benchmark", defaultValue = "false")
    private boolean benchmark;

    /**
     * Benchmark output filename.
     *
     * @since 3.1
     */
    @Parameter(property = "pmd.benchmarkOutputFilename", defaultValue = "${project.build.directory}/pmd-benchmark.txt")
    private String benchmarkOutputFilename;

    /**
     * Source level marker used to indicate whether a RuleViolation should be suppressed. If it is not set, PMD's
     * default will be used, which is <code>NOPMD</code>. See also <a
     * href="https://pmd.github.io/latest/pmd_userdocs_suppressing_warnings.html">PMD &#x2013; Suppressing warnings</a>.
     *
     * @since 3.4
     */
    @Parameter(property = "pmd.suppressMarker")
    private String suppressMarker;

    /**
     * per default pmd executions error are ignored to not break the whole
     *
     * @since 3.1
     */
    @Parameter(property = "pmd.skipPmdError", defaultValue = "true")
    private boolean skipPmdError;

    /**
     * Enables the analysis cache, which speeds up PMD. This
     * requires a cache file, that contains the results of the last
     * PMD run. Thus the cache is only effective, if this file is
     * not cleaned between runs.
     *
     * @since 3.8
     */
    @Parameter(property = "pmd.analysisCache", defaultValue = "false")
    private boolean analysisCache;

    /**
     * The location of the analysis cache, if it is enabled.
     * This file contains the results of the last PMD run and must not be cleaned
     * between consecutive PMD runs. Otherwise the cache is not in use.
     * If the file doesn't exist, PMD executes as if there is no cache enabled and
     * all files are analyzed. Otherwise only changed files will be analyzed again.
     *
     * @since 3.8
     */
    @Parameter(property = "pmd.analysisCacheLocation", defaultValue = "${project.build.directory}/pmd/pmd.cache")
    private String analysisCacheLocation;

    /**
     * Also render processing errors into the HTML report.
     * Processing errors are problems, that PMD encountered while executing the rules.
     * It can be parsing errors or exceptions during rule execution.
     * Processing errors indicate a bug in PMD and the information provided help in
     * reporting and fixing bugs in PMD.
     *
     * @since 3.9.0
     */
    @Parameter(property = "pmd.renderProcessingErrors", defaultValue = "true")
    private boolean renderProcessingErrors = true;

    /**
     * Also render the rule priority into the HTML report.
     *
     * @since 3.10.0
     */
    @Parameter(property = "pmd.renderRuleViolationPriority", defaultValue = "true")
    private boolean renderRuleViolationPriority = true;

    /**
     * Add a section in the HTML report, that groups the found violations by rule priority
     * in addition to grouping by file.
     *
     * @since 3.12.0
     */
    @Parameter(property = "pmd.renderViolationsByPriority", defaultValue = "true")
    private boolean renderViolationsByPriority = true;

    /**
     * Add a section in the HTML report that lists the suppressed violations.
     *
     * @since 3.17.0
     */
    @Parameter(property = "pmd.renderSuppressedViolations", defaultValue = "true")
    private boolean renderSuppressedViolations = true;

    /**
     * Before PMD is executed, the configured rulesets are resolved and copied into this directory.
     * <p>Note: Before 3.13.0, this was by default ${project.build.directory}.
     *
     * @since 3.13.0
     */
    @Parameter(property = "pmd.rulesetsTargetDirectory", defaultValue = "${project.build.directory}/pmd/rulesets")
    private File rulesetsTargetDirectory;

    /**
     * Used to locate configured rulesets. The rulesets could be on the plugin
     * classpath or in the local project file system.
     */
    @Component
    private ResourceManager locator;

    @Component
    private DependencyResolver dependencyResolver;

    /**
     * Internationalization component
     */
    @Component
    private I18N i18n;

    /**
     * Contains the result of the last PMD execution.
     * It might be <code>null</code> which means, that PMD
     * has not been executed yet.
     */
    private PmdResult pmdResult;

    /** {@inheritDoc} */
    public String getName(Locale locale) {
        return getI18nString(locale, "name");
    }

    /** {@inheritDoc} */
    public String getDescription(Locale locale) {
        return getI18nString(locale, "description");
    }

    /**
     * @param locale The locale
     * @param key The key to search for
     * @return The text appropriate for the locale.
     */
    protected String getI18nString(Locale locale, String key) {
        return i18n.getString("pmd-report", locale, "report.pmd." + key);
    }

    /**
     * Configures the PMD rulesets to be used directly.
     * Note: Usually the rulesets are configured via the property.
     *
     * @param rulesets the PMD rulesets to be used.
     * @see #rulesets
     */
    public void setRulesets(String[] rulesets) {
        this.rulesets = Arrays.copyOf(rulesets, rulesets.length);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void executeReport(Locale locale) throws MavenReportException {
        ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

            PmdReportRenderer r = new PmdReportRenderer(
                    getLog(),
                    getSink(),
                    i18n,
                    locale,
                    filesToProcess,
                    pmdResult.getViolations(),
                    renderRuleViolationPriority,
                    renderViolationsByPriority,
                    isAggregator());
            if (renderSuppressedViolations) {
                r.setSuppressedViolations(pmdResult.getSuppressedViolations());
            }
            if (renderProcessingErrors) {
                r.setProcessingErrors(pmdResult.getErrors());
            }

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

    @Override
    public boolean canGenerateReport() {
        if (skip) {
            getLog().info("Skipping PMD execution");
            return false;
        }

        boolean result = super.canGenerateReport();
        if (result) {
            try {
                executePmd();
                if (skipEmptyReport) {
                    result = pmdResult.hasViolations();
                    if (!result) {
                        getLog().debug("Skipping report since skipEmptyReport is true and "
                                + "there are no PMD violations.");
                    }
                }
            } catch (MavenReportException e) {
                throw new RuntimeException(e);
            }
        }
        return result;
    }

    private void executePmd() throws MavenReportException {
        if (pmdResult != null) {
            // PMD has already been run
            getLog().debug("PMD has already been run - skipping redundant execution.");
            return;
        }

        try {
            filesToProcess = getFilesToProcess();

            if (filesToProcess.isEmpty() && !"java".equals(language)) {
                getLog().warn("No files found to process. Did you add your additional source folders like javascript?"
                        + " (see also build-helper-maven-plugin)");
            }
        } catch (IOException e) {
            throw new MavenReportException("Can't get file list", e);
        }

        PmdRequest request = new PmdRequest();
        request.setLanguageAndVersion(language, targetJdk);
        request.setRulesets(resolveRulesets());
        request.setAuxClasspath(typeResolution ? determineAuxClasspath() : null);
        request.setSourceEncoding(getInputEncoding());
        request.addFiles(filesToProcess.keySet());
        request.setMinimumPriority(minimumPriority);
        request.setSuppressMarker(suppressMarker);
        request.setBenchmarkOutputLocation(benchmark ? benchmarkOutputFilename : null);
        request.setAnalysisCacheLocation(analysisCache ? analysisCacheLocation : null);
        request.setExcludeFromFailureFile(excludeFromFailureFile);

        request.setTargetDirectory(targetDirectory.getAbsolutePath());
        request.setOutputEncoding(getOutputEncoding());
        request.setFormat(format);
        request.setShowPmdLog(showPmdLog);
        request.setSkipPmdError(skipPmdError);
        request.setIncludeXmlInSite(includeXmlInSite);
        request.setReportOutputDirectory(getReportOutputDirectory().getAbsolutePath());
        request.setLogLevel(determineCurrentRootLogLevel());

        Toolchain tc = getToolchain();
        if (tc != null) {
            getLog().info("Toolchain in maven-pmd-plugin: " + tc);
            String javaExecutable = tc.findTool("java"); // NOI18N
            request.setJavaExecutable(javaExecutable);
        }

        getLog().info("PMD version: " + AbstractPmdReport.getPmdVersion());
        pmdResult = PmdExecutor.execute(request);
    }

    /**
     * Resolves the configured rulesets and copies them as files into the {@link #rulesetsTargetDirectory}.
     *
     * @return comma separated list of absolute file paths of ruleset files
     * @throws MavenReportException if a ruleset could not be found
     */
    private List<String> resolveRulesets() throws MavenReportException {
        // configure ResourceManager - will search for urls (URLResourceLoader) and files in various directories:
        // in the directory of the current project's pom file - note: extensions might replace the pom file on the fly
        locator.addSearchPath(
                FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath());
        // in the current project's directory
        locator.addSearchPath(FileResourceLoader.ID, project.getBasedir().getAbsolutePath());
        // in the base directory - that's the directory of the initial pom requested to build,
        // e.g. the root of a multi module build
        locator.addSearchPath(FileResourceLoader.ID, session.getRequest().getBaseDirectory());
        locator.setOutputDirectory(rulesetsTargetDirectory);

        String[] sets = new String[rulesets.length];
        try {
            for (int idx = 0; idx < rulesets.length; idx++) {
                String set = rulesets[idx];
                getLog().debug("Preparing ruleset: " + set);
                String rulesetFilename = determineRulesetFilename(set);
                File ruleset = locator.getResourceAsFile(rulesetFilename, getLocationTemp(set));
                if (null == ruleset) {
                    throw new MavenReportException("Could not resolve " + set);
                }
                sets[idx] = ruleset.getAbsolutePath();
            }
        } catch (ResourceNotFoundException | FileResourceCreationException e) {
            throw new MavenReportException(e.getMessage(), e);
        }
        return Arrays.asList(sets);
    }

    private String determineRulesetFilename(String ruleset) {
        String result = ruleset.trim();
        String lowercase = result.toLowerCase(Locale.ROOT);
        if (lowercase.startsWith("http://") || lowercase.startsWith("https://") || lowercase.endsWith(".xml")) {
            return result;
        }

        // assume last part is a single rule, e.g. myruleset.xml/SingleRule
        if (result.indexOf('/') > -1) {
            String rulesetFilename = result.substring(0, result.lastIndexOf('/'));
            if (rulesetFilename.toLowerCase(Locale.ROOT).endsWith(".xml")) {
                return rulesetFilename;
            }
        }
        // maybe a built-in ruleset name, e.g. java-design -> rulesets/java/design.xml
        int dashIndex = lowercase.indexOf('-');
        if (dashIndex > -1 && lowercase.indexOf('-', dashIndex + 1) == -1) {
            String language = result.substring(0, dashIndex);
            String rulesetName = result.substring(dashIndex + 1);
            return "rulesets/" + language + "/" + rulesetName + ".xml";
        }
        // fallback - no change of the given ruleset specifier
        return result;
    }

    /**
     * Convenience method to get the location of the specified file name.
     *
     * @param name the name of the file whose location is to be resolved
     * @return a String that contains the absolute file name of the file
     */
    protected String getLocationTemp(String name) {
        String loc = name;
        if (loc.indexOf('/') != -1) {
            loc = loc.substring(loc.lastIndexOf('/') + 1);
        }
        if (loc.indexOf('\\') != -1) {
            loc = loc.substring(loc.lastIndexOf('\\') + 1);
        }

        // MPMD-127 in the case that the rules are defined externally on a url
        // we need to replace some special url characters that cannot be
        // used in filenames on disk or produce ackward filenames.
        // replace all occurrences of the following characters: ? : & = %
        loc = loc.replaceAll("[\\?\\:\\&\\=\\%]", "_");

        if (!loc.endsWith(".xml")) {
            loc = loc + ".xml";
        }

        getLog().debug("Before: " + name + " After: " + loc);
        return loc;
    }

    private String determineAuxClasspath() throws MavenReportException {
        try {
            List<String> classpath = new ArrayList<>();
            if (isAggregator()) {
                List<String> dependencies = new ArrayList<>();

                // collect exclusions for projects within the reactor
                // if module a depends on module b and both are in the reactor
                // then we don't want to resolve the dependency as an artifact.
                List<String> exclusionPatterns = new ArrayList<>();
                for (MavenProject localProject : getAggregatedProjects()) {
                    exclusionPatterns.add(localProject.getGroupId() + ":" + localProject.getArtifactId());
                }
                TransformableFilter filter = new AndFilter(Arrays.asList(
                        new ExclusionsFilter(exclusionPatterns),
                        includeTests
                                ? ScopeFilter.including("compile", "provided", "test")
                                : ScopeFilter.including("compile", "provided")));

                for (MavenProject localProject : getAggregatedProjects()) {
                    ProjectBuildingRequest buildingRequest =
                            new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
                    // use any additional configured repo as well
                    buildingRequest.getRemoteRepositories().addAll(localProject.getRemoteArtifactRepositories());

                    Iterable<ArtifactResult> resolvedDependencies = dependencyResolver.resolveDependencies(
                            buildingRequest, localProject.getDependencies(), null, filter);

                    for (ArtifactResult resolvedArtifact : resolvedDependencies) {
                        dependencies.add(
                                resolvedArtifact.getArtifact().getFile().toString());
                    }

                    List<String> projectClasspath = includeTests
                            ? localProject.getTestClasspathElements()
                            : localProject.getCompileClasspathElements();

                    // Add the project's target folder first
                    classpath.addAll(projectClasspath);
                    if (!localProject.isExecutionRoot()) {
                        for (String path : projectClasspath) {
                            File pathFile = new File(path);
                            String[] children = pathFile.list();

                            if (!pathFile.exists() || (children != null && children.length == 0)) {
                                getLog().warn("The project " + localProject.getArtifactId()
                                        + " does not seem to be compiled. PMD results might be inaccurate.");
                            }
                        }
                    }
                }

                // Add the dependencies as last entries
                classpath.addAll(dependencies);

                getLog().debug("Using aggregated aux classpath: " + classpath);
            } else {
                classpath.addAll(
                        includeTests ? project.getTestClasspathElements() : project.getCompileClasspathElements());

                getLog().debug("Using aux classpath: " + classpath);
            }
            String path = StringUtils.join(classpath.iterator(), File.pathSeparator);
            return path;
        } catch (Exception e) {
            throw new MavenReportException(e.getMessage(), e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getOutputName() {
        return "pmd";
    }

    /**
     * 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
     * @deprecated Use {@link PmdExecutor#createRenderer(String, String)} instead.
     */
    @Deprecated
    public final Renderer createRenderer() throws MavenReportException {
        return PmdExecutor.createRenderer(format, getOutputEncoding());
    }
}
