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-slingfeature-maven-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new 8b0fe89 SLING-7860 Enhance slingfeature-maven-plugin to aggregate
multiple features into a single feature
8b0fe89 is described below
commit 8b0fe89d1c9753a3ee1be9958e3dd3daf7746e6f
Author: David Bosschaert <[email protected]>
AuthorDate: Fri Aug 31 13:58:37 2018 +0100
SLING-7860 Enhance slingfeature-maven-plugin to aggregate multiple features
into a single feature
This commit ensures that the order in which non-wildcard features are
processed in the order in which they are listed in the pom.
---
.../feature/maven/mojos/AggregateFeatures.java | 40 +++++++------
.../feature/maven/mojos/AggregateFeaturesTest.java | 67 +++++++++++++++++++++-
.../resources/aggregate-features/dir4/test_t.json | 8 +++
.../resources/aggregate-features/dir4/test_u.json | 11 ++++
.../resources/aggregate-features/dir4/test_v.json | 11 ++++
.../resources/aggregate-features/dir4/test_w.json | 8 +++
.../resources/aggregate-features/dir4/test_x.json | 20 +++++++
.../resources/aggregate-features/dir4/test_y.json | 14 +++++
.../resources/aggregate-features/dir4/test_z.json | 8 +++
9 files changed, 167 insertions(+), 20 deletions(-)
diff --git
a/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
b/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
index 162910b..ca4f6cb 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
@@ -30,7 +30,6 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.repository.RepositorySystem;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.Include;
import org.apache.sling.feature.builder.BuilderContext;
import org.apache.sling.feature.builder.FeatureBuilder;
import org.apache.sling.feature.builder.FeatureExtensionHandler;
@@ -44,17 +43,16 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
-import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
-import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
@@ -92,14 +90,6 @@ public class AggregateFeatures extends AbstractFeatureMojo {
Map<ArtifactId, Feature> featureMap = readFeatures(features,
contextFeatures);
- ArtifactId newFeatureID = new ArtifactId(project.getGroupId(),
project.getArtifactId(),
- project.getVersion(), classifier,
FeatureConstants.PACKAGING_FEATURE);
- Feature newFeature = new Feature(newFeatureID);
- newFeature.getIncludes().addAll(
- featureMap.keySet().stream()
- .map(Include::new)
- .collect(Collectors.toList()));
-
BuilderContext builderContext = new BuilderContext(new
FeatureProvider() {
@Override
public Feature provide(ArtifactId id) {
@@ -124,7 +114,9 @@ public class AggregateFeatures extends AbstractFeatureMojo {
ServiceLoader.load(FeatureExtensionHandler.class).iterator(),
Spliterator.ORDERED), false)
.toArray(FeatureExtensionHandler[]::new));
- Feature result = FeatureBuilder.assemble(newFeature, builderContext);
+ ArtifactId newFeatureID = new ArtifactId(project.getGroupId(),
project.getArtifactId(),
+ project.getVersion(), classifier,
FeatureConstants.PACKAGING_FEATURE);
+ Feature result = FeatureBuilder.assemble(newFeatureID, builderContext,
featureMap.values().toArray(new Feature[] {}));
try (FileWriter fileWriter = new FileWriter(new
File(aggregatedFeaturesDir, classifier + ".json"))) {
FeatureJSONWriter.write(fileWriter, result);
@@ -134,7 +126,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
}
private Map<ArtifactId, Feature> readFeatures(Collection<FeatureConfig>
featureConfigs, Map<ArtifactId, Feature> contextFeatures) throws
MojoExecutionException {
- Map<ArtifactId, Feature> featureMap = new HashMap<>();
+ Map<ArtifactId, Feature> featureMap = new LinkedHashMap<>();
try {
for (FeatureConfig fc : featureConfigs) {
@@ -189,6 +181,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
}
private void readFeaturesFromDirectory(FeatureConfig fc, Map<ArtifactId,
Feature> featureMap) throws IOException {
+ Map<String,Feature> readFeatures = new HashMap<>();
Map<String,String> includes = new HashMap<>();
Map<String,String> excludes = new HashMap<>();
@@ -202,7 +195,7 @@ public class AggregateFeatures extends AbstractFeatureMojo {
nextFile:
for (File f : new File(fc.location).listFiles()) {
// First check that it is allowed as part of the includes
- boolean matchesIncludes = includes.size() == 0;
+ boolean matchesIncludes = fc.includes.size() == 0;
for (Iterator<String> it = includes.values().iterator();
it.hasNext(); ) {
String inc = it.next();
@@ -232,8 +225,19 @@ public class AggregateFeatures extends AbstractFeatureMojo
{
}
Feature feat = readFeatureFromFile(f);
- featureMap.put(feat.getId(), feat);
+ readFeatures.put(f.getName(), feat);
+ }
+
+ // Ordering:
+ // put the read features in the main featureMap, order the non-globbed
ones as specified in the plugin
+ for (String inc : fc.includes) {
+ Feature feat = readFeatures.remove(inc);
+ if (feat != null) {
+ featureMap.put(feat.getId(), feat);
+ }
}
+ // Put all the remaining features on the map
+ readFeatures.values().stream().forEach(f -> featureMap.put(f.getId(),
f));
// If there are any non-glob includes/excludes left, fail as the
plugin is then incorrectly configured
for (Map.Entry<String,String> i : includes.entrySet()) {
@@ -281,8 +285,8 @@ public class AggregateFeatures extends AbstractFeatureMojo {
public static class FeatureConfig {
// If the configuration is a directory
String location;
- Set<String> includes = new HashSet<>();
- Set<String> excludes = new HashSet<>();
+ List<String> includes = new ArrayList<>();
+ List<String> excludes = new ArrayList<>();
// If the configuration is an artifact
String groupId;
diff --git
a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
index 8e7b90e..72e9523 100644
---
a/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
+++
b/src/test/java/org/apache/sling/feature/maven/mojos/AggregateFeaturesTest.java
@@ -104,8 +104,8 @@ public class AggregateFeaturesTest {
fc.setType("slingfeature");
fc.setClassifier("clf1");
- assertEquals(new HashSet<>(Arrays.asList("i1", "i2")), fc.includes);
- assertEquals(Collections.singleton("e1"), fc.excludes);
+ assertEquals(Arrays.asList("i1", "i2"), fc.includes);
+ assertEquals(Collections.singletonList("e1"), fc.excludes);
assertEquals("loc1", fc.location);
assertEquals("gid1", fc.groupId);
@@ -304,6 +304,69 @@ public class AggregateFeaturesTest {
}
@Test
+ public void testIncludeOrdering() throws Exception {
+ File featuresDir = new File(
+ getClass().getResource("/aggregate-features/dir4").getFile());
+
+ FeatureConfig fc1 = new FeatureConfig();
+ fc1.setLocation(featuresDir.getAbsolutePath());
+ fc1.setIncludes("test_x.json");
+
+ FeatureConfig fc2 = new FeatureConfig();
+ fc2.setLocation(featuresDir.getAbsolutePath());
+ fc2.setIncludes("test_u.json");
+ fc2.setIncludes("test_y.json");
+ fc2.setIncludes("test_v.json");
+ fc2.setIncludes("test_z.json");
+
+ FeatureConfig fc3 = new FeatureConfig();
+ fc3.setLocation(featuresDir.getAbsolutePath());
+ fc3.setIncludes("test_t.json");
+
+ Build mockBuild = Mockito.mock(Build.class);
+ Mockito.when(mockBuild.getDirectory()).thenReturn(tempDir.toString());
+
+ MavenProject mockProj = Mockito.mock(MavenProject.class);
+ Mockito.when(mockProj.getBuild()).thenReturn(mockBuild);
+ Mockito.when(mockProj.getGroupId()).thenReturn("g");
+ Mockito.when(mockProj.getArtifactId()).thenReturn("a");
+ Mockito.when(mockProj.getVersion()).thenReturn("999");
+
+ AggregateFeatures af = new AggregateFeatures();
+ af.classifier = "agg";
+ af.features = Arrays.asList(fc1, fc2, fc3);
+ af.project = mockProj;
+
+ af.execute();
+
+ File expectedFile = new File(tempDir.toFile(),
FeatureConstants.FEATURE_PROCESSED_LOCATION + "/agg.json");
+ try (Reader fr = new FileReader(expectedFile)) {
+ Feature genFeat = FeatureJSONReader.read(fr, null);
+ ArtifactId id = genFeat.getId();
+
+ assertEquals("g", id.getGroupId());
+ assertEquals("a", id.getArtifactId());
+ assertEquals("999", id.getVersion());
+ assertEquals("slingfeature", id.getType());
+ assertEquals("agg", id.getClassifier());
+
+ Map<String, Dictionary<String, Object>> expectedConfigs = new
HashMap<>();
+ expectedConfigs.put("t.pid", new
Hashtable<>(Collections.singletonMap("t", "t")));
+ expectedConfigs.put("u.pid", new
Hashtable<>(Collections.singletonMap("u", "u")));
+ expectedConfigs.put("v.pid", new
Hashtable<>(Collections.singletonMap("v", "v")));
+ expectedConfigs.put("x.pid", new
Hashtable<>(Collections.singletonMap("x", "x")));
+ expectedConfigs.put("y.pid", new
Hashtable<>(Collections.singletonMap("y", "y")));
+ expectedConfigs.put("z.pid", new
Hashtable<>(Collections.singletonMap("z", "z")));
+
+ Map<String, Dictionary<String, Object>> actualConfigs = new
HashMap<>();
+ for (org.apache.sling.feature.Configuration conf :
genFeat.getConfigurations()) {
+ actualConfigs.put(conf.getPid(), conf.getProperties());
+ }
+ assertEquals(expectedConfigs, actualConfigs);
+ }
+ }
+
+ @Test
public void testReadFeatureFromArtifact() throws Exception {
File featureFile = new File(
getClass().getResource("/aggregate-features/test_x.json").getFile());
diff --git a/src/test/resources/aggregate-features/dir4/test_t.json
b/src/test/resources/aggregate-features/dir4/test_t.json
new file mode 100644
index 0000000..f459d53
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_t.json
@@ -0,0 +1,8 @@
+{
+ "id":"test:t:9.9.9",
+ "configurations": {
+ "t.pid": {
+ "t": "t"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_u.json
b/src/test/resources/aggregate-features/dir4/test_u.json
new file mode 100644
index 0000000..9f8ffb5
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_u.json
@@ -0,0 +1,11 @@
+{
+ "id":"test:u:9.9.9",
+ "configurations": {
+ "u.pid": {
+ "u": "u"
+ },
+ "y.pid": {
+ "y": "u"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_v.json
b/src/test/resources/aggregate-features/dir4/test_v.json
new file mode 100644
index 0000000..78269af
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_v.json
@@ -0,0 +1,11 @@
+{
+ "id":"test:v:9.9.9",
+ "configurations": {
+ "v.pid": {
+ "v": "v"
+ },
+ "z.pid": {
+ "z": "v"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_w.json
b/src/test/resources/aggregate-features/dir4/test_w.json
new file mode 100644
index 0000000..8cf9e79
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_w.json
@@ -0,0 +1,8 @@
+{
+ "id":"test:w:9.9.9",
+ "configurations": {
+ "some.pid": {
+ "x": "z"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_x.json
b/src/test/resources/aggregate-features/dir4/test_x.json
new file mode 100644
index 0000000..8df875b
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_x.json
@@ -0,0 +1,20 @@
+{
+ "id":"test:x:9.9.9",
+ "configurations": {
+ "t.pid": {
+ "t": "x"
+ },
+ "v.pid": {
+ "v": "x"
+ },
+ "x.pid": {
+ "x": "x"
+ },
+ "y.pid": {
+ "y": "x"
+ },
+ "z.pid": {
+ "z": "x"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_y.json
b/src/test/resources/aggregate-features/dir4/test_y.json
new file mode 100644
index 0000000..4ce4e5e
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_y.json
@@ -0,0 +1,14 @@
+{
+ "id":"test:y:9.9.9",
+ "configurations": {
+ "v.pid": {
+ "v": "y"
+ },
+ "y.pid": {
+ "y": "y"
+ },
+ "z.pid": {
+ "z": "y"
+ }
+ }
+}
diff --git a/src/test/resources/aggregate-features/dir4/test_z.json
b/src/test/resources/aggregate-features/dir4/test_z.json
new file mode 100644
index 0000000..95103c5
--- /dev/null
+++ b/src/test/resources/aggregate-features/dir4/test_z.json
@@ -0,0 +1,8 @@
+{
+ "id":"test:z:1.0.1",
+ "configurations": {
+ "z.pid": {
+ "z": "z"
+ }
+ }
+}