JCRVLT-471 allow to include additional files/folders in META-INF (#48)
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
index d2d13d7..a3a1a43 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/AbstractMetadataPackageMojo.java
@@ -37,6 +37,10 @@
private static final String PROPERTIES_EMBEDDEDFILESMAP_KEY = "embeddedfiles.map";
+ protected String getProjectRelativeFilePath(File file) {
+ return "'" + project.getBasedir().toPath().relativize(file.toPath()).toString() + "'";
+ }
+
protected static File getFirstExistingDirectory(File[] directories) {
for (File dir: directories) {
if (dir.exists() && dir.isDirectory()) {
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 8c9cd22..236fd76 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
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.filevault.maven.packaging;
+import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
@@ -173,6 +174,10 @@
*/
public static final Artifact IGNORE_ARTIFACT = new DefaultArtifact("ignore", "ignore", "1.0", "", "", "", null);
+ protected String getProjectRelativeFilePath(File file) {
+ return "'" + project.getBasedir().toPath().relativize(file.toPath()).toString() + "'";
+ }
+
public AbstractValidateMojo() {
super();
this.validationExecutorFactory = new ValidationExecutorFactory(this.getClass().getClassLoader());
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
index 13a7860..e5537b4 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/GenerateMetadataMojo.java
@@ -449,9 +449,9 @@
// only execute in case of changes towards the filter.xml as the generated one contains a merge
if (filterSource != null) {
if (buildContext.hasDelta(filterSource)) {
- getLog().debug("Detecting a change on '" + filterSource + "' therefore not cancelling build");
+ getLog().debug("Detecting a change on " + getProjectRelativeFilePath(filterSource) + " therefore not cancelling build");
} else {
- getLog().debug("'" + filterSource + "' unchanged therefore cancelling build");
+ getLog().debug(getProjectRelativeFilePath(filterSource) + " unchanged therefore cancelling build");
return;
}
} else {
@@ -558,7 +558,7 @@
try {
filters.load(filterFile);
} catch (ConfigurationException e) {
- throw new IOException("Error loading filter file '" + filterFile + "'", e);
+ throw new IOException("Error loading filter file " + getProjectRelativeFilePath(filterFile) + "", e);
}
getLog().warn("The project is using a filter.xml provided via the resource plugin.");
@@ -618,7 +618,7 @@
try {
sourceFilters.load(filterSource);
} catch (ConfigurationException e) {
- throw new IOException("Error loading filter file '" + filterSource + "'", e);
+ throw new IOException("Error loading filter file " + getProjectRelativeFilePath(filterSource), e);
}
}
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 af9693c..fd298cb 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
@@ -177,7 +177,7 @@
metaInfRootDirectory = metaInfoVaultSourceDirectory.getParentFile();
}
File generatedMetaInfRootDirectory = new File(workDirectory, Constants.META_INF);
- getLog().info("Using generatedMetaInfRootDirectory: " + generatedMetaInfRootDirectory + " and metaInfRootDir: " + metaInfRootDirectory);
+ getLog().info("Validate files in generatedMetaInfRootDirectory " + getProjectRelativeFilePath(generatedMetaInfRootDirectory) + " and metaInfRootDir " + getProjectRelativeFilePath(generatedMetaInfRootDirectory));
ValidationContext context = new DirectoryValidationContext(generatedMetaInfRootDirectory, metaInfRootDirectory, resolver, getLog());
ValidationExecutor executor = validationExecutorFactory.createValidationExecutor(context, false, false, getValidatorSettingsForPackage(context.getProperties().getId(), false));
if (executor == null) {
@@ -205,7 +205,7 @@
scanner.setExcludes(excludes);
scanner.addDefaultExcludes();
scanner.scan();
- getLog().info("Scanning baseDir '" + baseDir + "'...");
+ getLog().info("Scanning baseDir " + getProjectRelativeFilePath(baseDir) + "...");
List<String> sortedFileNames = Arrays.asList(scanner.getIncludedFiles());
sortedFileNames.sort(new DotContentXmlFirstComparator());
for (String fileName : sortedFileNames) {
@@ -220,24 +220,24 @@
private void validateFile(ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
File absoluteFile = new File(baseDir, relativeFile);
validationHelper.clearPreviousValidationMessages(buildContext, absoluteFile);
- getLog().debug("Validating file '" + absoluteFile + "'...");
+ getLog().debug("Validating file " + getProjectRelativeFilePath(absoluteFile) + "...");
try (InputStream input = new FileInputStream(absoluteFile)) {
validateInputStream(executor, input, baseDir, isMetaInf, relativeFile);
} catch (FileNotFoundException e) {
- getLog().error("Could not find file " + absoluteFile, e);
+ getLog().error("Could not find file " + getProjectRelativeFilePath(absoluteFile), e);
} catch (IOException e) {
- getLog().error("Could not validate file " + absoluteFile, e);
+ getLog().error("Could not validate file " + getProjectRelativeFilePath(absoluteFile), e);
}
}
private void validateFolder(ValidationExecutor executor, File baseDir, boolean isMetaInf, String relativeFile) {
File absoluteFile = new File(baseDir, relativeFile);
validationHelper.clearPreviousValidationMessages(buildContext, absoluteFile);
- getLog().debug("Validating folder '" + absoluteFile + "'...");
+ getLog().debug("Validating folder " + getProjectRelativeFilePath(absoluteFile) + "...");
try {
validateInputStream(executor, null, baseDir, isMetaInf, relativeFile);
} catch (IOException e) {
- getLog().error("Could not validate folder " + absoluteFile, e);
+ getLog().error("Could not validate folder " + getProjectRelativeFilePath(absoluteFile), e);
}
}
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 a7a78f5..748e322 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
@@ -106,7 +106,7 @@
}
private void validatePackage(File file) throws IOException, ParserConfigurationException, SAXException, MojoExecutionException {
- getLog().info("Start validating package '" + file + "'...");
+ getLog().info("Start validating package " + getProjectRelativeFilePath(file) + "...");
// open file to extract the meta data for the validation context
ArchiveValidationContextImpl context;
@@ -121,7 +121,7 @@
} else {
throw new MojoExecutionException("No registered validators found!");
}
- getLog().debug("End validating package '" + file + "'.");
+ getLog().debug("End validating package " + getProjectRelativeFilePath(file) + ".");
}
}
diff --git a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java
index 61ebda2..60c4ff0 100644
--- a/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java
+++ b/src/main/java/org/apache/jackrabbit/filevault/maven/packaging/VaultMojo.java
@@ -79,6 +79,13 @@
@Component
private ArtifactHandlerManager artifactHandlerManager;
+
+ /**
+ * The directory that contains additional files and folders to end up in the package's META-INF folder.
+ * Every file and subfolder is considered except for the subfolder named {@code vault} and a file named {@code MANIFEST.MF}.
+ */
+ @Parameter(property = "vault.metaInfDirectory", required = false)
+ File metaInfDirectory;
/** Set to {@code true} to fail the build in case of files are being contained in the {@code jcrRootSourceDirectory} which are not
* covered by the filter rules and therefore would not end up in the package. */
@@ -235,7 +242,7 @@
Path destFile = Paths.get(destFileName);
if ((destFile.startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
(destFile.startsWith(Constants.META_INF) && enableMetaInfFiltering)) {
- getLog().info("Apply filtering to " + sourceFile);
+ getLog().info("Apply filtering to " + getProjectRelativeFilePath(sourceFile));
Resource resource = new Resource();
resource.setDirectory(sourceFile.getParent());
resource.setIncludes(Collections.singletonList(sourceFile.getName()));
@@ -243,7 +250,7 @@
File newTargetDirectory = applyFiltering(destFile.getParent().toString(), mavenResourcesExecution, resource);
sourceFile = new File(newTargetDirectory, sourceFile.getName());
}
- getLog().debug("Adding file '" + sourceFile + "' to package at '" + destFileName + "'");
+ getLog().debug("Adding file " + getProjectRelativeFilePath(sourceFile) + " to package at " + destFileName + "'");
archiver.addFile(sourceFile, destFileName);
}
@@ -260,7 +267,7 @@
if ((fileSet.getPrefix().startsWith(Constants.ROOT_DIR) && enableJcrRootFiltering) ||
(fileSet.getPrefix().startsWith(Constants.META_INF) && enableMetaInfFiltering)) {
- getLog().info("Apply filtering to FileSet below " + fileSet.getDirectory());
+ getLog().info("Apply filtering to FileSet below " + getProjectRelativeFilePath(fileSet.getDirectory()));
Resource resource = new Resource();
resource.setDirectory(fileSet.getDirectory().getPath());
if (fileSet.getIncludes() != null) {
@@ -377,32 +384,39 @@
public void execute() throws MojoExecutionException, MojoFailureException {
final File finalFile = getZipFile(outputDirectory, finalName, classifier);
- MavenResourcesExecution mavenResourcesExection = setupMavenResourcesExecution();
+ MavenResourcesExecution mavenResourcesExecution = setupMavenResourcesExecution();
try {
- // find the meta-inf source directory
- File metaInfDirectory = getMetaInfVaultSourceDirectory();
- // find the source directory
- final File jcrSourceDirectory = getJcrSourceDirectory();
- if (jcrSourceDirectory != null) {
- getLog().info("Packaging content from " + jcrSourceDirectory.getPath());
+ ContentPackageArchiver contentPackageArchiver = new ContentPackageArchiver();
+ contentPackageArchiver.setEncoding(resourceEncoding);
+
+ if (metaInfDirectory != null) {
+ if (metaInfDirectory.exists() && metaInfDirectory.isDirectory()) {
+ DefaultFileSet fileSet = createFileSet(metaInfDirectory, Constants.META_INF + "/",
+ Collections.singletonList(Constants.VAULT_DIR));
+ addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
+ getLog().info("Include additional META-INF files/folders from " + getProjectRelativeFilePath(metaInfDirectory) + " in package.");
+ } else {
+ getLog().warn("Given metaInfDirectory " + getProjectRelativeFilePath(metaInfDirectory) + " does not exist or is no directory. It won't be included in the package.");
+ }
}
+
+ // find the meta-inf/vault source directory
+ File metaInfVaultDirectory = getMetaInfVaultSourceDirectory();
+
// retrieve filters
Filters filters = loadGeneratedFilterFile();
Map<String, File> embeddedFiles = getEmbeddedFilesMap();
- ContentPackageArchiver contentPackageArchiver = new ContentPackageArchiver();
- contentPackageArchiver.setEncoding(resourceEncoding);
-
// 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) {
+ if (metaInfVaultDirectory != null) {
// first add the metadata from the metaInfDirectory (they should take precedence over the generated ones from workDirectory,
// except for the filter.xml, which should always come from the work directory)
- DefaultFileSet fileSet = createFileSet(metaInfDirectory, Constants.META_DIR + "/",
+ DefaultFileSet fileSet = createFileSet(metaInfVaultDirectory, Constants.META_DIR + "/",
Collections.singletonList(Constants.FILTER_XML));
duplicateFiles.putAll(getOverwrittenProtectedFiles(fileSet, true));
- addFileSetToArchive(mavenResourcesExection, contentPackageArchiver, fileSet);
+ addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
}
// then add all files from the workDirectory (they might overlap with the ones from metaInfDirectory, but the duplicates are
// just ignored in the package)
@@ -410,8 +424,8 @@
// 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 " + getProjectRelativeFilePath(protectedFiles.get(entry.getKey()))
+ + " and " + getProjectRelativeFilePath(entry.getValue()) + ".";
// INFO for the static ones all others warn
if (STATIC_META_INF_FILES.contains(entry.getKey())) {
@@ -420,23 +434,25 @@
getLog().warn(message);
}
}
- addFileSetToArchive(mavenResourcesExection, contentPackageArchiver, fileSet);
+ addFileSetToArchive(mavenResourcesExecution, contentPackageArchiver, fileSet);
// add embedded files
for (Map.Entry<String, File> entry : embeddedFiles.entrySet()) {
protectedFiles.put(new File(entry.getKey()), entry.getValue());
- addFileToArchive(mavenResourcesExection, contentPackageArchiver, entry.getValue(), entry.getKey());
+ addFileToArchive(mavenResourcesExecution, contentPackageArchiver, entry.getValue(), entry.getKey());
}
-
+ // find the source directory
+ final File jcrSourceDirectory = getJcrSourceDirectory();
// include content from build only if it exists
if (jcrSourceDirectory != null && jcrSourceDirectory.exists()) {
- Map<File, File> overwrittenFiles = addSourceDirectory(mavenResourcesExection, contentPackageArchiver, jcrSourceDirectory, filters, embeddedFiles);
+ getLog().info("Packaging content from " + getProjectRelativeFilePath(jcrSourceDirectory));
+ Map<File, File> overwrittenFiles = addSourceDirectory(mavenResourcesExecution, 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 " + getProjectRelativeFilePath(protectedFiles.get(entry.getKey()))
+ + " and " + getProjectRelativeFilePath(entry.getValue()) + ".";
if (failOnDuplicateEntries) {
getLog().error(message);
} else {
@@ -454,8 +470,8 @@
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 " + getProjectRelativeFilePath(uncoveredFile)
+ + " not covered by a filter rule and therefore not contained in the resulting package";
if (failOnUncoveredSourceFiles) {
getLog().error(message);
} else {
@@ -573,7 +589,7 @@
// is there an according .content.xml available? (ignore full-coverage files)
File genericAggregate = new File(inputFile, Constants.DOT_CONTENT_XML);
if (genericAggregate.exists()) {
- getLog().debug("Adding ancestor file '" + genericAggregate + "' to package at '" + destFile + "/" + Constants.DOT_CONTENT_XML +"'");
+ getLog().debug("Adding ancestor file " + getProjectRelativeFilePath(genericAggregate) + " to package at '" + destFile + "/" + Constants.DOT_CONTENT_XML +"'");
contentPackageArchiver.addFile(genericAggregate, destFile + "/" + Constants.DOT_CONTENT_XML);
}
addAncestors(contentPackageArchiver, inputFile.getParentFile(), inputRootFile, StringUtils.chomp(destFile, "/"));
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 0e599f6..c8c8445 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
@@ -155,11 +155,20 @@
.build()
.verifyExpectedFilesChecksum();
}
-
+
@Test
public void empty_package() throws VerificationException, IOException {
new ProjectBuilder()
.setTestProjectDir(TEST_PROJECT_NAME + "empty")
.build();
}
+
+ @Test
+ public void additional_metainf_files() throws Exception {
+ new ProjectBuilder()
+ .setTestProjectDir(TEST_PROJECT_NAME + "additional-metainf-files")
+ .build()
+ .verifyExpectedFiles()
+ .verifyExpectedManifest();
+ }
}
diff --git a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilterIT.java b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilterIT.java
index 1961cb0..f0a0daa 100644
--- a/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilterIT.java
+++ b/src/test/java/org/apache/jackrabbit/filevault/maven/packaging/it/FilterIT.java
@@ -154,6 +154,6 @@
@Test
public void test_filter_not_covering_all_files() throws Exception {
ProjectBuilder builder = verify("filter-not-covering-all-files", true);
- builder.verifyExpectedLogLines(new File(builder.getTestProjectDir(), "jcr_root/apps/.content.xml").getAbsolutePath());
+ builder.verifyExpectedLogLines(new File("jcr_root/apps/.content.xml").toString());
}
}
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 4c82551..f0ab5b3 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
@@ -262,7 +262,7 @@
}
static List<String> verifyPackageZipEntries(File packageFile) throws IOException {
- assertTrue("Project generates package file at " + packageFile, packageFile.exists());
+ assertTrue("Project did not generate package file at " + packageFile, packageFile.exists());
List<String> pkgZipEntries = new ArrayList<>();
try (JarFile jar = new JarFile(packageFile)) {
@@ -276,7 +276,7 @@
if ("META-INF/".equals(first)) {
first = pkgZipEntries.get(1);
}
- assertEquals("MANIFEST.MF must be first entry in package " + packageFile, "META-INF/MANIFEST.MF", first);
+ assertEquals("MANIFEST.MF is not first entry in package " + packageFile, "META-INF/MANIFEST.MF", first);
// ensure that there is a jcr_root directory
assertTrue("Package does not contain mandatory 'jcr_root' folder in package " + packageFile, pkgZipEntries.contains("jcr_root/"));
@@ -286,7 +286,7 @@
if (buildExpectedToFail) {
return this;
}
- assertEquals("Property '" + key + "' has correct value", value, getPackageProperty(key));
+ assertEquals("Property '" + key + "' has incorrect value", value, getPackageProperty(key));
return this;
}
@@ -338,7 +338,7 @@
public ProjectBuilder verifyExpectedFiles(File expectedFilesFile, List<String> pkgZipEntries) throws IOException {
// first check that only the expected entries are there in the package (regardless of the order)
List<String> expectedEntries = Files.readAllLines(expectedFilesFile.toPath(), StandardCharsets.UTF_8);
- assertEquals("Package contains the expected entry names",
+ assertEquals("Package does not contain the expected entry names",
toTidyString(expectedEntries),
toTidyString(pkgZipEntries));
return this;
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/MANIFEST.MF b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/MANIFEST.MF
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/MANIFEST.MF
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/license.txt b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/license.txt
new file mode 100644
index 0000000..13cd903
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/license.txt
@@ -0,0 +1,16 @@
+<!--
+ 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.
+ -->
\ No newline at end of file
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/subfolder/anotherfile.txt b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/subfolder/anotherfile.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/additional-metainf/subfolder/anotherfile.txt
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-files.txt b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-files.txt
new file mode 100644
index 0000000..8d9a65d
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-files.txt
@@ -0,0 +1,20 @@
+META-INF/
+META-INF/MANIFEST.MF
+META-INF/license.txt
+META-INF/subfolder/
+META-INF/subfolder/anotherfile.txt
+META-INF/maven/
+META-INF/maven/org.apache.jackrabbit.filevault/
+META-INF/maven/org.apache.jackrabbit.filevault/package-plugin-test-pkg/
+META-INF/maven/org.apache.jackrabbit.filevault/package-plugin-test-pkg/pom.properties
+META-INF/maven/org.apache.jackrabbit.filevault/package-plugin-test-pkg/pom.xml
+META-INF/vault/
+META-INF/vault/config.xml
+META-INF/vault/filter.xml
+META-INF/vault/properties.xml
+META-INF/vault/settings.xml
+jcr_root/
+jcr_root/apps/
+jcr_root/apps/htl/
+jcr_root/apps/htl/test/
+jcr_root/apps/htl/test/test.html
\ No newline at end of file
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-manifest.txt b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-manifest.txt
new file mode 100644
index 0000000..5468d39
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/expected-manifest.txt
@@ -0,0 +1,9 @@
+Content-Package-Description:Packaging test
+Content-Package-Id:org.apache.jackrabbit.filevault:package-plugin-test-pkg:1.0.0-SNAPSHOT
+Content-Package-Roots:/apps/htl/test
+Content-Package-Type:mixed
+Implementation-Title:Packaging test
+Implementation-Version:1.0.0-SNAPSHOT
+Import-Package:javax.jcr;version="[2.0.0,3.0.0)"
+Import-Package:org.apache.sling.scripting.sightly;version="[2.0.0,3.0.0)"
+Manifest-Version:1.0
\ No newline at end of file
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/jcr_root/apps/htl/test/test.html b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/jcr_root/apps/htl/test/test.html
new file mode 100644
index 0000000..98e2e96
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/jcr_root/apps/htl/test/test.html
@@ -0,0 +1,28 @@
+<!--
+ 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.
+ -->
+<!doctype html>
+<html lang="en-US">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Default Page Title</title>
+<body>
+<!-- note that the session is not a good example of a use class. but for only used the sake of this test -->
+<div class="session" data-sly-use.session="javax.jcr.Session">
+ <p>${session.userId}</p>
+</div>
+</body>
+</html>
diff --git a/src/test/resources/test-projects/default-test-projects/additional-metainf-files/pom.xml b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/pom.xml
new file mode 100755
index 0000000..56f85dc
--- /dev/null
+++ b/src/test/resources/test-projects/default-test-projects/additional-metainf-files/pom.xml
@@ -0,0 +1,93 @@
+<!--
+ 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>
+ <name>Packaging test</name>
+
+ <build>
+ <sourceDirectory>src/content/jcr_root</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>filevault-package-maven-plugin</artifactId>
+ <version>${plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <packageType>mixed</packageType>
+ <filters>
+ <filter>
+ <root>/apps/htl/test</root>
+ </filter>
+ </filters>
+ <metaInfDirectory>additional-metainf</metaInfDirectory>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>htl-maven-plugin</artifactId>
+ <version>1.1.2</version>
+ <executions>
+ <execution>
+ <id>validate-scripts</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ <configuration>
+ <sourceDirectory>jcr_root</sourceDirectory>
+ <includes>
+ <include>**/*.html</include>
+ </includes>
+ <failOnWarnings>true</failOnWarnings>
+ <generateJavaClasses>true</generateJavaClasses>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <!-- needed for HTL compilation validation -->
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.sightly.compiler</artifactId>
+ <version>1.0.14</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.sightly.compiler.java</artifactId>
+ <version>1.0.16</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>