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 2021/05/03 09:49:13 UTC

[jackrabbit-filevault-package-maven-plugin] branch feature/csv-report created (now 9d93916)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a change to branch feature/csv-report
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault-package-maven-plugin.git.


      at 9d93916  JCRVLT-518 optionally generate CSV report

This branch includes the following new commits:

     new 9d93916  JCRVLT-518 optionally generate CSV report

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[jackrabbit-filevault-package-maven-plugin] 01/01: JCRVLT-518 optionally generate CSV report

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/csv-report
in repository https://gitbox.apache.org/repos/asf/jackrabbit-filevault-package-maven-plugin.git

commit 9d939167483e06f59049b071b601f035b23943f3
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Mon May 3 11:48:55 2021 +0200

    JCRVLT-518 optionally generate CSV report
---
 pom.xml                                            |  5 ++
 .../maven/packaging/AbstractValidateMojo.java      | 92 ++++++++++++----------
 .../maven/packaging/ValidateFilesMojo.java         | 24 +++---
 .../maven/packaging/ValidatePackageMojo.java       | 26 +++---
 .../maven/packaging/ValidationHelper.java          | 56 ++++++++++---
 .../maven/packaging/AbstractValidateMojoTest.java  | 15 ++--
 .../maven/packaging/GenerateMetadataMojoTest.java  |  5 +-
 .../maven/packaging/SimpleEmbeddedTest.java        | 16 ++--
 .../filevault/maven/packaging/VaultMojoTest.java   |  5 +-
 .../maven/packaging/it/DefaultProjectIT.java       |  5 +-
 .../maven/packaging/it/ProjectBuilder.java         | 14 ++--
 11 files changed, 156 insertions(+), 107 deletions(-)

diff --git a/pom.xml b/pom.xml
index a4707cd..07ab4f9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -429,6 +429,11 @@
             <scope>compile</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-csv</artifactId>
+            <version>1.8</version>
+        </dependency>
         <!-- testing -->
         <dependency>
             <groupId>org.hamcrest</groupId>
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojo.java
index 236fd76..a8f864d 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojo.java
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.filevault.maven.packaging;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -26,6 +27,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.stream.Collectors;
 
+import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jackrabbit.filevault.maven.packaging.validator.impl.context.DependencyResolver;
 import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
@@ -154,6 +156,9 @@ public abstract class AbstractValidateMojo extends AbstractMojo {
     @Parameter(property = "vault.package.dependency.to.maven.ga")
     protected Collection<String> mapPackageDependencyToMavenGa;
 
+    @Parameter(property = "vault.validation.csvReportFile")
+    protected File csvReportFile;
+
     @Component
     protected RepositorySystem repositorySystem;
 
@@ -165,8 +170,6 @@ public abstract class AbstractValidateMojo extends AbstractMojo {
 
     protected final ValidationExecutorFactory validationExecutorFactory;
 
-    protected final ValidationHelper validationHelper;
-
     protected DependencyResolver resolver;
     
     /**
@@ -181,7 +184,6 @@ public abstract class AbstractValidateMojo extends AbstractMojo {
     public AbstractValidateMojo() {
         super();
         this.validationExecutorFactory = new ValidationExecutorFactory(this.getClass().getClassLoader());
-        this.validationHelper = new ValidationHelper();
     }
 
     static Map<Dependency, Artifact> resolveMap(Collection<String> mapPackageDependencyToMavenGa) {
@@ -212,49 +214,57 @@ public abstract class AbstractValidateMojo extends AbstractMojo {
         }
         translateLegacyParametersToValidatorParameters();
         final Collection<PackageInfo> resolvedDependencies = new LinkedList<>();
-        if (project != null) {
-            validationHelper.clearPreviousValidationMessages(buildContext, project.getBasedir());
-        }
+        
         // repository structure only defines valid roots
         // https://github.com/apache/jackrabbit-filevault-package-maven-plugin/blob/02a853e64d985f075fe88d19101d7c66d741767f/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/impl/DependencyValidator.java#L51
-        try {
-            Collection<String> validRoots = new LinkedList<>();
-            for (PackageInfo packageInfo : getPackageInfoFromMavenBasedDependencies(repositoryStructurePackages)) {
-                for (PathFilterSet set : packageInfo.getFilter().getFilterSets()) {
-                    validRoots.add(set.getRoot());
-                }
+        try (ValidationHelper validationHelper = new ValidationHelper()) {
+            if (csvReportFile != null) {
+                validationHelper.setCsvFile(csvReportFile, StandardCharsets.UTF_8, CSVFormat.EXCEL);
             }
-            if (!validRoots.isEmpty()) {
-                ValidatorSettings settings = null;
-                if (validatorsSettings != null) {
-                    settings = validatorsSettings.get(AdvancedFilterValidatorFactory.ID);
-                } else {
-                    validatorsSettings = new HashMap<>();
+            if (project != null) {
+                validationHelper.clearPreviousValidationMessages(buildContext, project.getBasedir());
+            }
+            try {
+                Collection<String> validRoots = new LinkedList<>();
+                for (PackageInfo packageInfo : getPackageInfoFromMavenBasedDependencies(repositoryStructurePackages)) {
+                    for (PathFilterSet set : packageInfo.getFilter().getFilterSets()) {
+                        validRoots.add(set.getRoot());
+                    }
                 }
-                if (settings == null) {
-                    settings = new ValidatorSettings();
-                    settings.addOption(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS, StringUtils.join(validRoots, ","));
-                    validatorsSettings.put(AdvancedFilterValidatorFactory.ID, settings);
-                } else {
-                    String oldValidRoots = settings.getOptions().get(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS);
-                    settings.addOption(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS, oldValidRoots + "," + StringUtils.join(validRoots, ","));
+                if (!validRoots.isEmpty()) {
+                    ValidatorSettings settings = null;
+                    if (validatorsSettings != null) {
+                        settings = validatorsSettings.get(AdvancedFilterValidatorFactory.ID);
+                    } else {
+                        validatorsSettings = new HashMap<>();
+                    }
+                    if (settings == null) {
+                        settings = new ValidatorSettings();
+                        settings.addOption(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS, StringUtils.join(validRoots, ","));
+                        validatorsSettings.put(AdvancedFilterValidatorFactory.ID, settings);
+                    } else {
+                        String oldValidRoots = settings.getOptions().get(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS);
+                        settings.addOption(AdvancedFilterValidatorFactory.OPTION_VALID_ROOTS, oldValidRoots + "," + StringUtils.join(validRoots, ","));
+                    }
                 }
+            } catch (IOException e) {
+                throw new MojoExecutionException("Could not get meta information for repositoryStructurePackages '"
+                        + StringUtils.join(repositoryStructurePackages, ",") + "': " + e.getMessage(), e);
             }
+            try {
+                resolvedDependencies.addAll(getPackageInfoFromMavenBasedDependencies(dependencies));
+            } catch (IOException e) {
+                throw new MojoExecutionException(
+                        "Could not get meta information for dependencies '" + StringUtils.join(dependencies, ",") + "': " + e.getMessage(),
+                        e);
+            }
+            // resolve mapping map
+            resolver = new DependencyResolver(DefaultRepositoryRequest.getRepositoryRequest(session, project), repositorySystem,
+                    resolutionErrorHandler, resolveMap(mapPackageDependencyToMavenGa), resolvedDependencies);
+            doExecute(validationHelper);
         } catch (IOException e) {
-            throw new MojoExecutionException("Could not get meta information for repositoryStructurePackages '"
-                    + StringUtils.join(repositoryStructurePackages, ",") + "': " + e.getMessage(), e);
-        }
-        try {
-            resolvedDependencies.addAll(getPackageInfoFromMavenBasedDependencies(dependencies));
-        } catch (IOException e) {
-            throw new MojoExecutionException(
-                    "Could not get meta information for dependencies '" + StringUtils.join(dependencies, ",") + "': " + e.getMessage(),
-                    e);
+            throw new MojoExecutionException("Could not create/write to CSV File", e);
         }
-        // resolve mapping map
-        resolver = new DependencyResolver(DefaultRepositoryRequest.getRepositoryRequest(session, project), repositorySystem,
-                resolutionErrorHandler, resolveMap(mapPackageDependencyToMavenGa), resolvedDependencies);
-        doExecute();
     }
 
     private Collection<PackageInfo> getPackageInfoFromMavenBasedDependencies(Collection<MavenBasedPackageDependency> dependencies) throws IOException {
@@ -312,12 +322,12 @@ public abstract class AbstractValidateMojo extends AbstractMojo {
         filterValidatorSettings.addOption(AdvancedFilterValidatorFactory.OPTION_SEVERITY_FOR_ORPHANED_FILTER_RULES, "debug");
     }
     
-    public abstract void doExecute() throws MojoExecutionException, MojoFailureException;
-    
+    public abstract void doExecute(ValidationHelper validationHelper) throws MojoExecutionException, MojoFailureException;
+
     protected Map<String, ValidatorSettings> getValidatorSettingsForPackage(PackageId packageId, boolean isSubPackage) {
         return getValidatorSettingsForPackage(getLog(), validatorsSettings, packageId, isSubPackage);
     }
-        
+
     static Map<String, ValidatorSettings> getValidatorSettingsForPackage(Log log, Map<String, ValidatorSettings> validatorsSettings, PackageId packageId, boolean isSubPackage) {
         Map<String, ValidatorSettings> validatorSettingsById = new HashMap<>();
         if (validatorsSettings == null) {
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidateFilesMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidateFilesMojo.java
index d2c0190..995602f 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidateFilesMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidateFilesMojo.java
@@ -168,7 +168,7 @@ public class ValidateFilesMojo extends AbstractValidateMojo {
     }
 
     @Override
-    public void doExecute() throws MojoExecutionException, MojoFailureException {
+    public void doExecute(ValidationHelper validationHelper) throws MojoExecutionException, MojoFailureException {
         disableChecksOnlyWorkingForPackages();
         try {
             File metaInfoVaultSourceDirectory = AbstractMetadataPackageMojo.getMetaInfVaultSourceDirectory(metaInfVaultDirectory, getLog());
@@ -185,12 +185,12 @@ public class ValidateFilesMojo extends AbstractValidateMojo {
             }
             validationHelper.printUsedValidators(getLog(), executor, context, true);
             if (metaInfRootDirectory != null) {
-                validateDirectory(executor, metaInfRootDirectory, true);
+                validateDirectory(validationHelper, executor, metaInfRootDirectory, true);
             }
-            validateDirectory(executor, generatedMetaInfRootDirectory, true);
+            validateDirectory(validationHelper, executor, generatedMetaInfRootDirectory, true);
             File jcrSourceDirectory = AbstractSourceAndMetadataPackageMojo.getJcrSourceDirectory(jcrRootSourceDirectory, builtContentDirectory, getLog());
             if (jcrSourceDirectory != null) {
-                validateDirectory(executor, jcrSourceDirectory, false);
+                validateDirectory(validationHelper, executor, jcrSourceDirectory, false);
             }
             validationHelper.printMessages(executor.done(), getLog(), buildContext, project.getBasedir().toPath());
         } catch (IOException | ConfigurationException e) {
@@ -199,7 +199,7 @@ public class ValidateFilesMojo extends AbstractValidateMojo {
         validationHelper.failBuildInCaseOfViolations(failOnValidationWarnings);
     }
 
-    private void validateDirectory(ValidationExecutor executor, File baseDir, boolean isMetaInf) {
+    private void validateDirectory(ValidationHelper validationHelper, ValidationExecutor executor, File baseDir, boolean isMetaInf) {
         Scanner scanner = buildContext.newScanner(baseDir);
         // make sure filtering does work equally as within the package goal
         scanner.setExcludes(excludes);
@@ -209,20 +209,20 @@ public class ValidateFilesMojo extends AbstractValidateMojo {
         List<String> sortedFileNames = Arrays.asList(scanner.getIncludedFiles());
         sortedFileNames.sort(new DotContentXmlFirstComparator());
         for (String fileName : sortedFileNames) {
-            validateFile(executor, baseDir, isMetaInf, fileName);
+            validateFile(validationHelper, executor, baseDir, isMetaInf, fileName);
         }
         for (String relativeFile : scanner.getIncludedDirectories()) {
-            validateFolder(executor, baseDir, isMetaInf, relativeFile);
+            validateFolder(validationHelper, executor, baseDir, isMetaInf, relativeFile);
         }
     }
 
 
-    private void validateFile(ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
+    private void validateFile(ValidationHelper validationHelper, ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
         File absoluteFile = new File(baseDir, relativeFile);
         validationHelper.clearPreviousValidationMessages(buildContext, absoluteFile);
         getLog().debug("Validating file " + getProjectRelativeFilePath(absoluteFile) + "...");
         try (InputStream input = new FileInputStream(absoluteFile)) {
-            validateInputStream(executor, input, baseDir, isMetaInf, relativeFile);
+            validateInputStream(validationHelper, executor, input, baseDir, isMetaInf, relativeFile);
         } catch (FileNotFoundException e) {
             getLog().error("Could not find file " + getProjectRelativeFilePath(absoluteFile), e);
         } catch (IOException e) {
@@ -230,18 +230,18 @@ public class ValidateFilesMojo extends AbstractValidateMojo {
         }
     }
     
-    private void validateFolder(ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
+    private void validateFolder(ValidationHelper validationHelper, ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
         File absoluteFile = new File(baseDir, relativeFile);
         validationHelper.clearPreviousValidationMessages(buildContext, absoluteFile);
         getLog().debug("Validating folder " + getProjectRelativeFilePath(absoluteFile) + "...");
         try {
-            validateInputStream(executor, null, baseDir, isMetaInf, relativeFile);
+            validateInputStream(validationHelper, executor, null, baseDir, isMetaInf, relativeFile);
         } catch (IOException e) {
             getLog().error("Could not validate folder " + getProjectRelativeFilePath(absoluteFile), e);
         }
     }
     
-    private void validateInputStream(ValidationExecutor executor, InputStream input, File baseDir, boolean isMetaInf, String relativeFile) throws IOException {
+    private void validateInputStream(ValidationHelper validationHelper, ValidationExecutor executor, InputStream input, File baseDir, boolean isMetaInf, String relativeFile) throws IOException {
         final Collection<ValidationViolation> messages;
         if (isMetaInf) {
             messages = executor.validateMetaInf(input, Paths.get(relativeFile), baseDir.toPath());
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidatePackageMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidatePackageMojo.java
index 748e322..f334b99 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidatePackageMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidatePackageMojo.java
@@ -80,18 +80,18 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
     }
 
     @Override
-    public void doExecute() throws MojoExecutionException, MojoFailureException {
+    public void doExecute(ValidationHelper validationHelper) throws MojoExecutionException, MojoFailureException {
         try {
             boolean foundPackage = false;
             if (packageFile != null && !packageFile.isDirectory()) {
-                validatePackage(packageFile);
+                validatePackage(validationHelper, packageFile);
                 foundPackage = true;
             } 
             if (!attachedArtifacts.isEmpty()) {
                 for (Artifact attached : attachedArtifacts) {
                     // validate attached artifacts with given classifiers
                     if (classifiers.contains(attached.getClassifier())) {
-                        validatePackage(attached.getFile());
+                        validatePackage(validationHelper, attached.getFile());
                         foundPackage = true;
                     }
                 }
@@ -105,7 +105,7 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
         }
     }
 
-    private void validatePackage(File file) throws IOException, ParserConfigurationException, SAXException, MojoExecutionException {
+    private void validatePackage(ValidationHelper validationHelper, File file) throws IOException, ParserConfigurationException, SAXException, MojoExecutionException {
         getLog().info("Start validating package " + getProjectRelativeFilePath(file) + "...");
 
         // open file to extract the meta data for the validation context
@@ -117,7 +117,7 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
             executor = validationExecutorFactory.createValidationExecutor(context, false, enforceRecursiveSubpackageValidation, getValidatorSettingsForPackage(context.getProperties().getId(), false));
             if (executor != null) {
                 validationHelper.printUsedValidators(getLog(), executor, context, true);
-                validateArchive(archive, file.toPath(), context, executor);
+                validateArchive(validationHelper, archive, file.toPath(), context, executor);
             } else {
                 throw new MojoExecutionException("No registered validators found!");
             }
@@ -125,13 +125,13 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
         }
     }
 
-    private void validateArchive(Archive archive, Path path, ArchiveValidationContextImpl context,
+    private void validateArchive(ValidationHelper validationHelper, Archive archive, Path path, ArchiveValidationContextImpl context,
             ValidationExecutor executor) throws IOException, SAXException, ParserConfigurationException {
-        validateEntry(archive, archive.getRoot(), Paths.get(""), path, context, executor);
+        validateEntry(validationHelper, archive, archive.getRoot(), Paths.get(""), path, context, executor);
         validationHelper.printMessages(executor.done(), getLog(), buildContext, packageFile.toPath());
     }
 
-    private void validateEntry(Archive archive, Archive.Entry entry, Path entryPath, Path packagePath, ArchiveValidationContextImpl context,
+    private void validateEntry(ValidationHelper validationHelper, Archive archive, Archive.Entry entry, Path entryPath, Path packagePath, ArchiveValidationContextImpl context,
             ValidationExecutor executor) throws IOException, SAXException, ParserConfigurationException {
         // sort children to make sure that .content.xml comes first!
         List<Archive.Entry> sortedEntryList = new ArrayList<Archive.Entry>(entry.getChildren());
@@ -139,17 +139,17 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
         
         for (Archive.Entry childEntry : sortedEntryList) {
             if (childEntry.isDirectory()) {
-                validateInputStream(null, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
-                validateEntry(archive, childEntry, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
+                validateInputStream(validationHelper, null, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
+                validateEntry(validationHelper, archive, childEntry, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
             } else {
                 try (InputStream input = archive.openInputStream(childEntry)) {
-                    validateInputStream(input, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
+                    validateInputStream(validationHelper, input, entryPath.resolve(childEntry.getName()), packagePath, context, executor);
                 }
             }
         }
     }
 
-    private void validateInputStream(@Nullable InputStream inputStream, Path entryPath, Path packagePath, ArchiveValidationContextImpl context,
+    private void validateInputStream(ValidationHelper validationHelper, @Nullable InputStream inputStream, Path entryPath, Path packagePath, ArchiveValidationContextImpl context,
             ValidationExecutor executor) throws IOException, SAXException, ParserConfigurationException {
         Collection<ValidationViolation> messages = new LinkedList<>();
         if (entryPath.startsWith(Constants.META_INF)) {
@@ -171,7 +171,7 @@ public class ValidatePackageMojo extends AbstractValidateMojo {
                         .createValidationExecutor(subPackageValidationContext, true, enforceRecursiveSubpackageValidation, getValidatorSettingsForPackage(subPackageValidationContext.getProperties().getId(), true));
                 if (subPackageValidationExecutor != null) {
                     validationHelper.printUsedValidators(getLog(), executor, subPackageValidationContext, false);
-                    validateArchive(subArchive, subPackagePath, subPackageValidationContext, subPackageValidationExecutor);
+                    validateArchive(validationHelper, subArchive, subPackagePath, subPackageValidationContext, subPackageValidationExecutor);
                 } else {
                     getLog().debug("Skip validating sub package as no validator is interested in it.");
                 }
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidationHelper.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidationHelper.java
index 7c6f7c9..c7bc96d 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidationHelper.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/ValidationHelper.java
@@ -16,22 +16,31 @@
  */
 package org.apache.jackrabbit.filevault.maven.packaging;
 
+import java.io.Closeable;
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
 import java.nio.file.Path;
+import java.text.MessageFormat;
 import java.util.Collection;
 import java.util.Map;
 
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jackrabbit.vault.validation.ValidationExecutor;
 import org.apache.jackrabbit.vault.validation.ValidationViolation;
 import org.apache.jackrabbit.vault.validation.spi.ValidationContext;
+import org.apache.jackrabbit.vault.validation.spi.ValidationMessageSeverity;
 import org.apache.jackrabbit.vault.validation.spi.Validator;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.logging.Log;
 import org.sonatype.plexus.build.incremental.BuildContext;
 import org.sonatype.plexus.build.incremental.DefaultBuildContext;
 
-public class ValidationHelper {
+public class ValidationHelper implements Closeable {
 
     /**
      * Set to {@code true} if at least one {@link ValidationViolation} has been given out
@@ -42,6 +51,8 @@ public class ValidationHelper {
      * Set to {@code true} if at least one validation violation with severity {@link ValidationMessageSeverity#ERROR} has been given out
      */
     private int noOfEmittedValidationMessagesWithLevelError = 0;
+    
+    private CSVPrinter csvPrinter = null;
 
     protected ValidationHelper() {
     }
@@ -53,8 +64,9 @@ public class ValidationHelper {
      * @param log
      * @param buildContext
      * @param baseDirectory the directory to which all absolute paths should be made relative (i.e. the Maven basedir)
+     * @throws IOException 
      */
-    public void printMessages(Collection<ValidationViolation> violations, Log log, BuildContext buildContext, Path baseDirectory) {
+    public void printMessages(Collection<ValidationViolation> violations, Log log, BuildContext buildContext, Path baseDirectory) throws IOException {
         for (ValidationViolation violation : violations) {
             final int buildContextSeverity;
                 switch (violation.getSeverity()) {
@@ -83,16 +95,22 @@ public class ValidationHelper {
                         buildContextSeverity = -1;
                         break;
             }
-            // only emit via build context inside eclipse, otherwise log from above is better!
-            if (buildContextSeverity > 0 && !(buildContext instanceof DefaultBuildContext)) {
-                File file;
-                if (violation.getAbsoluteFilePath() != null) {
-                    file = violation.getAbsoluteFilePath().toFile();
-                } else {
-                    // take the base path
-                    file = baseDirectory.toFile();
+               
+            if (buildContextSeverity > 0) {
+                // only emit via build context inside eclipse, otherwise log from above is better!
+                if (!(buildContext instanceof DefaultBuildContext)) {
+                    Path file;
+                    if (violation.getAbsoluteFilePath() != null) {
+                        file = violation.getAbsoluteFilePath();
+                    } else {
+                        // take the base path
+                        file = baseDirectory;
+                    }
+                    buildContext.addMessage(file.toFile(), violation.getLine(), violation.getColumn(), getMessage(violation), buildContextSeverity, violation.getThrowable());
+                }
+                if (!buildContext.isIncremental() && csvPrinter != null) {
+                    printToCsvFile(violation);
                 }
-                buildContext.addMessage(file, violation.getLine(), violation.getColumn(), getMessage(violation), buildContextSeverity, violation.getThrowable());
             }
         }
     }
@@ -160,4 +178,20 @@ public class ValidationHelper {
             throw new MojoFailureException("Found " + noOfEmittedValidationMessagesWithLevelError + " violation(s) (with severity=ERROR). Check above errors for details");
         }
     }
+
+    public void setCsvFile(File csvReportFile, Charset charset, CSVFormat format) throws IOException {
+        csvPrinter = new CSVPrinter(new OutputStreamWriter(new FileOutputStream(csvReportFile), charset), format);
+        csvPrinter.printRecord("Severity", "Validator ID", "Message", "File", "Line:Column", "Node Path");
+    }
+
+    private void printToCsvFile(ValidationViolation violation) throws IOException {
+        csvPrinter.printRecord(violation.getSeverity(), violation.getValidatorId(), violation.getMessage(), violation.getAbsoluteFilePath(), MessageFormat.format("{0}:{1}", violation.getLine(), violation.getColumn()), violation.getNodePath());
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (csvPrinter != null) {
+            csvPrinter.close();
+        }
+    }
 }
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojoTest.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojoTest.java
index 44c39b0..21063ad 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojoTest.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractValidateMojoTest.java
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.filevault.maven.packaging;
 
-import static org.junit.Assert.assertThat;
-
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -28,6 +26,7 @@ import org.apache.jackrabbit.vault.packaging.PackageId;
 import org.apache.maven.artifact.DefaultArtifact;
 import org.apache.maven.artifact.InvalidArtifactRTException;
 import org.apache.maven.plugin.logging.SystemStreamLog;
+import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
@@ -36,7 +35,7 @@ public class AbstractValidateMojoTest {
 
     @Test
     public void testValidMapWithIgnoredArtifacts() {
-        Assert.assertThat(AbstractValidateMojo.resolveMap(Arrays.asList("group1:name1=ignore", "group2:name2=groupId2:artifactId2")), 
+        MatcherAssert.assertThat(AbstractValidateMojo.resolveMap(Arrays.asList("group1:name1=ignore", "group2:name2=groupId2:artifactId2")), 
                 Matchers.allOf(
                     Matchers.hasEntry(Dependency.fromString("group1:name1"), AbstractValidateMojo.IGNORE_ARTIFACT),
                     Matchers.hasEntry(Dependency.fromString("group2:name2"), new DefaultArtifact("groupId2", "artifactId2", "", "", "", "", null)),
@@ -45,7 +44,7 @@ public class AbstractValidateMojoTest {
 
     @Test
     public void testValidMap() {
-        Assert.assertThat(AbstractValidateMojo.resolveMap(Arrays.asList("group1:name1=groupId1:artifactId1", "group2:name2=groupId2:artifactId2")), 
+        MatcherAssert.assertThat(AbstractValidateMojo.resolveMap(Arrays.asList("group1:name1=groupId1:artifactId1", "group2:name2=groupId2:artifactId2")), 
                 Matchers.allOf(
                     Matchers.hasEntry(Dependency.fromString("group1:name1"), new DefaultArtifact("groupId1", "artifactId1", "", "", "", "", null)),
                     Matchers.hasEntry(Dependency.fromString("group2:name2"), new DefaultArtifact("groupId2", "artifactId2", "", "", "", "", null)),
@@ -77,21 +76,21 @@ public class AbstractValidateMojoTest {
         Map<String, ValidatorSettings> expectedValidatorSettings = new HashMap<>();
         expectedValidatorSettings.put("id1", new ValidatorSettings().addOption("id1", "foo"));
         expectedValidatorSettings.put("id2", new ValidatorSettings().addOption("id2", "foo"));
-        Assert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
+        MatcherAssert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
         
         actualValidatorSettings = AbstractValidateMojo.getValidatorSettingsForPackage(new SystemStreamLog(), validatorsSettings, PackageId.fromString("mygroup:myname:1.0.0"), true);
         expectedValidatorSettings.put("id3", new ValidatorSettings().addOption("id3", "foo"));
-        Assert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
+        MatcherAssert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
         
         actualValidatorSettings = AbstractValidateMojo.getValidatorSettingsForPackage(new SystemStreamLog(), null, PackageId.fromString("mygroup:myname:1.0.0"), true);
         expectedValidatorSettings.clear();
-        Assert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
+        MatcherAssert.assertThat(actualValidatorSettings, Matchers.equalTo(expectedValidatorSettings));
     }
 
     @Test
     public void testDotContentXmlFirstComparator() {
         List<String> list = Arrays.asList("someEntryA", ".content.xml", "someEntryB", ".content.xml");
         list.sort(new AbstractValidateMojo.DotContentXmlFirstComparator());
-        assertThat(list, Matchers.contains(".content.xml", ".content.xml", "someEntryA", "someEntryB"));
+        MatcherAssert.assertThat(list, Matchers.contains(".content.xml", ".content.xml", "someEntryA", "someEntryB"));
     }
 }
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojoTest.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojoTest.java
index 2355ce9..5b2f0d8 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojoTest.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojoTest.java
@@ -38,6 +38,7 @@ import org.apache.jackrabbit.vault.packaging.PackageType;
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.archiver.jar.ManifestException;
+import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
@@ -114,11 +115,11 @@ public class GenerateMetadataMojoTest {
                     if (expectedAttributeValuePattern == null) {
                         Assert.fail("Found unexpected attribute " + attribute.getKey() + " in Manifest");
                     }
-                    Assert.assertThat("Found unexpected attribute value for " + attribute.getKey(), (String)attribute.getValue(), Matchers.matchesPattern(expectedAttributeValuePattern));
+                    MatcherAssert.assertThat("Found unexpected attribute value for " + attribute.getKey(), (String)attribute.getValue(), Matchers.matchesPattern(expectedAttributeValuePattern));
                     expectedAttributes.remove(attribute.getKey().toString());
                 }
             }
-            Assert.assertThat("Not found expected attributes in manifest", expectedAttributes, Matchers.anEmptyMap());
+            MatcherAssert.assertThat("Not found expected attributes in manifest", expectedAttributes, Matchers.anEmptyMap());
         } finally {
             outputFile.delete();
         }
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/SimpleEmbeddedTest.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/SimpleEmbeddedTest.java
index 36b959d..e8ef77e 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/SimpleEmbeddedTest.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/SimpleEmbeddedTest.java
@@ -22,8 +22,8 @@ import java.util.List;
 import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DefaultArtifact;
+import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -50,19 +50,19 @@ public class SimpleEmbeddedTest {
     @Test
     public void testGroupIdOnlyFilter() throws ConfigurationException {
         embedded.setGroupId("mygroupid");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(1), artifacts.get(4), artifacts.get(5), artifacts.get(6)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(1), artifacts.get(4), artifacts.get(5), artifacts.get(6)));
     }
 
     @Test
     public void testArtifactIdOnlyFilter() throws ConfigurationException {
         embedded.setArtifactId("artifact1");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(3), artifacts.get(4)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(3), artifacts.get(4)));
     }
 
     @Test
     public void testTypeBundleOnlyFilter() throws ConfigurationException {
         embedded.setType("bundle");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.contains(artifacts.get(4), artifacts.get(5), artifacts.get(6)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.contains(artifacts.get(4), artifacts.get(5), artifacts.get(6)));
     }
 
     @Test
@@ -70,21 +70,21 @@ public class SimpleEmbeddedTest {
         // in addition filter for jar
         embedded.setType("jar");
         embedded.setType("bundle");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.toArray()));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.toArray()));
     }
 
     @Test
     public void testClassifierOnlyFilter() throws ConfigurationException {
         // in addition filter for jar
         embedded.setClassifier("myclassifier");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.contains(artifacts.get(6)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.contains(artifacts.get(6)));
     }
 
     @Test
     public void testScopeOnlyFilter() {
         // should contain all artifacts with scope "compile", "runtime" or "system"
         embedded.setScope("compile");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(1), artifacts.get(5), artifacts.get(6)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(0), artifacts.get(1), artifacts.get(5), artifacts.get(6)));
     }
 
     @Test
@@ -92,7 +92,7 @@ public class SimpleEmbeddedTest {
         embedded.setType("bundle");
         embedded.setArtifactId("artifact1");
         embedded.setGroupId("mygroupid");
-        Assert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(4)));
+        MatcherAssert.assertThat(embedded.getMatchingArtifacts(artifacts), Matchers.containsInAnyOrder(artifacts.get(4)));
     }
 
     public final static class SimpleArtifact extends DefaultArtifact {
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojoTest.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojoTest.java
index 7536fe4..84e7fce 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojoTest.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojoTest.java
@@ -25,6 +25,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.jackrabbit.filevault.maven.packaging.it.ProjectBuilder;
 import org.codehaus.plexus.archiver.util.DefaultFileSet;
+import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Test;
@@ -37,7 +38,7 @@ public class VaultMojoTest {
         Set<String> excludes = Collections.emptySet();
         File sourceDirectory = new File(ProjectBuilder.TEST_PROJECTS_ROOT, "filter-tests/filter-not-covering-all-files/jcr_root");
         Collection<File> uncoveredFiles = VaultMojo.getUncoveredFiles(sourceDirectory, excludes, prefix, Collections.emptySet());
-        Assert.assertThat(uncoveredFiles, Matchers.contains(new File(sourceDirectory, "apps/.content.xml")));
+        MatcherAssert.assertThat(uncoveredFiles, Matchers.contains(new File(sourceDirectory, "apps/.content.xml")));
     }
 
     @Test
@@ -46,7 +47,7 @@ public class VaultMojoTest {
         File sourceDirectory = new File(ProjectBuilder.TEST_PROJECTS_ROOT, "filter-tests/filter-not-covering-all-files/jcr_root");
         Set<String> entryNames = Collections.singleton(new File("jcr_root/apps/.content.xml").getPath());
         Collection<File> uncoveredFiles = VaultMojo.getUncoveredFiles(sourceDirectory, excludes, "", entryNames);
-        Assert.assertThat(uncoveredFiles, Matchers.empty());
+        MatcherAssert.assertThat(uncoveredFiles, Matchers.empty());
     }
 
     @Test
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/DefaultProjectIT.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/DefaultProjectIT.java
index c8c8445..6b385f3 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/DefaultProjectIT.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/DefaultProjectIT.java
@@ -34,6 +34,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.NullOutputStream;
 import org.apache.jackrabbit.util.ISO8601;
 import org.apache.maven.it.VerificationException;
+import org.hamcrest.MatcherAssert;
 import org.hamcrest.number.OrderingComparison;
 import org.junit.Assert;
 import org.junit.Test;
@@ -118,8 +119,8 @@ public class DefaultProjectIT {
         Calendar date = ISO8601.parse(createdDate);
         assertNotNull("The created date is not compliant to the ISO8601 profile defined in https://www.w3.org/TR/NOTE-datetime", date);
         // check actual value
-        assertThat(date, OrderingComparison.greaterThan(dateBeforeRun));
-        assertThat(date, OrderingComparison.lessThan(dateAfterRun));
+        MatcherAssert.assertThat(date, OrderingComparison.greaterThan(dateBeforeRun));
+        MatcherAssert.assertThat(date, OrderingComparison.lessThan(dateAfterRun));
     
     }
 
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java
index f0ab5b3..3a858ce 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/ProjectBuilder.java
@@ -20,7 +20,6 @@ import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -56,12 +55,11 @@ import org.apache.maven.model.Model;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 import org.apache.maven.shared.utils.StringUtils;
 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.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.hamcrest.TypeSafeMatcher;
-import org.junit.Assert;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -294,7 +292,7 @@ public class ProjectBuilder {
         Properties properties;
         try (ZipFile zip = new ZipFile(testPackageFile)) {
             ZipEntry propertiesFile = zip.getEntry("META-INF/vault/properties.xml");
-            assertThat(propertiesFile, notNullValue());
+            MatcherAssert.assertThat(propertiesFile, notNullValue());
 
             properties = new Properties();
             properties.loadFromXML(zip.getInputStream(propertiesFile));
@@ -362,7 +360,7 @@ public class ProjectBuilder {
             if (entry == null) {
                 fail("Could not find entry with name " + name + " in package " + testPackageFile);
             }
-            Assert.assertThat(entry, new JarEntryMatcher(name, jar, expectedChecksum));
+            MatcherAssert.assertThat(entry, new JarEntryMatcher(name, jar, expectedChecksum));
         }
         return this;
     }
@@ -404,7 +402,7 @@ public class ProjectBuilder {
 
     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()));
+        MatcherAssert.assertThat("Order of entries within package", pkgZipEntries, Matchers.containsInRelativeOrder(expectedEntriesInOrder.toArray()));
         return this;
     }
 
@@ -415,7 +413,7 @@ public class ProjectBuilder {
         try (ZipFile zip = new ZipFile(testPackageFile)) {
             ZipEntry entry = zip.getEntry("META-INF/vault/filter.xml");
             assertNotNull("package has a filter.xml", entry);
-            String result = IOUtil.toString(zip.getInputStream(entry), "utf-8");
+            String result = IOUtils.toString(zip.getInputStream(entry), StandardCharsets.UTF_8);
             String expected = FileUtils.fileRead(expectedFilterFile);
             assertEquals("filter.xml is correct", normalizeWhitespace(expected), normalizeWhitespace(result));
         }
@@ -452,7 +450,7 @@ public class ProjectBuilder {
                 expectedLogLine = matcher.replaceAll(Matcher.quoteReplacement(placeholderValues[placeholderIndex]));
             }
             // update list
-            assertThat("Could not find the expected log line in the output '" + logTxtFile +"'", actualLogLines, Matchers.hasItem(expectedLogLine));
+            MatcherAssert.assertThat("Could not find the expected log line in the output '" + logTxtFile +"'", actualLogLines, Matchers.hasItem(expectedLogLine));
         }
         // support not and exists
         return this;