You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2019/11/26 17:41:26 UTC

svn commit: r1870467 - in /jackrabbit/commons/filevault-package-maven-plugin/trunk: ./ src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ src/test/resources/test-projects/fil...

Author: kwin
Date: Tue Nov 26 17:41:25 2019
New Revision: 1870467

URL: http://svn.apache.org/viewvc?rev=1870467&view=rev
Log:
JCRVLT-389 support filtering

This closes #33

Added:
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilteringIT.java
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/.gitattributes
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-filtered.txt
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-unfiltered.txt
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/filter.properties
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/test.properties
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/pom.xml
Modified:
    jackrabbit/commons/filevault-package-maven-plugin/trunk/pom.xml
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractSourceAndMetadataPackageMojo.java
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/IncludeExcludeList.java
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java
    jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java

Modified: jackrabbit/commons/filevault-package-maven-plugin/trunk/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/pom.xml?rev=1870467&r1=1870466&r2=1870467&view=diff
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/pom.xml (original)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/pom.xml Tue Nov 26 17:41:25 2019
@@ -427,9 +427,22 @@
 
         <!-- incremental build support (http://www.eclipse.org/m2e/documentation/m2e-making-maven-plugins-compat.html) -->
         <dependency>
-           <groupId>org.sonatype.plexus</groupId>
-           <artifactId>plexus-build-api</artifactId>
-           <version>0.0.7</version>
+            <groupId>org.sonatype.plexus</groupId>
+            <artifactId>plexus-build-api</artifactId>
+            <version>0.0.7</version>
+        </dependency>
+
+        <!-- for Maven filtering -->
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>maven-filtering</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>maven-shared-utils</artifactId>
+            <version>3.2.1</version>
         </dependency>
 
         <!-- testing -->
@@ -493,12 +506,6 @@
             <version>3.0.0</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.maven.shared</groupId>
-            <artifactId>maven-shared-utils</artifactId>
-            <version>3.2.0</version>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
     <!-- ====================================================================== -->

Modified: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractSourceAndMetadataPackageMojo.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractSourceAndMetadataPackageMojo.java?rev=1870467&r1=1870466&r2=1870467&view=diff
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractSourceAndMetadataPackageMojo.java (original)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractSourceAndMetadataPackageMojo.java Tue Nov 26 17:41:25 2019
@@ -21,7 +21,6 @@ import java.util.Set;
 
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.codehaus.plexus.util.AbstractScanner;
 import org.codehaus.plexus.util.DirectoryScanner;
 
 /**
@@ -48,9 +47,9 @@ public abstract class AbstractSourceAndM
             + "${project.basedir}/src/content/jcr_root," + "${project.build.outputDirectory}")
     private File[] jcrRootSourceDirectory;
 
+    
     /**
-     * The file name patterns to exclude in addition to the ones listed in
-     * {@link AbstractScanner#DEFAULTEXCLUDES}. The format of each pattern is described in {@link DirectoryScanner}.
+     * The file name patterns to exclude (in addition to the default ones if {@link AbstractSourceAndMetadataPackageMojo#addDefaultExcludes}. The format of each pattern is described in {@link DirectoryScanner}.
      * The comparison is against the path relative to the according filter root.
      * Since this is hardly predictable it is recommended to use only filename/directory name patterns here 
      * but not take into account file system hierarchies!
@@ -61,6 +60,36 @@ public abstract class AbstractSourceAndM
     @Parameter(property = "vault.excludes", defaultValue = "**/.vlt,**/.vltignore", required = true)
     protected Set<String> excludes;
 
+    /**
+     * By default files like {@code .gitignore}, {@code .cvsignore} etc. are excluded which means they will not being
+     * copied. If you need them for a particular reason you can do that by settings this to {@code false}. This means
+     * all files like the following will be copied.
+     * <ul>
+     * <li>Misc: &#42;&#42;/&#42;~, &#42;&#42;/#&#42;#, &#42;&#42;/.#&#42;, &#42;&#42;/%&#42;%, &#42;&#42;/._&#42;</li>
+     * <li>CVS: &#42;&#42;/CVS, &#42;&#42;/CVS/&#42;&#42;, &#42;&#42;/.cvsignore</li>
+     * <li>RCS: &#42;&#42;/RCS, &#42;&#42;/RCS/&#42;&#42;</li>
+     * <li>SCCS: &#42;&#42;/SCCS, &#42;&#42;/SCCS/&#42;&#42;</li>
+     * <li>VSSercer: &#42;&#42;/vssver.scc</li>
+     * <li>MKS: &#42;&#42;/project.pj</li>
+     * <li>SVN: &#42;&#42;/.svn, &#42;&#42;/.svn/&#42;&#42;</li>
+     * <li>GNU: &#42;&#42;/.arch-ids, &#42;&#42;/.arch-ids/&#42;&#42;</li>
+     * <li>Bazaar: &#42;&#42;/.bzr, &#42;&#42;/.bzr/&#42;&#42;</li>
+     * <li>SurroundSCM: &#42;&#42;/.MySCMServerInfo</li>
+     * <li>Mac: &#42;&#42;/.DS_Store</li>
+     * <li>Serena Dimension: &#42;&#42;/.metadata, &#42;&#42;/.metadata/&#42;&#42;</li>
+     * <li>Mercurial: &#42;&#42;/.hg, &#42;&#42;/.hg/&#42;&#42;</li>
+     * <li>GIT: &#42;&#42;/.git, &#42;&#42;/.gitignore, &#42;&#42;/.gitattributes, &#42;&#42;/.git/&#42;&#42;</li>
+     * <li>Bitkeeper: &#42;&#42;/BitKeeper, &#42;&#42;/BitKeeper/&#42;&#42;, &#42;&#42;/ChangeSet,
+     * &#42;&#42;/ChangeSet/&#42;&#42;</li>
+     * <li>Darcs: &#42;&#42;/_darcs, &#42;&#42;/_darcs/&#42;&#42;, &#42;&#42;/.darcsrepo,
+     * &#42;&#42;/.darcsrepo/&#42;&#42;&#42;&#42;/-darcs-backup&#42;, &#42;&#42;/.darcs-temp-mail
+     * </ul>
+     *
+     * @since 1.1.0
+     */
+    @Parameter(defaultValue = "true")
+    protected boolean addDefaultExcludes;
+
     protected File getJcrSourceDirectory() {
         return getJcrSourceDirectory(jcrRootSourceDirectory, builtContentDirectory, getLog());
     }

Modified: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/IncludeExcludeList.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/IncludeExcludeList.java?rev=1870467&r1=1870466&r2=1870467&view=diff
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/IncludeExcludeList.java (original)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/IncludeExcludeList.java Tue Nov 26 17:41:25 2019
@@ -21,6 +21,11 @@ import java.util.ArrayList;
 
 public class IncludeExcludeList extends ArrayList<String> {
 
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
     public boolean add(String entry) {
         return entry != null && super.add(entry);
     }

Modified: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java?rev=1870467&r1=1870466&r2=1870467&view=diff
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java (original)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java Tue Nov 26 17:41:25 2019
@@ -19,11 +19,13 @@ package org.apache.jackrabbit.filevault.
 import static org.codehaus.plexus.archiver.util.DefaultFileSet.fileSet;
 
 import java.io.File;
+import java.io.IOException;
 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;
@@ -34,12 +36,16 @@ import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 
 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;
@@ -47,115 +53,237 @@ import org.apache.maven.plugins.annotati
 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.shared.filtering.MavenFileFilter;
+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.StringUtils;
 
-/**
- * Build a content package.
- */
-@Mojo(
-        name = "package",
-        defaultPhase = LifecyclePhase.PACKAGE,
-        requiresDependencyResolution = ResolutionScope.COMPILE,
-        threadSafe = true
-)
+/** Build a content package. */
+@Mojo(name = "package", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
 public class VaultMojo extends AbstractSourceAndMetadataPackageMojo {
 
     private static final String PACKAGE_TYPE = "zip";
 
     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));
+
+    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;
 
-    /**
-     * 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 = "false"
-    )
+    /** 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 = "false")
     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"
-    )
+    /** 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.
-     */
-    @Parameter(
-            property = "vault.finalName",
-            defaultValue = "${project.build.finalName}",
-            required = true)
+    /** The name of the generated package ZIP file without the ".zip" file extension. */
+    @Parameter(property = "vault.finalName", defaultValue = "${project.build.finalName}", required = true)
     private String finalName;
 
-    /**
-     * Directory in which the built content package will be output.
-     */
-    @Parameter(
-            defaultValue="${project.build.directory}",
-            required = true)
+    /** Directory in which the built content package will be output. */
+    @Parameter(property = "vault.outputDirectory", defaultValue = "${project.build.directory}", required = true)
     private File outputDirectory;
 
+    @Parameter(property = "vault.enableMetaInfFiltering", defaultValue = "false")
+    private boolean enableMetaInfFiltering;
+
+    @Parameter(property = "vault.enableJcrRootFiltering", defaultValue = "false") 
+    private boolean enableJcrRootFiltering;
+
     /**
-     * The archive configuration to use. See <a
-     * href="http://maven.apache.org/shared/maven-archiver/index.html">the
-     * documentation for Maven Archiver</a>.
+     * <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>
      * 
-     * All settings related to manifest are not relevant as this gets overwritten by the manifest in {@link AbstractMetadataPackageMojo#workDirectory}
+     * <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. */
+    @Parameter(property = "vault.resourceEncoding", defaultValue = "${project.build.sourceEncoding}")
+    private String resourceEncoding;
+
+    /** Filters (path to  property files) to include during the filtering of resources. The default value is the filter list under build
+     * specifying a filter will override the filter list under build.
+     * 
+     * @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.
+     * (already defined are : jpg, jpeg, gif, bmp, png)
+     * @since 1.1.0 */
+    @Parameter(property="vault.nonFilteredFileExtensions")
+    private List<String> nonFilteredFileExtensions;
+
+    /** 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;
 
     /**
-     * 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<>();
+    @Component(role = MavenFileFilter.class, hint = "default")
+    private MavenFileFilter mavenFileFilter;
 
     /**
-     * Creates a {@link FileSet} for the archiver
+     */
+    @Component(role = MavenResourcesFiltering.class, hint = "default") 
+    MavenResourcesFiltering mavenResourcesFiltering;
+
+    /** 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
-     */
+     * @return the fileset */
     @Nonnull
-    private FileSet createFileSet(@Nonnull File directory, @Nonnull String prefix) {
+    protected DefaultFileSet createFileSet(@Nonnull File directory, @Nonnull String prefix) {
         return createFileSet(directory, prefix, null);
     }
 
-    /**
-     * Creates a {@link FileSet} for the archiver
+    /** Creates a {@link FileSet} for the archiver
+     * 
      * @param directory the directory
      * @param prefix the prefix
      * @param additionalExcludes excludes
-     * @return the fileset
-     */
+     * @return the fileset */
     @Nonnull
-    private FileSet createFileSet(@Nonnull File directory, @Nonnull String prefix, List<String> additionalExcludes) {
+    protected DefaultFileSet createFileSet(@Nonnull File directory, @Nonnull String prefix, List<String> additionalExcludes) {
         List<String> excludes = new LinkedList<>(this.excludes);
-        if(additionalExcludes != null) {
+        if (additionalExcludes != null) {
             excludes.addAll(additionalExcludes);
         }
-        return fileSet(directory)
+        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 {
+        if ((destFileName.startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
+            (destFileName.startsWith(Constants.ROOT_DIR) && enableMetaInfFiltering)) {
+            getLog().info("Apply filtering to " + sourceFile);
+            Resource resource = new Resource();
+            resource.setDirectory(sourceFile.getParent());
+            resource.setIncludes(Collections.singletonList(sourceFile.getName()));
+            resource.setFiltering(true);
+            File newTargetDirectory = applyFiltering(mavenResourcesExecution, resource);
+            sourceFile = new File(newTargetDirectory, sourceFile.getName());
+        }
+        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 {
+        // TODO: what to do with file sets not having any prefix set (workDirectory)
+        if ((fileSet.getPrefix().startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
+            (fileSet.getPrefix().startsWith(Constants.ROOT_DIR) && enableMetaInfFiltering)) {
+            
+            getLog().info("Apply filtering to FileSet below " + fileSet.getDirectory());
+            Resource resource = new Resource();
+            resource.setDirectory(fileSet.getDirectory().getPath());
+            if (fileSet.getIncludes() != null) {
+                resource.setIncludes(Arrays.asList(fileSet.getIncludes()));
+            }
+            if (fileSet.getExcludes() != null) {
+                resource.setExcludes(Arrays.asList(fileSet.getExcludes()));
+                // default exclude are managed via mavenResourcesExecution
+            }
+            resource.setFiltering(true);
+            File newTargetDirectory = applyFiltering(mavenResourcesExecution, resource);
+            fileSet.setDirectory(newTargetDirectory);
+        }
+
+        archiver.addFileSet(fileSet);
+    }
+
+    private @Nonnull File applyFiltering(MavenResourcesExecution mavenResourcesExecution, Resource resource) throws MavenFilteringException {
+        File targetPath = new File(project.getBuild().getDirectory(), "filteredFiles");
+        // 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));
+        mavenResourcesExecution.setOutputDirectory(targetPath);
+        mavenResourcesFiltering.filterResources(mavenResourcesExecution);
+        return targetPath;
     }
 
     private boolean isOverwritingProtectedFile(File zipFile, File sourceFile, boolean isProtected) {
@@ -168,25 +296,28 @@ public class VaultMojo extends AbstractS
         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<>(); 
+        Map<File, File> overwrittenFiles = new HashMap<>();
         final DirectoryScanner ds = new DirectoryScanner();
         final File dir = fileSet.getDirectory();
-        ds.setBasedir( dir );
+        ds.setBasedir(dir);
         final String[] inc = fileSet.getIncludes();
         if (inc != null && inc.length > 0) {
-            ds.setIncludes( inc );
+            ds.setIncludes(inc);
         }
         final String[] exc = fileSet.getExcludes();
         if (exc != null && exc.length > 0) {
-            ds.setExcludes( exc );
+            ds.setExcludes(exc);
         }
         if (fileSet.isUsingDefaultExcludes()) {
             ds.addDefaultExcludes();
         }
         ds.setCaseSensitive(fileSet.isCaseSensitive());
-        ds.setFollowSymlinks(false );
+        ds.setFollowSymlinks(false);
         ds.scan();
 
         String[] files = ds.getIncludedFiles();
@@ -200,13 +331,39 @@ public class VaultMojo extends AbstractS
         return overwrittenFiles;
     }
 
-    /**
-     * Executes this mojo
-     */
+    protected MavenResourcesExecution setupMavenResourcesExecution() {
+        MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
+        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 {
+    public void execute() throws MojoExecutionException, MojoFailureException {
         final File finalFile = new File(outputDirectory, finalName + PACKAGE_EXT);
 
+        MavenResourcesExecution mavenResourcesExection = setupMavenResourcesExecution();
         try {
             // find the meta-inf source directory
             File metaInfDirectory = getMetaInfVaultSourceDirectory();
@@ -220,23 +377,27 @@ public class VaultMojo extends AbstractS
             Map<String, File> embeddedFiles = getEmbeddedFilesMap();
 
             ContentPackageArchiver contentPackageArchiver = new ContentPackageArchiver();
-            
+
+            // A map with key = relative file in zip and value = absolute source file name)
             Map<File, File> duplicateFiles = new HashMap<>();
             contentPackageArchiver.setIncludeEmptyDirs(true);
             if (metaInfDirectory != null) {
-                // first add the metadata from the metaInfDirectory (they should take precedence over the generated ones from 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)
-                FileSet fileSet = createFileSet(metaInfDirectory, Constants.META_DIR + "/", Collections.singletonList(Constants.FILTER_XML));
+                DefaultFileSet fileSet = createFileSet(metaInfDirectory, Constants.META_DIR + "/",
+                        Collections.singletonList(Constants.FILTER_XML));
                 duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, true));
-                contentPackageArchiver.addFileSet(fileSet);
+                addFileSetToArchive(mavenResourcesExection, 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)
-            FileSet fileSet = createFileSet(workDirectory, "");
+            // 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 '" + protectedFiles.get(entry.getKey()) + "' and '" + entry.getValue() + "'.";
-                
+                String message = "Found duplicate file '" + entry.getKey() + "' from sources '" + protectedFiles.get(entry.getKey())
+                        + "' and '" + entry.getValue() + "'.";
+
                 // INFO for the static ones all others warn
                 if (STATIC_META_INF_FILES.contains(entry.getKey())) {
                     getLog().info(message);
@@ -244,21 +405,23 @@ public class VaultMojo extends AbstractS
                     getLog().warn(message);
                 }
             }
-            contentPackageArchiver.addFileSet(fileSet);
-            
+            addFileSetToArchive(mavenResourcesExection, contentPackageArchiver, fileSet);
+
             // add embedded files
             for (Map.Entry<String, File> entry : embeddedFiles.entrySet()) {
                 protectedFiles.put(new File(entry.getKey()), entry.getValue());
-                contentPackageArchiver.addFile(entry.getValue(), entry.getKey());
+                addFileToArchive(mavenResourcesExection, contentPackageArchiver, entry.getValue(), entry.getKey());
             }
-            
+
             // include content from build only if it exists
             if (jcrSourceDirectory != null && jcrSourceDirectory.exists()) {
-                duplicateFiles.putAll(addSourceDirectory(contentPackageArchiver, jcrSourceDirectory, filters, embeddedFiles));
+                Map<File, File> overwrittenFiles = addSourceDirectory(mavenResourcesExection, contentPackageArchiver, jcrSourceDirectory, filters, embeddedFiles);
+                duplicateFiles.putAll(overwrittenFiles);
 
                 if (!duplicateFiles.isEmpty()) {
                     for (Entry<File, File> entry : duplicateFiles.entrySet()) {
-                        String message = "Found duplicate file '" + entry.getKey() + "' from sources '" + protectedFiles.get(entry.getKey()) + "' and '" + entry.getValue() + "'.";
+                        String message = "Found duplicate file '" + entry.getKey() + "' from sources '" + protectedFiles.get(entry.getKey())
+                                + "' and '" + entry.getValue() + "'.";
                         if (failOnDuplicateEntries) {
                             getLog().error(message);
                         } else {
@@ -266,15 +429,18 @@ public class VaultMojo extends AbstractS
                         }
                     }
                     if (failOnDuplicateEntries) {
-                        throw new MojoFailureException("Found " + duplicateFiles.size() + " duplicate file(s) in content package, see above errors for details.");
+                        throw new MojoFailureException(
+                                "Found " + duplicateFiles.size() + " duplicate file(s) in content package, see above errors for details.");
                     }
                 }
 
                 // 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());
+                Collection<File> uncoveredFiles = getUncoveredFiles(jcrSourceDirectory, excludes, prefix,
+                        contentPackageArchiver.getFiles().keySet());
                 if (!uncoveredFiles.isEmpty()) {
                     for (File uncoveredFile : uncoveredFiles) {
-                        String message = "File '" + uncoveredFile + "' not covered by a filter rule and therefore not contained in the resulting package";
+                        String message = "File '" + uncoveredFile
+                                + "' not covered by a filter rule and therefore not contained in the resulting package";
                         if (failOnUncoveredSourceFiles) {
                             getLog().error(message);
                         } else {
@@ -282,7 +448,8 @@ public class VaultMojo extends AbstractS
                         }
                     }
                     if (failOnUncoveredSourceFiles) {
-                        throw new MojoFailureException("The following files are not covered by a filter rule: \n" + StringUtils.join(uncoveredFiles.iterator(), ",\n"));
+                        throw new MojoFailureException("The following files are not covered by a filter rule: \n"
+                                + StringUtils.join(uncoveredFiles.iterator(), ",\n"));
                     }
                 }
             }
@@ -300,21 +467,22 @@ public class VaultMojo extends AbstractS
             projectArtifact.setFile(finalFile);
             projectArtifact.setArtifactHandler(artifactHandlerManager.getArtifactHandler(PACKAGE_TYPE));
 
-        } catch (Exception e) {
+        } catch (IllegalStateException | ManifestException | IOException | DependencyResolutionRequiredException | ConfigurationException | MavenFilteringException e) {
             throw new MojoExecutionException(e.toString(), e);
         }
     }
 
-    private Map<File, File> addSourceDirectory(ContentPackageArchiver contentPackageArchiver, File jcrSourceDirectory, Filters filters, Map<String, File> embeddedFiles) {
+    private Map<File, File> addSourceDirectory(MavenResourcesExecution mavenResourcesExecution, ContentPackageArchiver contentPackageArchiver, File jcrSourceDirectory, Filters filters,
+            Map<String, File> embeddedFiles) throws MavenFilteringException {
         Map<File, File> duplicateFiles = new HashMap<>();
         // 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()) {
-            FileSet fileSet = createFileSet(jcrSourceDirectory, Constants.ROOT_DIR + prefix);
+            DefaultFileSet fileSet = createFileSet(jcrSourceDirectory, Constants.ROOT_DIR + prefix);
             duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, false));
-            contentPackageArchiver.addFileSet(fileSet);
+            addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
         } else {
             for (PathFilterSet filterSet : filterSets) {
                 String relPath = PlatformNameFormat.getPlatformPath(filterSet.getRoot());
@@ -332,7 +500,7 @@ public class VaultMojo extends AbstractS
                     if (isOverwritingProtectedFile(new File(destPath), sourceFile, false)) {
                         duplicateFiles.put(new File(destPath), sourceFile);
                     }
-                    contentPackageArchiver.addFile(sourceFile, destPath);
+                    addFileToArchive(mavenResourcesExecution, contentPackageArchiver, sourceFile, destPath);
                     // root path for ancestors is the parent directory
                 } else {
                     sourceFile = new File(jcrSourceDirectory, relPath);
@@ -343,12 +511,12 @@ public class VaultMojo extends AbstractS
                         sourceFile = sourceFile.getParentFile();
                         relPath = StringUtils.chomp(relPath, "/");
                     }
-                    
+
                     if (!jcrSourceDirectory.equals(sourceFile)) {
                         destPath = FileUtils.normalize(Constants.ROOT_DIR + prefix + relPath);
-                        FileSet fileSet = createFileSet(sourceFile, destPath + "/");
+                        DefaultFileSet fileSet = createFileSet(sourceFile, destPath + "/");
                         duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, false));
-                        contentPackageArchiver.addFileSet(fileSet);
+                        addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
                     }
                 }
                 // similar to AbstractExporter all ancestors should be contained as well (see AggregateImpl.prepare(...))
@@ -366,43 +534,44 @@ public class VaultMojo extends AbstractS
         // is there an according .content.xml available? (ignore full-coverage files)
         File genericAggregate = new File(inputFile, Constants.DOT_CONTENT_XML);
         if (genericAggregate.exists()) {
-            contentPackageArchiver.addFile(genericAggregate, 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
+    /** 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 {@link coveredFiles}
      * @param coveredFileNames the covered file names (should have relative file names), might have OS specific separators
      * @param additionalExcludes the file name patterns to exclude from the source directory (in addition to the default excludes)
-     * @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) {
+     * @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());
-        
+                .map(File::new)
+                .collect(Collectors.toList());
+
         /*
-         *  similar method as in {@link org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection#getResources();}
+         * 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) {
+    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()))) {
@@ -422,7 +591,7 @@ public class VaultMojo extends AbstractS
         }
         // use the manifest being generated beforehand
         archive.setManifestFile(manifestFile);
-        
+
         return archive;
     }
 }

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilteringIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilteringIT.java?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilteringIT.java (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilteringIT.java Tue Nov 26 17:41:25 2019
@@ -0,0 +1,55 @@
+/*
+ * 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.it;
+
+import java.io.IOException;
+
+import org.apache.maven.it.VerificationException;
+import org.junit.Test;
+
+/**
+ * Tests the behaviour of Maven filtering in packages.
+ */
+public class FilteringIT {
+
+    private ProjectBuilder verify(String projectName, String expectedFilesWithChecksumsFile, boolean enableJcrRootFiltering, boolean enableMetaInfFiltering, String ... goals) throws VerificationException, IOException {
+        return new ProjectBuilder()
+                .setTestProjectDir("filtering-tests/" + projectName)
+                .setTestGoals(goals)
+                .setProperty("vault.enableMetaInfFiltering", Boolean.toString(enableMetaInfFiltering))
+                .setProperty("vault.enableJcrRootFiltering", Boolean.toString(enableJcrRootFiltering))
+                .setExpectedFilesWithChecksumsFile(expectedFilesWithChecksumsFile)
+                .build() 
+                .verifyExpectedFilesChecksum();
+    }
+
+    /**
+     * Tests if a pom with no filter definition at all fails.
+     */
+    @Test
+    public void test_simple_filter_with_filtering_enabled() throws Exception {
+        verify("simple-filter", "expected-files-with-checksums-filtered.txt", true, true);
+    }
+
+    /**
+     * Tests if a pom with no filter definition at all fails.
+     */
+    @Test
+    public void test_simple_filter_with_filtering_disabled() throws Exception {
+        verify("simple-filter", "expected-files-with-checksums-unfiltered.txt", false, false);
+    }
+}

Modified: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java?rev=1870467&r1=1870466&r2=1870467&view=diff
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java (original)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java Tue Nov 26 17:41:25 2019
@@ -27,6 +27,8 @@ import static org.junit.Assert.fail;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -46,6 +48,8 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.BoundedReader;
 import org.apache.maven.it.VerificationException;
 import org.apache.maven.it.Verifier;
 import org.apache.maven.model.Model;
@@ -54,7 +58,10 @@ import org.apache.maven.shared.utils.Str
 import org.apache.maven.shared.utils.io.FileUtils;
 import org.apache.maven.shared.utils.io.IOUtil;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.hamcrest.Description;
 import org.hamcrest.Matchers;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Assert;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -213,13 +220,18 @@ public class ProjectBuilder {
         return this;
     }
 
+    public ProjectBuilder setExpectedFilesWithChecksumsFile(String expectedFilesWithChecksumsFile) {
+        this.expectedFilesWithChecksumsFile = new File(testProjectDir, expectedFilesWithChecksumsFile);
+        return this;
+    }
+
     public ProjectBuilder build() throws VerificationException, IOException {
         Verifier verifier = new Verifier(testProjectDir.getAbsolutePath());
         verifier.setSystemProperties(testProperties);
         verifier.setDebug(true);
         verifier.setAutoclean(false);
-        //verifier.setDebugJvm(true);
-
+        // verifier.setDebugJvm(true);
+        // verifier.setMavenDebug(true);
         try {
             verifier.executeGoals(Arrays.asList(testGoals));
             assertFalse("Build expected to fail in project " + testProjectDir.getAbsolutePath(), buildExpectedToFail);
@@ -327,13 +339,45 @@ public class ProjectBuilder {
                 if (entry == null) {
                     fail("Could not find entry with name " + name + " in package " + testPackageFile);
                 }
-                long actualChecksum = entry.getCrc();
-                assertEquals("Checksum of entry with name " + name + " is not equal to the expected value", expectedChecksum, actualChecksum);
+                Assert.assertThat(entry, new JarEntryMatcher(jar, expectedChecksum));
             }
         }
         return this;
     }
-    
+
+    private final static class JarEntryMatcher extends TypeSafeMatcher<JarEntry> {
+
+        private final long expectedCrc; 
+        private final JarFile jarFile;
+        public JarEntryMatcher(JarFile jarFile, long expectedCrc) {
+            this.jarFile = jarFile;
+            this.expectedCrc = expectedCrc;
+        }
+
+        @Override
+        protected void describeMismatchSafely(JarEntry item, Description mismatchDescription) {
+            mismatchDescription.appendText("was Jar entry with CRC '").appendText(Long.toHexString(item.getCrc())).appendText("'");
+            try (Reader reader = new BoundedReader(new InputStreamReader(jarFile.getInputStream(item), StandardCharsets.UTF_8), 8000)) {
+                String content = IOUtils.toString(reader);
+                // make new line visible
+                content = content.replaceAll("\r", Matcher.quoteReplacement("\r")).replaceAll("\n",  Matcher.quoteReplacement("\n"));
+                mismatchDescription.appendText("(").appendValue(content).appendText(")");
+            } catch (IOException e) {
+                mismatchDescription.appendText("(Could not extract value due to exception ").appendValue(e).appendText(")");
+            }
+        }
+
+        @Override
+        protected boolean matchesSafely(JarEntry item) {
+            return expectedCrc == item.getCrc();
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("having a crc ").appendText(Long.toHexString(expectedCrc));
+        }
+    }
+
     public ProjectBuilder verifyExpectedFilesOrder() throws IOException {
         List<String> expectedEntriesInOrder= Files.readAllLines(expectedOrderFile.toPath(), StandardCharsets.UTF_8);
         assertThat("Order of entries within package", pkgZipEntries, Matchers.containsInRelativeOrder(expectedEntriesInOrder.toArray()));

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/.gitattributes
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/.gitattributes?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/.gitattributes (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/.gitattributes Tue Nov 26 17:41:25 2019
@@ -0,0 +1,2 @@
+# properties files below ITs are checked for checksums, therefore ensure common line breaks
+*.properties text eol=lf
\ No newline at end of file

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-filtered.txt
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-filtered.txt?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-filtered.txt (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-filtered.txt Tue Nov 26 17:41:25 2019
@@ -0,0 +1 @@
+jcr_root/apps/foo/test.properties 10791371
\ No newline at end of file

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-unfiltered.txt
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-unfiltered.txt?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-unfiltered.txt (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/expected-files-with-checksums-unfiltered.txt Tue Nov 26 17:41:25 2019
@@ -0,0 +1 @@
+jcr_root/apps/foo/test.properties 34e5a01d
\ No newline at end of file

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/filter.properties
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/filter.properties?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/filter.properties (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/filter.properties Tue Nov 26 17:41:25 2019
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+customKey=customValue
\ No newline at end of file

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/test.properties
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/test.properties?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/test.properties (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/jcr_root/apps/foo/test.properties Tue Nov 26 17:41:25 2019
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+# only values which are not OS/environment specific should be validated here
+project.name=${project.name}
+customKey=${customKey}
\ No newline at end of file

Added: jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/pom.xml?rev=1870467&view=auto
==============================================================================
--- jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/pom.xml (added)
+++ jackrabbit/commons/filevault-package-maven-plugin/trunk/src/test/resources/test-projects/filtering-tests/simple-filter/pom.xml Tue Nov 26 17:41:25 2019
@@ -0,0 +1,50 @@
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <!-- ====================================================================== -->
+    <!-- P R O J E C T  D E S C R I P T I O N                                   -->
+    <!-- ====================================================================== -->
+    <groupId>org.apache.jackrabbit.filevault</groupId>
+    <artifactId>package-plugin-test-pkg</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>content-package</packaging>
+
+    <description>Test project that defines some inline filters.</description>
+    <name>My Filtering Test</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.jackrabbit</groupId>
+                <artifactId>filevault-package-maven-plugin</artifactId>
+                <version>${plugin.version}</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <filters>
+                        <filter>
+                            <root>/apps/foo</root>
+                        </filter>
+                    </filters>
+                    <filterFiles>
+                        <filterFile>filter.properties</filterFile>
+                    </filterFiles>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>