You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2017/05/29 08:12:55 UTC
svn commit: r1796586 - in /sling/whiteboard/cziegeler/provisioning-model: ./
src/main/java/org/apache/sling/feature/
src/main/java/org/apache/sling/feature/io/
src/main/java/org/apache/sling/provisioning/
Author: cziegeler
Date: Mon May 29 08:12:55 2017
New Revision: 1796586
URL: http://svn.apache.org/viewvc?rev=1796586&view=rev
Log:
Update model and use configurator format for configurations
Added:
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java (with props)
Removed:
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundle.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/provisioning/
Modified:
sling/whiteboard/cziegeler/provisioning-model/pom.xml
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Application.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Artifact.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/ArtifactId.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Configuration.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Feature.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Include.java
sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/io/FeatureReader.java
Modified: sling/whiteboard/cziegeler/provisioning-model/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/pom.xml?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/pom.xml (original)
+++ sling/whiteboard/cziegeler/provisioning-model/pom.xml Mon May 29 08:12:55 2017
@@ -61,6 +61,18 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.converter</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.configurator</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Application.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Application.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Application.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Application.java Mon May 29 08:12:55 2017
@@ -32,7 +32,7 @@ import java.util.List;
*/
public class Application {
- private final List<Bundle> bundles = new ArrayList<>();
+ private final Bundles bundles = new Bundles();
private final List<Configuration> configurations = new ArrayList<>();
@@ -45,11 +45,10 @@ public class Application {
private ArtifactId framework;
/**
- * Get the list of bundles.
- * The list can be modified
- * @return The list of bundles.
+ * Get the bundles
+ * @return The bundles object.
*/
- public List<Bundle> getBundles() {
+ public Bundles getBundles() {
return this.bundles;
}
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Artifact.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Artifact.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Artifact.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Artifact.java Mon May 29 08:12:55 2017
@@ -92,7 +92,7 @@ public class Artifact implements Compara
@Override
public String toString() {
- return "Artifact [id=" + id.toMvnUrl().substring(4)
+ return "Artifact [id=" + id.toMvnId()
+ "]";
}
}
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/ArtifactId.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/ArtifactId.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/ArtifactId.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/ArtifactId.java Mon May 29 08:12:55 2017
@@ -84,7 +84,17 @@ public class ArtifactId implements Compa
if ( url == null || !url.startsWith("mvn:") ) {
throw new IllegalArgumentException("Invalid mvn url: " + url);
}
- final String content = url.substring(4);
+ return fromMvnId(url.substring(4));
+ }
+
+ /**
+ * Create a new artifact from a maven url,
+ * [ repository-url '!' ] group-id '/' artifact-id [ '/' [version] [ '/' [type] [ '/' classifier ] ] ] ]
+ * @param content The id
+ * @return A new artifact
+ * @throws IllegalArgumentException If the id is not valid
+ */
+ public static ArtifactId fromMvnId(final String content) {
// ignore repository url
int pos = content.indexOf('!');
if ( pos != -1 ) {
@@ -136,7 +146,14 @@ public class ArtifactId implements Compa
* @see #fromMvnUrl(String)
*/
public String toMvnUrl() {
- final StringBuilder sb = new StringBuilder("mvn:");
+ return toId(new StringBuilder("mvn:"));
+ }
+
+ public String toMvnId() {
+ return toId(new StringBuilder());
+ }
+
+ private String toId(final StringBuilder sb) {
sb.append(this.groupId);
sb.append('/');
sb.append(this.artifactId);
@@ -258,6 +275,6 @@ public class ArtifactId implements Compa
@Override
public String toString() {
- return toMvnUrl().substring(4);
+ return toMvnId();
}
}
Added: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java?rev=1796586&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java (added)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java Mon May 29 08:12:55 2017
@@ -0,0 +1,74 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Bundles groups bundle {@code Artifact}s by start level.
+ */
+public class Bundles {
+
+ private final Map<Integer, List<Artifact>> startLevelMap = new TreeMap<>();
+
+ /**
+ * Get the map of all bundles sorted by start level. The map is sorted
+ * and iterating over the keys is done in start level order.
+ * @return The map of bundles. The map is unmodifiable.
+ */
+ public Map<Integer, List<Artifact>> getBundlesByStartLevel() {
+ return Collections.unmodifiableMap(this.startLevelMap);
+ }
+
+ @Override
+ public String toString() {
+ return "Bundles [" + this.startLevelMap
+ + "]";
+ }
+
+ public void add(final int startLevel, final Artifact bundle) {
+ List<Artifact> list = this.startLevelMap.get(startLevel);
+ if ( list == null ) {
+ list = new ArrayList<>();
+ this.startLevelMap.put(startLevel, list);
+ }
+ list.add(bundle);
+ }
+
+ public boolean remove(final ArtifactId id) {
+ for(final Map.Entry<Integer, List<Artifact>> entry : this.startLevelMap.entrySet()) {
+ for(final Artifact artifact : entry.getValue()) {
+ if ( artifact.getId().equals(id)) {
+ entry.getValue().remove(artifact);
+ if ( entry.getValue().isEmpty() ) {
+ this.startLevelMap.remove(entry.getKey());
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void clear() {
+ this.startLevelMap.clear();
+ }
+}
Propchange: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Bundles.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Configuration.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Configuration.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Configuration.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Configuration.java Mon May 29 08:12:55 2017
@@ -23,13 +23,13 @@ import java.util.Hashtable;
/**
* A configuration has either
* - a pid
- * - or a factory pid and an alias (pid)
+ * - or a factory pid and a name (pid)
* and properties.
*/
public class Configuration
implements Comparable<Configuration> {
- /** The pid. */
+ /** The pid or name for factory pids. */
private final String pid;
/** The factory pid. */
@@ -40,12 +40,29 @@ public class Configuration
/**
* Create a new configuration
- * @param pid The pid or alias for a factory pid
+ * @param pid The pid
+ * @throws IllegalArgumentException If pid is {@code null}
+ */
+ public Configuration(final String pid) {
+ if ( pid == null ) {
+ throw new IllegalArgumentException("pid must not be null");
+ }
+ this.pid = pid;
+ this.factoryPid = null;
+ }
+
+ /**
+ * Create a new factor configuration
* @param factoryPid The factory pid
+ * @param name The name of the factory pid
+ * @throws IllegalArgumentException If factoryPid or name is {@code null}
*/
- public Configuration(final String pid, final String factoryPid) {
- this.pid = (pid != null ? pid.trim() : null);
- this.factoryPid = (factoryPid != null ? factoryPid.trim() : null);
+ public Configuration(final String factoryPid, final String name) {
+ if ( factoryPid == null || name == null ) {
+ throw new IllegalArgumentException("factoryPid and/or name must not be null");
+ }
+ this.pid = name;
+ this.factoryPid = factoryPid;
}
private int compareString(final String a, final String b) {
@@ -73,21 +90,35 @@ public class Configuration
/**
* Get the pid.
- * If this is a factory configuration, it returns the alias for the configuration
- * @return The pid.
+ * If this is a factory configuration, it returns {@code null}
+ * @return The pid or {@code null}
*/
public String getPid() {
+ if ( this.isFactoryConfiguration() ) {
+ return null;
+ }
return this.pid;
}
/**
* Return the factory pid
- * @return The factory pid or null.
+ * @return The factory pid or {@code null}.
*/
public String getFactoryPid() {
return this.factoryPid;
}
+ public String getName() {
+ if ( this.isFactoryConfiguration() ) {
+ return this.pid;
+ }
+ return null;
+ }
+
+ public boolean isFactoryConfiguration() {
+ return this.factoryPid != null;
+ }
+
/**
* Get all properties of the configuration.
* @return The properties
@@ -98,8 +129,13 @@ public class Configuration
@Override
public String toString() {
+ if ( this.isFactoryConfiguration() ) {
+ return "Factory Configuration [factoryPid=" + factoryPid
+ + ", name=" + pid
+ + ", properties=" + properties
+ + "]";
+ }
return "Configuration [pid=" + pid
- + ", factoryPid=" + factoryPid
+ ", properties=" + properties
+ "]";
}
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Feature.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Feature.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Feature.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Feature.java Mon May 29 08:12:55 2017
@@ -18,8 +18,6 @@ package org.apache.sling.feature;
import java.util.ArrayList;
import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
/**
* A feature consists of
@@ -37,7 +35,7 @@ public class Feature implements Comparab
private final ArtifactId id;
- private final List<Bundle> bundles = new ArrayList<>();
+ private final Bundles bundles = new Bundles();
private final List<Configuration> configurations = new ArrayList<>();
@@ -94,27 +92,13 @@ public class Feature implements Comparab
}
/**
- * Get the list of bundles.
- * The list can be modified
- * @return The list of bundles.
+ * Get the bundles.
+ * @return The bundles object.
*/
- public List<Bundle> getBundles() {
+ public Bundles getBundles() {
return this.bundles;
}
- public SortedMap<Integer, List<Bundle>> getBundlesByStartLevel() {
- final SortedMap<Integer, List<Bundle>> map = new TreeMap<>();
- for(final Bundle b : this.getBundles()) {
- List<Bundle> list = map.get(b.getStartLevel());
- if ( list == null ) {
- list = new ArrayList<>();
- map.put(b.getStartLevel(), list);
- }
- list.add(b);
- }
- return map;
- }
-
public List<Configuration> getConfigurations() {
return this.configurations;
}
@@ -162,7 +146,7 @@ public class Feature implements Comparab
@Override
public String toString() {
- return "Feature [id=" + this.getId().toMvnUrl().substring(4)
+ return "Feature [id=" + this.getId().toMvnId()
+ ( this.getLocation() != null ? ", location=" + this.getLocation() : "")
+ "]";
}
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Include.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Include.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Include.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/Include.java Mon May 29 08:12:55 2017
@@ -16,13 +16,28 @@
*/
package org.apache.sling.feature;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
- * A include is an inclusion of a feature
+ * A include is an inclusion of a feature with optional removals
*/
public class Include implements Comparable<Include> {
private final ArtifactId id;
+ private final List<String> configurationRemovals = new ArrayList<>();
+
+ private final List<ArtifactId> bundleRemovals = new ArrayList<>();
+
+ private final List<String> frameworkPropertiesRemovals = new ArrayList<>();
+
+ private final List<String> textExtensionRemovals = new ArrayList<>();
+
+ private final Map<String, List<Artifact>> artifactExtensionRemovals = new HashMap<>();
+
/**
* Construct a new Include.
* @param id The id of the feature.
@@ -43,6 +58,26 @@ public class Include implements Comparab
return this.id;
}
+ public List<String> getConfigurationRemovals() {
+ return configurationRemovals;
+ }
+
+ public List<ArtifactId> getBundleRemovals() {
+ return bundleRemovals;
+ }
+
+ public List<String> getFrameworkPropertiesRemovals() {
+ return frameworkPropertiesRemovals;
+ }
+
+ public List<String> getTextExtensionRemovals() {
+ return textExtensionRemovals;
+ }
+
+ public Map<String, List<Artifact>> getArtifactExtensionRemovals() {
+ return artifactExtensionRemovals;
+ }
+
@Override
public int compareTo(final Include o) {
return this.id.compareTo(o.id);
@@ -66,7 +101,7 @@ public class Include implements Comparab
@Override
public String toString() {
- return "Include [id=" + id.toMvnUrl().substring(4)
+ return "Include [id=" + id.toMvnId()
+ "]";
}
}
Modified: sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/io/FeatureReader.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/io/FeatureReader.java?rev=1796586&r1=1796585&r2=1796586&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/io/FeatureReader.java (original)
+++ sling/whiteboard/cziegeler/provisioning-model/src/main/java/org/apache/sling/feature/io/FeatureReader.java Mon May 29 08:12:55 2017
@@ -18,12 +18,30 @@ package org.apache.sling.feature.io;
import java.io.IOException;
import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.felix.configurator.impl.TypeConverter;
+import org.apache.felix.configurator.impl.json.JSMin;
+import org.apache.felix.configurator.impl.json.JSONUtil;
+import org.apache.felix.configurator.impl.model.Config;
+import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.Feature;
/**
@@ -31,33 +49,231 @@ import org.apache.sling.feature.Feature;
*/
public class FeatureReader {
- private final String location;
-
+ /**
+ * Read a new feature from the reader
+ * The reader is not closed. It is up to the caller to close the reader.
+ * @param reader The reader for the feature
+ * @param location Optional location
+ * @return The read feature
+ * @throws IOException If an IO errors occurs or the JSON is invalid.
+ */
public static Feature read(final Reader reader, final String location)
throws IOException {
+ // minify JSON first (remove comments)
+ final String contents;
+ try ( final Writer out = new StringWriter()) {
+ final JSMin min = new JSMin(reader, out);
+ min.jsmin();
+ contents = out.toString();
+ }
+
final FeatureReader mr = new FeatureReader(location);
- return mr.readFeature(reader);
+ return mr.readFeature(new StringReader(contents));
}
+ private static final String FEATURE_ID = "id";
+
+ private static final String FEATURE_BUNDLES = "bundles";
+
+ private static final String FEATURE_FRAMEWORK_PROPERTIES = "framework-properties";
+
+ private static final String FEATURE_CONFIGURATIONS = "configurations";
+
+ private static final String FEATURE_INCLUDES = "includes";
+
+ private static final String FEATURE_REQUIREMENTS = "requirements";
+
+ private static final String FEATURE_CAPABILITIES = "capabilities";
+
+ private Feature feature;
+
+ private final String location;
+
+ private final String exceptionPrefix;
+
+ /**
+ * Private constructor
+ * @param location Optional location
+ */
private FeatureReader(final String location) {
this.location = location;
+ if ( location == null ) {
+ exceptionPrefix = "";
+ } else {
+ exceptionPrefix = location + " : ";
+ }
}
+ /**
+ * Read a full feature
+ * @param reader The reader
+ * @return The feature object
+ * @throws IOException If an IO error occurs or the JSON is not valid.
+ */
private Feature readFeature(final Reader reader)
throws IOException {
- try {
- final JsonObject obj = Json.createReader(reader).readObject();
+ final JsonObject json = Json.createReader(reader).readObject();
+
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> map = (Map<String, Object>) getValue(json);
+
+ final Set<String> keySet = map.keySet();
+ keySet.removeAll(Arrays.asList(FEATURE_ID,
+ FEATURE_BUNDLES,
+ FEATURE_FRAMEWORK_PROPERTIES,
+ FEATURE_CONFIGURATIONS,
+ FEATURE_INCLUDES,
+ FEATURE_REQUIREMENTS,
+ FEATURE_CAPABILITIES));
+ if ( !map.containsKey(FEATURE_ID) ) {
+ throw new IOException("Feature id is missing in " + this.location);
+ }
+ final Object idObj = map.get(FEATURE_ID);
+ checkType(FEATURE_ID, idObj, String.class);
+
+ this.feature = new Feature(ArtifactId.fromMvnId(idObj.toString()));
+ this.feature.setLocation(this.location);
+
+ this.readBundles(map);
+ this.readFrameworkProperties(map);
+ this.readConfigurations(map);
+
+ return feature;
+ }
+
+ /**
+ * Read the bundles / start levels section
+ * @param map The map describing the feature
+ * @throws IOException If the json is invalid.
+ */
+ private void readBundles(final Map<String, Object> map) throws IOException {
+ if ( map.containsKey(FEATURE_BUNDLES)) {
+ final Object bundlesObj = map.get(FEATURE_BUNDLES);
+ checkType(FEATURE_BUNDLES, bundlesObj, Map.class);
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> bundles = (Map<String, Object>) bundlesObj;
+ for(final String startLevelVal : bundles.keySet()) {
+ int startLevel = -1;
+ try {
+ startLevel = Integer.valueOf(startLevelVal);
+ } catch ( final NumberFormatException nfe) {
+ throw new IOException(this.exceptionPrefix + "Illegal start level '" + startLevelVal + "'");
+ }
+ final Object val = bundles.get(startLevelVal);
+ final List<Artifact> list = new ArrayList<>();
+ readArtifacts("startLevel", "bundle", list, val);
+ for(final Artifact a : list) {
+ this.feature.getBundles().add(startLevel, a);
+ }
+ }
+ }
+ }
+
+ private void readArtifacts(final String section,
+ final String artifactType,
+ final List<Artifact> artifacts,
+ final Object listObj)
+ throws IOException {
+ checkType(section, listObj, List.class);
+ @SuppressWarnings("unchecked")
+ final List<Object> list = (List<Object>) listObj;
+ for(final Object entry : list) {
+ final Artifact artifact;
+ checkType(artifactType, entry, Map.class, String.class);
+ if ( entry instanceof String ) {
+ artifact = new Artifact(ArtifactId.fromMvnId(entry.toString()));
+ } else {
+ // TODO - Object
+ final Map<String, Object> bundleObj = (Map<String, Object>) entry;
+ artifact = null;
+ }
+ artifacts.add(artifact);
+ }
+ }
+
+ private void readConfigurations(final Map<String, Object> map) throws IOException {
+ if ( map.containsKey(FEATURE_CONFIGURATIONS) ) {
+ // TODO JSONUtil prints out warnings and errors through SystemLogger - we need to catch them
+ // and throw an IOExceptio
+ final List<Config> configs = JSONUtil.readConfigurationsJSON(new TypeConverter(null),
+ 0, "", map);
+ for(final Config c : configs) {
+ if ( c.getEnvironments() != null ) {
+ throw new IOException(this.exceptionPrefix + "Environments for configurations are not supported");
+ }
+ final int pos = c.getPid().indexOf('~');
+ final Configuration config;
+ if ( pos != -1 ) {
+ config = new Configuration(c.getPid().substring(0, pos), c.getPid().substring(pos + 1));
+ } else {
+ config = new Configuration(c.getPid());
+ }
+ this.feature.getConfigurations().add(config);
+ }
+ }
+ }
+
+ private void readFrameworkProperties(final Map<String, Object> map) throws IOException {
+ if ( map.containsKey(FEATURE_FRAMEWORK_PROPERTIES) ) {
+ final Object propsObj= map.get(FEATURE_FRAMEWORK_PROPERTIES);
+ checkType(FEATURE_FRAMEWORK_PROPERTIES, propsObj, Map.class);
+
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> props = (Map<String, Object>) propsObj;
+ for(final Map.Entry<String, Object> entry : props.entrySet()) {
+ checkType("framework property value", entry.getValue(), String.class, Boolean.class, Number.class);
+ if ( feature.getFrameworkProperties().get(entry.getKey()) != null ) {
+ throw new IOException(this.exceptionPrefix + "Duplicate framework property " + entry.getKey());
+ }
+ feature.getFrameworkProperties().put(entry.getKey(), entry.getValue().toString());
+ }
+
+ }
+ }
+
+ private void checkType(final String key, final Object val, Class<?>...types) throws IOException {
+ boolean valid = false;
+ for(final Class<?> c : types) {
+ if ( c.isInstance(val) ) {
+ valid = true;
+ break;
+ }
+ }
+ if ( !valid ) {
+ throw new IOException(this.exceptionPrefix + "Key " + key + " is not one of the allowed types " + Arrays.toString(types) + " : " + val.getClass());
+ }
+ }
- final Set<String> keySet = obj.keySet();
- keySet.remove("id");
- final String id = obj.getString("id");
- final Feature feature = new Feature(ArtifactId.fromMvnUrl("mvn:" + id));
-
- final JsonObject bundles = obj.getJsonObject("bundles");
- return feature;
- } catch ( final IllegalArgumentException e) {
- throw new IOException("Unable to read feature from " + this.location, e);
+ private static Object getValue(final JsonValue value) {
+ switch ( value.getValueType() ) {
+ // type NULL -> return null
+ case NULL : return null;
+ // type TRUE or FALSE -> return boolean
+ case FALSE : return false;
+ case TRUE : return true;
+ // type String -> return String
+ case STRING : return ((JsonString)value).getString();
+ // type Number -> return long or double
+ case NUMBER : final JsonNumber num = (JsonNumber)value;
+ if (num.isIntegral()) {
+ return num.longValue();
+ }
+ return num.doubleValue();
+ // type ARRAY -> return list and call this method for each value
+ case ARRAY : final List<Object> array = new ArrayList<>();
+ for(final JsonValue x : ((JsonArray)value)) {
+ array.add(getValue(x));
+ }
+ return array;
+ // type OBJECT -> return map
+ case OBJECT : final Map<String, Object> map = new HashMap<>();
+ final JsonObject obj = (JsonObject)value;
+ for(final Map.Entry<String, JsonValue> entry : obj.entrySet()) {
+ map.put(entry.getKey(), getValue(entry.getValue()));
+ }
+ return map;
}
+ return null;
}
}