From commits-return-66205-archive-asf-public=cust-asf.ponee.io@sling.apache.org Tue Apr 3 15:45:58 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 5B09918064D for ; Tue, 3 Apr 2018 15:45:57 +0200 (CEST) Received: (qmail 24787 invoked by uid 500); 3 Apr 2018 13:45:56 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 24778 invoked by uid 99); 3 Apr 2018 13:45:56 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Apr 2018 13:45:56 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id B16BA80A6D; Tue, 3 Apr 2018 13:45:55 +0000 (UTC) Date: Tue, 03 Apr 2018 13:45:55 +0000 To: "commits@sling.apache.org" Subject: [sling-whiteboard] branch master updated: Improve handling of runmodes in provisioning model-feature conversions MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <152276315567.7583.1501830064342959732@gitbox.apache.org> From: davidb@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: sling-whiteboard X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: e23e01939c9f4870b3dcbaaa309f599fb811c852 X-Git-Newrev: 364eb107feade07af92161569845b1c1d0bd5a86 X-Git-Rev: 364eb107feade07af92161569845b1c1d0bd5a86 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated 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-whiteboard.git The following commit(s) were added to refs/heads/master by this push: new 364eb10 Improve handling of runmodes in provisioning model-feature conversions 364eb10 is described below commit 364eb107feade07af92161569845b1c1d0bd5a86 Author: David Bosschaert 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/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java b/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java index 3c904fe..dd6d830 100644 --- a/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java +++ b/featuremodel/feature-modelconverter/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 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 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 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/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java b/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java index 62a4f00..6af4aa3 100644 --- a/featuremodel/feature-modelconverter/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java +++ b/featuremodel/feature-modelconverter/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 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 entry : artifact.getMetadata().entrySet()) { - newArtifact.getMetadata().put(entry.getKey(), entry.getValue()); - } + for(final Map.Entry 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 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 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/featuremodel/feature-modelconverter/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java b/featuremodel/feature-modelconverter/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java index 98f2dbc..249d9dc 100644 --- a/featuremodel/feature-modelconverter/src/test/java/org/apache/sling/feature/modelconverter/impl/ModelConverterTest.java +++ b/featuremodel/feature-modelconverter/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 m1 = kvToMap(rm1.getSettings()); @@ -426,13 +450,23 @@ public class ModelConverterTest { List al2 = new ArrayList<>(); g2.iterator().forEachRemaining(al2::add); - for (int i=0; i < al1.size(); i++) { + for (int i=0; i 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/featuremodel/feature-modelconverter/src/test/resources/boot.json b/featuremodel/feature-modelconverter/src/test/resources/boot.json index c267b67..4cc7d40 100644 --- a/featuremodel/feature-modelconverter/src/test/resources/boot.json +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/boot.txt b/featuremodel/feature-modelconverter/src/test/resources/boot.txt index df5a947..d8a6fec 100644 --- a/featuremodel/feature-modelconverter/src/test/resources/boot.txt +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/launchpad.json b/featuremodel/feature-modelconverter/src/test/resources/launchpad.json new file mode 100644 index 0000000..0dd9318 --- /dev/null +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/launchpad.txt b/featuremodel/feature-modelconverter/src/test/resources/launchpad.txt new file mode 100644 index 0000000..188bf76 --- /dev/null +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/oak.json b/featuremodel/feature-modelconverter/src/test/resources/oak.json index d94aa8d..03f64c3 100644 --- a/featuremodel/feature-modelconverter/src/test/resources/oak.json +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/simple.json b/featuremodel/feature-modelconverter/src/test/resources/simple.json new file mode 100644 index 0000000..4cc130a --- /dev/null +++ b/featuremodel/feature-modelconverter/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/featuremodel/feature-modelconverter/src/test/resources/simple.txt b/featuremodel/feature-modelconverter/src/test/resources/simple.txt new file mode 100644 index 0000000..53e40a2 --- /dev/null +++ b/featuremodel/feature-modelconverter/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.