diff --git a/src/main/java/eu/xenit/alfred/initializr/generator/alfresco/extensions/DynamicExtensionsProjectGenerationConfiguration.java b/src/main/java/eu/xenit/alfred/initializr/generator/alfresco/extensions/DynamicExtensionsProjectGenerationConfiguration.java
deleted file mode 100644
index e232e27..0000000
--- a/src/main/java/eu/xenit/alfred/initializr/generator/alfresco/extensions/DynamicExtensionsProjectGenerationConfiguration.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package eu.xenit.alfred.initializr.generator.alfresco.extensions;
-
-public class DynamicExtensionsProjectGenerationConfiguration {
-
-}
diff --git a/src/main/java/eu/xenit/alfred/initializr/generator/build/gradle/CustomGradleBuildWriter.java b/src/main/java/eu/xenit/alfred/initializr/generator/build/gradle/CustomGradleBuildWriter.java
index f7919c3..f4a0b20 100644
--- a/src/main/java/eu/xenit/alfred/initializr/generator/build/gradle/CustomGradleBuildWriter.java
+++ b/src/main/java/eu/xenit/alfred/initializr/generator/build/gradle/CustomGradleBuildWriter.java
@@ -4,17 +4,29 @@
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.Dependency.Exclusion;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
+import io.spring.initializr.generator.buildsystem.gradle.GradleBuild.TaskCustomization;
+import io.spring.initializr.generator.buildsystem.gradle.GradleBuild.TaskCustomization.Invocation;
import io.spring.initializr.generator.buildsystem.gradle.GroovyDslGradleBuildWriter;
import io.spring.initializr.generator.io.IndentingWriter;
import io.spring.initializr.generator.version.VersionProperty;
import io.spring.initializr.generator.version.VersionReference;
+import java.util.Collection;
import java.util.Map;
+import java.util.function.Consumer;
/**
* Adapted from {@link io.spring.initializr.generator.buildsystem.gradle.GradleBuildWriter}
*
* Original class hides utility methods as private, which makes it hard to simply override the {@link
* #writeTo(IndentingWriter writer, GradleBuild build)} method
+ *
+ * Customisations:
+ *
+ * - Support for dependencies on sub-projects: Spring Initializrs' does not support (and does not want to support)
+ * multi-module projects at this time
+ * - Pretty-formatting task-customization invocations: customized tasks with invocations are printet on a single
+ * line. Especially for Dynamic Extensions bnd tool configuration, this gets unwieldy.
+ *
*/
public class CustomGradleBuildWriter extends GroovyDslGradleBuildWriter {
@@ -92,4 +104,61 @@ private String dependencyExclusionAsString(Exclusion exclusion) {
return "exclude group: '" + exclusion.getGroupId() + "', module: '" + exclusion.getArtifactId() + "'";
}
+
+ @Override
+ protected void writeTaskCustomizations(IndentingWriter writer, GradleBuild build) {
+ Map taskCustomizations = build.getTaskCustomizations();
+
+ taskCustomizations.forEach((name, customization) -> {
+ writer.println();
+ writer.println(name + " {");
+ writer.indented(() -> writeAutoFormattedTaskCustomization(writer, customization));
+ writer.println("}");
+ });
+ }
+
+ protected void writeAutoFormattedTaskCustomization(IndentingWriter writer, TaskCustomization customization) {
+ writeCollection(writer, customization.getInvocations(), writeTaskInvocation(writer));
+ writeMap(writer, customization.getAssignments(), (key, value) -> key + " = " + value);
+ customization.getNested().forEach((property, nestedCustomization) -> {
+ writer.println(property + " {");
+ writer.indented(() -> writeAutoFormattedTaskCustomization(writer, nestedCustomization));
+ writer.println("}");
+ });
+ }
+
+ private Consumer writeTaskInvocation(IndentingWriter writer) {
+ return invocation -> {
+ String arguments = String.join(", ", invocation.getArguments());
+
+ int argumentsCount = invocation.getArguments().size();
+ if (argumentsCount == 0) {
+ arguments = "()";
+ } else if (argumentsCount == 1) {
+ arguments = " " + arguments;
+ } else {
+ arguments = "(" + arguments + ")";
+ }
+
+ writer.println(invocation.getTarget() + arguments);
+ };
+ }
+
+ protected void writeCollection(IndentingWriter writer, Collection collection,
+ Consumer callback) {
+ writeCollection(writer, collection, callback, null);
+ }
+
+ protected void writeCollection(IndentingWriter writer, Collection collection,
+ Consumer callback, Runnable beforeWriting) {
+ if (!collection.isEmpty()) {
+ if (beforeWriting != null) {
+ beforeWriting.run();
+ }
+ collection.forEach(callback::accept);
+ }
+ }
+
+
+
}
\ No newline at end of file
diff --git a/src/main/java/eu/xenit/alfred/initializr/generator/extensions/dynext/DynamicExtensionsProjectGenerationConfiguration.java b/src/main/java/eu/xenit/alfred/initializr/generator/extensions/dynext/DynamicExtensionsProjectGenerationConfiguration.java
new file mode 100644
index 0000000..d42fb26
--- /dev/null
+++ b/src/main/java/eu/xenit/alfred/initializr/generator/extensions/dynext/DynamicExtensionsProjectGenerationConfiguration.java
@@ -0,0 +1,93 @@
+package eu.xenit.alfred.initializr.generator.extensions.dynext;
+
+import static org.springframework.util.StringUtils.quote;
+
+import eu.xenit.alfred.initializr.generator.alfresco.platform.PlatformBuild;
+import eu.xenit.alfred.initializr.generator.build.BuildCustomizer;
+import eu.xenit.alfred.initializr.generator.build.gradle.platform.PlatformGradleBuild;
+import eu.xenit.alfred.initializr.generator.build.gradle.root.RootGradleBuild;
+import eu.xenit.alfred.initializr.generator.condition.ConditionalOnRequestedFacet;
+import eu.xenit.alfred.initializr.generator.packaging.amp.AmpPackaging;
+import eu.xenit.alfred.initializr.generator.sdk.alfred.AlfredSdk;
+import eu.xenit.alfred.initializr.generator.sdk.alfred.AlfredSdk.Configurations;
+import io.spring.initializr.generator.buildsystem.Dependency;
+import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem;
+import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
+import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
+import io.spring.initializr.generator.condition.ConditionalOnPackaging;
+import io.spring.initializr.generator.project.ProjectGenerationConfiguration;
+import io.spring.initializr.generator.project.ResolvedProjectDescription;
+import io.spring.initializr.generator.version.VersionReference;
+import io.spring.initializr.metadata.support.MetadataBuildItemResolver;
+import org.springframework.context.annotation.Bean;
+
+@ProjectGenerationConfiguration
+@ConditionalOnRequestedFacet("dynamic-extensions")
+public class DynamicExtensionsProjectGenerationConfiguration {
+
+ private final static String DYN_EXT = "dynamic-extensions";
+
+ private final MetadataBuildItemResolver resolver;
+
+ public DynamicExtensionsProjectGenerationConfiguration(MetadataBuildItemResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ @Bean
+ @ConditionalOnBuildSystem(GradleBuildSystem.ID)
+ public BuildCustomizer addRootDynamicExtensionsAmp(MetadataBuildItemResolver resolver) {
+ return (build) -> {
+
+ String dynamicExtensionVersion = this.getDynamicExtensionsDependency().getVersion().getValue();
+ build.ext("dynamicExtensionsVersion", quote(dynamicExtensionVersion));
+
+ Dependency alfrescoAmp = GradleDependency.from(this.getDynamicExtensionsDependency())
+ .type("amp")
+ .version(VersionReference.ofProperty("dynamic-extensions-version"))
+ .configuration(Configurations.ALFRESCO_AMP)
+ .build();
+ build.dependencies().add(DYN_EXT, alfrescoAmp);
+ };
+ }
+
+ @Bean
+ @ConditionalOnBuildSystem(GradleBuildSystem.ID)
+ @ConditionalOnPackaging(AmpPackaging.ID)
+ public BuildCustomizer packageDynamicExtensionBundleAsAmp() {
+ return (build) -> {
+
+ build.customizeTask("sourceSets", sourceSets -> {
+ sourceSets.nested("main", main -> {
+ main.nested("amp", amp -> {
+ amp.invoke("dynamicExtension");
+ });
+ });
+ });
+ };
+ }
+
+ @Bean
+ @ConditionalOnBuildSystem(GradleBuildSystem.ID)
+ public BuildCustomizer platformConfigureDynamicExtensionsPlugin(
+ ResolvedProjectDescription project) {
+ return (build) -> {
+
+ String pluginVersion = this.getDynamicExtensionsDependency().getVersion().getValue();
+ build.addPlugin("eu.xenit.de", pluginVersion);
+
+ // dependencies on -webscripts and -annotations are added by the plugin
+ // TODO review we want to change this ?!
+
+ build.customizeTask("jar", jar -> {
+ jar.invoke("bnd",
+ "'Alfresco-Spring-Configuration': '"+project.getPackageName()+"'"
+ );
+ });
+ };
+ }
+
+ private Dependency getDynamicExtensionsDependency() {
+ return resolver.resolveDependency("dynamic-extensions");
+ }
+
+}
diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories
index 66ea181..9128be1 100644
--- a/src/main/resources/META-INF/spring.factories
+++ b/src/main/resources/META-INF/spring.factories
@@ -11,6 +11,7 @@ eu.xenit.alfred.initializr.generator.sdk.alfred.docker.DockerBuildGenerationConf
eu.xenit.alfred.initializr.generator.sdk.alfred.docker.AlfredSdkComposeProjectGenerationConfiguration,\
eu.xenit.alfred.initializr.generator.alfresco.platform.AlfrescoModuleProjectGenerationConfiguration,\
eu.xenit.alfred.initializr.generator.docker.compose.DockerComposeProjectGenerationConfiguration,\
+eu.xenit.alfred.initializr.generator.extensions.dynext.DynamicExtensionsProjectGenerationConfiguration,\
eu.xenit.alfred.initializr.generator.extensions.alfred.telemetry.AlfredTelemetryProjectGenerationConfiguration,\
eu.xenit.alfred.initializr.generator.extensions.alfred.telemetry.grafana.GrafanaDockerComposeProjectGenerationConfiguration,\
eu.xenit.alfred.initializr.generator.extensions.alfred.telemetry.graphite.GraphiteProjectGenerationConfiguration
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index 93b3e93..9ecbc40 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -55,8 +55,7 @@ initializr:
- name: Dynamic Extensions
id: dynamic-extensions
facets:
- - platform
- - alfrescoAmp
+ - dynamic-extensions
groupId: eu.xenit
artifactId: alfresco-dynamic-extensions-repo
version: 2.0.1
diff --git a/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildAssert.java b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildAssert.java
index d8daa16..6bf5dfc 100644
--- a/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildAssert.java
+++ b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildAssert.java
@@ -1,10 +1,14 @@
package eu.xenit.alfred.initializr.asserts.build.gradle;
+import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem;
+import java.util.function.Consumer;
import lombok.Getter;
import org.assertj.core.api.AbstractStringAssert;
public class GradleBuildAssert extends AbstractStringAssert {
+
+
public GradleBuildAssert(String content) {
super(content, GradleBuildAssert.class);
}
@@ -61,4 +65,10 @@ public GradleBuildAssert hasDependency(String configuration, String dependency)
@Getter(lazy=true)
private final DependenciesAssert dependencies = new DependenciesAssert(this.actual);
+ public GradleBuildAssert assertTask(String task, Consumer callback)
+ {
+ String section = GradleBuildParser.extractSection(task, this.actual);
+ callback.accept(new GradleTaskAssertion(section));
+ return this;
+ }
}
diff --git a/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildParser.java b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildParser.java
index e08f63f..5bd00cd 100644
--- a/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildParser.java
+++ b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleBuildParser.java
@@ -21,14 +21,41 @@ public static String extractSection(String name, String content) {
content = content.substring(openPluginsIndex + name.length() + " {".length()).trim();
+ // FIXME here we should start tracking the level ? we could open a few more 'sections'
+
// now 'content' contains the start of the section
- // the assumption here is that the closing brace is on a separate line
+ // we start tracking the 'depth', to support nested sections
+ //
+ // ASSUMPTION: the matching closing brace is:
+ // 1. at the end of a line (after trimming)
+ // 2. alone on a new line (is that the same as case (1) ?
+ // This is to avoid running into variables in strings like "${foo}"
+
List section = new ArrayList<>();
- for(String line : content.split(System.lineSeparator())) {
- if ("}".equalsIgnoreCase(line.trim()))
- {
- // found end of section on a new line
- return String.join(System.lineSeparator(), section);
+ int depth = 1;
+ for (String line : content.split(System.lineSeparator())) {
+
+ if (line.trim().matches("^\\w+\\s\\{.*$")) {
+ depth++;
+ }
+// else if (line.trim().startsWith("}")) {
+// depth--;
+// }
+
+ if (line.trim().endsWith("}")) {
+ depth--;
+
+ if (depth == 0) {
+
+ if (!line.trim().equalsIgnoreCase("}"))
+ {
+ // there is useful content before the closing '}'
+ // Example: maven { url 'https://artifacts.alfresco.com/nexus/content/groups/public/' }
+
+ section.add(line.substring(0, line.indexOf("}")).trim());
+ }
+ return String.join(System.lineSeparator(), section);
+ }
}
section.add(line);
@@ -36,7 +63,7 @@ public static String extractSection(String name, String content) {
// if we end up here, something went wrong
// the matching closing brace was not found ?!
- throw new IllegalStateException("matching closing brace not found for section "+name);
+ throw new IllegalStateException("matching closing brace not found for section " + name);
}
@@ -95,5 +122,39 @@ public void testUnbalancedBraces() {
String result = extractSection("plugins", missingClosingBrace);
}
+
+ @Test
+ public void testNested() {
+ String gradle = String.join("\n",
+ "sourceSets {",
+ " main {",
+ " amp {",
+ " dynamicExtension()",
+ " }",
+ " }",
+ "}");
+
+ String sourceSets = extractSection("sourceSets", gradle);
+ String main = extractSection("main", sourceSets);
+ String amp = extractSection("amp", main);
+
+ assertThat(amp).isEqualTo("dynamicExtension()");
+ }
+
+ @Test
+ public void testOnSingleLine() {
+ String gradle = String.join("\n",
+ "repositories {",
+ " mavenCentral()",
+ " maven { url 'https://artifacts.alfresco.com/nexus/content/groups/public/' }",
+ "}",
+ ""
+ );
+
+ String repositories = extractSection("repositories", gradle);
+ String maven = extractSection("maven", repositories);
+
+ assertThat(maven).isEqualTo("url 'https://artifacts.alfresco.com/nexus/content/groups/public/'");
+ }
}
}
diff --git a/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleTaskAssertion.java b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleTaskAssertion.java
new file mode 100644
index 0000000..64465ff
--- /dev/null
+++ b/src/test/java/eu/xenit/alfred/initializr/asserts/build/gradle/GradleTaskAssertion.java
@@ -0,0 +1,18 @@
+package eu.xenit.alfred.initializr.asserts.build.gradle;
+
+import java.util.function.Consumer;
+import org.assertj.core.api.AbstractStringAssert;
+
+public class GradleTaskAssertion extends AbstractStringAssert {
+
+ public GradleTaskAssertion(String actual) {
+ super(actual, GradleTaskAssertion.class);
+ }
+
+ public GradleTaskAssertion nested(String task, Consumer callback)
+ {
+ String section = GradleBuildParser.extractSection(task, this.actual);
+ callback.accept(new GradleTaskAssertion(section));
+ return this;
+ }
+}
diff --git a/src/test/java/eu/xenit/alfred/initializr/integration/DynamicExtensionsTests.java b/src/test/java/eu/xenit/alfred/initializr/integration/DynamicExtensionsTests.java
index bc19d3b..5586dec 100644
--- a/src/test/java/eu/xenit/alfred/initializr/integration/DynamicExtensionsTests.java
+++ b/src/test/java/eu/xenit/alfred/initializr/integration/DynamicExtensionsTests.java
@@ -1,12 +1,13 @@
package eu.xenit.alfred.initializr.integration;
import eu.xenit.alfred.initializr.asserts.build.gradle.GradleMultiProjectAssert;
+import eu.xenit.alfred.initializr.asserts.build.gradle.GradleTaskAssertion;
import io.spring.initializr.web.project.ProjectRequest;
+import org.assertj.core.api.AbstractCharSequenceAssert;
import org.junit.Test;
public class DynamicExtensionsTests extends BaseGeneratorTests {
- private static final String DE_RELEASE = "2.0.1";
@Test
public void testDefaultBuild() {
ProjectRequest request = createProjectRequest("dynamic-extensions");
@@ -14,11 +15,44 @@ public void testDefaultBuild() {
GradleMultiProjectAssert result = generateGradleBuild(request);
result.rootGradleBuild()
- .hasDependency("alfrescoAmp", quote("eu.xenit:alfresco-dynamic-extensions-repo-52:"+DE_RELEASE+"@amp"));
+ .hasDependency("alfrescoAmp", quote("eu.xenit:alfresco-dynamic-extensions-repo-52:${dynamicExtensionsVersion}@amp"));
+ // Only packaging .amp
result.platformGradleBuild()
- .hasDependency("implementation", quote("eu.xenit:alfresco-dynamic-extensions-repo-52:"+DE_RELEASE));
+ .hasPlugin("eu.xenit.de")
+ .assertTask("sourceSets", sourceSets -> {
+ sourceSets.isNotBlank();
+ sourceSets.nested("main", main -> {
+ main.nested("amp", amp -> {
+ amp.isEqualTo("dynamicExtension()");
+ });
+ });
+ });
+
+ }
+
+ @Test
+ public void testDynamicExtensionsWithJarPackaging() {
+ ProjectRequest request = createProjectRequest("dynamic-extensions");
+ request.setPackaging("jar");
+
+ GradleMultiProjectAssert result = generateGradleBuild(request);
+
+ result.rootGradleBuild()
+ .hasDependency("alfrescoAmp", quote("eu.xenit:alfresco-dynamic-extensions-repo-52:${dynamicExtensionsVersion}@amp"));
+
+
+ // This should NOT be present for .jar packaging
+ result.platformGradleBuild()
+ .hasPlugin("eu.xenit.de")
+ .assertTask("sourceSets", sourceSets -> {
+ sourceSets.nested("main", main -> {
+ main.nested("amp", amp -> {
+ amp.doesNotContain("dynamicExtension()");
+ });
+ });
+ });
}
}
\ No newline at end of file