/*
 * 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.jackrabbit.filevault.maven.packaging.mojo;

import static org.codehaus.plexus.archiver.util.DefaultFileSet.fileSet;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.jackrabbit.filevault.maven.packaging.Filters;
import org.apache.jackrabbit.filevault.maven.packaging.impl.ContentPackageArchiver;
import org.apache.jackrabbit.filevault.maven.packaging.impl.PlexusIoNonExistingDirectoryResource;
import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.maven.shared.filtering.MavenResourcesExecution;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.codehaus.plexus.archiver.FileSet;
import org.codehaus.plexus.archiver.jar.ManifestException;
import org.codehaus.plexus.archiver.util.DefaultFileSet;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.MatchPatterns;
import org.codehaus.plexus.util.StringUtils;
import org.jetbrains.annotations.NotNull;

/** Builds a content package. Uses the metadata generated by and embedded artifacts (like subpackages or OSGi bundles) configured in a preceding execution of goal {@code generate-metadata}. 
 * <p>
 * <i>This goal is executed/bound by default for Maven modules of type {@code content-package}.</i>
 */
@Mojo(name = "package", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class VaultMojo extends AbstractSourceAndMetadataPackageMojo {

    private static final String PACKAGE_TYPE = "zip";

    public static final String PACKAGE_EXT = "." + PACKAGE_TYPE;

    private static final Collection<File> STATIC_META_INF_FILES = Arrays.asList(new File(Constants.META_DIR, Constants.CONFIG_XML),
            new File(Constants.META_DIR, Constants.SETTINGS_XML));

    @Component
    private ArtifactHandlerManager artifactHandlerManager;
    
    /**
     * The directory that contains additional files and folders to end up in the package's META-INF folder.
     * Every file and subfolder is considered except for the subfolder named {@code vault} and a file named {@code MANIFEST.MF}.
     */
    @Parameter(property = "vault.metaInfDirectory", required = false)
    File metaInfDirectory;

    /** Set to {@code true} to fail the build in case of files are being contained in the {@code jcrRootSourceDirectory} which are not
     * covered by the filter rules and therefore would not end up in the package. */
    @Parameter(property = "vault.failOnUncoveredSourceFiles", required = true, defaultValue = "true")
    private boolean failOnUncoveredSourceFiles;

    /** Set to {@code false} to not fail the build in case of files/folders being added to the resulting package more than once. Usually
     * this indicates overlapping with embedded files or overlapping filter rules. */
    @Parameter(property = "vault.failOnDuplicateEntries", required = true, defaultValue = "true")
    private boolean failOnDuplicateEntries;

    /** The name of the generated package ZIP file without the ".zip" file extension. The optional classifier parameter will be appended
     * to the name of the package. */
    @Parameter(property = "vault.finalName", defaultValue = "${project.build.finalName}", required = true)
    private String finalName;

    /** Directory in which the built content package will be output. */
    @Parameter(property = "vault.outputDirectory", defaultValue = "${project.build.directory}", required = true)
    private File outputDirectory;

    /** Enables resource filtering on the meta-inf source files similar to what the <a href="https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html">maven-resources-plugin</a> does.
     * It is recommended to limit filtering with {@link #filteredFilePatterns} and {@link #nonFilteredFileExtensions}.
     * @since 1.1.0 
     */
    @Parameter(property = "vault.enableMetaInfFiltering", defaultValue = "false")
    private boolean enableMetaInfFiltering;

    /** Enables resource filtering on the {@link AbstractSourceAndMetadataPackageMojo#jcrRootSourceDirectory} source files similar to what the <a href="https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html">maven-resources-plugin</a> does.
     * It is recommended to limit filtering with {@link #filteredFilePatterns} and {@link #nonFilteredFileExtensions}.
     * @since 1.1.0 
     */
    @Parameter(property = "vault.enableJcrRootFiltering", defaultValue = "false") 
    private boolean enableJcrRootFiltering;

    /**
     * <p>
     * Set of delimiters for expressions to filter within the resources. 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>
     * <p>
     * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
     * </p>
     *
     * @since 1.1.0 */
    @Parameter(property = "vault.delimiters")
    private LinkedHashSet<String> delimiters;

    /** Use default delimiters in addition to custom delimiters, if any.
     *
     * @since 1.1.0 
     */
    @Parameter(property = "vault.useDefaultDelimiters", defaultValue = "true")
    private boolean useDefaultDelimiters;

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

    /**
     * The list of extra filter properties files to be used along with System properties, project properties, and filter properties files specified in the POM build/filters section, which should be used for the filtering during the current mojo execution.
     * 
     * @since 1.1.0 */
    @Parameter(property="vault.filters")
    private List<String> filterFiles;

    /** Expression preceded with this String won't be interpolated. <code>\${foo}</code> will be replaced with <code>${foo}</code>.
     *
     * @since 1.1.0 */
    @Parameter(property="vault.escapeString")
    protected String escapeString;

    /** To escape interpolated values with Windows path <code>c:\foo\bar</code> will be replaced with <code>c:\\foo\\bar</code>.
     *
     * @since 1.1.0 */
    @Parameter(property="vault.escapedBackslashesInFilePath", defaultValue = "false")
    private boolean escapedBackslashesInFilePath;

    /** Additional list of file extensions that should not be filtered, e.g. binaries.
     * Already predefined as extensions which should never be filtered are: jpg, jpeg, gif, bmp, png, ico.
     * Instead of using this deny list approach for binary files and others which should not be filtered, 
     * consider using an allow list via {@link #filteredFilePatterns} instead.
     * @since 1.1.0 */
    @Parameter(property="vault.nonFilteredFileExtensions")
    private List<String> nonFilteredFileExtensions;

    /** 
     * Restricts the files which should be filtered to the ones having matching one of the given <a href="http://ant.apache.org/manual/dirtasks.html#patterns">Ant patterns</a>.
     * Evaluated before {@link #nonFilteredFileExtensions}.
     * All patterns are relative to the root paths (given through the filter.xml root entries or the META-INF directory).
     * If empty or not set all files except for the ones from {@link #nonFilteredFileExtensions} are filtered.
     * @since 1.1.8 */
    @Parameter(property="vault.filteredFilePatterns")
    private List<String> filteredFilePatterns;

    /** Stop searching endToken at the end of line when filtering is applied.
     * 
     * @since 1.1.0 */
    @Parameter(property="vault.supportMultiLineFiltering", defaultValue = "false")
    private boolean supportMultiLineFiltering;

    @Parameter(defaultValue = "${session}", readonly = true, required = false)
    protected MavenSession session;

    /** The archive configuration to use. See <a href="http://maven.apache.org/shared/maven-archiver/index.html">the documentation for Maven
     * Archiver</a>.
     * 
     * All settings related to manifest are not relevant as this gets overwritten by the manifest in
     * {@link AbstractMetadataPackageMojo#workDirectory} */
    @Parameter
    private MavenArchiveConfiguration archive;

    /**
     */
    @Component(role = MavenResourcesFiltering.class, hint = "default") 
    MavenResourcesFiltering mavenResourcesFiltering;

    @Component
    private MavenProjectHelper projectHelper;

    /** All file names (relative to the zip root) which are supposed to not get overwritten in the package. The value is the source file. */
    private Map<File, File> protectedFiles = new HashMap<>();

    /** Creates a {@link FileSet} for the archiver
     * 
     * @param directory the directory
     * @param prefix the prefix
     * @return the fileset */
    @NotNull
    protected DefaultFileSet createFileSet(@NotNull File directory, @NotNull String prefix) {
        return createFileSet(directory, prefix, null);
    }

    /** Creates a {@link FileSet} for the archiver
     * 
     * @param directory the directory
     * @param prefix the prefix
     * @param additionalExcludes excludes
     * @return the fileset */
    @NotNull
    protected DefaultFileSet createFileSet(@NotNull File directory, @NotNull String prefix, List<String> additionalExcludes) {
        List<String> excludes = new LinkedList<>(this.excludes);
        if (additionalExcludes != null) {
            excludes.addAll(additionalExcludes);
        }
        DefaultFileSet fileSet = fileSet(directory)
                .prefixed(prefix)
                .includeExclude(null, excludes.toArray(new String[0]))
                .includeEmptyDirs(true);
        fileSet.setUsingDefaultExcludes(addDefaultExcludes);
        return fileSet;
    }

    /**
     * Adds a file to the archiver and optionally applies some filtering.
     * @param mavenResourcesExecution
     * @param archiver
     * @param sourceFile
     * @param destFileName
     * @throws MavenFilteringException in case filtering failed
     */
    protected void addFileToArchive(MavenResourcesExecution mavenResourcesExecution, ContentPackageArchiver archiver, File sourceFile,
            String destFileName) throws MavenFilteringException {
        Path destFile = Paths.get(destFileName);
        if ((destFile.startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
            (destFile.startsWith(Constants.META_INF) && enableMetaInfFiltering)) {
            MatchPatterns matchPatterns = MatchPatterns.from(filteredFilePatterns.toArray(new String[0]));
            if (filteredFilePatterns == null || matchPatterns.matches(sourceFile.toString(), true)) {
                getLog().info("Apply filtering to " + getProjectRelativeFilePath(sourceFile));
                Resource resource = new Resource();
                resource.setDirectory(sourceFile.getParent());
                resource.setIncludes(Collections.singletonList(sourceFile.getName()));
                resource.setFiltering(true);
                File newTargetDirectory = applyFiltering(destFile.getParent().toString(), mavenResourcesExecution, resource);
                sourceFile = new File(newTargetDirectory, sourceFile.getName());
            }
        }
        getLog().debug("Adding file " + getProjectRelativeFilePath(sourceFile) + " to package at " + destFileName + "'");
        archiver.addFile(sourceFile, destFileName);

    }

    /**
     * Adds a fileSet to the archiver and optionally applies some filtering.
     * @param mavenResourcesExecution
     * @param archiver
     * @param fileSet
     * @throws MavenFilteringException in case filtering failed
     */
    protected void addFileSetToArchive(MavenResourcesExecution mavenResourcesExecution, ContentPackageArchiver archiver, DefaultFileSet fileSet) throws MavenFilteringException {
        // ignore directories added with no prefix (workDirectory)
        if ((fileSet.getPrefix().startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
            (fileSet.getPrefix().startsWith(Constants.META_INF) && enableMetaInfFiltering)) {
            
            getLog().info("Apply filtering to FileSet below " + getProjectRelativeFilePath(fileSet.getDirectory()));
            Resource filteringSourceResource = new Resource();
            filteringSourceResource.setDirectory(fileSet.getDirectory().getPath());
            
            // since allow lists (i.e. only filtering specific extensions) is not natively supported
            // split up the fileSet
            if (filteredFilePatterns != null && !filteredFilePatterns.isEmpty()) {
                if (fileSet.getIncludes() != null) {
                    throw new IllegalStateException("FileSet can not have includes set, as those are used for filteredFileExtensions");
                }
                // create an additional file set with unfiltered files
                DefaultFileSet unfilteredFileSet = cloneFileSet(fileSet);
                
                // add all filtered file patterns to excludes
                String[] excludes = Stream.of(Arrays.asList(fileSet.getExcludes()), filteredFilePatterns).flatMap(x -> x.stream()).toArray(String[]::new);
                unfilteredFileSet.setExcludes(excludes);
                
                getLog().debug("Adding unfiltered fileSet '" + getString(unfilteredFileSet) + "' to package");
                archiver.addFileSet(unfilteredFileSet);
                filteringSourceResource.setIncludes(filteredFilePatterns);
            } else {
                if (fileSet.getIncludes() != null) {
                    filteringSourceResource.setIncludes(Arrays.asList(fileSet.getIncludes()));
                }
            }
           
            if (fileSet.getExcludes() != null) {
                filteringSourceResource.setExcludes(Arrays.asList(fileSet.getExcludes()));
                // default exclude are managed via mavenResourcesExecution
            }
            filteringSourceResource.setFiltering(true);
            File newTargetDirectory = applyFiltering(fileSet.getPrefix(), mavenResourcesExecution, filteringSourceResource);
            if (newTargetDirectory.exists()) {
                fileSet.setDirectory(newTargetDirectory);
                getLog().debug("Adding filtered fileSet '" + getString(fileSet) + "' to package");
                archiver.addFileSet(fileSet);
            }
        } else {
            getLog().debug("Adding fileSet '" + getString(fileSet) + "' to package");
            archiver.addFileSet(fileSet);
        }
    }

    static DefaultFileSet cloneFileSet(DefaultFileSet defaultFileSet) {
        DefaultFileSet newFileSet = new DefaultFileSet(defaultFileSet.getDirectory());
        newFileSet.setCaseSensitive(defaultFileSet.isCaseSensitive());
        newFileSet.setExcludes(defaultFileSet.getExcludes());
        newFileSet.setFileMappers(defaultFileSet.getFileMappers());
        newFileSet.setFileSelectors(defaultFileSet.getFileSelectors());
        newFileSet.setIncludes(defaultFileSet.getIncludes());
        newFileSet.setIncludingEmptyDirectories(defaultFileSet.isIncludingEmptyDirectories());
        newFileSet.setPrefix(defaultFileSet.getPrefix());
        newFileSet.setStreamTransformer(defaultFileSet.getStreamTransformer());
        newFileSet.setUsingDefaultExcludes(defaultFileSet.isUsingDefaultExcludes());
        return newFileSet;
    }

    private static String getString(FileSet fileSet) {
        StringBuilder sb = new StringBuilder("FileSet [");
        sb.append("directory=").append(fileSet.getDirectory());
        sb.append(" prefix=").append(fileSet.getPrefix());
        sb.append(" excludes=").append(StringUtils.join(fileSet.getExcludes(), ", "));
        sb.append("]");
        return sb.toString();
    }

    private @NotNull File applyFiltering(String prefix, MavenResourcesExecution mavenResourcesExecution, Resource resource) throws MavenFilteringException {
        File targetPath = new File(project.getBuild().getDirectory(), "filteredFiles");
        mavenResourcesExecution.setOutputDirectory(targetPath);
        targetPath = new File(targetPath, prefix);
        // which path to set as target (is a temporary path)
        getLog().debug("Applying filtering to resource " + resource);
        resource.setTargetPath(targetPath.getPath());
        mavenResourcesExecution.setResources(Collections.singletonList(resource));
        mavenResourcesFiltering.filterResources(mavenResourcesExecution);
        return targetPath;
    }

    private boolean isOverwritingProtectedFile(File zipFile, File sourceFile, boolean isProtected) {
        if (protectedFiles.containsKey(zipFile)) {
            return true;
        }
        if (isProtected) {
            protectedFiles.put(zipFile, sourceFile);
        }
        return false;
    }

    /** @param fileSet
     * @param isProtected
     * @return a map with key = file path in zip and value = absolute source file */
    private Map<File, File> getOverwrittenProtectedFiles(FileSet fileSet, boolean isProtected) {
        // copied from PlexusIoFileResourceCollection.getResources()
        Map<File, File> overwrittenFiles = new HashMap<>();
        final DirectoryScanner ds = new DirectoryScanner();
        final File dir = fileSet.getDirectory();
        ds.setBasedir(dir);
        final String[] inc = fileSet.getIncludes();
        if (inc != null && inc.length > 0) {
            ds.setIncludes(inc);
        }
        final String[] exc = fileSet.getExcludes();
        if (exc != null && exc.length > 0) {
            ds.setExcludes(exc);
        }
        if (fileSet.isUsingDefaultExcludes()) {
            ds.addDefaultExcludes();
        }
        ds.setCaseSensitive(fileSet.isCaseSensitive());
        ds.setFollowSymlinks(false);
        ds.scan();

        String[] files = ds.getIncludedFiles();
        for (String file : files) {
            File zipFileEntry = new File(fileSet.getPrefix() + file);
            File sourceFile = new File(fileSet.getDirectory(), file);
            if (isOverwritingProtectedFile(zipFileEntry, sourceFile, isProtected)) {
                overwrittenFiles.put(zipFileEntry, sourceFile);
            }
        }
        return overwrittenFiles;
    }

    protected MavenResourcesExecution setupMavenResourcesExecution() {
        MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
        mavenResourcesExecution.setEncoding(resourceEncoding);
        mavenResourcesExecution.setEscapeString(escapeString);
        mavenResourcesExecution.setSupportMultiLineFiltering(supportMultiLineFiltering);
        mavenResourcesExecution.setMavenProject(project);

        // if these are NOT set, just use the defaults, which are '${*}' and '@'.
        mavenResourcesExecution.setDelimiters(delimiters, useDefaultDelimiters);

        if (nonFilteredFileExtensions != null) {
            mavenResourcesExecution.setNonFilteredFileExtensions(nonFilteredFileExtensions);
        }

        if (filterFiles == null) {
            filterFiles = project.getBuild().getFilters();
        }
        mavenResourcesExecution.setFilters(filterFiles);
        mavenResourcesExecution.setEscapedBackslashesInFilePath(escapedBackslashesInFilePath);
        mavenResourcesExecution.setMavenSession(this.session);
        mavenResourcesExecution.setEscapeString(this.escapeString);
        mavenResourcesExecution.setSupportMultiLineFiltering(supportMultiLineFiltering);
        mavenResourcesExecution.setAddDefaultExcludes(addDefaultExcludes);
        mavenResourcesExecution.setOverwrite(true);
        mavenResourcesExecution.setUseDefaultFilterWrappers(true);
        return mavenResourcesExecution;
    }

    /** Executes this mojo */
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        final File finalFile = getZipFile(outputDirectory, finalName, classifier);

        MavenResourcesExecution mavenResourcesExecution = setupMavenResourcesExecution();
        try {
            ContentPackageArchiver contentPackageArchiver = new ContentPackageArchiver();
            contentPackageArchiver.setEncoding(resourceEncoding);

            if (metaInfDirectory != null) {
                if (metaInfDirectory.exists() && metaInfDirectory.isDirectory()) {
                    DefaultFileSet fileSet = createFileSet(metaInfDirectory, Constants.META_INF + "/",
                            Collections.singletonList(Constants.VAULT_DIR));
                    addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
                    getLog().info("Include additional META-INF files/folders from " + getProjectRelativeFilePath(metaInfDirectory) + " in package.");
                } else {
                    getLog().warn("Given metaInfDirectory " + getProjectRelativeFilePath(metaInfDirectory) + " does not exist or is no directory. It won't be included in the package.");
                }
            }
            
            // find the meta-inf/vault source directory
            File metaInfVaultDirectory = getMetaInfVaultSourceDirectory();
            
            // retrieve filters
            Filters filters = loadGeneratedFilterFile();
            Map<String, File> embeddedFiles = getEmbeddedFilesMap();

            File workDirectory = getWorkDirectory(false);
            // A map with key = relative file in zip and value = absolute source file name)
            Map<File, File> duplicateFiles = new HashMap<>();
            contentPackageArchiver.setIncludeEmptyDirs(true);
            if (metaInfVaultDirectory != null) {
                if (metaInfVaultDirectory.getAbsoluteFile().toPath().normalize().startsWith(workDirectory.getAbsoluteFile().toPath().normalize())) {
                    throw new MojoFailureException("metaInfVaultDirectory ("+metaInfVaultDirectory+") must be outside of workDirectory ("+ workDirectory + ")!");
                }
                // first add the metadata from the metaInfDirectory (they should take precedence over the generated ones from workDirectory,
                // except for the filter.xml, which should always come from the work directory)
                DefaultFileSet fileSet = createFileSet(metaInfVaultDirectory, Constants.META_DIR + "/",
                        Collections.singletonList(Constants.FILTER_XML));
                duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, true));
                addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
            }
            // then add all files from the workDirectory (they might overlap with the ones from metaInfDirectory, but the duplicates are
            // just ignored in the package)
            DefaultFileSet fileSet = createFileSet(workDirectory, "");
            // issue warning in case of overlaps
            Map<File, File> overwrittenWorkFiles = getOverwrittenProtectedFiles(fileSet, true);
            for (Entry<File, File> entry : overwrittenWorkFiles.entrySet()) {
                String message = "Found duplicate file '" + entry.getKey() + "' from sources " + getProjectRelativeFilePath(protectedFiles.get(entry.getKey()))
                        + " and " + getProjectRelativeFilePath(entry.getValue()) + ".";

                // INFO for the static ones all others warn
                if (STATIC_META_INF_FILES.contains(entry.getKey())) {
                    getLog().info(message);
                } else {
                    getLog().warn(message);
                }
            }
            addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);

            // add embedded files
            for (Map.Entry<String, File> entry : embeddedFiles.entrySet()) {
                protectedFiles.put(new File(entry.getKey()), entry.getValue());
                addFileToArchive(mavenResourcesExecution, contentPackageArchiver, entry.getValue(), entry.getKey());
            }
            // find the source directory
            final File jcrSourceDirectory = getJcrSourceDirectory();
            addSourceDirectory(mavenResourcesExecution, contentPackageArchiver, jcrSourceDirectory, filters, embeddedFiles);


            if (!duplicateFiles.isEmpty()) {
                for (Entry<File, File> entry : duplicateFiles.entrySet()) {
                    String message = "Found duplicate file '" + entry.getKey() + "' from sources " + getProjectRelativeFilePath(protectedFiles.get(entry.getKey()))
                            + " and " + getProjectRelativeFilePath(entry.getValue()) + ".";
                    if (failOnDuplicateEntries) {
                        getLog().error(message);
                    } else {
                        getLog().warn(message);
                    }
                }
                if (failOnDuplicateEntries) {
                    throw new MojoFailureException(
                            "Found " + duplicateFiles.size() + " duplicate file(s) in content package, see above errors for details.");
                }
            }

            // add mandatory jcr_root folder
            if (!contentPackageArchiver.getFiles().containsKey(Constants.ROOT_DIR + "/")) {
                contentPackageArchiver.addResource(new PlexusIoNonExistingDirectoryResource(Constants.ROOT_DIR), Constants.ROOT_DIR, 0);
            }
            MavenArchiver mavenArchiver = new MavenArchiver();
            mavenArchiver.setArchiver(contentPackageArchiver);
            mavenArchiver.setOutputFile(finalFile);
            mavenArchiver.configureReproducible(outputTimestamp);
            mavenArchiver.createArchive(null, project, getMavenArchiveConfiguration(getGeneratedManifestFile(false)));

            if (StringUtils.isNotEmpty(classifier)) {
                projectHelper.attachArtifact(project, PACKAGE_TYPE, classifier, finalFile);
            } else {
                // set the file for the project's artifact and ensure the
                // artifact is correctly handled with the "zip" handler
                // (workaround for MNG-1682)
                final Artifact projectArtifact = project.getArtifact();
                projectArtifact.setFile(finalFile);
                projectArtifact.setArtifactHandler(artifactHandlerManager.getArtifactHandler(PACKAGE_TYPE));
            }
        } catch (IllegalStateException | ManifestException | IOException | DependencyResolutionRequiredException | ConfigurationException | MavenFilteringException e) {
            throw new MojoExecutionException(e.toString(), e);
        }
    }

    private File getZipFile(File basedir, String resultFinalName, String classifier) {
        if (basedir == null) {
            throw new IllegalArgumentException("basedir is not allowed to be null");
        }
        if (resultFinalName == null) {
            throw new IllegalArgumentException("finalName is not allowed to be null");
        }
        StringBuilder fileName = new StringBuilder(resultFinalName);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(classifier)) {
            fileName.append("-").append(classifier);
        }
        fileName.append(PACKAGE_EXT);
        return new File(basedir, fileName.toString());
    }

    private Map<File, File> addSourceDirectory(MavenResourcesExecution mavenResourcesExecution, ContentPackageArchiver contentPackageArchiver, File jcrSourceDirectory, Filters filters,
            Map<String, File> embeddedFiles) throws MavenFilteringException, MojoFailureException {
        Map<File, File> duplicateFiles = new HashMap<>();
        
        if (jcrSourceDirectory == null || !jcrSourceDirectory.exists()) {
            return Collections.emptyMap();
            
        }
        if (jcrSourceDirectory.getAbsoluteFile().toPath().normalize().startsWith(getWorkDirectory(false).getAbsoluteFile().toPath().normalize())) {
            throw new MojoFailureException("jcrSourceDirectory ("+jcrSourceDirectory+") must be outside of workDirectory ("+ workDirectory + ")!");
        }
        getLog().info("Packaging content from " + getProjectRelativeFilePath(jcrSourceDirectory));
        // See GRANITE-16348
        // we want to build a list of all the root directories in the order they were specified in the filter
        // but ignore the roots that don't point to a directory
        List<PathFilterSet> filterSets = filters.getFilterSets();
        if (filterSets.isEmpty()) {
            DefaultFileSet fileSet = createFileSet(jcrSourceDirectory, Constants.ROOT_DIR + prefix);
            duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, false));
            addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
        } else {
            for (PathFilterSet filterSet : filterSets) {
                String relPath = PlatformNameFormat.getPlatformPath(filterSet.getRoot());
                String destPath = FileUtils.normalize(Constants.ROOT_DIR + prefix + relPath);

                // CQ-4204625 skip embedded files, they have been added already
                if (embeddedFiles.containsKey(destPath)) {
                    continue;
                }
                // check for full coverage aggregate
                File sourceFile = new File(jcrSourceDirectory, relPath + ".xml");
                if (sourceFile.isFile()) {
                    destPath = FileUtils.normalize(Constants.ROOT_DIR + prefix + relPath + ".xml");
                    if (isOverwritingProtectedFile(new File(destPath), sourceFile, false)) {
                        duplicateFiles.put(new File(destPath), sourceFile);
                    }
                    addFileToArchive(mavenResourcesExecution, contentPackageArchiver, sourceFile, destPath);
                    // similar to AbstractExporter all ancestors should be contained as well (see AggregateImpl.prepare(...))
                    addAncestors(contentPackageArchiver, sourceFile, jcrSourceDirectory, destPath);
                } else { 
                    // root path for ancestors is in one of the parent directories?
                    sourceFile = new File(jcrSourceDirectory, relPath);

                    // traverse the ancestors until we find a existing directory (see CQ-4204625)
                    while ((!sourceFile.exists() || !sourceFile.isDirectory())
                            && !jcrSourceDirectory.equals(sourceFile)) {
                        sourceFile = sourceFile.getParentFile();
                        relPath = StringUtils.chomp(relPath, "/");
                    }

                    if (!jcrSourceDirectory.equals(sourceFile)) {
                        destPath = FileUtils.normalize(Constants.ROOT_DIR + prefix + relPath);
                        DefaultFileSet fileSet = createFileSet(sourceFile, destPath + "/");
                        duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, false));
                        addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
                        // similar to AbstractExporter all ancestors should be contained as well (see AggregateImpl.prepare(...))
                        addAncestors(contentPackageArchiver, sourceFile, jcrSourceDirectory, destPath);
                    }
                }
                
            }
        }
        // check for uncovered files (i.e. files from the source which are not even added to the content package)
        Collection<File> uncoveredFiles = getUncoveredFiles(jcrSourceDirectory, excludes, prefix,
                contentPackageArchiver.getFiles().keySet());
        if (!uncoveredFiles.isEmpty()) {
            for (File uncoveredFile : uncoveredFiles) {
                String message = "File " + getProjectRelativeFilePath(uncoveredFile)
                        + " not covered by a filter rule and therefore not contained in the resulting package";
                if (failOnUncoveredSourceFiles) {
                    getLog().error(message);
                } else {
                    getLog().warn(message);
                }
            }
            if (failOnUncoveredSourceFiles) {
                throw new MojoFailureException("The following files are not covered by a filter rule: \n"
                        + StringUtils.join(uncoveredFiles.iterator(), ",\n"));
            }
        }
        return duplicateFiles;
    }

    private void addAncestors(ContentPackageArchiver contentPackageArchiver, File inputFile, File inputRootFile, String destFile) {
        // include up to (including root)
        if (!inputFile.getAbsolutePath().startsWith(inputRootFile.getAbsolutePath())) {
            return;
        }
        // is there an according .content.xml available? (ignore full-coverage files)
        File genericAggregate = new File(inputFile, Constants.DOT_CONTENT_XML);
        if (genericAggregate.exists()) {
            getLog().debug("Adding ancestor file " + getProjectRelativeFilePath(genericAggregate) + " to package at '" + destFile + "/" + Constants.DOT_CONTENT_XML +"'");
            contentPackageArchiver.addFile(genericAggregate, destFile + "/" + Constants.DOT_CONTENT_XML);
        }
        addAncestors(contentPackageArchiver, inputFile.getParentFile(), inputRootFile, StringUtils.chomp(destFile, "/"));
    }

    /** Checks if some files (optionally prefixed) below the given source directory are not listed in coveredFiles
     * 
     * @param sourceDirectory the source directory
     * @param prefix the optional prefix to prepend to the relative file name before comparing with {@code coveredFileNames}
     * @param coveredFileNames the covered file names (should have relative file names), might have OS specific separators
     * @return the absolute file names in the source directory which are not already listed in {@code entryNames}. */
    protected static Collection<File> getUncoveredFiles(final File sourceDirectory, Collection<String> excludes, String prefix,
            Collection<String> coveredFileNames) {
        // check for uncovered files (i.e. files from the source which are not even added to the content package)
        // entry name still have platform-dependent separators here (https://github.com/codehaus-plexus/plexus-archiver/issues/129)
        Collection<File> coveredFiles = coveredFileNames.stream()
                .map(File::new)
                .collect(Collectors.toList());

        /*
         * similar method as in {@link org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection#getResources();}
         */
        DirectoryScanner scanner = new DirectoryScanner();
        scanner.setBasedir(sourceDirectory);
        scanner.setExcludes(excludes.toArray(new String[0]));
        scanner.addDefaultExcludes();
        scanner.scan();

        Collection<File> allFiles = Stream.of(scanner.getIncludedFiles())
                .map(File::new)
                .collect(Collectors.toList());

        return getUncoveredFiles(sourceDirectory, prefix, allFiles, coveredFiles);
    }

    private static Collection<File> getUncoveredFiles(final File sourceDirectory, String prefix, final Collection<File> allFiles,
            final Collection<File> coveredFiles) {
        Collection<File> uncoveredFiles = new ArrayList<>();
        for (File file : allFiles) {
            if (!coveredFiles.contains(new File(Constants.ROOT_DIR + prefix, file.getPath()))) {
                uncoveredFiles.add(new File(sourceDirectory, file.getPath()));
            }
        }
        return uncoveredFiles;
    }

    private MavenArchiveConfiguration getMavenArchiveConfiguration(File manifestFile) {
        if (archive == null) {
            archive = new MavenArchiveConfiguration();

            archive.setAddMavenDescriptor(true);
            archive.setCompress(true);
            archive.setIndex(false);
        }
        // use the manifest being generated beforehand
        archive.setManifestFile(manifestFile);

        return archive;
    }
}
