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:39 UTC
[sling-org-apache-sling-feature-modelconverter] 21/40: Improve
handling of runmodes in provisioning model-feature conversions
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 856cd9b207111496acf68e218f5821864d3563ca
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Tue Apr 3 14:43:49 2018 +0100
Improve handling of runmodes in provisioning model-feature conversions
Also handle cases where ':' is used in configuration keys, something
that the OSGi configurator doesn't allow.
---
.../modelconverter/impl/FeatureToProvisioning.java | 46 +++++++---
.../modelconverter/impl/ProvisioningToFeature.java | 97 ++++++++++++++--------
.../modelconverter/impl/ModelConverterTest.java | 62 ++++++++++----
src/test/resources/boot.json | 5 ++
src/test/resources/boot.txt | 6 ++
src/test/resources/launchpad.json | 28 +++++++
src/test/resources/launchpad.txt | 20 +++++
src/test/resources/oak.json | 6 +-
src/test/resources/simple.json | 9 ++
src/test/resources/simple.txt | 24 ++++++
10 files changed, 239 insertions(+), 64 deletions(-)
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 3c904fe..dd6d830 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
@@ -151,40 +151,64 @@ public class FeatureToProvisioning {
// configurations
for(final org.apache.sling.feature.Configuration cfg : configurations) {
final Configuration c;
+
+ String[] runModes = null;
if ( cfg.isFactoryConfiguration() ) {
c = new Configuration(cfg.getName(), cfg.getFactoryPid());
} else {
- c = new Configuration(cfg.getPid(), null);
+ String pid = cfg.getPid();
+ pid = pid.replaceAll("[.][.](\\S+)", ":$1");
+ int rmIdx = pid.indexOf(".runmodes.");
+ if (rmIdx > 0) {
+ String rm = pid.substring(rmIdx + ".runmodes.".length());
+ pid = pid.substring(0, rmIdx);
+ runModes = rm.split("[.]");
+ }
+ c = new Configuration(pid, null);
}
final Enumeration<String> keys = cfg.getProperties().keys();
while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- c.getProperties().put(key, cfg.getProperties().get(key));
- }
+ String key = keys.nextElement();
+ Object val = cfg.getProperties().get(key);
- String[] runModes = null;
- Object rm = c.getProperties().remove(".runmodes");
- if (rm instanceof String) {
- runModes = ((String) rm).split(",");
+ if (key.startsWith("..")) {
+ key = ":" + key.substring(2);
+ }
+ c.getProperties().put(key, val);
}
+
f.getOrCreateRunMode(runModes).getConfigurations().add(c);
}
// framework properties
for(final Map.Entry<String, String> prop : frameworkProps) {
- f.getOrCreateRunMode(null).getSettings().put(prop.getKey(), prop.getValue());
+ String key = prop.getKey();
+ if (key.startsWith(".runmodes:")) {
+ int lastIdx = key.lastIndexOf(':');
+ String rm = key.substring(".runmodes:".length(), lastIdx);
+ String[] runmodes = rm.split(",");
+ key = key.substring(lastIdx + 1);
+ f.getOrCreateRunMode(runmodes).getSettings().put(key, prop.getValue());
+ } else {
+ f.getOrCreateRunMode(null).getSettings().put(key, prop.getValue());
+ }
}
// extensions: content packages and repoinit
for(final Extension ext : extensions) {
if ( Extension.NAME_CONTENT_PACKAGES.equals(ext.getName()) ) {
for(final org.apache.sling.feature.Artifact cp : ext.getArtifacts() ) {
+ String[] runmodes = null;
final ArtifactId id = cp.getId();
final Artifact newCP = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
for(final Map.Entry<String, String> prop : cp.getMetadata()) {
- newCP.getMetadata().put(prop.getKey(), prop.getValue());
+ if (prop.getKey().equals("runmodes")) {
+ runmodes = prop.getValue().split(",");
+ } else {
+ newCP.getMetadata().put(prop.getKey(), prop.getValue());
+ }
}
- f.getOrCreateRunMode(null).getOrCreateArtifactGroup(0).add(newCP);
+ f.getOrCreateRunMode(runmodes).getOrCreateArtifactGroup(20).add(newCP);
}
} else if ( Extension.NAME_REPOINIT.equals(ext.getName()) ) {
diff --git a/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java b/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
index 62a4f00..6af4aa3 100644
--- a/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
+++ b/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
@@ -148,7 +148,7 @@ public class ProvisioningToFeature {
modes = calculateRunModes(effectiveModel, runModes);
}
- removeInactiveFeaturesAndRunModes(effectiveModel, modes);
+ // removeInactiveFeaturesAndRunModes(effectiveModel, modes);
return effectiveModel;
}
@@ -237,6 +237,7 @@ public class ProvisioningToFeature {
}
}
+ // TODO is this needed for something?
private static void removeInactiveFeaturesAndRunModes(final Model m,
final Set<String> activeRunModes) {
final String[] requiredFeatures = new String[] {ModelConstants.FEATURE_LAUNCHPAD, ModelConstants.FEATURE_BOOT};
@@ -394,35 +395,33 @@ public class ProvisioningToFeature {
Extension cpExtension = extensions.getByName(Extension.NAME_CONTENT_PACKAGES);
for(final RunMode runMode : feature.getRunModes() ) {
- if ( !ModelConstants.FEATURE_LAUNCHPAD.equals(feature.getName()) ) {
- for(final ArtifactGroup group : runMode.getArtifactGroups()) {
- for(final Artifact artifact : group) {
- final ArtifactId id = ArtifactId.fromMvnUrl(artifact.toMvnUrl());
- final org.apache.sling.feature.Artifact newArtifact = new org.apache.sling.feature.Artifact(id);
+ for(final ArtifactGroup group : runMode.getArtifactGroups()) {
+ for(final Artifact artifact : group) {
+ final ArtifactId id = ArtifactId.fromMvnUrl(artifact.toMvnUrl());
+ final org.apache.sling.feature.Artifact newArtifact = new org.apache.sling.feature.Artifact(id);
- for(final Map.Entry<String, String> entry : artifact.getMetadata().entrySet()) {
- newArtifact.getMetadata().put(entry.getKey(), entry.getValue());
- }
+ for(final Map.Entry<String, String> entry : artifact.getMetadata().entrySet()) {
+ newArtifact.getMetadata().put(entry.getKey(), entry.getValue());
+ }
- if ( newArtifact.getId().getType().equals("zip") ) {
- if ( cpExtension == null ) {
- cpExtension = new Extension(ExtensionType.ARTIFACTS, Extension.NAME_CONTENT_PACKAGES, true);
- extensions.add(cpExtension);
- }
- cpExtension.getArtifacts().add(newArtifact);
- } else {
- int startLevel = group.getStartLevel();
- if ( startLevel == 0) {
- if ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
- startLevel = 1;
- } else if ( startLevel == 0 ) {
- startLevel = 20;
- }
+ if ( newArtifact.getId().getType().equals("zip") ) {
+ if ( cpExtension == null ) {
+ cpExtension = new Extension(ExtensionType.ARTIFACTS, Extension.NAME_CONTENT_PACKAGES, true);
+ extensions.add(cpExtension);
+ }
+ cpExtension.getArtifacts().add(newArtifact);
+ } else {
+ int startLevel = group.getStartLevel();
+ if ( startLevel == 0) {
+ if ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
+ startLevel = 1;
+ } else if ( startLevel == 0 ) {
+ startLevel = 20;
}
- newArtifact.getMetadata().put("start-level", String.valueOf(startLevel));
-
- bundles.add(newArtifact);
}
+ newArtifact.getMetadata().put("start-level", String.valueOf(startLevel));
+
+ bundles.add(newArtifact);
}
}
}
@@ -430,26 +429,54 @@ public class ProvisioningToFeature {
for(final Configuration cfg : runMode.getConfigurations()) {
final org.apache.sling.feature.Configuration newCfg;
if ( cfg.getFactoryPid() != null ) {
- newCfg = new org.apache.sling.feature.Configuration(cfg.getFactoryPid(), cfg.getPid());
+ String pid = cfg.getPid();
+ if (pid.startsWith(":")) {
+ // The configurator doesn't accept colons ':' in it's keys, so replace these
+ pid = ".." + pid.substring(1);
+ }
+
+ String[] runModeNames = runMode.getNames();
+ if (runModeNames != null) {
+ pid = pid + ".runmodes." + String.join(".", runModeNames);
+ }
+
+ newCfg = new org.apache.sling.feature.Configuration(cfg.getFactoryPid(), pid);
} else {
- newCfg = new org.apache.sling.feature.Configuration(cfg.getPid());
+ String pid = cfg.getPid();
+ if (pid.startsWith(":")) {
+ // The configurator doesn't accept colons ':' in it's keys, so replace these
+ pid = ".." + pid.substring(1);
+ }
+
+ String[] runModeNames = runMode.getNames();
+ if (runModeNames != null) {
+ pid = pid + ".runmodes." + String.join(".", runModeNames);
+ }
+
+ newCfg = new org.apache.sling.feature.Configuration(pid);
}
final Enumeration<String> keys = cfg.getProperties().keys();
while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- newCfg.getProperties().put(key, cfg.getProperties().get(key));
- }
+ String key = keys.nextElement();
+ Object value = cfg.getProperties().get(key);
- String[] runModeNames = runMode.getNames();
- if (runModeNames != null) {
- newCfg.getProperties().put(".runmodes", String.join(",", runModeNames));
+ if (key.startsWith(":")) {
+ key = ".." + key.substring(1);
+ }
+ newCfg.getProperties().put(key, value);
}
configurations.add(newCfg);
}
for(final Map.Entry<String, String> prop : runMode.getSettings()) {
- properties.put(prop.getKey(), prop.getValue());
+ String[] runModeNames = runMode.getNames();
+ if (runModeNames == null) {
+ properties.put(prop.getKey(), prop.getValue());
+ } else {
+ properties.put(".runmodes:" + String.join(",", runModeNames) + ":" +
+ prop.getKey(), prop.getValue());
+ }
}
}
Extension repoExtension = extensions.getByName(Extension.NAME_REPOINIT);
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 98f2dbc..249d9dc 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
@@ -115,6 +115,26 @@ public class ModelConverterTest {
}
@Test
+ public void testLaunchpadToProvModel() throws Exception {
+ testConvertToProvisioningModel("/launchpad.json", "/launchpad.txt");
+ }
+
+ @Test
+ public void testLaunchpadToFeature() throws Exception {
+ testConvertToFeature("/launchpad.txt", "/launchpad.json");
+ }
+
+ @Test
+ public void testSimpleToProvModel() throws Exception {
+ testConvertToProvisioningModel("/simple.json", "/simple.txt");
+ }
+
+ @Test
+ public void testSimpleToFeature() throws Exception {
+ testConvertToFeature("/simple.txt", "/simple.json");
+ }
+
+ @Test
public void testProvModelRoundtripFolder() throws Exception {
String dir = System.getProperty("test.prov.files.dir");
File filesDir;
@@ -365,27 +385,31 @@ public class ModelConverterTest {
boolean found = false;
for (Configuration cfg2 : configs2) {
- if (!cfg2.getPid().equals(cfg1.getPid())) {
+ if (cfg1.getFactoryPid() == null) {
+ if (cfg2.getFactoryPid() != null) {
+ continue;
+ }
+ } else if (!cfg1.getFactoryPid().equals(cfg2.getFactoryPid())) {
continue;
}
- found = true;
- if (cfg1.getFactoryPid() == null) {
- if (cfg2.getFactoryPid() != null)
- return false;
- } else {
- if (!cfg1.getFactoryPid().equals(cfg2.getFactoryPid())) {
- return false;
- }
+ if (!cfg1.getPid().equals(cfg2.getPid())) {
+ continue;
}
+ // Factory and ordinary PIDs are equal, so check the content
+ found = true;
+
if (!configPropsEqual(cfg1.getProperties(), cfg2.getProperties())) {
return false;
}
break;
}
- assertTrue("Configuration with PID " + cfg1.getPid() + " not found", found);
+ if (!found) {
+ // Configuration with this PID not found
+ return false;
+ }
}
Map<String, String> m1 = kvToMap(rm1.getSettings());
@@ -426,13 +450,23 @@ public class ModelConverterTest {
List<Artifact> al2 = new ArrayList<>();
g2.iterator().forEachRemaining(al2::add);
- for (int i=0; i < al1.size(); i++) {
+ for (int i=0; i<al1.size(); i++) {
Artifact a1 = al1.get(i);
- Artifact a2 = al2.get(i);
- if (a1.compareTo(a2) != 0)
+ boolean found = false;
+ for (Iterator<Artifact> it = al2.iterator(); it.hasNext(); ) {
+ Artifact a2 = it.next();
+ if (a1.compareTo(a2) == 0) {
+ found = true;
+ it.remove();
+ }
+ }
+ if (!found) {
return false;
+ }
}
- return true;
+
+ // Should have found all artifacts
+ return (al2.size() == 0);
}
private int effectiveStartLevel(String featureName, int startLevel) {
diff --git a/src/test/resources/boot.json b/src/test/resources/boot.json
index c267b67..4cc7d40 100644
--- a/src/test/resources/boot.json
+++ b/src/test/resources/boot.json
@@ -90,6 +90,11 @@
"sling.run.mode.install.options": "oak_tar,oak_mongo",
"repository.home": "${sling.home}/repository",
"localIndexDir": "${sling.home}/repository/index",
+
+ "# we need runmodes here too...": "",
+ ".runmodes:a:something": "else",
+ ".runmodes::b:special": "true",
+
"#": "${sling.home} needs to be provided at launch time"
}
}
diff --git a/src/test/resources/boot.txt b/src/test/resources/boot.txt
index df5a947..d8a6fec 100644
--- a/src/test/resources/boot.txt
+++ b/src/test/resources/boot.txt
@@ -28,6 +28,12 @@
sling.run.mode.install.options=oak_tar,oak_mongo
repository.home=${sling.home}/repository
localIndexDir=${sling.home}/repository/index
+
+[settings runModes=:b]
+ special=true
+
+[settings runModes=a]
+ something=else
[variables]
slf4j.version=1.7.25
diff --git a/src/test/resources/launchpad.json b/src/test/resources/launchpad.json
new file mode 100644
index 0000000..0dd9318
--- /dev/null
+++ b/src/test/resources/launchpad.json
@@ -0,0 +1,28 @@
+{
+ "id":"generated:feature:1.0.0",
+ "variables":{
+ "provisioning.model.name":":launchpad"
+ },
+ "bundles":[
+ {
+ "id":"org.apache.sling:org.apache.sling.launchpad.base:5.6.10-2.6.26",
+ "start-level":"20"
+ },
+ {
+ "id":"org.apache.sling:org.apache.sling.commons.osgi:2.4.0",
+ "run-modes":":something",
+ "start-level":"20"
+ }
+ ],
+ "configurations":{
+ "..bootstrap":{
+ "..bootstrap":"uninstall com.google.guava 15.0.0\n"
+ },
+ "..bootstrap.runmodes.:standalone":{
+ "..bootstrap":"uninstall org.apache.felix.http.bridge\nuninstall org.apache.felix.http.api\n"
+ },
+ "org.apache.testing.ConfigPid.factory-configuration.runmodes.:standalone":{
+ "key1":"val1"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/launchpad.txt b/src/test/resources/launchpad.txt
new file mode 100644
index 0000000..188bf76
--- /dev/null
+++ b/src/test/resources/launchpad.txt
@@ -0,0 +1,20 @@
+[feature name=:launchpad]
+
+[artifacts]
+ org.apache.sling/org.apache.sling.launchpad.base/5.6.10-2.6.26
+
+[configurations]
+ :bootstrap
+ uninstall com.google.guava 15.0.0
+
+[artifacts runModes=:something]
+
+ org.apache.sling/org.apache.sling.commons.osgi/2.4.0
+
+[configurations runModes=:standalone]
+ :bootstrap
+ uninstall org.apache.felix.http.bridge
+ uninstall org.apache.felix.http.api
+
+ org.apache.testing.ConfigPid.factory-configuration
+ key1="val1"
diff --git a/src/test/resources/oak.json b/src/test/resources/oak.json
index d94aa8d..03f64c3 100644
--- a/src/test/resources/oak.json
+++ b/src/test/resources/oak.json
@@ -86,12 +86,10 @@
"userPrivilegeNames": ["jcr:all"],
"groupPrivilegeNames": ["jcr:read"]
},
- "org.apache.jackrabbit.oak.segment.SegmentNodeStoreService": {
- ".runmodes": "oak_tar",
+ "org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.runmodes.oak_tar": {
"name": "Default NodeStore"
},
- "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService": {
- ".runmodes": "oak_mongo",
+ "org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.runmodes.oak_mongo": {
"mongouri": "mongodb://localhost:27017",
"db": "sling"
}
diff --git a/src/test/resources/simple.json b/src/test/resources/simple.json
new file mode 100644
index 0000000..4cc130a
--- /dev/null
+++ b/src/test/resources/simple.json
@@ -0,0 +1,9 @@
+{
+ "id":"generated:simple:1.0.0",
+ "bundles":[
+ {
+ "id":"org.apache.aries:org.apache.aries.util:1.1.3",
+ "start-level":"20"
+ }
+ ]
+}
diff --git a/src/test/resources/simple.txt b/src/test/resources/simple.txt
new file mode 100644
index 0000000..53e40a2
--- /dev/null
+++ b/src/test/resources/simple.txt
@@ -0,0 +1,24 @@
+#
+# 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=simple]
+
+[artifacts]
+ org.apache.aries/org.apache.aries.util/1.1.3
--
To stop receiving notification emails like this one, please contact
davidb@apache.org.