/*
 * 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.plugin.resources.remote;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
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 java.util.TreeMap;

import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Model;
import org.apache.maven.model.Organization;
import org.apache.maven.model.Resource;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.resources.remote.io.xpp3.RemoteResourcesBundleXpp3Reader;
import org.apache.maven.plugin.resources.remote.io.xpp3.SupplementalDataModelXpp3Reader;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingResult;
import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
import org.apache.maven.shared.filtering.MavenFileFilter;
import org.apache.maven.shared.filtering.MavenFileFilterRequest;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.codehaus.plexus.resource.ResourceManager;
import org.codehaus.plexus.resource.loader.FileResourceLoader;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.artifact.ArtifactType;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.util.artifact.JavaScopes;

/**
 * <p>
 * Pull down resourceBundles containing remote resources and process the resources contained inside. When that is done,
 * the resources are injected into the current (in-memory) Maven project, making them available to the process-resources
 * phase.
 * </p>
 * <p>
 * Resources that end in ".vm" are treated as Velocity templates. For those, the ".vm" is stripped off for the final
 * artifact name and it's fed through Velocity to have properties expanded, conditions processed, etc...
 * </p>
 * Resources that don't end in ".vm" are copied "as is".
 * <p>
 * This is a support abstract class, with two non-aggregating and aggregating implementations.
 * </p>
 */
public abstract class AbstractProcessRemoteResourcesMojo extends AbstractMojo {
    private static final String TEMPLATE_SUFFIX = ".vm";

    /**
     * <p>
     * In cases where a local resource overrides one from a remote resource bundle, that resource should be filtered if
     * the resource set specifies it. In those cases, this parameter defines the list of delimiters for filterable
     * expressions. These delimiters are specified in the form 'beginToken*endToken'. If no '*' is given, the delimiter
     * is assumed to be the same for start and end.
     * </p>
     * <p>
     * So, the default filtering delimiters might be specified as:
     * </p>
     *
     * <pre>
     * &lt;delimiters&gt;
     *   &lt;delimiter&gt;${*}&lt;/delimiter&gt;
     *   &lt;delimiter&gt;@&lt;/delimiter&gt;
     * &lt;/delimiters&gt;
     * </pre>
     * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
     *
     * @since 1.1
     */
    @Parameter
    protected List<String> filterDelimiters;

    /**
     * @since 1.1
     */
    @Parameter(defaultValue = "true")
    protected boolean useDefaultFilterDelimiters;

    /**
     * The character encoding scheme to be applied when filtering resources.
     */
    @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
    protected String encoding;

    /**
     * The directory where processed resources will be placed for packaging.
     */
    @Parameter(defaultValue = "${project.build.directory}/maven-shared-archive-resources")
    private File outputDirectory;

    /**
     * The directory containing extra information appended to the generated resources.
     */
    @Parameter(defaultValue = "${basedir}/src/main/appended-resources")
    private File appendedResourcesDirectory;

    /**
     * Supplemental model data. Useful when processing
     * artifacts with incomplete POM metadata.
     * <p/>
     * By default, this Mojo looks for supplemental model data in the file
     * "<code>${appendedResourcesDirectory}/supplemental-models.xml</code>".
     *
     * @since 1.0-alpha-5
     */
    @Parameter
    private String[] supplementalModels;

    /**
     * List of artifacts that are added to the search path when looking
     * for supplementalModels, expressed with <code>groupId:artifactId:version[:type[:classifier]]</code> format.
     *
     * @since 1.1
     */
    @Parameter
    private List<String> supplementalModelArtifacts;

    /**
     * The resource bundles that will be retrieved and processed,
     * expressed with <code>groupId:artifactId:version[:type[:classifier]]</code> format.
     */
    @Parameter(required = true)
    private List<String> resourceBundles;

    /**
     * Skip remote-resource processing
     *
     * @since 1.0-alpha-5
     */
    @Parameter(property = "remoteresources.skip", defaultValue = "false")
    private boolean skip;

    /**
     * Attaches the resources to the main build of the project as a resource directory.
     *
     * @since 1.5
     */
    @Parameter(defaultValue = "true", property = "attachToMain")
    private boolean attachToMain;

    /**
     * Attaches the resources to the test build of the project as a resource directory.
     *
     * @since 1.5
     */
    @Parameter(defaultValue = "true", property = "attachToTest")
    private boolean attachToTest;

    /**
     * Additional properties to be passed to Velocity.
     * Several properties are automatically added:<ul>
     * <li><code>project</code> - the current MavenProject </li>
     * <li><code>projects</code> - the list of dependency projects</li>
     * <li><code>projectsSortedByOrganization</code> - the list of dependency projects sorted by organization</li>
     * <li><code>projectTimespan</code> - the timespan of the current project (requires inceptionYear in pom)</li>
     * <li><code>locator</code> - the ResourceManager that can be used to retrieve additional resources</li>
     * </ul>
     * See <a
     * href="https://maven.apache.org/ref/current/maven-project/apidocs/org/apache/maven/project/MavenProject.html"> the
     * javadoc for MavenProject</a> for information about the properties on the MavenProject.
     */
    @Parameter
    protected Map<String, Object> properties = new HashMap<>();

    /**
     * Whether to include properties defined in the project when filtering resources.
     *
     * @since 1.2
     */
    @Parameter(defaultValue = "false")
    protected boolean includeProjectProperties = false;

    /**
     * When the result of velocity transformation fits in memory, it is compared with the actual contents on disk
     * to eliminate unnecessary destination file overwrite. This improves build times since further build steps
     * typically rely on the modification date.
     *
     * @since 1.6
     */
    @Parameter(defaultValue = "5242880")
    protected int velocityFilterInMemoryThreshold = 5 * 1024 * 1024;

    /**
     * The Maven session.
     */
    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    protected MavenSession mavenSession;

    /**
     * The current project.
     */
    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    protected MavenProject project;

    /**
     * Scope to include. An Empty string indicates all scopes (default is "runtime").
     *
     * @since 1.0
     */
    @Parameter(property = "includeScope", defaultValue = "runtime")
    protected String includeScope;

    /**
     * Scope to exclude. An Empty string indicates no scopes (default).
     *
     * @since 1.0
     */
    @Parameter(property = "excludeScope", defaultValue = "")
    protected String excludeScope;

    /**
     * When resolving project dependencies, specify the scopes to include.
     * The default is the same as "includeScope" if there are no exclude scopes set.
     * Otherwise, it defaults to "test" to grab all the dependencies so the
     * exclude filters can filter out what is not needed.
     *
     * @since 1.5
     */
    @Parameter
    protected String[] resolveScopes;

    /**
     * Comma separated list of Artifact names to exclude.
     *
     * @since 1.0
     */
    @Parameter(property = "excludeArtifactIds", defaultValue = "")
    protected String excludeArtifactIds;

    /**
     * Comma separated list of Artifact names to include.
     *
     * @since 1.0
     */
    @Parameter(property = "includeArtifactIds", defaultValue = "")
    protected String includeArtifactIds;

    /**
     * Comma separated list of GroupId Names to exclude.
     *
     * @since 1.0
     */
    @Parameter(property = "excludeGroupIds", defaultValue = "")
    protected String excludeGroupIds;

    /**
     * Comma separated list of GroupIds to include.
     *
     * @since 1.0
     */
    @Parameter(property = "includeGroupIds", defaultValue = "")
    protected String includeGroupIds;

    /**
     * If we should exclude transitive dependencies
     *
     * @since 1.0
     */
    @Parameter(property = "excludeTransitive", defaultValue = "false")
    protected boolean excludeTransitive;

    /**
     * Timestamp for reproducible output archive entries, either formatted as ISO 8601
     * <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
     * <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
     */
    @Parameter(defaultValue = "${project.build.outputTimestamp}")
    private String outputTimestamp;

    @Component
    protected RepositorySystem repoSystem;

    /**
     * Filtering support, for local resources that override those in the remote bundle.
     */
    @Component
    private MavenFileFilter fileFilter;

    @Component
    private ResourceManager locator;

    @Component
    private ProjectBuilder projectBuilder;

    @Component
    private ArtifactHandlerManager artifactHandlerManager;

    /**
     * Map of artifacts to supplemental project object models.
     */
    private Map<String, Model> supplementModels;

    /**
     * Merges supplemental data model with artifact metadata. Useful when processing artifacts with
     * incomplete POM metadata.
     */
    private final ModelInheritanceAssembler inheritanceAssembler = new ModelInheritanceAssembler();

    private VelocityEngine velocity;

    @Override
    public void execute() throws MojoExecutionException {
        if (skip) {
            getLog().info("Skipping remote resources execution.");
            return;
        }

        if (encoding == null || encoding.isEmpty()) {
            getLog().warn("File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
                    + ", i.e. build is platform dependent!");
        }

        if (resolveScopes == null) {
            resolveScopes = new String[] {
                (this.includeScope == null || this.includeScope.isEmpty()) ? JavaScopes.TEST : this.includeScope
            };
        }

        if (supplementalModels == null) {
            File sups = new File(appendedResourcesDirectory, "supplemental-models.xml");
            if (sups.exists()) {
                try {
                    supplementalModels = new String[] {sups.toURI().toURL().toString()};
                } catch (MalformedURLException e) {
                    // ignore
                    getLog().debug("URL issue with supplemental-models.xml: " + e);
                }
            }
        }

        configureLocator();

        if (includeProjectProperties) {
            final Properties projectProperties = project.getProperties();
            for (Object key : projectProperties.keySet()) {
                properties.put(key.toString(), projectProperties.get(key).toString());
            }
        }

        ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
        try {
            validate();

            List<File> resourceBundleArtifacts = downloadBundles(resourceBundles);
            supplementModels = loadSupplements(supplementalModels);

            ClassLoader classLoader = initalizeClassloader(resourceBundleArtifacts);

            Thread.currentThread().setContextClassLoader(classLoader);

            velocity = new VelocityEngine();
            velocity.setProperty("resource.loaders", "classpath");
            velocity.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
            velocity.init();

            VelocityContext context = buildVelocityContext(properties);

            processResourceBundles(classLoader, context);

            if (outputDirectory.exists()) {
                // ----------------------------------------------------------------------------
                // Push our newly generated resources directory into the MavenProject so that
                // these resources can be picked up by the process-resources phase.
                // ----------------------------------------------------------------------------
                Resource resource = new Resource();
                resource.setDirectory(outputDirectory.getAbsolutePath());
                // MRRESOURCES-61 handle main and test resources separately
                if (attachToMain) {
                    project.getResources().add(resource);
                }
                if (attachToTest) {
                    project.getTestResources().add(resource);
                }

                // ----------------------------------------------------------------------------
                // Write out archiver dot file
                // ----------------------------------------------------------------------------
                try {
                    File dotFile = new File(project.getBuild().getDirectory(), ".plxarc");
                    FileUtils.mkdir(dotFile.getParentFile().getAbsolutePath());
                    FileUtils.fileWrite(dotFile.getAbsolutePath(), outputDirectory.getName());
                } catch (IOException e) {
                    throw new MojoExecutionException("Error creating dot file for archiving instructions.", e);
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(origLoader);
        }
    }

    private void configureLocator() throws MojoExecutionException {
        if (supplementalModelArtifacts != null && !supplementalModelArtifacts.isEmpty()) {
            List<File> artifacts = downloadBundles(supplementalModelArtifacts);

            for (File artifact : artifacts) {
                if (artifact.isDirectory()) {
                    locator.addSearchPath(FileResourceLoader.ID, artifact.getAbsolutePath());
                } else {
                    try {
                        locator.addSearchPath(
                                "jar", "jar:" + artifact.toURI().toURL().toExternalForm());
                    } catch (MalformedURLException e) {
                        throw new MojoExecutionException("Could not use jar " + artifact.getAbsolutePath(), e);
                    }
                }
            }
        }

        locator.addSearchPath(
                FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath());
        if (appendedResourcesDirectory != null) {
            locator.addSearchPath(FileResourceLoader.ID, appendedResourcesDirectory.getAbsolutePath());
        }
        locator.addSearchPath("url", "");
        locator.setOutputDirectory(new File(project.getBuild().getDirectory()));
    }

    protected List<MavenProject> getProjects() {
        List<MavenProject> projects = new ArrayList<>();

        // add filters in well known order, least specific to most specific
        FilterArtifacts filter = new FilterArtifacts();

        Set<Artifact> artifacts = new LinkedHashSet<>();
        artifacts.addAll(getAllDependencies());
        if (this.excludeTransitive) {
            filter.addFilter(new ProjectTransitivityFilter(getDirectDependencies(), true));
        }

        filter.addFilter(new ScopeFilter(this.includeScope, this.excludeScope));
        filter.addFilter(new GroupIdFilter(this.includeGroupIds, this.excludeGroupIds));
        filter.addFilter(new ArtifactIdFilter(this.includeArtifactIds, this.excludeArtifactIds));

        // perform filtering
        try {
            artifacts = filter.filter(artifacts);
        } catch (ArtifactFilterException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }

        getLog().debug("PROJECTS: " + artifacts);

        for (Artifact artifact : artifacts) {
            if (artifact.isSnapshot()) {
                artifact.setVersion(artifact.getBaseVersion());
            }

            getLog().debug("Building project for " + artifact);
            MavenProject p;
            try {
                ProjectBuildingRequest req = new DefaultProjectBuildingRequest()
                        .setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL)
                        .setProcessPlugins(false)
                        .setRepositorySession(mavenSession.getRepositorySession())
                        .setSystemProperties(mavenSession.getSystemProperties())
                        .setUserProperties(mavenSession.getUserProperties())
                        .setLocalRepository(mavenSession.getLocalRepository())
                        .setRemoteRepositories(project.getRemoteArtifactRepositories());
                ProjectBuildingResult res = projectBuilder.build(artifact, req);
                p = res.getProject();
            } catch (ProjectBuildingException e) {
                getLog().warn("Invalid project model for artifact [" + artifact.getGroupId() + ":"
                        + artifact.getArtifactId() + ":" + artifact.getVersion() + "]. "
                        + "It will be ignored by the remote resources Mojo.");
                continue;
            }

            String supplementKey = generateSupplementMapKey(
                    p.getModel().getGroupId(), p.getModel().getArtifactId());

            if (supplementModels.containsKey(supplementKey)) {
                Model mergedModel = mergeModels(p.getModel(), supplementModels.get(supplementKey));
                MavenProject mergedProject = new MavenProject(mergedModel);
                projects.add(mergedProject);
                mergedProject.setArtifact(artifact);
                mergedProject.setVersion(artifact.getVersion());
                getLog().debug("Adding project with groupId [" + mergedProject.getGroupId() + "] (supplemented)");
            } else {
                projects.add(p);
                getLog().debug("Adding project with groupId [" + p.getGroupId() + "]");
            }
        }
        projects.sort(new ProjectComparator());
        return projects;
    }

    /**
     * Returns all the transitive hull of all the involved maven projects.
     */
    protected abstract Set<Artifact> getAllDependencies();

    /**
     * Returns all the direct dependencies of all the involved maven projects.
     */
    protected abstract Set<Artifact> getDirectDependencies();

    protected Map<Organization, List<MavenProject>> getProjectsSortedByOrganization(List<MavenProject> projects) {
        Map<Organization, List<MavenProject>> organizations = new TreeMap<>(new OrganizationComparator());
        List<MavenProject> unknownOrganization = new ArrayList<>();

        for (MavenProject p : projects) {
            if (p.getOrganization() != null
                    && StringUtils.isNotEmpty(p.getOrganization().getName())) {
                List<MavenProject> sortedProjects = organizations.get(p.getOrganization());
                if (sortedProjects == null) {
                    sortedProjects = new ArrayList<>();
                }
                sortedProjects.add(p);

                organizations.put(p.getOrganization(), sortedProjects);
            } else {
                unknownOrganization.add(p);
            }
        }
        if (!unknownOrganization.isEmpty()) {
            Organization unknownOrg = new Organization();
            unknownOrg.setName("an unknown organization");
            organizations.put(unknownOrg, unknownOrganization);
        }

        return organizations;
    }

    protected boolean copyResourceIfExists(File file, String relFileName, VelocityContext context)
            throws IOException, MojoExecutionException {
        for (Resource resource : project.getResources()) {
            File resourceDirectory = new File(resource.getDirectory());

            if (!resourceDirectory.exists()) {
                continue;
            }

            // TODO - really should use the resource includes/excludes and name mapping
            File source = new File(resourceDirectory, relFileName);
            File templateSource = new File(resourceDirectory, relFileName + TEMPLATE_SUFFIX);

            if (!source.exists() && templateSource.exists()) {
                source = templateSource;
            }

            if (source.exists() && !source.equals(file)) {
                if (source == templateSource) {
                    try (DeferredFileOutputStream os =
                            new DeferredFileOutputStream(velocityFilterInMemoryThreshold, file)) {
                        try (Reader reader = getReader(source);
                                Writer writer = getWriter(os)) {
                            velocity.evaluate(context, writer, "", reader);
                        } catch (ParseErrorException | MethodInvocationException | ResourceNotFoundException e) {
                            throw new MojoExecutionException("Error rendering velocity resource: " + source, e);
                        }
                        fileWriteIfDiffers(os);
                    }
                } else if (resource.isFiltering()) {

                    MavenFileFilterRequest req = setupRequest(resource, source, file);

                    try {
                        fileFilter.copyFile(req);
                    } catch (MavenFilteringException e) {
                        throw new MojoExecutionException("Error filtering resource: " + source, e);
                    }
                } else {
                    FileUtils.copyFile(source, file);
                }

                // exclude the original (so eclipse doesn't complain about duplicate resources)
                resource.addExclude(relFileName);

                return true;
            }
        }
        return false;
    }

    private Reader getReader(File source) throws IOException {
        if (encoding != null) {
            return new InputStreamReader(Files.newInputStream(source.toPath()), encoding);
        } else {
            return ReaderFactory.newPlatformReader(source);
        }
    }

    private Writer getWriter(OutputStream os) throws IOException {
        if (encoding != null) {
            return new OutputStreamWriter(os, encoding);
        } else {
            return WriterFactory.newPlatformWriter(os);
        }
    }

    /**
     * If the transformation result fits in memory and the destination file already exists
     * then both are compared.
     * <p>If destination file is byte-by-byte equal, then it is not overwritten.
     * This improves subsequent compilation times since upstream plugins property see that
     * the resource was not modified.
     * <p>Note: the method should be called after {@link DeferredFileOutputStream#close}
     *
     * @param outStream Deferred stream
     * @throws IOException On IO error.
     */
    private void fileWriteIfDiffers(DeferredFileOutputStream outStream) throws IOException {
        File file = outStream.getFile();
        if (outStream.isThresholdExceeded()) {
            getLog().info("File " + file + " was overwritten due to content limit threshold " + outStream.getThreshold()
                    + " reached");
            return;
        }
        boolean needOverwrite = true;

        if (file.exists()) {
            try (InputStream is = Files.newInputStream(file.toPath());
                    InputStream newContents = new ByteArrayInputStream(outStream.getData())) {
                needOverwrite = !IOUtil.contentEquals(is, newContents);
                if (getLog().isDebugEnabled()) {
                    getLog().debug("File " + file + " contents " + (needOverwrite ? "differs" : "does not differ"));
                }
            }
        }

        if (!needOverwrite) {
            getLog().debug("File " + file + " is up to date");
            return;
        }
        getLog().debug("Writing " + file);

        try (OutputStream os = Files.newOutputStream(file.toPath())) {
            outStream.writeTo(os);
        }
    }

    private MavenFileFilterRequest setupRequest(Resource resource, File source, File file) {
        MavenFileFilterRequest req = new MavenFileFilterRequest();
        req.setFrom(source);
        req.setTo(file);
        req.setFiltering(resource.isFiltering());

        req.setMavenProject(project);
        req.setMavenSession(mavenSession);
        req.setInjectProjectBuildFilters(true);

        if (encoding != null) {
            req.setEncoding(encoding);
        }

        if (filterDelimiters != null && !filterDelimiters.isEmpty()) {
            LinkedHashSet<String> delims = new LinkedHashSet<>();
            if (useDefaultFilterDelimiters) {
                delims.addAll(req.getDelimiters());
            }

            for (String delim : filterDelimiters) {
                if (delim == null) {
                    delims.add("${*}");
                } else {
                    delims.add(delim);
                }
            }

            req.setDelimiters(delims);
        }

        return req;
    }

    protected void validate() throws MojoExecutionException {
        int bundleCount = 1;

        for (String artifactDescriptor : resourceBundles) {
            // groupId:artifactId:version, groupId:artifactId:version:type
            // or groupId:artifactId:version:type:classifier
            String[] s = StringUtils.split(artifactDescriptor, ":");

            if (s.length < 3 || s.length > 5) {
                String position;

                if (bundleCount == 1) {
                    position = "1st";
                } else if (bundleCount == 2) {
                    position = "2nd";
                } else if (bundleCount == 3) {
                    position = "3rd";
                } else {
                    position = bundleCount + "th";
                }

                throw new MojoExecutionException("The " + position
                        + " resource bundle configured must specify a groupId, artifactId, "
                        + " version and, optionally, type and classifier for a remote resource bundle. "
                        + "Must be of the form <resourceBundle>groupId:artifactId:version</resourceBundle>, "
                        + "<resourceBundle>groupId:artifactId:version:type</resourceBundle> or "
                        + "<resourceBundle>groupId:artifactId:version:type:classifier</resourceBundle>");
            }

            bundleCount++;
        }
    }

    private static final String KEY_PROJECTS = "projects";
    private static final String KEY_PROJECTS_ORGS = "projectsSortedByOrganization";

    protected VelocityContext buildVelocityContext(Map<String, Object> properties) {
        // the following properties are expensive to calculate, so we provide them lazily
        VelocityContext context = new VelocityContext(properties) {
            @Override
            public Object internalGet(String key) {
                Object result = super.internalGet(key);
                if (result == null && key != null && key.startsWith(KEY_PROJECTS) && containsKey(key)) {
                    // calculate and put projects* properties
                    List<MavenProject> projects = getProjects();
                    put(KEY_PROJECTS, projects);
                    put(KEY_PROJECTS_ORGS, getProjectsSortedByOrganization(projects));
                    return super.internalGet(key);
                }
                return result;
            }
        };
        // to have a consistent getKeys()/containsKey() behaviour, keys must be present from the start
        context.put(KEY_PROJECTS, null);
        context.put(KEY_PROJECTS_ORGS, null);
        // the following properties are cheap to calculate, so we provide them eagerly

        // Reproducible Builds: try to use reproducible output timestamp
        MavenArchiver archiver = new MavenArchiver();
        Date outputDate = archiver.parseOutputTimestamp(outputTimestamp);

        String inceptionYear = project.getInceptionYear();
        String year = new SimpleDateFormat("yyyy").format((outputDate == null) ? new Date() : outputDate);

        if (inceptionYear == null || inceptionYear.isEmpty()) {
            if (getLog().isDebugEnabled()) {
                getLog().debug("inceptionYear not specified, defaulting to " + year);
            }

            inceptionYear = year;
        }
        context.put("project", project);
        context.put("presentYear", year);
        context.put("locator", locator);

        if (inceptionYear.equals(year)) {
            context.put("projectTimespan", year);
        } else {
            context.put("projectTimespan", inceptionYear + "-" + year);
        }
        return context;
    }

    private List<File> downloadBundles(List<String> bundles) throws MojoExecutionException {
        List<File> bundleArtifacts = new ArrayList<>();

        for (String artifactDescriptor : bundles) {
            getLog().info("Preparing remote bundle " + artifactDescriptor);
            // groupId:artifactId:version[:type[:classifier]]
            String[] s = artifactDescriptor.split(":");

            File artifactFile = null;
            // check if the artifact is part of the reactor
            if (mavenSession != null) {
                List<MavenProject> list = mavenSession.getProjects();
                for (MavenProject p : list) {
                    if (s[0].equals(p.getGroupId()) && s[1].equals(p.getArtifactId()) && s[2].equals(p.getVersion())) {
                        if (s.length >= 4 && "test-jar".equals(s[3])) {
                            artifactFile = new File(p.getBuild().getTestOutputDirectory());
                        } else {
                            artifactFile = new File(p.getBuild().getOutputDirectory());
                        }
                    }
                }
            }
            if (artifactFile == null || !artifactFile.exists()) {
                String g = s[0];
                String a = s[1];
                String v = s[2];
                String type = s.length >= 4 ? s[3] : "jar";
                ArtifactType artifactType =
                        RepositoryUtils.newArtifactType(type, artifactHandlerManager.getArtifactHandler(type));
                String classifier = s.length == 5 ? s[4] : artifactType.getClassifier();

                DefaultArtifact artifact =
                        new DefaultArtifact(g, a, classifier, artifactType.getExtension(), v, artifactType);

                try {
                    ArtifactRequest request =
                            new ArtifactRequest(artifact, project.getRemoteProjectRepositories(), "remote-resources");
                    ArtifactResult result = repoSystem.resolveArtifact(mavenSession.getRepositorySession(), request);
                    artifactFile = result.getArtifact().getFile();
                } catch (ArtifactResolutionException e) {
                    throw new MojoExecutionException("Error processing remote resources", e);
                }
            }
            bundleArtifacts.add(artifactFile);
        }

        return bundleArtifacts;
    }

    private ClassLoader initalizeClassloader(List<File> artifacts) throws MojoExecutionException {
        RemoteResourcesClassLoader cl = new RemoteResourcesClassLoader(null);
        try {
            for (File artifact : artifacts) {
                cl.addURL(artifact.toURI().toURL());
            }
            return cl;
        } catch (MalformedURLException e) {
            throw new MojoExecutionException("Unable to configure resources classloader: " + e.getMessage(), e);
        }
    }

    protected void processResourceBundles(ClassLoader classLoader, VelocityContext context)
            throws MojoExecutionException {
        List<Map.Entry<String, RemoteResourcesBundle>> remoteResources = new ArrayList<>();
        int bundleCount = 0;
        int resourceCount = 0;

        // list remote resources form bundles
        try {
            RemoteResourcesBundleXpp3Reader bundleReader = new RemoteResourcesBundleXpp3Reader();

            for (Enumeration<URL> e = classLoader.getResources(BundleRemoteResourcesMojo.RESOURCES_MANIFEST);
                    e.hasMoreElements(); ) {
                URL url = e.nextElement();
                bundleCount++;
                getLog().debug("processResourceBundle on bundle#" + bundleCount + " " + url);

                RemoteResourcesBundle bundle;

                try (InputStream in = url.openStream()) {
                    bundle = bundleReader.read(in);
                }

                int n = 0;
                for (String bundleResource : bundle.getRemoteResources()) {
                    n++;
                    resourceCount++;
                    getLog().debug("bundle#" + bundleCount + " resource#" + n + " " + bundleResource);
                    remoteResources.add(new AbstractMap.SimpleEntry<>(bundleResource, bundle));
                }
            }
        } catch (IOException ioe) {
            throw new MojoExecutionException("Error finding remote resources manifests", ioe);
        } catch (XmlPullParserException xppe) {
            throw new MojoExecutionException("Error parsing remote resource bundle descriptor.", xppe);
        }

        getLog().info("Copying " + resourceCount + " resource" + ((resourceCount > 1) ? "s" : "") + " from "
                + bundleCount + " bundle" + ((bundleCount > 1) ? "s" : "") + ".");

        String velocityResource = null;
        try {

            for (Map.Entry<String, RemoteResourcesBundle> entry : remoteResources) {
                String bundleResource = entry.getKey();
                RemoteResourcesBundle bundle = entry.getValue();

                String projectResource = bundleResource;

                boolean doVelocity = false;
                if (projectResource.endsWith(TEMPLATE_SUFFIX)) {
                    projectResource = projectResource.substring(0, projectResource.length() - 3);
                    velocityResource = bundleResource;
                    doVelocity = true;
                }

                // Don't overwrite resource that are already being provided.

                File f = new File(outputDirectory, projectResource);

                FileUtils.mkdir(f.getParentFile().getAbsolutePath());

                if (!copyResourceIfExists(f, projectResource, context)) {
                    if (doVelocity) {
                        try (DeferredFileOutputStream os =
                                new DeferredFileOutputStream(velocityFilterInMemoryThreshold, f)) {
                            try (Writer writer = bundle.getSourceEncoding() == null
                                    ? new OutputStreamWriter(os)
                                    : new OutputStreamWriter(os, bundle.getSourceEncoding())) {
                                if (bundle.getSourceEncoding() == null) {
                                    // TODO: Is this correct? Shouldn't we behave like the rest of maven and fail
                                    // down to JVM default instead ISO-8859-1 ?
                                    velocity.mergeTemplate(bundleResource, "ISO-8859-1", context, writer);
                                } else {
                                    velocity.mergeTemplate(bundleResource, bundle.getSourceEncoding(), context, writer);
                                }
                            }
                            fileWriteIfDiffers(os);
                        }
                    } else {
                        URL resUrl = classLoader.getResource(bundleResource);
                        if (resUrl != null) {
                            FileUtils.copyURLToFile(resUrl, f);
                        }
                    }

                    File appendedResourceFile = new File(appendedResourcesDirectory, projectResource);
                    File appendedVmResourceFile = new File(appendedResourcesDirectory, projectResource + ".vm");

                    if (appendedResourceFile.exists()) {
                        getLog().info("Copying appended resource: " + projectResource);
                        try (InputStream in = Files.newInputStream(appendedResourceFile.toPath());
                                OutputStream out = new FileOutputStream(f, true)) {
                            IOUtil.copy(in, out);
                        }

                    } else if (appendedVmResourceFile.exists()) {
                        getLog().info("Filtering appended resource: " + projectResource + ".vm");

                        try (Reader reader = new FileReader(appendedVmResourceFile);
                                Writer writer = getWriter(bundle, f)) {
                            Velocity.init();
                            Velocity.evaluate(context, writer, "remote-resources", reader);
                        }
                    }
                }
            }
        } catch (IOException ioe) {
            throw new MojoExecutionException("Error reading remote resource", ioe);
        } catch (VelocityException e) {
            throw new MojoExecutionException("Error rendering Velocity resource '" + velocityResource + "'", e);
        }
    }

    private Writer getWriter(RemoteResourcesBundle bundle, File f) throws IOException {
        Writer writer;
        if (bundle.getSourceEncoding() == null) {
            writer = new PrintWriter(new FileWriter(f, true));
        } else {
            writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(f, true), bundle.getSourceEncoding()));
        }
        return writer;
    }

    protected Model getSupplement(Xpp3Dom supplementModelXml) throws MojoExecutionException {
        MavenXpp3Reader modelReader = new MavenXpp3Reader();
        Model model = null;

        try {
            model = modelReader.read(new StringReader(supplementModelXml.toString()));
            String groupId = model.getGroupId();
            String artifactId = model.getArtifactId();

            if (groupId == null || groupId.trim().equals("")) {
                throw new MojoExecutionException(
                        "Supplemental project XML " + "requires that a <groupId> element be present.");
            }

            if (artifactId == null || artifactId.trim().equals("")) {
                throw new MojoExecutionException(
                        "Supplemental project XML " + "requires that a <artifactId> element be present.");
            }
        } catch (IOException e) {
            getLog().warn("Unable to read supplemental XML: " + e.getMessage(), e);
        } catch (XmlPullParserException e) {
            getLog().warn("Unable to parse supplemental XML: " + e.getMessage(), e);
        }

        return model;
    }

    protected Model mergeModels(Model parent, Model child) {
        inheritanceAssembler.assembleModelInheritance(child, parent);
        return child;
    }

    private static String generateSupplementMapKey(String groupId, String artifactId) {
        return groupId.trim() + ":" + artifactId.trim();
    }

    private Map<String, Model> loadSupplements(String[] models) throws MojoExecutionException {
        if (models == null) {
            getLog().debug("Supplemental data models won't be loaded. No models specified.");
            return Collections.emptyMap();
        }

        List<Supplement> supplements = new ArrayList<>();
        for (String set : models) {
            getLog().debug("Preparing ruleset: " + set);
            try {
                File f = locator.getResourceAsFile(set, getLocationTemp(set));

                if (null == f || !f.exists()) {
                    throw new MojoExecutionException("Cold not resolve " + set);
                }
                if (!f.canRead()) {
                    throw new MojoExecutionException("Supplemental data models won't be loaded. " + "File "
                            + f.getAbsolutePath() + " cannot be read, check permissions on the file.");
                }

                getLog().debug("Loading supplemental models from " + f.getAbsolutePath());

                SupplementalDataModelXpp3Reader reader = new SupplementalDataModelXpp3Reader();
                SupplementalDataModel supplementalModel = reader.read(new FileReader(f));
                supplements.addAll(supplementalModel.getSupplement());
            } catch (Exception e) {
                String msg = "Error loading supplemental data models: " + e.getMessage();
                getLog().error(msg, e);
                throw new MojoExecutionException(msg, e);
            }
        }

        getLog().debug("Loading supplements complete.");

        Map<String, Model> supplementMap = new HashMap<>();
        for (Supplement sd : supplements) {
            Xpp3Dom dom = (Xpp3Dom) sd.getProject();

            Model m = getSupplement(dom);
            supplementMap.put(generateSupplementMapKey(m.getGroupId(), m.getArtifactId()), m);
        }

        return supplementMap;
    }

    /**
     * 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
     */
    private 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);
        }
        getLog().debug("Before: " + name + " After: " + loc);
        return loc;
    }

    static class OrganizationComparator implements Comparator<Organization> {
        @Override
        public int compare(Organization org1, Organization org2) {
            int i = compareStrings(org1.getName(), org2.getName());
            if (i == 0) {
                i = compareStrings(org1.getUrl(), org2.getUrl());
            }
            return i;
        }

        private int compareStrings(String s1, String s2) {
            if (s1 == null && s2 == null) {
                return 0;
            } else if (s1 == null) {
                return 1;
            } else if (s2 == null) {
                return -1;
            }

            return s1.compareToIgnoreCase(s2);
        }
    }

    static class ProjectComparator implements Comparator<MavenProject> {
        @Override
        public int compare(MavenProject p1, MavenProject p2) {
            return p1.getArtifact().compareTo(p2.getArtifact());
        }
    }
}
