You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by da...@apache.org on 2018/04/27 10:01:29 UTC

[sling-org-apache-sling-feature-modelconverter] 11/40: Support variables in converting from features to provisioning model

This is an automated email from the ASF dual-hosted git repository.

davidb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-modelconverter.git

commit dac2347464ec6c47ed58b944a3dffb8697fa5764
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Tue Mar 20 10:46:52 2018 +0000

    Support variables in converting from features to provisioning model
---
 pom.xml                                            |  18 +++-
 .../modelconverter/impl/FeatureToProvisioning.java |  24 +++--
 .../modelconverter/impl/ModelConverterTest.java    |  74 +++++++++++++--
 src/test/resources/boot.json                       |  92 +++++++++++++++----
 src/test/resources/boot.txt                        |  70 +++++++++-----
 src/test/resources/oak.json                        | 101 +++++++++++++++++++++
 src/test/resources/oak.txt                         |  91 +++++++++++++++++++
 7 files changed, 411 insertions(+), 59 deletions(-)

diff --git a/pom.xml b/pom.xml
index 8d19064..c77652f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,12 @@
              <version>1.3.1</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>5.6.10</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature</artifactId>
             <version>0.0.1-SNAPSHOT</version>
@@ -156,9 +162,15 @@
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.framework</artifactId>
-            <version>5.6.10</version>
-            <!--  <scope>test</scope>  -->
+            <artifactId>org.apache.felix.converter</artifactId>
+            <version>0.1.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configurator</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java b/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java
index 2325549..ed0bd38 100644
--- a/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java
+++ b/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java
@@ -27,6 +27,7 @@ import org.apache.sling.feature.process.FeatureResolver;
 import org.apache.sling.feature.support.ArtifactManager;
 import org.apache.sling.feature.support.FeatureUtil;
 import org.apache.sling.feature.support.json.ApplicationJSONReader;
+import org.apache.sling.feature.support.json.FeatureJSONReader.SubstituteVariables;
 import org.apache.sling.provisioning.model.Artifact;
 import org.apache.sling.provisioning.model.Configuration;
 import org.apache.sling.provisioning.model.Feature;
@@ -52,15 +53,18 @@ public class FeatureToProvisioning {
     private static final String PROVISIONING_MODEL_NAME_VARIABLE = "provisioning.model.name";
 
     public static void convert(File file, String output, ArtifactManager am) throws IOException {
-        org.apache.sling.feature.Feature feature = FeatureUtil.getFeature(file.getAbsolutePath(), am);
+        org.apache.sling.feature.Feature feature = FeatureUtil.getFeature(file.getAbsolutePath(), am, SubstituteVariables.NONE);
 
-        String featureName = feature.getVariables().get(PROVISIONING_MODEL_NAME_VARIABLE);
-        if (featureName == null) {
+        Object featureNameVar = feature.getVariables().remove(PROVISIONING_MODEL_NAME_VARIABLE);
+        String featureName;
+        if (featureNameVar instanceof String) {
+            featureName = (String) featureNameVar;
+        } else {
             featureName = feature.getId().getArtifactId();
         }
 
         Feature newFeature = new Feature(featureName);
-        convert(newFeature, feature.getBundles(), feature.getConfigurations(), feature.getFrameworkProperties(), feature.getExtensions(), output);
+        convert(newFeature, feature.getVariables(), feature.getBundles(), feature.getConfigurations(), feature.getFrameworkProperties(), feature.getExtensions(), output);
     }
 
     public static void convert(List<File> files, String output, boolean createApp, ArtifactManager am) throws Exception {
@@ -95,11 +99,16 @@ public class FeatureToProvisioning {
         }
         final Feature feature = new Feature(featureName);
 
-        convert(feature, app.getBundles(), app.getConfigurations(), app.getFrameworkProperties(), app.getExtensions(), outputFile);
+        convert(feature, app.getVariables(), app.getBundles(), app.getConfigurations(), app.getFrameworkProperties(), app.getExtensions(), outputFile);
     }
 
-    private static void convert(Feature f, Bundles bundles, Configurations configurations, KeyValueMap frameworkProps,
+    private static void convert(Feature f, KeyValueMap variables, Bundles bundles, Configurations configurations, KeyValueMap frameworkProps,
             Extensions extensions, String outputFile) {
+        org.apache.sling.provisioning.model.KeyValueMap<String> vars = f.getVariables();
+        for (Map.Entry<String, String> entry : variables) {
+            vars.put(entry.getKey(), entry.getValue());
+        }
+
         Map<org.apache.sling.feature.Configuration, org.apache.sling.feature.Artifact> configBundleMap = new HashMap<>();
 
         // bundles
@@ -153,6 +162,9 @@ public class FeatureToProvisioning {
                 c.getProperties().put(key, cfg.getProperties().get(key));
             }
 
+            // Remove these if they got in
+            c.getProperties().remove(org.apache.sling.feature.Configuration.PROP_ARTIFACT);
+
             // Check if the configuration has an associated runmode via the bundle that it belongs to
             org.apache.sling.feature.Artifact bundle = configBundleMap.get(cfg);
             String[] runModes;
diff --git a/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java b/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java
index bba43c5..46dc48b 100644
--- a/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java
+++ b/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java
@@ -24,6 +24,7 @@ import org.apache.sling.provisioning.model.Configuration;
 import org.apache.sling.provisioning.model.Feature;
 import org.apache.sling.provisioning.model.KeyValueMap;
 import org.apache.sling.provisioning.model.Model;
+import org.apache.sling.provisioning.model.ModelConstants;
 import org.apache.sling.provisioning.model.RunMode;
 import org.apache.sling.provisioning.model.Section;
 import org.junit.After;
@@ -31,17 +32,23 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 public class ModelConverterTest {
@@ -66,13 +73,22 @@ public class ModelConverterTest {
 
     @Test
     public void testBoot() throws Exception {
-        File inFile = new File(getClass().getResource("/boot.json").toURI());
-        File outFile = new File(tempDir.toFile(), "/boot.generated.txt");
+        testConvertToProvisioningModel("/boot.json", "/boot.txt");
+    }
+
+    @Test
+    public void testOak() throws Exception {
+        testConvertToProvisioningModel("/oak.json", "/oak.txt");
+    }
+
+    private void testConvertToProvisioningModel(String originalJSON, String expectedProvModel) throws URISyntaxException, IOException {
+        File inFile = new File(getClass().getResource(originalJSON).toURI());
+        File outFile = new File(tempDir.toFile(), expectedProvModel + ".generated");
 
         FeatureToProvisioning.convert(inFile, outFile.getAbsolutePath(),
                 artifactManager);
 
-        File expectedFile = new File(getClass().getResource("/boot.txt").toURI());
+        File expectedFile = new File(getClass().getResource(expectedProvModel).toURI());
         Model expected = ProvisioningToFeature.readProvisioningModel(expectedFile);
         Model actual = ProvisioningToFeature.readProvisioningModel(outFile);
         assertModelsEqual(expected, actual);
@@ -117,6 +133,9 @@ public class ModelConverterTest {
             if (rm2.getNames() != null)
                 return false;
         } else {
+            if (rm2.getNames() == null)
+                return false;
+
             HashSet<String> names1 = new HashSet<>(Arrays.asList(rm1.getNames()));
             HashSet<String> names2 = new HashSet<>(Arrays.asList(rm2.getNames()));
 
@@ -150,9 +169,22 @@ public class ModelConverterTest {
 
         for (int i=0; i < configs1.size(); i++) {
             Configuration cfg1 = configs1.get(i);
-            Configuration cfg2 = configs2.get(i);
-            if (!cfg1.getProperties().equals(cfg2.getProperties()))
-                return false;
+
+            boolean found = false;
+            for (Configuration cfg2 : configs2) {
+                if (!cfg2.getPid().equals(cfg1.getPid())) {
+                    continue;
+                }
+                found = true;
+
+                Map<String, Object> m1 = cfgMap(cfg1.getProperties());
+                Map<String, Object> m2 = cfgMap(cfg2.getProperties());
+                if (!m1.equals(m2)) {
+                    return false;
+                }
+                break;
+            }
+            assertTrue("Configuration with PID " + cfg1.getPid() + " not found", found);
         }
 
         Map<String, String> m1 = kvToMap(rm1.getSettings());
@@ -161,6 +193,31 @@ public class ModelConverterTest {
         return m1.equals(m2);
     }
 
+    private Map<String, Object> cfgMap(Dictionary<String, Object> properties) {
+        Map<String, Object> m = new HashMap<>();
+        for (Enumeration<String> e = properties.keys(); e.hasMoreElements(); ) {
+            String key = e.nextElement();
+            Object value = properties.get(key);
+            if (ModelConstants.CFG_UNPROCESSED.equals(key) && value instanceof String) {
+                String val = (String) value;
+                // Collapse line continuation characters
+                val = val.replaceAll("[\\\\]\\r?\\n", "");
+                for (String line : val.split("\\r?\\n")) {
+
+                    String[] kv = line.trim().split("=");
+                    if (kv.length >= 2) {
+                        String v = kv[1].trim().replaceAll("[" +Pattern.quote("[") + "]\\s+[\"]", "[\"");
+                        v = v.replaceAll("[\"][,]\\s*[]]","\"]");
+                        m.put(kv[0].trim(), v.trim());
+                    }
+                }
+            } else {
+                m.put(key, value);
+            }
+        }
+        return m;
+    }
+
     private Map<String, String> kvToMap(KeyValueMap<String> kvm) {
         Map<String, String> m = new HashMap<>();
 
@@ -191,10 +248,7 @@ public class ModelConverterTest {
     }
 
     private void assertKVMapEquals(KeyValueMap<String> expected, KeyValueMap<String> actual) {
-        assertEquals(expected.size(), actual.size());
-        for (Map.Entry<String, String> entry : expected) {
-            assertEquals(entry.getValue(), actual.get(entry.getKey()));
-        }
+        assertEquals(kvToMap(expected), kvToMap(actual));
     }
 
     private void assertSectionsEqual(List<Section> expected, List<Section> actual) {
diff --git a/src/test/resources/boot.json b/src/test/resources/boot.json
index 2a17a40..8d0634a 100644
--- a/src/test/resources/boot.json
+++ b/src/test/resources/boot.json
@@ -9,25 +9,79 @@
         "#": "The model name when transformed to the provisioning model",
         "provisioning.model.name": ":boot"
     },
-    "bundles": 
-        ["org.slf4j/slf4j-api/${slf4j.version}",
-        "org.apache.sling/org.apache.sling.commons.log/5.1.0",
-        "org.apache.sling/org.apache.sling.commons.logservice/1.0.6",
-        "org.slf4j/jcl-over-slf4j/${slf4j.version}",
-        "org.slf4j/log4j-over-slf4j/${slf4j.version}",
-        "org.apache.sling/org.apache.sling.settings/1.3.8",
-        "org.apache.sling/org.apache.sling.fragment.xml/1.0.2",
-        "org.apache.sling/org.apache.sling.fragment.transaction/1.0.0",
-        "org.apache.sling/org.apache.sling.javax.activation/0.1.0",
-        "org.apache.sling/org.apache.sling.fragment.ws/1.0.2",
-        "org.apache.sling/org.apache.sling.launchpad.installer/1.2.2",
-        "org.apache.sling/org.apache.sling.installer.core/3.8.12",
-        "org.apache.sling/org.apache.sling.installer.provider.file/1.1.0",
-        "org.apache.sling/org.apache.sling.installer.factory.configuration/1.1.2",
-        "org.apache.felix/org.apache.felix.configadmin/1.8.16",
-        "org.apache.felix/org.apache.felix.eventadmin/1.4.10",
-        "org.apache.aries/org.apache.aries.util/1.1.3",
-        "org.apache.geronimo.specs/geronimo-atinject_1.0_spec/1.0"],
+    "bundles": [
+        {
+            "id": "org.slf4j/slf4j-api/${slf4j.version}",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.commons.log/5.1.0",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.commons.logservice/1.0.6",
+            "start-level": 20
+        },
+        {
+            "id": "org.slf4j/jcl-over-slf4j/${slf4j.version}",
+            "start-level": 20
+        },
+        {
+            "id": "org.slf4j/log4j-over-slf4j/${slf4j.version}",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.settings/1.3.8",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.fragment.xml/1.0.2",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.fragment.transaction/1.0.0",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.javax.activation/0.1.0",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.fragment.ws/1.0.2",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.launchpad.installer/1.2.2",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.installer.core/3.8.12",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.installer.provider.file/1.1.0",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.installer.factory.configuration/1.1.2",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.felix/org.apache.felix.configadmin/1.8.16",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.felix/org.apache.felix.eventadmin/1.4.10",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.aries/org.apache.aries.util/1.1.3",
+            "start-level": 20
+        },
+        {
+            "id": "org.apache.geronimo.specs/geronimo-atinject_1.0_spec/1.0",
+            "start-level": 20
+        }],
         
     "framework-properties": {
         "# oak_tar and oak_mongo run modes are mutually exclusive":
diff --git a/src/test/resources/boot.txt b/src/test/resources/boot.txt
index b8d2e7f..7e22e39 100644
--- a/src/test/resources/boot.txt
+++ b/src/test/resources/boot.txt
@@ -1,26 +1,54 @@
+#
+#  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.
+#
+# The :boot feature contains all things to bootstrap the installation.
+#
 [feature name=:boot]
 
+# additional entries for sling.properties
+# ---------------------------------------
+# oak_tar and oak_mongo run modes are mutually exclusive,
+# and cannot be changed after the first startup
 [settings]
-  localIndexDir=${sling.home}/repository/index
-  repository.home=${sling.home}/repository
-  sling.run.mode.install.options=oak_tar,oak_mongo
+    sling.run.mode.install.options=oak_tar,oak_mongo
+    repository.home=${sling.home}/repository
+    localIndexDir=${sling.home}/repository/index
+
+[variables]
+    slf4j.version=1.7.25
 
 [artifacts startLevel=20]
-  org.apache.aries/org.apache.aries.util/1.1.3
-  org.apache.felix/org.apache.felix.configadmin/1.8.16
-  org.apache.felix/org.apache.felix.eventadmin/1.4.10
-  org.apache.geronimo.specs/geronimo-atinject_1.0_spec/1.0
-  org.apache.sling/org.apache.sling.commons.log/5.1.0
-  org.apache.sling/org.apache.sling.commons.logservice/1.0.6
-  org.apache.sling/org.apache.sling.fragment.transaction/1.0.0
-  org.apache.sling/org.apache.sling.fragment.ws/1.0.2
-  org.apache.sling/org.apache.sling.fragment.xml/1.0.2
-  org.apache.sling/org.apache.sling.installer.core/3.8.12
-  org.apache.sling/org.apache.sling.installer.factory.configuration/1.1.2
-  org.apache.sling/org.apache.sling.installer.provider.file/1.1.0
-  org.apache.sling/org.apache.sling.javax.activation/0.1.0
-  org.apache.sling/org.apache.sling.launchpad.installer/1.2.2
-  org.apache.sling/org.apache.sling.settings/1.3.8
-  org.slf4j/jcl-over-slf4j/1.7.25
-  org.slf4j/log4j-over-slf4j/1.7.25
-  org.slf4j/slf4j-api/1.7.25
+    org.slf4j/slf4j-api/${slf4j.version}
+    org.apache.sling/org.apache.sling.commons.log/5.1.0
+    org.apache.sling/org.apache.sling.commons.logservice/1.0.6
+    org.slf4j/jcl-over-slf4j/${slf4j.version}
+    org.slf4j/log4j-over-slf4j/${slf4j.version}
+    org.apache.sling/org.apache.sling.settings/1.3.8
+    org.apache.sling/org.apache.sling.fragment.xml/1.0.2
+    org.apache.sling/org.apache.sling.fragment.transaction/1.0.0
+    org.apache.sling/org.apache.sling.javax.activation/0.1.0
+    org.apache.sling/org.apache.sling.fragment.ws/1.0.2
+    org.apache.sling/org.apache.sling.launchpad.installer/1.2.2
+    org.apache.sling/org.apache.sling.installer.core/3.8.12
+    org.apache.sling/org.apache.sling.installer.provider.file/1.1.0
+    org.apache.sling/org.apache.sling.installer.factory.configuration/1.1.2
+    org.apache.felix/org.apache.felix.configadmin/1.8.16
+    org.apache.felix/org.apache.felix.eventadmin/1.4.10
+    org.apache.aries/org.apache.aries.util/1.1.3
+    # dependency with javax.inject - required for Sling Models (SLING-4710)
+    org.apache.geronimo.specs/geronimo-atinject_1.0_spec/1.0
diff --git a/src/test/resources/oak.json b/src/test/resources/oak.json
new file mode 100644
index 0000000..ab50c29
--- /dev/null
+++ b/src/test/resources/oak.json
@@ -0,0 +1,101 @@
+{
+    "id": "org.apache.sling.simple/oak/1.0.0",
+    
+    "variables": {
+        "oak.version": "1.6.8"
+    },
+    
+    "bundles": [
+        {
+            "id": "org.apache.felix/org.apache.felix.jaas/1.0.2",
+            "start-level": 10
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-core/${oak.version}",
+            "start-level": 15
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-commons/${oak.version}",
+            "start-level": 15
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-lucene/${oak.version}",
+            "start-level": 15
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-blob/${oak.version}",
+            "start-level": 15
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-jcr/${oak.version}",
+            "start-level": 15
+        },
+        {
+            "id": "org.apache.jackrabbit/oak-segment-tar/${oak.version}",
+            "start-level": 15,
+            "run-modes": "oak_tar",
+            "configurations": {
+                "org.apache.jackrabbit.oak.segment.SegmentNodeStoreService": {
+                    "name": "Default NodeStore"
+                }
+            }
+        },
+        {
+            "id": "org.mongodb/mongo-java-driver/3.4.1",
+            "start-level": 15,
+            "run-modes": "oak_mongo",
+            "configurations": {
+                "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService": {
+                    "mongouri": "mongodb://localhost:27017",
+                    "db": "sling"
+                }
+            }
+        },
+        {
+            "id": "com.h2database/h2-mvstore/1.4.196",
+            "start-level": 15,
+            "run-modes": "oak_mongo"
+        },
+        {
+            "id": "org.apache.sling/org.apache.sling.jcr.oak.server/1.1.4",
+            "start-level": 16
+        }
+    ],
+    "configurations": {
+        "org.apache.felix.jaas.Configuration.factory-GuestLoginModule": {
+            "jaas.controlFlag": "optional",
+            "jaas.classname": "org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule",
+            "jaas.ranking:Integer": 300
+        }, 
+        "org.apache.felix.jaas.Configuration.factory-LoginModuleImpl" : {
+            "jaas.controlFlag": "required",
+            "jaas.classname": "org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl"
+        },
+        "org.apache.felix.jaas.Configuration.factory-TokenLoginModule" : {
+            "jaas.controlFlag": "sufficient",
+            "jaas.classname": "org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule",
+            "jaas.ranking:Integer": 200
+        },
+        "org.apache.felix.jaas.ConfigurationSpi": {
+            "jaas.defaultRealmName": "jackrabbit.oak",
+            "jaas.configProviderName": "FelixJaasProvider"
+        },
+        "org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl" : {
+            "org.apache.jackrabbit.oak.authentication.configSpiName": "FelixJaasProvider"
+        },
+        "org.apache.jackrabbit.oak.security.user.UserConfigurationImpl": {
+            "groupsPath": "/home/groups",
+            "usersPath": "/home/users",
+            "defaultDepth": "1",
+            "importBehavior": "besteffort"
+        },
+        "org.apache.jackrabbit.oak.security.user.RandomAuthorizableNodeName": {
+            "length:Integer": 21
+        },
+        "org.apache.jackrabbit.oak.spi.security.user.action.DefaultAuthorizableActionProvider": {
+            "enabledActions": ["org.apache.jackrabbit.oak.spi.security.user.action.AccessControlAction"],
+            "userPrivilegeNames": ["jcr:all"],
+            "groupPrivilegeNames": ["jcr:read"]
+        }
+    }
+}
diff --git a/src/test/resources/oak.txt b/src/test/resources/oak.txt
new file mode 100644
index 0000000..5d2675c
--- /dev/null
+++ b/src/test/resources/oak.txt
@@ -0,0 +1,91 @@
+#
+#  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.
+#
+# This is the OAK feature.
+[feature name=oak]
+
+[variables]
+    oak.version=1.6.8
+
+# The segment node store is used via a configuration
+[artifacts startLevel=10]
+    org.apache.felix/org.apache.felix.jaas/1.0.2
+
+[artifacts startLevel=15]
+    org.apache.jackrabbit/oak-core/${oak.version}
+    org.apache.jackrabbit/oak-commons/${oak.version}
+    org.apache.jackrabbit/oak-lucene/${oak.version}
+    org.apache.jackrabbit/oak-blob/${oak.version}
+    org.apache.jackrabbit/oak-jcr/${oak.version}
+
+[artifacts startLevel=15 runModes=oak_tar]
+    org.apache.jackrabbit/oak-segment-tar/${oak.version}
+
+[artifacts startLevel=15 runModes=oak_mongo]
+    org.mongodb/mongo-java-driver/3.4.1
+    com.h2database/h2-mvstore/1.4.196
+
+# start the Oak server instance after all components have been configured
+# and started to avoid restarting that component ( see SLING-4556 )
+[artifacts startLevel=16]
+    org.apache.sling/org.apache.sling.jcr.oak.server/1.1.4
+
+[configurations]
+  org.apache.felix.jaas.Configuration.factory-GuestLoginModule
+    jaas.controlFlag="optional"
+    jaas.classname="org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule"
+    jaas.ranking=I"300"
+
+  org.apache.felix.jaas.Configuration.factory-LoginModuleImpl
+    jaas.controlFlag="required"
+    jaas.classname="org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl"
+
+  org.apache.felix.jaas.Configuration.factory-TokenLoginModule
+    jaas.controlFlag="sufficient"
+    jaas.classname="org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule"
+    jaas.ranking=I"200"
+
+  org.apache.felix.jaas.ConfigurationSpi
+    jaas.defaultRealmName="jackrabbit.oak"
+    jaas.configProviderName="FelixJaasProvider"
+
+  org.apache.jackrabbit.oak.security.authentication.AuthenticationConfigurationImpl
+    org.apache.jackrabbit.oak.authentication.configSpiName="FelixJaasProvider"
+
+  org.apache.jackrabbit.oak.security.user.UserConfigurationImpl
+    groupsPath="/home/groups"
+    usersPath="/home/users"
+    defaultDepth="1"
+    importBehavior="besteffort"
+
+  org.apache.jackrabbit.oak.security.user.RandomAuthorizableNodeName
+    length=I"21"
+
+  org.apache.jackrabbit.oak.spi.security.user.action.DefaultAuthorizableActionProvider
+    enabledActions=["org.apache.jackrabbit.oak.spi.security.user.action.AccessControlAction"]
+    userPrivilegeNames=["jcr:all"]
+    groupPrivilegeNames=["jcr:read"]
+
+[configurations runModes=oak_tar]
+  org.apache.jackrabbit.oak.segment.SegmentNodeStoreService
+    name="Default\ NodeStore"
+
+[configurations runModes=oak_mongo]
+  org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService
+    mongouri="mongodb://localhost:27017"
+    db="sling"

-- 
To stop receiving notification emails like this one, please contact
davidb@apache.org.