Skip to content

Commit cafb278

Browse files
committed
fix: record option groups to metadata JAR
closed #642 Signed-off-by: Max Brauer <mbrauer@vmware.com>
1 parent 2209f38 commit cafb278

File tree

2 files changed

+190
-4
lines changed

2 files changed

+190
-4
lines changed

spring-cloud-dataflow-apps-plugin/spring-cloud-dataflow-apps-metadata-plugin/src/main/java/org/springframework/cloud/dataflow/app/plugin/MetadataAggregationMojo.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public class MetadataAggregationMojo extends AbstractMojo {
134134
private final JsonMarshaller jsonMarshaller = new JsonMarshaller();
135135

136136
public void execute() throws MojoExecutionException {
137-
Result result = new Result(gatherConfigurationMetadata(null), gatherVisibleMetadata());
137+
Result result = new Result(gatherConfigurationMetadata(null), gatherVisibleMetadata(), gatherOptionGroupsMetadata());
138138
produceArtifact(result);
139139

140140
if (storeFilteredMetadata) {
@@ -332,6 +332,46 @@ else if (properties.containsKey(SPRING_CLOUD_STREAM_FUNCTION_DEFINITION)) {
332332
return visible;
333333
}
334334

335+
/**
336+
* Read all existing option groups metadata from this project runtime dependencies and merge them in a single object.
337+
*/
338+
/*default*/ Properties gatherOptionGroupsMetadata() throws MojoExecutionException {
339+
Properties optionGroups = new Properties();
340+
try {
341+
for (String path : mavenProject.getRuntimeClasspathElements()) {
342+
if (Files.isDirectory(Paths.get(path))) {
343+
Path optionGroupsPath = Paths.get(path, "META-INF", SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES);
344+
File optionGroupsFile = optionGroupsPath.toFile();
345+
if (optionGroupsFile.canRead()) {
346+
try (InputStream is = new FileInputStream(optionGroupsFile)) {
347+
Properties properties = new Properties();
348+
properties.load(is);
349+
getLog().debug("Loading option groups from " + path);
350+
optionGroups.putAll(properties);
351+
}
352+
}
353+
}
354+
else {
355+
try (ZipFile zipFile = new ZipFile(new File(path))) {
356+
ZipEntry entry = zipFile.getEntry("META-INF/" + SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES);
357+
if (entry != null) {
358+
try (InputStream inputStream = zipFile.getInputStream(entry)) {
359+
Properties properties = new Properties();
360+
properties.load(inputStream);
361+
getLog().debug("Loading option groups from " + path);
362+
optionGroups.putAll(properties);
363+
}
364+
}
365+
}
366+
}
367+
}
368+
}
369+
catch (Exception e) {
370+
throw new MojoExecutionException("Exception trying to read option groups metadata from dependencies of project", e);
371+
}
372+
return optionGroups;
373+
}
374+
335375
/*default*/ ConfigurationMetadata gatherConfigurationMetadata(MetadataFilter metadataFilters)
336376
throws MojoExecutionException {
337377
ConfigurationMetadata metadata = new ConfigurationMetadata();
@@ -502,11 +542,11 @@ private void mergeCommaDelimitedValue(Properties currentProperties, Properties n
502542

503543
entry = new ZipEntry("META-INF/" + SPRING_CLOUD_DATAFLOW_PORT_MAPPING_PROPERTIES);
504544
jos.putNextEntry(entry);
545+
result.getPortMappingProperties().store(jos, "Describes visible port mapping properties for this app");
505546

506547
entry = new ZipEntry("META-INF/" + SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES);
507548
jos.putNextEntry(entry);
508-
509-
result.getPortMappingProperties().store(jos, "Describes visible port mapping properties for this app");
549+
result.getOptionGroupsProperties().store(jos, "Describes option groups for this app");
510550

511551
getLog().info(String.format("Attaching %s to current project", output.getCanonicalPath()));
512552
projectHelper.attachArtifact(mavenProject, output, classifier);
@@ -630,6 +670,8 @@ public String toString() {
630670

631671
private final Properties visible;
632672

673+
private final Properties optionGroups;
674+
633675
private Properties getPortMappingProperties() {
634676
Properties portMappingProperties = new Properties();
635677
visible.entrySet().stream()
@@ -638,9 +680,14 @@ private Properties getPortMappingProperties() {
638680
return portMappingProperties;
639681
}
640682

641-
private Result(ConfigurationMetadata metadata, Properties visible) {
683+
private Properties getOptionGroupsProperties() {
684+
return optionGroups;
685+
}
686+
687+
Result(ConfigurationMetadata metadata, Properties visible, Properties optionGroups) {
642688
this.metadata = metadata;
643689
this.visible = visible;
690+
this.optionGroups = optionGroups;
644691
}
645692
}
646693
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright 2018-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.dataflow.app.plugin;
18+
19+
import java.io.File;
20+
import java.io.InputStream;
21+
import java.util.Properties;
22+
import java.util.zip.ZipEntry;
23+
import java.util.zip.ZipFile;
24+
25+
import org.apache.maven.project.MavenProject;
26+
import org.apache.maven.project.MavenProjectHelper;
27+
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.api.io.TempDir;
29+
30+
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
import static org.mockito.Mockito.mock;
34+
import static org.mockito.Mockito.when;
35+
import static org.springframework.cloud.dataflow.app.plugin.MetadataAggregationMojo.CONFIGURATION_PROPERTIES_INBOUND_PORTS;
36+
import static org.springframework.cloud.dataflow.app.plugin.MetadataAggregationMojo.SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES;
37+
38+
/**
39+
* @author Max Brauer
40+
*/
41+
class OptionGroupsTest {
42+
43+
@TempDir
44+
File tempDir;
45+
46+
@Test
47+
void shouldWriteOptionGroupsToMetadataJar() throws Exception {
48+
MetadataAggregationMojo mojo = new MetadataAggregationMojo();
49+
MavenProject project = createMockMavenProject();
50+
setField(mojo, "mavenProject", project);
51+
setField(mojo, "projectHelper", mock(MavenProjectHelper.class));
52+
setField(mojo, "classifier", "metadata");
53+
54+
ConfigurationMetadata metadata = new ConfigurationMetadata();
55+
56+
Properties ports = new Properties(); // no ports
57+
58+
Properties optionGroups = new Properties();
59+
optionGroups.setProperty("com.vmware.tanzu.dataflow.configuration-properties.option-groups.common", "prop1,prop2,prop3");
60+
optionGroups.setProperty("com.vmware.tanzu.dataflow.configuration-properties.option-groups.readers.filereader", "reader.prop1,reader.prop2");
61+
optionGroups.setProperty("com.vmware.tanzu.dataflow.configuration-properties.option-groups.writers.filewriter", "writer.prop1,writer.prop2,writer.prop3");
62+
63+
MetadataAggregationMojo.Result result = new MetadataAggregationMojo.Result(metadata, ports, optionGroups);
64+
65+
mojo.produceArtifact(result);
66+
67+
File output = new File(tempDir, "target/test-artifact-1.0.0-SNAPSHOT-metadata.jar");
68+
assertThat(output).exists();
69+
70+
try (ZipFile zipFile = new ZipFile(output)) {
71+
ZipEntry optionGroupsEntry = zipFile.getEntry("META-INF/" + SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES);
72+
assertThat(optionGroupsEntry).isNotNull();
73+
74+
Properties optionGroupsProps = new Properties();
75+
try (InputStream is = zipFile.getInputStream(optionGroupsEntry)) {
76+
optionGroupsProps.load(is);
77+
}
78+
assertThat(optionGroupsProps)
79+
.as("Option groups file should contain option groups properties")
80+
.containsKey("com.vmware.tanzu.dataflow.configuration-properties.option-groups.common")
81+
.containsKey("com.vmware.tanzu.dataflow.configuration-properties.option-groups.readers.filereader")
82+
.containsKey("com.vmware.tanzu.dataflow.configuration-properties.option-groups.writers.filewriter");
83+
assertThat(optionGroupsProps.getProperty("com.vmware.tanzu.dataflow.configuration-properties.option-groups.common"))
84+
.isEqualTo("prop1,prop2,prop3");
85+
}
86+
}
87+
88+
@Test
89+
void shouldWriteEmptyOptionGroupsToMetadataJar() throws Exception {
90+
MetadataAggregationMojo mojo = new MetadataAggregationMojo();
91+
MavenProject project = createMockMavenProject();
92+
setField(mojo, "mavenProject", project);
93+
setField(mojo, "projectHelper", mock(MavenProjectHelper.class));
94+
setField(mojo, "classifier", "metadata");
95+
96+
ConfigurationMetadata metadata = new ConfigurationMetadata();
97+
98+
Properties ports = new Properties(); // no ports
99+
Properties optionGroups = new Properties(); // no option groups
100+
101+
MetadataAggregationMojo.Result result = new MetadataAggregationMojo.Result(metadata, ports, optionGroups);
102+
103+
mojo.produceArtifact(result);
104+
105+
File output = new File(tempDir, "target/test-artifact-1.0.0-SNAPSHOT-metadata.jar");
106+
assertThat(output).exists();
107+
108+
try (ZipFile zipFile = new ZipFile(output)) {
109+
ZipEntry optionGroupsEntry = zipFile.getEntry("META-INF/" + SPRING_CLOUD_DATAFLOW_OPTION_GROUPS_PROPERTIES);
110+
assertThat(optionGroupsEntry)
111+
.as("Option groups file should exist even when empty")
112+
.isNotNull();
113+
114+
Properties optionGroupsProps = new Properties();
115+
try (InputStream is = zipFile.getInputStream(optionGroupsEntry)) {
116+
optionGroupsProps.load(is);
117+
}
118+
assertThat(optionGroupsProps)
119+
.as("Option groups should be empty when no groups provided")
120+
.isEmpty();
121+
}
122+
}
123+
124+
private MavenProject createMockMavenProject() {
125+
MavenProject project = mock(MavenProject.class);
126+
File targetDir = new File(tempDir, "target");
127+
targetDir.mkdirs();
128+
when(project.getBasedir()).thenReturn(tempDir);
129+
when(project.getArtifactId()).thenReturn("test-artifact");
130+
when(project.getVersion()).thenReturn("1.0.0-SNAPSHOT");
131+
return project;
132+
}
133+
134+
private void setField(Object target, String fieldName, Object value) throws Exception {
135+
java.lang.reflect.Field field = target.getClass().getDeclaredField(fieldName);
136+
field.setAccessible(true);
137+
field.set(target, value);
138+
}
139+
}

0 commit comments

Comments
 (0)