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 a7af344 SLING-7779 API Region support for the Sling Feature Model
a7af344 is described below
commit a7af344de677f0a764ea8d43dac7fd1af3161d1d
Author: David Bosschaert <[email protected]>
AuthorDate: Wed Oct 31 12:34:45 2018 +0000
SLING-7779 API Region support for the Sling Feature Model
Initial commit for the apiregions extension, which transforms region in
formation in feature models into runtime-accessed resources.
---
featuremodel/feature-extension-apiregions/pom.xml | 61 ++++++++++
.../whitelisting/extensions/APIRegionHandler.java | 75 +++++++++++++
.../whitelisting/extensions/AbstractHandler.java | 58 ++++++++++
.../extensions/BundleArtifactFeatureHandler.java | 123 +++++++++++++++++++++
.../extensions/BundleMappingHandler.java | 63 +++++++++++
.../org.apache.sling.feature.builder.MergeHandler | 1 +
...apache.sling.feature.builder.PostProcessHandler | 2 +
7 files changed, 383 insertions(+)
diff --git a/featuremodel/feature-extension-apiregions/pom.xml
b/featuremodel/feature-extension-apiregions/pom.xml
new file mode 100644
index 0000000..0fb4d4b
--- /dev/null
+++ b/featuremodel/feature-extension-apiregions/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?><!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>34</version>
+ <relativePath />
+ </parent>
+
+ <artifactId>org.apache.sling.feature.extension.apiregions</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <name>Sling Featuremodel - API Regions Exension</name>
+
+ <properties>
+ <jdk.version>8</jdk.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+
<exclude>src/main/resources/META-INF/services/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-json_1.0_spec</artifactId>
+ <version>1.0-alpha-1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.feature</artifactId>
+ <version>0.1.3-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git
a/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/APIRegionHandler.java
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/APIRegionHandler.java
new file mode 100644
index 0000000..1756412
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/APIRegionHandler.java
@@ -0,0 +1,75 @@
+/*
+ * 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.whitelisting.extensions;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.HandlerContext;
+import org.apache.sling.feature.builder.MergeHandler;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonValue;
+import javax.json.stream.JsonGenerator;
+
+public class APIRegionHandler implements MergeHandler {
+
+ @Override
+ public boolean canMerge(Extension extension) {
+ return "api-regions".equals(extension.getName());
+ }
+
+ @Override
+ public void merge(HandlerContext context, Feature target, Feature source,
Extension targetEx, Extension sourceEx) {
+ if (!targetEx.getName().equals("api-regions") ||
!sourceEx.getName().equals("api-regions"))
+ return;
+
+ JsonReader srcJR = Json.createReader(new
StringReader(sourceEx.getJSON()));
+ JsonArray srcJA = srcJR.readArray();
+
+ JsonReader tgtJR = Json.createReader(new
StringReader(targetEx.getJSON()));
+ JsonArray tgtJA = tgtJR.readArray();
+
+ StringWriter sw = new StringWriter();
+ JsonGenerator gen = Json.createGenerator(sw);
+ gen.writeStartArray();
+ for (JsonValue jv : tgtJA) {
+ gen.write(jv);
+ }
+
+ for (int i=0; i < srcJA.size(); i++) {
+ gen.writeStartObject();
+ JsonObject jo = srcJA.getJsonObject(i);
+ for (Map.Entry<String, JsonValue> entry : jo.entrySet()) {
+ gen.write(entry.getKey(), entry.getValue());
+ }
+ gen.write("org-feature", source.getId().toMvnId());
+ gen.writeEnd();
+ }
+
+ gen.writeEnd();
+ gen.close();
+
+ targetEx.setJSON(sw.toString());
+ }
+}
diff --git
a/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/AbstractHandler.java
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/AbstractHandler.java
new file mode 100644
index 0000000..ddc2d5e
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/AbstractHandler.java
@@ -0,0 +1,58 @@
+/*
+ * 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.whitelisting.extensions;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Date;
+import java.util.Properties;
+
+class AbstractHandler {
+ private static final String FILE_PREFIX = "whitelisting.";
+
+ protected File getDataFile(String name) throws IOException {
+ Path p = Files.createTempFile(FILE_PREFIX, name);
+ File f = p.toFile();
+ f.deleteOnExit();
+
+ System.setProperty(FILE_PREFIX + name, f.getCanonicalPath());
+ return f;
+ }
+
+ protected Properties loadProperties(File file) throws IOException,
FileNotFoundException {
+ Properties map = new Properties();
+ if (file.exists()) {
+ try (InputStream is = new FileInputStream(file)) {
+ map.load(is);
+ }
+ }
+ return map;
+ }
+
+ protected void storeProperties(Properties properties, File file) throws
IOException, FileNotFoundException {
+ try (OutputStream os = new FileOutputStream(file)) {
+ properties.store(os, "Generated at " + new Date());
+ }
+ }
+}
diff --git
a/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleArtifactFeatureHandler.java
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleArtifactFeatureHandler.java
new file mode 100644
index 0000000..79558c4
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleArtifactFeatureHandler.java
@@ -0,0 +1,123 @@
+/*
+ * 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.whitelisting.extensions;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.HandlerContext;
+import org.apache.sling.feature.builder.PostProcessHandler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonValue;
+
+public class BundleArtifactFeatureHandler extends AbstractHandler implements
PostProcessHandler {
+ @Override
+ public void postProcess(HandlerContext context, Feature feature, Extension
extension) {
+ if (!"api-regions".equals(extension.getName()))
+ return;
+
+ try {
+ writeBundleToFeatureMap(feature);
+ writeFeatureToRegionAndPackageMap(feature, extension);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void writeBundleToFeatureMap(Feature feature) throws IOException {
+ File bundlesFile = getDataFile("bundles.properties");
+ Properties map = loadProperties(bundlesFile);
+
+ for (Artifact b : feature.getBundles()) {
+ String id = b.getId().toMvnId().trim();
+
+ String fid = b.getMetadata().get("org-feature");
+ if (fid == null)
+ fid = feature.getId().toMvnId().trim();
+
+ String m = map.getProperty(id);
+ if (m != null) {
+ List<String> l = Arrays.asList(m.split(","));
+ if (!l.contains(fid))
+ m = m.trim() + "," + fid;
+ } else {
+ m = fid;
+ }
+ map.put(id, m);
+ }
+
+ storeProperties(map, bundlesFile);
+ }
+
+ private void writeFeatureToRegionAndPackageMap(Feature feature, Extension
extension) throws IOException {
+ JsonReader jr = Json.createReader(new
StringReader(extension.getJSON()));
+ JsonArray ja = jr.readArray();
+
+ File featuresFile = getDataFile("features.properties");
+ File regionsFile = getDataFile("regions.properties");
+ Properties frMap = loadProperties(featuresFile);
+ Properties rpMap = loadProperties(regionsFile);
+
+ for (JsonValue jv : ja) {
+ if (jv instanceof JsonObject) {
+ JsonObject jo = (JsonObject) jv;
+ String fid = jo.getString("org-feature");
+ if (fid == null)
+ fid = feature.getId().toMvnId();
+
+ Set<String> regionSet = new HashSet<>();
+ String regions = frMap.getProperty(fid);
+ if (regions != null) {
+ regionSet.addAll(Arrays.asList(regions.split(",")));
+ }
+ String region = jo.getString("name");
+ regionSet.add(region);
+
+ frMap.put(fid,
regionSet.stream().collect(Collectors.joining(",")));
+
+ Set<String> packageSet = new HashSet<>();
+ String packages = rpMap.getProperty(region);
+ if (packages != null) {
+ packageSet.addAll(Arrays.asList(packages.split(",")));
+ }
+ JsonArray eja = jo.getJsonArray("exports");
+ for (int i=0; i < eja.size(); i++) {
+ packageSet.add(eja.getString(i));
+ }
+ rpMap.put(region,
packageSet.stream().collect(Collectors.joining(",")));
+ }
+ }
+
+ storeProperties(frMap, featuresFile);
+ storeProperties(rpMap, regionsFile);
+ }
+}
diff --git
a/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleMappingHandler.java
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleMappingHandler.java
new file mode 100644
index 0000000..1338e88
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/java/org/apache/sling/feature/whitelisting/extensions/BundleMappingHandler.java
@@ -0,0 +1,63 @@
+/*
+ * 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.whitelisting.extensions;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.HandlerContext;
+import org.apache.sling.feature.builder.PostProcessHandler;
+import org.osgi.framework.Constants;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.jar.JarFile;
+
+public class BundleMappingHandler extends AbstractHandler implements
PostProcessHandler {
+ @Override
+ public void postProcess(HandlerContext context, Feature feature, Extension
extension) {
+ if (!"api-regions".equals(extension.getName()))
+ return;
+
+
+ try {
+ File idBSNFile = getDataFile("idbsnver.properties");
+ Properties map = loadProperties(idBSNFile);
+
+ for (Artifact b : feature.getBundles()) {
+ File f = context.getArtifactProvider().provide(b.getId());
+
+ try (JarFile jf = new JarFile(f)) {
+ String bsn =
jf.getManifest().getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+ if (bsn == null)
+ continue;
+
+ String ver =
jf.getManifest().getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+ if (ver == null)
+ ver = "0.0.0";
+
+ map.put(b.getId().toMvnId(), bsn.trim() + "~" +
ver.trim());
+ }
+ }
+
+ storeProperties(map, idBSNFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git
a/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.MergeHandler
b/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.MergeHandler
new file mode 100644
index 0000000..359d2fa
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.MergeHandler
@@ -0,0 +1 @@
+org.apache.sling.feature.whitelisting.extensions.APIRegionHandler
diff --git
a/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler
b/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler
new file mode 100644
index 0000000..22b67f7
--- /dev/null
+++
b/featuremodel/feature-extension-apiregions/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler
@@ -0,0 +1,2 @@
+org.apache.sling.feature.whitelisting.extensions.BundleMappingHandler
+org.apache.sling.feature.whitelisting.extensions.BundleArtifactFeatureHandler