This is an automated email from the ASF dual-hosted git repository.
dklco pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 3f71c90 Adding a mojo for validating using an oak repository provided
by sling mocks and no longer loading the dependencies dynamically
3f71c90 is described below
commit 3f71c904dfa9eeac49b0f0eca2204d32cd7112be
Author: Dan Klco <[email protected]>
AuthorDate: Wed Jan 26 22:02:45 2022 -0500
Adding a mojo for validating using an oak repository provided by sling
mocks and no longer loading the dependencies dynamically
---
sling-repoinit-maven-plugin/pom.xml | 52 ++++++-
.../src/it/projects/content-package/pom.xml | 9 +-
.../src/it/projects/failing-convert/pom.xml | 3 -
.../src/it/projects/failing-parse/pom.xml | 10 +-
.../projects/failing-validate/invoker.properties} | 5 +-
.../{failing-parse => failing-validate}/pom.xml | 9 +-
.../failing-validate/src/main/repoinit/simple.txt} | 5 +-
.../src/it/projects/failing-validate/verify.groovy | 23 +++
.../src/it/projects/simple/pom.xml | 11 +-
.../org/apache/sling/maven/repoinit/BaseMojo.java | 21 ++-
.../apache/sling/maven/repoinit/ContentFolder.java | 101 +++++++++++++
.../org/apache/sling/maven/repoinit/ParseMojo.java | 102 +++----------
.../apache/sling/maven/repoinit/ValidateMojo.java | 162 +++++++++++++++++++++
.../src/site/markdown/index.md | 3 -
.../apache/sling/maven/repoinit/ParseMojoTest.java | 53 +------
.../sling/maven/repoinit/ToOsgiConfigMojoTest.java | 4 +-
.../sling/maven/repoinit/ValidateMojoTest.java | 140 ++++++++++++++++++
.../invalid/{unsupported.txt => requires-cnd.txt} | 5 +-
.../invalid/{unsupported.txt => willfail.txt} | 5 +-
.../src/test/resources/cnd/test.cnd | 22 +++
.../test/resources/contentloader/json/tags.json | 8 +
21 files changed, 569 insertions(+), 184 deletions(-)
diff --git a/sling-repoinit-maven-plugin/pom.xml
b/sling-repoinit-maven-plugin/pom.xml
index ef81fd9..ea38db4 100644
--- a/sling-repoinit-maven-plugin/pom.xml
+++ b/sling-repoinit-maven-plugin/pom.xml
@@ -66,15 +66,55 @@
<version>2.21.9</version>
</dependency>
- <!-- parse -->
+ <!-- parse and validate -->
<dependency>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-api</artifactId>
- <version>1.7.3</version>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.repoinit.parser</artifactId>
+ <version>1.6.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.repoinit</artifactId>
+ <version>1.1.36</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.sling-mock-oak</artifactId>
+ <version>3.1.2-1.40.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
+ <version>3.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ <version>23.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <version>2.0</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.3.9</version>
+ <scope>provided</scope>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.8.4</version>
<scope>provided</scope>
@@ -203,7 +243,7 @@
<postBuildHookScript>verify.groovy</postBuildHookScript>
<goals>clean install</goals>
<writeJunitReport>true</writeJunitReport>
-
<localRepositoryPath>${project.build.directory}/it-repo</localRepositoryPath>
+
<localRepositoryPath>/Users/klco/Desktop/it-repo</localRepositoryPath>
</configuration>
</plugin>
</plugins>
@@ -218,7 +258,7 @@
</plugin>
</plugins>
</reporting>
-
+
<profiles>
<profile>
<id>ci</id>
diff --git
a/sling-repoinit-maven-plugin/src/it/projects/content-package/pom.xml
b/sling-repoinit-maven-plugin/src/it/projects/content-package/pom.xml
index 3b9a8bb..6898646 100644
--- a/sling-repoinit-maven-plugin/src/it/projects/content-package/pom.xml
+++ b/sling-repoinit-maven-plugin/src/it/projects/content-package/pom.xml
@@ -38,9 +38,12 @@
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.6.10</parserVersion>
- </configuration>
+ </execution>
+ <execution>
+ <id>validate</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
</execution>
<execution>
<id>convert</id>
diff --git
a/sling-repoinit-maven-plugin/src/it/projects/failing-convert/pom.xml
b/sling-repoinit-maven-plugin/src/it/projects/failing-convert/pom.xml
index e62da25..bb5bf0d 100644
--- a/sling-repoinit-maven-plugin/src/it/projects/failing-convert/pom.xml
+++ b/sling-repoinit-maven-plugin/src/it/projects/failing-convert/pom.xml
@@ -36,9 +36,6 @@
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.6.10</parserVersion>
- </configuration>
</execution>
<execution>
<id>convert</id>
diff --git a/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
b/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
index 8932735..b5dfe8f 100644
--- a/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
+++ b/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
@@ -36,9 +36,6 @@
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.2.0</parserVersion>
- </configuration>
</execution>
<execution>
<id>convert</id>
@@ -50,6 +47,13 @@
</configuration>
</execution>
</executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+
<artifactId>org.apache.sling.repoinit.parser</artifactId>
+ <version>1.2.0</version>
+ </dependency>
+ </dependencies>
</plugin>
</plugins>
</build>
diff --git
a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/invoker.properties
similarity index 88%
copy from sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
copy to
sling-repoinit-maven-plugin/src/it/projects/failing-validate/invoker.properties
index e8077f9..2d6d169 100644
--- a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
+++
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/invoker.properties
@@ -16,7 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-
-
-# Not supported in repoinit 1.2.0
-disable user E : "Testing unescaped single backslash \ in this string."
\ No newline at end of file
+invoker.buildResult = failure
\ No newline at end of file
diff --git a/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/pom.xml
similarity index 90%
copy from sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
copy to sling-repoinit-maven-plugin/src/it/projects/failing-validate/pom.xml
index 8932735..064f440 100644
--- a/sling-repoinit-maven-plugin/src/it/projects/failing-parse/pom.xml
+++ b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/pom.xml
@@ -36,9 +36,12 @@
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.2.0</parserVersion>
- </configuration>
+ </execution>
+ <execution>
+ <id>validate</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
</execution>
<execution>
<id>convert</id>
diff --git
a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/src/main/repoinit/simple.txt
similarity index 88%
copy from sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
copy to
sling-repoinit-maven-plugin/src/it/projects/failing-validate/src/main/repoinit/simple.txt
index e8077f9..973dbac 100644
--- a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
+++
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/src/main/repoinit/simple.txt
@@ -17,6 +17,5 @@
# under the License.
#
-
-# Not supported in repoinit 1.2.0
-disable user E : "Testing unescaped single backslash \ in this string."
\ No newline at end of file
+# nt:folders are rigid on their structure
+create path /content(nt:folder)/test(nt:unstructured)
\ No newline at end of file
diff --git
a/sling-repoinit-maven-plugin/src/it/projects/failing-validate/verify.groovy
b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/verify.groovy
new file mode 100644
index 0000000..142b537
--- /dev/null
+++ b/sling-repoinit-maven-plugin/src/it/projects/failing-validate/verify.groovy
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+import java.io.File;
+
+def buildLog = new File( basedir, 'build.log');
+
+def res = buildLog.readLines().grep(~/.+Failed to execute script:
.+simple.txt.+/)
+
+assert res.size() > 0 : "Expected message not found"
\ No newline at end of file
diff --git a/sling-repoinit-maven-plugin/src/it/projects/simple/pom.xml
b/sling-repoinit-maven-plugin/src/it/projects/simple/pom.xml
index d539c8c..592bd23 100644
--- a/sling-repoinit-maven-plugin/src/it/projects/simple/pom.xml
+++ b/sling-repoinit-maven-plugin/src/it/projects/simple/pom.xml
@@ -1,5 +1,5 @@
<?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
@@ -36,9 +36,6 @@
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.6.10</parserVersion>
- </configuration>
</execution>
<execution>
<id>convert</id>
@@ -49,6 +46,12 @@
<outputDir>${project.basedir}/src/main/jcr_root</outputDir>
</configuration>
</execution>
+ <execution>
+ <id>validate</id>
+ <goals>
+ <goal>validate</goal>
+ </goals>
+ </execution>
</executions>
</plugin>
</plugins>
diff --git
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/BaseMojo.java
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/BaseMojo.java
index 1277a78..885c183 100644
---
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/BaseMojo.java
+++
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/BaseMojo.java
@@ -29,6 +29,7 @@ import java.util.stream.Stream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
+import org.jetbrains.annotations.NotNull;
public abstract class BaseMojo extends AbstractMojo {
@@ -49,28 +50,32 @@ public abstract class BaseMojo extends AbstractMojo {
List<String> includedFiles;
List<File> findScripts() throws MojoExecutionException {
+ return findByGlob(scriptBaseDir, includedFiles);
+ }
+
+ List<File> findByGlob(@NotNull File baseDir, @NotNull List<String>
patterns) throws MojoExecutionException {
- List<PathMatcher> matchers = includedFiles.stream()
+ List<PathMatcher> matchers = patterns.stream()
.map(pattern ->
FileSystems.getDefault().getPathMatcher("glob:" + pattern))
.collect(Collectors.toList());
- getLog().info("Loading scripts from: " + scriptBaseDir + " using
patterns: " + includedFiles);
+ getLog().debug("Loading files from: " + baseDir + " using patterns: "
+ patterns);
try {
- try (Stream<Path> paths = Files.walk(scriptBaseDir.toPath())) {
- List<File> scripts = paths.map(path ->
scriptBaseDir.toPath().relativize(path))
+ try (Stream<Path> paths = Files.walk(baseDir.toPath())) {
+ List<File> scripts = paths.map(path ->
baseDir.toPath().relativize(path))
.filter(file -> matchers.stream().anyMatch(matcher ->
matcher.matches(file)))
- .map(path ->
scriptBaseDir.toPath().resolve(path).toAbsolutePath())
+ .map(path ->
baseDir.toPath().resolve(path).toAbsolutePath())
.map(Path::toFile)
.collect(Collectors.toList());
if (scripts.isEmpty()) {
getLog().warn(
- "No scripts found in directory: " + scriptBaseDir
+ " with patterns: " + includedFiles);
+ "No files found in directory: " + baseDir + " with
patterns: " + patterns);
}
return scripts;
}
} catch (IOException e) {
- throw new MojoExecutionException("Could not find scripts in
directory: " + scriptBaseDir
- + " using patterns: " + includedFiles + " Exception: " +
e.getMessage(), e);
+ throw new MojoExecutionException("Could not find files in
directory: " + baseDir
+ + " using patterns: " + patterns + " Exception: " +
e.getMessage(), e);
}
}
}
diff --git
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ContentFolder.java
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ContentFolder.java
new file mode 100644
index 0000000..2d92fda
--- /dev/null
+++
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ContentFolder.java
@@ -0,0 +1,101 @@
+/*
+ * 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.maven.repoinit;
+
+import java.io.File;
+
+public class ContentFolder {
+
+ public enum Type {
+ JSON, VLT_XML
+ }
+
+ private File folder;
+ private String path;
+ private Type type;
+
+ /**
+ *
+ */
+ public ContentFolder() {
+ this.type = Type.VLT_XML;
+ }
+
+ /**
+ * @param folder
+ * @param path
+ * @param type
+ */
+ public ContentFolder(File folder, String path, Type type) {
+ this.folder = folder;
+ this.path = path;
+ this.type = type;
+ }
+
+ /**
+ * @return the folder
+ */
+ public File getFolder() {
+ return folder;
+ }
+
+ /**
+ * @param folder the folder to set
+ */
+ public void setFolder(File folder) {
+ this.folder = folder;
+ }
+
+ /**
+ * @return the path
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * @param path the path to set
+ */
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ /**
+ * @return the type
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "ContentFolder [folder=" + folder + ", path=" + path + ",
type=" + type + "]";
+ }
+
+}
diff --git
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ParseMojo.java
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ParseMojo.java
index 850afd9..a064205 100644
---
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ParseMojo.java
+++
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ParseMojo.java
@@ -21,64 +21,25 @@ import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.eclipse.aether.RepositorySystem;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.artifact.DefaultArtifact;
-import org.eclipse.aether.repository.RemoteRepository;
-import org.eclipse.aether.resolution.ArtifactRequest;
-import org.eclipse.aether.resolution.ArtifactResolutionException;
-import org.eclipse.aether.resolution.ArtifactResult;
+import org.apache.sling.repoinit.parser.impl.ParseException;
+import org.apache.sling.repoinit.parser.impl.RepoInitParserImpl;
+import org.apache.sling.repoinit.parser.impl.TokenMgrError;
+import org.apache.sling.repoinit.parser.operations.Operation;
+import org.jetbrains.annotations.NotNull;
/**
* Goal which parses the specified RepoInit files. Any errors encountered will
* be reported and fail the build.
*/
-@Mojo(name = "parse", defaultPhase = LifecyclePhase.PROCESS_SOURCES,
requiresProject = false, requiresDependencyResolution = ResolutionScope.RUNTIME)
+@Mojo(name = "parse", defaultPhase = LifecyclePhase.PROCESS_SOURCES,
requiresProject = false)
public class ParseMojo extends BaseMojo {
- /**
- * The entry point to Maven Artifact Resolver, i.e. the component doing
all the
- * work.
- */
- @Component
- RepositorySystem repoSystem;
-
- /**
- * The current repository/network configuration of Maven.
- */
- @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
- RepositorySystemSession repoSession;
-
- /**
- * The project's remote repositories to use for the resolution.
- */
- @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly
= true)
- List<RemoteRepository> remoteRepos;
-
- /**
- * The version of Sling RepoInit parser to use to parse the repoinit files.
- *
- * <a href=
- *
"https://search.maven.org/search?q=a:org.apache.sling.repoinit.parser">Released
- * Sling RepoInit Parser versions</a>
- */
- @Parameter(property = "repoinit.parserVersion", required = true)
- String parserVersion;
-
public void execute()
throws MojoExecutionException {
@@ -89,59 +50,30 @@ public class ParseMojo extends BaseMojo {
return;
}
- File parserJar = resolveParser();
- try (URLClassLoader classLoader = new URLClassLoader(new URL[] {
parserJar.toURI().toURL() })) {
- Class<?> parserClass = classLoader
-
.loadClass("org.apache.sling.repoinit.parser.impl.RepoInitParserImpl");
-
- for (File script : scripts) {
- getLog().info("Parsing script: " + script.getAbsolutePath());
- parseScript(parserClass, script);
- }
- getLog().info("All scripts parsed successfully!");
- } catch (IllegalArgumentException | SecurityException |
ClassNotFoundException | IOException e) {
- throw new MojoExecutionException("Could not parse scripts: " +
e.getMessage(), e);
+ for (File script : scripts) {
+ getLog().info("Parsing script: " + script.getAbsolutePath());
+ parseScript(script);
}
+ getLog().info("All scripts parsed successfully!");
}
- private void parseScript(Class<?> parserClass, File script) throws
MojoExecutionException {
+ @NotNull
+ List<Operation> parseScript(@NotNull File script) throws
MojoExecutionException {
try {
try (Reader reader = new BufferedReader(new FileReader(script))) {
- Object parser = parserClass.getConstructor(Reader.class)
- .newInstance(reader);
- Method parse = parser.getClass().getDeclaredMethod("parse");
- List<?> operations = (List<?>) parse.invoke(parser);
+ List<Operation> operations = new
RepoInitParserImpl(reader).parse();
getLog().info("Parsed operations: \n\n"
+
operations.stream().map(Object::toString).collect(Collectors.joining("\n")) +
"\n");
+ return operations;
}
- } catch (InvocationTargetException e) {
+ } catch (ParseException | TokenMgrError e) {
throw new MojoExecutionException(
"Failed to parse script " + script.getAbsolutePath() + "
Exception: "
- + e.getTargetException().getMessage(),
- e.getTargetException());
- } catch (InstantiationException | NoSuchMethodException |
SecurityException | IllegalAccessException
- | IllegalArgumentException e) {
- throw new MojoExecutionException("Unexpected exception calling
parser: " + e.getMessage(), e);
+ + e.getMessage(),
+ e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to read script from
files: " + e.getMessage(), e);
}
}
- private File resolveParser() throws MojoExecutionException {
- try {
- Artifact artifact = new DefaultArtifact(
- "org.apache.sling:org.apache.sling.repoinit.parser:" +
parserVersion);
- ArtifactRequest request = new ArtifactRequest();
- request.setArtifact(artifact);
- request.setRepositories(remoteRepos);
- getLog().info("Getting Repoint Parser version " +
artifact.getVersion() + " from " + remoteRepos);
- ArtifactResult result = repoSystem.resolveArtifact(repoSession,
request);
- getLog().info("Resolved artifact " + artifact + " to " +
result.getArtifact().getFile() + " from "
- + result.getRepository());
- return result.getArtifact().getFile();
- } catch (IllegalArgumentException | ArtifactResolutionException e) {
- throw new MojoExecutionException("Couldn't download artifact: " +
e.getMessage(), e);
- }
-
- }
}
diff --git
a/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ValidateMojo.java
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ValidateMojo.java
new file mode 100644
index 0000000..61bf484
--- /dev/null
+++
b/sling-repoinit-maven-plugin/src/main/java/org/apache/sling/maven/repoinit/ValidateMojo.java
@@ -0,0 +1,162 @@
+/*
+ * 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.maven.repoinit;
+
+import java.io.File;
+import java.io.FileReader;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.jcr.repoinit.JcrRepoInitOpsProcessor;
+import org.apache.sling.jcr.repoinit.impl.JcrRepoInitOpsProcessorImpl;
+import org.apache.sling.maven.repoinit.ContentFolder.Type;
+import org.apache.sling.repoinit.parser.operations.Operation;
+import org.apache.sling.testing.mock.sling.ResourceResolverType;
+import org.apache.sling.testing.mock.sling.context.SlingContextImpl;
+import org.apache.sling.testing.mock.sling.junit5.SlingContext;
+import org.apache.sling.testing.mock.sling.junit5.SlingContextBuilder;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Goal which validates the specified RepoInit files by installing them into a
+ * mock Sling repository. Any errors encountered will be reported and fail the
+ * build.
+ */
+@Mojo(name = "validate", defaultPhase = LifecyclePhase.TEST, requiresProject =
false)
+public class ValidateMojo extends ParseMojo {
+
+ /**
+ * CND (compact node definitions) to load before running the validation.
+ * Supports glob style patterns. All globs are evaluated relative to the
+ * <code>${project.basedir}</code>
+ *
+ * <a
href="https://docs.oracle.com/javase/tutorial/essential/io/find.html">More
+ * on Globs in Java</a>
+ */
+ @Parameter(property = "repoinit.nodeDefinitions", required = false)
+ List<String> nodeDefinitions;
+
+ /**
+ * Initial content folders to load before running the RepoInit scripts.
+ */
+ @Parameter(property = "repoinit.contentFolders", required = false)
+ List<ContentFolder> contentFolders;
+
+ /**
+ * The Maven Project
+ */
+ @Parameter(defaultValue = "${project}", required = true, readonly = true)
+ MavenProject project = null;
+
+ @Override
+ public void execute()
+ throws MojoExecutionException {
+ getLog().info("Loading scripts from: " + scriptBaseDir);
+ List<File> scripts = findScripts();
+
+ if (scripts.isEmpty()) {
+ return;
+ }
+
+ LinkedHashMap<String, List<Operation>> parsedScripts = new
LinkedHashMap<>();
+ for (File script : scripts) {
+ getLog().debug("Parsing script: " + script.getAbsolutePath());
+ parsedScripts.put(script.getAbsolutePath(), parseScript(script));
+ }
+ getLog().info("All scripts parsed successfully!");
+
+ getLog().info("Setting up Sling context...");
+ try (ValidatorContext context = new ValidatorContext()) {
+ Session session =
Optional.ofNullable(context.resourceResolver().adaptTo(Session.class))
+ .orElseThrow(() -> new MojoExecutionException("Failed to
get Session from Sling Context"));
+
+ if (nodeDefinitions != null && !nodeDefinitions.isEmpty()) {
+ getLog().info("Loading nodetypes");
+ loadNodeDefinitions(nodeDefinitions, session);
+ }
+
+ if (contentFolders != null && !contentFolders.isEmpty()) {
+ getLog().info("Loading initial content");
+ loadInitialContent(contentFolders, context);
+ }
+
+ JcrRepoInitOpsProcessor processor = new
JcrRepoInitOpsProcessorImpl();
+ for (Entry<String, List<Operation>> parsed :
parsedScripts.entrySet()) {
+ getLog().info("Executing script: " + parsed.getKey());
+ try {
+ processor.apply(session, parsed.getValue());
+ } catch (Exception e) {
+ throw new MojoExecutionException("Failed to execute
script: " + parsed.getKey()
+ + ", Exception: " + e.toString(), e);
+ }
+ }
+ }
+ getLog().info("All scripts executed successfully!");
+ }
+
+ void loadNodeDefinitions(@NotNull List<String> globs, @NotNull Session
session) throws MojoExecutionException {
+ File root = new File(".");
+ List<File> cndFiles = findByGlob(root, globs);
+ for (File cndFile : cndFiles) {
+ getLog().info("Loading node types from: " +
cndFile.getAbsolutePath());
+ try {
+ CndImporter.registerNodeTypes(new FileReader(cndFile),
session);
+ } catch (Exception e) {
+ throw new MojoExecutionException(
+ "Failed to load CND file: " +
cndFile.getAbsolutePath() + ", Exception: " + e.toString(), e);
+ }
+ }
+ }
+
+ void loadInitialContent(@NotNull List<ContentFolder> contentFolders,
@NotNull ValidatorContext context)
+ throws MojoExecutionException {
+ for (ContentFolder contentFolder : contentFolders) {
+ if (contentFolder.getFolder() == null ||
!contentFolder.getFolder().isDirectory()
+ || contentFolder.getPath() == null ||
contentFolder.getType() == null) {
+ throw new MojoExecutionException("Invalid initial content
folder: " + contentFolder);
+ }
+ if (contentFolder.getType() == Type.VLT_XML) {
+
context.load(true).folderFileVaultXml(contentFolder.getFolder(),
contentFolder.getPath());
+ } else {
+ context.load(true).folderJson(contentFolder.getFolder(),
contentFolder.getPath());
+ }
+ }
+ }
+
+ class ValidatorContext extends SlingContextImpl implements AutoCloseable {
+ ValidatorContext() {
+ setResourceResolverType(ResourceResolverType.JCR_OAK);
+ super.setUp();
+ }
+
+ @Override
+ public void close() {
+ super.tearDown();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/sling-repoinit-maven-plugin/src/site/markdown/index.md
b/sling-repoinit-maven-plugin/src/site/markdown/index.md
index 4bac7be..96be07c 100644
--- a/sling-repoinit-maven-plugin/src/site/markdown/index.md
+++ b/sling-repoinit-maven-plugin/src/site/markdown/index.md
@@ -40,9 +40,6 @@ builds a content package containing the configurations.
<goals>
<goal>parse</goal>
</goals>
- <configuration>
- <parserVersion>1.6.10</parserVersion>
- </configuration>
</execution>
<execution>
<id>convert</id>
diff --git
a/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ParseMojoTest.java
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ParseMojoTest.java
index 4b229d9..a1e6101 100644
---
a/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ParseMojoTest.java
+++
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ParseMojoTest.java
@@ -17,31 +17,19 @@
package org.apache.sling.maven.repoinit;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import java.io.File;
import java.util.Collections;
import org.apache.maven.monitor.logging.DefaultLog;
import org.apache.maven.plugin.MojoExecutionException;
-import org.eclipse.aether.RepositorySystem;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.resolution.ArtifactRequest;
-import org.eclipse.aether.resolution.ArtifactResolutionException;
-import org.eclipse.aether.resolution.ArtifactResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
-import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
@@ -50,49 +38,21 @@ import org.mockito.quality.Strictness;
@MockitoSettings(strictness = Strictness.LENIENT)
class ParseMojoTest {
- @Mock
- RepositorySystem repoSystem;
-
- @Mock
- RepositorySystemSession repoSession;
-
ParseMojo parseMojo;
CapturingLogger log = new CapturingLogger();
@BeforeEach
- void beforeEach() throws IllegalArgumentException,
ArtifactResolutionException {
+ void beforeEach() throws IllegalArgumentException {
parseMojo = new ParseMojo();
- parseMojo.repoSystem = repoSystem;
- parseMojo.repoSession = repoSession;
log.reset();
parseMojo.setLog(new DefaultLog(log));
- when(repoSystem.resolveArtifact(any(RepositorySystemSession.class),
any(ArtifactRequest.class)))
- .thenAnswer(this::mockResponse);
- }
-
- ArtifactResult mockResponse(InvocationOnMock invocation) throws
ArtifactResolutionException {
- ArtifactRequest request = (ArtifactRequest)
invocation.getArguments()[1];
-
- File artifactFile = new File(
- "target/unit-test-jars/org.apache.sling.repoinit.parser-" +
request.getArtifact().getVersion()
- + ".jar");
- ArtifactResult result = new ArtifactResult(request);
- if (!artifactFile.exists()) {
- throw new
ArtifactResolutionException(Collections.singletonList(result));
- }
- Artifact artifact = mock(Artifact.class);
- when(artifact.getFile()).thenReturn(artifactFile);
-
- result.setArtifact(artifact);
- return result;
}
@Test
void testParser() throws MojoExecutionException {
parseMojo.includedFiles = Collections.singletonList("*.txt");
- parseMojo.parserVersion = "1.2.0";
parseMojo.scriptBaseDir = new File("src/test/repoinit");
parseMojo.execute();
@@ -107,7 +67,6 @@ class ParseMojoTest {
@Test
void testLargeFile() throws MojoExecutionException {
parseMojo.includedFiles =
Collections.singletonList("large/combined.txt");
- parseMojo.parserVersion = "1.6.10";
parseMojo.scriptBaseDir = new File("src/test/repoinit");
parseMojo.execute();
@@ -119,28 +78,22 @@ class ParseMojoTest {
@Test
void testNoFiles() throws MojoExecutionException {
parseMojo.includedFiles = Collections.singletonList("*.tx");
- parseMojo.parserVersion = "1.2.0";
parseMojo.scriptBaseDir = new File("src/test/repoinit");
parseMojo.execute();
- assertTrue(log.getLogs().contains("[warn] No scripts found in
directory:"),
+ assertTrue(log.getLogs().contains("[warn] No files found in
directory:"),
() -> "Expected to warning and did not in: \n" +
log.getLogs());
- assertFalse(log.getLogs().contains("Getting Repoint Parser version"),
- () -> "Expected not to resolve repoinit parser version if no
scripts found");
}
@ParameterizedTest
@CsvSource({
- "invalid/unsupported.txt,1.2.0,Failed to parse script",
"invalid/invalid.txt,1.6.10,Failed to parse script",
- "invalid/apache.png,1.6.10,Failed to parse script",
- "*.txt,0.2.0,Couldn't download artifact: The following artifacts
could not be resolved:
org.apache.sling:org.apache.sling.repoinit.parser:jar:0.2.0" })
+ "invalid/apache.png,1.6.10,Failed to parse script" })
void testFailures(String filePattern, String parserVersion, String
messageSubStr)
throws MojoExecutionException {
parseMojo.includedFiles = Collections.singletonList(filePattern);
- parseMojo.parserVersion = parserVersion;
parseMojo.scriptBaseDir = new File("src/test/repoinit");
String message = assertThrows(MojoExecutionException.class, () ->
parseMojo.execute()).getMessage();
diff --git
a/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ToOsgiConfigMojoTest.java
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ToOsgiConfigMojoTest.java
index ad09f6a..286e77e 100644
---
a/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ToOsgiConfigMojoTest.java
+++
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ToOsgiConfigMojoTest.java
@@ -87,7 +87,7 @@ class ToOsgiConfigMojoTest {
toOsgiConfigMojo.execute();
- assertTrue(log.getLogs().contains("[warn] No scripts found in
directory:"),
+ assertTrue(log.getLogs().contains("[warn] No files found in
directory:"),
() -> "Expected to warning and did not in: \n" +
log.getLogs());
}
@@ -101,7 +101,7 @@ class ToOsgiConfigMojoTest {
toOsgiConfigMojo.scriptBaseDir = new
File("src/test/repoinit/somethingelse");
String message = assertThrows(MojoExecutionException.class, () ->
toOsgiConfigMojo.execute()).getMessage();
- assertTrue(message.contains("Could not find scripts in directory:"),
+ assertTrue(message.contains("Could not find files in directory:"),
"Did not recieve expected message in: " + message);
}
diff --git
a/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ValidateMojoTest.java
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ValidateMojoTest.java
new file mode 100644
index 0000000..4924c92
--- /dev/null
+++
b/sling-repoinit-maven-plugin/src/test/java/org/apache/sling/maven/repoinit/ValidateMojoTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.maven.repoinit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+import org.apache.maven.monitor.logging.DefaultLog;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.sling.maven.repoinit.ContentFolder.Type;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class ValidateMojoTest {
+
+ ValidateMojo validateMojo;
+
+ CapturingLogger log = new CapturingLogger();
+
+ @BeforeEach
+ void beforeEach() throws IllegalArgumentException {
+ validateMojo = new ValidateMojo();
+ log.reset();
+ validateMojo.setLog(new DefaultLog(log));
+ }
+
+ @Test
+ void testValidator() throws MojoExecutionException {
+ validateMojo.includedFiles = Collections.singletonList("*.txt");
+ validateMojo.scriptBaseDir = new File("src/test/repoinit");
+
+ validateMojo.execute();
+
+ assertEquals(2, log.getLines().stream().filter(l ->
l.contains("[debug] Parsing script:")).count(),
+ "Did not find the expected number of files parsed");
+
+ assertTrue(log.getLogs().contains("[info] All scripts executed
successfully!"),
+ () -> "Expected to find success message and did not in: \n" +
log.getLogs());
+ }
+
+ @Test
+ void testLoadCnd() throws MojoExecutionException {
+ validateMojo.scriptBaseDir = new File("src/test/repoinit");
+ validateMojo.includedFiles =
Collections.singletonList("invalid/requires-cnd.txt");
+
+ Throwable realCause = assertThrows(MojoExecutionException.class, () ->
validateMojo.execute(),
+ "Expected loading of repoinit script to fail due to missing
node types").getCause().getCause();
+ assertTrue(realCause instanceof NoSuchNodeTypeException, "Expected
exception type not thrown");
+
+ log.reset();
+ validateMojo.nodeDefinitions =
Collections.singletonList("src/test/resources/cnd/test.cnd");
+ validateMojo.execute();
+ assertTrue(log.getLogs().contains("[info] All scripts executed
successfully!"),
+ () -> "Expected to find success message and did not in: \n" +
log.getLogs());
+ }
+
+ @Test
+ void testLoadContent() throws MojoExecutionException {
+ validateMojo.scriptBaseDir = new File("src/test/repoinit");
+ validateMojo.includedFiles =
Collections.singletonList("invalid/requires-cnd.txt");
+ validateMojo.nodeDefinitions =
Collections.singletonList("src/test/resources/cnd/test.cnd");
+
+ ContentFolder contentFolder = new ContentFolder();
+ contentFolder.setFolder(new
File("src/test/resources/contentloader/json"));
+ contentFolder.setType(Type.JSON);
+ contentFolder.setPath("/etc/taxonomy");
+ validateMojo.contentFolders = Collections.singletonList(contentFolder);
+ validateMojo.execute();
+ assertTrue(log.getLogs().contains("[info] All scripts executed
successfully!"),
+ () -> "Expected to find success message and did not in: \n" +
log.getLogs());
+ }
+
+ @Test
+ void testFailingScriptScript() throws MojoExecutionException {
+ validateMojo.scriptBaseDir = new File("src/test/repoinit");
+ validateMojo.includedFiles =
Collections.singletonList("invalid/willfail.txt");
+ validateMojo.nodeDefinitions = Collections.emptyList();
+
+ validateMojo.contentFolders = Collections.emptyList();
+ assertThrows(MojoExecutionException.class, () ->
validateMojo.execute());
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void testInvalidContentFolder(ContentFolder contentFolder) throws
MojoExecutionException {
+ validateMojo.scriptBaseDir = new File("src/test/repoinit");
+ validateMojo.includedFiles =
Collections.singletonList("invalid/requires-cnd.txt");
+ validateMojo.nodeDefinitions =
Collections.singletonList("src/test/resources/cnd/test.cnd");
+
+ validateMojo.contentFolders = Collections.singletonList(contentFolder);
+ MojoExecutionException exception =
assertThrows(MojoExecutionException.class, () -> validateMojo.execute(),
+ "Expected loading of repoinit script to fail due to missing
node types");
+ assertTrue(exception.getMessage().contains("Invalid initial content
folder: ContentFolder"),
+ "Unexpected message: " + exception.getMessage());
+
+ }
+
+ static Stream<ContentFolder> testInvalidContentFolder() {
+ List<ContentFolder> invalidFolders = new ArrayList<>();
+ invalidFolders.add(new ContentFolder(new
File("src/test/resources/contentloader/json"), "/etc/taxonomy", null));
+ invalidFolders.add(new ContentFolder(new
File("src/test/resources/contentloader/json"), null, Type.JSON));
+ invalidFolders
+ .add(new ContentFolder(new
File("src/test/resources/contentloader/not/a/folder"), "/", Type.JSON));
+ invalidFolders
+ .add(new ContentFolder(new
File("src/test/resources/contentloader/json/tags.json"), "/", Type.JSON));
+ return invalidFolders.stream();
+ }
+
+}
\ No newline at end of file
diff --git
a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
b/sling-repoinit-maven-plugin/src/test/repoinit/invalid/requires-cnd.txt
similarity index 88%
copy from sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
copy to sling-repoinit-maven-plugin/src/test/repoinit/invalid/requires-cnd.txt
index e8077f9..78a7eb9 100644
--- a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
+++ b/sling-repoinit-maven-plugin/src/test/repoinit/invalid/requires-cnd.txt
@@ -16,7 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-
-
-# Not supported in repoinit 1.2.0
-disable user E : "Testing unescaped single backslash \ in this string."
\ No newline at end of file
+create path (sling:Folder) /etc/taxonomy(sling:Taxonomy)/item1(sling:Taxonomy)
\ No newline at end of file
diff --git
a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
b/sling-repoinit-maven-plugin/src/test/repoinit/invalid/willfail.txt
similarity index 88%
rename from
sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
rename to sling-repoinit-maven-plugin/src/test/repoinit/invalid/willfail.txt
index e8077f9..973dbac 100644
--- a/sling-repoinit-maven-plugin/src/test/repoinit/invalid/unsupported.txt
+++ b/sling-repoinit-maven-plugin/src/test/repoinit/invalid/willfail.txt
@@ -17,6 +17,5 @@
# under the License.
#
-
-# Not supported in repoinit 1.2.0
-disable user E : "Testing unescaped single backslash \ in this string."
\ No newline at end of file
+# nt:folders are rigid on their structure
+create path /content(nt:folder)/test(nt:unstructured)
\ No newline at end of file
diff --git a/sling-repoinit-maven-plugin/src/test/resources/cnd/test.cnd
b/sling-repoinit-maven-plugin/src/test/resources/cnd/test.cnd
new file mode 100644
index 0000000..7aa59ed
--- /dev/null
+++ b/sling-repoinit-maven-plugin/src/test/resources/cnd/test.cnd
@@ -0,0 +1,22 @@
+// 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.
+//
+[sling:Taxonomy] > nt:hierarchyNode, mix:lastModified
+ orderable
+ - sling:related (string)
+ - jcr:title (string)
+ + * (sling:Taxonomy) = sling:Taxonomy version
\ No newline at end of file
diff --git
a/sling-repoinit-maven-plugin/src/test/resources/contentloader/json/tags.json
b/sling-repoinit-maven-plugin/src/test/resources/contentloader/json/tags.json
new file mode 100644
index 0000000..deef802
--- /dev/null
+++
b/sling-repoinit-maven-plugin/src/test/resources/contentloader/json/tags.json
@@ -0,0 +1,8 @@
+{
+ "jcr:primaryType": "sling:Taxonomy",
+ "jcr:title": "Reference",
+ "community": {
+ "jcr:primaryType": "sling:Taxonomy",
+ "jcr:title": "Community"
+ }
+}