You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2017/05/29 13:50:16 UTC

svn commit: r1796629 - in /sling/whiteboard/cziegeler/provisioning-model/src: main/java/org/apache/sling/feature/json/ test/resources/features/

Author: cziegeler
Date: Mon May 29 13:50:16 2017
New Revision: 1796629

URL: http://svn.apache.org/viewvc?rev=1796629&view=rev
Log:
Add full feature test file

Added:
    sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java   (with props)
Modified:
    sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
    sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
    sling/whiteboard/cziegeler/provisioning-model/src/test/resources/features/test.json

Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java?rev=1796629&r1=1796628&r2=1796629&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java Mon May 29 13:50:16 2017
@@ -23,18 +23,13 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonNumber;
 import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonValue;
 
 import org.apache.felix.configurator.impl.TypeConverter;
 import org.apache.felix.configurator.impl.json.JSMin;
@@ -42,8 +37,11 @@ import org.apache.felix.configurator.imp
 import org.apache.felix.configurator.impl.model.Config;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Capability;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.Include;
+import org.apache.sling.feature.Requirement;
 
 /**
  * This class offers a method to read a model using a {@code Reader} instance.
@@ -74,19 +72,6 @@ public class FeatureJSONReader {
         return mr.readFeature(new StringReader(contents));
     }
 
-    private static final String FEATURE_ID = "id";
-
-    private static final String FEATURE_BUNDLES = "bundles";
-
-    private static final String FEATURE_FRAMEWORK_PROPERTIES = "framework-properties";
-
-    private static final String FEATURE_CONFIGURATIONS = "configurations";
-
-    private static final String FEATURE_INCLUDES = "includes";
-
-    private static final String FEATURE_REQUIREMENTS = "requirements";
-
-    private static final String FEATURE_CAPABILITIES = "capabilities";
 
     private Feature feature;
 
@@ -118,21 +103,15 @@ public class FeatureJSONReader {
         final JsonObject json = Json.createReader(reader).readObject();
 
         @SuppressWarnings("unchecked")
-        final Map<String, Object> map = (Map<String, Object>) getValue(json);
+        final Map<String, Object> map = (Map<String, Object>) JSONUtil.getValue(json);
 
         final Set<String> keySet = new HashSet<>(map.keySet());
-        keySet.removeAll(Arrays.asList(FEATURE_ID,
-                FEATURE_BUNDLES,
-                FEATURE_FRAMEWORK_PROPERTIES,
-                FEATURE_CONFIGURATIONS,
-                FEATURE_INCLUDES,
-                FEATURE_REQUIREMENTS,
-                FEATURE_CAPABILITIES));
-        if ( !map.containsKey(FEATURE_ID) ) {
-            throw new IOException("Feature id is missing in " + this.location);
+        keySet.removeAll(JSONConstants.FEATURE_KNOWN_PROPERTIES);
+        if ( !map.containsKey(JSONConstants.FEATURE_ID) ) {
+            throw new IOException(this.exceptionPrefix + "Feature id is missing");
         }
-        final Object idObj = map.get(FEATURE_ID);
-        checkType(FEATURE_ID, idObj, String.class);
+        final Object idObj = map.get(JSONConstants.FEATURE_ID);
+        checkType(JSONConstants.FEATURE_ID, idObj, String.class);
 
         this.feature = new Feature(ArtifactId.fromMvnId(idObj.toString()));
         this.feature.setLocation(this.location);
@@ -141,20 +120,138 @@ public class FeatureJSONReader {
         this.readFrameworkProperties(map);
         this.readConfigurations(map);
 
-        // TODO - capabilities, requirements, extensions, includes
+        this.readCapabilities(map);
+        this.readRequirements(map);
+        this.readIncludes(map);
+
+        // TODO - extensions
 
+        // TODO - check duplicates (e.g. bundles, includes...)
         return feature;
     }
 
+    private void readIncludes(Map<String, Object> map) throws IOException {
+        if ( map.containsKey(JSONConstants.FEATURE_INCLUDES)) {
+            final Object includesObj = map.get(JSONConstants.FEATURE_INCLUDES);
+            checkType(JSONConstants.FEATURE_INCLUDES, includesObj, List.class);
+
+            @SuppressWarnings("unchecked")
+            final List<Object> includes = (List<Object>)includesObj;
+            for(final Object inc : includes) {
+                checkType("Include", inc, Map.class, String.class);
+                if ( inc instanceof String ) {
+                    final ArtifactId id = ArtifactId.fromMvnId(inc.toString());
+                    this.feature.getIncludes().add(new Include(id));
+                } else {
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> obj = (Map<String, Object>) inc;
+                    if ( !obj.containsKey(JSONConstants.ARTIFACT_ID) ) {
+                        throw new IOException(exceptionPrefix + " include is missing required artifact id");
+                    }
+                    checkType("Include " + JSONConstants.ARTIFACT_ID, obj.get(JSONConstants.ARTIFACT_ID), String.class);
+                    final ArtifactId id = ArtifactId.fromMvnId(obj.get(JSONConstants.ARTIFACT_ID).toString());
+                    final Include include = new Include(id);
+                    feature.getIncludes().add(include);
+
+                    if ( obj.containsKey(JSONConstants.INCLUDE_REMOVALS) ) {
+                        // TODO - removals
+                    }
+                }
+            }
+        }
+    }
+
+    private void readRequirements(Map<String, Object> map) throws IOException {
+        if ( map.containsKey(JSONConstants.FEATURE_REQUIREMENTS)) {
+            final Object reqObj = map.get(JSONConstants.FEATURE_REQUIREMENTS);
+            checkType(JSONConstants.FEATURE_REQUIREMENTS, reqObj, List.class);
+
+            @SuppressWarnings("unchecked")
+            final List<Object> requirements = (List<Object>)reqObj;
+            for(final Object req : requirements) {
+                checkType("Requirement", req, Map.class);
+                @SuppressWarnings("unchecked")
+                final Map<String, Object> obj = (Map<String, Object>) req;
+
+                if ( !obj.containsKey(JSONConstants.REQCAP_NAMESPACE) ) {
+                    throw new IOException(this.exceptionPrefix + "Namespace is missing for requirement");
+                }
+                checkType("Requirement namespace", obj.get(JSONConstants.REQCAP_NAMESPACE), String.class);
+
+                final Requirement r = new Requirement(obj.get(JSONConstants.REQCAP_NAMESPACE).toString());
+                feature.getRequirements().add(r);
+
+                if ( obj.containsKey(JSONConstants.REQCAP_ATTRIBUTES) ) {
+                    checkType("Requirement attributes", obj.get(JSONConstants.REQCAP_ATTRIBUTES), Map.class);
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> attrs = (Map<String, Object>)obj.get(JSONConstants.REQCAP_ATTRIBUTES);
+                    for(final Map.Entry<String, Object> entry : attrs.entrySet()) {
+                        r.getAttributes().put(entry.getKey(), entry.getValue().toString());
+                    }
+                }
+
+                if ( obj.containsKey(JSONConstants.REQCAP_DIRECTIVES) ) {
+                    checkType("Requirement directives", obj.get(JSONConstants.REQCAP_DIRECTIVES), Map.class);
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> dirs = (Map<String, Object>)obj.get(JSONConstants.REQCAP_DIRECTIVES);
+                    for(final Map.Entry<String, Object> entry : dirs.entrySet()) {
+                        r.getDirectives().put(entry.getKey(), entry.getValue().toString());
+                    }
+                }
+            }
+        }
+    }
+
+    private void readCapabilities(Map<String, Object> map) throws IOException {
+        if ( map.containsKey(JSONConstants.FEATURE_CAPABILITIES)) {
+            final Object capObj = map.get(JSONConstants.FEATURE_CAPABILITIES);
+            checkType(JSONConstants.FEATURE_CAPABILITIES, capObj, List.class);
+
+            @SuppressWarnings("unchecked")
+            final List<Object> capabilities = (List<Object>)capObj;
+            for(final Object cap : capabilities) {
+                checkType("Capability", cap, Map.class);
+                @SuppressWarnings("unchecked")
+                final Map<String, Object> obj = (Map<String, Object>) cap;
+
+                if ( !obj.containsKey(JSONConstants.REQCAP_NAMESPACE) ) {
+                    throw new IOException(this.exceptionPrefix + "Namespace is missing for capability");
+                }
+                checkType("Capability namespace", obj.get(JSONConstants.REQCAP_NAMESPACE), String.class);
+
+                final Capability c = new Capability(obj.get(JSONConstants.REQCAP_NAMESPACE).toString());
+                feature.getCapabilities().add(c);
+
+                if ( obj.containsKey(JSONConstants.REQCAP_ATTRIBUTES) ) {
+                    checkType("Capability attributes", obj.get(JSONConstants.REQCAP_ATTRIBUTES), Map.class);
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> attrs = (Map<String, Object>)obj.get(JSONConstants.REQCAP_ATTRIBUTES);
+                    for(final Map.Entry<String, Object> entry : attrs.entrySet()) {
+                        c.getAttributes().put(entry.getKey(), entry.getValue().toString());
+                    }
+                }
+
+                if ( obj.containsKey(JSONConstants.REQCAP_DIRECTIVES) ) {
+                    checkType("Capability directives", obj.get(JSONConstants.REQCAP_DIRECTIVES), Map.class);
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> dirs = (Map<String, Object>)obj.get(JSONConstants.REQCAP_DIRECTIVES);
+                    for(final Map.Entry<String, Object> entry : dirs.entrySet()) {
+                        c.getDirectives().put(entry.getKey(), entry.getValue().toString());
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Read the bundles / start levels section
      * @param map The map describing the feature
      * @throws IOException If the json is invalid.
      */
     private void readBundles(final Map<String, Object> map) throws IOException {
-        if ( map.containsKey(FEATURE_BUNDLES)) {
-            final Object bundlesObj = map.get(FEATURE_BUNDLES);
-            checkType(FEATURE_BUNDLES, bundlesObj, Map.class);
+        if ( map.containsKey(JSONConstants.FEATURE_BUNDLES)) {
+            final Object bundlesObj = map.get(JSONConstants.FEATURE_BUNDLES);
+            checkType(JSONConstants.FEATURE_BUNDLES, bundlesObj, Map.class);
             @SuppressWarnings("unchecked")
             final Map<String, Object> bundles = (Map<String, Object>) bundlesObj;
             for(final String startLevelVal : bundles.keySet()) {
@@ -190,60 +287,40 @@ public class FeatureJSONReader {
             } else {
                 @SuppressWarnings("unchecked")
                 final Map<String, Object> bundleObj = (Map<String, Object>) entry;
-                final ArtifactId id;
-                if ( bundleObj.containsKey("id") ) {
-                    checkType(artifactType + " id", bundleObj.get("id"), String.class);
-                    if ( bundleObj.containsKey("artifactId")
-                         || bundleObj.containsKey("groupId")
-                         || bundleObj.containsKey("version")
-                         || bundleObj.containsKey("classifier")
-                         || bundleObj.containsKey("type") ) {
-                        throw new IOException(exceptionPrefix + " " + artifactType + " id must not be specified together with one of groupId/artifactId/version/classifier/type");
-                    }
-                    id = ArtifactId.fromMvnId(bundleObj.get("id").toString());
-                } else {
-                    if ( !bundleObj.containsKey("artifactId")
-                         || !bundleObj.containsKey("groupId")
-                         || !bundleObj.containsKey("version") ) {
-                        throw new IOException(exceptionPrefix + " " + artifactType + " is missing either id or groupId/artifactId/version");
-                    }
-                    checkType(artifactType + " group id", bundleObj.get("groupId"), String.class);
-                    checkType(artifactType + " artifact id", bundleObj.get("artifactId"), String.class);
-                    checkType(artifactType + " version", bundleObj.get("version"), String.class);
-
-                    if ( bundleObj.containsKey("classifier") ) {
-                        checkType(artifactType + " classifier", bundleObj.get("classifier"), String.class);
-                    }
-                    if ( bundleObj.containsKey("type") ) {
-                        checkType(artifactType + " type", bundleObj.get("type"), String.class);
-                    }
-                    id = new ArtifactId(bundleObj.get("groupId").toString(),
-                            bundleObj.get("artifactId").toString(),
-                            bundleObj.get("version").toString(),
-                            bundleObj.get("classifier").toString(),
-                            bundleObj.get("type").toString());
+                if ( !bundleObj.containsKey(JSONConstants.ARTIFACT_ID) ) {
+                    throw new IOException(exceptionPrefix + " " + artifactType + " is missing required artifact id");
                 }
+                checkType(artifactType + " " + JSONConstants.ARTIFACT_ID, bundleObj.get(JSONConstants.ARTIFACT_ID), String.class);
+                final ArtifactId id = ArtifactId.fromMvnId(bundleObj.get(JSONConstants.ARTIFACT_ID).toString());
 
                 artifact = new Artifact(id);
                 for(final Map.Entry<String, Object> metadataEntry : bundleObj.entrySet()) {
                     final String key = metadataEntry.getKey();
-                    if ( key.equals("id")
-                         || key.equals("groupId")
-                         || key.equals("artifactId")
-                         || key.equals("version")
-                         || key.equals("classifier")
-                         || key.equals("type")
-                         || key.equals("configurations")) {
-
+                    if ( JSONConstants.ARTIFACT_KNOWN_PROPERTIES.contains(key) ) {
                         continue;
                     }
                     checkType(artifactType + " metadata " + key, metadataEntry.getValue(), String.class, Number.class, Boolean.class);
                     artifact.getMetadata().put(key, metadataEntry.getValue().toString());
                 }
-                if ( bundleObj.containsKey(FEATURE_CONFIGURATIONS) ) {
-
+                if ( bundleObj.containsKey(JSONConstants.FEATURE_CONFIGURATIONS) ) {
+                    checkType(artifactType + " configurations", bundleObj.get(JSONConstants.FEATURE_CONFIGURATIONS), Map.class);
+                    final JSONUtil.Report report = new JSONUtil.Report();
+                    @SuppressWarnings("unchecked")
                     final List<Config> configs = JSONUtil.readConfigurationsJSON(new TypeConverter(null),
-                        0, "", bundleObj);
+                        0, "", (Map<String, ?>)bundleObj.get(JSONConstants.FEATURE_CONFIGURATIONS), report);
+                    if ( !report.errors.isEmpty() || !report.warnings.isEmpty() ) {
+                        final StringBuilder builder = new StringBuilder(this.exceptionPrefix);
+                        builder.append("Errors in configurations:");
+                        for(final String w : report.warnings) {
+                            builder.append("\n");
+                            builder.append(w);
+                        }
+                        for(final String e : report.errors) {
+                            builder.append("\n");
+                            builder.append(e);
+                        }
+                        throw new IOException(builder.toString());
+                    }
                     for(final Config c : configs) {
                         if ( c.getEnvironments() != null ) {
                             throw new IOException(this.exceptionPrefix + "Environments for configurations are not supported");
@@ -265,11 +342,25 @@ public class FeatureJSONReader {
     }
 
     private void readConfigurations(final Map<String, Object> map) throws IOException {
-        if ( map.containsKey(FEATURE_CONFIGURATIONS) ) {
-            // TODO JSONUtil prints out warnings and errors through SystemLogger - we need to catch them
-            //      and throw an IOException
+        if ( map.containsKey(JSONConstants.FEATURE_CONFIGURATIONS) ) {
+            checkType(JSONConstants.FEATURE_CONFIGURATIONS, map.get(JSONConstants.FEATURE_CONFIGURATIONS), Map.class);
+            final JSONUtil.Report report = new JSONUtil.Report();
+            @SuppressWarnings("unchecked")
             final List<Config> configs = JSONUtil.readConfigurationsJSON(new TypeConverter(null),
-                    0, "", map);
+                    0, "", (Map<String, ?>)map.get(JSONConstants.FEATURE_CONFIGURATIONS), report);
+            if ( !report.errors.isEmpty() || !report.warnings.isEmpty() ) {
+                final StringBuilder builder = new StringBuilder(this.exceptionPrefix);
+                builder.append("Errors in configurations:");
+                for(final String w : report.warnings) {
+                    builder.append("\n");
+                    builder.append(w);
+                }
+                for(final String e : report.errors) {
+                    builder.append("\n");
+                    builder.append(e);
+                }
+                throw new IOException(builder.toString());
+            }
             for(final Config c : configs) {
                 if ( c.getEnvironments() != null ) {
                     throw new IOException(this.exceptionPrefix + "Environments for configurations are not supported");
@@ -290,9 +381,9 @@ public class FeatureJSONReader {
     }
 
     private void readFrameworkProperties(final Map<String, Object> map) throws IOException {
-        if ( map.containsKey(FEATURE_FRAMEWORK_PROPERTIES) ) {
-            final Object propsObj= map.get(FEATURE_FRAMEWORK_PROPERTIES);
-            checkType(FEATURE_FRAMEWORK_PROPERTIES, propsObj, Map.class);
+        if ( map.containsKey(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES) ) {
+            final Object propsObj= map.get(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES);
+            checkType(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, propsObj, Map.class);
 
             @SuppressWarnings("unchecked")
             final Map<String, Object> props = (Map<String, Object>) propsObj;
@@ -326,43 +417,6 @@ public class FeatureJSONReader {
             throw new IOException(this.exceptionPrefix + "Key " + key + " is not one of the allowed types " + Arrays.toString(types) + " : " + val.getClass());
         }
     }
-
-    /**
-     * Get a Java object for the JSON value.
-     * @param value The value
-     * @return The Java object.
-     */
-    private static Object getValue(final JsonValue value) {
-        switch ( value.getValueType() ) {
-            // type NULL -> return null
-            case NULL : return null;
-            // type TRUE or FALSE -> return boolean
-            case FALSE : return false;
-            case TRUE : return true;
-            // type String -> return String
-            case STRING : return ((JsonString)value).getString();
-            // type Number -> return long or double
-            case NUMBER : final JsonNumber num = (JsonNumber)value;
-                          if (num.isIntegral()) {
-                               return num.longValue();
-                          }
-                          return num.doubleValue();
-            // type ARRAY -> return list and call this method for each value
-            case ARRAY : final List<Object> array = new ArrayList<>();
-                         for(final JsonValue x : ((JsonArray)value)) {
-                             array.add(getValue(x));
-                         }
-                         return array;
-            // type OBJECT -> return map
-            case OBJECT : final Map<String, Object> map = new HashMap<>();
-                          final JsonObject obj = (JsonObject)value;
-                          for(final Map.Entry<String, JsonValue> entry : obj.entrySet()) {
-                              map.put(entry.getKey(), getValue(entry.getValue()));
-                          }
-                          return map;
-        }
-        return null;
-    }
 }
 
 

Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java?rev=1796629&r1=1796628&r2=1796629&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java Mon May 29 13:50:16 2017
@@ -48,10 +48,10 @@ public class FeatureJSONWriter {
         final JsonGenerator w = Json.createGenerator(writer);
         w.writeStartObject();
 
-        w.write("id", feature.getId().toMvnId());
+        w.write(JSONConstants.FEATURE_ID, feature.getId().toMvnId());
 
         if ( !feature.getBundles().getBundlesByStartLevel().isEmpty() ) {
-            w.write("bundles");
+            w.write(JSONConstants.FEATURE_BUNDLES);
             w.writeStartObject();
             for(final Map.Entry<Integer, List<Artifact>> entry : feature.getBundles().getBundlesByStartLevel().entrySet()) {
                 w.write(String.valueOf(entry.getKey()));
@@ -69,7 +69,7 @@ public class FeatureJSONWriter {
                         w.write(artifact.getId().toMvnId());
                     } else {
                         w.writeStartObject();
-                        w.write("id", artifact.getId().toMvnId());
+                        w.write(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
 
                         for(final Map.Entry<String, String> me : artifact.getMetadata()) {
                             w.write(me.getKey(), me.getValue());
@@ -85,6 +85,7 @@ public class FeatureJSONWriter {
             w.writeEnd();
         }
 
+        // configurations
         final List<Configuration> cfgs = new ArrayList<>();
         for(final Configuration cfg : feature.getConfigurations()) {
             final String artifactProp = (String)cfg.getProperties().get(Configuration.PROP_ARTIFACT);
@@ -94,13 +95,30 @@ public class FeatureJSONWriter {
         }
         writeConfigurations(w, cfgs);
 
+        // framework properties
+        if ( !feature.getFrameworkProperties().isEmpty() ) {
+            w.write(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES);
+            w.writeStartObject();
+
+            for(final Map.Entry<String, String> entry : feature.getFrameworkProperties()) {
+                w.write(entry.getKey(), entry.getValue());
+            }
+            w.writeEnd();
+        }
+
+        // TODO includes, requirements, capabilities, extensions
         w.writeEnd();
         w.flush();
     }
 
+    /**
+     * Write the list of configurations into a "configurations" element
+     * @param w The json generator
+     * @param cfgs The list of configurations
+     */
     private static void writeConfigurations(final JsonGenerator w, final List<Configuration> cfgs) {
         if ( !cfgs.isEmpty() ) {
-            w.write("configurations");
+            w.write(JSONConstants.FEATURE_CONFIGURATIONS);
             w.writeStartObject();
             for(final Configuration cfg : cfgs) {
                 final String key;

Added: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java?rev=1796629&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java (added)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java Mon May 29 13:50:16 2017
@@ -0,0 +1,60 @@
+/*
+ * 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.json;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.sling.feature.Configuration;
+
+public abstract class JSONConstants {
+
+    public static final String FEATURE_ID = "id";
+
+    public static final String FEATURE_BUNDLES = "bundles";
+
+    public static final String FEATURE_FRAMEWORK_PROPERTIES = "framework-properties";
+
+    public static final String FEATURE_CONFIGURATIONS = "configurations";
+
+    public static final String FEATURE_INCLUDES = "includes";
+
+    public static final String FEATURE_REQUIREMENTS = "requirements";
+
+    public static final String FEATURE_CAPABILITIES = "capabilities";
+
+    public static final List<String> FEATURE_KNOWN_PROPERTIES = Arrays.asList(FEATURE_ID,
+            FEATURE_BUNDLES,
+            FEATURE_FRAMEWORK_PROPERTIES,
+            FEATURE_CONFIGURATIONS,
+            FEATURE_INCLUDES,
+            FEATURE_REQUIREMENTS,
+            FEATURE_CAPABILITIES);
+
+    public static final String ARTIFACT_ID = "id";
+
+    public static final List<String> ARTIFACT_KNOWN_PROPERTIES = Arrays.asList(ARTIFACT_ID,
+            Configuration.PROP_ARTIFACT,
+            FEATURE_CONFIGURATIONS);
+
+    public static final String INCLUDE_REMOVALS = "removals";
+
+    public static final String REQCAP_NAMESPACE = "namespace";
+    public static final String REQCAP_ATTRIBUTES = "attributes";
+    public static final String REQCAP_DIRECTIVES = "directives";
+
+}

Propchange: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/json/JSONConstants.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: sling/whiteboard/cziegeler/provisioning-model/src/test/resources/features/test.json
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/test/resources/features/test.json?rev=1796629&r1=1796628&r2=1796629&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/test/resources/features/test.json (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/test/resources/features/test.json Mon May 29 13:50:16 2017
@@ -1,3 +1,74 @@
 {
-    "id" : "org.apache.sling/test-feature/1.1"
+    "id" : "org.apache.sling/test-feature/1.1",
+
+    "includes" : [
+         {
+             "id" : "org.apache.sling/sling/9",
+             "removals" : {
+                 "configurations" : [
+                 ],
+                 "bundles" : [
+                 ],
+                 "framework-properties" : [
+                 ]
+             }
+         }
+    ],
+    "requirements" : [
+          {
+              "namespace" : "osgi.contract",
+              "directives" : {
+                  "filter" : "(&(osgi.contract=JavaServlet)(version=3.1))"
+              }
+          }
+    ],
+    "capabilities" : [
+        {
+             "namespace" : "osgi.implementation",
+             "attributes" : {
+                   "osgi.implementation" : "osgi.http",
+                   "version:Version" : "1.1"
+             },
+             "directives" : {
+                  "uses" : "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
+             }
+        },
+        {
+             "namespace" : "osgi.service",
+             "attributes" : {
+                  "objectClass:List<String>" : "org.osgi.service.http.runtime.HttpServiceRuntime"
+             },
+             "directives" : {
+                  "uses" : "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
+             }
+        }
+    ],
+    "framework-properties" : {
+        "foo" : 1,
+        "brave" : "something",
+        "org.apache.felix.scr.directory" : "launchpad/scr"
+    },
+    "bundles" : {
+      "1" : [
+            {
+              "id" : "org.apache.sling/oak-server/1.0.0",
+              "hash" : "4632463464363646436"
+            },
+            "org.apache.sling/application-bundle/2.0.0",
+            "org.apache.sling/another-bundle/2.1.0"
+          ],
+      "2" : [
+            "org.apache.sling/foo-xyz/1.2.3"
+          ]
+    },
+    "configurations" : {
+        "my.pid" : {
+           "foo" : 5,
+           "bar" : "test",
+           "number:Integer" : 7
+        },
+        "my.factory.pid~name" : {
+           "a.value" : "yeah"
+        }
+    }
 }
\ No newline at end of file