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");
+        }
+    }
+
+}