You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2018/10/17 22:00:54 UTC
[sling-slingfeature-maven-plugin] 01/01: SLING-8032 - Add a MOJO
which is able to validate JSON Feature file against the JSON Schema
This is an automated email from the ASF dual-hosted git repository.
simonetripodi pushed a commit to branch schema-validation
in repository https://gitbox.apache.org/repos/asf/sling-slingfeature-maven-plugin.git
commit 1245b9f45d706aa5ec1929fa5e0fd0783352f5ea
Author: Simo Tripodi <st...@adobe.com>
AuthorDate: Thu Oct 18 00:00:27 2018 +0200
SLING-8032 - Add a MOJO which is able to validate JSON Feature file
against the JSON Schema
initial checkin
---
pom.xml | 11 ++
src/it/schema-validation-ko/invoker.properties | 18 +++
src/it/schema-validation-ko/pom.xml | 43 +++++++
.../src/main/features/invalid-feature.json | 5 +
src/it/schema-validation-ko/verify.bsh | 43 +++++++
src/it/schema-validation-ok/invoker.properties | 17 +++
src/it/schema-validation-ok/pom.xml | 43 +++++++
.../src/main/features/valid-feature.json | 29 +++++
src/it/schema-validation-ok/verify.bsh | 42 ++++++
.../maven/mojos/ValidationFeaturesMojo.java | 143 +++++++++++++++++++++
10 files changed, 394 insertions(+)
diff --git a/pom.xml b/pom.xml
index 7403abd..e00de19 100644
--- a/pom.xml
+++ b/pom.xml
@@ -216,6 +216,17 @@
<artifactId>maven-filtering</artifactId>
<version>3.1.1</version>
</dependency>
+ <!-- schema validation -->
+ <dependency>
+ <groupId>com.github.java-json-tools</groupId>
+ <artifactId>json-schema-validator</artifactId>
+ <version>2.2.10</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.2.3</version>
+ </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
diff --git a/src/it/schema-validation-ko/invoker.properties b/src/it/schema-validation-ko/invoker.properties
new file mode 100644
index 0000000..57af569
--- /dev/null
+++ b/src/it/schema-validation-ko/invoker.properties
@@ -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.
+
+invoker.goals = clean validate
+invoker.buildResult = failure
+invoker.debug = true
diff --git a/src/it/schema-validation-ko/pom.xml b/src/it/schema-validation-ko/pom.xml
new file mode 100644
index 0000000..2c8d1a0
--- /dev/null
+++ b/src/it/schema-validation-ko/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ agreements. See the NOTICE file distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ Version 2.0 (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ either express or implied. See the License for the specific language governing permissions
+ and limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>slingfeature-maven-plugin-test</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <name>Apache Sling Features Maven plugin test</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <executions>
+ <execution>
+ <id>analyze</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>features-schema-validation</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/it/schema-validation-ko/src/main/features/invalid-feature.json b/src/it/schema-validation-ko/src/main/features/invalid-feature.json
new file mode 100644
index 0000000..59ff8cc
--- /dev/null
+++ b/src/it/schema-validation-ko/src/main/features/invalid-feature.json
@@ -0,0 +1,5 @@
+{
+ "id":"org.apache.sling:slingfeature-maven-plugin-test:1.0.0-SNAPSHOT",
+ "model-version": 5,
+ "bundles": [ false ]
+}
diff --git a/src/it/schema-validation-ko/verify.bsh b/src/it/schema-validation-ko/verify.bsh
new file mode 100644
index 0000000..01a9b16
--- /dev/null
+++ b/src/it/schema-validation-ko/verify.bsh
@@ -0,0 +1,43 @@
+/*
+ * 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.*;
+import java.util.*;
+ import org.codehaus.plexus.util.*;
+ boolean check() {
+ File file = new File(basedir, "target/slingtest.json");
+ String log = FileUtils.fileRead(file);
+ String[] values = {
+ "/definitions/Bundle: instance type (boolean) does not match any allowed primitive type (allowed: ["object","string"])",
+ "/properties/model-version: instance type (integer) does not match any allowed primitive type (allowed: ["string"])",
+ "One or more features Feature file validation detected one or more error(s), please read the plugin log for more datils"
+ };
+ for (String value : values) {
+ if (log.indexOf(value) < 0) {
+ System.out.println("FAILED!");
+ return false;
+ }
+ }
+ return true;
+ }
+ try {
+ return check();
+ }
+ catch(Throwable t) {
+ t.printStackTrace();
+ return false;
+ }
+ return true;
diff --git a/src/it/schema-validation-ok/invoker.properties b/src/it/schema-validation-ok/invoker.properties
new file mode 100644
index 0000000..f56145d
--- /dev/null
+++ b/src/it/schema-validation-ok/invoker.properties
@@ -0,0 +1,17 @@
+# 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.
+
+invoker.goals = clean validate
+invoker.debug = true
diff --git a/src/it/schema-validation-ok/pom.xml b/src/it/schema-validation-ok/pom.xml
new file mode 100644
index 0000000..2c8d1a0
--- /dev/null
+++ b/src/it/schema-validation-ok/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ agreements. See the NOTICE file distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file to you under the Apache License,
+ Version 2.0 (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ either express or implied. See the License for the specific language governing permissions
+ and limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>slingfeature-maven-plugin-test</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0.0-SNAPSHOT</version>
+
+ <name>Apache Sling Features Maven plugin test</name>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>@project.groupId@</groupId>
+ <artifactId>@project.artifactId@</artifactId>
+ <version>@project.version@</version>
+ <executions>
+ <execution>
+ <id>analyze</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>features-schema-validation</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/src/it/schema-validation-ok/src/main/features/valid-feature.json b/src/it/schema-validation-ok/src/main/features/valid-feature.json
new file mode 100644
index 0000000..dbef6ec
--- /dev/null
+++ b/src/it/schema-validation-ok/src/main/features/valid-feature.json
@@ -0,0 +1,29 @@
+{
+ "id":"org.apache.sling:slingfeature-maven-plugin-test:1.0.0-SNAPSHOT",
+ "include": {
+ "id": "org.apache.sling:slingfeature:slingfeature:base:${project.version}",
+ "removals": {
+ "configurations": ["org.apache.sling.jcr.repoinit.impl.RepositoryInitializer"]
+ }
+ },
+ "bundles":[
+ {
+ "id":"org.osgi:org.osgi.framework:1.9.0",
+ "start-level":"20"
+ }
+ ],
+ "api-regions:JSON|false": [
+ {
+ "name": "global",
+ "exports": [
+ "org.osgi.util.function"
+ ]
+ },
+ {
+ "name": "asf",
+ "exports": [
+ "org.osgi.util.function"
+ ]
+ }
+ ]
+}
diff --git a/src/it/schema-validation-ok/verify.bsh b/src/it/schema-validation-ok/verify.bsh
new file mode 100644
index 0000000..df66f2d
--- /dev/null
+++ b/src/it/schema-validation-ok/verify.bsh
@@ -0,0 +1,42 @@
+/*
+ * 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.*;
+import java.util.*;
+
+import org.codehaus.plexus.util.*;
+
+ boolean check() {
+ File file = new File(basedir, "build.log");
+ String log = FileUtils.fileRead(file);
+
+ if (log.indexOf("All processed Feature files are valid") < 0) {
+ System.out.println( "FAILED!" );
+ return false;
+ }
+ return true;
+ }
+
+ try {
+ return check();
+ }
+ catch(Throwable t) {
+ t.printStackTrace();
+ return false;
+ }
+
+ return true;
diff --git a/src/main/java/org/apache/sling/feature/maven/mojos/ValidationFeaturesMojo.java b/src/main/java/org/apache/sling/feature/maven/mojos/ValidationFeaturesMojo.java
new file mode 100644
index 0000000..39640a1
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/ValidationFeaturesMojo.java
@@ -0,0 +1,143 @@
+/*
+ * 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.feature.maven.mojos;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+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.apache.maven.shared.utils.io.DirectoryScanner;
+import org.apache.maven.shared.utils.logging.MessageUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.fge.jsonschema.core.exceptions.ProcessingException;
+import com.github.fge.jsonschema.core.report.ProcessingMessage;
+import com.github.fge.jsonschema.core.report.ProcessingReport;
+import com.github.fge.jsonschema.main.JsonSchema;
+import com.github.fge.jsonschema.main.JsonSchemaFactory;
+
+@Mojo(
+ name = "features-schema-validation",
+ defaultPhase = LifecyclePhase.VALIDATE,
+ requiresDependencyResolution = ResolutionScope.TEST,
+ threadSafe = true
+)
+public final class ValidationFeaturesMojo extends AbstractMojo {
+
+ @Parameter(defaultValue = "https://raw.githubusercontent.com/apache/sling-org-apache-sling-feature/master/schema/Feature-1.0.0.schema.json")
+ private String jsonSchemaUri;
+
+ @Parameter(defaultValue = "${basedir}/src/main/features")
+ private File featuresDirectory;
+
+ @Parameter(defaultValue = "**/*.json")
+ private String[] includes;
+
+ @Parameter(defaultValue = "")
+ private String excludes;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ JsonSchemaFactory schemaFactory = JsonSchemaFactory.byDefault();
+
+ JsonSchema schema = null;
+
+ getLog().debug(MessageUtils.buffer().a("Retrieving the JSON Schema from ").strong(jsonSchemaUri).a("...").toString());
+
+ try {
+ schema = schemaFactory.getJsonSchema(jsonSchemaUri);
+ getLog().debug(MessageUtils.buffer().a("JSON Schema ").strong(jsonSchemaUri).a(" successfully retrieved").toString());
+ } catch (ProcessingException e) {
+ throw new MojoExecutionException("An error occured when retrieving the JSON Schema from " + jsonSchemaUri, e);
+ }
+
+ getLog().debug(MessageUtils.buffer().a("Retrieving the JSON Feature files scanning ").strong(featuresDirectory).a(" directory...").toString());
+
+ DirectoryScanner directoryScanner = new DirectoryScanner();
+ directoryScanner.setBasedir(featuresDirectory);
+ directoryScanner.setIncludes(includes);
+ if (excludes != null && excludes.length() > 0) {
+ directoryScanner.setExcludes(excludes);
+ }
+ directoryScanner.scan();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ boolean failed = false;
+
+ for (String featureFileName : directoryScanner.getIncludedFiles()) {
+ File featureFile = new File(featuresDirectory, featureFileName);
+ JsonNode instance = null;
+
+ getLog().debug(MessageUtils.buffer().a("Reading the Feature file ").strong(featureFile).a("...").toString());
+
+ try {
+ instance = mapper.readTree(featureFile);
+ getLog().debug(MessageUtils.buffer().a("Feature file ").strong(featureFile).a(" successfully read").toString());
+ } catch (IOException e) {
+ throw new MojoExecutionException("An error occurred while reading " + featureFile + " Feature file:", e);
+ }
+
+ getLog().debug(MessageUtils.buffer().a("Validating the Feature file ").strong(featureFile).a("...").toString());
+
+ try {
+ ProcessingReport report = schema.validate(instance, true);
+
+ if (report.isSuccess()) {
+ getLog().info(MessageUtils.buffer().a("Feature file ").mojo(featureFile).a(" validation passed").toString());
+ } else {
+ failed = true;
+
+ getLog().error(MessageUtils.buffer().a("Feature file ").error(featureFile).a(" validation detected one or more errors:").toString());
+
+ for (ProcessingMessage message : report) {
+ String errorMessage = String.format(" * %s: %s",
+ message.asJson().get("schema").get("pointer").asText(),
+ message.getMessage() );
+
+ switch (message.getLogLevel()) {
+ case ERROR:
+ case FATAL:
+ getLog().error(errorMessage);
+ break;
+
+ default:
+ getLog().debug(errorMessage);
+ break;
+ }
+ }
+ }
+ } catch (ProcessingException e) {
+ getLog().error(MessageUtils.buffer().a("An error occurred while validating Feature ").error(featureFile).a(", read the log for details:").toString(), e);
+ }
+ }
+
+ if (failed) {
+ throw new MojoFailureException("One or more features Feature file validation detected one or more error(s), please read the plugin log for more datils");
+ } else {
+ getLog().info("All processed Feature files are valid");
+ }
+ }
+
+}