This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-scriptingbundle-maven-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new 0d45342 SLING-10808 - Generate scripting capabilities from Jackrabbit
FileVault content packages
0d45342 is described below
commit 0d45342a4c3bcb532ffa07fbb2f3ce3f1d0b7970
Author: Radu Cotescu <[email protected]>
AuthorDate: Mon Sep 20 10:38:16 2021 +0200
SLING-10808 - Generate scripting capabilities from Jackrabbit FileVault
content packages
* added support to generate provided and required capabilities based on
FileVault content
packages by reading the .content.xml files
---
pom.xml | 34 +++-
.../plugin/bnd/BundledScriptsScannerPlugin.java | 8 +-
.../plugin/capability/Capabilities.java | 7 +-
.../scriptingbundle/plugin/maven/MetadataMojo.java | 4 +-
.../plugin/processor/Constants.java | 4 +
.../plugin/processor/FileProcessor.java | 177 +++++++++++++--------
.../plugin/processor/PathOnlyScriptAnalyser.java | 10 +-
.../processor/ResourceTypeFolderAnalyser.java | 27 +++-
.../processor/ResourceTypeFolderPredicate.java | 12 +-
.../processor/filevault/VaultContentXmlReader.java | 158 ++++++++++++++++++
.../scriptingbundle/plugin/AbstractPluginTest.java | 27 ++++
.../bnd/BundledScriptsScannerPluginTest.java | 3 +
.../plugin/maven/MetadataMojoTest.java | 6 +
.../plugin/processor/FileProcessorTest.java | 6 +-
.../filevault/VaultContentXmlReaderTest.java | 74 +++++++++
src/test/resources/filevault-1/bnd.bnd | 18 +++
src/test/resources/filevault-1/pom.xml | 49 ++++++
.../apps/my-scripts/_escaped_test/.content.xml | 22 +++
.../my-scripts/_escaped_test/_escaped_test.html | 18 +++
.../jcr_root/apps/my-scripts/image/.content.xml | 23 +++
.../jcr_root/apps/my-scripts/image/image.html | 18 +++
.../jcr_root/apps/my-scripts/teaser/.content.xml | 22 +++
.../jcr_root/apps/my-scripts/teaser/teaser.html | 18 +++
.../multiple-resource-super-type.xml | 23 +++
.../filevault-docview-examples/not-a-docview.xml | 21 +++
.../single-value-required-resource-types.xml | 23 +++
26 files changed, 717 insertions(+), 95 deletions(-)
diff --git a/pom.xml b/pom.xml
index 8ffdb54..211a764 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,7 +54,7 @@
</properties>
<prerequisites>
- <maven>${mavenVersion}</maven>
+ <maven>${maven.version}</maven>
</prerequisites>
<build>
@@ -217,7 +217,37 @@
<version>4.3.0</version>
<scope>compile</scope>
</dependency>
-
+ <!-- FileVault -->
+ <dependency>
+ <groupId>org.apache.jackrabbit.vault</groupId>
+ <artifactId>org.apache.jackrabbit.vault</artifactId>
+ <version>3.5.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>oak-jackrabbit-api</artifactId>
+ <version>1.40.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-spi-commons</artifactId>
+ <version>2.20.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.resource</artifactId>
+ <version>3.0.22</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java
index caa3293..d7893cc 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPlugin.java
@@ -61,6 +61,7 @@ public class BundledScriptsScannerPlugin implements
AnalyzerPlugin, Plugin {
@Override
public boolean analyzeJar(Analyzer analyzer) throws Exception {
logger = new BndLogger(reporter);
+ boolean inContentPackage =
"content-package".equals(analyzer.get("project.packaging"));
Path workDirectory = Paths.get(analyzer.get(PROJECT_BUILD_FOLDER),
"scriptingbundle-maven-plugin");
Files.createDirectories(workDirectory);
Set<PathMatcher> includes = getConfiguredIncludes();
@@ -93,7 +94,7 @@ public class BundledScriptsScannerPlugin implements
AnalyzerPlugin, Plugin {
scriptEngineMappings = getConfiguredScriptEngineMappings();
capabilities = Capabilities
.fromFileSystemTree(workDirectory, walkPath(workDirectory,
includes, excludes), logger,
- getConfiguredSearchPaths(), scriptEngineMappings,
getMissingRequirementsOptional());
+ getConfiguredSearchPaths(), scriptEngineMappings,
getMissingRequirementsOptional(), inContentPackage);
String providedCapabilitiesDefinition =
capabilities.getProvidedCapabilitiesString();
String requiredCapabilitiesDefinition =
capabilities.getRequiredCapabilitiesString();
@@ -199,10 +200,7 @@ public class BundledScriptsScannerPlugin implements
AnalyzerPlugin, Plugin {
private Stream<Path> walkPath(Path path, Set<PathMatcher> includes,
Set<PathMatcher> excludes) throws IOException {
return Files.walk(path).filter(file -> {
- boolean include = false;
- if (includes.isEmpty()) {
- include = true;
- }
+ boolean include = includes.isEmpty();
Optional<PathMatcher> includeOptions =
includes.stream().filter(pathMatcher -> pathMatcher.matches(file)).findFirst();
if (includeOptions.isPresent()) {
include = true;
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/capability/Capabilities.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/capability/Capabilities.java
index bd8e4de..4cf9179 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/capability/Capabilities.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/capability/Capabilities.java
@@ -132,14 +132,15 @@ public class Capabilities {
public static @NotNull Capabilities fromFileSystemTree(@NotNull Path root,
@NotNull Stream<Path> files, @NotNull Logger logger,
@NotNull
Set<String> searchPaths,
@NotNull
Map<String, String> scriptEngineMappings,
- boolean
missingRequirementsOptional) {
+ boolean
missingRequirementsOptional,
+ boolean
inContentPackage) {
Set<ProvidedResourceTypeCapability> providedResourceTypeCapabilities =
new LinkedHashSet<>();
Set<ProvidedScriptCapability> providedScriptCapabilities = new
LinkedHashSet<>();
Set<RequiredResourceTypeCapability> requiredResourceTypeCapabilities =
new LinkedHashSet<>();
FileProcessor fileProcessor = new FileProcessor(logger, searchPaths,
scriptEngineMappings);
- ResourceTypeFolderAnalyser resourceTypeFolderAnalyser = new
ResourceTypeFolderAnalyser(logger, root, fileProcessor);
+ ResourceTypeFolderAnalyser resourceTypeFolderAnalyser = new
ResourceTypeFolderAnalyser(logger, root, fileProcessor, inContentPackage);
PathOnlyScriptAnalyser
- pathOnlyScriptAnalyser = new PathOnlyScriptAnalyser(logger,
root, scriptEngineMappings, fileProcessor);
+ pathOnlyScriptAnalyser = new PathOnlyScriptAnalyser(logger,
root, scriptEngineMappings, fileProcessor, inContentPackage);
files.forEach(path -> {
if (Files.isDirectory(path)) {
Capabilities resourceTypeCapabilities =
resourceTypeFolderAnalyser.getCapabilities(path);
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java
index 32d0f66..1a562e4 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojo.java
@@ -178,6 +178,7 @@ public class MetadataMojo extends AbstractMojo {
private Capabilities capabilities;
public void execute() {
+ boolean inContentPackage =
"content-package".equals(project.getPackaging());
Logger logger = new MavenLogger(getLog());
Path workDirectory = Paths.get(project.getBuild().getDirectory(),
"scriptingbundle-maven-plugin");
try {
@@ -226,7 +227,8 @@ public class MetadataMojo extends AbstractMojo {
logger,
searchPaths,
scriptEngineMappings,
- missingRequirementsOptional
+ missingRequirementsOptional,
+ inContentPackage
);
String providedCapabilitiesDefinition =
capabilities.getProvidedCapabilitiesString();
String requiredCapabilitiesDefinition =
capabilities.getRequiredCapabilitiesString();
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java
index 55cbc89..0c38ba8 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/Constants.java
@@ -54,6 +54,10 @@ public final class Constants {
public static final String BND_SEARCH_PATHS = "searchPaths";
public static final String BND_MISSING_REQUIREMENTS_OPTIONAL =
"missingRequirementsOptional";
+ public static final String SLING_RESOURCE_SUPER_TYPE_XML_LOCAL_NAME =
"resourceSuperType";
+ public static final String SLING_REQUIRED_RESOURCE_TYPES =
"sling:requiredResourceTypes";
+ public static final String SLING_REQUIRED_RESOURCE_TYPES_XML_LOCAL_NAME =
"requiredResourceTypes";
+
public static final Map<String, String>
DEFAULT_EXTENSION_TO_SCRIPT_ENGINE_MAPPING;
public static final Set<String> DEFAULT_SEARCH_PATHS;
public static final Set<String> DEFAULT_SOURCE_DIRECTORIES;
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessor.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessor.java
index 2ddc24b..8a5f81d 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessor.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessor.java
@@ -35,9 +35,11 @@ import java.util.Set;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.sling.api.resource.type.ResourceType;
import
org.apache.sling.scriptingbundle.plugin.capability.ProvidedResourceTypeCapability;
import
org.apache.sling.scriptingbundle.plugin.capability.RequiredResourceTypeCapability;
+import
org.apache.sling.scriptingbundle.plugin.processor.filevault.VaultContentXmlReader;
import org.jetbrains.annotations.NotNull;
import org.osgi.framework.VersionRange;
@@ -61,93 +63,108 @@ public class FileProcessor {
this.scriptEngineMappings = scriptEngineMappings;
}
- public void processExtendsFile(@NotNull ResourceType resourceType,
@NotNull Path extendsFile,
+ public void processExtendsFile(@NotNull ResourceType resourceType,
@NotNull Path file,
@NotNull Set<ProvidedResourceTypeCapability>
providedCapabilities,
@NotNull Set<RequiredResourceTypeCapability>
requiredCapabilities) throws IllegalArgumentException {
try {
- List<String> extendResources = Files.readAllLines(extendsFile,
StandardCharsets.UTF_8);
- if (extendResources.size() == 1) {
- String extend = extendResources.get(0);
- Parameters parameters = OSGiHeader.parseHeader(extend);
- if (parameters.size() < 1 || parameters.size() > 1) {
- throw new IllegalArgumentException(String.format("The file
'%s' must contain one clause only (not multiple ones separated by ',')",
extendsFile));
- }
- Entry<String, Attrs> extendsParameter =
parameters.entrySet().iterator().next();
- for (String attributeName :
extendsParameter.getValue().keySet()) {
- if
(!EXTENDS_ALLOWED_ATTRIBUTE_NAMES.contains(attributeName)) {
- throw new
IllegalArgumentException(String.format("Found unsupported attribute/directive
'%s' in file '%s'. Only the following attributes or directives may be used in
the extends file: %s", attributeName, extendsFile, String.join(",",
EXTENDS_ALLOWED_ATTRIBUTE_NAMES)));
- }
- }
- String extendedResourceType =
FilenameUtils.normalize(extendsParameter.getKey(), true);
- boolean isOptional =
aQute.bnd.osgi.Constants.OPTIONAL.equals(extendsParameter.getValue().get(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE));
- Set<String> searchPathResourceTypes =
processSearchPathResourceTypes(resourceType);
- Optional<ProvidedResourceTypeCapability> rootCapability =
providedCapabilities.stream().filter(capability ->
-
capability.getResourceTypes().equals(searchPathResourceTypes) &&
capability.getSelectors().isEmpty() &&
- StringUtils.isEmpty(capability.getRequestMethod())
&& StringUtils.isEmpty(capability.getRequestExtension())
- ).findFirst();
- rootCapability.ifPresent(capability -> {
- providedCapabilities.remove(capability);
- ProvidedResourceTypeCapability replacement =
-
ProvidedResourceTypeCapability.builder().fromCapability(capability)
-
.withExtendsResourceType(extendedResourceType).build();
- providedCapabilities.add(replacement);
-
- });
- if (!rootCapability.isPresent()) {
- providedCapabilities.add(
- ProvidedResourceTypeCapability.builder()
-
.withResourceTypes(processSearchPathResourceTypes(resourceType))
- .withVersion(resourceType.getVersion())
-
.withExtendsResourceType(extendedResourceType)
- .build());
- }
- RequiredResourceTypeCapability.Builder requiredBuilder =
-
RequiredResourceTypeCapability.builder().withResourceType(extendedResourceType);
- if (isOptional) {
- requiredBuilder.withIsOptional();
- }
- extractVersionRange(extendsFile, requiredBuilder,
extendsParameter.getValue().getVersion());
- requiredCapabilities.add(requiredBuilder.build());
+ List<String> extendedResources = Files.readAllLines(file,
StandardCharsets.UTF_8);
+ if (extendedResources.size() == 1) {
+ processExtendedResourceType(resourceType, file,
providedCapabilities, requiredCapabilities, extendedResources.get(0));
} else {
- throw new IllegalArgumentException(String.format("The file
'%s' must contain one line only (not multiple ones)", extendsFile));
+ throw new IllegalArgumentException(String.format("The file
'%s' must contain one line only (not multiple ones)", file));
}
} catch (IOException e) {
- throw new UncheckedIOException(String.format("Unable to read file
%s.", extendsFile.toString()), e);
+ throw new UncheckedIOException(String.format("Unable to read file
%s.", file.toString()), e);
}
}
+ private void processExtendedResourceType(@NotNull ResourceType
resourceType, @NotNull Path extendsFile,
+ @NotNull Set<ProvidedResourceTypeCapability>
providedCapabilities,
+ @NotNull Set<RequiredResourceTypeCapability>
requiredCapabilities, @NotNull String extendedResource) {
+ Parameters parameters = OSGiHeader.parseHeader(extendedResource);
+ if (parameters.size() != 1) {
+ throw new IllegalArgumentException(String.format("The file '%s'
must contain one clause only (not multiple ones separated by ',')",
+ extendsFile));
+ }
+ Entry<String, Attrs> extendsParameter =
parameters.entrySet().iterator().next();
+ for (String attributeName : extendsParameter.getValue().keySet()) {
+ if (!EXTENDS_ALLOWED_ATTRIBUTE_NAMES.contains(attributeName)) {
+ throw new IllegalArgumentException(String.format("Found
unsupported attribute/directive '%s' in file '%s'. Only the following
attributes or directives may be used in the extends file: %s", attributeName,
+ extendsFile, String.join(",",
EXTENDS_ALLOWED_ATTRIBUTE_NAMES)));
+ }
+ }
+ String extendedResourceType =
FilenameUtils.normalize(extendsParameter.getKey(), true);
+ boolean isOptional =
aQute.bnd.osgi.Constants.OPTIONAL.equals(extendsParameter.getValue().get(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE));
+ Set<String> searchPathResourceTypes =
processSearchPathResourceTypes(resourceType);
+ Optional<ProvidedResourceTypeCapability> rootCapability =
providedCapabilities.stream().filter(capability ->
+ capability.getResourceTypes().equals(searchPathResourceTypes) &&
capability.getSelectors().isEmpty() &&
+ StringUtils.isEmpty(capability.getRequestMethod()) &&
StringUtils.isEmpty(capability.getRequestExtension())
+ ).findFirst();
+ rootCapability.ifPresent(capability -> {
+ providedCapabilities.remove(capability);
+ ProvidedResourceTypeCapability replacement =
+
ProvidedResourceTypeCapability.builder().fromCapability(capability)
+
.withExtendsResourceType(extendedResourceType).build();
+ providedCapabilities.add(replacement);
+
+ });
+ if (!rootCapability.isPresent()) {
+ providedCapabilities.add(
+ ProvidedResourceTypeCapability.builder()
+
.withResourceTypes(processSearchPathResourceTypes(resourceType))
+ .withVersion(resourceType.getVersion())
+ .withExtendsResourceType(extendedResourceType)
+ .build());
+ }
+ RequiredResourceTypeCapability.Builder requiredBuilder =
+
RequiredResourceTypeCapability.builder().withResourceType(extendedResourceType);
+ if (isOptional) {
+ requiredBuilder.withIsOptional();
+ }
+ extractVersionRange(extendsFile, requiredBuilder,
extendsParameter.getValue().getVersion());
+ requiredCapabilities.add(requiredBuilder.build());
+ }
+
void processRequiresFile(@NotNull Path requiresFile,
@NotNull
Set<RequiredResourceTypeCapability> requiredCapabilities) {
try {
List<String> requiredResourceTypes =
Files.readAllLines(requiresFile, StandardCharsets.UTF_8);
- for (String requiredResourceType : requiredResourceTypes) {
- Parameters parameters =
OSGiHeader.parseHeader(requiredResourceType);
- if (parameters.size() < 1 || parameters.size() > 1) {
- throw new IllegalArgumentException(String.format("Each
line in file '%s' must contain one clause only (not multiple ones separated by
',')", requiresFile));
- }
- Entry<String, Attrs> requiresParameter =
parameters.entrySet().iterator().next();
- for (String attributeName :
requiresParameter.getValue().keySet()) {
- if
(!REQUIRES_ALLOWED_ATTRIBUTE_NAMES.contains(attributeName)) {
- throw new
IllegalArgumentException(String.format("Found unsupported attribute/directive
'%s' in file '%s'. Only the following attributes or directives may be used in
the requires file: %s", attributeName, requiresFile, String.join(",",
REQUIRES_ALLOWED_ATTRIBUTE_NAMES)));
- }
- }
- String resourceType =
FilenameUtils.normalize(requiresParameter.getKey(), true);
- boolean isOptional =
aQute.bnd.osgi.Constants.OPTIONAL.equals(requiresParameter.getValue().get(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE));
- RequiredResourceTypeCapability.Builder requiredBuilder =
-
RequiredResourceTypeCapability.builder().withResourceType(resourceType);
- if (isOptional) {
- requiredBuilder.withIsOptional();
+ processRequiredResourceTypes(requiresFile, requiredCapabilities,
requiredResourceTypes);
+ } catch (IOException e) {
+ throw new UncheckedIOException(String.format("Unable to read file
%s.", requiresFile), e);
+ }
+ }
+
+ private void processRequiredResourceTypes(@NotNull Path requiresFile,
@NotNull Set<RequiredResourceTypeCapability> requiredCapabilities,
+ List<String> requiredResourceTypes) {
+ for (String requiredResourceType : requiredResourceTypes) {
+ Parameters parameters =
OSGiHeader.parseHeader(requiredResourceType);
+ if (parameters.size() != 1) {
+ throw new IllegalArgumentException(String.format("Each line in
file '%s' must contain one clause only (not multiple ones separated by ',')",
+ requiresFile));
+ }
+ Entry<String, Attrs> requiresParameter =
parameters.entrySet().iterator().next();
+ for (String attributeName : requiresParameter.getValue().keySet())
{
+ if (!REQUIRES_ALLOWED_ATTRIBUTE_NAMES.contains(attributeName))
{
+ throw new IllegalArgumentException(String.format("Found
unsupported attribute/directive '%s' in file '%s'. Only the following
attributes or directives may be used in the requires file: %s", attributeName,
+ requiresFile, String.join(",",
REQUIRES_ALLOWED_ATTRIBUTE_NAMES)));
}
- extractVersionRange(requiresFile, requiredBuilder,
requiresParameter.getValue().getVersion());
- requiredCapabilities.add(requiredBuilder.build());
}
- } catch (IOException e) {
- throw new UncheckedIOException(String.format("Unable to read file
%s.", requiresFile.toString()), e);
+ String resourceType =
FilenameUtils.normalize(requiresParameter.getKey(), true);
+ boolean isOptional =
aQute.bnd.osgi.Constants.OPTIONAL.equals(requiresParameter.getValue().get(aQute.bnd.osgi.Constants.RESOLUTION_DIRECTIVE));
+ RequiredResourceTypeCapability.Builder requiredBuilder =
+
RequiredResourceTypeCapability.builder().withResourceType(resourceType);
+ if (isOptional) {
+ requiredBuilder.withIsOptional();
+ }
+ extractVersionRange(requiresFile, requiredBuilder,
requiresParameter.getValue().getVersion());
+ requiredCapabilities.add(requiredBuilder.build());
}
}
public void processScriptFile(@NotNull Path resourceTypeDirectory,
@NotNull Path scriptPath,
- @NotNull ResourceType resourceType,
@NotNull Set<ProvidedResourceTypeCapability> providedCapabilities) {
+ @NotNull ResourceType resourceType,
@NotNull Set<ProvidedResourceTypeCapability> providedCapabilities,
+ boolean inContentPackage) {
String filePath = scriptPath.toString();
String extension = FilenameUtils.getExtension(filePath);
if (StringUtils.isNotEmpty(extension)) {
@@ -158,11 +175,14 @@ public class FileProcessor {
List<String> selectors = new ArrayList<>();
if (pathSegments > 1) {
for (int i = 0; i < pathSegments - 1; i++) {
-
selectors.add(relativeResourceTypeFolder.getName(i).toString());
+ selectors.add(inContentPackage ?
+
PlatformNameFormat.getRepositoryName(relativeResourceTypeFolder.getName(i).toString())
:
+
relativeResourceTypeFolder.getName(i).toString()
+ );
}
}
String scriptFileName = scriptFile.toString();
- Script script = Script.parseScript(scriptFileName);
+ Script script = Script.parseScript(inContentPackage ?
PlatformNameFormat.getRepositoryPath(scriptFileName) : scriptFileName);
if (script != null) {
String scriptEngine =
scriptEngineMappings.get(script.getScriptExtension());
if (scriptEngine != null) {
@@ -236,4 +256,21 @@ public class FileProcessor {
log.warn(String.format("Invalid version range format %s in file
%s.", version, requiresFile));
}
}
+
+ public void processVaultFile(@NotNull Path entry, @NotNull ResourceType
resourceType,
+ @NotNull Set<ProvidedResourceTypeCapability>
providedCapabilities,
+ @NotNull Set<RequiredResourceTypeCapability>
requiredCapabilities) {
+ try {
+ VaultContentXmlReader reader = new VaultContentXmlReader(entry);
+ Optional<String> slingResourceSuperType =
reader.getSlingResourceSuperType();
+ slingResourceSuperType.ifPresent(
+ resourceSuperType ->
processExtendedResourceType(resourceType, entry, providedCapabilities,
requiredCapabilities,
+ resourceSuperType));
+ if (!reader.getSlingRequiredResourceTypes().isEmpty()) {
+ processRequiredResourceTypes(entry, requiredCapabilities, new
ArrayList<>(reader.getSlingRequiredResourceTypes()));
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(String.format("Unable to read file
%s.", entry), e);
+ }
+ }
}
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/PathOnlyScriptAnalyser.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/PathOnlyScriptAnalyser.java
index 81f0e3f..666a04c 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/PathOnlyScriptAnalyser.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/PathOnlyScriptAnalyser.java
@@ -29,6 +29,7 @@ import java.util.function.Predicate;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.sling.scriptingbundle.plugin.capability.Capabilities;
import
org.apache.sling.scriptingbundle.plugin.capability.ProvidedScriptCapability;
import
org.apache.sling.scriptingbundle.plugin.capability.RequiredResourceTypeCapability;
@@ -40,13 +41,15 @@ public class PathOnlyScriptAnalyser {
private final Predicate<Path> isNotAResourceTypeFolder;
private final Map<String, String> scriptEngineMappings;
private final FileProcessor fileProcessor;
+ private final boolean inContentPackage;
public PathOnlyScriptAnalyser(@NotNull Logger logger, @NotNull Path
scriptsDirectory, @NotNull Map<String, String> scriptEngineMappings,
- @NotNull FileProcessor fileProcessor) {
+ @NotNull FileProcessor fileProcessor,
boolean inContentPackage) {
this.scriptsDirectory = scriptsDirectory;
- this.isNotAResourceTypeFolder = new
ResourceTypeFolderPredicate(logger).negate();
+ this.isNotAResourceTypeFolder = new
ResourceTypeFolderPredicate(logger, inContentPackage).negate();
this.scriptEngineMappings = scriptEngineMappings;
this.fileProcessor = fileProcessor;
+ this.inContentPackage = inContentPackage;
}
public @NotNull Capabilities getProvidedScriptCapability(@NotNull Path
file) {
@@ -68,6 +71,9 @@ public class PathOnlyScriptAnalyser {
int dotLastIndex = name.lastIndexOf('.');
if (dotLastIndex > -1 && dotLastIndex != name.length()
- 1) {
String scriptPath = FilenameUtils.normalize("/" +
scriptsDirectory.relativize(file).toString(), true);
+ if (inContentPackage) {
+ scriptPath =
PlatformNameFormat.getRepositoryPath(scriptPath);
+ }
ProvidedScriptCapability providedScriptCapability =
ProvidedScriptCapability.builder(scriptEngineMappings).withPath(scriptPath).build();
Path requires =
parent.resolve(Constants.REQUIRES_FILE);
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderAnalyser.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderAnalyser.java
index b7b6820..d1df4df 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderAnalyser.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderAnalyser.java
@@ -29,6 +29,7 @@ import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.io.FilenameUtils;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.sling.api.resource.type.ResourceType;
import org.apache.sling.scriptingbundle.plugin.capability.Capabilities;
import
org.apache.sling.scriptingbundle.plugin.capability.ProvidedResourceTypeCapability;
@@ -41,13 +42,16 @@ public class ResourceTypeFolderAnalyser {
private final Logger logger;
private final Path scriptsDirectory;
private final ResourceTypeFolderPredicate resourceTypeFolderPredicate;
- private FileProcessor fileProcessor;
+ private final FileProcessor fileProcessor;
+ private final boolean inContentPackage;
- public ResourceTypeFolderAnalyser(@NotNull Logger logger, @NotNull Path
scriptsDirectory, @NotNull FileProcessor fileProcessor) {
+ public ResourceTypeFolderAnalyser(@NotNull Logger logger, @NotNull Path
scriptsDirectory, @NotNull FileProcessor fileProcessor,
+ boolean inContentPackage) {
this.logger = logger;
this.scriptsDirectory = scriptsDirectory;
- this.resourceTypeFolderPredicate = new
ResourceTypeFolderPredicate(logger);
+ this.resourceTypeFolderPredicate = new
ResourceTypeFolderPredicate(logger, inContentPackage);
this.fileProcessor = fileProcessor;
+ this.inContentPackage = inContentPackage;
}
public Capabilities getCapabilities(@NotNull Path resourceTypeDirectory) {
@@ -56,8 +60,14 @@ public class ResourceTypeFolderAnalyser {
if (resourceTypeDirectory.startsWith(scriptsDirectory) &&
resourceTypeFolderPredicate.test(resourceTypeDirectory)) {
try (DirectoryStream<Path> resourceTypeDirectoryStream =
Files.newDirectoryStream(resourceTypeDirectory)) {
Path relativeResourceTypeDirectory =
scriptsDirectory.relativize(resourceTypeDirectory);
- final ResourceType
- resourceType =
ResourceType.parseResourceType(FilenameUtils.normalize(relativeResourceTypeDirectory.toString(),
true));
+ final ResourceType resourceType =
+ ResourceType.parseResourceType(
+ FilenameUtils.normalize(inContentPackage ?
+
PlatformNameFormat.getRepositoryPath(relativeResourceTypeDirectory.toString()) :
+ relativeResourceTypeDirectory.toString(),
+ true
+ )
+ );
resourceTypeDirectoryStream.forEach(entry -> {
if (Files.isRegularFile(entry)) {
Path file = entry.getFileName();
@@ -66,8 +76,10 @@ public class ResourceTypeFolderAnalyser {
fileProcessor.processExtendsFile(resourceType,
entry, providedCapabilities, requiredCapabilities);
} else if
(Constants.REQUIRES_FILE.equals(file.toString())) {
fileProcessor.processRequiresFile(entry,
requiredCapabilities);
+ } else if
(org.apache.jackrabbit.vault.util.Constants.DOT_CONTENT_XML.equals(file.toString()))
{
+ fileProcessor.processVaultFile(entry,
resourceType, providedCapabilities, requiredCapabilities);
} else {
-
fileProcessor.processScriptFile(resourceTypeDirectory, entry, resourceType,
providedCapabilities);
+
fileProcessor.processScriptFile(resourceTypeDirectory, entry, resourceType,
providedCapabilities, inContentPackage);
}
}
} else if (Files.isDirectory(entry) &&
!resourceTypeFolderPredicate.test(entry)) {
@@ -82,7 +94,8 @@ public class ResourceTypeFolderAnalyser {
return true;
})) {
selectorFilesStream.forEach(
- file ->
fileProcessor.processScriptFile(resourceTypeDirectory, file, resourceType,
providedCapabilities)
+ file ->
fileProcessor.processScriptFile(resourceTypeDirectory, file, resourceType,
+ providedCapabilities,
inContentPackage)
);
} catch (IOException e) {
logger.error(String.format("Unable to scan folder
%s.", entry.toString()), e);
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderPredicate.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderPredicate.java
index 684c685..fe92ca4 100644
---
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderPredicate.java
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/ResourceTypeFolderPredicate.java
@@ -24,14 +24,18 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Predicate;
+import org.apache.jackrabbit.vault.util.PlatformNameFormat;
+import
org.apache.sling.scriptingbundle.plugin.processor.filevault.VaultContentXmlReader;
import org.osgi.framework.Version;
public class ResourceTypeFolderPredicate implements Predicate<Path> {
private final Logger logger;
+ private final boolean inContentPackage;
- public ResourceTypeFolderPredicate(Logger logger) {
+ public ResourceTypeFolderPredicate(Logger logger, boolean
inContentPackage) {
this.logger = logger;
+ this.inContentPackage = inContentPackage;
}
@Override
@@ -61,14 +65,18 @@ public class ResourceTypeFolderPredicate implements
Predicate<Path> {
} else {
resourceTypeLabel = lastSegmentString;
}
+ if (inContentPackage) {
+ resourceTypeLabel =
PlatformNameFormat.getRepositoryPath(resourceTypeLabel);
+ }
try (DirectoryStream<Path> directoryStream =
Files.newDirectoryStream(folder, Files::isRegularFile)) {
for (Path path : directoryStream) {
Path fileName = path.getFileName();
if (fileName != null) {
String childName = fileName.toString();
- Script script = Script.parseScript(childName);
+ Script script = Script.parseScript(inContentPackage ?
PlatformNameFormat.getRepositoryPath(childName) : childName);
if (
Constants.EXTENDS_FILE.equals(childName) ||
+
org.apache.jackrabbit.vault.util.Constants.DOT_CONTENT_XML.equals(childName) &&
new VaultContentXmlReader(path).getSlingResourceSuperType().isPresent() ||
(
script != null &&
(
diff --git
a/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java
new file mode 100644
index 0000000..edee6bc
--- /dev/null
+++
b/src/main/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReader.java
@@ -0,0 +1,158 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.sling.scriptingbundle.plugin.processor.filevault;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import javax.jcr.PropertyType;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.vault.util.DocViewProperty;
+import org.apache.sling.jcr.resource.api.JcrResourceConstants;
+import org.apache.sling.scriptingbundle.plugin.processor.Constants;
+import org.jetbrains.annotations.NotNull;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class VaultContentXmlReader {
+
+ private static final DocumentBuilderFactory documentBuilderFactory;
+
+ static {
+ try {
+ documentBuilderFactory = DocumentBuilderFactory.newInstance();
+
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
documentBuilderFactory.setAttribute(XMLConstants.FEATURE_SECURE_PROCESSING,
Boolean.TRUE);
+ documentBuilderFactory.setExpandEntityReferences(false);
+ documentBuilderFactory.setNamespaceAware(true);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalStateException("Cannot disable DTD features.", e);
+ }
+ }
+
+ private final String resourceSuperType;
+ private final Path path;
+ private final Set<String> requiredResourceTypes;
+
+ public VaultContentXmlReader(@NotNull Path path) throws IOException {
+ this.path = path;
+ this.requiredResourceTypes = new HashSet<>();
+ try (BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8)) {
+ DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
+ Document document = documentBuilder.parse(new InputSource(reader));
+ NodeList nodeList =
document.getElementsByTagNameNS(NameConstants.JCR_ROOT.getNamespaceURI(),
+ NameConstants.JCR_ROOT.getLocalName());
+ if (nodeList.getLength() == 1 &&
nodeList.item(0).equals(document.getDocumentElement())) {
+ String resourceSuperTypeRawValue =
document.getDocumentElement().getAttributeNS(JcrResourceConstants.SLING_NAMESPACE_URI,
+ Constants.SLING_RESOURCE_SUPER_TYPE_XML_LOCAL_NAME);
+ if (StringUtils.isNotEmpty(resourceSuperTypeRawValue)) {
+ DocViewProperty resourceSuperTypeDocViewProperty =
+
DocViewProperty.parse(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY,
resourceSuperTypeRawValue);
+ if ((resourceSuperTypeDocViewProperty.type ==
PropertyType.STRING ||
+ resourceSuperTypeDocViewProperty.type ==
PropertyType.UNDEFINED) && !resourceSuperTypeDocViewProperty.isMulti) {
+ this.resourceSuperType =
resourceSuperTypeDocViewProperty.values[0];
+ } else {
+ throw new
IllegalArgumentException(String.format("Invalid %s property value (%s) in file
%s.",
+
JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY,
resourceSuperTypeRawValue, path));
+ }
+ } else {
+ this.resourceSuperType = null;
+ }
+
+ String requiredResourceTypesRawValue =
+
document.getDocumentElement().getAttributeNS(JcrResourceConstants.SLING_NAMESPACE_URI
+ ,
Constants.SLING_REQUIRED_RESOURCE_TYPES_XML_LOCAL_NAME);
+ if (StringUtils.isNotEmpty(requiredResourceTypesRawValue)) {
+ DocViewProperty requiredResourceTypesDocViewProperty =
+
DocViewProperty.parse(Constants.SLING_REQUIRED_RESOURCE_TYPES,
+ requiredResourceTypesRawValue);
+ if (requiredResourceTypesDocViewProperty.isMulti &&
+ (requiredResourceTypesDocViewProperty.type ==
PropertyType.STRING ||
+ requiredResourceTypesDocViewProperty.type
== PropertyType.UNDEFINED)) {
+
requiredResourceTypes.addAll(Arrays.asList(requiredResourceTypesDocViewProperty.values));
+ } else {
+ throw new
IllegalArgumentException(String.format("Invalid %s property value (%s) in file
%s.",
+ Constants.SLING_REQUIRED_RESOURCE_TYPES,
requiredResourceTypesRawValue, path));
+ }
+ }
+
+
+ } else {
+ throw new IllegalArgumentException(String.format(
+ "Path %s does not seem to provide a Docview format -
https://jackrabbit.apache.org/filevault/docview.html.",
+ path));
+ }
+ } catch (ParserConfigurationException | SAXException e) {
+ throw new IOException(e);
+ }
+
+
+ }
+
+ @NotNull
+ public Path getPath() {
+ return path;
+ }
+
+ @NotNull
+ public Optional<String> getSlingResourceSuperType() {
+ return Optional.ofNullable(resourceSuperType);
+ }
+
+ @NotNull
+ public Set<String> getSlingRequiredResourceTypes() {
+ return Collections.unmodifiableSet(requiredResourceTypes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(path, resourceSuperType, requiredResourceTypes);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VaultContentXmlReader) {
+ VaultContentXmlReader other = (VaultContentXmlReader) obj;
+ return Objects.equals(path, other.path) &&
Objects.equals(resourceSuperType, other.resourceSuperType) &&
+ Objects.equals(requiredResourceTypes,
other.requiredResourceTypes);
+ }
+ return false;
+ }
+}
diff --git
a/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java
b/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java
index 9a96b9b..ee5adb2 100644
---
a/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java
+++
b/src/test/java/org/apache/sling/scriptingbundle/plugin/AbstractPluginTest.java
@@ -38,6 +38,8 @@ import org.osgi.framework.VersionRange;
/** Common base class for both Bnd plugin and Maven plugin */
public abstract class AbstractPluginTest {
+ protected static final Set<String> FILEVAULT_PROJECTS = new
HashSet<>(Arrays.asList("filevault-1"));
+
public abstract PluginExecution executePluginOnProject(String projectName)
throws Exception;
public abstract void cleanUp(String projectName) throws Exception;
@@ -197,6 +199,31 @@ public abstract class AbstractPluginTest {
}
@Test
+ public void testFileVault1() throws Exception {
+ try {
+ PluginExecution execution = executePluginOnProject("filevault-1");
+ Capabilities capabilities = execution.getCapabilities();
+ Set<ProvidedResourceTypeCapability> pExpected = new
HashSet<>(Arrays.asList(
+
ProvidedResourceTypeCapability.builder().withResourceTypes("my-scripts/image",
"/apps/my-scripts/image")
+
.withScriptEngine("htl").withScriptExtension("html").withExtendsResourceType("generic/image").build(),
+
ProvidedResourceTypeCapability.builder().withResourceTypes("my-scripts/teaser",
"/apps/my-scripts/teaser")
+
.withScriptEngine("htl").withScriptExtension("html").build(),
+
ProvidedResourceTypeCapability.builder().withResourceTypes("my-scripts/escaped:test",
"/apps/my-scripts/escaped:test")
+
.withScriptEngine("htl").withScriptExtension("html").build()
+ ));
+ Set<RequiredResourceTypeCapability> rExpected = new
HashSet<>(Arrays.asList(
+
RequiredResourceTypeCapability.builder().withResourceType("generic/image").withIsOptional().build(),
+
RequiredResourceTypeCapability.builder().withResourceType("required/one").withIsOptional().build(),
+
RequiredResourceTypeCapability.builder().withResourceType("required/two").withIsOptional().build(),
+
RequiredResourceTypeCapability.builder().withResourceType("my-scripts/image").build()
+ ));
+ verifyCapabilities(capabilities, pExpected, rExpected,
Collections.emptySet());
+ } finally {
+ cleanUp("filevault-1");
+ }
+ }
+
+ @Test
public void testProject4() throws Exception {
try {
PluginExecution execution = executePluginOnProject("project-4");
diff --git
a/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java
b/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java
index 1f694e7..12a2976 100644
---
a/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java
+++
b/src/test/java/org/apache/sling/scriptingbundle/plugin/bnd/BundledScriptsScannerPluginTest.java
@@ -49,6 +49,9 @@ public class BundledScriptsScannerPluginTest extends
AbstractPluginTest {
builder.setProperties(bndFile.getParentFile(),
builder.loadProperties(bndFile));
builder.set(BundledScriptsScannerPlugin.PROJECT_ROOT_FOLDER,
projectRootFolder.toString());
builder.set(BundledScriptsScannerPlugin.PROJECT_BUILD_FOLDER,
projectTargetFolder.toString());
+ if (FILEVAULT_PROJECTS.contains(projectName)) {
+ builder.set("project.packaging", "content-package");
+ }
return builder;
}
diff --git
a/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java
b/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java
index 0c053bb..7b1327e 100644
---
a/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java
+++
b/src/test/java/org/apache/sling/scriptingbundle/plugin/maven/MetadataMojoTest.java
@@ -20,6 +20,9 @@ package org.apache.sling.scriptingbundle.plugin.maven;
import java.io.File;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.maven.execution.MavenSession;
@@ -45,6 +48,9 @@ public class MetadataMojoTest extends AbstractPluginTest {
File projectDirectory = Paths.get("src", "test", "resources",
projectName).toFile();
MavenProject project = mojoRule.readMavenProject(projectDirectory);
MavenSession session = mojoRule.newMavenSession(project);
+ if (FILEVAULT_PROJECTS.contains(projectName)) {
+ project.setPackaging("content-package");
+ }
MojoExecution execution = mojoRule.newMojoExecution("metadata");
MetadataMojo validateMojo = (MetadataMojo)
mojoRule.lookupConfiguredMojo(session, execution);
MojoProject mojoProject = new MojoProject();
diff --git
a/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessorTest.java
b/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessorTest.java
index 55e074c..fc1c57e 100644
---
a/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessorTest.java
+++
b/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/FileProcessorTest.java
@@ -58,7 +58,7 @@ public class FileProcessorTest {
Assert.assertEquals(expectedRequiredCapability,
requiredCapabilities.iterator().next());
Assert.assertEquals(1, providedCapabilities.size());
ProvidedResourceTypeCapability expectedProvidedCapability =
ProvidedResourceTypeCapability.builder()
- .withResourceTypes(new
HashSet<String>(Arrays.asList("my/resource", "/apps/my/resource")))
+ .withResourceTypes(new HashSet<>(Arrays.asList("my/resource",
"/apps/my/resource")))
.withVersion(MY_RESOURCE_TYPE.getVersion())
.withExtendsResourceType("org/apache/sling/bar")
.build();
@@ -111,7 +111,7 @@ public class FileProcessorTest {
public void testScriptValid() {
Path resourceTypeFolder = Paths.get("apps", "my", "resource", "2.0");
Path script = Paths.get("apps", "my", "resource", "2.0", "selectorb",
"selectora.POST.html");
- processor.processScriptFile(resourceTypeFolder, script,
MY_RESOURCE_TYPE, providedCapabilities);
+ processor.processScriptFile(resourceTypeFolder, script,
MY_RESOURCE_TYPE, providedCapabilities, false);
Assert.assertEquals(1, providedCapabilities.size());
ProvidedResourceTypeCapability expectedProvidedCapability =
ProvidedResourceTypeCapability.builder()
.withResourceTypes(new HashSet<>(Arrays.asList("my/resource",
"/apps/my/resource")))
@@ -128,7 +128,7 @@ public class FileProcessorTest {
public void testScriptUnknownExtension() {
Path resourceTypeFolder = Paths.get("scripts", "apps", "my",
"resource", "2.0");
Path script = Paths.get("scripts", "apps", "my", "resource", "2.0",
"selectorb", "selectora.POST.abc");
- processor.processScriptFile(resourceTypeFolder, script,
MY_RESOURCE_TYPE, providedCapabilities);
+ processor.processScriptFile(resourceTypeFolder, script,
MY_RESOURCE_TYPE, providedCapabilities, false);
// this must not throw an exception but a WARN should be emitted in
the log to make users aware of potential misconfigurations
Assert.assertEquals(0, providedCapabilities.size());
}
diff --git
a/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReaderTest.java
b/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReaderTest.java
new file mode 100644
index 0000000..fb5f702
--- /dev/null
+++
b/src/test/java/org/apache/sling/scriptingbundle/plugin/processor/filevault/VaultContentXmlReaderTest.java
@@ -0,0 +1,74 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.sling.scriptingbundle.plugin.processor.filevault;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Optional;
+
+import org.apache.sling.scriptingbundle.plugin.processor.Slf4jLogger;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class VaultContentXmlReaderTest {
+
+ @Test
+ public void testReader() throws IOException {
+ VaultContentXmlReader vaultContentXmlReader = new
VaultContentXmlReader(Paths.get("src/test/resources" +
+
"/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/.content.xml"));
+ Optional<String> resourceSuperType =
vaultContentXmlReader.getSlingResourceSuperType();
+ assertTrue(resourceSuperType.isPresent());
+ assertEquals("generic/image", resourceSuperType.get());
+
+ assertTrue(
+ vaultContentXmlReader.getSlingRequiredResourceTypes().size()
== 2 &&
+
vaultContentXmlReader.getSlingRequiredResourceTypes().containsAll(Arrays.asList("required/one",
"required/two"))
+ );
+
+ }
+
+ @Test
+ public void multipleValueResourceSuperType() throws IOException {
+ IllegalArgumentException iae =
assertThrows(IllegalArgumentException.class, () -> new VaultContentXmlReader(
+
Paths.get("src/test/resources/filevault-docview-examples/multiple-resource-super-type.xml")));
+ assertTrue(iae.getMessage().contains("Invalid sling:resourceSuperType
property value ([generic/image])"));
+ }
+
+ @Test
+ public void singleValueRequiredResourceTypes() throws IOException {
+ IllegalArgumentException iae =
assertThrows(IllegalArgumentException.class, () -> new VaultContentXmlReader(
+
Paths.get("src/test/resources/filevault-docview-examples/single-value-required-resource-types.xml")));
+ assertTrue(iae.getMessage().contains("Invalid
sling:requiredResourceTypes property value (required/one,required/two)"));
+ }
+
+ @Test
+ public void notADocView() throws IOException {
+ IllegalArgumentException iae =
assertThrows(IllegalArgumentException.class, () -> new VaultContentXmlReader(
+
Paths.get("src/test/resources/filevault-docview-examples/not-a-docview.xml")));
+ assertTrue(iae.getMessage().contains("does not seem to provide a
Docview format - https://jackrabbit.apache.org/filevault/docview.html"));
+ }
+}
diff --git a/src/test/resources/filevault-1/bnd.bnd
b/src/test/resources/filevault-1/bnd.bnd
new file mode 100644
index 0000000..dd5a963
--- /dev/null
+++ b/src/test/resources/filevault-1/bnd.bnd
@@ -0,0 +1,18 @@
+# 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.
+-plugin:
org.apache.sling.scriptingbundle.plugin.bnd.BundledScriptsScannerPlugin; \
+ sourceDirectories="src/main/content/jcr_root"
diff --git a/src/test/resources/filevault-1/pom.xml
b/src/test/resources/filevault-1/pom.xml
new file mode 100644
index 0000000..c9f6949
--- /dev/null
+++ b/src/test/resources/filevault-1/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.sling</groupId>
+ <artifactId>scriptingbundle-maven-plugin-filevault-1</artifactId>
+ <version>0.0.1</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>scriptingbundle-maven-plugin</artifactId>
+ <configuration>
+
<sourceDirectories>src/main/content/jcr_root</sourceDirectories>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>metadata</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/.content.xml
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/.content.xml
new file mode 100644
index 0000000..3409a80
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ jcr:title="Escaped Test"
+/>
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/_escaped_test.html
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/_escaped_test.html
new file mode 100644
index 0000000..2853663
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/_escaped_test/_escaped_test.html
@@ -0,0 +1,18 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/.content.xml
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/.content.xml
new file mode 100644
index 0000000..77528b2
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/.content.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ sling:resourceSuperType="generic/image"
+ sling:requiredResourceTypes="[required/one,required/two]"
+/>
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/image.html
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/image.html
new file mode 100644
index 0000000..2853663
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/image/image.html
@@ -0,0 +1,18 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/.content.xml
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/.content.xml
new file mode 100644
index 0000000..ce48607
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/.content.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ sling:requiredResourceTypes="[my-scripts/image]"
+/>
diff --git
a/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/teaser.html
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/teaser.html
new file mode 100644
index 0000000..2853663
--- /dev/null
+++
b/src/test/resources/filevault-1/src/main/content/jcr_root/apps/my-scripts/teaser/teaser.html
@@ -0,0 +1,18 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
diff --git
a/src/test/resources/filevault-docview-examples/multiple-resource-super-type.xml
b/src/test/resources/filevault-docview-examples/multiple-resource-super-type.xml
new file mode 100644
index 0000000..eaf0192
--- /dev/null
+++
b/src/test/resources/filevault-docview-examples/multiple-resource-super-type.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ sling:resourceSuperType="[generic/image]"
+ sling:requiredResourceTypes="[required/one,required/two]"
+/>
diff --git a/src/test/resources/filevault-docview-examples/not-a-docview.xml
b/src/test/resources/filevault-docview-examples/not-a-docview.xml
new file mode 100644
index 0000000..0bbb270
--- /dev/null
+++ b/src/test/resources/filevault-docview-examples/not-a-docview.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root sling:resourceSuperType="a/b/c"
xmlns:jcr="http://this/is/not/the/namespace/you/are/looking/for"
+ xmlns:sling="http://this/is/not/the/namespace/you/are/looking/for"/>
diff --git
a/src/test/resources/filevault-docview-examples/single-value-required-resource-types.xml
b/src/test/resources/filevault-docview-examples/single-value-required-resource-types.xml
new file mode 100644
index 0000000..92e2a4f
--- /dev/null
+++
b/src/test/resources/filevault-docview-examples/single-value-required-resource-types.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ sling:resourceSuperType="generic/image"
+ sling:requiredResourceTypes="required/one,required/two"
+/>