com.adobe.ac.maven.ncss.NcssReportMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.adobe.ac.maven.ncss.NcssReportMojo.java

Source

package com.adobe.ac.maven.ncss;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * 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.
 */

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.doxia.site.renderer.SiteRenderer;
import org.codehaus.plexus.util.DirectoryScanner;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

/**
 * Goal which touches a timestamp file.
 *
 * @goal report
 */
public class NcssReportMojo extends AbstractMavenReport {
    private static final String OUTPUT_NAME = "javancss";

    /**
     * Specifies the directory where the HTML report will be generated.
     * 
     * @parameter expression="${project.reporting.outputDirectory}"
     * @required
     * @readonly
     */
    private File outputDirectory;

    /**
     * Specifies the directory where the XML report will be generated.
     * 
     * @parameter default-value="${project.build.directory}"
     * @required
     */
    private File xmlOutputDirectory;

    /**
     * Specifies the location of the source files to be used.
     * 
     * @parameter expression="${project.build.sourceDirectory}"
     * @required
     * @readonly
     */
    private File sourceDirectory;

    /**
     * Specifies the maximum number of lines to take into account into the reports.
     * 
     * @parameter default-value="30"
     * @required
     */
    private int lineThreshold;

    /**
     * Specified the name of the temporary file generated by Javancss prior report generation.
     * 
     * @parameter default-value="javancss-raw-report.xml"
     * @required
     */
    private String tempFileName;

    /**
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * @parameter expression="${component.org.codehaus.doxia.site.renderer.SiteRenderer}"
     * @required
     * @readonly
     */
    private SiteRenderer siteRenderer;

    /**
     * The projects in the reactor for aggregation report.
     * 
     * @parameter expression="${reactorProjects}"
     * @readonly
     */
    private List<MavenProject> reactorProjects;

    /**
     * List of ant-style patterns used to specify the java sources that should be included when running JavaNCSS.
     * If this is not specified, all .java files in the project source directories are included.
     * 
     * @parameter
     */
    private String[] includes;

    /**
     * List of ant-style patterns used to specify the java sources that should be excluded when running JavaNCSS.
     * If this is not specified, no files in the project source directories are excluded.
     * 
     * @parameter
     */
    private String[] excludes;

    /**
     * Encoding to use when reading the javancss xml file. This should match the encoding used in the source files that javancss is parsing.
     * It defaults to the <em>System.getProperty("file.encoding");</em>, but you can override it.
     * 
     * @parameter
     */
    private String forceEncoding;

    /**
     * @see org.apache.maven.reporting.MavenReport#execute(java.util.Locale)
     */
    public void executeReport(final Locale locale) throws MavenReportException {
        if (getLog().isDebugEnabled()) {
            getLog().debug("NcssReportMojo.executeReport()");
        }

        if (!canGenerateReport()) {
            throw new MavenReportException("Cannot generate report ");
        }

        if (canGenerateSingleReport()) {
            generateSingleReport(locale);
        }
        if (canGenerateAggregateReport()) {
            generateAggregateReport(locale);
        }
    }

    private void generateAggregateReport(final Locale locale) throws MavenReportException {
        // All this work just to get "target" so that we can scan the filesystem for
        // child javancss xml files...
        final String basedir = project.getBasedir().toString();
        final String output = xmlOutputDirectory.toString();
        if (getLog().isDebugEnabled()) {
            getLog().debug("basedir: " + basedir);
            getLog().debug("output: " + output);
        }
        String relative = null;
        if (output.startsWith(basedir)) {
            relative = output.substring(basedir.length() + 1);
        } else {
            getLog().error("Unable to aggregate report because I can't "
                    + "determine the relative location of the XML report");
            return;
        }
        getLog().debug("relative: " + relative);
        final List<ModuleReport> reports = new ArrayList<ModuleReport>();
        for (final Iterator<MavenProject> it = reactorProjects.iterator(); it.hasNext();) {
            final MavenProject child = (MavenProject) it.next();
            final File xmlReport = new File(child.getBasedir() + File.separator + relative, tempFileName);
            if (xmlReport.exists()) {
                reports.add(new ModuleReport(child, loadDocument(xmlReport)));
            } else {
                getLog().debug("xml file not found: " + xmlReport);
            }
        }
        getLog().debug("Aggregating " + reports.size() + " JavaNCSS reports");

        // parse the freshly generated file and write the report
        final NcssAggregateReportGenerator reportGenerator = new NcssAggregateReportGenerator(getSink(),
                getBundle(locale), getLog());
        reportGenerator.doReport(locale, reports, lineThreshold);
    }

    private boolean isIncludeExcludeUsed() {
        return ((excludes != null) || (includes != null));
    }

    private void generateSingleReport(final Locale locale) throws MavenReportException {
        if (getLog().isDebugEnabled()) {
            getLog().debug("Calling NCSSExecuter with src    : " + sourceDirectory);
            getLog().debug("Calling NCSSExecuter with output : " + buildOutputFile());
            getLog().debug("Calling NCSSExecuter with includes : " + includes);
            getLog().debug("Calling NCSSExecuter with excludes : " + excludes);
        }
        // run javaNCss and produce an temp xml file
        NcssExecuter ncssExecuter;
        if (isIncludeExcludeUsed()) {
            ncssExecuter = new NcssExecuter(scanForSources(), buildOutputFile());
        } else {
            ncssExecuter = new NcssExecuter(sourceDirectory, buildOutputFile());
        }

        ncssExecuter.execute();
        if (!isTempReportGenerated()) {
            throw new MavenReportException("Can't process temp ncss xml file.");
        }
        // parse the freshly generated file and write the report
        final NcssReportGenerator reportGenerator = new NcssReportGenerator(getSink(), getBundle(locale), getLog());
        reportGenerator.doReport(loadDocument(), lineThreshold);
    }

    /**
     * Load the xml file generated by javancss.
     * It first tries to load it as is.
     * If this fails it tries to load it with the forceEncoding parameter which defaults to the system property "file.encoding".
     * If this latter fails, it throws a MavenReportException.
     */
    private Document loadDocument(final File file) throws MavenReportException {
        try {
            return loadDocument(file, null);
        } catch (DocumentException ignored) {
            if (forceEncoding == null) {
                forceEncoding = System.getProperty("file.encoding");
            }
            getLog().debug("Loading document without specifying encoding failed, trying with forceEncoding = ["
                    + forceEncoding + "]");
            try {
                return loadDocument(file, forceEncoding);
            } catch (DocumentException de) {

                throw new MavenReportException(de.getMessage(), de);
            }
        }
    }

    private Document loadDocument(final File file, final String encoding) throws DocumentException {
        final SAXReader saxReader = new SAXReader();
        if (encoding != null) {
            saxReader.setEncoding(encoding);
            getLog().debug("Loading xml file with encoding : " + encoding);
        }
        return saxReader.read(file);
    }

    private Document loadDocument() throws MavenReportException {
        return loadDocument(buildOutputFile());
    }

    /**
     * Check that the expected temporary file generated by JavaNCSS exists.
     * 
     * @return <code>true</code> if the temporary report exists, <code>false</code> otherwise.
     */
    private boolean isTempReportGenerated() {
        return buildOutputFile().exists();
    }

    /**
     * @see org.apache.maven.reporting.MavenReport#canGenerateReport()
     */
    public boolean canGenerateReport() {
        return (canGenerateSingleReport() || canGenerateAggregateReport());
    }

    private boolean canGenerateAggregateReport() {
        boolean result = false;

        if (project.getModules().size() == 0) {
            // no child modules
            result = false;
        } else if (sourceDirectory != null && sourceDirectory.exists()) {
            // only non-source projects can aggregate
            final Collection<File> sources = scanForSources();
            result = sources == null || sources.isEmpty();
        } else {
            result = true;
        }

        return result;
    }

    private boolean canGenerateSingleReport() {
        boolean result = false;

        if (sourceDirectory == null || !sourceDirectory.exists()) {
            result = false;
        } else {
            // now that we know we have a valid existing source directory
            // we check if any *.as files are existing.
            final Collection<File> sources = scanForSources();
            result = (sources != null) && (!sources.isEmpty());
        }

        return result;
    }

    /**
     * gets a list of all files in the source directory.
     * 
     * @return the list of all files in the source directory;
     */
    private Collection<File> scanForSources() {
        final String[] defaultIncludes = { "**\\*.as" };
        final DirectoryScanner scanner = new DirectoryScanner();
        if (includes == null) {
            scanner.setIncludes(defaultIncludes);
        } else {
            scanner.setIncludes(includes);
        }
        if (excludes != null) {
            scanner.setExcludes(excludes);
        }
        scanner.setBasedir(sourceDirectory);
        getLog().debug("Scanning base directory " + sourceDirectory);
        scanner.scan();
        final int maxFiles = scanner.getIncludedFiles().length;
        final Collection<File> result = new ArrayList<File>(maxFiles);
        for (int i = 0; i < maxFiles; i++) {
            result.add(new File(sourceDirectory + File.separator + scanner.getIncludedFiles()[i]));
        }
        return result;
    }

    /**
     * Build a path for the output filename.
     * 
     * @return A String representation of the output filename.
     */
    /* package */File buildOutputFile() {
        return new File(getXmlOutputDirectory() + File.separator + tempFileName);
    }

    /**
     * @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale)
     */
    public String getName(final Locale locale) {
        return getBundle(locale).getString("report.ncss.name");
    }

    /**
     * @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale)
     */
    public String getDescription(final Locale locale) {
        return getBundle(locale).getString("report.ncss.description");
    }

    /**
     * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
     */
    protected String getOutputDirectory() {
        return outputDirectory.getAbsolutePath();
    }

    protected String getXmlOutputDirectory() {
        return xmlOutputDirectory.getAbsolutePath();
    }

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

    /**
     * @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer()
     */
    protected SiteRenderer getSiteRenderer() {
        return siteRenderer;
    }

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

    /**
     * Getter for the source directory
     * 
     * @return the source directory as a File object.
     */
    protected File getSourceDirectory() {
        return sourceDirectory;
    }

    // helper to retrieve the right bundle
    private static ResourceBundle getBundle(final Locale locale) {
        return ResourceBundle.getBundle("as3ncss", locale, NcssReportMojo.class.getClassLoader());
    }
}