package org.apache.maven.plugins.checkstyle.exec;

/*
 * 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.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.model.Resource;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
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.FileUtils;
import org.codehaus.plexus.util.StringUtils;

import com.puppycrawl.tools.checkstyle.Checker;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.ConfigurationLoader.IgnoredModulesOptions;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
import com.puppycrawl.tools.checkstyle.PackageNamesLoader;
import com.puppycrawl.tools.checkstyle.PropertiesExpander;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.FilterSet;
import com.puppycrawl.tools.checkstyle.filters.SuppressionsLoader;

/**
 * @author Olivier Lamy
 * @since 2.5
 * @version $Id$
 */
@Component( role = CheckstyleExecutor.class, hint = "default", instantiationStrategy = "per-lookup" )
public class DefaultCheckstyleExecutor
    extends AbstractLogEnabled
    implements CheckstyleExecutor
{
    @Requirement( hint = "default" )
    private ResourceManager locator;
    
    @Requirement( hint = "license" )
    private ResourceManager licenseLocator;

    public CheckstyleResults executeCheckstyle( CheckstyleExecutorRequest request )
        throws CheckstyleExecutorException, CheckstyleException
    {
        if ( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "executeCheckstyle start headerLocation : " + request.getHeaderLocation() );
        }

        MavenProject project = request.getProject();

        configureResourceLocator( locator, request, null );
        
        configureResourceLocator( licenseLocator, request, request.getLicenseArtifacts() );

        // Config is less critical than License, locator can still be used.
        // configureResourceLocator( configurationLocator, request, request.getConfigurationArtifacts() );

        List<File> files;
        try
        {
            files = getFilesToProcess( request );
        }
        catch ( IOException e )
        {
            throw new CheckstyleExecutorException( "Error getting files to process", e );
        }

        final String suppressionsFilePath = getSuppressionsFilePath( request );
        FilterSet filterSet = getSuppressionsFilterSet( suppressionsFilePath );

        Checker checker = new Checker();

        // setup classloader, needed to avoid "Unable to get class information for ..." errors
        List<String> classPathStrings = new ArrayList<>();
        List<String> outputDirectories = new ArrayList<>();
        
        // stand-alone
        Collection<File> sourceDirectories = null;
        Collection<File> testSourceDirectories = request.getTestSourceDirectories();
        
        // aggregator
        Map<MavenProject, Collection<File>> sourceDirectoriesByProject = new HashMap<>();
        Map<MavenProject, Collection<File>> testSourceDirectoriesByProject = new HashMap<>();
        
        if ( request.isAggregate() )
        {
            for ( MavenProject childProject : request.getReactorProjects() )
            {
                sourceDirectories = new ArrayList<>( childProject.getCompileSourceRoots().size() );
                List<String> compileSourceRoots = childProject.getCompileSourceRoots();
                for ( String compileSourceRoot : compileSourceRoots )
                {
                    sourceDirectories.add( new File( compileSourceRoot ) );
                }
                sourceDirectoriesByProject.put( childProject, sourceDirectories );
                
                testSourceDirectories = new ArrayList<>( childProject.getTestCompileSourceRoots().size() );
                List<String> testCompileSourceRoots = childProject.getTestCompileSourceRoots();
                for ( String testCompileSourceRoot : testCompileSourceRoots )
                {
                    testSourceDirectories.add( new File( testCompileSourceRoot ) );
                }
                testSourceDirectoriesByProject.put( childProject, testSourceDirectories );
                
                prepareCheckstylePaths( request, childProject, classPathStrings, outputDirectories,
                                        sourceDirectories, testSourceDirectories );
            }
        }
        else
        {
            sourceDirectories = request.getSourceDirectories();
            prepareCheckstylePaths( request, project, classPathStrings, outputDirectories, sourceDirectories,
                                    testSourceDirectories );
        }

        final List<URL> urls = new ArrayList<>( classPathStrings.size() );

        for ( String path : classPathStrings )
        {
            try
            {
                urls.add( new File( path ).toURI().toURL() );
            }
            catch ( MalformedURLException e )
            {
                throw new CheckstyleExecutorException( e.getMessage(), e );
            }
        }

        for ( String outputDirectoryString : outputDirectories )
        {
            try
            {
                if ( outputDirectoryString != null )
                {
                    File outputDirectoryFile = new File( outputDirectoryString );
                    if ( outputDirectoryFile.exists() )
                    {
                        URL outputDirectoryUrl = outputDirectoryFile.toURI().toURL();
                        getLogger().debug( "Adding the outputDirectory " + outputDirectoryUrl.toString()
                                               + " to the Checkstyle class path" );
                        urls.add( outputDirectoryUrl );
                    }
                }
            }
            catch ( MalformedURLException e )
            {
                throw new CheckstyleExecutorException( e.getMessage(), e );
            }
        }

        URLClassLoader projectClassLoader = AccessController.doPrivileged( new PrivilegedAction<URLClassLoader>()
        {
            public URLClassLoader run()
            {
                return new URLClassLoader( urls.toArray( new URL[urls.size()] ), null );
            }
        } );

        checker.setClassLoader( projectClassLoader );

        checker.setModuleClassLoader( Thread.currentThread().getContextClassLoader() );

        if ( filterSet != null )
        {
            checker.addFilter( filterSet );
        }
        Configuration configuration = getConfiguration( request );
        checker.configure( configuration );

        AuditListener listener = request.getListener();

        if ( listener != null )
        {
            checker.addListener( listener );
        }

        if ( request.isConsoleOutput() )
        {
            checker.addListener( request.getConsoleListener() );
        }

        CheckstyleCheckerListener checkerListener = new CheckstyleCheckerListener( configuration );
        if ( request.isAggregate() )
        {
            for ( MavenProject childProject : request.getReactorProjects() )
            {
                sourceDirectories = sourceDirectoriesByProject.get( childProject );
                testSourceDirectories = testSourceDirectoriesByProject.get( childProject );
                addSourceDirectory( checkerListener, sourceDirectories,
                                    testSourceDirectories,
                                    childProject.getResources(), request );
            }
        }
        else
        {
            addSourceDirectory( checkerListener, sourceDirectories, testSourceDirectories, request.getResources(),
                                request );
        }

        checker.addListener( checkerListener );

        int nbErrors = checker.process( files );

        checker.destroy();

        if ( projectClassLoader instanceof Closeable )
        {
            try
            {
                ( ( Closeable ) projectClassLoader ).close();
            }
            catch ( IOException ex ) 
            {
                // Nothing we can do - and not detrimental to the build (save running out of file handles).
                getLogger().info( "Failed to close custom Classloader - this indicated a bug in the code.", ex );
            }
        }

        if ( request.getStringOutputStream() != null )
        {
            String message = request.getStringOutputStream().toString().trim();

            if ( message.length() > 0 )
            {
                getLogger().info( message );
            }
        }

        if ( nbErrors > 0 )
        {
            StringBuilder message = new StringBuilder( "There " );
            if ( nbErrors == 1 )
            {
                message.append( "is" );
            }
            else
            {
                message.append( "are" );
            }
            message.append( " " );
            message.append( nbErrors );
            message.append( " error" );
            if ( nbErrors != 1 )
            {
                message.append( "s" );
            }
            message.append( " reported by Checkstyle" );
            String version = getCheckstyleVersion();
            if ( version != null )
            {
                message.append( " " );
                message.append( version );
            }
            message.append( " with " );
            message.append( request.getConfigLocation() );
            message.append( " ruleset." );

            if ( request.isFailsOnError() )
            {
                // TODO: should be a failure, not an error. Report is not meant to
                // throw an exception here (so site would
                // work regardless of config), but should record this information
                throw new CheckstyleExecutorException( message.toString() );
            }
            else
            {
                getLogger().info( message.toString() );
            }
        }

        return checkerListener.getResults();
    }

    protected void addSourceDirectory( CheckstyleCheckerListener sinkListener, Collection<File> sourceDirectories,
                                       Collection<File> testSourceDirectories, List<Resource> resources,
                                       CheckstyleExecutorRequest request )
    {
        if ( sourceDirectories != null )
        {
            for ( File sourceDirectory : sourceDirectories )
            {
                if ( sourceDirectory.exists() )
                {
                    sinkListener.addSourceDirectory( sourceDirectory );
                }
            }
        }

        if ( request.isIncludeTestSourceDirectory() && ( testSourceDirectories != null ) )
        {
            for ( File testSourceDirectory : testSourceDirectories )
            {
                if ( testSourceDirectory.isDirectory() )
                {
                    sinkListener.addSourceDirectory( testSourceDirectory );
                }
            }
        }

        if ( resources != null )
        {
            for ( Resource resource : resources )
            {
                if ( resource.getDirectory() != null )
                {
                    File resourcesDirectory = new File( resource.getDirectory() );
                    if ( resourcesDirectory.exists() && resourcesDirectory.isDirectory() )
                    {
                        sinkListener.addSourceDirectory( resourcesDirectory );
                        getLogger().debug( "Added '" + resourcesDirectory.getAbsolutePath()
                                + "' as a source directory." );
                    }
                }
            }
        }
    }

    public Configuration getConfiguration( CheckstyleExecutorRequest request )
        throws CheckstyleExecutorException
    {
        try
        {
            // Checkstyle will always use the context classloader in order
            // to load resources (dtds),
            // so we have to fix it
            ClassLoader checkstyleClassLoader = PackageNamesLoader.class.getClassLoader();
            Thread.currentThread().setContextClassLoader( checkstyleClassLoader );
            String configFile = getConfigFile( request );
            Properties overridingProperties = getOverridingProperties( request );
            IgnoredModulesOptions omitIgnoredModules;
            if ( request.isOmitIgnoredModules() )
            {
                omitIgnoredModules = IgnoredModulesOptions.OMIT;
            }
            else
            {
                omitIgnoredModules = IgnoredModulesOptions.EXECUTE;
            }
            Configuration config =
                ConfigurationLoader.loadConfiguration( configFile, new PropertiesExpander( overridingProperties ),
                                                       omitIgnoredModules );
            String effectiveEncoding = StringUtils.isNotEmpty( request.getEncoding() ) ? request.getEncoding() : System
                .getProperty( "file.encoding", "UTF-8" );
            
            if ( StringUtils.isEmpty( request.getEncoding() ) )
            {
                getLogger().warn( "File encoding has not been set, using platform encoding " + effectiveEncoding
                                      + ", i.e. build is platform dependent!" );
            }

            if ( "Checker".equals( config.getName() )
                    || "com.puppycrawl.tools.checkstyle.Checker".equals( config.getName() ) )
            {
                if ( config instanceof DefaultConfiguration )
                {
                    // MCHECKSTYLE-173 Only add the "charset" attribute if it has not been set
                    addAttributeIfNotExists( (DefaultConfiguration) config, "charset", effectiveEncoding );
                    addAttributeIfNotExists( (DefaultConfiguration) config, "cacheFile", request.getCacheFile() );
                }
                else
                {
                    getLogger().warn( "Failed to configure file encoding on module " + config );
                }
            }
            return config;
        }
        catch ( CheckstyleException e )
        {
            throw new CheckstyleExecutorException( "Failed during checkstyle configuration", e );
        }
    }

    private void addAttributeIfNotExists( DefaultConfiguration config, String name, String value )
    {
        try
        {
            // MCHECKSTYLE-132 DefaultConfiguration addAttribute has changed in checkstyle 5.3
            if ( config.getAttribute( name ) == null )
            {
                config.addAttribute( name, value );
            }
        }
        catch ( CheckstyleException ex )
        {
            // MCHECKSTYLE-159 Checkstyle 5.4+ throws an exception when trying to access an attribute that doesn't exist
            config.addAttribute( name, value );
        }
    }

    private void prepareCheckstylePaths( CheckstyleExecutorRequest request, MavenProject project,
                                         List<String> classPathStrings, List<String> outputDirectories,
                                         Collection<File> sourceDirectories, Collection<File> testSourceDirectories )
        throws CheckstyleExecutorException
    {
        try
        {
            outputDirectories.add( project.getBuild().getOutputDirectory() );

            if ( request.isIncludeTestSourceDirectory() && ( testSourceDirectories != null )
                && anyDirectoryExists( testSourceDirectories ) )
            {
                classPathStrings.addAll( project.getTestClasspathElements() );
                outputDirectories.add( project.getBuild().getTestOutputDirectory() );
            }
            else
            {
                classPathStrings.addAll( project.getCompileClasspathElements() );
            }
        }
        catch ( DependencyResolutionRequiredException e )
        {
            throw new CheckstyleExecutorException( e.getMessage(), e );
        }
    }
    
    private boolean anyDirectoryExists( Collection<File> files )
    {
        for ( File file : files )
        {
            if ( file.isDirectory() )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * Get the effective Checkstyle version at runtime.
     * @return the MANIFEST implementation version of Checkstyle API package (can be <code>null</code>)
     *
     *@todo Copied from CheckstyleReportGenerator - move to a utility class
     */
    private String getCheckstyleVersion()
    {
        Package checkstyleApiPackage = Configuration.class.getPackage();

        return ( checkstyleApiPackage == null ) ? null : checkstyleApiPackage.getImplementationVersion();
    }

    private Properties getOverridingProperties( CheckstyleExecutorRequest request )
        throws CheckstyleExecutorException
    {
        Properties p = new Properties();
        InputStream in = null;
        try
        {
            if ( request.getPropertiesLocation() != null )
            {
                if ( getLogger().isDebugEnabled() )
                {
                    getLogger().debug( "request.getPropertiesLocation() " + request.getPropertiesLocation() );
                }

                File propertiesFile = locator.getResourceAsFile( request.getPropertiesLocation(),
                                                                 "checkstyle-checker.properties" );

                if ( propertiesFile != null )
                {
                    in = new FileInputStream( propertiesFile );
                    p.load( in );
                    in.close();
                    in = null;
                }
            }

            if ( StringUtils.isNotEmpty( request.getPropertyExpansion() ) )
            {
                String propertyExpansion = request.getPropertyExpansion();
                // Convert \ to \\, so that p.load will convert it back properly
                propertyExpansion = StringUtils.replace( propertyExpansion, "\\", "\\\\" );
                p.load( new ByteArrayInputStream( propertyExpansion.getBytes() ) );
            }

            // Workaround for MCHECKSTYLE-48
            // Make sure that "config/maven-header.txt" is the default value
            // for headerLocation, if configLocation="config/maven_checks.xml"
            String headerLocation = request.getHeaderLocation();
            if ( "config/maven_checks.xml".equals( request.getConfigLocation() ) )
            {

                if ( "LICENSE.txt".equals( request.getHeaderLocation() ) )
                {
                    headerLocation = "config/maven-header.txt";
                }
            }
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "headerLocation " + headerLocation );
            }

            if ( StringUtils.isNotEmpty( headerLocation ) )
            {
                try
                {
                    File headerFile = licenseLocator.getResourceAsFile( headerLocation, "checkstyle-header.txt" );

                    if ( headerFile != null )
                    {
                        p.setProperty( "checkstyle.header.file", headerFile.getAbsolutePath() );
                    }
                }
                catch ( FileResourceCreationException | ResourceNotFoundException e )
                {
                    getLogger().debug( "Unable to process header location: " + headerLocation );
                    getLogger().debug( "Checkstyle will throw exception if ${checkstyle.header.file} is used" );
                }
            }

            if ( request.getCacheFile() != null )
            {
                p.setProperty( "checkstyle.cache.file", request.getCacheFile() );
            }
        }
        catch ( IOException | ResourceNotFoundException | FileResourceCreationException e )
        {
            throw new CheckstyleExecutorException( "Failed to get overriding properties", e );
        }
        finally
        {
            IOUtils.closeQuietly( in );
        }
        if ( request.getSuppressionsFileExpression() != null )
        {
            String suppressionsFilePath = getSuppressionsFilePath( request );

            if ( suppressionsFilePath != null )
            {
                p.setProperty( request.getSuppressionsFileExpression(), suppressionsFilePath );
            }
        }

        return p;
    }

    private List<File> getFilesToProcess( CheckstyleExecutorRequest request )
        throws IOException
    {
        StringBuilder excludesStr = new StringBuilder();

        if ( StringUtils.isNotEmpty( request.getExcludes() ) )
        {
            excludesStr.append( request.getExcludes() );
        }

        String[] defaultExcludes = FileUtils.getDefaultExcludes();
        for ( String defaultExclude : defaultExcludes )
        {
            if ( excludesStr.length() > 0 )
            {
                excludesStr.append( "," );
            }

            excludesStr.append( defaultExclude );
        }

        Set<File> files = new LinkedHashSet<>();
        if ( request.isAggregate() )
        {
            for ( MavenProject project : request.getReactorProjects() )
            {
                Set<File> sourceDirectories = new LinkedHashSet<>();
                
                // CompileSourceRoots are absolute paths
                List<String> compileSourceRoots = project.getCompileSourceRoots(); 
                for ( String compileSourceRoot : compileSourceRoots )
                {
                    sourceDirectories.add( new File( compileSourceRoot ) );
                }

                Set<File> testSourceDirectories = new LinkedHashSet<>();
                // CompileSourceRoots are absolute paths
                List<String> testCompileSourceRoots = project.getTestCompileSourceRoots(); 
                for ( String testCompileSourceRoot : testCompileSourceRoots )
                {
                    testSourceDirectories.add( new File( testCompileSourceRoot ) );
                }

                addFilesToProcess( request, sourceDirectories, project.getResources(), project.getTestResources(),
                                   files, testSourceDirectories );
            }
        }
        else
        {
            Collection<File> sourceDirectories = request.getSourceDirectories();
            addFilesToProcess( request, sourceDirectories, request.getResources(),
                request.getTestResources(), files, request.getTestSourceDirectories() );
        }

        getLogger().debug( "Added " + files.size() + " files to process." );

        return new ArrayList<>( files );
    }

    private void addFilesToProcess( CheckstyleExecutorRequest request, Collection<File> sourceDirectories,
                                    List<Resource> resources, List<Resource> testResources, Collection<File> files,
                                    Collection<File> testSourceDirectories )
        throws IOException
    {
        if ( sourceDirectories != null )
        {
            for ( File sourceDirectory : sourceDirectories )
            {
                if ( sourceDirectory.isDirectory() )
                {
                    final List<File> sourceFiles =
                        FileUtils.getFiles( sourceDirectory, request.getIncludes(), request.getExcludes() );
                    files.addAll( sourceFiles );
                    getLogger().debug( "Added " + sourceFiles.size() + " source files found in '"
                                           + sourceDirectory.getAbsolutePath() + "'." );
                }
            }
        }

        if ( request.isIncludeTestSourceDirectory() && testSourceDirectories != null )
        {
            for ( File testSourceDirectory : testSourceDirectories )
            {
                if ( testSourceDirectory.isDirectory() )
                {
                    final List<File> testSourceFiles =
                        FileUtils.getFiles( testSourceDirectory, request.getIncludes(), request.getExcludes() );
                    
                    files.addAll( testSourceFiles );
                    getLogger().debug( "Added " + testSourceFiles.size() + " test source files found in '"
                            + testSourceDirectory.getAbsolutePath() + "'." );
                }
            }
        }

        if ( resources != null && request.isIncludeResources() )
        {
            addResourceFilesToProcess( request, resources, files );
        }
        else
        {
            getLogger().debug( "No resources found in this project." );
        }

        if ( testResources != null && request.isIncludeTestResources() )
        {
            addResourceFilesToProcess( request, testResources, files );
        }
        else
        {
            getLogger().debug( "No test resources found in this project." );
        }
    }

    private void addResourceFilesToProcess( CheckstyleExecutorRequest request, List<Resource> resources,
                                            Collection<File> files )
        throws IOException
    {
        for ( Resource resource : resources )
        {
            if ( resource.getDirectory() != null )
            {
                File resourcesDirectory = new File( resource.getDirectory() );
                if ( resourcesDirectory.isDirectory() )
                {
                    String includes = request.getResourceIncludes();
                    String excludes = request.getResourceExcludes();

                    // MCHECKSTYLE-214: Only with project-root respect in/excludes, otherwise you'll get every file
                    if ( resourcesDirectory.equals( request.getProject().getBasedir() ) )
                    {
                        String resourceIncludes = StringUtils.join( resource.getIncludes().iterator(), "," );
                        if ( StringUtils.isEmpty( includes ) )
                        {
                            includes = resourceIncludes;
                        }
                        else
                        {
                            includes += "," + resourceIncludes;
                        }
                        
                        String resourceExcludes = StringUtils.join( resource.getExcludes().iterator(), "," );
                        if ( StringUtils.isEmpty( excludes ) )
                        {
                            excludes = resourceExcludes;
                        }
                        else
                        {
                            excludes += "," + resourceExcludes;
                        }
                    }
                    
                    List<File> resourceFiles =
                        FileUtils.getFiles( resourcesDirectory, includes, excludes );
                    files.addAll( resourceFiles );
                    getLogger().debug( "Added " + resourceFiles.size() + " resource files found in '"
                            + resourcesDirectory.getAbsolutePath() + "'." );
                }
                else
                {
                    getLogger().debug( "The resources directory '" + resourcesDirectory.getAbsolutePath()
                            + "' does not exist or is not a directory." );
                }
            }
        }
    }

    private FilterSet getSuppressionsFilterSet( final String suppressionsFilePath )
        throws CheckstyleExecutorException
    {
        if ( suppressionsFilePath == null )
        {
            return null;
        }

        try
        {
            return SuppressionsLoader.loadSuppressions( suppressionsFilePath );
        }
        catch ( CheckstyleException ce )
        {
            throw new CheckstyleExecutorException( "Failed to load suppressions file from: "
                + suppressionsFilePath, ce );
        }
    }

    private String getSuppressionsFilePath( final CheckstyleExecutorRequest request )
        throws CheckstyleExecutorException
    {
        final String suppressionsLocation = request.getSuppressionsLocation();
        if ( StringUtils.isEmpty( suppressionsLocation ) )
        {
            return null;
        }
        
        try
        {
            File suppressionsFile = locator.getResourceAsFile( suppressionsLocation, "checkstyle-suppressions.xml" );
            return suppressionsFile == null ? null : suppressionsFile.getAbsolutePath();
        }
        catch ( ResourceNotFoundException e )
        {
            throw new CheckstyleExecutorException( "Unable to find suppressions file at location: "
                + suppressionsLocation, e );
        }
        catch ( FileResourceCreationException e )
        {
            throw new CheckstyleExecutorException( "Unable to process suppressions file location: "
                + suppressionsLocation, e );
        }
    }

    private String getConfigFile( CheckstyleExecutorRequest request )
        throws CheckstyleExecutorException
    {
        try
        {
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "request.getConfigLocation() " + request.getConfigLocation() );
            }

            File configFile = locator.getResourceAsFile( request.getConfigLocation(), "checkstyle-checker.xml" );
            if ( configFile == null )
            {
                throw new CheckstyleExecutorException( "Unable to process config location: "
                    + request.getConfigLocation() );
            }
            return configFile.getAbsolutePath();
        }
        catch ( ResourceNotFoundException e )
        {
            throw new CheckstyleExecutorException( "Unable to find configuration file at location: "
                + request.getConfigLocation(), e );
        }
        catch ( FileResourceCreationException e )
        {
            throw new CheckstyleExecutorException( "Unable to process configuration file at location: "
                + request.getConfigLocation(), e );
        }

    }

    /**
     * Configures search paths in the resource locator.
     * This method should only be called once per execution.
     *
     * @param request executor request data.
     */
    private void configureResourceLocator( final ResourceManager resourceManager,
                                           final CheckstyleExecutorRequest request,
                                           final List<Artifact> additionalArtifacts )
    {
        final MavenProject project = request.getProject();
        resourceManager.setOutputDirectory( new File( project.getBuild().getDirectory() ) );

        // Recurse up the parent hierarchy and add project directories to the search roots
        MavenProject parent = project;
        while ( parent != null && parent.getFile() != null )
        {
            // MCHECKSTYLE-131 ( olamy ) I don't like this hack.
            // (dkulp) Me either.   It really pollutes the location stuff
            // by allowing searches of stuff outside the current module.
            File dir = parent.getFile().getParentFile();
            resourceManager.addSearchPath( FileResourceLoader.ID, dir.getAbsolutePath() );
            parent = parent.getParent();
        }
        resourceManager.addSearchPath( "url", "" );
        
        // MCHECKSTYLE-225: load licenses from additional artifacts, not from classpath
        if ( additionalArtifacts != null )
        {
            for ( Artifact licenseArtifact : additionalArtifacts )
            {
                try
                {
                    resourceManager.addSearchPath( "jar", "jar:" + licenseArtifact.getFile().toURI().toURL() );
                }
                catch ( MalformedURLException e )
                {
                    // noop
                }
            }
        }
    }
}
