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:25 UTC
[sling-org-apache-sling-feature-modelconverter] 07/40: Support the
slinstart maven plugin by providing a model converter API
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 b9c87b7e46912e24e555e8e2a68f5733c0bfebbb
Author: David Bosschaert <da...@gmail.com>
AuthorDate: Fri Mar 9 10:46:10 2018 +0000
Support the slinstart maven plugin by providing a model converter API
---
pom.xml | 26 +-
.../modelconverter/impl/FeatureToProvisioning.java | 216 ++++++++
.../sling/feature/modelconverter/impl/Main.java | 554 +-------------------
.../impl/{Main.java => ProvisioningToFeature.java} | 562 ++++++---------------
4 files changed, 393 insertions(+), 965 deletions(-)
diff --git a/pom.xml b/pom.xml
index d5359d5..2e0c607 100644
--- a/pom.xml
+++ b/pom.xml
@@ -83,6 +83,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.resolver</artifactId>
+ <version>1.0.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
@@ -104,6 +110,12 @@
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.feature.analyser</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.feature.resolver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>provided</scope>
@@ -126,10 +138,18 @@
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
- <!-- Testing -->
+
+ <!-- Testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.framework</artifactId>
+ <version>5.6.10</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
new file mode 100644
index 0000000..44eaaac
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/modelconverter/impl/FeatureToProvisioning.java
@@ -0,0 +1,216 @@
+/*
+ * 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.modelconverter.impl;
+
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Bundles;
+import org.apache.sling.feature.Configurations;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.Extensions;
+import org.apache.sling.feature.KeyValueMap;
+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.provisioning.model.Artifact;
+import org.apache.sling.provisioning.model.Configuration;
+import org.apache.sling.provisioning.model.Feature;
+import org.apache.sling.provisioning.model.Model;
+import org.apache.sling.provisioning.model.Section;
+import org.apache.sling.provisioning.model.io.ModelWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class FeatureToProvisioning {
+ private static Logger LOGGER = LoggerFactory.getLogger(FeatureToProvisioning.class);
+
+ public static void convert(File file, String output, ArtifactManager am) throws IOException {
+ org.apache.sling.feature.Feature feature = FeatureUtil.getFeature(file.getAbsolutePath(), am);
+
+ String featureName;
+ if (feature.getTitle() != null) {
+ featureName = feature.getTitle();
+ } else {
+ featureName = feature.getId().getArtifactId();
+ }
+
+ Feature newFeature = new Feature(featureName);
+ convert(newFeature, feature.getBundles(), feature.getConfigurations(), feature.getFrameworkProperties(), feature.getExtensions(), output);
+ }
+
+ public static void convert(List<File> files, String output, boolean createApp, ArtifactManager am) throws Exception {
+ try (FeatureResolver fr = null) { // TODO we could use the resolver: new FrameworkResolver(am)
+ if ( createApp ) {
+ // each file is an application
+ int index = 1;
+ for(final File appFile : files ) {
+ try ( final FileReader r = new FileReader(appFile) ) {
+ final Application app = ApplicationJSONReader.read(r);
+ FeatureToProvisioning.convert(app, files.size() > 1 ? index : 0, output);
+ }
+ index++;
+ }
+ } else {
+ final Application app = FeatureUtil.assembleApplication(null, am, fr, files.stream()
+ .map(File::getAbsolutePath)
+ .toArray(String[]::new));
+ FeatureToProvisioning.convert(app, 0, output);
+ }
+ }
+ }
+
+ private static void convert(final Application app, final int index, final String outputFile) {
+ String featureName;
+
+ List<ArtifactId> fids = app.getFeatureIds();
+ if (fids.size() > 0) {
+ featureName = fids.get(0).getArtifactId();
+ } else {
+ featureName = "application";
+ }
+ final Feature feature = new Feature(featureName);
+
+ convert(feature, app.getBundles(), app.getConfigurations(), app.getFrameworkProperties(), app.getExtensions(), outputFile);
+ }
+
+ private static void convert(Feature f, Bundles bundles, Configurations configurations, KeyValueMap frameworkProps,
+ Extensions extensions, String outputFile) {
+ Map<org.apache.sling.feature.Configuration, org.apache.sling.feature.Artifact> configBundleMap = new HashMap<>();
+
+ // bundles
+ for(final org.apache.sling.feature.Artifact bundle : bundles) {
+ final ArtifactId id = bundle.getId();
+ final Artifact newBundle = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
+
+ Object configs = bundle.getMetadata().getObject("configurations");
+ if (configs instanceof List) {
+ for (Object config : (List<?>) configs) {
+ if (config instanceof org.apache.sling.feature.Configuration) {
+ configBundleMap.put((org.apache.sling.feature.Configuration) config, bundle);
+ }
+ }
+ }
+
+ for(final Map.Entry<String, String> prop : bundle.getMetadata()) {
+ switch (prop.getKey()) {
+ // these are handled separately
+ case "start-level":
+ case "run-modes":
+ break;
+ default:
+ newBundle.getMetadata().put(prop.getKey(), prop.getValue());
+ }
+ }
+
+ int startLevel;
+ String sl = bundle.getMetadata().get("start-level");
+ if (sl != null) {
+ startLevel = Integer.parseInt(sl);
+ } else {
+ startLevel = 20;
+ }
+
+ String[] runModes = getRunModes(bundle);
+ f.getOrCreateRunMode(runModes).getOrCreateArtifactGroup(startLevel).add(newBundle);
+ }
+
+ // configurations
+ for(final org.apache.sling.feature.Configuration cfg : configurations) {
+ final Configuration c;
+ if ( cfg.isFactoryConfiguration() ) {
+ c = new Configuration(cfg.getName(), cfg.getFactoryPid());
+ } else {
+ c = new Configuration(cfg.getPid(), null);
+ }
+ final Enumeration<String> keys = cfg.getProperties().keys();
+ while ( keys.hasMoreElements() ) {
+ final String key = keys.nextElement();
+ c.getProperties().put(key, cfg.getProperties().get(key));
+ }
+
+ // 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;
+ if (bundle != null) {
+ runModes = getRunModes(bundle);
+ } else {
+ runModes = null;
+ }
+ 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());
+ }
+
+ // 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() ) {
+ 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());
+ }
+ f.getOrCreateRunMode(null).getOrCreateArtifactGroup(0).add(newCP);
+ }
+
+ } else if ( Extension.NAME_REPOINIT.equals(ext.getName()) ) {
+ final Section section = new Section("repoinit");
+ section.setContents(ext.getText());
+ f.getAdditionalSections().add(section);
+ } else if ( ext.isRequired() ) {
+ LOGGER.error("Unable to convert required extension {}", ext.getName());
+ System.exit(1);
+ }
+ }
+
+ LOGGER.info("Writing feature...");
+ final String out = outputFile;
+ final File file = new File(out);
+ final Model m = new Model();
+ m.getFeatures().add(f);
+ try ( final FileWriter writer = new FileWriter(file)) {
+ ModelWriter.write(writer, m);
+ } catch ( final IOException ioe) {
+ LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
+ System.exit(1);
+ }
+ }
+
+ private static String[] getRunModes(final org.apache.sling.feature.Artifact bundle) {
+ String runMode = bundle.getMetadata().get("run-modes");
+ String[] runModes;
+ if (runMode != null) {
+ runModes = runMode.split(",");
+ } else {
+ runModes = null;
+ }
+ return runModes;
+ }
+}
diff --git a/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java b/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java
index ccc3f85..81a9e3c 100644
--- a/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java
@@ -16,60 +16,23 @@
*/
package org.apache.sling.feature.modelconverter.impl;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
-import org.apache.sling.feature.Application;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Bundles;
-import org.apache.sling.feature.Configurations;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Extensions;
-import org.apache.sling.feature.KeyValueMap;
-import org.apache.sling.feature.process.FeatureResolver;
-import org.apache.sling.feature.resolver.FrameworkResolver;
-import org.apache.sling.feature.support.ArtifactHandler;
import org.apache.sling.feature.support.ArtifactManager;
import org.apache.sling.feature.support.ArtifactManagerConfig;
-import org.apache.sling.feature.support.FeatureUtil;
-import org.apache.sling.feature.support.json.ApplicationJSONReader;
-import org.apache.sling.feature.support.json.ApplicationJSONWriter;
-import org.apache.sling.feature.support.json.FeatureJSONWriter;
-import org.apache.sling.provisioning.model.Artifact;
-import org.apache.sling.provisioning.model.ArtifactGroup;
-import org.apache.sling.provisioning.model.Configuration;
-import org.apache.sling.provisioning.model.Feature;
-import org.apache.sling.provisioning.model.MergeUtility;
-import org.apache.sling.provisioning.model.Model;
-import org.apache.sling.provisioning.model.ModelConstants;
-import org.apache.sling.provisioning.model.ModelUtility;
-import org.apache.sling.provisioning.model.ModelUtility.ResolverOptions;
-import org.apache.sling.provisioning.model.ModelUtility.VariableResolver;
-import org.apache.sling.provisioning.model.RunMode;
-import org.apache.sling.provisioning.model.Section;
-import org.apache.sling.provisioning.model.Traceable;
-import org.apache.sling.provisioning.model.io.ModelReader;
-import org.apache.sling.provisioning.model.io.ModelWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
public class Main {
private static Logger LOGGER;
@@ -167,10 +130,6 @@ public class Main {
return null;
}
- private static FeatureResolver getFeatureResolver(ArtifactManager am) {
- return new FrameworkResolver(am, Collections.emptyMap());
- }
-
public static void main(final String[] args) {
// setup logging
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
@@ -229,41 +188,13 @@ public class Main {
if ( output == null ) {
output = createApp ? "application.json" : "feature.json";
}
- final Model model = createModel(files, runModes);
-
- if ( createApp ) {
- final Application app = buildApplication(model);
-
- writeApplication(app, output);
- } else {
- final List<org.apache.sling.feature.Feature> features = buildFeatures(model);
- int index = 1;
- for(final org.apache.sling.feature.Feature feature : features) {
- writeFeature(feature, output, features.size() > 1 ? index : 0);
- index++;
- }
- }
+ ProvisioningToFeature.convert(files, output, runModes, createApp, includeModelInfo, propsFile);
} else {
if ( output == null ) {
output = createApp ? "application.txt" : "feature.txt";
}
- try (FeatureResolver fr = getFeatureResolver(am)) {
- if ( createApp ) {
- // each file is an application
- int index = 1;
- for(final File appFile : files ) {
- try ( final FileReader r = new FileReader(appFile) ) {
- final Application app = ApplicationJSONReader.read(r);
- convert(app, files.size() > 1 ? index : 0);
- }
- index++;
- }
- } else {
- final Application app = FeatureUtil.assembleApplication(null, am, fr, files.stream()
- .map(File::getAbsolutePath)
- .toArray(String[]::new));
- convert(app, 0);
- }
+ try {
+ FeatureToProvisioning.convert(files, output, createApp, am);
} catch ( final IOException ioe) {
LOGGER.error("Unable to read feature/application files " + ioe.getMessage(), ioe);
System.exit(1);
@@ -274,471 +205,4 @@ public class Main {
}
}
- private static List<org.apache.sling.feature.Feature> buildFeatures(final Model model) {
- final List<org.apache.sling.feature.Feature> features = new ArrayList<>();
-
- for(final Feature feature : model.getFeatures() ) {
- final String idString;
- // use a default name if not present or not usable as a Maven artifactId ( starts with ':')
- if ( feature.getName() != null && !feature.isSpecial() ) {
- if ( feature.getVersion() != null ) {
- idString = "generated/" + feature.getName() + "/" + feature.getVersion();
- } else {
- idString = "generated/" + feature.getName() + "/1.0.0";
- }
- } else {
- idString = "generated/feature/1.0.0";
- }
- final org.apache.sling.feature.Feature f = new org.apache.sling.feature.Feature(ArtifactId.parse(idString));
- features.add(f);
-
- buildFromFeature(feature, f.getBundles(), f.getConfigurations(), f.getExtensions(), f.getFrameworkProperties());
- }
-
- return features;
- }
-
- private static Application buildApplication(final Model model) {
- final Application app = new Application();
-
- for(final Feature feature : model.getFeatures() ) {
- buildFromFeature(feature, app.getBundles(), app.getConfigurations(), app.getExtensions(), app.getFrameworkProperties());
- }
-
- // hard coded dependency to launchpad api
- final org.apache.sling.feature.Artifact a = new org.apache.sling.feature.Artifact(ArtifactId.parse("org.apache.sling/org.apache.sling.launchpad.api/1.2.0"));
- a.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, "1");
- // sling.properties (TODO)
- if ( propsFile == null ) {
- app.getFrameworkProperties().put("org.osgi.framework.bootdelegation", "sun.*,com.sun.*");
- } else {
-
- }
- // felix framework hard coded for now
- app.setFramework(FeatureUtil.getFelixFrameworkId(null));
- return app;
- }
-
- private static void buildFromFeature(final Feature feature,
- final Bundles bundles,
- final Configurations configurations,
- final Extensions extensions,
- final KeyValueMap properties) {
- 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 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 ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
- startLevel = 1;
- } else if ( startLevel == 0 ) {
- startLevel = 20;
- }
- newArtifact.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, String.valueOf(startLevel));
- bundles.add(newArtifact);
- }
- }
- }
- }
-
- 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());
- } else {
- newCfg = new org.apache.sling.feature.Configuration(cfg.getPid());
- }
- final Enumeration<String> keys = cfg.getProperties().keys();
- while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- newCfg.getProperties().put(key, cfg.getProperties().get(key));
- }
- configurations.add(newCfg);
- }
-
- for(final Map.Entry<String, String> prop : runMode.getSettings()) {
- properties.put(prop.getKey(), prop.getValue());
- }
- }
- Extension repoExtension = extensions.getByName(Extension.NAME_REPOINIT);
- for(final Section sect : feature.getAdditionalSections("repoinit")) {
- final String text = sect.getContents();
- if ( repoExtension == null ) {
- repoExtension = new Extension(ExtensionType.TEXT, Extension.NAME_REPOINIT, true);
- extensions.add(repoExtension);
- repoExtension.setText(text);
- } else {
- repoExtension.setText(repoExtension.getText() + "\n\n" + text);
- }
- }
- }
-
- private static void writeApplication(final Application app, final String out) {
- LOGGER.info("Writing application...");
- final File file = new File(out);
- try ( final FileWriter writer = new FileWriter(file)) {
- ApplicationJSONWriter.write(writer, app);
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to write application to {} : {}", out, ioe.getMessage(), ioe);
- System.exit(1);
- }
- }
-
- private static void writeFeature(final org.apache.sling.feature.Feature f, String out, final int index) {
- LOGGER.info("Writing feature...");
- if ( index > 0 ) {
- final int lastDot = out.lastIndexOf('.');
- if ( lastDot == -1 ) {
- out = out + "_" + String.valueOf(index);
- } else {
- out = out.substring(0, lastDot) + "_" + String.valueOf(index) + out.substring(lastDot);
- }
- }
- final File file = new File(out);
- try ( final FileWriter writer = new FileWriter(file)) {
- FeatureJSONWriter.write(writer, f);
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
- System.exit(1);
- }
- }
-
- /**
- * Read the models and prepare the model
- * @param files The model files
- */
- private static Model createModel(final List<File> files,
- final String runModes) {
- LOGGER.info("Assembling model...");
- Model model = null;
- for(final File initFile : files) {
- try {
- model = processModel(model, initFile);
- } catch ( final IOException iae) {
- LOGGER.error("Unable to read provisioning model {} : {}", initFile, iae.getMessage(), iae);
- System.exit(1);
- }
- }
-
- final Model effectiveModel = ModelUtility.getEffectiveModel(model, new ResolverOptions().variableResolver(new VariableResolver() {
-
- @Override
- public String resolve(Feature feature, String name) {
- if ( "sling.home".equals(name) ) {
- return "${sling.home}";
- }
- return feature.getVariables().get(name);
- }
- }));
- final Map<Traceable, String> errors = ModelUtility.validate(effectiveModel);
- if ( errors != null ) {
- LOGGER.error("Invalid assembled provisioning model.");
- for(final Map.Entry<Traceable, String> entry : errors.entrySet()) {
- LOGGER.error("- {} : {}", entry.getKey().getLocation(), entry.getValue());
- }
- System.exit(1);
- }
- final Set<String> modes = calculateRunModes(effectiveModel, runModes);
-
- removeInactiveFeaturesAndRunModes(effectiveModel, modes);
-
- return effectiveModel;
- }
-
- /**
- * Process the given model and merge it into the provided model
- * @param model The already read model
- * @param modelFile The model file
- * @return The merged model
- * @throws IOException If reading fails
- */
- private static Model processModel(Model model,
- final File modelFile) throws IOException {
- LOGGER.info("- reading model {}", modelFile);
-
- final Model nextModel = readProvisioningModel(modelFile);
- // resolve references to other models
- final ResolverOptions options = new ResolverOptions().variableResolver(new VariableResolver() {
-
- @Override
- public String resolve(final Feature feature, final String name) {
- return name;
- }
- });
-
-
- final Model effectiveModel = ModelUtility.getEffectiveModel(nextModel, options);
- for(final Feature feature : effectiveModel.getFeatures()) {
- for(final RunMode runMode : feature.getRunModes()) {
- for(final ArtifactGroup group : runMode.getArtifactGroups()) {
- final List<org.apache.sling.provisioning.model.Artifact> removeList = new ArrayList<>();
- for(final org.apache.sling.provisioning.model.Artifact a : group) {
- if ( "slingstart".equals(a.getType())
- || "slingfeature".equals(a.getType())) {
-
- final ArtifactManagerConfig cfg = new ArtifactManagerConfig();
- final ArtifactManager mgr = ArtifactManager.getArtifactManager(cfg);
-
- final ArtifactId correctedId = new ArtifactId(a.getGroupId(),
- a.getArtifactId(),
- a.getVersion(),
- "slingstart".equals(a.getType()) ? "slingfeature" : a.getClassifier(),
- "txt");
-
- final ArtifactHandler handler = mgr.getArtifactHandler(correctedId.toMvnUrl());
- model = processModel(model, handler.getFile());
-
- removeList.add(a);
- } else {
- final org.apache.sling.provisioning.model.Artifact realArtifact = nextModel.getFeature(feature.getName()).getRunMode(runMode.getNames()).getArtifactGroup(group.getStartLevel()).search(a);
-
- if ( includeModelInfo ) {
- realArtifact.getMetadata().put("model-filename", modelFile.getName());
- }
- if ( runMode.getNames() != null ) {
- realArtifact.getMetadata().put("runmodes", String.join(",", runMode.getNames()));
- }
- }
- }
- for(final org.apache.sling.provisioning.model.Artifact r : removeList) {
- nextModel.getFeature(feature.getName()).getRunMode(runMode.getNames()).getArtifactGroup(group.getStartLevel()).remove(r);
- }
- }
- }
- }
-
- if ( model == null ) {
- model = nextModel;
- } else {
- MergeUtility.merge(model, nextModel);
- }
- return model;
- }
-
- /**
- * Read the provisioning model
- */
- private static Model readProvisioningModel(final File file)
- throws IOException {
- try (final FileReader is = new FileReader(file)) {
- final Model m = ModelReader.read(is, file.getAbsolutePath());
- return m;
- }
- }
-
- private static void removeInactiveFeaturesAndRunModes(final Model m,
- final Set<String> activeRunModes) {
- final String[] requiredFeatures = new String[] {ModelConstants.FEATURE_LAUNCHPAD, ModelConstants.FEATURE_BOOT};
- // first pass:
- // - remove special features except boot required ones
- // - remove special run modes and inactive run modes
- // - remove special configurations (TODO)
- final Iterator<Feature> i = m.getFeatures().iterator();
- while ( i.hasNext() ) {
- final Feature feature = i.next();
- if ( feature.isSpecial() ) {
- boolean remove = true;
- if ( requiredFeatures != null ) {
- for(final String name : requiredFeatures) {
- if ( feature.getName().equals(name) ) {
- remove = false;
- break;
- }
- }
- }
- if ( remove ) {
- i.remove();
- continue;
- }
- }
- feature.setComment(null);
- final Iterator<RunMode> rmI = feature.getRunModes().iterator();
- while ( rmI.hasNext() ) {
- final RunMode rm = rmI.next();
- if ( rm.isActive(activeRunModes) || rm.isRunMode(ModelConstants.RUN_MODE_STANDALONE) ) {
- final Iterator<Configuration> cI = rm.getConfigurations().iterator();
- while ( cI.hasNext() ) {
- final Configuration config = cI.next();
- if ( config.isSpecial() ) {
- cI.remove();
- continue;
- }
- config.setComment(null);
- }
- } else {
- rmI.remove();
- continue;
- }
- }
- }
-
- // second pass: aggregate the settings and add them to the first required feature
- final Feature requiredFeature = m.getFeature(requiredFeatures[0]);
- if ( requiredFeature != null ) {
- for(final Feature f : m.getFeatures()) {
- if ( f.getName().equals(requiredFeature.getName()) ) {
- continue;
- }
- copyAndClearSettings(requiredFeature, f.getRunMode(new String[] {ModelConstants.RUN_MODE_STANDALONE}));
- copyAndClearSettings(requiredFeature, f.getRunMode());
- }
- }
- }
-
- private static void copyAndClearSettings(final Feature requiredFeature, final RunMode rm) {
- if ( rm != null && !rm.getSettings().isEmpty() ) {
- final RunMode requiredRunMode = requiredFeature.getOrCreateRunMode(null);
- final Set<String> keys = new HashSet<>();
- for(final Map.Entry<String, String> entry : rm.getSettings()) {
- requiredRunMode.getSettings().put(entry.getKey(), entry.getValue());
- keys.add(entry.getKey());
- }
-
- for(final String key : keys) {
- rm.getSettings().remove(key);
- }
- }
- }
-
- private static Set<String> calculateRunModes(final Model model, final String runModes) {
- final Set<String> modesSet = new HashSet<>();
-
- // check configuration property first
- if (runModes != null && runModes.trim().length() > 0) {
- final String[] modes = runModes.split(",");
- for(int i=0; i < modes.length; i++) {
- modesSet.add(modes[i].trim());
- }
- }
-
- // handle configured options
- final Feature feature = model.getFeature(ModelConstants.FEATURE_BOOT);
- if ( feature != null ) {
- handleOptions(modesSet, feature.getRunMode().getSettings().get("sling.run.mode.options"));
- handleOptions(modesSet, feature.getRunMode().getSettings().get("sling.run.mode.install.options"));
- }
-
- return modesSet;
- }
-
- private static void handleOptions(final Set<String> modesSet, final String propOptions) {
- if ( propOptions != null && propOptions.trim().length() > 0 ) {
-
- final String[] options = propOptions.trim().split("\\|");
- for(final String opt : options) {
- String selected = null;
- final String[] modes = opt.trim().split(",");
- for(int i=0; i<modes.length; i++) {
- modes[i] = modes[i].trim();
- if ( selected != null ) {
- modesSet.remove(modes[i]);
- } else {
- if ( modesSet.contains(modes[i]) ) {
- selected = modes[i];
- }
- }
- }
- if ( selected == null ) {
- selected = modes[0];
- modesSet.add(modes[0]);
- }
- }
- }
- }
-
- private static void convert(final Application app, final int index) {
- final Feature f = new Feature("application");
-
- // bundles
- for(final org.apache.sling.feature.Artifact bundle : app.getBundles()) {
- final ArtifactId id = bundle.getId();
- final Artifact newBundle = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
- for(final Map.Entry<String, String> prop : bundle.getMetadata()) {
- newBundle.getMetadata().put(prop.getKey(), prop.getValue());
- }
- int startLevel = bundle.getStartOrder();
- if ( startLevel == 0 ) {
- startLevel = 20;
- }
- f.getOrCreateRunMode(null).getOrCreateArtifactGroup(startLevel).add(newBundle);
- }
-
- // configurations
- for(final org.apache.sling.feature.Configuration cfg : app.getConfigurations()) {
- final Configuration c;
- if ( cfg.isFactoryConfiguration() ) {
- c = new Configuration(cfg.getName(), cfg.getFactoryPid());
- } else {
- c = new Configuration(cfg.getPid(), null);
- }
- final Enumeration<String> keys = cfg.getProperties().keys();
- while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- c.getProperties().put(key, cfg.getProperties().get(key));
- }
- f.getOrCreateRunMode(null).getConfigurations().add(c);
- }
-
- // framework properties
- for(final Map.Entry<String, String> prop : app.getFrameworkProperties()) {
- f.getOrCreateRunMode(null).getSettings().put(prop.getKey(), prop.getValue());
- }
-
- // extensions: content packages and repoinit
- for(final Extension ext : app.getExtensions()) {
- if ( Extension.NAME_CONTENT_PACKAGES.equals(ext.getName()) ) {
- for(final org.apache.sling.feature.Artifact cp : ext.getArtifacts() ) {
- 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());
- }
- f.getOrCreateRunMode(null).getOrCreateArtifactGroup(0).add(newCP);
- }
-
- } else if ( Extension.NAME_REPOINIT.equals(ext.getName()) ) {
- final Section section = new Section("repoinit");
- section.setContents(ext.getText());
- f.getAdditionalSections().add(section);
- } else if ( ext.isRequired() ) {
- LOGGER.error("Unable to convert required extension {}", ext.getName());
- System.exit(1);
- }
- }
-
- LOGGER.info("Writing feature...");
- String out = output;
- if ( index > 0 ) {
- final int lastDot = out.lastIndexOf('.');
- if ( lastDot == -1 ) {
- out = out + "_" + String.valueOf(index);
- } else {
- out = out.substring(0, lastDot) + "_" + String.valueOf(index) + out.substring(lastDot);
- }
- }
- final File file = new File(out);
- final Model m = new Model();
- m.getFeatures().add(f);
- try ( final FileWriter writer = new FileWriter(file)) {
- ModelWriter.write(writer, m);
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
- System.exit(1);
- }
- }
}
diff --git a/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java b/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
similarity index 61%
copy from src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java
copy to src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
index ccc3f85..e3a4a52 100644
--- a/src/main/java/org/apache/sling/feature/modelconverter/impl/Main.java
+++ b/src/main/java/org/apache/sling/feature/modelconverter/impl/ProvisioningToFeature.java
@@ -16,25 +16,6 @@
*/
package org.apache.sling.feature.modelconverter.impl;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
import org.apache.sling.feature.Application;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Bundles;
@@ -43,13 +24,10 @@ import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Extensions;
import org.apache.sling.feature.KeyValueMap;
-import org.apache.sling.feature.process.FeatureResolver;
-import org.apache.sling.feature.resolver.FrameworkResolver;
import org.apache.sling.feature.support.ArtifactHandler;
import org.apache.sling.feature.support.ArtifactManager;
import org.apache.sling.feature.support.ArtifactManagerConfig;
import org.apache.sling.feature.support.FeatureUtil;
-import org.apache.sling.feature.support.json.ApplicationJSONReader;
import org.apache.sling.feature.support.json.ApplicationJSONWriter;
import org.apache.sling.feature.support.json.FeatureJSONWriter;
import org.apache.sling.provisioning.model.Artifact;
@@ -66,369 +44,54 @@ import org.apache.sling.provisioning.model.RunMode;
import org.apache.sling.provisioning.model.Section;
import org.apache.sling.provisioning.model.Traceable;
import org.apache.sling.provisioning.model.io.ModelReader;
-import org.apache.sling.provisioning.model.io.ModelWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class Main {
-
- private static Logger LOGGER;
-
- private static String runModes;
-
- private static String output;
-
- private static String input;
-
- private static boolean createApp = false;
-
- private static boolean includeModelInfo = false;
-
- private static String repoUrls;
-
- private static String propsFile;
-
- /**
- * Parse the command line parameters and update a configuration object.
- * @param args Command line parameters
- * @return Configuration object.
- */
- private static void parseArgs(final String[] args) {
- final Option repoOption = Option.builder("u").hasArg().argName("Set repository url")
- .desc("repository url").required().build();
-
- final Option modelOption = new Option("f", true, "Set feature files/directories");
- final Option propsOption = new Option("p", true, "sling.properties file");
- final Option runModeOption = new Option("r", true, "Set run modes (comma separated)");
- final Option createAppOption = new Option("a", false, "If enabled, create application json");
- createAppOption.setArgs(0);
- final Option includeModelOption = new Option("i", false, "Include model filename as metadata for artifacts");
- includeModelOption.setArgs(0);
-
- final Option outputOption = Option.builder("o").hasArg().argName("Set output file")
- .desc("output file").build();
-
- final Options options = new Options();
- options.addOption(repoOption);
- options.addOption(modelOption);
- options.addOption(createAppOption);
- options.addOption(outputOption);
- options.addOption(includeModelOption);
- options.addOption(propsOption);
- options.addOption(runModeOption);
-
- final CommandLineParser parser = new DefaultParser();
- try {
- final CommandLine cl = parser.parse(options, args);
-
- if ( cl.hasOption(repoOption.getOpt()) ) {
- repoUrls = cl.getOptionValue(repoOption.getOpt());
- }
- if ( cl.hasOption(modelOption.getOpt()) ) {
- input = cl.getOptionValue(modelOption.getOpt());
- }
- if ( cl.hasOption(createAppOption.getOpt()) ) {
- createApp = true;
- }
- if ( cl.hasOption(includeModelOption.getOpt()) ) {
- includeModelInfo = true;
- }
- if ( cl.hasOption(runModeOption.getOpt()) ) {
- runModes = cl.getOptionValue(runModeOption.getOpt());
- }
- if ( cl.hasOption(outputOption.getOpt()) ) {
- output = cl.getOptionValue(outputOption.getOpt());
- }
- if ( cl.hasOption(propsOption.getOpt()) ) {
- propsFile = cl.getOptionValue(propsOption.getOpt());
- }
- } catch ( final ParseException pe) {
- LOGGER.error("Unable to parse command line: {}", pe.getMessage(), pe);
- System.exit(1);
- }
- if ( input == null ) {
- LOGGER.error("Required argument missing: model file or directory");
- System.exit(1);
- }
- }
-
- private static ArtifactManager getArtifactManager() {
- final ArtifactManagerConfig amConfig = new ArtifactManagerConfig();
- if ( repoUrls != null ) {
- amConfig.setRepositoryUrls(repoUrls.split(","));
- }
- try {
- return ArtifactManager.getArtifactManager(amConfig);
- } catch ( IOException ioe) {
- LOGGER.error("Unable to create artifact manager " + ioe.getMessage(), ioe);
- System.exit(1);
- }
- // we never reach this, but have to keep the compiler happy
- return null;
- }
-
- private static FeatureResolver getFeatureResolver(ArtifactManager am) {
- return new FrameworkResolver(am, Collections.emptyMap());
- }
-
- public static void main(final String[] args) {
- // setup logging
- System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
- System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");
- System.setProperty("org.slf4j.simpleLogger.levelInBrackets", "true");
- System.setProperty("org.slf4j.simpleLogger.showLogName", "false");
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
- LOGGER = LoggerFactory.getLogger("modelconverter");
+public class ProvisioningToFeature {
+ private static Logger LOGGER = LoggerFactory.getLogger(ProvisioningToFeature.class);
- LOGGER.info("Apache Sling Provisiong Model to Feature Application Converter");
- LOGGER.info("");
+ public static void convert(List<File> files, String outputFile, String runModes, boolean createApp,
+ boolean includeModelInfo, String propsFile) {
+ final Model model = createModel(files, runModes, includeModelInfo);
- parseArgs(args);
+ if ( createApp ) {
+ final Application app = buildApplication(model, propsFile);
- final ArtifactManagerConfig amConfig = new ArtifactManagerConfig();
- if ( repoUrls != null ) {
- amConfig.setRepositoryUrls(repoUrls.split(","));
- }
- final ArtifactManager am = getArtifactManager();
-
- final File f = new File(input);
- final List<File> files = new ArrayList<>();
- if ( f.isDirectory() ) {
- for(final File file : f.listFiles()) {
- if ( file.isFile() && !file.getName().startsWith(".") ) {
- files.add(file);
- }
- }
- if ( files.isEmpty() ) {
- LOGGER.error("No files found in {}", f);
- System.exit(1);
- }
- Collections.sort(files);
+ writeApplication(app, outputFile);
} else {
- files.add(f);
- }
- boolean isJson = false;
- boolean isTxt = false;
- for(final File t : files) {
- if ( t.getName().endsWith(".json") ) {
- if ( isTxt ) {
- LOGGER.error("Input files are a mixture of JSON and txt");
- System.exit(1);
- }
- isJson = true;
- } else {
- if ( isJson ) {
- LOGGER.error("Input files are a mixture of JSON and txt");
- System.exit(1);
- }
- isTxt = true;
- }
- }
-
- if ( isTxt ) {
- if ( output == null ) {
- output = createApp ? "application.json" : "feature.json";
- }
- final Model model = createModel(files, runModes);
-
- if ( createApp ) {
- final Application app = buildApplication(model);
-
- writeApplication(app, output);
- } else {
- final List<org.apache.sling.feature.Feature> features = buildFeatures(model);
- int index = 1;
- for(final org.apache.sling.feature.Feature feature : features) {
- writeFeature(feature, output, features.size() > 1 ? index : 0);
- index++;
- }
- }
- } else {
- if ( output == null ) {
- output = createApp ? "application.txt" : "feature.txt";
- }
- try (FeatureResolver fr = getFeatureResolver(am)) {
- if ( createApp ) {
- // each file is an application
- int index = 1;
- for(final File appFile : files ) {
- try ( final FileReader r = new FileReader(appFile) ) {
- final Application app = ApplicationJSONReader.read(r);
- convert(app, files.size() > 1 ? index : 0);
- }
- index++;
- }
- } else {
- final Application app = FeatureUtil.assembleApplication(null, am, fr, files.stream()
- .map(File::getAbsolutePath)
- .toArray(String[]::new));
- convert(app, 0);
- }
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to read feature/application files " + ioe.getMessage(), ioe);
- System.exit(1);
- } catch ( final Exception e) {
- LOGGER.error("Problem generating application", e);
- System.exit(1);
- }
- }
- }
-
- private static List<org.apache.sling.feature.Feature> buildFeatures(final Model model) {
- final List<org.apache.sling.feature.Feature> features = new ArrayList<>();
-
- for(final Feature feature : model.getFeatures() ) {
- final String idString;
- // use a default name if not present or not usable as a Maven artifactId ( starts with ':')
- if ( feature.getName() != null && !feature.isSpecial() ) {
- if ( feature.getVersion() != null ) {
- idString = "generated/" + feature.getName() + "/" + feature.getVersion();
- } else {
- idString = "generated/" + feature.getName() + "/1.0.0";
- }
- } else {
- idString = "generated/feature/1.0.0";
+ final List<org.apache.sling.feature.Feature> features = buildFeatures(model);
+ int index = 1;
+ for(final org.apache.sling.feature.Feature feature : features) {
+ writeFeature(feature, outputFile, features.size() > 1 ? index : 0);
+ index++;
}
- final org.apache.sling.feature.Feature f = new org.apache.sling.feature.Feature(ArtifactId.parse(idString));
- features.add(f);
-
- buildFromFeature(feature, f.getBundles(), f.getConfigurations(), f.getExtensions(), f.getFrameworkProperties());
- }
-
- return features;
- }
-
- private static Application buildApplication(final Model model) {
- final Application app = new Application();
-
- for(final Feature feature : model.getFeatures() ) {
- buildFromFeature(feature, app.getBundles(), app.getConfigurations(), app.getExtensions(), app.getFrameworkProperties());
- }
-
- // hard coded dependency to launchpad api
- final org.apache.sling.feature.Artifact a = new org.apache.sling.feature.Artifact(ArtifactId.parse("org.apache.sling/org.apache.sling.launchpad.api/1.2.0"));
- a.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, "1");
- // sling.properties (TODO)
- if ( propsFile == null ) {
- app.getFrameworkProperties().put("org.osgi.framework.bootdelegation", "sun.*,com.sun.*");
- } else {
-
- }
- // felix framework hard coded for now
- app.setFramework(FeatureUtil.getFelixFrameworkId(null));
- return app;
- }
-
- private static void buildFromFeature(final Feature feature,
- final Bundles bundles,
- final Configurations configurations,
- final Extensions extensions,
- final KeyValueMap properties) {
- 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 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 ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
- startLevel = 1;
- } else if ( startLevel == 0 ) {
- startLevel = 20;
- }
- newArtifact.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, String.valueOf(startLevel));
- bundles.add(newArtifact);
- }
- }
- }
- }
-
- 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());
- } else {
- newCfg = new org.apache.sling.feature.Configuration(cfg.getPid());
- }
- final Enumeration<String> keys = cfg.getProperties().keys();
- while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- newCfg.getProperties().put(key, cfg.getProperties().get(key));
- }
- configurations.add(newCfg);
- }
-
- for(final Map.Entry<String, String> prop : runMode.getSettings()) {
- properties.put(prop.getKey(), prop.getValue());
- }
- }
- Extension repoExtension = extensions.getByName(Extension.NAME_REPOINIT);
- for(final Section sect : feature.getAdditionalSections("repoinit")) {
- final String text = sect.getContents();
- if ( repoExtension == null ) {
- repoExtension = new Extension(ExtensionType.TEXT, Extension.NAME_REPOINIT, true);
- extensions.add(repoExtension);
- repoExtension.setText(text);
- } else {
- repoExtension.setText(repoExtension.getText() + "\n\n" + text);
- }
- }
- }
-
- private static void writeApplication(final Application app, final String out) {
- LOGGER.info("Writing application...");
- final File file = new File(out);
- try ( final FileWriter writer = new FileWriter(file)) {
- ApplicationJSONWriter.write(writer, app);
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to write application to {} : {}", out, ioe.getMessage(), ioe);
- System.exit(1);
- }
- }
-
- private static void writeFeature(final org.apache.sling.feature.Feature f, String out, final int index) {
- LOGGER.info("Writing feature...");
- if ( index > 0 ) {
- final int lastDot = out.lastIndexOf('.');
- if ( lastDot == -1 ) {
- out = out + "_" + String.valueOf(index);
- } else {
- out = out.substring(0, lastDot) + "_" + String.valueOf(index) + out.substring(lastDot);
- }
- }
- final File file = new File(out);
- try ( final FileWriter writer = new FileWriter(file)) {
- FeatureJSONWriter.write(writer, f);
- } catch ( final IOException ioe) {
- LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
- System.exit(1);
}
}
/**
* Read the models and prepare the model
* @param files The model files
+ * @param includeModelInfo
*/
private static Model createModel(final List<File> files,
- final String runModes) {
+ final String runModes, boolean includeModelInfo) {
LOGGER.info("Assembling model...");
Model model = null;
for(final File initFile : files) {
try {
- model = processModel(model, initFile);
+ model = processModel(model, initFile, includeModelInfo);
} catch ( final IOException iae) {
LOGGER.error("Unable to read provisioning model {} : {}", initFile, iae.getMessage(), iae);
System.exit(1);
@@ -464,11 +127,12 @@ public class Main {
* Process the given model and merge it into the provided model
* @param model The already read model
* @param modelFile The model file
+ * @param includeModelInfo
* @return The merged model
* @throws IOException If reading fails
*/
private static Model processModel(Model model,
- final File modelFile) throws IOException {
+ final File modelFile, boolean includeModelInfo) throws IOException {
LOGGER.info("- reading model {}", modelFile);
final Model nextModel = readProvisioningModel(modelFile);
@@ -501,7 +165,7 @@ public class Main {
"txt");
final ArtifactHandler handler = mgr.getArtifactHandler(correctedId.toMvnUrl());
- model = processModel(model, handler.getFile());
+ model = processModel(model, handler.getFile(), includeModelInfo);
removeList.add(a);
} else {
@@ -661,68 +325,134 @@ public class Main {
}
}
- private static void convert(final Application app, final int index) {
- final Feature f = new Feature("application");
+ private static Application buildApplication(final Model model, String propsFile) {
+ final Application app = new Application();
+
+ for(final Feature feature : model.getFeatures() ) {
+ buildFromFeature(feature, app.getBundles(), app.getConfigurations(), app.getExtensions(), app.getFrameworkProperties());
+ }
+
+ // hard coded dependency to launchpad api
+ final org.apache.sling.feature.Artifact a = new org.apache.sling.feature.Artifact(ArtifactId.parse("org.apache.sling/org.apache.sling.launchpad.api/1.2.0"));
+ a.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, "1");
+ // sling.properties (TODO)
+ if ( propsFile == null ) {
+ app.getFrameworkProperties().put("org.osgi.framework.bootdelegation", "sun.*,com.sun.*");
+ } else {
- // bundles
- for(final org.apache.sling.feature.Artifact bundle : app.getBundles()) {
- final ArtifactId id = bundle.getId();
- final Artifact newBundle = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
- for(final Map.Entry<String, String> prop : bundle.getMetadata()) {
- newBundle.getMetadata().put(prop.getKey(), prop.getValue());
+ }
+ // felix framework hard coded for now
+ app.setFramework(FeatureUtil.getFelixFrameworkId(null));
+ return app;
+ }
+
+ private static void buildFromFeature(final Feature feature,
+ final Bundles bundles,
+ final Configurations configurations,
+ final Extensions extensions,
+ final KeyValueMap properties) {
+ 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 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 ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
+ startLevel = 1;
+ } else if ( startLevel == 0 ) {
+ startLevel = 20;
+ }
+ newArtifact.getMetadata().put(org.apache.sling.feature.Artifact.KEY_START_ORDER, String.valueOf(startLevel));
+ bundles.add(newArtifact);
+ }
+ }
+ }
}
- int startLevel = bundle.getStartOrder();
- if ( startLevel == 0 ) {
- startLevel = 20;
+
+ 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());
+ } else {
+ newCfg = new org.apache.sling.feature.Configuration(cfg.getPid());
+ }
+ final Enumeration<String> keys = cfg.getProperties().keys();
+ while ( keys.hasMoreElements() ) {
+ final String key = keys.nextElement();
+ newCfg.getProperties().put(key, cfg.getProperties().get(key));
+ }
+ configurations.add(newCfg);
}
- f.getOrCreateRunMode(null).getOrCreateArtifactGroup(startLevel).add(newBundle);
- }
- // configurations
- for(final org.apache.sling.feature.Configuration cfg : app.getConfigurations()) {
- final Configuration c;
- if ( cfg.isFactoryConfiguration() ) {
- c = new Configuration(cfg.getName(), cfg.getFactoryPid());
- } else {
- c = new Configuration(cfg.getPid(), null);
+ for(final Map.Entry<String, String> prop : runMode.getSettings()) {
+ properties.put(prop.getKey(), prop.getValue());
}
- final Enumeration<String> keys = cfg.getProperties().keys();
- while ( keys.hasMoreElements() ) {
- final String key = keys.nextElement();
- c.getProperties().put(key, cfg.getProperties().get(key));
+ }
+ Extension repoExtension = extensions.getByName(Extension.NAME_REPOINIT);
+ for(final Section sect : feature.getAdditionalSections("repoinit")) {
+ final String text = sect.getContents();
+ if ( repoExtension == null ) {
+ repoExtension = new Extension(ExtensionType.TEXT, Extension.NAME_REPOINIT, true);
+ extensions.add(repoExtension);
+ repoExtension.setText(text);
+ } else {
+ repoExtension.setText(repoExtension.getText() + "\n\n" + text);
}
- f.getOrCreateRunMode(null).getConfigurations().add(c);
}
+ }
- // framework properties
- for(final Map.Entry<String, String> prop : app.getFrameworkProperties()) {
- f.getOrCreateRunMode(null).getSettings().put(prop.getKey(), prop.getValue());
- }
- // extensions: content packages and repoinit
- for(final Extension ext : app.getExtensions()) {
- if ( Extension.NAME_CONTENT_PACKAGES.equals(ext.getName()) ) {
- for(final org.apache.sling.feature.Artifact cp : ext.getArtifacts() ) {
- 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());
- }
- f.getOrCreateRunMode(null).getOrCreateArtifactGroup(0).add(newCP);
- }
+ private static List<org.apache.sling.feature.Feature> buildFeatures(final Model model) {
+ final List<org.apache.sling.feature.Feature> features = new ArrayList<>();
- } else if ( Extension.NAME_REPOINIT.equals(ext.getName()) ) {
- final Section section = new Section("repoinit");
- section.setContents(ext.getText());
- f.getAdditionalSections().add(section);
- } else if ( ext.isRequired() ) {
- LOGGER.error("Unable to convert required extension {}", ext.getName());
- System.exit(1);
+ for(final Feature feature : model.getFeatures() ) {
+ final String idString;
+ // use a default name if not present or not usable as a Maven artifactId ( starts with ':')
+ if ( feature.getName() != null && !feature.isSpecial() ) {
+ if ( feature.getVersion() != null ) {
+ idString = "generated/" + feature.getName() + "/" + feature.getVersion();
+ } else {
+ idString = "generated/" + feature.getName() + "/1.0.0";
+ }
+ } else {
+ idString = "generated/feature/1.0.0";
}
+ final org.apache.sling.feature.Feature f = new org.apache.sling.feature.Feature(ArtifactId.parse(idString));
+ features.add(f);
+
+ buildFromFeature(feature, f.getBundles(), f.getConfigurations(), f.getExtensions(), f.getFrameworkProperties());
}
+ return features;
+ }
+
+ private static void writeApplication(final Application app, final String out) {
+ LOGGER.info("Writing application...");
+ final File file = new File(out);
+ try ( final FileWriter writer = new FileWriter(file)) {
+ ApplicationJSONWriter.write(writer, app);
+ } catch ( final IOException ioe) {
+ LOGGER.error("Unable to write application to {} : {}", out, ioe.getMessage(), ioe);
+ System.exit(1);
+ }
+ }
+
+ private static void writeFeature(final org.apache.sling.feature.Feature f, String out, final int index) {
LOGGER.info("Writing feature...");
- String out = output;
if ( index > 0 ) {
final int lastDot = out.lastIndexOf('.');
if ( lastDot == -1 ) {
@@ -732,10 +462,8 @@ public class Main {
}
}
final File file = new File(out);
- final Model m = new Model();
- m.getFeatures().add(f);
try ( final FileWriter writer = new FileWriter(file)) {
- ModelWriter.write(writer, m);
+ FeatureJSONWriter.write(writer, f);
} catch ( final IOException ioe) {
LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
System.exit(1);
--
To stop receiving notification emails like this one, please contact
davidb@apache.org.