package org.apache.rat.mp;

/*
 * 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.
 */

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.xml.transform.TransformerConfigurationException;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.rat.Defaults;
import org.apache.rat.Report;
import org.apache.rat.ReportConfiguration;
import org.apache.rat.analysis.IHeaderMatcher;
import org.apache.rat.analysis.util.HeaderMatcherMultiplexer;
import org.apache.rat.api.RatException;
import org.apache.rat.license.ILicenseFamily;
import org.apache.rat.report.IReportable;
import org.apache.rat.report.claim.ClaimStatistic;
import org.codehaus.plexus.util.DirectoryScanner;

/**
 * Abstract base class for Mojos, which are running Rat.
 */
public abstract class AbstractRatMojo extends AbstractMojo {
	/**
	 * The Maven specific default excludes.
	 */
	static final List<String> MAVEN_DEFAULT_EXCLUDES = Collections
			.unmodifiableList(Arrays.asList("target/**/*", //
					"cobertura.ser", //
					"release.properties", //
					"pom.xml.releaseBackup"));

	/**
	 * The Eclipse specific default excludes.
	 */
	static final List<String> ECLIPSE_DEFAULT_EXCLUDES = Collections
			.unmodifiableList(Arrays.asList(".classpath",//
					".project", //
					".settings/**/*"));

	/**
	 * The IDEA specific default excludes.
	 */
	static final List<String> IDEA_DEFAULT_EXCLUDES = Collections
			.unmodifiableList(Arrays.asList(//
					"*.iml", //
					"*.ipr", //
					"*.iws", //
					".idea/**/*"));

	/**
	 * The base directory, in which to search for files.
	 *
	 */
	@Parameter(property = "rat.basedir", defaultValue = "${basedir}", required = true)
	protected File basedir;

	/**
	 * Specifies the licenses to accept. Deprecated, use {@link #licenses}
	 * instead.
	 *
	 * @deprecated Use {@link #licenses} instead.
	 */
	@Deprecated
	@Parameter
	private HeaderMatcherSpecification[] licenseMatchers;

	/**
	 * Specifies the licenses to accept. By default, these are added to the
	 * default licenses, unless you set {@link #addDefaultLicenseMatchers} to
	 * true.
	 *
	 * @since 0.8
	 */
	@Parameter
	private IHeaderMatcher[] licenses;

	/**
	 * The set of approved license family names.
	 * 
	 * @deprecated Use {@link #licenseFamilies} instead.
	 */
	@Deprecated
	private LicenseFamilySpecification[] licenseFamilyNames;

	/**
	 * Specifies the license families to accept.
	 *
	 * @since 0.8
	 */
	@Parameter
	private ILicenseFamily[] licenseFamilies;

	/**
	 * Whether to add the default list of license matchers.
	 *
	 */
	@Parameter(property = "rat.addDefaultLicenseMatchers", defaultValue = "true")
	private boolean addDefaultLicenseMatchers;

	/**
	 * Specifies files, which are included in the report. By default, all files
	 * are included.
	 *
	 */
	@Parameter
	private String[] includes;

	/**
	 * Specifies files, which are excluded in the report. By default, no files
	 * are excluded.
	 *
	 */
	@Parameter
	private String[] excludes;

	/**
	 * Whether to use the default excludes when scanning for files. The default
	 * excludes are:
	 * <ul>
	 * <li>meta data files for version control systems</li>
	 * <li>temporary files used by Maven, see <a
	 * href="#useMavenDefaultExcludes">useMavenDefaultExcludes</a></li>
	 * <li>configuration files for Eclipse, see <a
	 * href="#useEclipseDefaultExcludes">useEclipseDefaultExcludes</a></li>
	 * <li>configuration files for IDEA, see <a
	 * href="#useIdeaDefaultExcludes">useIdeaDefaultExcludes</a></li>
	 * </ul>
	 */
	@Parameter(property = "rat.useDefaultExcludes", defaultValue = "true")
	private boolean useDefaultExcludes;

	/**
	 * Whether to use the Maven specific default excludes when scanning for
	 * files. Maven specific default excludes are given by the constant
	 * MAVEN_DEFAULT_EXCLUDES: The <code>target</code> directory, the
	 * <code>cobertura.ser</code> file, and so on.
	 */
	@Parameter(property = "rat.useMavenDefaultExcludes", defaultValue = "true")
	private boolean useMavenDefaultExcludes;

	/**
	 * Whether to use the Eclipse specific default excludes when scanning for
	 * files. Eclipse specific default excludes are given by the constant
	 * ECLIPSE_DEFAULT_EXCLUDES: The <code>.classpath</code> and
	 * <code>.project</code> files, the <code>.settings</code> directory, and so
	 * on.
	 */
	@Parameter(property = "rat.useEclipseDefaultExcludes", defaultValue = "true")
	private boolean useEclipseDefaultExcludes;

	/**
	 * Whether to use the IDEA specific default excludes when scanning for
	 * files. IDEA specific default excludes are given by the constant
	 * IDEA_DEFAULT_EXCLUDES: The <code>*.iml</code>, <code>*.ipr</code> and
	 * <code>*.iws</code> files and the <code>.idea</code> directory.
	 */
	@Parameter(property = "rat.useIdeaDefaultExcludes", defaultValue = "true")
	private boolean useIdeaDefaultExcludes;

	/**
	 * Whether to exclude subprojects. This is recommended, if you want a
	 * separate apache-rat-plugin report for each subproject.
	 *
	 */
	@Parameter(property = "rat.excludeSubprojects", defaultValue = "true")
	private boolean excludeSubProjects;

	/**
     * 
     */
	@Parameter(name = "project", readonly = true)
	private MavenProject project;

	/**
	 * @return Returns the Maven project.
	 */
	protected MavenProject getProject() {
		return project;
	}

	/**
	 * Returns the set of {@link IHeaderMatcher header matchers} to use.
	 *
	 * @throws MojoFailureException
	 *             An error in the plugin configuration was detected.
	 * @throws MojoExecutionException
	 *             An error occurred while calculating the result.
	 * @return Array of license matchers to use
	 */
	protected IHeaderMatcher[] getLicenseMatchers()
			throws MojoFailureException, MojoExecutionException {
		final List<IHeaderMatcher> list = new ArrayList<IHeaderMatcher>();
		if (licenses != null) {
			list.addAll(Arrays.asList(licenses));
		}

		if (licenseMatchers != null) {
			for (final HeaderMatcherSpecification spec : licenseMatchers) {
				final String className = spec.getClassName();
				final IHeaderMatcher headerMatcher = newInstance(
						IHeaderMatcher.class, className);
				list.add(headerMatcher);
			}
		}

		if (addDefaultLicenseMatchers) {
			list.addAll(Arrays.asList(Defaults.DEFAULT_MATCHERS));
		}
		return list.toArray(new IHeaderMatcher[list.size()]);
	}

	private <T> T newInstance(final Class<T> clazz, final String className)
			throws MojoExecutionException, MojoFailureException {
		try {
			final ClassLoader cl = Thread.currentThread()
					.getContextClassLoader();
			@SuppressWarnings("unchecked")
			// incorrect cast will be caught below
			final T o = (T) cl.loadClass(className).newInstance();

			if (!clazz.isAssignableFrom(o.getClass())) {
				throw new MojoFailureException("The class "
						+ o.getClass().getName() + " does not implement "
						+ clazz.getName());
			}
			return o;
		} catch (InstantiationException e) {
			throw new MojoExecutionException("Failed to instantiate class "
					+ className + ": " + e.getMessage(), e);
		} catch (ClassCastException e) {
			throw new MojoExecutionException("The class " + className
					+ " is not implementing " + clazz.getName() + ": "
					+ e.getMessage(), e);
		} catch (IllegalAccessException e) {
			throw new MojoExecutionException("Illegal access to class "
					+ className + ": " + e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			throw new MojoExecutionException("Class " + className
					+ " not found: " + e.getMessage(), e);
		}
	}

	/**
	 * Adds the given string array to the list.
	 *
	 * @param pList
	 *            The list to which the array elements are being added.
	 * @param pArray
	 *            The strings to add to the list.
	 */
	private static void add(List<String> pList, String[] pArray) {
		if (pArray != null) {
			Collections.addAll(pList, pArray);
		}
	}

	/**
	 * Creates an iterator over the files to check.
	 *
	 * @return A container of files, which are being checked.
	 */
	protected IReportable getResources() {
		final DirectoryScanner ds = new DirectoryScanner();
		ds.setBasedir(basedir);
		setExcludes(ds);
		setIncludes(ds);
		ds.scan();
		whenDebuggingLogExcludedFiles(ds);
		final String[] files = ds.getIncludedFiles();
		logAboutIncludedFiles(files);
		try {
			return new FilesReportable(basedir, files);
		} catch (IOException e) {
			throw new UndeclaredThrowableException(e);
		}
	}

	private void logAboutIncludedFiles(final String[] files) {
		if (files.length == 0) {
			getLog().warn("No resources included.");
		} else {
			getLog().info(
					files.length
							+ " resources included (use -debug for more details)");
			if (getLog().isDebugEnabled()) {
				for (String resource : files) {
					getLog().debug(" - included " + resource);
				}
			}
		}
	}

	private void whenDebuggingLogExcludedFiles(final DirectoryScanner ds) {
		if (getLog().isDebugEnabled()) {
			final String[] excludedFiles = ds.getExcludedFiles();
			if (excludedFiles.length == 0) {
				getLog().debug("No excluded resources.");
			} else {
				getLog().debug(
						"Excluded " + excludedFiles.length + " resources:");
				for (final String resource : excludedFiles) {
					getLog().debug(" - excluded " + resource);
				}
			}
		}
	}

	private void setIncludes(DirectoryScanner ds) {
		if (includes != null) {
			ds.setIncludes(includes);
		}
	}

	private void setExcludes(DirectoryScanner ds) {
		final List<String> excludeList = buildDefaultExclusions();
		if (excludes == null || excludes.length == 0) {
			getLog().info("No excludes explicitly specified.");
		} else {
			for (String exclude : excludes) {
				getLog().info("Exclude: " + exclude);
			}
		}
		add(excludeList, excludes);
		if (!excludeList.isEmpty()) {
			String[] allExcludes = excludeList.toArray(new String[excludeList
					.size()]);
			ds.setExcludes(allExcludes);
		}
	}

	private List<String> buildDefaultExclusions() {
		final List<String> results = new ArrayList<String>();

		addPlexusDefaults(results);

		addMavenDefaults(results);

		addEclipseDefaults(results);

		addIdeaDefaults(results);

		if (excludeSubProjects && project != null
				&& project.getModules() != null) {
			for (Object o : project.getModules()) {
				String moduleSubPath = (String) o;
				results.add(moduleSubPath + "/**/*");
			}
		}

		getLog().debug("Finished creating list of implicit excludes.");
		if (results.isEmpty()) {
			getLog().info("No excludes implicitly specified.");
		} else {
			getLog().info(
					results.size()
							+ " implicit excludes (use -debug for more details).");
			for (final String exclude : results) {
				getLog().debug("Implicit exclude: " + exclude);
			}
		}

		return results;
	}

	private void addPlexusDefaults(final List<String> excludeList1) {
		if (useDefaultExcludes) {
			getLog().debug("Adding plexus default exclusions...");
			Collections.addAll(excludeList1, DirectoryScanner.DEFAULTEXCLUDES);
		} else {
			getLog().debug(
					"rat.useDefaultExcludes set to false. "
							+ "Plexus default exclusions will not be added");
		}
	}

	private void addMavenDefaults(final List<String> excludeList1) {
		if (useMavenDefaultExcludes) {
			getLog().debug(
					"Adding exclusions often needed by Maven projects...");
			excludeList1.addAll(MAVEN_DEFAULT_EXCLUDES);
		} else {
			getLog().debug(
					"rat.useMavenDefaultExcludes set to false. "
							+ "Exclusions often needed by Maven projects will not be added.");
		}
	}

	private void addEclipseDefaults(final List<String> excludeList1) {
		if (useEclipseDefaultExcludes) {
			getLog().debug(
					"Adding exclusions often needed by projects "
							+ "developed in Eclipse...");
			excludeList1.addAll(ECLIPSE_DEFAULT_EXCLUDES);
		} else {
			getLog().debug(
					"rat.useEclipseDefaultExcludes set to false. "
							+ "Exclusions often needed by projects developed in "
							+ "Eclipse will not be added.");
		}
	}

	private void addIdeaDefaults(final List<String> excludeList1) {
		if (useIdeaDefaultExcludes) {
			getLog().debug(
					"Adding exclusions often needed by projects "
							+ "developed in IDEA...");
			excludeList1.addAll(IDEA_DEFAULT_EXCLUDES);
		} else {
			getLog().debug(
					"rat.useIdeaDefaultExcludes set to false. "
							+ "Exclusions often needed by projects developed in "
							+ "IDEA will not be added.");
		}
	}

	/**
	 * Writes the report to the given stream.
	 *
	 * @param out
	 *            The target writer, to which the report is being written.
	 * @param style
	 *            The stylesheet to use, or <code>null</code> for raw XML
	 * 
	 * @return the current statistic.
	 * 
	 * @throws MojoFailureException
	 *             An error in the plugin configuration was detected.
	 * @throws MojoExecutionException
	 *             Another error occurred while creating the report.
	 */
	protected ClaimStatistic createReport(Writer out, InputStream style)
			throws MojoExecutionException, MojoFailureException {
		final ReportConfiguration configuration = getConfiguration();
		try {
			if (style != null) {
				return Report.report(out, getResources(), style, configuration);
			} else {
				return Report.report(getResources(), out, configuration);
			}
		} catch (TransformerConfigurationException e) {
			throw new MojoExecutionException(e.getMessage(), e);
		} catch (IOException e) {
			throw new MojoExecutionException(e.getMessage(), e);
		} catch (InterruptedException e) {
			throw new MojoExecutionException(e.getMessage(), e);
		} catch (RatException e) {
			throw new MojoExecutionException(e.getMessage(), e);
		}
	}

	protected ReportConfiguration getConfiguration()
			throws MojoFailureException, MojoExecutionException {
		final ReportConfiguration configuration = new ReportConfiguration();
		configuration.setHeaderMatcher(new HeaderMatcherMultiplexer(
				getLicenseMatchers()));
		configuration.setApprovedLicenseNames(getApprovedLicenseNames());
		return configuration;
	}

	private ILicenseFamily[] getApprovedLicenseNames()
			throws MojoExecutionException, MojoFailureException {
		final List<ILicenseFamily> list = new ArrayList<ILicenseFamily>();
		if (licenseFamilies != null) {
			list.addAll(Arrays.asList(licenseFamilies));
		}
		if (licenseFamilyNames != null) {
			for (LicenseFamilySpecification spec : licenseFamilyNames) {
				list.add(newInstance(ILicenseFamily.class, spec.getClassName()));
			}
		}

		if (list.isEmpty()) {
			return null;
		}
		return list.toArray(new ILicenseFamily[list.size()]);
	}
}
