Skip to content

Commit baabef6

Browse files
committed
Create mapping for Spring Boot version to supported min and max java versions
See gh-608
1 parent 2cb375d commit baabef6

File tree

5 files changed

+308
-27
lines changed

5 files changed

+308
-27
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2012 - present 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 io.spring.start.site.project;
18+
19+
import java.util.List;
20+
21+
import io.spring.initializr.generator.language.Language;
22+
import io.spring.initializr.generator.language.kotlin.KotlinLanguage;
23+
import io.spring.initializr.generator.version.Version;
24+
import io.spring.initializr.generator.version.VersionParser;
25+
import io.spring.initializr.generator.version.VersionRange;
26+
27+
/**
28+
* Maps Spring Boot versions to minimum and maximum Java versions.
29+
*
30+
* @author Moritz Halbritter
31+
*/
32+
class JavaVersionMapping {
33+
34+
private static final List<Mapping> mappings = List.of(Mapping.of("[3.4.0-M1,3.5.0-M1)", 17, 24, "1.9.25"),
35+
Mapping.of("[3.5.0-M1,4.0.0-M1)", 17, 25, "1.9.25"), Mapping.of("[4.0.0-M1,4.1.0-M1)", 17, 25, "2.2.0"));
36+
37+
private final KotlinVersionMapping kotlinMapping = new KotlinVersionMapping();
38+
39+
/**
40+
* Returns the minimum supported Java version.
41+
* @param springBootVersion the version of Spring Boot
42+
* @param language the project language
43+
* @return the minimum Java version
44+
*/
45+
int getMinJavaVersion(Version springBootVersion, Language language) {
46+
Mapping mapping = findMapping(springBootVersion);
47+
int result = mapping.minJavaVersion();
48+
if (isKotlin(language)) {
49+
return Math.max(result, this.kotlinMapping.getMinJavaVersion(mapping.kotlinVersion()));
50+
}
51+
return result;
52+
}
53+
54+
/**
55+
* Returns the maximum supported Java version.
56+
* @param springBootVersion the version of Spring Boot
57+
* @param language the project language
58+
* @return the maximum Java version
59+
*/
60+
int getMaxJavaVersion(Version springBootVersion, Language language) {
61+
Mapping mapping = findMapping(springBootVersion);
62+
int result = mapping.maxJavaVersion();
63+
if (isKotlin(language)) {
64+
return Math.min(result, this.kotlinMapping.getMaxJavaVersion(mapping.kotlinVersion()));
65+
}
66+
return result;
67+
}
68+
69+
private boolean isKotlin(Language language) {
70+
return language instanceof KotlinLanguage;
71+
}
72+
73+
private Mapping findMapping(Version springBootVersion) {
74+
for (Mapping mapping : mappings) {
75+
if (mapping.match(springBootVersion)) {
76+
return mapping;
77+
}
78+
}
79+
throw new IllegalStateException("Missing mapping for " + springBootVersion);
80+
}
81+
82+
private record Mapping(VersionRange range, int minJavaVersion, int maxJavaVersion, Version kotlinVersion) {
83+
boolean match(Version springBootVersion) {
84+
return this.range.match(springBootVersion);
85+
}
86+
87+
static Mapping of(String range, int minJavaVersion, int maxJavaVersion, String kotlinVersion) {
88+
return new Mapping(VersionParser.DEFAULT.parseRange(range), minJavaVersion, maxJavaVersion,
89+
VersionParser.DEFAULT.parse(kotlinVersion));
90+
}
91+
}
92+
93+
}

start-site/src/main/java/io/spring/start/site/project/JavaVersionProjectDescriptionCustomizer.java

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,9 @@
2020
import java.util.List;
2121

2222
import io.spring.initializr.generator.language.Language;
23-
import io.spring.initializr.generator.language.kotlin.KotlinLanguage;
2423
import io.spring.initializr.generator.project.MutableProjectDescription;
2524
import io.spring.initializr.generator.project.ProjectDescriptionCustomizer;
2625
import io.spring.initializr.generator.version.Version;
27-
import io.spring.initializr.generator.version.VersionParser;
28-
import io.spring.initializr.generator.version.VersionRange;
2926

3027
/**
3128
* Validate that the requested java version is compatible with the chosen Spring Boot
@@ -37,47 +34,37 @@
3734
*/
3835
public class JavaVersionProjectDescriptionCustomizer implements ProjectDescriptionCustomizer {
3936

40-
private static final VersionRange SPRING_BOOT_3_5_OR_LATER = VersionParser.DEFAULT.parseRange("3.5.0");
41-
4237
private static final List<String> UNSUPPORTED_VERSIONS = Arrays.asList("1.6", "1.7", "1.8");
4338

4439
private static final int MAX_JAVA_VERSION = 25;
4540

41+
private final JavaVersionMapping mapping = new JavaVersionMapping();
42+
4643
@Override
4744
public void customize(MutableProjectDescription description) {
48-
String javaVersion = description.getLanguage().jvmVersion();
45+
Language language = description.getLanguage();
46+
Version bootVersion = description.getPlatformVersion();
47+
int minSupported = this.mapping.getMinJavaVersion(bootVersion, language);
48+
int maxSupported = this.mapping.getMaxJavaVersion(bootVersion, language);
49+
String javaVersion = language.jvmVersion();
4950
if (UNSUPPORTED_VERSIONS.contains(javaVersion)) {
50-
updateTo(description, "17");
51+
updateTo(description, minSupported);
5152
return;
5253
}
5354
Integer javaGeneration = determineJavaGeneration(javaVersion);
5455
if (javaGeneration == null) {
5556
return;
5657
}
57-
if (javaGeneration < 17) {
58-
updateTo(description, "17");
59-
}
60-
if (javaGeneration >= 22) {
61-
if (isKotlin(description)) {
62-
// Kotlin 1.9.x doesn't support Java > 21
63-
updateTo(description, "21");
64-
}
58+
if (javaGeneration < minSupported) {
59+
updateTo(description, minSupported);
6560
}
66-
if (javaGeneration >= 25) {
67-
// Spring Boot < 3.5.x supports Java 24 at most
68-
Version platformVersion = description.getPlatformVersion();
69-
if (!SPRING_BOOT_3_5_OR_LATER.match(platformVersion)) {
70-
updateTo(description, "24");
71-
}
61+
if (javaGeneration > maxSupported) {
62+
updateTo(description, maxSupported);
7263
}
7364
}
7465

75-
private boolean isKotlin(MutableProjectDescription description) {
76-
return description.getLanguage() instanceof KotlinLanguage;
77-
}
78-
79-
private void updateTo(MutableProjectDescription description, String jvmVersion) {
80-
Language language = Language.forId(description.getLanguage().id(), jvmVersion);
66+
private void updateTo(MutableProjectDescription description, int jvmVersion) {
67+
Language language = Language.forId(description.getLanguage().id(), Integer.toString(jvmVersion));
8168
description.setLanguage(language);
8269
}
8370

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2012 - present 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 io.spring.start.site.project;
18+
19+
import java.util.List;
20+
21+
import io.spring.initializr.generator.version.Version;
22+
import io.spring.initializr.generator.version.VersionParser;
23+
import io.spring.initializr.generator.version.VersionRange;
24+
25+
/**
26+
* Maps Kotlin versions to minimum and maximum Java versions.
27+
*
28+
* @author Moritz Halbritter
29+
*/
30+
class KotlinVersionMapping {
31+
32+
private static final List<Mapping> mappings = List.of(Mapping.of("[1.9.0,1.9.20)", 17, 20),
33+
Mapping.of("[1.9.20,2.0.0)", 17, 21), Mapping.of("[2.0.0,2.1.0)", 17, 22),
34+
Mapping.of("[2.1.0,2.2.0)", 17, 23), Mapping.of("[2.2.0,2.3.0)", 17, 24));
35+
36+
/**
37+
* Returns the minimum supported Java version.
38+
* @param kotlinVersion the version kotlin
39+
* @return the minimum Java version
40+
*/
41+
int getMinJavaVersion(Version kotlinVersion) {
42+
return findMapping(kotlinVersion).minJavaVersion();
43+
}
44+
45+
/**
46+
* Returns the minimum supported Java version.
47+
* @param kotlinVersion the version kotlin
48+
* @return the maximum Java version
49+
*/
50+
int getMaxJavaVersion(Version kotlinVersion) {
51+
return findMapping(kotlinVersion).maxJavaVersion();
52+
}
53+
54+
private Mapping findMapping(Version kotlinVersion) {
55+
for (Mapping mapping : mappings) {
56+
if (mapping.match(kotlinVersion)) {
57+
return mapping;
58+
}
59+
}
60+
throw new IllegalStateException("Missing mapping for " + kotlinVersion);
61+
}
62+
63+
private record Mapping(VersionRange range, int minJavaVersion, int maxJavaVersion) {
64+
boolean match(Version kotlinVersion) {
65+
return this.range.match(kotlinVersion);
66+
}
67+
68+
static Mapping of(String range, int minJavaVersion, int maxJavaVersion) {
69+
return new Mapping(VersionParser.DEFAULT.parseRange(range), minJavaVersion, maxJavaVersion);
70+
}
71+
72+
}
73+
74+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2012 - present 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 io.spring.start.site.project;
18+
19+
import io.spring.initializr.generator.language.Language;
20+
import io.spring.initializr.generator.language.java.JavaLanguage;
21+
import io.spring.initializr.generator.language.kotlin.KotlinLanguage;
22+
import io.spring.initializr.generator.version.Version;
23+
import io.spring.initializr.generator.version.VersionParser;
24+
import org.junit.jupiter.params.ParameterizedTest;
25+
import org.junit.jupiter.params.provider.CsvSource;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
/**
30+
* Tests for {@link JavaVersionMapping}.
31+
*
32+
* @author Moritz Halbritter
33+
*/
34+
class JavaVersionMappingTests {
35+
36+
private final JavaVersionMapping mapping = new JavaVersionMapping();
37+
38+
@CsvSource(textBlock = """
39+
3.4.0,17,24
40+
3.5.0,17,25
41+
4.0.0,17,25
42+
""")
43+
@ParameterizedTest(name = "Spring Boot {0} with Java | min {1} | max {2}")
44+
void java(String bootVersion, int expectedJavaMin, int expectedJavaMax) {
45+
Version version = toVersion(bootVersion);
46+
Language java = new JavaLanguage();
47+
int min = this.mapping.getMinJavaVersion(version, java);
48+
int max = this.mapping.getMaxJavaVersion(version, java);
49+
assertThat(min).isEqualTo(expectedJavaMin);
50+
assertThat(max).isEqualTo(expectedJavaMax);
51+
}
52+
53+
@CsvSource(textBlock = """
54+
3.4.0,17,21
55+
3.5.0,17,21
56+
4.0.0,17,24
57+
""")
58+
@ParameterizedTest(name = "Spring Boot {0} with Kotlin | min {1} | max {2}")
59+
void kotlin(String bootVersion, int expectedJavaMin, int expectedJavaMax) {
60+
Version version = toVersion(bootVersion);
61+
Language kotlin = new KotlinLanguage();
62+
int min = this.mapping.getMinJavaVersion(version, kotlin);
63+
int max = this.mapping.getMaxJavaVersion(version, kotlin);
64+
assertThat(min).isEqualTo(expectedJavaMin);
65+
assertThat(max).isEqualTo(expectedJavaMax);
66+
}
67+
68+
private Version toVersion(String version) {
69+
return VersionParser.DEFAULT.parse(version);
70+
}
71+
72+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2012 - present 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 io.spring.start.site.project;
18+
19+
import io.spring.initializr.generator.version.Version;
20+
import io.spring.initializr.generator.version.VersionParser;
21+
import org.junit.jupiter.params.ParameterizedTest;
22+
import org.junit.jupiter.params.provider.CsvSource;
23+
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
26+
/**
27+
* Tests for {@link KotlinVersionMapping}.
28+
*
29+
* @author Moritz Halbritter
30+
*/
31+
class KotlinVersionMappingTests {
32+
33+
private final KotlinVersionMapping mapping = new KotlinVersionMapping();
34+
35+
@CsvSource(textBlock = """
36+
1.9.0,17,20
37+
1.9.20,17,21
38+
2.0.0,17,22
39+
2.1.0,17,23
40+
2.2.0,17,24
41+
""")
42+
@ParameterizedTest(name = "Kotlin {0} | min {1} | max {2}")
43+
void test(String kotlinVersion, int expectedJavaMin, int expectedJavaMax) {
44+
Version version = toVersion(kotlinVersion);
45+
int min = this.mapping.getMinJavaVersion(version);
46+
int max = this.mapping.getMaxJavaVersion(version);
47+
assertThat(min).isEqualTo(expectedJavaMin);
48+
assertThat(max).isEqualTo(expectedJavaMax);
49+
}
50+
51+
private Version toVersion(String version) {
52+
return VersionParser.DEFAULT.parse(version);
53+
}
54+
55+
}

0 commit comments

Comments
 (0)