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
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 @@
@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 @@
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 @@
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 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 @@
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 @@
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 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 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 @@
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();
- }
- extractVersionRange(requiresFile, requiredBuilder, requiresParameter.getValue().getVersion());
- requiredCapabilities.add(requiredBuilder.build());
- }
+ processRequiredResourceTypes(requiresFile, requiredCapabilities, requiredResourceTypes);
} catch (IOException e) {
- throw new UncheckedIOException(String.format("Unable to read file %s.", requiresFile.toString()), 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)));
+ }
+ }
+ 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 @@
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 @@
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 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 @@
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 @@
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.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 @@
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 @@
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 @@
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 @@
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.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 @@
} 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 @@
/** 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 @@
}
@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 @@
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 @@
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 @@
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 @@
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 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 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"
+/>