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 caaf453 SLING-7860 Enhance slingfeature-maven-plugin to aggregate
multiple features into a single feature
caaf453 is described below
commit caaf453722578fd08997a5fbaad9212b0d32e279
Author: David Bosschaert <[email protected]>
AuthorDate: Tue Aug 28 15:07:32 2018 +0100
SLING-7860 Enhance slingfeature-maven-plugin to aggregate multiple features
into a single feature
Initial code for supporting this.
---
.../feature/maven/mojos/AggregateFeatures.java | 207 +++++++++++++++++++++
.../feature/maven/mojos/GenerateResources.java | 33 +---
.../{GenerateResources.java => Substitution.java} | 44 +----
.../META-INF/m2e/lifecycle-mapping-metadata.xml | 1 +
.../feature/maven/mojos/GenerateResourceTest.java | 4 +-
5 files changed, 217 insertions(+), 72 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
new file mode 100644
index 0000000..07ed674
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/AggregateFeatures.java
@@ -0,0 +1,207 @@
+/*
+ * 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.maven.mojos;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+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.FeatureProvider;
+import org.apache.sling.feature.io.json.FeatureJSONReader;
+import org.apache.sling.feature.io.json.FeatureJSONWriter;
+import org.apache.sling.feature.maven.FeatureConstants;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Aggregate multiple features into a single one.
+ */
+@Mojo(name = "aggregate-features",
+ defaultPhase = LifecyclePhase.PACKAGE,
+ requiresDependencyResolution = ResolutionScope.TEST,
+ threadSafe = true
+)
+public class AggregateFeatures extends AbstractFeatureMojo {
+ @Parameter(required=false)
+ private String classifier;
+
+ @Parameter
+ private List<FeatureConfig> features;
+
+ @Parameter(property = "project.remoteArtifactRepositories", readonly =
true, required = true)
+ protected List<ArtifactRepository> remoteRepositories;
+
+ @Parameter(property = "localRepository", readonly = true, required = true)
+ protected ArtifactRepository localRepository;
+
+ @Component
+ private RepositorySystem repoSystem;
+
+ @Component
+ private ArtifactResolver artifactResolver;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ Map<ArtifactId, Feature> featureMap = readFeatures(features);
+
+ 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()));
+
+ Feature result = FeatureBuilder.assemble(newFeature, new
BuilderContext(new FeatureProvider() {
+ @Override
+ public Feature provide(ArtifactId id) {
+ return featureMap.get(id);
+ }
+ }));
+
+ File aggregatedFeaturesDir = new
File(project.getBuild().getDirectory(),
FeatureConstants.FEATURE_PROCESSED_LOCATION);
+ aggregatedFeaturesDir.mkdirs();
+
+ try (FileWriter fileWriter = new FileWriter(new
File(aggregatedFeaturesDir, classifier + ".json"))) {
+ FeatureJSONWriter.write(fileWriter, result);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Problem writing assembled
feature", e);
+ }
+ }
+
+ private Map<ArtifactId, Feature> readFeatures(Collection<FeatureConfig>
featureConfigs) throws MojoExecutionException {
+ Map<ArtifactId, Feature> featureMap = new HashMap<>();
+
+ try {
+ for (FeatureConfig fc : featureConfigs) {
+ if (fc.location != null) {
+ readFeaturesFromDirectory(fc, featureMap);
+ } else if (fc.artifactId != null) {
+ readFeaturesFromArtifact(fc, featureMap);
+ }
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException("Problem reading feature", e);
+ }
+
+ return featureMap;
+ }
+
+ private void readFeaturesFromArtifact(FeatureConfig fc, Map<ArtifactId,
Feature> featureMap) throws IOException {
+ Artifact art = repoSystem.createArtifactWithClassifier(
+ fc.groupId, fc.artifactId, fc.version, fc.type, fc.classifier);
+
+ ArtifactResolutionRequest resReq = new ArtifactResolutionRequest()
+ .setArtifact(art)
+ .setLocalRepository(localRepository)
+ .setRemoteRepositories(remoteRepositories);
+ artifactResolver.resolve(resReq);
+
+ File artFile = art.getFile();
+ readFeatureFromFile(artFile, featureMap);
+ }
+
+ private void readFeaturesFromDirectory(FeatureConfig fc, Map<ArtifactId,
Feature> featureMap) throws IOException {
+ for (File f : new File(fc.location).listFiles()) {
+ readFeatureFromFile(f, featureMap);
+ }
+ }
+
+ private void readFeatureFromFile(File f, Map<ArtifactId, Feature>
featureMap) throws IOException {
+ String content = new String(Files.readAllBytes(f.toPath()));
+ content = Substitution.replaceMavenVars(project, content);
+ Feature feat = FeatureJSONReader.read(new StringReader(content), null,
FeatureJSONReader.SubstituteVariables.NONE);
+ featureMap.put(feat.getId(), feat);
+ }
+
+ public static class FeatureConfig {
+ // If the configuration is a directory
+ String location;
+ Set<String> includes = new HashSet<>();
+ Set<String> excludes = new HashSet<>();
+
+ // If the configuration is an artifact
+ String groupId;
+ String artifactId;
+ String version;
+ String type;
+ String classifier;
+
+ public void setLocation(String loc) {
+ location = loc;
+ }
+
+ public void setIncludes(String i) {
+ includes.add(i);
+ }
+
+ public void setExcludes(String e) {
+ excludes.add(e);
+ }
+
+ public void setGroupId(String gid) {
+ groupId = gid;
+ }
+
+ public void setArtifactId(String aid) {
+ artifactId = aid;
+ }
+
+ public void setVersion(String ver) {
+ version = ver;
+ }
+
+ public void setType(String t) {
+ type = t;
+ }
+
+ public void setClassifier(String clf) {
+ classifier = clf;
+ }
+
+ @Override
+ public String toString() {
+ return "FeatureConfig [location=" + location + ", includes=" +
includes + ", excludes=" + excludes + ", groupId="
+ + groupId + ", artifactId=" + artifactId + ", version=" +
version + ", type=" + type + ", classifier="
+ + classifier + "]";
+ }
+ }
+}
diff --git
a/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
b/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
index ca78cbd..0fe467b 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
@@ -22,12 +22,10 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.apache.maven.project.MavenProject;
+import org.apache.sling.feature.maven.FeatureConstants;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
-import java.nio.file.Files;
@Mojo(
name = "generate-resources",
@@ -44,7 +42,7 @@ public class GenerateResources extends AbstractFeatureMojo {
if (files == null)
return;
- File processedFeaturesDir = new
File(project.getBuild().getDirectory(), "features/processed");
+ File processedFeaturesDir = new
File(project.getBuild().getDirectory(),
FeatureConstants.FEATURE_PROCESSED_LOCATION);
processedFeaturesDir.mkdirs();
for (File f : files) {
@@ -53,35 +51,10 @@ public class GenerateResources extends AbstractFeatureMojo {
}
try {
- substituteVars(project, f, processedFeaturesDir);
+ Substitution.substituteMavenVars(project, f,
processedFeaturesDir);
} catch (IOException e) {
throw new MojoExecutionException("Problem processing feature
file " + f.getAbsolutePath(), e);
}
}
}
-
- private static File substituteVars(MavenProject project, File f, File
processedFeaturesDir) throws IOException {
- File file = new File(processedFeaturesDir, f.getName());
-
- if (file.exists() && file.lastModified() > f.lastModified()) {
- // The file already exists, so we don't need to write it again
- return file;
- }
-
- try (FileWriter fw = new FileWriter(file)) {
- for (String s : Files.readAllLines(f.toPath())) {
- fw.write(replaceVars(project, s));
- fw.write(System.getProperty("line.separator"));
- }
- }
- return file;
- }
-
- static String replaceVars(MavenProject project, String s) {
- // There must be a better way than enumerating all these?
- s = s.replaceAll("\\Q${project.groupId}\\E", project.getGroupId());
- s = s.replaceAll("\\Q${project.artifactId}\\E",
project.getArtifactId());
- s = s.replaceAll("\\Q${project.version}\\E", project.getVersion());
- return s;
- }
}
diff --git
a/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
b/src/main/java/org/apache/sling/feature/maven/mojos/Substitution.java
similarity index 52%
copy from
src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
copy to src/main/java/org/apache/sling/feature/maven/mojos/Substitution.java
index ca78cbd..6d5d8f2 100644
--- a/src/main/java/org/apache/sling/feature/maven/mojos/GenerateResources.java
+++ b/src/main/java/org/apache/sling/feature/maven/mojos/Substitution.java
@@ -16,12 +16,6 @@
*/
package org.apache.sling.feature.maven.mojos;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import java.io.File;
@@ -29,38 +23,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
-@Mojo(
- name = "generate-resources",
- defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
- requiresDependencyResolution = ResolutionScope.TEST,
- threadSafe = true)
-public class GenerateResources extends AbstractFeatureMojo {
- @Parameter(defaultValue="${basedir}/src/main/features")
- private File featuresDirectory;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- File[] files = featuresDirectory.listFiles();
- if (files == null)
- return;
-
- File processedFeaturesDir = new
File(project.getBuild().getDirectory(), "features/processed");
- processedFeaturesDir.mkdirs();
-
- for (File f : files) {
- if (!f.getName().endsWith(".json")) {
- continue;
- }
-
- try {
- substituteVars(project, f, processedFeaturesDir);
- } catch (IOException e) {
- throw new MojoExecutionException("Problem processing feature
file " + f.getAbsolutePath(), e);
- }
- }
- }
-
- private static File substituteVars(MavenProject project, File f, File
processedFeaturesDir) throws IOException {
+class Substitution {
+ static File substituteMavenVars(MavenProject project, File f, File
processedFeaturesDir) throws IOException {
File file = new File(processedFeaturesDir, f.getName());
if (file.exists() && file.lastModified() > f.lastModified()) {
@@ -70,14 +34,14 @@ public class GenerateResources extends AbstractFeatureMojo {
try (FileWriter fw = new FileWriter(file)) {
for (String s : Files.readAllLines(f.toPath())) {
- fw.write(replaceVars(project, s));
+ fw.write(replaceMavenVars(project, s));
fw.write(System.getProperty("line.separator"));
}
}
return file;
}
- static String replaceVars(MavenProject project, String s) {
+ static String replaceMavenVars(MavenProject project, String s) {
// There must be a better way than enumerating all these?
s = s.replaceAll("\\Q${project.groupId}\\E", project.getGroupId());
s = s.replaceAll("\\Q${project.artifactId}\\E",
project.getArtifactId());
diff --git a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
index f316c03..d293092 100644
--- a/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
+++ b/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
@@ -23,6 +23,7 @@
<goals>
<goal>process-resources</goal>
<goal>attach-feature</goal>
+ <goal>aggregate-features</goal>
</goals>
</pluginExecutionFilter>
<action>
diff --git
a/src/test/java/org/apache/sling/feature/maven/mojos/GenerateResourceTest.java
b/src/test/java/org/apache/sling/feature/maven/mojos/GenerateResourceTest.java
index 0bc7503..56d44ee 100644
---
a/src/test/java/org/apache/sling/feature/maven/mojos/GenerateResourceTest.java
+++
b/src/test/java/org/apache/sling/feature/maven/mojos/GenerateResourceTest.java
@@ -83,9 +83,9 @@ public class GenerateResourceTest {
Mockito.when(mp.getArtifactId()).thenReturn("a.b.c");
Mockito.when(mp.getVersion()).thenReturn("1.2.3-SNAPSHOT");
- assertEquals("xxxabcyyy", GenerateResources.replaceVars(mp,
+ assertEquals("xxxabcyyy", Substitution.replaceMavenVars(mp,
"xxx${project.groupId}yyy"));
- assertEquals("xxxabcyyya.b.c1.2.3-SNAPSHOT",
GenerateResources.replaceVars(mp,
+ assertEquals("xxxabcyyya.b.c1.2.3-SNAPSHOT",
Substitution.replaceMavenVars(mp,
"xxx${project.groupId}yyy${project.artifactId}${project.version}"));
}