Add version range support for Kotlin version

Closes gh-556
This commit is contained in:
Stephane Nicoll
2017-12-11 16:18:43 +01:00
parent 6fbb1262d3
commit faa7de99c2
13 changed files with 219 additions and 28 deletions

View File

@@ -340,6 +340,7 @@ public class ProjectGenerator {
ProjectRequest request = requestResolver.resolve(originalRequest, metadata);
// request resolved so we can log what has been requested
Version bootVersion = Version.safeParse(request.getBootVersion());
List<Dependency> dependencies = request.getResolvedDependencies();
List<String> dependencyIds = dependencies.stream().map(Dependency::getId)
.collect(Collectors.toList());
@@ -352,7 +353,7 @@ public class ProjectGenerator {
// Kotlin supported as of M6
final boolean kotlinSupport = VERSION_2_0_0_M6
.compareTo(Version.safeParse(request.getBootVersion())) <= 0;
.compareTo(bootVersion) <= 0;
model.put("kotlinSupport", kotlinSupport);
if (isMavenBuild(request)) {
@@ -419,8 +420,8 @@ public class ProjectGenerator {
// Add various versions
model.put("dependencyManagementPluginVersion", metadata.getConfiguration()
.getEnv().getGradle().getDependencyManagementPluginVersion());
model.put("kotlinVersion",
metadata.getConfiguration().getEnv().getKotlin().getVersion());
model.put("kotlinVersion", metadata.getConfiguration().getEnv().getKotlin()
.resolveKotlinVersion(bootVersion));
if ("kotlin".equals(request.getLanguage())) {
model.put("kotlin", true);
}
@@ -433,15 +434,15 @@ public class ProjectGenerator {
// Gradle plugin has changed as from 1.3.0
model.put("bootOneThreeAvailable", VERSION_1_3_0_M1
.compareTo(Version.safeParse(request.getBootVersion())) <= 0);
.compareTo(bootVersion) <= 0);
model.put("bootTwoZeroAvailable", VERSION_2_0_0_M1
.compareTo(Version.safeParse(request.getBootVersion())) <= 0);
.compareTo(bootVersion) <= 0);
// Gradle plugin has changed again as from 1.4.2
model.put("springBootPluginName",
(VERSION_1_4_2_M1
.compareTo(Version.safeParse(request.getBootVersion())) <= 0
.compareTo(bootVersion) <= 0
? "org.springframework.boot" : "spring-boot"));
// New testing stuff

View File

@@ -196,7 +196,7 @@ public class ProjectRequest extends BasicProjectRequest {
initializeRepositories(metadata, requestedVersion);
initializeProperties(metadata);
initializeProperties(metadata, requestedVersion);
afterResolution(metadata);
}
@@ -219,12 +219,14 @@ public class ProjectRequest extends BasicProjectRequest {
}));
}
protected void initializeProperties(InitializrMetadata metadata) {
protected void initializeProperties(InitializrMetadata metadata,
Version requestedVersion) {
String kotlinVersion = metadata.getConfiguration().getEnv().getKotlin()
.resolveKotlinVersion(requestedVersion);
if ("gradle".equals(build)) {
buildProperties.getGradle().put("springBootVersion", this::getBootVersion);
if ("kotlin".equals(getLanguage())) {
buildProperties.getGradle().put("kotlinVersion", () -> metadata
.getConfiguration().getEnv().getKotlin().getVersion());
buildProperties.getGradle().put("kotlinVersion", () -> kotlinVersion);
}
}
else {
@@ -235,7 +237,7 @@ public class ProjectRequest extends BasicProjectRequest {
this::getJavaVersion);
if ("kotlin".equals(getLanguage())) {
buildProperties.getVersions().put(new VersionProperty("kotlin.version"),
() -> metadata.getConfiguration().getEnv().getKotlin().getVersion());
() -> kotlinVersion);
buildProperties.getMaven().put("kotlin.compiler.incremental", () -> "true");
}
}

View File

@@ -26,6 +26,12 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.spring.initializr.util.InvalidVersionException;
import io.spring.initializr.util.Version;
import io.spring.initializr.util.VersionParser;
import io.spring.initializr.util.VersionRange;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.StringUtils;
@@ -319,6 +325,7 @@ public class InitializrConfiguration {
public void validate() {
maven.parent.validate();
boms.forEach((k, v) -> v.validate());
kotlin.validate();
}
public void merge(Env other) {
@@ -329,7 +336,7 @@ public class InitializrConfiguration {
invalidApplicationNames = other.invalidApplicationNames;
forceSsl = other.forceSsl;
gradle.merge(other.gradle);
kotlin.version = other.kotlin.version;
kotlin.merge(other.kotlin);
maven.merge(other.maven);
other.boms.forEach(boms::putIfAbsent);
other.repositories.forEach(repositories::putIfAbsent);
@@ -360,17 +367,114 @@ public class InitializrConfiguration {
public static class Kotlin {
/**
* Kotlin version to use.
* Default kotlin version.
*/
private String version;
private String defaultVersion;
public String getVersion() {
return version;
/**
* Kotlin version mappings.
*/
private final List<Mapping> mappings = new ArrayList<>();
/**
* Resolve the kotlin version to use based on the Spring Boot version.
* @param bootVersion the Spring Boot version
* @return the kotlin version to use
*/
public String resolveKotlinVersion(Version bootVersion) {
for (Mapping mapping : this.mappings) {
if (mapping.range.match(bootVersion)) {
return mapping.version;
}
}
if (defaultVersion == null) {
throw new InvalidInitializrMetadataException(
"No Kotlin version mapping available for " + bootVersion);
}
return this.defaultVersion;
}
public void setVersion(String version) {
this.version = version;
public String getDefaultVersion() {
return this.defaultVersion;
}
public void setDefaultVersion(String defaultVersion) {
this.defaultVersion = defaultVersion;
}
public List<Mapping> getMappings() {
return this.mappings;
}
public void validate() {
VersionParser simpleParser = new VersionParser(Collections.emptyList());
mappings.forEach(m -> {
if (m.versionRange == null) {
throw new InvalidInitializrMetadataException(
"VersionRange is mandatory, invalid version mapping for " + this);
}
m.range = simpleParser.parseRange(m.versionRange);
if (m.version == null) {
throw new InvalidInitializrMetadataException(
"Version is mandatory, invalid version mapping for " + this);
}
});
}
public void updateVersionRange(VersionParser versionParser) {
mappings.forEach(it -> {
try {
it.range = versionParser.parseRange(it.versionRange);
}
catch (InvalidVersionException ex) {
throw new InvalidInitializrMetadataException(
"Invalid version range " + it.versionRange + " for " + this, ex);
}
});
}
private void merge(Kotlin other) {
this.defaultVersion = other.defaultVersion;
this.mappings.clear();
this.mappings.addAll(other.mappings);
}
/**
* Map several attribute of the dependency for a given version range.
*/
public static class Mapping {
/**
* The version range of this mapping.
*/
private String versionRange;
/**
* The kotlin version for this mapping.
*/
private String version;
@JsonIgnore
private VersionRange range;
public String getVersionRange() {
return this.versionRange;
}
public void setVersionRange(String versionRange) {
this.versionRange = versionRange;
}
public String getVersion() {
return this.version;
}
public void setVersion(String version) {
this.version = version;
}
}
}
public static class Maven {

View File

@@ -218,6 +218,7 @@ public class InitializrMetadata {
dependencies.updateVersionRange(parser);
configuration.getEnv().getBoms().values()
.forEach(it -> it.updateVersionRange(parser));
configuration.getEnv().getKotlin().updateVersionRange(parser);
}
/**

View File

@@ -16,11 +16,16 @@
package io.spring.initializr.metadata;
import io.spring.initializr.metadata.InitializrConfiguration.Env.Kotlin;
import io.spring.initializr.util.Version;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
/**
* Tests for {@link InitializrConfiguration}.
*
* @author Stephane Nicoll
*/
public class InitializrConfigurationTests {
@@ -159,4 +164,35 @@ public class InitializrConfigurationTests {
assertEquals("http://foo/bar/", this.properties.getEnv().getArtifactRepository());
}
@Test
public void resolveKotlinVersionMatchingMapping() {
Kotlin kotlin = this.properties.getEnv().getKotlin();
kotlin.setDefaultVersion("1.2.3");
kotlin.getMappings().add(createKotlinVersionMapping(
"[1.4.0.RELEASE,1.5.0.RELEASE)", "1.5"));
kotlin.getMappings().add(createKotlinVersionMapping("1.5.0.RELEASE", "1.6"));
kotlin.validate();
assertThat(kotlin.resolveKotlinVersion(Version.parse("1.5.3.RELEASE")))
.isEqualTo("1.6");
}
@Test
public void resolveKotlinVersionUsingDefault() {
Kotlin kotlin = this.properties.getEnv().getKotlin();
kotlin.setDefaultVersion("1.2.3");
kotlin.getMappings().add(createKotlinVersionMapping(
"[1.4.0.RELEASE,1.5.0.RELEASE)", "1.5"));
kotlin.validate();
assertThat(kotlin.resolveKotlinVersion(Version.parse("1.3.2.RELEASE")))
.isEqualTo("1.2.3");
}
private Kotlin.Mapping createKotlinVersionMapping(String versionRange,
String kotlinVersion){
Kotlin.Mapping mapping = new Kotlin.Mapping();
mapping.setVersionRange(versionRange);
mapping.setVersion(kotlinVersion);
return mapping;
}
}

View File

@@ -33,6 +33,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Tests for {@link InitializrMetadataBuilder}.
*
* @author Stephane Nicoll
*/
public class InitializrMetadataBuilderTests {
@@ -163,8 +165,6 @@ public class InitializrMetadataBuilderTests {
assertEquals(defaultEnv.getFallbackApplicationName(),
actualEnv.getFallbackApplicationName());
assertEquals(defaultEnv.isForceSsl(), actualEnv.isForceSsl());
assertEquals(defaultEnv.getKotlin().getVersion(),
actualEnv.getKotlin().getVersion());
}
@Test
@@ -184,7 +184,7 @@ public class InitializrMetadataBuilderTests {
actualEnv.getSpringBootMetadataUrl());
assertEquals("FooBarApplication", actualEnv.getFallbackApplicationName());
assertEquals(false, actualEnv.isForceSsl());
assertEquals("1.0.0-beta-2423", actualEnv.getKotlin().getVersion());
assertEquals("1.0.0-beta-2423", actualEnv.getKotlin().getDefaultVersion());
}
@Test

View File

@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.List;
import io.spring.initializr.metadata.BillOfMaterials.Mapping;
import io.spring.initializr.metadata.InitializrConfiguration.Env.Kotlin;
import io.spring.initializr.test.metadata.InitializrMetadataTestBuilder;
import io.spring.initializr.util.Version;
import org.junit.Rule;
@@ -173,7 +174,11 @@ public class InitializrMetadataTests {
"1.3.x.BUILD-SNAPSHOT", null, null, "0.2.0.RELEASE"));
InitializrMetadata metadata = InitializrMetadataTestBuilder
.withDefaults().addDependencyGroup("test", dependency)
.addBom("foo-bom", bom).build();
.addBom("foo-bom", bom)
.setKotlinEnv("1.3",
createKotlinVersionMapping("[1.2.0.RELEASE,1.3.x.RELEASE]", "1.1"),
createKotlinVersionMapping("1.3.x.BUILD-SNAPSHOT", "1.2"))
.build();
List<DefaultMetadataElement> bootVersions = Arrays.asList(
DefaultMetadataElement.create("1.3.6.RELEASE", "1.3.6", false),
@@ -187,6 +192,8 @@ public class InitializrMetadataTests {
.resolve(Version.parse("1.3.6.RELEASE")).getVersion()).isEqualTo("0.1.0.RELEASE");
assertThat(metadata.getDependencies().get("bar")
.resolve(Version.parse("1.3.7.BUILD-SNAPSHOT")).getVersion()).isEqualTo("0.2.0.RELEASE");
assertThat(metadata.getConfiguration().getEnv().getKotlin()
.resolveKotlinVersion(Version.parse("1.3.7.BUILD-SNAPSHOT"))).isEqualTo("1.2");
}
@Test
@@ -212,4 +219,12 @@ public class InitializrMetadataTests {
assertThat(metadata.getPackageName().getContent()).isEqualTo("org.acme.foobar");
}
private Kotlin.Mapping createKotlinVersionMapping(String versionRange,
String kotlinVersion){
Kotlin.Mapping mapping = new Kotlin.Mapping();
mapping.setVersionRange(versionRange);
mapping.setVersion(kotlinVersion);
return mapping;
}
}

View File

@@ -24,6 +24,7 @@ import io.spring.initializr.metadata.BillOfMaterials;
import io.spring.initializr.metadata.DefaultMetadataElement;
import io.spring.initializr.metadata.Dependency;
import io.spring.initializr.metadata.DependencyGroup;
import io.spring.initializr.metadata.InitializrConfiguration.Env.Kotlin;
import io.spring.initializr.metadata.InitializrConfiguration.Env.Maven.ParentPom;
import io.spring.initializr.metadata.InitializrMetadata;
import io.spring.initializr.metadata.InitializrMetadataBuilder;
@@ -190,9 +191,15 @@ public class InitializrMetadataTestBuilder {
return this;
}
public InitializrMetadataTestBuilder setKotlinEnv(String kotlinVersion) {
builder.withCustomizer(it -> it.getConfiguration().getEnv()
.getKotlin().setVersion(kotlinVersion));
public InitializrMetadataTestBuilder setKotlinEnv(String defaultKotlinVersion,
Kotlin.Mapping... mappings) {
builder.withCustomizer(it -> {
it.getConfiguration().getEnv().getKotlin()
.setDefaultVersion(defaultKotlinVersion);
for (Kotlin.Mapping mapping : mappings) {
it.getConfiguration().getEnv().getKotlin().getMappings().add(mapping);
}
});
return this;
}

View File

@@ -7,4 +7,4 @@ initializr:
invalidApplicationNames:
- InvalidApplication
kotlin:
version: 1.0.0-beta-2423
default-version: 1.0.0-beta-2423

View File

@@ -22,6 +22,13 @@ initializr:
artifactId: my-api-dependencies-bom
version: 1.0.0.RELEASE
repositories: my-api-repo-3
kotlin:
defaultVersion: 1.2
mappings:
- versionRange: "[1.0.0.RELEASE,1.2.0.RELEASE)"
version: 1.0
- versionRange: "[1.2.0.RELEASE,1.5.0.RELEASE)"
version: 1.1
repositories:
my-api-repo-1:
name: repo1

View File

@@ -131,7 +131,7 @@ initializr:
gradle:
dependency-management-plugin-version: 0.6.0.RELEASE
kotlin:
version: 1.1.61
default-version: 1.1.61
dependencies:
- name: Core
content:

View File

@@ -117,6 +117,14 @@ public class MainControllerIntegrationTests
.hasSpringBootStarterTest();
}
@Test
public void kotlinRange() {
downloadZip("/starter.zip?style=web&language=kotlin&bootVersion=1.2.1.RELEASE")
.isKotlinProject().isMavenProject()
.pomAssert().hasDependenciesCount(4)
.hasProperty("kotlin.version", "1.1");
}
@Test
public void gradleWarProject() {
downloadZip("/starter.zip?style=web&style=security&packaging=war&type=gradle.zip")

View File

@@ -37,7 +37,17 @@
"dependencyManagementPluginVersion": "1.0.0.RELEASE"
},
"kotlin": {
"version": null
"defaultVersion": "1.2",
"mappings": [
{
"versionRange": "[1.0.0.RELEASE,1.2.0.RELEASE)",
"version": "1.0"
},
{
"versionRange": "[1.2.0.RELEASE,1.5.0.RELEASE)",
"version": "1.1"
}
]
},
"maven": {
"parent": {