You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by pa...@apache.org on 2020/01/17 20:27:51 UTC
[sling-org-apache-sling-feature-extension-apiregions] 01/01:
SLING-9007: Add launcher spi that generates the property files.
This is an automated email from the ASF dual-hosted git repository.
pauls pushed a commit to branch SLING-9007-2
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-extension-apiregions.git
commit e4de12eaba33cd8033ca6b239efe15d27d02502b
Author: Karl Pauls <kp...@adobe.com>
AuthorDate: Fri Jan 17 21:27:30 2020 +0100
SLING-9007: Add launcher spi that generates the property files.
---
pom.xml | 6 +
.../apiregions/APIRegionMergeHandler.java | 16 ++-
.../apiregions/launcher/LauncherProperties.java | 160 +++++++++++++++++++++
.../apiregions/launcher/RegionLauncher.java | 71 +++++++++
.../launcher/RegionLauncherExtension.java | 54 +++++++
...apache.sling.feature.builder.PostProcessHandler | 2 -
.../org.apache.sling.feature.launcher.spi.Launcher | 1 +
...eature.launcher.spi.extensions.ExtensionHandler | 1 +
8 files changed, 304 insertions(+), 7 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9debc0b..5103f99 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,12 @@
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.feature.launcher</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
<!-- Testing -->
<dependency>
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java b/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
index 2ad9647..a544954 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/APIRegionMergeHandler.java
@@ -69,17 +69,23 @@ public class APIRegionMergeHandler implements MergeHandler {
targetRegion.add(srcExp);
}
}
- LinkedHashSet<ArtifactId> origins = new LinkedHashSet<>(Arrays.asList(targetRegion.getFeatureOrigins()));
- origins.add(source.getId());
- targetRegion.setFeatureOrigins(origins.toArray(new ArtifactId[0]));
+ LinkedHashSet<ArtifactId> targetOrigins = new LinkedHashSet<>(Arrays.asList(targetRegion.getFeatureOrigins()));
+ LinkedHashSet<ArtifactId> sourceOrigins = new LinkedHashSet<>(Arrays.asList(sourceRegion.getFeatureOrigins()));
+ if (sourceOrigins.isEmpty()) {
+ sourceOrigins.add(source.getId());
+ }
+ targetOrigins.addAll(sourceOrigins);
+ targetRegion.setFeatureOrigins(targetOrigins.toArray(new ArtifactId[0]));
}
}
// If there are any remaining regions in the src extension, process them now
for (final ApiRegion r : srcRegions.listRegions()) {
LinkedHashSet<ArtifactId> origins = new LinkedHashSet<>(Arrays.asList(r.getFeatureOrigins()));
- origins.add(source.getId());
- r.setFeatureOrigins(origins.toArray(new ArtifactId[0]));
+ if (origins.isEmpty()) {
+ origins.add(source.getId());
+ r.setFeatureOrigins(origins.toArray(new ArtifactId[0]));
+ }
if (!targetRegions.add(r)) {
throw new IllegalStateException("Duplicate region " + r.getName());
}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/LauncherProperties.java b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/LauncherProperties.java
new file mode 100644
index 0000000..516ed09
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/LauncherProperties.java
@@ -0,0 +1,160 @@
+/*
+ * 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.extension.apiregions.launcher;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.ArtifactProvider;
+import org.apache.sling.feature.extension.apiregions.api.ApiExport;
+import org.apache.sling.feature.extension.apiregions.api.ApiRegion;
+import org.apache.sling.feature.extension.apiregions.api.ApiRegions;
+import org.apache.sling.feature.io.IOUtils;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+public class LauncherProperties
+{
+ public static Properties getBundleIDtoBSNandVersionMap(Feature app, ArtifactProvider artifactProvider) {
+ Map<ArtifactId, String> map = new HashMap<>();
+
+ for (Artifact bundle : app.getBundles())
+ {
+ map.computeIfAbsent(bundle.getId(), id ->
+ {
+ try(JarFile jarFile = IOUtils.getJarFileFromURL(artifactProvider.provide(id), true, null)) {
+ Attributes manifest = jarFile.getManifest().getMainAttributes();
+ String bsn = manifest.getValue(Constants.BUNDLE_SYMBOLICNAME);
+ if (bsn != null && !bsn.trim().isEmpty())
+ {
+ return bsn.trim() + "~" + Version.parseVersion(manifest.getValue(Constants.BUNDLE_VERSION));
+ }
+ else {
+ return null;
+ }
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ });
+ }
+
+ Properties result = new Properties();
+
+ for (Map.Entry<ArtifactId, String> entry : map.entrySet()) {
+ result.setProperty(entry.getKey().toMvnId(), entry.getValue());
+ }
+
+ return result;
+ }
+
+ public static Properties getBundleIDtoFeaturesMap(Feature app) {
+ Map<ArtifactId, Set<ArtifactId>> map = new HashMap<>();
+
+ for (Artifact bundle : app.getBundles())
+ {
+ map.compute(bundle.getId(), (id, features) ->
+ {
+ if (features == null)
+ {
+ features = new HashSet<>();
+ }
+ features.addAll(Arrays.asList(bundle.getFeatureOrigins()));
+ return features;
+ });
+ }
+
+ Properties result = new Properties();
+
+ for (Map.Entry<ArtifactId, Set<ArtifactId>> entry : map.entrySet()) {
+ result.setProperty(entry.getKey().toMvnId(), entry.getValue().stream().map(ArtifactId::toMvnId).collect(Collectors.joining(",")));
+ }
+
+ return result;
+ }
+
+ public static Properties getFeatureIDtoRegionsMap(ApiRegions regions) {
+ Map<ArtifactId, Set<String>> map = new HashMap<>();
+
+ for (ApiRegion region : regions.listRegions())
+ {
+ for (ArtifactId featureId : region.getFeatureOrigins()) {
+ map.compute(featureId, (id, regionNames) -> {
+ if (regionNames == null) {
+ regionNames = new HashSet<>();
+ }
+ regionNames.add(region.getName());
+ return regionNames;
+ });
+ }
+ }
+
+ Properties result = new Properties();
+
+ for (Map.Entry<ArtifactId, Set<String>> entry : map.entrySet()) {
+ result.setProperty(entry.getKey().toMvnId(), String.join(",", entry.getValue()));
+ }
+
+ return result;
+ }
+
+ public static Properties getRegionNametoPackagesMap(ApiRegions regions) {
+ Map<String, Set<String>> map = new HashMap<>();
+
+ for (ApiRegion region : regions.listRegions())
+ {
+ for (ApiExport export : region.listExports()) {
+ map.compute(region.getName(), (name, exports) -> {
+ if (exports == null) {
+ exports = new HashSet<>();
+ }
+ exports.add(export.getName());
+ return exports;
+ });
+ }
+ }
+
+ Properties result = new Properties();
+
+ for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
+ result.setProperty(entry.getKey(), String.join(",", entry.getValue()));
+ }
+
+ return result;
+ }
+
+
+ public static void save(Properties properties, File file) throws IOException {
+ try (FileOutputStream output = new FileOutputStream(file))
+ {
+ properties.store(output, "");
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncher.java b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncher.java
new file mode 100644
index 0000000..850581d
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncher.java
@@ -0,0 +1,71 @@
+/*
+ * 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.extension.apiregions.launcher;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.builder.ArtifactProvider;
+import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+import org.apache.sling.feature.launcher.spi.LauncherRunContext;
+
+public class RegionLauncher extends FrameworkLauncher
+{
+ public static final String IDBSNVER_FILENAME = "idbsnver.properties";
+ public static final String BUNDLE_FEATURE_FILENAME = "bundles.properties";
+
+ @Override
+ public void prepare(LauncherPrepareContext context, ArtifactId frameworkId, Feature app) throws Exception
+ {
+ super.prepare(context, frameworkId, app);
+
+ ArtifactProvider artifactProvider = id ->
+ {
+ try
+ {
+ return context.getArtifactFile(id);
+ }
+ catch (IOException e)
+ {
+ throw new UncheckedIOException(e);
+ }
+ };
+
+
+ final File base = File.createTempFile("apiregions", ".properties");
+ base.delete();
+ base.mkdirs();
+ File idbsnverFile = new File(base, IDBSNVER_FILENAME);
+ File bundlesFile = new File(base, BUNDLE_FEATURE_FILENAME);
+
+ LauncherProperties.save(LauncherProperties.getBundleIDtoBSNandVersionMap(app, artifactProvider), idbsnverFile);
+ LauncherProperties.save(LauncherProperties.getBundleIDtoFeaturesMap(app), bundlesFile);
+
+ app.getFrameworkProperties().put("sling.feature.apiregions.resource." + IDBSNVER_FILENAME, idbsnverFile.toURI().toURL().toString());
+ app.getFrameworkProperties().put("sling.feature.apiregions.resource." + BUNDLE_FEATURE_FILENAME, bundlesFile.toURI().toURL().toString());
+ }
+
+ @Override
+ public int run(LauncherRunContext context, ClassLoader cl) throws Exception
+ {
+ return super.run(context, cl);
+ }
+}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncherExtension.java b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncherExtension.java
new file mode 100644
index 0000000..7a180a7
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/launcher/RegionLauncherExtension.java
@@ -0,0 +1,54 @@
+/*
+ * 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.extension.apiregions.launcher;
+
+import java.io.File;
+import javax.json.JsonArray;
+
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.extension.apiregions.api.ApiRegions;
+import org.apache.sling.feature.launcher.spi.extensions.ExtensionContext;
+import org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler;
+
+public class RegionLauncherExtension implements ExtensionHandler
+{
+ public static final String FEATURE_REGION_FILENAME = "features.properties";
+ public static final String REGION_PACKAGE_FILENAME = "regions.properties";
+
+ @Override
+ public boolean handle(ExtensionContext extensionContext, Extension extension) throws Exception
+ {
+ if (!extension.getName().equals(ApiRegions.EXTENSION_NAME))
+ return false;
+
+ final File base = File.createTempFile("apiregions", ".properties");
+ base.delete();
+ base.mkdirs();
+ File featuresFile = new File(base, FEATURE_REGION_FILENAME);
+ File regionsFile = new File(base, REGION_PACKAGE_FILENAME);
+
+ final ApiRegions apiRegions = ApiRegions.parse((JsonArray) extension.getJSONStructure());
+
+ LauncherProperties.save(LauncherProperties.getFeatureIDtoRegionsMap(apiRegions), featuresFile);
+ LauncherProperties.save(LauncherProperties.getRegionNametoPackagesMap(apiRegions), regionsFile);
+
+ extensionContext.addFrameworkProperty("sling.feature.apiregions.resource." + FEATURE_REGION_FILENAME, featuresFile.toURI().toURL().toString());
+ extensionContext.addFrameworkProperty("sling.feature.apiregions.resource." + REGION_PACKAGE_FILENAME, regionsFile.toURI().toURL().toString());
+
+ return true;
+ }
+}
diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler b/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler
deleted file mode 100644
index 1bf6138..0000000
--- a/src/main/resources/META-INF/services/org.apache.sling.feature.builder.PostProcessHandler
+++ /dev/null
@@ -1,2 +0,0 @@
-org.apache.sling.feature.extension.apiregions.BundleMappingHandler
-org.apache.sling.feature.extension.apiregions.BundleArtifactFeatureHandler
diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher b/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher
new file mode 100644
index 0000000..887412d
--- /dev/null
+++ b/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.Launcher
@@ -0,0 +1 @@
+org.apache.sling.feature.extension.apiregions.launcher.RegionLauncher
\ No newline at end of file
diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler b/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler
new file mode 100644
index 0000000..89e2efc
--- /dev/null
+++ b/src/main/resources/META-INF/services/org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler
@@ -0,0 +1 @@
+org.apache.sling.feature.extension.apiregions.launcher.RegionLauncherExtension
\ No newline at end of file